SDL: как остановить аудио, а не возобновить, что на самом деле делает SDL_PauseAudio (1)? - PullRequest
11 голосов
/ 16 ноября 2011

Разрабатывая приложение для iOS, использующее инфраструктуру CoreAudio, я имею дело с IMHO бессмысленным поведением SDL reg. Воспроизведение аудио. SDL воспроизводит аудио в цикле, и единственный способ запустить воспроизведение - это вызвать SDL_PauseAudio(0), а единственный способ остановить его (без других побочных эффектов, о котором я не буду здесь говорить) - это вызвать SDL_PauseAudio(1). Насколько я знаю.

В чем проблема для меня в SDL здесь? Проще говоря, следующий вызов SDL_PauseAudio(1) фактически возобновляет воспроизведение, заставляя фреймворк воспроизвести mess *, прежде чем запрашивать новые звуковые данные *. Это связано с тем, как SDL_CoreAudio.c реализует цикл воспроизведения.

Это означает, что SDL не реализует STOP, он реализует просто PAUSE / RESUME и неправильно управляет обработкой звука. Это означает, что если вы играете sampleA и хотите воспроизвести sampleB позже, вы услышите также фрагменты sampleA, ожидая только прослушивания воспроизведения sampleB.

Если я не прав, поправьте меня.

Если нет, то вот мой diff, который я использовал для реализации поведения STOP: как только я закончу воспроизведение sampleA, я вызываю SDL_PauseAudio(2), чтобы цикл воспроизведения завершился, и следующий вызов SDL_PauseAudio (0) запустил его снова, это время, играя без беспорядка из sampleA, но правильно воспроизводя только данные из 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 Ответ

0 голосов
/ 03 июля 2014

Способ решения вашей проблемы, например, заключается в улучшении управления вашим аудиоустройством с помощью 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);
}

Это работает для меня, обратный вызов не вызывается после stopAudio (), и динамик не отправляет мусор.

...