-
Notifications
You must be signed in to change notification settings - Fork 494
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
sokol_audio ALSA: buffer size initialization problem on some Linux configs #400
Comments
Hmm, interesting. I guess SoLoud will have the same problem then. That's were the sokol_audio.h backend code is taken from. It works on my Asus Zenbook laptop with Ubuntu (currently at v20.04, but also on v18.x). Here's the init code from SoLoud: miniaudio on the other hand seems to call set_rate_near before set_buffer_size_near. Thanks for the report and suggested fix, I'll try to add it later today! |
Ok I committed a fix, it's quite different from your code though: ...but it's hard to test without being able to reproduce the original problem. I think the order of calls isn't the problem though, but instead that ALSA might not support the requested buffer size on your config. The difference between I also changed a hard assert into a soft initialization error if the actual buffer size is no longer a multiple of the sokol-audio fifo packet size (e.g. on my laptop the minimal ALSA buffer size seems to be 96 frames, which is not a multiple of the 128 frames for the ring buffer packet size, hopefully this isn't a problem with "realistic" buffer sizes, and those are always multiple of 128. If not, more fixes are needed. Can you give the fix a whirl and let me know if this works now on your machines? (if not please reopen this issue). |
Doesn't work for me:
|
Man that's weird.. Is this one of the sokol-samples or your own code? What's the initial value for buffer_frames? The sokol-samples use the default buffer size of 2048 frames, it would be very strange if this would result in 1881 allocated frames... |
1881 isn't even a multiple of 32, 64 or 96... (96 frames seems to be the minimal supported buffer size on my config). |
This is from saudio-app.
This is from alsa function call:
|
Hmm... currently I have no clue what to do about this. If ALSA allocates such weird buffer sizes the entire code of pushing audio packets needs to be rewritten... why would any audio hardware require such an odd buffer size? |
1881 isn't a multiple of any 2^N number, but it's a multiple of 3: 3*627 = 1881. But 627 also isn't a particularly "round number". This is very very odd. |
It should be noted, that this weird behaviour happens only when sample rate is 44100. For 48000 everything works as expected.
|
Aha, interesting! When you try to initialize with sample rate 44100, does the ALSA initialization change this to 48000 (e.g. (44100 / 48000) * 2048 = 1881,6 ...so at least this explains where that strange buffer size is coming from. It seems like ALSA adjusts the buffer size to get the same latency if it cannot match the requested sample rate. 1881 samples at 44.1 kHz would cover the same duration as 2048 samples at 48 kHz... I think this gives me some ideas how to proceed, but I need to study the ALSA API a bit more. I'm currently busy with D3D11 swapchain stuff, but hopefully I can look into this afterwards. Thanks for your investigations ! |
Hmm ok, I've been reading up a bit more on how ALSA setup-configuration works, and I did a bit more code cleanup as result, but I don't think this fixes the problems on your machines. Before going into the details, I don't understand why the previous (and current) code doesn't work on your setup, because the setup code should accept a buffer size of 2048 frames, but automatically select 48kHz sample rate even if 44.1 kHz was requested (since this combination: 2048 buffer size and 48kHz seems to be supported on your machine). The way this ALSA configuration stuff works is that you first setup a structure with all possible parameter combinations: Line 1072 in 5b5d9a7
...all following function calls "restrict" this configuration space more and more to throw out "unwanted" configs. So step by step (with the new code): Remove all 'access types' that are not RW_INTERLEAVED: Line 1073 in 5b5d9a7
Remove all configs with sample formats that are not FLOAT_LE: Lines 1074 to 1077 in 5b5d9a7
Remove all configs with buffer sizes different from the requested buffer size: Lines 1078 to 1081 in 5b5d9a7
Remove all configs where the channel count doesn't match: Lines 1082 to 1085 in 5b5d9a7
...and finally remove all configs with a non-matching sample rate, but allow ALSA to pick a "nearby" sample rate: Lines 1086 to 1092 in 5b5d9a7
If after any of those steps the remaining "configuration space" is empty (meaning this combination of parameters is not supported by the ALSA driver), the Now the strange part: if the combination of 2048 sample frames at 48 kHz is supported on your hardware configs, then all config steps should succeed, and the last function |
I've looked at openal-soft ALSA initialization code and borrowed one function call, that you are not using. With this patch, everything works. But I don't understand why... diff --git a/sokol_audio.h b/sokol_audio.h
index 8df5813..897526a 100644
--- a/sokol_audio.h
+++ b/sokol_audio.h
@@ -1083,6 +1083,11 @@ _SOKOL_PRIVATE bool _saudio_backend_init(void) {
SOKOL_LOG("sokol_audio.h: requested channel count not supported");
goto error;
}
+ /* disable resampler */
+ if(snd_pcm_hw_params_set_rate_resample(_saudio.backend.device, params, 0) < 0) {
+ SOKOL_LOG("set_rate_resample failed");
+ goto error;
+ }
/* let ALSA pick a nearby sampling rate */
rate = _saudio.sample_rate;
dir = 0; |
...which is also strange because I would except that resampling is a good thing if a requested sample rate isn't supported. But maybe this is what enables picking a nearby sample rate in the first place instead of trying to emulate the requested sample rate by resampling. Thanks for looking into this, I'll try to add this fix tomorrow :) |
Oops. I was too fast, to report everything is OK. There is sound, but it is not right:
Sorry. P.S. Initially, I've tried to set '1', but got no sound at all. |
Hmm this sounds like there's still some disagreement about sample rates and/or buffer sizes, maybe it's just the returned sample rate that's wrong. I really should try to get my hands on one of those "problematic" laptops. What are those two laptops models you're testing on? Maybe similar configs are sold as very cheap laptops. PS: and do you know how to get the chipset info on Linux? E.g. what command tells me that I have (for instance) a "Conexant CX20751/2"? |
...I wonder if the best short-term solution is to simply set the default sample rate in sokol_audio.h to 48kHz. E.g. if "native" 48kHz is more widely supported than 44.1kHz, this would definitely make sense. I'll try to do some research what native sample rates are common... (PS: only downside would be that I need to add resampling to my plmpeg video decoding sample, because MPEG1 audio frequency is (typically?) 44.1kHz (definitely in the example video I used). |
...another more robust solution is to rewrite the ring buffer code so that the audio streaming buffer size doesn't need to be a multiple of the ring-buffer packet size... I just remembered that I did something similar in the plmpeg.h sokol-sample... This would allow sokol_audio.h to work with odd buffer sizes (like 1881 frames we've seen here). I need to think this through a bit, and it will be a little while until I can take care of this. |
Yes, to this. The AAudio backend could benefit from being able to take a lower latency path where the callback can be called with different values (even within one audio session) depending on the characteristics of the underlying audio device. |
In function
_saudio_backend_init()
,snd_pcm_hw_params_set_rate_near()
return negative result.Reproduced on two different computers. Both run Arch current (x86_64):
The following patch fixes sound (saudio-app and modplay-app work), but I'm not sure that it doesn't hammer something else.
I.e. we set rate first, then try to set buffer size. The code was copied from alsa samples. I'm not sure, if we must change anything else (period_size).
P.S. It would be nice, if samples report sound initializion failure somehow. With red screen for example.
The text was updated successfully, but these errors were encountered: