Pass RageSoundParams to Play() (or SetParams). This should help fix

the long-standing ambiguity of "what happens if parameters are changed
for a second copy of a sound when a first is still playing".
This commit is contained in:
Glenn Maynard
2004-02-28 02:09:46 +00:00
parent 71d1380951
commit be03ed1c21
8 changed files with 96 additions and 121 deletions
+22 -67
View File
@@ -60,7 +60,7 @@ RageSoundParams::RageSoundParams():
m_Balance = 0; // center m_Balance = 0; // center
speed_input_samples = speed_output_samples = 1; speed_input_samples = speed_output_samples = 1;
AccurateSync = false; AccurateSync = false;
StopMode = RageSoundParams::M_STOP; StopMode = M_AUTO;
} }
RageSound::RageSound() RageSound::RageSound()
@@ -153,13 +153,6 @@ bool RageSound::Load(CString sSoundFilePath, int precache)
m_sFilePath = sSoundFilePath; m_sFilePath = sSoundFilePath;
position = 0; position = 0;
// Check for "loop" hint
if( m_sFilePath.Find("loop") != -1 )
SetStopMode( RageSoundParams::M_LOOP );
else
SetStopMode( RageSoundParams::M_STOP );
CString error; CString error;
Sample = SoundReader_FileReader::OpenFile( m_sFilePath, error ); Sample = SoundReader_FileReader::OpenFile( m_sFilePath, error );
if( Sample == NULL ) if( Sample == NULL )
@@ -192,20 +185,6 @@ bool RageSound::Load(CString sSoundFilePath, int precache)
return true; return true;
} }
void RageSound::SetStartSeconds( float secs )
{
ASSERT(!playing);
m_Param.m_StartSecond = secs;
}
void RageSound::SetLengthSeconds(float secs)
{
RAGE_ASSERT_M( secs == -1 || secs >= 0, ssprintf("%f",secs) );
ASSERT(!playing);
m_Param.m_LengthSeconds = secs;
}
/* Read data at the rate we're playing it. We only do this to smooth out the rate /* Read data at the rate we're playing it. We only do this to smooth out the rate
* we read data; the sound thread will always read more if it's needed. * we read data; the sound thread will always read more if it's needed.
* *
@@ -522,8 +501,8 @@ void RageSound::StartPlaying()
LockMut(SOUNDMAN->lock); LockMut(SOUNDMAN->lock);
// If no volume is set, use the default. // If no volume is set, use the default.
if( GetVolume() == -1 ) if( m_Param.m_Volume == -1 )
SetVolume( SOUNDMAN->GetMixVolume() ); m_Param.m_Volume = SOUNDMAN->GetMixVolume();
stopped_position = -1; stopped_position = -1;
@@ -560,9 +539,9 @@ void RageSound::StopPlaying()
pos_map.clear(); pos_map.clear();
} }
RageSound *RageSound::Play() RageSound *RageSound::Play( const RageSoundParams *params )
{ {
return SOUNDMAN->PlaySound(*this); return SOUNDMAN->PlaySound( *this, params );
} }
void RageSound::Stop() void RageSound::Stop()
@@ -788,48 +767,18 @@ bool RageSound::SetPositionFrames( int frames )
return true; return true;
} }
void RageSound::SetStopMode( RageSoundParams::StopMode_t m ) void RageSoundParams::SetPlaybackRate( float NewSpeed )
{ {
m_Param.StopMode = m;
}
RageSoundParams::StopMode_t RageSound::GetStopMode() const
{
return m_Param.StopMode;
}
void RageSound::SetAccurateSync( bool yes )
{
m_Param.AccurateSync = yes;
}
void RageSound::SetPlaybackRate( float NewSpeed )
{
LockMut(SOUNDMAN->lock);
if(GetPlaybackRate() == NewSpeed)
return;
if( NewSpeed == 1.00f ) if( NewSpeed == 1.00f )
{ {
m_Param.speed_input_samples = 1; m_Param.speed_output_samples = 1; speed_input_samples = 1; speed_output_samples = 1;
} else { } else {
/* Approximate it to the nearest tenth. */ /* Approximate it to the nearest tenth. */
m_Param.speed_input_samples = int( roundf(NewSpeed * 10) ); speed_input_samples = int( roundf(NewSpeed * 10) );
m_Param.speed_output_samples = 10; speed_output_samples = 10;
} }
} }
void RageSound::SetFadeLength( float fSeconds )
{
m_Param.m_FadeLength = fSeconds;
}
void RageSound::SetVolume( float fVolume )
{
m_Param.m_Volume = fVolume;
}
float RageSound::GetVolume() const float RageSound::GetVolume() const
{ {
return m_Param.m_Volume; return m_Param.m_Volume;
@@ -840,19 +789,25 @@ float RageSound::GetPlaybackRate() const
return float(m_Param.speed_input_samples) / m_Param.speed_output_samples; return float(m_Param.speed_input_samples) / m_Param.speed_output_samples;
} }
void RageSound::SetStartTime( const RageTimer &tm )
{
m_Param.StartTime = tm;
}
RageTimer RageSound::GetStartTime() const RageTimer RageSound::GetStartTime() const
{ {
return m_Param.StartTime; return m_Param.StartTime;
} }
void RageSound::SetBalance( float f ) void RageSound::SetParams( const RageSoundParams &p )
{ {
m_Param.m_Balance = f; m_Param = p;
}
RageSoundParams::StopMode_t RageSound::GetStopMode() const
{
if( m_Param.StopMode != RageSoundParams::M_AUTO )
return m_Param.StopMode;
if( m_sFilePath.Find("loop") != -1 )
return RageSoundParams::M_LOOP;
else
return RageSoundParams::M_STOP;
} }
/* /*
+12 -16
View File
@@ -32,6 +32,7 @@ struct RageSoundParams
/* Amount of time to fade out at the end. */ /* Amount of time to fade out at the end. */
float m_FadeLength; float m_FadeLength;
void SetNoFade() { m_FadeLength = 0; }
float m_Volume; float m_Volume;
@@ -41,6 +42,7 @@ struct RageSoundParams
/* Number of samples input and output when changing speed. Currently, /* Number of samples input and output when changing speed. Currently,
* this is either 1/1, 5/4 or 4/5. */ * this is either 1/1, 5/4 or 4/5. */
int speed_input_samples, speed_output_samples; int speed_input_samples, speed_output_samples;
void SetPlaybackRate( float fScale );
bool AccurateSync; bool AccurateSync;
@@ -52,7 +54,10 @@ struct RageSoundParams
* M_LOOP restarts. * M_LOOP restarts.
* M_CONTINUE feeds silence, which is useful to continue timing longer than the actual sound. */ * M_CONTINUE feeds silence, which is useful to continue timing longer than the actual sound. */
enum StopMode_t { enum StopMode_t {
M_STOP, M_LOOP, M_CONTINUE M_STOP, /* stop when finished */
M_LOOP, /* loop */
M_CONTINUE, /* keep playing silence */
M_AUTO /* obey filename hints */
} StopMode; } StopMode;
}; };
@@ -82,37 +87,27 @@ public:
bool Load(CString fn, int precache = 2); bool Load(CString fn, int precache = 2);
void Unload(); void Unload();
void SetStopMode( RageSoundParams::StopMode_t m );
RageSoundParams::StopMode_t GetStopMode() const;
void SetStartSeconds(float secs = 0); /* default = beginning */
void SetLengthSeconds(float secs = -1); /* default = no length limit */
void StartPlaying(); void StartPlaying();
void StopPlaying(); void StopPlaying();
CString GetError() const { return error; } CString GetError() const { return error; }
bool Error() const { return !error.empty(); } bool Error() const { return !error.empty(); }
RageSound *Play(); RageSound *Play( const RageSoundParams *params=NULL );
void Stop(); void Stop();
float GetLengthSeconds(); float GetLengthSeconds();
float GetPositionSeconds( bool *approximate=NULL, RageTimer *Timestamp=NULL ) const; float GetPositionSeconds( bool *approximate=NULL, RageTimer *Timestamp=NULL ) const;
int GetSampleRate() const; int GetSampleRate() const;
bool SetPositionSeconds( float fSeconds = -1); bool SetPositionSeconds( float fSeconds );
CString GetLoadedFilePath() const { return m_sFilePath; } CString GetLoadedFilePath() const { return m_sFilePath; }
bool IsPlaying() const { return playing; } bool IsPlaying() const { return playing; }
void SetAccurateSync( bool yes=true );
void SetPlaybackRate( float fScale );
void SetFadeLength( float fSeconds );
void SetVolume( float fVolume );
float GetVolume() const;
void SetNoFade() { SetFadeLength(0); }
float GetPlaybackRate() const; float GetPlaybackRate() const;
void SetStartTime( const RageTimer &tm );
RageTimer GetStartTime() const; RageTimer GetStartTime() const;
void SetBalance( float f ); float GetVolume() const;
void SetParams( const RageSoundParams &p );
const RageSoundParams &GetParams() const { return m_Param; }
private: private:
/* If we were copied from another RageSound, this will point to it; otherwise /* If we were copied from another RageSound, this will point to it; otherwise
@@ -164,6 +159,7 @@ private:
int GetData(char *buffer, int size); int GetData(char *buffer, int size);
void Fail(CString reason); void Fail(CString reason);
int Bytes_Available() const; int Bytes_Available() const;
RageSoundParams::StopMode_t GetStopMode() const; /* resolves M_AUTO */
static void RateChange(char *buf, int &cnt, int speed_input_samples, int speed_output_samples, int channels); static void RateChange(char *buf, int &cnt, int speed_input_samples, int speed_output_samples, int channels);
+6 -2
View File
@@ -98,7 +98,7 @@ int RageSoundManager::GetDriverSampleRate( int rate ) const
return driver->GetSampleRate( rate ); return driver->GetSampleRate( rate );
} }
RageSound *RageSoundManager::PlaySound(RageSound &snd) RageSound *RageSoundManager::PlaySound( RageSound &snd, const RageSoundParams *params )
{ {
LockMut(lock); LockMut(lock);
@@ -113,8 +113,12 @@ RageSound *RageSoundManager::PlaySound(RageSound &snd)
owned_sounds.insert(sound_to_play); owned_sounds.insert(sound_to_play);
} }
if( params )
sound_to_play->SetParams( *params );
// Move to the start position. // Move to the start position.
sound_to_play->SetPositionSeconds(); sound_to_play->SetPositionSeconds( sound_to_play->GetParams().m_StartSecond );
sound_to_play->StartPlaying(); sound_to_play->StartPlaying();
return sound_to_play; return sound_to_play;
+2 -1
View File
@@ -9,6 +9,7 @@
class RageSound; class RageSound;
class RageSoundBase; class RageSoundBase;
class RageSoundDriver; class RageSoundDriver;
struct RageSoundParams;
class RageSoundManager class RageSoundManager
{ {
@@ -43,7 +44,7 @@ public:
void PlayOnce( CString sPath ); void PlayOnce( CString sPath );
RageSound *PlaySound(RageSound &snd); RageSound *PlaySound( RageSound &snd, const RageSoundParams *params );
void StopPlayingSound(RageSound &snd); void StopPlayingSound(RageSound &snd);
/* A list of all sounds that currently exist. RageSound adds and removes /* A list of all sounds that currently exist. RageSound adds and removes
+7 -11
View File
@@ -133,19 +133,15 @@ void StartPlayingMusic( const RageTimer &when, const MusicToPlay &ToPlay, MusicP
Playing.m_Music->Load( ToPlay.file, false ); Playing.m_Music->Load( ToPlay.file, false );
RageSoundParams p;
p.m_StartSecond = ToPlay.start_sec;
p.m_LengthSeconds = ToPlay.length_sec;
p.m_FadeLength = ToPlay.fade_len;
p.StartTime = when;
if( ToPlay.force_loop ) if( ToPlay.force_loop )
Playing.m_Music->SetStopMode( RageSound::M_LOOP ); p.StopMode = RageSoundParams::M_LOOP;
Playing.m_Music->SetStartSeconds( ToPlay.start_sec ); Playing.m_Music->SetPositionSeconds( p.m_StartSecond );
if( ToPlay.length_sec == -1 )
Playing.m_Music->SetLengthSeconds();
else
Playing.m_Music->SetLengthSeconds( ToPlay.length_sec );
Playing.m_Music->SetFadeLength( ToPlay.fade_len );
Playing.m_Music->SetPositionSeconds();
Playing.m_Music->SetStartTime( when );
Playing.m_Music->StartPlaying(); Playing.m_Music->StartPlaying();
} }
+15 -10
View File
@@ -373,8 +373,6 @@ ScreenEdit::ScreenEdit( CString sName ) : Screen( sName )
m_soundMusic.Load(m_pSong->GetMusicPath()); m_soundMusic.Load(m_pSong->GetMusicPath());
m_soundMusic.SetAccurateSync(true);
m_soundMusic.SetStopMode( RageSoundParams::M_CONTINUE );
m_soundAssistTick.Load( THEME->GetPathToS("ScreenEdit assist tick") ); m_soundAssistTick.Load( THEME->GetPathToS("ScreenEdit assist tick") );
} }
@@ -417,8 +415,9 @@ void ScreenEdit::PlayTicks()
fSecondsUntil /= m_soundMusic.GetPlaybackRate(); /* 2x music rate means the time until the tick is halved */ fSecondsUntil /= m_soundMusic.GetPlaybackRate(); /* 2x music rate means the time until the tick is halved */
RageTimer when = GAMESTATE->m_LastBeatUpdate + (fSecondsUntil - (float)TICK_EARLY_SECONDS); RageTimer when = GAMESTATE->m_LastBeatUpdate + (fSecondsUntil - (float)TICK_EARLY_SECONDS);
m_soundAssistTick.SetStartTime( when ); RageSoundParams p;
m_soundAssistTick.Play(); p.StartTime = when;
m_soundAssistTick.Play( &p );
} }
} }
@@ -1941,9 +1940,12 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers )
m_Foreground.LoadFromSong( m_pSong ); m_Foreground.LoadFromSong( m_pSong );
} }
m_soundMusic.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate ); RageSoundParams p;
m_soundMusic.SetPositionSeconds( fStartSeconds ); p.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate );
m_soundMusic.StartPlaying(); p.m_StartSecond = fStartSeconds;
p.AccurateSync = true;
p.StopMode = RageSoundParams::M_CONTINUE;
m_soundMusic.Play( &p );
} }
break; break;
case record: case record:
@@ -1970,9 +1972,12 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers )
float fStartSeconds = m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat); float fStartSeconds = m_pSong->GetElapsedTimeFromBeat(GAMESTATE->m_fSongBeat);
LOG->Trace( "Starting playback at %f", fStartSeconds ); LOG->Trace( "Starting playback at %f", fStartSeconds );
m_soundMusic.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate ); RageSoundParams p;
m_soundMusic.SetPositionSeconds( fStartSeconds ); p.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate );
m_soundMusic.StartPlaying(); p.m_StartSecond = fStartSeconds;
p.AccurateSync = true;
p.StopMode = RageSoundParams::M_CONTINUE;
m_soundMusic.Play( &p );
} }
break; break;
case insert_and_shift: case insert_and_shift:
+10 -8
View File
@@ -961,7 +961,6 @@ void ScreenGameplay::LoadNextSong()
m_soundMusic = new RageSound; m_soundMusic = new RageSound;
m_soundMusic->SetAccurateSync();
m_soundMusic->Load( GAMESTATE->m_pCurSong->GetMusicPath() ); m_soundMusic->Load( GAMESTATE->m_pCurSong->GetMusicPath() );
/* Set up song-specific graphics. */ /* Set up song-specific graphics. */
@@ -1017,12 +1016,14 @@ float ScreenGameplay::StartPlayingSong(float MinTimeToNotes, float MinTimeToMusi
fStartSecond = min(fStartSecond, -MinTimeToMusic); fStartSecond = min(fStartSecond, -MinTimeToMusic);
ASSERT( m_soundMusic ); ASSERT( m_soundMusic );
m_soundMusic->SetPositionSeconds( fStartSecond );
m_soundMusic->SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate );
/* Keep the music playing after it's finished; we'll stop it. */ RageSoundParams p;
m_soundMusic->SetStopMode( RageSoundParams::M_CONTINUE ); p.AccurateSync = true;
m_soundMusic->StartPlaying(); p.SetPlaybackRate( GAMESTATE->m_SongOptions.m_fMusicRate );
p.StopMode = RageSoundParams::M_CONTINUE;
p.m_StartSecond = fStartSecond;
m_soundMusic->Play( &p );
SOUND->TakeOverSound( m_soundMusic, &GAMESTATE->m_pCurSong->m_Timing ); SOUND->TakeOverSound( m_soundMusic, &GAMESTATE->m_pCurSong->m_Timing );
m_soundMusic = NULL; // SOUND owns it now m_soundMusic = NULL; // SOUND owns it now
@@ -1068,8 +1069,9 @@ void ScreenGameplay::PlayTicks()
fSecondsUntil /= GAMESTATE->m_SongOptions.m_fMusicRate; /* 2x music rate means the time until the tick is halved */ fSecondsUntil /= GAMESTATE->m_SongOptions.m_fMusicRate; /* 2x music rate means the time until the tick is halved */
RageTimer when = GAMESTATE->m_LastBeatUpdate + (fSecondsUntil - (float)TICK_EARLY_SECONDS); RageTimer when = GAMESTATE->m_LastBeatUpdate + (fSecondsUntil - (float)TICK_EARLY_SECONDS);
m_soundAssistTick.SetStartTime( when ); RageSoundParams p;
m_soundAssistTick.Play(); p.StartTime = when;
m_soundAssistTick.Play( &p );
} }
} }
+22 -6
View File
@@ -57,7 +57,10 @@ ScreenTestSound::ScreenTestSound( CString sClassName ) : Screen( sClassName )
//s[0].s.SetStartSeconds(45); //s[0].s.SetStartSeconds(45);
//s[0].s.SetPositionSeconds(); //s[0].s.SetPositionSeconds();
// s[4].s.SetLengthSeconds(1); // s[4].s.SetLengthSeconds(1);
s[0].s.SetPlaybackRate(1.20f); RageSoundParams p;
p.SetPlaybackRate( 1.20f );
s[0].s.SetParams( p );
//s[0].s.SetStopMode(RageSound::M_LOOP); //s[0].s.SetStopMode(RageSound::M_LOOP);
//s[0].s.Play(); //s[0].s.Play();
@@ -92,9 +95,9 @@ void ScreenTestSound::UpdateText(int n)
"%s", "%s",
n+1, fn.c_str(), n+1, fn.c_str(),
s[n].s.IsPlaying()? "Playing":"Stopped", s[n].s.IsPlaying()? "Playing":"Stopped",
s[n].s.GetStopMode() == RageSoundParams::M_STOP? s[n].s.GetParams().StopMode == RageSoundParams::M_STOP?
"Stop when finished": "Stop when finished":
s[n].s.GetStopMode() == RageSoundParams::M_CONTINUE? s[n].s.GetParams().StopMode == RageSoundParams::M_CONTINUE?
"Continue until stopped": "Continue until stopped":
"Loop", "Loop",
pos.size()? pos.c_str(): "none playing", pos.size()? pos.c_str(): "none playing",
@@ -130,13 +133,26 @@ void ScreenTestSound::Input( const DeviceInput& DeviceI, const InputEventType ty
s[selected].s.Stop(); s[selected].s.Stop();
break; break;
case 'l': case 'l':
s[selected].s.SetStopMode(RageSoundParams::M_LOOP); {
RageSoundParams p = s[selected].s.GetParams();
p.StopMode = RageSoundParams::M_LOOP;
s[selected].s.SetParams( p );
}
break; break;
case 'a': case 'a':
s[selected].s.SetStopMode(RageSoundParams::M_STOP); {
RageSoundParams p = s[selected].s.GetParams();
p.StopMode = RageSoundParams::M_STOP;
s[selected].s.SetParams( p );
}
break; break;
case 'c': case 'c':
s[selected].s.SetStopMode(RageSoundParams::M_CONTINUE); {
RageSoundParams p = s[selected].s.GetParams();
p.StopMode = RageSoundParams::M_CONTINUE;
s[selected].s.SetParams( p );
}
break; break;
/* case SDLK_LEFT: /* case SDLK_LEFT: