From 235af35603d1c36cd857bd8d012c4002f087bef2 Mon Sep 17 00:00:00 2001 From: Amar Takhar Date: Fri, 17 Apr 2009 02:14:42 +0000 Subject: [PATCH] * Remove a short-lived hack (hours?) and replace it with a PaStreamFinishedCallback which is called anytime a PaCallback is exited with anything other than 0. (normal operation) paStreamFinishedCallback handles stopping the audio stream when we've run to the end of the current selection or the stream is stopped. * Add framesPerBuffer to paCallback debug output in preperation for dynamic buffers. * Set paPrimeOutputBuffersUsingStreamCallback in Pa_OpenStream to prime the output buffer using the callback rather than initing with empty space which is the default. * Indent paCallback decleration another level. Originally committed to SVN as r2807. --- aegisub/src/audio_player_portaudio2.cpp | 44 +++++++++++++++++++------ aegisub/src/audio_player_portaudio2.h | 20 ++++++----- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/aegisub/src/audio_player_portaudio2.cpp b/aegisub/src/audio_player_portaudio2.cpp index 63a32766f..a79bd9e87 100644 --- a/aegisub/src/audio_player_portaudio2.cpp +++ b/aegisub/src/audio_player_portaudio2.cpp @@ -94,14 +94,15 @@ int PortAudioPlayer::paCallback(const void *inputBuffer, void *outputBuffer, uns AudioProvider *provider = player->GetProvider(); #ifdef PORTAUDIO2_DEBUG - printf("paCallBack: playPos: %lld startPos: %lld paStart: %f Pa_GetStreamTime: %f AdcTime: %f DacTime: %f CPU: %f\n", + printf("paCallBack: playPos: %lld startPos: %lld paStart: %f Pa_GetStreamTime: %f AdcTime: %f DacTime: %f framesPerBuffer: %lu CPU: %f\n", player->playPos, player->startPos, player->paStart, Pa_GetStreamTime(player->stream), - timeInfo->inputBufferAdcTime, timeInfo->outputBufferDacTime, Pa_GetStreamCpuLoad(player->stream)); + timeInfo->inputBufferAdcTime, timeInfo->outputBufferDacTime, framesPerBuffer, Pa_GetStreamCpuLoad(player->stream)); #endif // Calculate how much left int64_t lenAvailable = (player->endPos - player->playPos) > 0 ? framesPerBuffer : 0; + // Play something if (lenAvailable > 0) { provider->GetAudioWithVolume(outputBuffer, player->playPos, lenAvailable, player->GetVolume()); @@ -112,19 +113,17 @@ int PortAudioPlayer::paCallback(const void *inputBuffer, void *outputBuffer, uns // Continue as normal return 0; } - else { - // Set the end position to be less then the current play position. - player->endPos = player->endPos - (framesPerBuffer + 8192); - // Abort stream and stop the callback. - return paAbort; - } + // Abort stream and stop the callback. + return paAbort; } //////// // Play void PortAudioPlayer::Play(int64_t start,int64_t count) { + PaError err; + // Stop if it's already playing wxMutexLocker locker(PAMutex); @@ -135,7 +134,16 @@ void PortAudioPlayer::Play(int64_t start,int64_t count) { // Start playing if (!playing) { - PaError err = Pa_StartStream(stream); + + err = Pa_SetStreamFinishedCallback(stream, paStreamFinishedCallback); + + if (err != paNoError) { + wxLogDebug(_T("PortAudioPlayer::Play Could not set FinishedCallback\n")); + return; + } + + err = Pa_StartStream(stream); + if (err != paNoError) { return; } @@ -164,6 +172,21 @@ void PortAudioPlayer::Stop(bool timerToo) { } } +////////////////////////////////////////////// +// Called when the callback has finished. + +void PortAudioPlayer::paStreamFinishedCallback(void *userData) { + PortAudioPlayer *player = (PortAudioPlayer *) userData; + + player->playing = false; + + if (player->displayTimer) { + player->displayTimer->Stop(); + } + + wxLogDebug(_T("PortAudioPlayer::paStreamFinishedCallback Stopping stream.")); +} + /////////////// // Open stream @@ -191,7 +214,7 @@ void PortAudioPlayer::OpenStream() { wxLogDebug(_T("PortAudioPlayer::OpenStream Output channels: %d, Latency: %f Sample Rate: %ld\n"), pa_output_p.channelCount, pa_output_p.suggestedLatency, pa_output_p.sampleFormat); - PaError err = Pa_OpenStream(&stream, NULL, &pa_output_p, provider->GetSampleRate(), 256, paClipOff, paCallback, this); + PaError err = Pa_OpenStream(&stream, NULL, &pa_output_p, provider->GetSampleRate(), 256, paPrimeOutputBuffersUsingStreamCallback, paCallback, this); if (err != paNoError) { @@ -213,6 +236,7 @@ void PortAudioPlayer::CloseStream() { } catch (...) {} } + //////////////////////// /// Get current stream position. int64_t PortAudioPlayer::GetCurrentPosition() diff --git a/aegisub/src/audio_player_portaudio2.h b/aegisub/src/audio_player_portaudio2.h index 94127a408..81c85c022 100644 --- a/aegisub/src/audio_player_portaudio2.h +++ b/aegisub/src/audio_player_portaudio2.h @@ -65,15 +65,17 @@ private: void *stream; PaTime paStart; -static int paCallback( - const void *inputBuffer, - void *outputBuffer, - unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo* - timeInfo, - PaStreamCallbackFlags - statusFlags, - void *userData); + static int paCallback( + const void *inputBuffer, + void *outputBuffer, + unsigned long framesPerBuffer, + const PaStreamCallbackTimeInfo* + timeInfo, + PaStreamCallbackFlags + statusFlags, + void *userData); + + static void paStreamFinishedCallback(void *userData); public: PortAudioPlayer();