Skip to content

Commit

Permalink
Fixed|dsFluidSynth|dsFMOD: Pausing and resuming the song
Browse files Browse the repository at this point in the history
When a map is loaded, the song may be paused and resumed later.
This way causing a few hundred milliseconds to be lost from the
beginning of playback, as dsFMOD would not stop the streaming
sample when it was paused. Instead, the sound was muted and kept
playing.
  • Loading branch information
skyjake committed Jul 27, 2012
1 parent 97cdb24 commit f95bf5a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
54 changes: 35 additions & 19 deletions doomsday/plugins/fluidsynth/src/fluidsynth_music.cpp
Expand Up @@ -189,19 +189,21 @@ static int synthWorkThread(void* parm)
{
if(blockBuffer->availableForWriting() < BLOCK_SIZE)
{
// There's no room for the next block, let's sleep for a while.
// We should not or cannot produce samples right now, let's sleep for a while.
Thread_Sleep(50);
continue;
}

//DSFLUIDSYNTH_TRACE("Synthesizing next block...");
//DSFLUIDSYNTH_TRACE("Synthesizing next block using fsPlayer " << fsPlayer);

// Synthesize a block of samples into our buffer.
fluid_synth_write_s16(DMFluid_Synth(), BLOCK_SAMPLES, samples, 0, 2, samples, 1, 2);
blockBuffer->write(samples, BLOCK_SIZE);

//DSFLUIDSYNTH_TRACE("Block written.");
}

DSFLUIDSYNTH_TRACE("Synth worker dies.");
return 0;
}

Expand Down Expand Up @@ -229,10 +231,19 @@ static int streamOutSamples(sfxbuffer_t* buf, void* data, unsigned int size)
}
else
{
//DSFLUIDSYNTH_TRACE("Streaming out failed.");
return 0; // Not enough data to fill the requested buffer.
}
}

static void startWorker()
{
DENG_ASSERT(worker == NULL);

workerShouldStop = false;
worker = Sys_StartThread(synthWorkThread, 0);
}

/**
* Starts the synthesizer thread and music playback.
*/
Expand All @@ -257,17 +268,32 @@ static void startPlayer()

DMFluid_Sfx()->Load(sfxBuf, &streamSample);

workerShouldStop = false;
worker = Sys_StartThread(synthWorkThread, 0);
startWorker();

// Update the buffer's volume.
DMFluid_Sfx()->Set(sfxBuf, SFXBP_VOLUME, musicVolume);

DMFluid_Sfx()->Play(sfxBuf);
}

static void stopWorker()
{
if(worker)
{
DSFLUIDSYNTH_TRACE("stopWorker: Stopping thread " << worker);

workerShouldStop = true;
Sys_WaitThread(worker, 1000, NULL);
worker = 0;

DSFLUIDSYNTH_TRACE("stopWorker: Thread stopped.");
}
}

static void stopPlayer()
{
DSFLUIDSYNTH_TRACE("stopPlayer: fsPlayer " << fsPlayer);

if(!fsPlayer) return;

// Destroy the sfx buffer.
Expand All @@ -277,16 +303,7 @@ static void stopPlayer()
DMFluid_Sfx()->Destroy(sfxBuf);
sfxBuf = 0;

if(worker)
{
DSFLUIDSYNTH_TRACE("stopPlayer: Stopping thread " << worker);

workerShouldStop = true;
Sys_WaitThread(worker, 1000, NULL);
worker = 0;

DSFLUIDSYNTH_TRACE("stopPlayer: Thread stopped.");
}
stopWorker();

DSFLUIDSYNTH_TRACE("stopPlayer: " << fsPlayer);

Expand Down Expand Up @@ -411,10 +428,7 @@ void DM_Music_Update(void)

void DM_Music_Stop(void)
{
if(!fsPlayer) return;

DMFluid_Sfx()->Stop(sfxBuf);
fluid_player_stop(fsPlayer);
stopPlayer();
}

#if 0
Expand Down Expand Up @@ -457,15 +471,17 @@ int DM_Music_Play(int looped)

void DM_Music_Pause(int setPause)
{
if(!fsPlayer) return;
if(!fsPlayer || !sfxBuf) return;

if(setPause)
{
DMFluid_Sfx()->Stop(sfxBuf);
DSFLUIDSYNTH_TRACE("Song paused.");
}
else
{
DMFluid_Sfx()->Play(sfxBuf);
DSFLUIDSYNTH_TRACE("Song resumed.");
}
}

Expand Down
9 changes: 8 additions & 1 deletion doomsday/plugins/fmod/src/fmod_sfx.cpp
Expand Up @@ -413,13 +413,20 @@ void DS_SFX_Stop(sfxbuffer_t* buf)
DSFMOD_TRACE("SFX_Stop: sfxbuffer " << buf);

BufferInfo& info = bufferInfo(buf);

Streams::iterator found = streams.find(info.sound);
if(found != streams.end() && info.channel)
{
info.channel->setPaused(true);
}

if(info.channel)
{
info.channel->setUserData(0);
info.channel->setCallback(0);
info.channel->setMute(true);
info.channel = 0;
}
}

// Clear the flag that tells the Sfx module about playing buffers.
buf->flags &= ~SFXBF_PLAYING;
Expand Down

0 comments on commit f95bf5a

Please sign in to comment.