2016-01-29 40 views
1

我想在Python中編寫一個簡單的音頻函數生成器,以在Raspberry Pi(模型2)上運行。碼基本上做到這一點:在低功率計算機上從Python生成平滑音頻

  • 生成的音頻信號的1秒(比方說,一個正弦波或方波等)
  • 重複地播放它在一個循環

例如:

import pyaudio 
from numpy import linspace,sin,pi,int16 

def note(freq, len, amp=1, rate=44100): 
t = linspace(0,len,len*rate) 
data = sin(2*pi*freq*t)*amp 
return data.astype(int16) # two byte integers 

RATE = 44100 
FREQ = 261.6 

pa = pyaudio.PyAudio() 
s = pa.open(output=True, 
      channels=2, 
      rate=RATE, 
      format=pyaudio.paInt16, 
      output_device_index=2) 

# generate 1 second of sound 
tone = note(FREQ, 1, amp=10000, rate=RATE) 

# play it forever  
while True: 
    s.write(tone) 

的問題是,在音頻的可聽「嘀」的循環結果的每次迭代,使用外置USB聲卡也是如此。有什麼辦法可以避免這種情況,而不是試圖用C重寫所有的東西?

我嘗試使用pyaudio回調接口,但實際上聽起來更糟糕(就像也許我的Pi是脹氣)。

生成的音頻需要很短,因爲它最終將通過外部控制進行動態調整,並且任何超過1秒的控制更改延遲都會讓人覺得尷尬。有沒有更好的方法來從Python代碼中產生這些信號?

+0

這種點擊可能與使用'PyAudio'的阻塞模式有關。出於您的目的(小緩衝區/低延遲),最好使用回調模式。嘗試以下示例:https://people.csail.mit.edu/hubert/pyaudio/docs/#example-callback-mode-audio-i-o – quasoft

回答

4

您正在聽到「打勾」,因爲您發送的音頻不連貫。 261.6赫茲的一個第二個是包含261.6個週期,所以你結束了大約半個週期結束時遺留下來的:

Waveform showing discontinuity at 1 second

您需要更改頻率,以便有一個整數的每秒鐘的週期數(例如262Hz),改變持續時間,使其足夠長時間達到整個週期數,或者每秒產生一個新的音頻片段,以正確的階段開始,以適應最後一個塊停止的地方。

+0

好吧,現在你說我感到很蠢。讓我去調整我的代碼,讓我產生一個完整的時期,看看會發生什麼。這實際上是我嘗試製作一個簡單的測試用例,而不必複製更復雜的代碼,但顯然我沒有想到它。 – larsks

+0

將此標記爲答案,因爲即使使用正確生成完整句點的代碼,我也會得到不確定的結果。如其中,有時它運行順暢,有時相同的代碼 - 沒有變化 - 會產生可聽見的「節拍」。如果我可以可靠地重現,我會回來... – larsks

1

我正在尋找一個類似的問題給你,並發現一個變化,通過連接一堆預先計算的塊來發揮預先計算的長度。

http://milkandtang.com/blog/2013/02/16/making-noise-in-python/

使用用於與1秒預先計算的塊「play_tone」功能循環似乎產生一個平滑的探測輸出,但是這是在PC上。如果這不適合你,那可能是樹莓派有不同的後端實現,不喜歡連續寫入。

+0

我最終解決了我的問題,然後將它打包好,並用它在K-4「STEM」夜演示:https://github.com/larsks /蟒-siggen – larsks