Reputation: 733
I'm trying to build a simple metronome to learn the nim programming language, and though I can get audio to play, the timing doesn't work. I'm running this on Mac OSX and there is always a lag every third or fourth 'click'
Here's my code:
# nim code to create a metronome
import times, os
import sdl2, sdl2/mixer
sdl2.init(INIT_AUDIO)
var click : ChunkPtr
var channel : cint
var audio_rate : cint
var audio_format : uint16
var audio_buffers : cint = 4096
var audio_channels : cint = 2
if mixer.openAudio(audio_rate, audio_format, audio_channels, audio_buffers) != 0:
quit("There was a problem")
click = mixer.loadWAV("click.wav")
var bpm = 120
var next_click = getTime()
let dur = initDuration(milliseconds = toInt(60000 / bpm))
var last_click = getTime()
while true:
var now = getTime()
if now >= next_click:
next_click = next_click + dur
# discard mixer.playChannelTimed(0, click, 0, cint(500)
discard mixer.playChannel(0, click, 0)
os.sleep(1)
Any idea why the lag?
(by the way, the click.wav file is only one channel and 0.2 seconds long)
Upvotes: 1
Views: 212
Reputation: 7681
The call to os.sleep(1)
is unreliable as a high precision timing control. On MacOSX it calls to nanosleep, which states:
If the interval specified in req is not an exact multiple of the
granularity underlying clock (see time(7)), then the interval will be
rounded up to the next multiple. Furthermore, after the sleep
completes, there may still be a delay before the CPU becomes free to
once again execute the calling thread.
As such, you need to find a different more reliable waiting method or simply remove that delay and burn CPU cicles in the hope of being more precise (your program could still get preempted by the OS anyway).
Upvotes: 1