coreaudio: dynamically allocate AudioQueueBuffers. We need more than two buffers to flip between if they are small, or CoreAudio won't make any sound; apparently it needs X milliseconds of audio queued when it needs to play more or it drops any queued buffers. We are currently guessing 50 milliseconds as a minimum, but there's probably a more proper way to get the minimum time period from the system. Fixes Bugzilla #3656.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
diff --git a/src/audio/coreaudio/SDL_coreaudio.h b/src/audio/coreaudio/SDL_coreaudio.h
index 2227d44..85f19d4 100644
--- a/src/audio/coreaudio/SDL_coreaudio.h
+++ b/src/audio/coreaudio/SDL_coreaudio.h
@@ -47,7 +47,8 @@ struct SDL_PrivateAudioData
{
SDL_Thread *thread;
AudioQueueRef audioQueue;
- AudioQueueBufferRef audioBuffer[2];
+ int numAudioBuffers;
+ AudioQueueBufferRef *audioBuffer;
void *buffer;
UInt32 bufferOffset;
UInt32 bufferSize;
diff --git a/src/audio/coreaudio/SDL_coreaudio.m b/src/audio/coreaudio/SDL_coreaudio.m
index a1c3736..2b9d6de 100644
--- a/src/audio/coreaudio/SDL_coreaudio.m
+++ b/src/audio/coreaudio/SDL_coreaudio.m
@@ -533,11 +533,12 @@ COREAUDIO_CloseDevice(_THIS)
}
if (this->hidden->audioQueue) {
- for (i = 0; i < SDL_arraysize(this->hidden->audioBuffer); i++) {
+ for (i = 0; i < this->hidden->numAudioBuffers; i++) {
if (this->hidden->audioBuffer[i]) {
AudioQueueFreeBuffer(this->hidden->audioQueue, this->hidden->audioBuffer[i]);
}
}
+ SDL_free(this->hidden->audioBuffer);
AudioQueueDispose(this->hidden->audioQueue, 1);
}
@@ -663,7 +664,25 @@ prepare_audioqueue(_THIS)
return 0;
}
- for (i = 0; i < SDL_arraysize(this->hidden->audioBuffer); i++) {
+ /* Make sure we can feed the device at least 50 milliseconds at a time. */
+ const double msecs = (this->spec.size / ((double) this->spec.freq)) * 1000.0;
+ if (msecs >= 50.0) {
+ this->hidden->numAudioBuffers = 2;
+ } else {
+ this->hidden->numAudioBuffers = (int) (SDL_ceil(50.0 / msecs) * 2);
+ }
+
+ this->hidden->audioBuffer = SDL_calloc(1, sizeof (AudioQueueBufferRef) * this->hidden->numAudioBuffers);
+ if (this->hidden->audioBuffer == NULL) {
+ SDL_OutOfMemory();
+ return 0;
+ }
+
+#if DEBUG_COREAUDIO
+ printf("COREAUDIO: numAudioBuffers == %d\n", this->hidden->numAudioBuffers);
+#endif
+
+ for (i = 0; i < this->hidden->numAudioBuffers; i++) {
result = AudioQueueAllocateBuffer(this->hidden->audioQueue, this->spec.size, &this->hidden->audioBuffer[i]);
CHECK_RESULT("AudioQueueAllocateBuffer");
SDL_memset(this->hidden->audioBuffer[i]->mAudioData, this->spec.silence, this->hidden->audioBuffer[i]->mAudioDataBytesCapacity);