simplify RageSounds using a qeue (this was actually in Windows a15, just

forgot to commit it)
allow disabling beat alignment
This commit is contained in:
Glenn Maynard
2004-04-06 04:10:41 +00:00
parent 9a41c54bf5
commit 29464ea185
3 changed files with 126 additions and 131 deletions
+121 -128
View File
@@ -24,7 +24,7 @@ RageSounds *SOUND = NULL;
* on the same fractional beat when we loop. (XXX: should we increase fade_len, too?
* That would cause the extra pad time to be silence.)
*/
/* Lock this before touching any of these globals. */
/* Lock this before touching g_UpdatingTimer or g_Playing. */
static RageMutex *g_Mutex;
static bool g_UpdatingTimer;
static bool g_ThreadedMusicStart = true;
@@ -56,101 +56,32 @@ struct MusicPlaying
}
};
static MusicPlaying *g_Playing;
static RageThread MusicThread;
/* These buffers can be accessed without locking. */
#include "RageUtil_CircularBuffer.h"
CircBuf<CString *> g_SoundsToPlayOnce;
CircBuf<CString *> g_SoundsToPlayOnceFromDir;
struct MusicToPlay
{
CString file, timing_file;
bool HasTiming;
bool force_loop;
float start_sec, length_sec, fade_len;
bool pending;
MusicToPlay() { pending=false; }
bool align_beat;
};
CircBuf<MusicToPlay *> g_MusicsToPlay;
static MusicToPlay g_MusicToPlay;
static MusicPlaying *g_Playing;
static RageThread MusicThread;
static vector<CString> g_SoundsToPlayOnce, g_SoundsToPlayOnceFromDir;
void StartQueuedSounds()
{
/* Don't hold the mutex if we don't have to. */
while( 1 )
{
CString sPath;
g_Mutex->Lock();
if( g_SoundsToPlayOnce.size() )
{
sPath = g_SoundsToPlayOnce.back();
g_SoundsToPlayOnce.erase( g_SoundsToPlayOnce.begin()+g_SoundsToPlayOnce.size()-1, g_SoundsToPlayOnce.end() );
}
g_Mutex->Unlock();
if( sPath != "" )
SOUNDMAN->PlayOnce( sPath );
else
break;
}
while( 1 )
{
CString sPath;
g_Mutex->Lock();
if( g_SoundsToPlayOnceFromDir.size() )
{
sPath = g_SoundsToPlayOnceFromDir.back();
g_SoundsToPlayOnceFromDir.erase( g_SoundsToPlayOnceFromDir.begin()+g_SoundsToPlayOnceFromDir.size()-1, g_SoundsToPlayOnceFromDir.end() );
}
g_Mutex->Unlock();
if( sPath != "" )
{
// make sure there's a slash at the end of this path
if( sPath.Right(1) != "/" )
sPath += "/";
CStringArray arraySoundFiles;
GetDirListing( sPath + "*.mp3", arraySoundFiles );
GetDirListing( sPath + "*.wav", arraySoundFiles );
GetDirListing( sPath + "*.ogg", arraySoundFiles );
if( arraySoundFiles.empty() )
return;
int index = rand() % arraySoundFiles.size();
SOUNDMAN->PlayOnce( sPath + arraySoundFiles[index] );
}
else
break;
}
}
void StartPlayingMusic( const RageTimer &when, const MusicToPlay &ToPlay, MusicPlaying &Playing )
{
Playing.m_HasTiming = ToPlay.HasTiming;
Playing.m_TimingDelayed = true;
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 )
p.StopMode = RageSoundParams::M_LOOP;
Playing.m_Music->SetParams( p );
Playing.m_Music->SetPositionSeconds( p.m_StartSecond );
Playing.m_Music->StartPlaying();
}
void StartMusic( MusicToPlay &ToPlay )
static void StartMusic( MusicToPlay &ToPlay )
{
LockMutex L( *g_Mutex );
if( g_Playing->m_Music->IsPlaying() && !g_Playing->m_Music->GetLoadedFilePath().CompareNoCase(ToPlay.file) )
return;
if( ToPlay.file.empty() )
{
if( g_Playing->m_Music->IsPlaying() )
@@ -172,7 +103,7 @@ void StartMusic( MusicToPlay &ToPlay )
ToPlay.HasTiming = true;
}
if( ToPlay.HasTiming && ToPlay.force_loop && ToPlay.length_sec != -1 )
if( ToPlay.align_beat && ToPlay.HasTiming && ToPlay.force_loop && ToPlay.length_sec != -1 )
{
/* Extend the loop period so it always starts and ends on the same fractional
* beat. That is, if it starts on beat 1.5, and ends on beat 10.2, extend it
@@ -215,6 +146,8 @@ void StartMusic( MusicToPlay &ToPlay )
* start now. */
if( !g_Playing->m_HasTiming && !g_UpdatingTimer )
StartImmediately = true;
if( !ToPlay.align_beat )
StartImmediately = true;
RageTimer when; /* zero */
if( !StartImmediately )
@@ -241,16 +174,75 @@ void StartMusic( MusicToPlay &ToPlay )
when = GAMESTATE->m_LastBeatUpdate + PresumedLatency + fDistance;
}
/* Important: don't hold the mutex while we load the actual sound. */
/* Important: don't hold the mutex while we load and seek the actual sound. */
L.Unlock();
{
NewMusic->m_HasTiming = ToPlay.HasTiming;
NewMusic->m_TimingDelayed = true;
NewMusic->m_Music->Load( ToPlay.file, false );
StartPlayingMusic( when, ToPlay, *NewMusic );
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 )
p.StopMode = RageSoundParams::M_LOOP;
NewMusic->m_Music->SetParams( p );
NewMusic->m_Music->SetPositionSeconds( p.m_StartSecond );
NewMusic->m_Music->StartPlaying();
}
LockMut( *g_Mutex );
delete g_Playing;
g_Playing = NewMusic;
}
static void StartQueuedSounds()
{
CString *p;
while( g_SoundsToPlayOnce.read( &p, 1 ) )
{
if( *p != "" )
SOUNDMAN->PlayOnce( *p );
delete p;
}
while( g_SoundsToPlayOnceFromDir.read( &p, 1 ) )
{
CString sPath( *p );
if( sPath != "" )
{
// make sure there's a slash at the end of this path
if( sPath.Right(1) != "/" )
sPath += "/";
CStringArray arraySoundFiles;
GetDirListing( sPath + "*.mp3", arraySoundFiles );
GetDirListing( sPath + "*.wav", arraySoundFiles );
GetDirListing( sPath + "*.ogg", arraySoundFiles );
if( arraySoundFiles.empty() )
return;
int index = rand() % arraySoundFiles.size();
SOUNDMAN->PlayOnce( sPath + arraySoundFiles[index] );
}
delete p;
}
MusicToPlay *pMusic;
while( g_MusicsToPlay.read( &pMusic, 1 ) )
{
/* Don't bother starting this music if there's another one in the queue after it. */
if( !g_MusicsToPlay.num_readable() )
StartMusic( *pMusic );
delete pMusic;
}
}
int MusicThread_start( void *p )
{
while( !g_Shutdown )
@@ -258,19 +250,6 @@ int MusicThread_start( void *p )
SDL_Delay( 10 );
StartQueuedSounds();
LockMutex L( *g_Mutex );
if( !g_MusicToPlay.pending )
continue;
/* We have a sound to start. Don't keep the lock while we do this; if another
* music tries to start in the meantime, it'll cause a skip. */
MusicToPlay ToPlay = g_MusicToPlay;
g_MusicToPlay.pending = false;
L.Unlock();
StartMusic( ToPlay );
}
return 0;
@@ -281,6 +260,10 @@ RageSounds::RageSounds()
/* Init RageSoundMan first: */
ASSERT( SOUNDMAN );
g_SoundsToPlayOnce.reserve( 16 );
g_SoundsToPlayOnceFromDir.reserve( 16 );
g_MusicsToPlay.reserve( 16 );
g_Mutex = new RageMutex("RageSounds");
g_Playing = new MusicPlaying( new RageSound );
@@ -307,6 +290,17 @@ RageSounds::~RageSounds()
delete g_Playing;
delete g_Mutex;
CString *p;
while( g_SoundsToPlayOnce.read( &p, 1 ) )
delete p;
while( g_SoundsToPlayOnceFromDir.read( &p, 1 ) )
delete p;
MusicToPlay *pMusic;
while( g_MusicsToPlay.read( &pMusic, 1 ) )
delete pMusic;
}
static float GetFrameTimingAdjustment( float fDeltaTime )
@@ -414,34 +408,31 @@ CString RageSounds::GetMusicPath() const
return g_Playing->m_Music->GetLoadedFilePath();
}
/* This function should not touch the disk at all. */
void RageSounds::PlayMusic( const CString &file, const CString &timing_file, bool force_loop, float start_sec, float length_sec, float fade_len )
/* If g_ThreadedMusicStart, this function should not touch the disk at all. */
void RageSounds::PlayMusic( const CString &file, const CString &timing_file, bool force_loop, float start_sec, float length_sec, float fade_len, bool align_beat )
{
LockMut( *g_Mutex );
// LOG->Trace("play '%s' (current '%s')", file.c_str(), g_Playing->m_Music->GetLoadedFilePath().c_str());
if( g_Playing->m_Music->IsPlaying() && !g_Playing->m_Music->GetLoadedFilePath().CompareNoCase(file) )
return; // do nothing
MusicToPlay ToPlay;
MusicToPlay *ToPlay = new MusicToPlay;
ToPlay.file = file;
ToPlay.force_loop = force_loop;
ToPlay.start_sec = start_sec;
ToPlay.length_sec = length_sec;
ToPlay.fade_len = fade_len;
ToPlay.timing_file = timing_file;
ToPlay.pending = true;
ToPlay->file = file;
ToPlay->force_loop = force_loop;
ToPlay->start_sec = start_sec;
ToPlay->length_sec = length_sec;
ToPlay->fade_len = fade_len;
ToPlay->timing_file = timing_file;
ToPlay->align_beat = align_beat;
/* If no timing file was specified, look for one in the same place as the music file. */
if( ToPlay.timing_file == "" )
ToPlay.timing_file = SetExtension( file, "sm" );
if( ToPlay->timing_file == "" )
ToPlay->timing_file = SetExtension( file, "sm" );
if( g_ThreadedMusicStart )
{
g_MusicToPlay = ToPlay;
}
else
StartMusic( ToPlay );
/* Add the MusicToPlay to the g_MusicsToPlay queue. */
if( !g_MusicsToPlay.write( &ToPlay, 1 ) )
delete ToPlay;
if( !g_ThreadedMusicStart )
StartQueuedSounds();
}
void RageSounds::HandleSongTimer( bool on )
@@ -452,9 +443,10 @@ void RageSounds::HandleSongTimer( bool on )
void RageSounds::PlayOnce( CString sPath )
{
g_Mutex->Lock();
g_SoundsToPlayOnce.push_back( sPath );
g_Mutex->Unlock();
/* Add the sound to the g_SoundsToPlayOnce queue. */
CString *p = new CString( sPath );
if( !g_SoundsToPlayOnce.write( &p, 1 ) )
delete p;
if( !g_ThreadedMusicStart )
StartQueuedSounds();
@@ -462,9 +454,10 @@ void RageSounds::PlayOnce( CString sPath )
void RageSounds::PlayOnceFromDir( CString PlayOnceFromDir )
{
g_Mutex->Lock();
g_SoundsToPlayOnceFromDir.push_back( PlayOnceFromDir );
g_Mutex->Unlock();
/* Add the path to the g_SoundsToPlayOnceFromDir queue. */
CString *p = new CString( PlayOnceFromDir );
if( !g_SoundsToPlayOnceFromDir.write( &p, 1 ) )
delete p;
if( !g_ThreadedMusicStart )
StartQueuedSounds();
+2 -2
View File
@@ -13,8 +13,8 @@ public:
~RageSounds();
void Update( float fDeltaTime );
void PlayMusic( const CString &file, bool force_loop = false, float start_sec = 0, float length_sec = -1, float fade_len = 0 ) { PlayMusic( file, "", force_loop, start_sec, length_sec, fade_len ); }
void PlayMusic( const CString &file, const CString &timing_file, bool force_loop = false, float start_sec = 0, float length_sec = -1, float fade_len = 0 );
void PlayMusic( const CString &file, bool force_loop = false, float start_sec = 0, float length_sec = -1, float fade_len = 0, bool align_beat = true ) { PlayMusic( file, "", force_loop, start_sec, length_sec, fade_len, align_beat ); }
void PlayMusic( const CString &file, const CString &timing_file, bool force_loop = false, float start_sec = 0, float length_sec = -1, float fade_len = 0, bool align_beat = true );
void StopMusic() { PlayMusic(""); }
CString GetMusicPath() const;
+3 -1
View File
@@ -58,6 +58,7 @@ const int NUM_SCORE_DIGITS = 9;
#define SCORE_SORT_CHANGE_COMMAND(i) THEME->GetMetric ("ScreenSelectMusic",ssprintf("ScoreP%iSortChangeCommand", i+1))
#define SCORE_FRAME_SORT_CHANGE_COMMAND(i) THEME->GetMetric ("ScreenSelectMusic",ssprintf("ScoreFrameP%iSortChangeCommand", i+1))
#define DO_ROULETTE_ON_MENU_TIMER THEME->GetMetricB("ScreenSelectMusic","DoRouletteOnMenuTimer")
#define ALIGN_MUSIC_BEATS THEME->GetMetricB("ScreenSelectMusic","AlignMusicBeat")
static const ScreenMessage SM_AllowOptionsMenuRepeat = ScreenMessage(SM_User+1);
CString g_sFallbackCDTitlePath;
@@ -676,7 +677,8 @@ void ScreenSelectMusic::Update( float fDeltaTime )
true,
m_fSampleStartSeconds,
m_fSampleLengthSeconds,
1.5f); /* fade out for 1.5 seconds */
1.5f, /* fade out for 1.5 seconds */
ALIGN_MUSIC_BEATS );
}
}
}