Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metronome demo is flawed #133

Open
cmaughan opened this issue May 17, 2023 · 5 comments
Open

Metronome demo is flawed #133

cmaughan opened this issue May 17, 2023 · 5 comments

Comments

@cmaughan
Copy link

I recently integrated the sample code for PortAudio/AudioEngine into a test app. Everything worked, but the audio quality for the metronome was poor; with annoying distortion of the sound on occasion.

The root cause of this problem is that the metronome calculates a simple sin/cos wave using the current time information. Inevitably from one audio frame to the next, the time value used in the sin() calculation will drift as tempo is synced across the network. This means that the waveform being filled into the audio buffers will have discontinuities of phase, and distortion is heard.

I'm sure many users who have integrated the metronome into their code will have heard this.

One simple solution would be to trigger a complete 'ping' for every beat and fill the buffer with the wave until the ping has timed out. In this way, discontinuities between audio frames are removed. I tried this and it makes a nice clean sound.

I know that using sin/cos won't be typical, and wavetables, etc. are more likely, but it's a shame that the sample source code generates poor audio!

@fgo-ableton
Copy link
Collaborator

Ja. Back when we wrote this we chose this approach to have the sample code as simple as possible. Also in my experience this has been working fairly well for most audio drivers on most platforms. But yes, if the timestamps coming from the driver have too much jitter for the host time filter to smoothen them out it gets nasty.
What platform/driver are you using PortAudio with?

@cmaughan
Copy link
Author

On my main machine, I have something called a 'Realtek USB2.0 audio' output. I tried using DirectSound, MME, WASAPI drivers. I also tried it on my laptop (not sure what that has in it). Increasing the size of the audio frames helps, because then you get less phase differences / second of the wave. And it does usually settle down and get cleaner. I'm really surprised others don't encounter this. Maybe I'm just unlucky with my setup.

@fgo-ableton
Copy link
Collaborator

I see. In Live on Windows we actually disable Link when not using an ASIO driver because there is just too much jitter in the timestamps. It turns out using i.e. ASIO4ALL leads to way better results than using the default Windows APIs.

@cmaughan
Copy link
Author

My point in the bug is really that the approach is incorrect: you can't guarantee consistent phase between audio frames using the current approach. 'Use a better driver' is one solution. Generate a complete audio sample for each click is another.... it is simple enough to figure out a click is due, and generate 'n' audio samples for the duration, filling the buffers till they are done.
Note that the effect is also more pronounced with smaller audio frames, say 256 samples....
I will paste my crude fix here as an example...

@fgo-ableton
Copy link
Collaborator

Yes, I understand. I'm just saying we chose this route to have easier example code knowing that this will lead to bad results in some scenarios.
I'll consider updating the examples.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants