Skip to content

Commit

Permalink
Merge pull request #20 from modulesio/suspend-resume
Browse files Browse the repository at this point in the history
Add AudioContext suspend/resume
  • Loading branch information
avaer committed Oct 26, 2018
2 parents be9e57a + 5905703 commit 221e1e2
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 16 deletions.
3 changes: 3 additions & 0 deletions labsound/include/LabSound/core/AudioContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ class AudioContext
void connectParam(std::shared_ptr<AudioParam> param, std::shared_ptr<AudioNode> driver, uint32_t index);

void holdSourceNodeUntilFinished(std::shared_ptr<AudioScheduledSourceNode> node);

void suspend();
void resume();

// Necessary to call when using an OfflineAudioDestinationNode
void startRendering();
Expand Down
2 changes: 2 additions & 0 deletions labsound/include/LabSound/core/AudioDestinationNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class AudioDestinationNode : public AudioNode, public AudioIOCallback

size_t currentSampleFrame() const { return m_currentSampleFrame; }
double currentTime() const;
virtual void suspend() {}
virtual void resume() {}

virtual unsigned numberOfChannels() const { return 2; } // FIXME: update when multi-channel (more than stereo) is supported

Expand Down
8 changes: 8 additions & 0 deletions labsound/src/core/AudioContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ void AudioContext::holdSourceNodeUntilFinished(std::shared_ptr<AudioScheduledSou
automaticSources.push_back(node);
}

void AudioContext::suspend() {
m_destinationNode->suspend();
}

void AudioContext::resume() {
m_destinationNode->resume();
}

void AudioContext::handleAutomaticSources()
{
std::lock_guard<std::mutex> lock(m_updateMutex);
Expand Down
9 changes: 5 additions & 4 deletions labsound/src/internal/src/linux/AudioDestinationLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ AudioDestinationLinux::AudioDestinationLinux(AudioIOCallback & callback, float s
{
m_sampleRate = sampleRate;
m_renderBus.setSampleRate(m_sampleRate);
m_inputBus.setSampleRate(m_sampleRate);
dac.reset(new RtAudio()); // XXX
configure();
}

AudioDestinationLinux::~AudioDestinationLinux()
{
dac.release(); // XXX
/* if (dac.isStreamOpen())
dac.closeStream(); */
// dac.release(); // XXX
if (dac->isStreamOpen())
dac->closeStream();
}

void AudioDestinationLinux::configure()
Expand Down Expand Up @@ -94,7 +95,7 @@ void AudioDestinationLinux::stop()
{
try
{
// dac->stopStream(); // XXX
dac->stopStream();
m_isPlaying = false;
}
catch (RtAudioError & e)
Expand Down
4 changes: 4 additions & 0 deletions labsound/src/internal/src/ml/AudioDestinationMl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ void AudioDestinationMl::stop()
} else {
std::cerr << "failed to stop ml output sound: " << result << std::endl;
}

if (isRecording()) {
stopRecording();
}
}

void AudioDestinationMl::startRecording()
Expand Down
9 changes: 5 additions & 4 deletions labsound/src/internal/src/win/AudioDestinationWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ AudioDestinationWin::AudioDestinationWin(AudioIOCallback & callback, float sampl
{
m_sampleRate = sampleRate;
m_renderBus.setSampleRate(m_sampleRate);
m_inputBus.setSampleRate(m_sampleRate);
dac.reset(new RtAudio()); // XXX
configure();
}

AudioDestinationWin::~AudioDestinationWin()
{
dac.release(); // XXX
/* if (dac.isStreamOpen())
dac.closeStream(); */
// dac.release(); // XXX
if (dac->isStreamOpen())
dac->closeStream();
}

void AudioDestinationWin::configure()
Expand Down Expand Up @@ -94,7 +95,7 @@ void AudioDestinationWin::stop()
{
try
{
// dac->stopStream(); // XXX
dac->stopStream();
m_isPlaying = false;
}
catch (RtAudioError & e)
Expand Down
46 changes: 38 additions & 8 deletions labsound/third_party/rtaudio/src/RtAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4331,39 +4331,50 @@ void RtApiWasapi::stopStream( void )
// inform stream thread by setting stream state to STREAM_STOPPING
stream_.state = STREAM_STOPPING;

HANDLE captureEvent = ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent;
SetEvent(captureEvent);

HANDLE renderEvent = ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent;
SetEvent(renderEvent);

// wait until stream thread is stopped
while( stream_.state != STREAM_STOPPED ) {
Sleep( 1 );

DWORD result = WaitForSingleObject( (HANDLE)stream_.callbackInfo.thread, 0);
if (result != WAIT_TIMEOUT) {
break;
}
}

// Wait for the last buffer to play before stopping.
Sleep( 1000 * stream_.bufferSize / stream_.sampleRate );

// stop capture client if applicable
if ( ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient ) {
HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop();
if ( FAILED( hr ) ) {
/* HRESULT hr = */( ( WasapiHandle* ) stream_.apiHandle )->captureAudioClient->Stop();
/* if ( FAILED( hr ) ) {
errorText_ = "RtApiWasapi::stopStream: Unable to stop capture stream.";
error( RtAudioError::DRIVER_ERROR );
return;
}
} */
}

// stop render client if applicable
if ( ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient ) {
HRESULT hr = ( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop();
if ( FAILED( hr ) ) {
/* HRESULT hr = */( ( WasapiHandle* ) stream_.apiHandle )->renderAudioClient->Stop();
/* if ( FAILED( hr ) ) {
errorText_ = "RtApiWasapi::stopStream: Unable to stop render stream.";
error( RtAudioError::DRIVER_ERROR );
return;
}
} */
}

// close thread handle
if ( stream_.callbackInfo.thread && !CloseHandle( ( void* ) stream_.callbackInfo.thread ) ) {
errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread.";
/* errorText_ = "RtApiWasapi::stopStream: Unable to close callback thread.";
error( RtAudioError::THREAD_ERROR );
return;
return; */
}

stream_.callbackInfo.thread = (ThreadHandle) NULL;
Expand All @@ -4383,10 +4394,21 @@ void RtApiWasapi::abortStream( void )

// inform stream thread by setting stream state to STREAM_STOPPING
stream_.state = STREAM_STOPPING;

HANDLE captureEvent = ( ( WasapiHandle* ) stream_.apiHandle )->captureEvent;
SetEvent(captureEvent);

HANDLE renderEvent = ( ( WasapiHandle* ) stream_.apiHandle )->renderEvent;
SetEvent(renderEvent);

// wait until stream thread is stopped
while ( stream_.state != STREAM_STOPPED ) {
Sleep( 1 );

DWORD result = WaitForSingleObject( (HANDLE)stream_.callbackInfo.thread, 0);
if (result != WAIT_TIMEOUT) {
break;
}
}

// stop capture client if applicable
Expand Down Expand Up @@ -5017,6 +5039,10 @@ void RtApiWasapi::wasapiThread()
// if the callback input buffer was not pulled from captureBuffer, wait for next capture event
if ( !callbackPulled ) {
WaitForSingleObject( captureEvent, INFINITE );

if (stream_.state == STREAM_STOPPING) {
break;
}
}

// Get capture buffer from stream
Expand Down Expand Up @@ -5073,6 +5099,10 @@ void RtApiWasapi::wasapiThread()
// if the callback output buffer was not pushed to renderBuffer, wait for next render event
if ( callbackPulled && !callbackPushed ) {
WaitForSingleObject( renderEvent, INFINITE );

if (stream_.state == STREAM_STOPPING) {
break;
}
}

// Get render buffer from stream
Expand Down

0 comments on commit 221e1e2

Please sign in to comment.