SDL: как остановить звук - не возобновить, что SDL_PauseAudio (1) действительно?
Разработка приложения iOS, которое использует инфраструктуру CoreAudio, я имею дело с бессмысленным поведением IMHO в реестре SDL. воспроизведение звука. SDL воспроизводит аудио в цикле, и только способ запуска воспроизведения состоит в вызове SDL_PauseAudio(0)
, и единственный способ остановить его (без других побочных эффектов, о котором я не буду говорить здесь) - вызвать SDL_PauseAudio(1)
. Насколько я знаю.
В чем проблема для меня в SDL здесь? Просто - следующий вызов SDL_PauseAudio(1)
на самом деле возобновляет воспроизведение, заставляя фреймворк играть в какой-то беспорядок * перед запросом новых звуковых данных *. Это связано с тем, как SDL_CoreAudio.c реализует цикл воспроизведения.
Это означает, что SDL не реализует STOP, он реализует только PAUSE/RESUME и неправильно управляет обработкой звука. Это означает, что если вы будете играть в sampleA и хотите продолжить воспроизведение sampleB, вы также услышите фрагменты sampleA, ожидая только услышать воспроизведение образца B.
Если я ошибаюсь, пожалуйста, поправьте меня.
Если нет, то здесь мой diff, который я использовал для реализации также STOP-поведения: как только я закончу игру sampleA, я вызываю SDL_PauseAudio(2)
, чтобы цикл воспроизведения завершался, а следующий вызов в SDL_PauseAudio (0) запускает его снова, это время, не играя беспорядок из образцаA, но правильно воспроизводя только данные из smapleB.
Index: src/audio/coreaudio/SDL_coreaudio.c
===================================================================
--- src/audio/coreaudio/SDL_coreaudio.c
+++ src/audio/coreaudio/SDL_coreaudio.c
@@ -250,6 +250,12 @@
abuf = &ioData->mBuffers[i];
SDL_memset(abuf->mData, this->spec.silence, abuf->mDataByteSize);
}
+ if (2 == this->paused)
+ {
+ // this changes 'pause' behavior to 'stop' behavior - next
+ // plyaing starts from beginning, i.e. it won't resume
+ this->hidden->bufferOffset = this->hidden->bufferSize;
+ }
return 0;
}
Мне стыдно, что я отредактировал SDL-код, но у меня нет связи с авторами и не нашел никакой помощи. Ну, для меня это странно, что никто не нуждается в STOP-поведении в SDL?
Ответы
Ответ 1
Способом вашей проблемы является, например, более эффективное управление вашим аудиоустройством с помощью SDL. Вот что я предлагаю:
void myAudioCallback(void *userdata, Uint8 *stream, int len) { ... }
SDL_AudioDeviceID audioDevice;
void startAudio()
{
// prepare the device
static SDL_AudioSpec audioSpec;
SDL_zero(audioSpec);
audioSpec.channels = 2;
audioSpec.freq = 44100;
audioSpec.format = AUDIO_S16SYS;
audioSpec.userdata = (void*)myDataLocation;
audioSpec.callback = myAudioCallback;
audioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, &audioSpec, 0);
// actually start playback
SDL_PauseAudioDevice(audioDevice, 0);
}
void stopAudio()
{
SDL_CloseAudioDevice(audioDevice);
}
Это работает для меня, callback не вызывается после stopAudio(), и мусор не отправляется в динамик.