在 python 中尝试使用声音设备操纵声音阵列时延迟太高
Too high latency while trying to manipulate sound arrays using sounddevice in python
几天前,我在Python 2.7.5 中安装了a sounddevice 库。我正在尝试制作一个声音阵列,并在我按下 MIDI 控制器上的一个键后立即为其添加一些效果。但是我得到了 0.1 到 0.2 秒的巨大延迟,这使得我的代码无用:
import numpy as np
import sounddevice as sd
import time
import math
#we're making a sound array with a 5 seconds length noisy sound and playing it:
duration=5
framerate = 44100
array=0.02*np.random.uniform(-1, 1, framerate*duration)
sd.play(array, framerate)
t=time.time()
while(True):
signal=raw_input("push ENTER to hear a beep")
start_iter=int(framerate*(time.time()-t))
end_iter=min(start_iter+framerate/4, len(array))
#we're trying to change our data array and play a beep signal of 0.25 second after each ENTER press instantly
for i in range(start_iter, end_iter):
array[i]=0.05*math.sin(440*2*math.pi*i/44100.)
if end_iter==len(array): break #safe exit of a process after 5 seconds has passed
为简单起见,我的声音阵列只是一种嘈杂的声音,我的效果包含 440Hz 的蜂鸣声。我在这里使用 raw_input()(在 Python 3.x 中输入 "input()")而不是使用 Pygame 库可能实现的 MIDI 输入。我的代码有效,但每次我们按 ENTER 时,我们都会在蜂鸣信号之前听到短暂的延迟。
有没有可能消除它?如果没有,是否有任何其他库允许实时播放无延迟的声音流?
您可以使用 sounddevice.default.latency. Note however, that this is a suggested latency, the actual latency may be different, depending on the hardware and probably also on the host API. You can get an estimate of the actual latency with sounddevice.Stream.latency 指定所需的延迟时间。
默认情况下,sounddevice
模块使用 PortAudio 的 high 延迟设置,希望提供更稳健的行为。您可以将它切换到 PortAudio 的 low 设置,或者您可以尝试任何您想要的数值(以秒为单位)。
import sounddevice as sd
sd.default.latency = 'low'
或者,你当然也可以使用play()
等的latency
参数
如果您想更好地控制时间,您可能需要编写自己的自定义回调函数。在那里你可以使用 time
参数,在回调函数之外你可以使用 sounddevice.Stream.time.
您也可以尝试在不使用 callback
参数的情况下启动流,然后在其上使用 sounddevice.Stream.write()。我不知道这会对延迟造成什么影响,但可能值得一试。
关于其他库,因为您似乎已经在使用 PyGame,您也可以将它用于音频输出。它可能有也可能没有不同的延迟。
顺便说一句,我不知道您的代码是否是线程安全的,因为您正在操作数组,而回调将内存地址提供给 PortAudio。像这样实现它可能不是一个好主意。
几天前,我在Python 2.7.5 中安装了a sounddevice 库。我正在尝试制作一个声音阵列,并在我按下 MIDI 控制器上的一个键后立即为其添加一些效果。但是我得到了 0.1 到 0.2 秒的巨大延迟,这使得我的代码无用:
import numpy as np
import sounddevice as sd
import time
import math
#we're making a sound array with a 5 seconds length noisy sound and playing it:
duration=5
framerate = 44100
array=0.02*np.random.uniform(-1, 1, framerate*duration)
sd.play(array, framerate)
t=time.time()
while(True):
signal=raw_input("push ENTER to hear a beep")
start_iter=int(framerate*(time.time()-t))
end_iter=min(start_iter+framerate/4, len(array))
#we're trying to change our data array and play a beep signal of 0.25 second after each ENTER press instantly
for i in range(start_iter, end_iter):
array[i]=0.05*math.sin(440*2*math.pi*i/44100.)
if end_iter==len(array): break #safe exit of a process after 5 seconds has passed
为简单起见,我的声音阵列只是一种嘈杂的声音,我的效果包含 440Hz 的蜂鸣声。我在这里使用 raw_input()(在 Python 3.x 中输入 "input()")而不是使用 Pygame 库可能实现的 MIDI 输入。我的代码有效,但每次我们按 ENTER 时,我们都会在蜂鸣信号之前听到短暂的延迟。 有没有可能消除它?如果没有,是否有任何其他库允许实时播放无延迟的声音流?
您可以使用 sounddevice.default.latency. Note however, that this is a suggested latency, the actual latency may be different, depending on the hardware and probably also on the host API. You can get an estimate of the actual latency with sounddevice.Stream.latency 指定所需的延迟时间。
默认情况下,sounddevice
模块使用 PortAudio 的 high 延迟设置,希望提供更稳健的行为。您可以将它切换到 PortAudio 的 low 设置,或者您可以尝试任何您想要的数值(以秒为单位)。
import sounddevice as sd
sd.default.latency = 'low'
或者,你当然也可以使用play()
等的latency
参数
如果您想更好地控制时间,您可能需要编写自己的自定义回调函数。在那里你可以使用 time
参数,在回调函数之外你可以使用 sounddevice.Stream.time.
您也可以尝试在不使用 callback
参数的情况下启动流,然后在其上使用 sounddevice.Stream.write()。我不知道这会对延迟造成什么影响,但可能值得一试。
关于其他库,因为您似乎已经在使用 PyGame,您也可以将它用于音频输出。它可能有也可能没有不同的延迟。
顺便说一句,我不知道您的代码是否是线程安全的,因为您正在操作数组,而回调将内存地址提供给 PortAudio。像这样实现它可能不是一个好主意。