在低功耗计算机上从Python生成流畅的音频

时间:2016-01-29 02:10:18

标签: python audio portaudio pyaudio

我正在尝试用Python编写一个简单的音频函数生成器,以便在Raspberry Pi(模型2)上运行。代码基本上是这样做的:

  • 生成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)

问题是循环的每次迭代都会产生一个声音" tick"在音频中,即使使用外部USB声卡。有没有办法避免这种情况,而不是试图重写C中的所有内容?

我尝试使用pyaudio回调接口,但实际上听起来更糟糕(比如我的Pi可能很烦人)。

生成的音频需要很短,因为它最终会通过外部控制进行动态调整,而控制变化超过1秒的延迟只会感觉很尴尬。有没有更好的方法从Python代码中生成这些信号?

2 个答案:

答案 0 :(得分:6)

你听到了#34; tick"因为您发送的音频存在不连续性。 261.6 Hz的一秒钟包含261.6个周期,因此最终剩下大约半个周期:

Waveform showing discontinuity at 1 second

您需要更改频率,以便每秒有一整个周期(例如,262 Hz),更改持续时间,使其足够长,持续整数个周期,或者每隔一秒生成一个新的音频片段,从正确的阶段开始,以适应最后一个块离开的位置。

答案 1 :(得分:1)

我正在向您寻找类似的问题,并通过连接一堆预先计算的块找到了一个预先计算长度的变体。

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

使用带有1秒预先计算的块的for循环" play_tone"函数似乎生成一个平滑的声音输出,但这是在PC上。如果这对你不起作用,可能是树莓派有不同的后端实现,不喜欢连续写入。