使用pyaudio搭建节拍器;错误的时机

Using pyaudio to build a Metronome; wrong timing

所以想做一个节拍器,决定用pyaudio。我知道还有其他方法,但我想稍后再做点别的。

到目前为止我的代码是这样的:


CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
def play_audio(filename):
    wf=wave.open(filename,"rb")
    p=pyaudio.PyAudio()
    stream_play=p.open(format=p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                output=True)
    data = wf.readframes(CHUNK)
    while True:
        if data != '':
            stream_play.write(data)
            data = wf.readframes(CHUNK)
        if data == b"":
            break
    stream_play.stop_stream()
    stream_play.close()
    p.terminate()

def metronom(bpm):
    while True: 
        play_callback(beep)
        time.sleep(60/bpm)

beep="beep-07a.wav"



我以为成功了,但不幸的是时机完全不对。我也用回调函数试过,但时间同样错误。

现在的解决方案是这样的

def metronom(bpm):
    while True: 
        startTime = time.time()
        play_callback(beep)
        endTime=time.time()-startTime
        time.sleep(60/bpm-endTime)

您希望每 60/bpm 秒调用一次 play_audio 函数,但函数调用本身需要时间:您需要读取文件、打开流、播放文件(谁知道需要多长时间它是)并关闭流。这样就增加了从一次点击到下一次点击的时间。

要解决此问题,您可以尝试从睡眠时间中减去 运行 play_audio 功能所需的时间。您还可以在单​​独的线程上试验 运行ning play_audio。

如果你的节拍器只需要一个滴答声,如果你在 windows OS 你可以很容易地使用 Winsound 创建一个节拍器, 尝试以下。

import winsound
frequency = 25  # Set Frequency To 25 Hertz
duration = 5*1000  # Set Duration To 5000 ms or 5 second
winsound.Beep(frequency, duration)