forked from mia/Aegisub
* 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:
parent
50ce42d2e9
commit
6c256fd181
2 changed files with 45 additions and 19 deletions
|
@ -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()
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in a new issue