diff --git a/src/Player.cpp b/src/Player.cpp index 547a62d3b9..3c799ca99c 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -408,9 +408,35 @@ void Player::Init( break; } + // calculate A-mod speed here, so we can adjust properly on a per-song basis. + // XXX: can we find a better location for this? + // XXX: Yes, I copied the same comment practically. --wolfman2000 + if (m_pPlayerState->m_PlayerOptions.GetCurrent().m_fAvgScrollBPM != 0) + { + float avgBPM; + if (GAMESTATE->IsCourseMode() ) + { + vector &entries = GAMESTATE->m_pCurTrail[pn]->m_vEntries; + float foundBPMs = 0; + FOREACH_CONST( TrailEntry, entries, e ) + { + foundBPMs += e->pSong->m_SongTiming.GetBPMUsedMostOften(); + } + avgBPM = foundBPMs / entries.size(); + } + else + { + avgBPM = GAMESTATE->m_pCurSong->m_SongTiming.GetBPMUsedMostOften(); + } + + // set an X-mod equal to Anum / avgBPM (e.g. A600 with 150 becomes 4x) + PO_GROUP_ASSIGN(m_pPlayerState->m_PlayerOptions, ModsLevel_Preferred, m_fScrollSpeed, + m_pPlayerState->m_PlayerOptions.GetPreferred().m_fAvgScrollBPM / avgBPM); + } + // calculate M-mod speed here, so we can adjust properly on a per-song basis. // XXX: can we find a better location for this? - if( m_pPlayerState->m_PlayerOptions.GetCurrent().m_fMaxScrollBPM != 0 ) + else if( m_pPlayerState->m_PlayerOptions.GetCurrent().m_fMaxScrollBPM != 0 ) { DisplayBpms bpms; diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index f0e908b79e..4b2c950396 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -27,6 +27,7 @@ void PlayerOptions::Init() { m_bSetScrollSpeed = false; m_fMaxScrollBPM = 0; m_SpeedfMaxScrollBPM = 1.0f; + m_fAvgScrollBPM = 0; m_SpeedfAvgScrollBPM = 1.0f; m_fTimeSpacing = 0; m_SpeedfTimeSpacing = 1.0f; m_fScrollSpeed = 1.0f; m_SpeedfScrollSpeed = 1.0f; m_fScrollBPM = 200; m_SpeedfScrollBPM = 1.0f; @@ -62,6 +63,7 @@ void PlayerOptions::Approach( const PlayerOptions& other, float fDeltaSeconds ) APPROACH( fTimeSpacing ); APPROACH( fScrollSpeed ); //APPROACH( fMaxScrollBPM ); // if uncommented, causes crashes. -aj + //APPROACH( fAvgScrollBPM ); // not sure if this crashes, but playing safe. -Wolfman2000 fapproach( m_fScrollBPM, other.m_fScrollBPM, fDeltaSeconds * other.m_SpeedfScrollBPM*150 ); for( int i=0; i &AddTo, bool bForceNoteSkin ) const if( !m_fTimeSpacing ) { - if( m_fMaxScrollBPM ) + if( m_fAvgScrollBPM ) + { + RString s = ssprintf( "a%.0f", m_fAvgScrollBPM ); + AddTo.push_back( s ); + } + else if( m_fMaxScrollBPM ) { RString s = ssprintf( "m%.0f", m_fMaxScrollBPM ); AddTo.push_back( s ); @@ -342,6 +349,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut SET_FLOAT( fTimeSpacing ) m_fTimeSpacing = 0; m_fMaxScrollBPM = 0; + m_fAvgScrollBPM = 0; } else if( sscanf( sBit, "c%f", &level ) == 1 ) { @@ -351,6 +359,7 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut SET_FLOAT( fTimeSpacing ) m_fTimeSpacing = 1; m_fMaxScrollBPM = 0; + m_fAvgScrollBPM = 0; } // oITG's m-mods // XXX: will not properly tween, I don't think. @@ -363,6 +372,14 @@ bool PlayerOptions::FromOneModString( const RString &sOneMod, RString &sErrorOut */ SET_FLOAT( fMaxScrollBPM ) m_fTimeSpacing = 0; + m_fAvgScrollBPM = 0; + } + // Third Style inspired a-mods + else if( sscanf( sBit, "a%f", &level ) == 1 ) + { + SET_FLOAT( fAvgScrollBPM ); + m_fTimeSpacing = 0; + m_fMaxScrollBPM = 0; } else if( sBit == "clearall" ) Init(); @@ -666,6 +683,7 @@ bool PlayerOptions::operator==( const PlayerOptions &other ) const COMPARE(m_fScrollSpeed); COMPARE(m_fScrollBPM); COMPARE(m_fMaxScrollBPM); + COMPARE(m_fAvgScrollBPM); COMPARE(m_fRandomSpeed); COMPARE(m_FailType); COMPARE(m_bMuteOnError); @@ -734,9 +752,9 @@ bool PlayerOptions::IsEasierForSongAndSteps( Song* pSong, Steps* pSteps, PlayerN if( m_fCover ) return true; - // M-mods make songs with indefinite BPMs easier because + // M-mods and a-mods make songs with indefinite BPMs easier because // they ensure that the song has a scrollable speed. - if( m_fMaxScrollBPM != 0 ) + if( m_fMaxScrollBPM != 0 || m_fAvgScrollBPM != 0 ) { // BPM display is obfuscated // if( pSong->m_DisplayBPMType == DISPLAY_BPM_RANDOM ) @@ -830,6 +848,7 @@ RString PlayerOptions::GetSavedPrefsString() const SAVE( m_fScrollSpeed ); SAVE( m_fScrollBPM ); SAVE( m_fMaxScrollBPM ); + SAVE( m_fAvgScrollBPM ); SAVE( m_fScrolls[SCROLL_REVERSE] ); SAVE( m_fPerspectiveTilt ); SAVE( m_bTransforms[TRANSFORM_NOHOLDS] ); @@ -859,6 +878,7 @@ void PlayerOptions::ResetPrefs( ResetPrefsType type ) CPY( m_fScrollSpeed ); CPY( m_fScrollBPM ); CPY( m_fMaxScrollBPM ); + CPY( m_fAvgScrollBPM ); break; case saved_prefs_invalid_for_course: break; @@ -933,6 +953,7 @@ public: p->m_fTimeSpacing = FArg(1); p->m_fTimeSpacing = 1; p->m_fMaxScrollBPM = 0; + p->m_fAvgScrollBPM = 0; return 0; } @@ -949,6 +970,7 @@ public: p->m_fScrollSpeed = FArg(1); p->m_fTimeSpacing = 0; p->m_fMaxScrollBPM = 0; + p->m_fAvgScrollBPM = 0; return 0; } @@ -965,6 +987,23 @@ public: { p->m_fMaxScrollBPM = FArg(1); p->m_fTimeSpacing = 0; + p->m_fAvgScrollBPM = 0; + return 0; + } + static int GetAMod( T * p, lua_State * L ) + { + if (!p->m_fTimeSpacing && p->m_fAvgScrollBPM) + lua_pushnumber(L, p->m_fAvgScrollBPM); + else + lua_pushnil(L); + + return 1; + } + static int SetAMod( T * p, lua_State * L ) + { + p->m_fAvgScrollBPM = FArg(1); + p->m_fTimeSpacing = 0; + p->m_fMaxScrollBPM = 0; return 0; } @@ -1185,6 +1224,8 @@ public: ADD_METHOD( SetXMod ); ADD_METHOD( GetMMod ); ADD_METHOD( SetMMod ); + ADD_METHOD( GetAMod ); + ADD_METHOD( SetAMod ); // Accel ADD_METHOD( GetBoost ); diff --git a/src/PlayerOptions.h b/src/PlayerOptions.h index ac32f86ee5..1741688f27 100644 --- a/src/PlayerOptions.h +++ b/src/PlayerOptions.h @@ -22,6 +22,7 @@ public: PlayerOptions(): m_bSetScrollSpeed(false), m_fTimeSpacing(0), m_SpeedfTimeSpacing(1.0f), m_fMaxScrollBPM(0), m_SpeedfMaxScrollBPM(1.0f), + m_fAvgScrollBPM(0), m_SpeedfAvgScrollBPM(1.0f), m_fScrollSpeed(1.0f), m_SpeedfScrollSpeed(1.0f), m_fScrollBPM(200), m_SpeedfScrollBPM(1.0f), m_fDark(0), m_SpeedfDark(1.0f), @@ -158,8 +159,9 @@ public: /* All floats have a corresponding speed setting, which determines how fast * PlayerOptions::Approach approaches. */ bool m_bSetScrollSpeed; // true if the scroll speed was set by FromString - float m_fTimeSpacing, m_SpeedfTimeSpacing; // instead of Beat spacing (CMods, mMods) + float m_fTimeSpacing, m_SpeedfTimeSpacing; // instead of Beat spacing (CMods, mMods, aMods) float m_fMaxScrollBPM, m_SpeedfMaxScrollBPM; + float m_fAvgScrollBPM, m_SpeedfAvgScrollBPM; float m_fScrollSpeed, m_SpeedfScrollSpeed; // used if !m_bTimeSpacing (xMods) float m_fScrollBPM, m_SpeedfScrollBPM; // used if m_bTimeSpacing (CMod) float m_fAccels[NUM_ACCELS], m_SpeedfAccels[NUM_ACCELS]; diff --git a/src/Song.cpp b/src/Song.cpp index 54b5241986..c90cfeeaf2 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -847,9 +847,13 @@ void Song::ReCalculateRadarValuesAndLastSecond(bool fromCache, bool duringCache) { if( fromCache && this->GetFirstSecond() >= 0 && this->GetLastSecond() > 0 ) { + this->m_SongTiming.SetLastRowFromTime(this->GetLastSecond()); // this is loaded from cache, then we just have to calculate the radar values. for( unsigned i=0; iCalculateRadarValues( m_fMusicLengthSeconds ); + m_vpSteps[i]->m_Timing.SetLastRowFromTime(this->GetLastSecond()); + } return; } @@ -904,6 +908,12 @@ void Song::ReCalculateRadarValuesAndLastSecond(bool fromCache, bool duringCache) // Yes, for some reason we can have freaky stuff take place here. this->firstSecond = (localFirst < localLast) ? localFirst : 0; this->lastSecond = localLast; + + this->m_SongTiming.SetLastRowFromTime(localLast); + for( unsigned i = 0; i < this->m_vpSteps.size(); ++i) + { + this->m_vpSteps[i]->m_Timing.SetLastRowFromTime(localLast); + } } // Return whether the song is playable in the given style. diff --git a/src/StepMania-net2008.vcproj b/src/StepMania-net2008.vcproj index e1d7a88288..6b70917388 100644 --- a/src/StepMania-net2008.vcproj +++ b/src/StepMania-net2008.vcproj @@ -19,7 +19,7 @@ <_ProjectFileVersion>10.0.30319.1 - $(TargetDir)../Program/ - $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(ConfigurationName) + $(TargetDir)..\Program\ + $(SolutionDir)\build-$(SolutionName)\$(ProjectName)\$(ConfigurationName) true true - $(TargetDir)../Program/ - $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(ConfigurationName) + $(TargetDir)..\Program\ + $(SolutionDir)\build-$(SolutionName)\$(ProjectName)\$(ConfigurationName) false - $(TargetDir)../Program/ - $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(ConfigurationName) + $(TargetDir)..\Program\ + $(SolutionDir)\build-$(SolutionName)\$(ProjectName)\$(ConfigurationName) true true - $(TargetDir)../Program/ - $(SolutionDir)/build-$(SolutionName)/$(ProjectName)/$(ConfigurationName) + $(TargetDir)..\Program\ + $(SolutionDir)\build-$(SolutionName)\$(ProjectName)\$(ConfigurationName) false AllRules.ruleset @@ -93,18 +93,10 @@ AllRules.ruleset - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Include;$(IncludePath) - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Lib;$(LibraryPath) - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Include;$(IncludePath) - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Include;$(IncludePath) StepMania-debug StepMania-fastdebug StepMania-SSE2 StepMania - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Include;$(IncludePath) - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Lib;$(LibraryPath) - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Lib;$(LibraryPath) - C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (Summer 2004)\Lib;$(LibraryPath) @@ -120,14 +112,13 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) Disabled - .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;$(DXSDK_DIR)\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;WINDOWS;DEBUG;GLEW_STATIC;%(PreprocessorDefinitions) Sync EnableFastChecks MultiThreadedDebugDLL Use global.h - $(IntDir)StepMania.pch $(IntDir) $(IntDir) $(IntDir)vc80.pdb @@ -138,7 +129,6 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) EditAndContinue 4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996;%(DisableSpecificWarnings) true - true false @@ -148,9 +138,9 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;Comctl32.lib;swscale.lib;avcodec.lib;avformat.lib;avutil.lib;%(AdditionalDependencies) - ../Program/StepMania-debug.exe + ..\Program\StepMania-debug.exe true - ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;..\extern\mad-0.15.1b\msvc++\Release\%(AdditionalLibraryDirectories) + ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;$(DXSDK_DIR)\Lib\x86;..\extern\mad-0.15.1b\msvc++\Release\%(AdditionalLibraryDirectories) wininet.lib;msimg32.lib;libci.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) true $(IntDir)StepMania.pdb @@ -185,17 +175,15 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) AnySuitable true Size - .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;$(DXSDK_DIR)\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;WINDOWS;RELEASE;GLEW_STATIC;%(PreprocessorDefinitions) true - false Sync MultiThreadedDLL false false Use global.h - $(IntDir)StepMania.pch $(IntDir) $(IntDir) $(IntDir)vc80.pdb @@ -215,9 +203,9 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;Comctl32.lib;swscale.lib;avcodec.lib;avformat.lib;avutil.lib;%(AdditionalDependencies) - ../Program/StepMania.exe + ..\Program\StepMania.exe true - ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;..\extern\mad-0.15.1b\msvc++\Release\%(AdditionalLibraryDirectories) + ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;$(DXSDK_DIR)\Lib\x86;..\extern\mad-0.15.1b\msvc++\Release\%(AdditionalLibraryDirectories) wininet.lib;msimg32.lib;libci.lib;%(IgnoreSpecificDefaultLibraries) $(IntDir)StepMania.pdb true @@ -249,14 +237,13 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) MaxSpeed - .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;$(DXSDK_DIR)\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;WINDOWS;DEBUG;GLEW_STATIC;%(PreprocessorDefinitions) Sync Default MultiThreadedDebugDLL Use global.h - $(IntDir)StepMania.pch $(IntDir) $(IntDir) $(IntDir)vc80.pdb @@ -279,9 +266,9 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;Comctl32.lib;swscale.lib;avcodec.lib;avformat.lib;avutil.lib;%(AdditionalDependencies) - ../Program/StepMania-fastdebug.exe + ..\Program\StepMania-fastdebug.exe true - ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;..\extern\mad-0.15.1b\msvc++\Release\;%(AdditionalLibraryDirectories) + ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;$(DXSDK_DIR)\Lib\x86;..\extern\mad-0.15.1b\msvc++\Release\;%(AdditionalLibraryDirectories) wininet.lib;msimg32.lib;libci.lib;msvcrt.lib;%(IgnoreSpecificDefaultLibraries) true $(IntDir)StepMania.pdb @@ -316,10 +303,9 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) AnySuitable true Speed - .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;%(AdditionalIncludeDirectories) + .;..\extern\lua-5.1\src;..\extern\ffmpeg\include;BaseClasses;..\extern\jsoncpp\include;..\extern\glew-1.5.8\include;..\extern\pcre;..\extern\mad-0.15.1b;..\extern\libpng\lib;..\extern\libpng\include;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis;$(DXSDK_DIR)\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;WINDOWS;RELEASE;GLEW_STATIC;%(PreprocessorDefinitions) true - false MultiThreadedDLL @@ -328,7 +314,6 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) StreamingSIMDExtensions2 Use global.h - $(IntDir)StepMania-SSE2.pch $(IntDir) $(IntDir) $(IntDir)vc80.pdb @@ -348,9 +333,9 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir) /MACHINE:I386 "$(IntDir)verstub.obj" %(AdditionalOptions) shell32.lib;gdi32.lib;user32.lib;ole32.lib;advapi32.lib;Comctl32.lib;swscale.lib;avcodec.lib;avformat.lib;avutil.lib;%(AdditionalDependencies) - ..\Program/StepMania-SSE2.exe + ..\Program\StepMania-SSE2.exe true - ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;..\extern\mad-0.15.1b\msvc++\Release\%(AdditionalLibraryDirectories) + ..\extern\libpng\lib;..\extern\ffmpeg\lib;..\extern\libjpeg\;..\extern\zlib\;$(DXSDK_DIR)\Lib\x86;..\extern\mad-0.15.1b\msvc++\Release\%(AdditionalLibraryDirectories) wininet.lib;msimg32.lib;libci.lib;%(IgnoreSpecificDefaultLibraries) $(IntDir)StepMania-SSE2.pdb true diff --git a/src/TimingData.cpp b/src/TimingData.cpp index fca50a6cbf..b10c81df35 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -9,7 +9,7 @@ TimingSegment* GetSegmentAtRow( int iNoteRow, TimingSegmentType tst ); -TimingData::TimingData(float fOffset) : m_fBeat0OffsetInSeconds(fOffset) +TimingData::TimingData(float fOffset) : m_fBeat0OffsetInSeconds(fOffset), lastRow(-1) { } @@ -19,6 +19,7 @@ void TimingData::Copy( const TimingData& cpy ) Clear(); m_fBeat0OffsetInSeconds = cpy.m_fBeat0OffsetInSeconds; + lastRow = cpy.lastRow; m_sFile = cpy.m_sFile; FOREACH_TimingSegmentType( tst ) @@ -169,6 +170,90 @@ struct ts_less : binary_function } }; +void TimingData::SetLastRowFromTime(float seconds) +{ + float beat = 0; + // TODO: Address this. + float dummy1, dummy5; + bool dummy2, dummy3; + int dummy4; + GetBeatAndBPSFromElapsedTime(seconds, beat, dummy1, dummy2, dummy3, dummy4, dummy5); + this->lastRow = BeatToNoteRow(beat); +} + +float TimingData::GetBPMUsedMostOften() +{ + if (this == NULL) + { + return -1; // not taking ANY chances. + } + + if (!HasBpmChanges()) + { + return GetBPMSegmentAtRow(0)->GetBPM(); + } + + // TODO: Find a way to make this const compatible. + vector &bpms = m_avpTimingSegments[SEGMENT_BPM]; + map lengths; + map::iterator location; + + BPMSegment *prev = ToBPM(GetBPMSegmentAtRow(0)); + BPMSegment *curr = ToBPM(bpms[1]); + BPMSegment *next = curr; + float runningTime = GetElapsedTimeFromBeat(next->GetBeat()); + lengths.insert(make_pair(prev->GetBPM(), runningTime)); + + for( unsigned i = 1; i < bpms.size(); ++i ) + { + bool isLast = (i + 1 == bpms.size()); + + if (isLast) + { + runningTime = GetElapsedTimeFromBeat(NoteRowToBeat(lastRow)); + } + else + { + next = ToBPM(bpms[i + 1]); + runningTime = GetElapsedTimeFromBeat(next->GetBeat()); + } + + float curBPM = curr->GetBPM(); + location = lengths.find(curBPM); + float elapsedTime = runningTime - lengths[prev->GetBPM()]; + if (location == lengths.end()) + { + lengths[curBPM] = elapsedTime; + } + else + { + lengths[curBPM] += elapsedTime; + } + + if (!isLast) + { + prev = curr; + curr = next; + } + } + + // at this point, go through the map. + float highestKey = -1; + float highestValue = -1; + + // TODO: C++11 this. + FOREACHM_CONST(float, float, lengths, it) + { + if (it->second > highestValue) + { + highestValue = it->second; + highestKey = it->first; + } + } + + return highestKey; +} + // Multiply the BPM in the range [fStartBeat,fEndBeat) by fFactor. void TimingData::MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ) { diff --git a/src/TimingData.h b/src/TimingData.h index 7fd1acdcd1..12295885fc 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -286,6 +286,8 @@ public: bool IsJudgableAtRow( int row ) const { return !IsWarpAtRow(row) && !IsFakeAtRow(row); } bool IsJudgableAtBeat( float beat ) const { return IsJudgableAtRow( BeatToNoteRow( beat ) ); } + float GetBPMUsedMostOften(); + void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const; @@ -376,6 +378,8 @@ public: return m_avpTimingSegments[tst]; } + void SetLastRowFromTime(float seconds); + /** * @brief Tidy up the timing data, e.g. provide default BPMs, labels, tickcounts. * @param allowEmpty true if completely empty TimingData should be left @@ -396,6 +400,9 @@ public: /** @brief The initial offset of a song. */ float m_fBeat0OffsetInSeconds; + /** @brief The row of the final song. */ + int lastRow; + // XXX: this breaks encapsulation. get rid of it ASAP vector ToVectorString(TimingSegmentType tst, int dec = 6) const; protected: