1010
1111#include " osapi/osapi.h"
1212
13- #include " sound/openal.h"
14-
1513#include " tracing/tracing.h"
1614
1715#include " io/key.h"
@@ -25,8 +23,6 @@ using namespace cutscene::player;
2523namespace {
2624using namespace cutscene ;
2725
28- const int MAX_AUDIO_BUFFERS = 15 ;
29-
3026std::unique_ptr<Decoder> findDecoder (__UNUSED const SCP_string& name, __UNUSED const PlaybackProperties& properties) {
3127#ifdef WITH_FFMPEG
3228 {
@@ -71,19 +67,23 @@ void audioPlaybackInit(PlayerState* state) {
7167 }
7268 state->hasAudio = true ;
7369
74- OpenAL_ErrorCheck (alGenSources (1 , &state->audioSid ), return );
75- OpenAL_ErrorPrint (alSourcef (state->audioSid , AL_GAIN, 1 .0f ));
76-
77- state->audioBuffers .clear ();
78- state->audioBuffers .resize (MAX_AUDIO_BUFFERS, 0 );
70+ // best guess defaults, might change later
71+ state->audioSpec .channels = 2 ;
72+ state->audioSpec .format = SDL_AUDIO_S16LE;
73+ state->audioSpec .freq = 48000 ;
7974
80- OpenAL_ErrorCheck (alGenBuffers (static_cast <ALsizei>(state->audioBuffers .size ()), state->audioBuffers .data ()),
81- return );
75+ state->audioStream = SDL_OpenAudioDeviceStream (SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
76+ &state->audioSpec ,
77+ nullptr , nullptr );
8278
83- for ( auto buffer : state->audioBuffers ) {
84- state-> unqueuedAudioBuffers . push (buffer) ;
79+ if ( ! state->audioStream ) {
80+ return ;
8581 }
8682
83+ // stream is created in a paused state, so start it playing
84+ // it will just be silent until data is queued
85+ SDL_ResumeAudioStreamDevice (state->audioStream );
86+
8787 state->audioInited = true ;
8888}
8989
@@ -185,76 +185,44 @@ void processSubtitleData(PlayerState* state) {
185185bool processAudioData (PlayerState* state) {
186186 TRACE_SCOPE (tracing::CutsceneProcessAudioData);
187187
188+ AudioFramePtr audioData;
189+
188190 if (!state->hasAudio ) {
189191 if (state->decoder ->hasAudio ()) {
190192 // Even if we don't play the sound we still need to remove it from the queue
191- AudioFramePtr audioData;
192193 while (state->decoder ->tryPopAudioData (audioData)) {
193194 // Intentionally left empty
194195 }
195196 }
196197 return false ;
197198 }
198199
199- ALint processed = 0 ;
200- OpenAL_ErrorCheck (alGetSourcei (state->audioSid , AL_BUFFERS_PROCESSED, &processed), return false );
201-
202- // First check for free buffers and push them int the audio queue
203- for (int i = 0 ; i < processed; ++i) {
204- ALuint buffer;
205- OpenAL_ErrorPrint (alSourceUnqueueBuffers (state->audioSid , 1 , &buffer));
206- state->unqueuedAudioBuffers .push (buffer);
207- }
208-
209- AudioFramePtr audioData;
210-
211- while (!state->unqueuedAudioBuffers .empty () && state->decoder ->tryPopAudioData (audioData)) {
212- auto buffer = state->unqueuedAudioBuffers .front ();
213- state->unqueuedAudioBuffers .pop ();
214-
215- ALenum format = (audioData->channels == 2 ) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
216-
217- OpenAL_ErrorCheck (alBufferData (buffer,
218- format,
219- audioData->audioData .data (),
220- static_cast <ALsizei>(audioData->audioData .size () * sizeof (short )),
221- static_cast <ALsizei>(audioData->rate )), return false );
222-
223- OpenAL_ErrorCheck (alSourceQueueBuffers (state->audioSid , 1 , &buffer), return false );
224- }
225-
226- ALint status = 0 , queued = 0 ;
227- OpenAL_ErrorCheck (alGetSourcei (state->audioSid , AL_SOURCE_STATE, &status), return false );
200+ while (state->decoder ->tryPopAudioData (audioData)) {
201+ // change audio format if needed (doesn't affect currently queued data)
202+ if ((audioData->channels != state->audioSpec .channels ) ||
203+ (audioData->rate != state->audioSpec .freq ))
204+ {
205+ state->audioSpec .channels = audioData->channels ;
206+ state->audioSpec .freq = audioData->rate ;
228207
229- OpenAL_ErrorCheck (alGetSourcei (state->audioSid , AL_BUFFERS_QUEUED, &queued), return false );
208+ SDL_SetAudioStreamFormat (state->audioStream , &state->audioSpec , nullptr );
209+ }
230210
231- if ((status != AL_PLAYING) && (queued > 0 )) {
232- OpenAL_ErrorPrint (alSourcePlay (state->audioSid ));
211+ // add it to the queue
212+ SDL_PutAudioStreamData (state->audioStream , audioData->audioData .data (),
213+ static_cast <int >(audioData->audioData .size () * sizeof (short )));
233214 }
234215
235- // Get status again in cause we just started playback
236- OpenAL_ErrorCheck (alGetSourcei (state->audioSid , AL_SOURCE_STATE, &status), return false );
237- return status == AL_PLAYING;
216+ return true ;
238217}
239218
240219void audioPlaybackClose (PlayerState* state) {
241220 if (!state->audioInited ) {
242221 return ;
243222 }
244223
245- ALint p = 0 ;
246-
247- OpenAL_ErrorPrint (alSourceStop (state->audioSid ));
248- OpenAL_ErrorPrint (alGetSourcei (state->audioSid , AL_BUFFERS_PROCESSED, &p));
249- OpenAL_ErrorPrint (alSourceUnqueueBuffers (state->audioSid , p, state->audioBuffers .data ()));
250- OpenAL_ErrorPrint (alDeleteSources (1 , &state->audioSid ));
251-
252- for (auto buffer : state->audioBuffers ) {
253- // make sure that the buffer is real before trying to delete, it could crash for some otherwise
254- if ((buffer != 0 ) && alIsBuffer (buffer)) {
255- OpenAL_ErrorPrint (alDeleteBuffers (1 , &buffer));
256- }
257- }
224+ SDL_DestroyAudioStream (state->audioStream );
225+ state->audioStream = nullptr ;
258226
259227 state->audioInited = false ;
260228}
0 commit comments