maltek
maltek

Reputation: 23

Using pyaudio to build a Metronome; wrong timing

So I wanted to build a metronome and decided to use pyaudio. I know there are other ways but I want to make something else later with that.

Thats my Code so far:


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"



I thought it worked out, but unfortunately the timing is completely off. I also tried it with a callback function, but had the same wrong timing.

THE SOLUTION NOW LOOKS LIKE THIS

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

Upvotes: 1

Views: 327

Answers (2)

margalo
margalo

Reputation: 138

You want the play_audio function to be called every 60/bpm seconds, but the function call itself takes time: you need to read the file, open the stream, play the file (who knows how long it is) and close the stream. So that adds to the time from one click to the next.

To fix this problem, you could try subtracting the time it takes to run the play_audio function from the time you sleep. You could also experiment with running play_audio on a separate thread.

Upvotes: 1

floprm
floprm

Reputation: 102

If you metronome just need a tick sound and if you are on windows OS you can easily use Winsound to create a metronome, try following.

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

Upvotes: 0

Related Questions