| Summary: | SDL 2.0.5 won't play sound at 96KHz on macOS | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Lior Halphon <LIJI32> |
| Component: | audio | Assignee: | Ryan C. Gordon <icculus> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | ||
| Version: | 2.0.5 | ||
| Hardware: | x86_64 | ||
| OS: | macOS 10.12 | ||
| Attachments: | sample.wav at 96k | ||
|
Description
Lior Halphon
2017-05-20 08:38:25 UTC
Created attachment 2745 [details] sample.wav at 96k This is working here for me with the test/loopwave.c program in SDL's source distribution ( https://hg.libsdl.org/SDL/file/7860594a8ad7/test/loopwave.c ) and a 96KHz wave file (attached) on macOS 10.12.5. --ryan. Is there some code you can post that reproduces this bug? The following code reproduces the problem. It should play white noise for 10 seconds, but only plays for a split second. Changing freq to 96000 or samples to 2048 solves it.
#include <stdlib.h>
#include <SDL2/SDL.h>
static void audio_callback(void *gb, Uint8 *stream, int len)
{
while (len--) {
*(stream++) = rand();
}
}
int main(int argc, char **argv)
{
SDL_AudioSpec want_aspec, have_aspec;
SDL_Init( SDL_INIT_EVERYTHING );
/* Configure Audio */
memset(&want_aspec, 0, sizeof(want_aspec));
want_aspec.freq = 96000;
want_aspec.format = AUDIO_S16SYS;
want_aspec.channels = 2;
want_aspec.samples = 512;
want_aspec.callback = audio_callback;
want_aspec.userdata = NULL;
SDL_OpenAudio(&want_aspec, &have_aspec);
/* Start Audio */
SDL_PauseAudio(0);
SDL_Delay(10000);
return 0;
}
(In reply to Lior Halphon from comment #3) > Changing freq to 96000 to 44100* This is a quirk in Mac OS X CoreAudio. If you don't fill audio buffers fast enough they'll stop being used in the audio pipeline. The only answer I've found is to make sure you have 15-20 ms in your audio buffers. Changing your buffer size or reducing your audio rate is the correct workaround. This is true on iOS as well. (In reply to Sam Lantinga from comment #6) > This is true on iOS as well. Hmm, we might be able to mitigate this now that we have SDL_AudioStream, which can buffer the difference if the app wants too small of a buffer per-callback... (But it's still possible the issue is me misusing CoreAudio and it only manifests when the buffers are small.) --ryan. How did it work in SDL 2.0.4 and 1.2 then? What was changed to make this an issue? (In reply to Lior Halphon from comment #8) > How did it work in SDL 2.0.4 and 1.2 then? What was changed to make this an > issue? We moved from Apple's AudioUnits API to AudioQueues. --ryan. This should be fixed by https://hg.libsdl.org/SDL/rev/ad26a063ffff ... poking at Apple's API suggests that what CoreAudio wants is at least X milliseconds of audio available when it's time to feed the audio hardware, and it doesn't care if you queued one gigantic buffer to get there or a dozen tiny ones. I imagine it's possible that a USB or bluetooth device wants way more buffered at a time than the on-board PCM chip, and there's probably an API to query for that minimum limit, but aiming for being able to buffer two blocks of 50 milliseconds seems to work okay (20ms was too small). This approach also lets us have the app's callback fire with the originally-desired sample size but also not use a full SDL_AudioStream to buffer the difference. --ryan. (In reply to Ryan C. Gordon from comment #10) > I imagine it's possible that a USB or bluetooth device wants way more > buffered at a time than the on-board PCM chip, and there's probably an API > to query for that minimum limit, but aiming for being able to buffer two > blocks of 50 milliseconds seems to work okay (20ms was too small). Turns out 50 only needs to be 10 when you use the correct variable with the equation (samples, not size). https://hg.libsdl.org/SDL/rev/0b4a3c824d38 --ryan. |