diff --git a/stepmania/src/AutoKeysounds.cpp b/stepmania/src/AutoKeysounds.cpp index 1db08dcb33..229b20e947 100644 --- a/stepmania/src/AutoKeysounds.cpp +++ b/stepmania/src/AutoKeysounds.cpp @@ -121,32 +121,72 @@ void AutoKeysounds::LoadTracks( const Song *pSong, RageSoundReader *&pShared, Ra pPlayer2 = NULL; pShared = NULL; - RString sError; - RageSoundReader *pSongReader = RageSoundReader_FileReader::OpenFile( pSong->GetMusicPath(), sError ); + vector vsMusicFile; - /* Load the buffering filter before the effects filters, so effects aren't delayed. */ - pSongReader = new RageSoundReader_Extend( pSongReader ); - pSongReader = new RageSoundReader_ThreadedBuffer( pSongReader ); - pShared = pSongReader; - - - if( pSong->HasLeadTrack() ) + vsMusicFile.push_back( pSong->GetMusicPath() ); + FOREACH_ENUM( InstrumentTrack, it ) { - RageSoundReader *pLeadTrackReader = RageSoundReader_FileReader::OpenFile( pSong->GetLeadTrackPath(), sError ); + if( it == InstrumentTrack_Guitar ) + continue; + if( pSong->HasInstrumentTrack(it) ) + vsMusicFile.push_back( pSong->GetInstrumentTrackPath(it) ); + } + + + vector vpSounds; + FOREACH( RString, vsMusicFile, s ) + { + RString sError; + RageSoundReader *pSongReader = RageSoundReader_FileReader::OpenFile( *s, sError ); + vpSounds.push_back( pSongReader ); + } + + if( vpSounds.size() == 1 ) + { + RageSoundReader *pSongReader = vpSounds[0]; + /* Load the buffering filter before the effects filters, so effects aren't delayed. */ - pLeadTrackReader = new RageSoundReader_Extend( pLeadTrackReader ); - pLeadTrackReader = new RageSoundReader_ThreadedBuffer( pLeadTrackReader ); - pPlayer1 = pLeadTrackReader; + pSongReader = new RageSoundReader_Extend( pSongReader ); + pSongReader = new RageSoundReader_ThreadedBuffer( pSongReader ); + pShared = pSongReader; + } + else + { + RageSoundReader_Merge *pMerge = new RageSoundReader_Merge; + + FOREACH( RageSoundReader *, vpSounds, so ) + pMerge->AddSound( *so ); + pMerge->Finish( SOUNDMAN->GetDriverSampleRate() ); + + RageSoundReader *pSongReader = pMerge; + + /* Load the buffering filter before the effects filters, so effects aren't delayed. */ + pSongReader = new RageSoundReader_Extend( pSongReader ); + pSongReader = new RageSoundReader_ThreadedBuffer( pSongReader ); + pShared = pSongReader; + } + + + + + if( pSong->HasInstrumentTrack(InstrumentTrack_Guitar) ) + { + RString sError; + RageSoundReader *pGuitarTrackReader = RageSoundReader_FileReader::OpenFile( pSong->GetInstrumentTrackPath(InstrumentTrack_Guitar), sError ); + /* Load the buffering filter before the effects filters, so effects aren't delayed. */ + pGuitarTrackReader = new RageSoundReader_Extend( pGuitarTrackReader ); + pGuitarTrackReader = new RageSoundReader_ThreadedBuffer( pGuitarTrackReader ); + pPlayer1 = pGuitarTrackReader; } return; - if( pSongReader->GetNumChannels() <= 2 ) - { - /* If we only have one track, return it as the shared track. */ - pShared = pSongReader; - return; - } + //if( pSongReader->GetNumChannels() <= 2 ) + //{ + // /* If we only have one track, return it as the shared track. */ + // pShared = pSongReader; + // return; + //} // TODO: Make this work for player 2, and for 2 players diff --git a/stepmania/src/NotesLoaderMidi.cpp b/stepmania/src/NotesLoaderMidi.cpp index 54ce1bc7ee..ec23fd40df 100644 --- a/stepmania/src/NotesLoaderMidi.cpp +++ b/stepmania/src/NotesLoaderMidi.cpp @@ -920,7 +920,25 @@ bool MidiLoader::LoadFromDir( const RString &sDir, Song &out ) GetDirListing( sDir + RString("*guitar.mp3"), vsFiles ); GetDirListing( sDir + RString("*guitar.wav"), vsFiles ); if( vsFiles.size() > 0 ) - out.m_sLeadTrackFile = vsFiles[0]; + out.m_sInstrumentTrackFile[InstrumentTrack_Guitar] = vsFiles[0]; + } + + { + vector vsFiles; + GetDirListing( sDir + RString("*rhythm.ogg"), vsFiles ); + GetDirListing( sDir + RString("*rhythm.mp3"), vsFiles ); + GetDirListing( sDir + RString("*rhythm.wav"), vsFiles ); + if( vsFiles.size() > 0 ) + out.m_sInstrumentTrackFile[InstrumentTrack_Rhythm] = vsFiles[0]; + } + + { + vector vsFiles; + GetDirListing( sDir + RString("*bass.ogg"), vsFiles ); + GetDirListing( sDir + RString("*bass.mp3"), vsFiles ); + GetDirListing( sDir + RString("*bass.wav"), vsFiles ); + if( vsFiles.size() > 0 ) + out.m_sInstrumentTrackFile[InstrumentTrack_Bass] = vsFiles[0]; } vector vsFiles; diff --git a/stepmania/src/NotesLoaderSM.cpp b/stepmania/src/NotesLoaderSM.cpp index fb317feaf2..95f20329a6 100644 --- a/stepmania/src/NotesLoaderSM.cpp +++ b/stepmania/src/NotesLoaderSM.cpp @@ -332,8 +332,22 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache else if( sValueName=="MUSIC" ) out.m_sMusicFile = sParams[1]; - else if( sValueName=="LEADTRACK" ) - out.m_sLeadTrackFile = sParams[1]; + else if( sValueName=="INSTRUMENTTRACK" ) + { + vector vs1; + split( sParams[1], ",", vs1 ); + FOREACH_CONST( RString, vs1, s ) + { + vector vs2; + split( *s, "=", vs2 ); + if( vs2.size() >= 2 ) + { + InstrumentTrack it = StringToInstrumentTrack( vs2[0] ); + if( it != InstrumentTrack_Invalid ) + out.m_sInstrumentTrackFile[it] = vs2[1]; + } + } + } else if( sValueName=="MUSICLENGTH" ) { diff --git a/stepmania/src/NotesWriterSM.cpp b/stepmania/src/NotesWriterSM.cpp index cd885e2e3e..dc99059cc2 100644 --- a/stepmania/src/NotesWriterSM.cpp +++ b/stepmania/src/NotesWriterSM.cpp @@ -52,7 +52,18 @@ static void WriteGlobalTags( RageFile &f, const Song &out ) f.PutLine( ssprintf( "#LYRICSPATH:%s;", SmEscape(out.m_sLyricsFile).c_str() ) ); f.PutLine( ssprintf( "#CDTITLE:%s;", SmEscape(out.m_sCDTitleFile).c_str() ) ); f.PutLine( ssprintf( "#MUSIC:%s;", SmEscape(out.m_sMusicFile).c_str() ) ); - f.PutLine( ssprintf( "#LEADTRACK:%s;", SmEscape(out.m_sLeadTrackFile).c_str() ) ); + + { + vector vs; + FOREACH_ENUM( InstrumentTrack, it ) + if( out.HasInstrumentTrack(it) ) + vs.push_back( InstrumentTrackToString(it) + "=" + out.m_sInstrumentTrackFile[it] ); + if( !vs.empty() ) + { + RString s = join( ",", vs ); + f.PutLine( "#INSTRUMENTTRACK:" + s + ";\n" ); + } + } f.PutLine( ssprintf( "#OFFSET:%.3f;", out.m_Timing.m_fBeat0OffsetInSeconds ) ); f.PutLine( ssprintf( "#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds ) ); f.PutLine( ssprintf( "#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds ) ); diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index 7dbc2797a4..a6cc2ef8ba 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -33,7 +33,7 @@ #include #include -const int FILE_CACHE_VERSION = 156; // increment this to invalidate cache +const int FILE_CACHE_VERSION = 159; // increment this to invalidate cache const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f; @@ -41,6 +41,15 @@ static Preference g_fLongVerSongSeconds( "LongVerSongSeconds", 60*2.5f ) static Preference g_fMarathonVerSongSeconds( "MarathonVerSongSeconds", 60*5.f ); static Preference g_BackUpAllSongSaves( "BackUpAllSongSaves", false ); +static const char *InstrumentTrackNames[] = { + "Guitar", + "Rhythm", + "Bass", +}; +XToString( InstrumentTrack ); +StringToX( InstrumentTrack ); + + Song::Song() { FOREACH_BackgroundLayer( i ) @@ -362,7 +371,9 @@ void Song::TidyUpData() ASSERT_M( m_sSongDir.Left(3) != "../", m_sSongDir ); /* meaningless */ FixupPath( m_sSongDir, "" ); FixupPath( m_sMusicFile, m_sSongDir ); - FixupPath( m_sLeadTrackFile, m_sSongDir ); + FOREACH_ENUM( InstrumentTrack, i ) + if( !m_sInstrumentTrackFile[i].empty() ) + FixupPath( m_sInstrumentTrackFile[i], m_sSongDir ); FixupPath( m_sBannerFile, m_sSongDir ); FixupPath( m_sLyricsFile, m_sSongDir ); FixupPath( m_sBackgroundFile, m_sSongDir ); @@ -1053,7 +1064,10 @@ bool Song::HasMusic() const return m_sMusicFile != "" && IsAFile(GetMusicPath()); } bool Song::HasBanner() const {return m_sBannerFile != "" && IsAFile(GetBannerPath()); } -bool Song::HasLeadTrack() const {return m_sLeadTrackFile != "" && IsAFile(GetLeadTrackPath()); } +bool Song::HasInstrumentTrack( InstrumentTrack it ) const +{ + return m_sInstrumentTrackFile[it] != "" && IsAFile(GetInstrumentTrackPath(it)); +} bool Song::HasLyrics() const {return m_sLyricsFile != "" && IsAFile(GetLyricsPath()); } bool Song::HasBackground() const {return m_sBackgroundFile != "" && IsAFile(GetBackgroundPath()); } bool Song::HasCDTitle() const {return m_sCDTitleFile != "" && IsAFile(GetCDTitlePath()); } @@ -1121,9 +1135,9 @@ RString Song::GetMusicPath() const return GetSongAssetPath( m_sMusicFile, m_sSongDir ); } -RString Song::GetLeadTrackPath() const +RString Song::GetInstrumentTrackPath( InstrumentTrack it ) const { - return GetSongAssetPath( m_sLeadTrackFile, m_sSongDir ); + return GetSongAssetPath( m_sInstrumentTrackFile[it], m_sSongDir ); } RString Song::GetBannerPath() const diff --git a/stepmania/src/song.h b/stepmania/src/song.h index 62ed410bad..433baf4c00 100644 --- a/stepmania/src/song.h +++ b/stepmania/src/song.h @@ -29,6 +29,17 @@ enum BackgroundLayer }; #define FOREACH_BackgroundLayer( bl ) FOREACH_ENUM( BackgroundLayer, bl ) +enum InstrumentTrack +{ + InstrumentTrack_Guitar, + InstrumentTrack_Rhythm, + InstrumentTrack_Bass, + NUM_InstrumentTrack, + InstrumentTrack_Invalid +}; +const RString& InstrumentTrackToString( InstrumentTrack it ); +InstrumentTrack StringToInstrumentTrack( const RString& s ); + struct LyricSegment { float m_fStartTime; @@ -113,7 +124,8 @@ public: RString m_sCredit; RString m_sMusicFile; - RString m_sLeadTrackFile; + RString m_sInstrumentTrackFile[NUM_InstrumentTrack]; + float m_fMusicLengthSeconds; float m_fFirstBeat; // beat of first note float m_fLastBeat; // beat of last note @@ -130,7 +142,7 @@ public: RString m_sCDTitleFile; RString GetMusicPath() const; - RString GetLeadTrackPath() const; + RString GetInstrumentTrackPath( InstrumentTrack it ) const; RString GetBannerPath() const; RString GetLyricsPath() const; RString GetBackgroundPath() const; @@ -140,7 +152,7 @@ public: bool m_bHasMusic, m_bHasBanner; bool HasMusic() const; - bool HasLeadTrack() const; + bool HasInstrumentTrack( InstrumentTrack it ) const; bool HasBanner() const; bool HasBackground() const; bool HasCDTitle() const;