Glitch encountered when using spatialized audio
Issue was originally reported in source repository, but adding it here for visibility - also curious if this issue can be reproduced by others.
I've noticed a "crackling" sound artifact in a few cases when spatialization is enabled. Here's a video with the sound artifact:
https://github.com/isledecomp/isle-portable/assets/1135351/4f2ba446-8a41-494e-af7e-52c94b73833f
I've set up a minimally reproducible example app for this issue here:
It would seem the problem is related to the fact that the "siren" sound is set to have a high volume:
ma_sound_set_volume(&siren, 0.984011f); // must be high
However, the issue is not present when spatialization is disabled.
I've noticed this too. With a simple sine wave at 200Hz looping from an in-memory stream I notice a slight crackling when the sound loops.
@mackron did you have a chance to try to reproduce it, or any idea what the problem might be? Unfortunately this issue affects a number of sounds used in our project, so would love to figure this out. Other than this issue miniaudio is a perfect fit for us. Thanks!
I haven't forgotten about this one, just haven't a chance to properly sit down and investigate it. Same for many other outstanding issues here.
@ethindp Your issue is different. Yours is almost certainly due to the start and end of the sound not being contiguous. If you're absolutely certain that's not the case feel free to open a separate ticket.
I can confirm that I can reproduce this as well on all three major desktop operating systems. Tested and reproduced on Windows x86_64, macOS ARM64, and Linux x86_64.
For the sake of being comprehensive, here's a cross-platform version of @foxtacles' test app that only uses POSIX calls and should compile cleanly on macOS and Linux. hospital-posix.zip
Thanks so much for your work!
I've finally got to looking at this. It's an annoying one, but I have a workaround to get you going. The workaround is either disable pitch shifting entirely with the MA_SOUND_FLAG_NO_PITCH flag in ma_sound_init_from_file(), or disable doppler effect with ma_sound_set_doppler_factor(&siren, 0.0f). Using MA_SOUND_FLAG_NO_PITCH is the faster option, but it will disable ma_sound_set_pitch() and doppler effect. If you need neither of these, MA_SOUND_FLAG_NO_PITCH is the way to go anyway.
As for why this is happening, it's something to do with the internal resampler. I don't know why it's affecting the siren sound and not others. I'll need to investigate further, but I don't think it'll be a simple solution. I have plans to do an overhaul of the resampler so hopefully it'll be fixed when I get to that. I've added your siren sound to my test suite and have added a note to my todo list to make sure I test against your sound.
You mentioned that this doesn't happen when spatialization is disabled. That is because when spatialization is disabled, so is the doppler effect.
Hope this helps! And sorry for the exceptionally long delay on getting to this.
Thank you! I can confirm that setting the Doppler factor to 0.0f does indeed resolve the glitch. We do need the Doppler effect in our game but it's not very noticeable so temporarily disabling it works for us.
Hope this helps! And sorry for the exceptionally long delay on getting to this.
Absolutely! And no worries about the time it took. miniaudio is an excellent fit for our application, and integration was a breeze even without prior experience in the audio space, so I very much appreciate your work here!
So I'm not sure how to make my sound contiguous; I'm generating it like so:
constexpr float A = 1.0;
constexpr float Fs = 44100.0;
constexpr float f = 200.0;
float phi = 0.0;
float delta = 2 * std::numbers::pi * f / Fs;
for (std::size_t i = 0; i < 44100; ++i) {
samples.emplace_back(A * std::sin(phi));
phi += delta;
}
Is this wrong in some way?
So I'm not sure how to make my sound contiguous; I'm generating it like so:
constexpr float A = 1.0; constexpr float Fs = 44100.0; constexpr float f = 200.0; float phi = 0.0; float delta = 2 * std::numbers::pi * f / Fs; for (std::size_t i = 0; i < 44100; ++i) { samples.emplace_back(A * std::sin(phi)); phi += delta; }
Is this wrong in some way?
You need to generate a single cycle of samples so it wraps around perfectly. Instead you generate 1 second of audio which causes a discontinuity of the signal. To calculate how many samples you need for a single cycle at a given frequency, you should divide the sampling rate by the frequency then round the number up to the nearest integer.