* 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.
This commit is contained in:
Amar Takhar 2009-04-17 02:14:42 +00:00
parent 50ce42d2e9
commit 6c256fd181
2 changed files with 45 additions and 19 deletions

View file

@ -94,14 +94,15 @@ int PortAudioPlayer::paCallback(const void *inputBuffer, void *outputBuffer, uns
AudioProvider *provider = player->GetProvider(); AudioProvider *provider = player->GetProvider();
#ifdef PORTAUDIO2_DEBUG #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), 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 #endif
// Calculate how much left // Calculate how much left
int64_t lenAvailable = (player->endPos - player->playPos) > 0 ? framesPerBuffer : 0; int64_t lenAvailable = (player->endPos - player->playPos) > 0 ? framesPerBuffer : 0;
// Play something // Play something
if (lenAvailable > 0) { if (lenAvailable > 0) {
provider->GetAudioWithVolume(outputBuffer, player->playPos, lenAvailable, player->GetVolume()); provider->GetAudioWithVolume(outputBuffer, player->playPos, lenAvailable, player->GetVolume());
@ -112,19 +113,17 @@ int PortAudioPlayer::paCallback(const void *inputBuffer, void *outputBuffer, uns
// Continue as normal // Continue as normal
return 0; 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. // Abort stream and stop the callback.
return paAbort; return paAbort;
}
} }
//////// ////////
// Play // Play
void PortAudioPlayer::Play(int64_t start,int64_t count) { void PortAudioPlayer::Play(int64_t start,int64_t count) {
PaError err;
// Stop if it's already playing // Stop if it's already playing
wxMutexLocker locker(PAMutex); wxMutexLocker locker(PAMutex);
@ -135,7 +134,16 @@ void PortAudioPlayer::Play(int64_t start,int64_t count) {
// Start playing // Start playing
if (!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) { if (err != paNoError) {
return; 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 // Open stream
@ -191,7 +214,7 @@ void PortAudioPlayer::OpenStream() {
wxLogDebug(_T("PortAudioPlayer::OpenStream Output channels: %d, Latency: %f Sample Rate: %ld\n"), 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); 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) { if (err != paNoError) {
@ -213,6 +236,7 @@ void PortAudioPlayer::CloseStream() {
} catch (...) {} } catch (...) {}
} }
//////////////////////// ////////////////////////
/// Get current stream position. /// Get current stream position.
int64_t PortAudioPlayer::GetCurrentPosition() int64_t PortAudioPlayer::GetCurrentPosition()

View file

@ -65,15 +65,17 @@ private:
void *stream; void *stream;
PaTime paStart; PaTime paStart;
static int paCallback( static int paCallback(
const void *inputBuffer, const void *inputBuffer,
void *outputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* const PaStreamCallbackTimeInfo*
timeInfo, timeInfo,
PaStreamCallbackFlags PaStreamCallbackFlags
statusFlags, statusFlags,
void *userData); void *userData);
static void paStreamFinishedCallback(void *userData);
public: public:
PortAudioPlayer(); PortAudioPlayer();