diff --git a/stepmania/src/Background.cpp b/stepmania/src/Background.cpp index 9f932598d3..6e2d314466 100644 --- a/stepmania/src/Background.cpp +++ b/stepmania/src/Background.cpp @@ -308,19 +308,21 @@ void Background::LoadFromRandom( float fFirstBeat, float fLastBeat, const Timing } // change BG every BPM change that is at the beginning of a measure + int iStartIndex = BeatToNoteRow(fFirstBeat); + int iEndIndex = BeatToNoteRow(fLastBeat); for( unsigned i=0; i fLastBeat ) + if( bpmseg.m_iStartIndex < iStartIndex || bpmseg.m_iStartIndex > iEndIndex ) continue; // skip CString sBGName = CreateRandomBGA(); if( sBGName != "" ) - m_aBGChanges.push_back( BackgroundChange(bpmseg.m_fStartBeat,sBGName) ); + m_aBGChanges.push_back( BackgroundChange(NoteRowToBeat(bpmseg.m_iStartIndex),sBGName) ); } } diff --git a/stepmania/src/NoteField.cpp b/stepmania/src/NoteField.cpp index 29308f19a7..2b6a3c9eb7 100644 --- a/stepmania/src/NoteField.cpp +++ b/stepmania/src/NoteField.cpp @@ -485,9 +485,9 @@ void NoteField::DrawPrimitives() vector &aBPMSegments = GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments; for( unsigned i=0; i= fFirstBeatToDraw && - aBPMSegments[i].m_fStartBeat <= fLastBeatToDraw) - DrawBPMText( aBPMSegments[i].m_fStartBeat, aBPMSegments[i].m_fBPM ); + if(aBPMSegments[i].m_iStartIndex >= iFirstIndexToDraw && + aBPMSegments[i].m_iStartIndex <= iLastIndexToDraw) + DrawBPMText( NoteRowToBeat(aBPMSegments[i].m_iStartIndex), aBPMSegments[i].GetBPM() ); } // // Freeze text @@ -495,9 +495,9 @@ void NoteField::DrawPrimitives() vector &aStopSegments = GAMESTATE->m_pCurSong->m_Timing.m_StopSegments; for( unsigned i=0; i= fFirstBeatToDraw && - aStopSegments[i].m_fStartBeat <= fLastBeatToDraw) - DrawFreezeText( aStopSegments[i].m_fStartBeat, aStopSegments[i].m_fStopSeconds ); + if(aStopSegments[i].m_iStartRow >= iFirstIndexToDraw && + aStopSegments[i].m_iStartRow <= iLastIndexToDraw) + DrawFreezeText( NoteRowToBeat(aStopSegments[i].m_iStartRow), NoteRowToBeat(aStopSegments[i].m_iStartRow) ); } // diff --git a/stepmania/src/NotesLoaderBMS.cpp b/stepmania/src/NotesLoaderBMS.cpp index e6efddb652..97952ba66c 100644 --- a/stepmania/src/NotesLoaderBMS.cpp +++ b/stepmania/src/NotesLoaderBMS.cpp @@ -10,6 +10,7 @@ #include "song.h" #include "Steps.h" #include "RageUtil_CharConversions.h" +#include "NoteTypes.h" /* BMS encoding: tap-hold 4&8panel: Player1 Player2 @@ -602,10 +603,10 @@ void BMSLoader::ReadGlobalTags( const NameToData_t &mapNameToData, Song &out ) if( GetTagFromMap( mapNameToData, "#bpm", sData ) ) { - BPMSegment newSeg( 0, strtof(sData, NULL) ); + BPMSegment newSeg( 0, BeatToNoteRow(strtof(sData, NULL)) ); out.AddBPMSegment( newSeg ); - LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", newSeg.m_fStartBeat, newSeg.m_fBPM ); + LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartIndex), newSeg.GetBPM() ); } NameToData_t::const_iterator it; @@ -691,9 +692,11 @@ void BMSLoader::ReadGlobalTags( const NameToData_t &mapNameToData, Song &out ) { float fBPM = strtof( sBPM, NULL ); - BPMSegment newSeg( fBeat, fBPM ); + BPMSegment newSeg; + newSeg.m_iStartIndex = BeatToNoteRow(fBeat); + newSeg.SetBPM( fBPM ); out.AddBPMSegment( newSeg ); - LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", newSeg.m_fStartBeat, newSeg.m_fBPM ); + LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", fBeat, newSeg.GetBPM() ); } else LOG->Warn( "Couldn't find tag '%s' in '%s'.", sTagToLookFor.c_str(), m_sDir.c_str() ); @@ -710,9 +713,9 @@ void BMSLoader::ReadGlobalTags( const NameToData_t &mapNameToData, Song &out ) float fBeats = strtof(sBeats,NULL) / 48.0f; float fFreezeSecs = fBeats / fBPS; - StopSegment newSeg( fBeat, fFreezeSecs ); + StopSegment newSeg( BeatToNoteRow(fBeat), fFreezeSecs ); out.AddStopSegment( newSeg ); - LOG->Trace( "Inserting new Freeze at beat %f, secs %f", newSeg.m_fStartBeat, newSeg.m_fStopSeconds ); + LOG->Trace( "Inserting new Freeze at beat %f, secs %f", fBeat, newSeg.m_fStopSeconds ); } else LOG->Warn( "Couldn't find tag '%s' in '%s'.", sTagToLookFor.c_str(), m_sDir.c_str() ); @@ -735,9 +738,11 @@ void BMSLoader::ReadGlobalTags( const NameToData_t &mapNameToData, Song &out ) { float fBPM = strtof( sBPM, NULL ); - BPMSegment newSeg( NoteRowToBeat(iStepIndex), fBPM ); + BPMSegment newSeg; + newSeg.m_iStartIndex = iStepIndex; + newSeg.SetBPM( fBPM ); out.AddBPMSegment( newSeg ); - LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", newSeg.m_fStartBeat, newSeg.m_fBPM ); + LOG->Trace( "Inserting new BPM change at beat %f, BPM %f", NoteRowToBeat(newSeg.m_iStartIndex), newSeg.GetBPM() ); } else LOG->Warn( "Couldn't find tag '%s' in '%s'.", sTagToLookFor.c_str(), m_sDir.c_str() ); @@ -834,9 +839,9 @@ void BMSLoader::SetTimeSigAdjustments( const MeasureToTimeSig_t &sigs, Song *pOu * adjustment and the BPM adjustment together, everything remains consistent. * Adjust m_TimeSigAdjustments first, or fAdjustmentEndBeat will be wrong. */ m_TimeSigAdjustments[iMeasure] = 1.0f / fFactor; - float fAdjustmentStartBeat = NoteRowToBeat( GetMeasureStartRow( sigs, iMeasure ) ); - float fAdjustmentEndBeat = NoteRowToBeat( GetMeasureStartRow( sigs, iMeasure+1 ) ); - pOut->m_Timing.MultiplyBPMInBeatRange( fAdjustmentStartBeat, fAdjustmentEndBeat, 1.0f / fFactor ); + int iAdjustmentStartRow = GetMeasureStartRow( sigs, iMeasure ); + int iAdjustmentEndRow = GetMeasureStartRow( sigs, iMeasure+1 ); + pOut->m_Timing.MultiplyBPMInBeatRange( iAdjustmentStartRow, iAdjustmentEndRow, 1.0f / fFactor ); } } diff --git a/stepmania/src/NotesLoaderDWI.cpp b/stepmania/src/NotesLoaderDWI.cpp index 07209f5321..864531996a 100644 --- a/stepmania/src/NotesLoaderDWI.cpp +++ b/stepmania/src/NotesLoaderDWI.cpp @@ -375,7 +375,7 @@ bool DWILoader::LoadFromDWIFile( CString sPath, Song &out ) out.m_sCDTitleFile = sParams[1]; else if( 0==stricmp(sValueName,"BPM") ) - out.AddBPMSegment( BPMSegment(0, strtof(sParams[1], NULL)) ); + out.AddBPMSegment( BPMSegment(0, BeatToNoteRow(strtof(sParams[1], NULL))) ); else if( 0==stricmp(sValueName,"DISPLAYBPM") ) { @@ -425,11 +425,10 @@ bool DWILoader::LoadFromDWIFile( CString sPath, Song &out ) LOG->Warn( "Invalid FREEZE in '%s': '%s'", m_sLoadingFile.c_str(), arrayFreezeExpressions[f].c_str() ); continue; } - float fIndex = strtof( arrayFreezeValues[0],NULL ) * ROWS_PER_BEAT / 4.0f; - float fFreezeBeat = NoteRowToBeat( fIndex ); + int iFreezeRow = BeatToNoteRow( strtof( arrayFreezeValues[0],NULL ) / 4.0f ); float fFreezeSeconds = strtof( arrayFreezeValues[1], NULL ) / 1000.0f; - out.AddStopSegment( StopSegment(fFreezeBeat, fFreezeSeconds) ); + out.AddStopSegment( StopSegment(iFreezeRow, fFreezeSeconds) ); // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", fFreezeBeat, fFreezeSeconds ); } } @@ -448,11 +447,11 @@ bool DWILoader::LoadFromDWIFile( CString sPath, Song &out ) LOG->Warn( "Invalid CHANGEBPM in '%s': '%s'", m_sLoadingFile.c_str(), arrayBPMChangeExpressions[b].c_str() ); continue; } - float fIndex = strtof( arrayBPMChangeValues[0], NULL ) * ROWS_PER_BEAT / 4.0f; - float fBeat = NoteRowToBeat( fIndex ); - float fNewBPM = strtof( arrayBPMChangeValues[1], NULL ); - out.AddBPMSegment( BPMSegment(fBeat, fNewBPM) ); + BPMSegment bs; + bs.m_iStartIndex = BeatToNoteRow( strtof( arrayBPMChangeValues[0],NULL ) / 4.0f ); + bs.SetBPM( strtof( arrayBPMChangeValues[1], NULL ) ); + out.AddBPMSegment( bs ); } } diff --git a/stepmania/src/NotesLoaderSM.cpp b/stepmania/src/NotesLoaderSM.cpp index 820024706d..233d790932 100644 --- a/stepmania/src/NotesLoaderSM.cpp +++ b/stepmania/src/NotesLoaderSM.cpp @@ -7,6 +7,7 @@ #include "RageUtil.h" #include "SongManager.h" #include "RageFileManager.h" +#include "NoteTypes.h" #define MAX_EDIT_SIZE_BYTES 20*1024 // 20 KB @@ -110,7 +111,7 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) const float fFreezeSeconds = strtof( arrayFreezeValues[1], NULL ); StopSegment new_seg; - new_seg.m_fStartBeat = fFreezeBeat; + new_seg.m_iStartRow = BeatToNoteRow(fFreezeBeat); new_seg.m_fStopSeconds = fFreezeSeconds; // LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds ); @@ -141,8 +142,8 @@ void SMLoader::LoadTimingFromSMFile( const MsdFile &msd, TimingData &out ) const float fNewBPM = strtof( arrayBPMChangeValues[1], NULL ); BPMSegment new_seg; - new_seg.m_fStartBeat = fBeat; - new_seg.m_fBPM = fNewBPM; + new_seg.m_iStartIndex = BeatToNoteRow(fBeat); + new_seg.SetBPM( fNewBPM ); out.AddBPMSegment( new_seg ); } diff --git a/stepmania/src/NotesWriterDWI.cpp b/stepmania/src/NotesWriterDWI.cpp index 4aca99fbb1..1ad7e7d653 100644 --- a/stepmania/src/NotesWriterDWI.cpp +++ b/stepmania/src/NotesWriterDWI.cpp @@ -350,9 +350,9 @@ bool NotesWriterDWI::Write( CString sPath, const Song &out ) /* Write transliterations, if we have them, since DWI doesn't support UTF-8. */ f.PutLine( ssprintf("#TITLE:%s;", out.GetFullTranslitTitle().c_str()) ); f.PutLine( ssprintf("#ARTIST:%s;", out.GetTranslitArtist().c_str()) ); - ASSERT( out.m_Timing.m_BPMSegments[0].m_fStartBeat == 0 ); + ASSERT( out.m_Timing.m_BPMSegments[0].m_iStartIndex == 0 ); f.PutLine( ssprintf("#FILE:%s;", out.m_sMusicFile.c_str()) ); - f.PutLine( ssprintf("#BPM:%.3f;", out.m_Timing.m_BPMSegments[0].m_fBPM) ); + f.PutLine( ssprintf("#BPM:%.3f;", out.m_Timing.m_BPMSegments[0].GetBPM()) ); f.PutLine( ssprintf("#GAP:%d;", int(-roundf( out.m_Timing.m_fBeat0OffsetInSeconds*1000 ))) ); f.PutLine( ssprintf("#SAMPLESTART:%.3f;", out.m_fMusicSampleStartSeconds) ); f.PutLine( ssprintf("#SAMPLELENGTH:%.3f;", out.m_fMusicSampleLengthSeconds) ); @@ -381,7 +381,7 @@ bool NotesWriterDWI::Write( CString sPath, const Song &out ) for( unsigned i=0; i #include @@ -62,7 +63,7 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out ) { const BPMSegment &bs = out.m_Timing.m_BPMSegments[i]; - f.Write( ssprintf( "%.3f=%.3f", bs.m_fStartBeat, bs.m_fBPM ) ); + f.Write( ssprintf( "%.3f=%.3f", NoteRowToBeat(bs.m_iStartIndex), bs.GetBPM() ) ); if( i != out.m_Timing.m_BPMSegments.size()-1 ) f.Write( "," ); } @@ -73,7 +74,7 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out ) { const StopSegment &fs = out.m_Timing.m_StopSegments[i]; - f.PutLine( ssprintf( "%.3f=%.3f", fs.m_fStartBeat, fs.m_fStopSeconds ) ); + f.PutLine( ssprintf( "%.3f=%.3f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) ); if( i != out.m_Timing.m_StopSegments.size()-1 ) f.Write( "," ); } diff --git a/stepmania/src/ScreenEdit.cpp b/stepmania/src/ScreenEdit.cpp index 9f9ca98db4..bab647ce86 100644 --- a/stepmania/src/ScreenEdit.cpp +++ b/stepmania/src/ScreenEdit.cpp @@ -1190,7 +1190,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) + if( m_pSong->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) break; } @@ -1198,7 +1198,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ { // create a new StopSegment if( fStopDelta > 0 ) - m_pSong->AddStopSegment( StopSegment(GAMESTATE->m_fSongBeat, fStopDelta) ); + m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(GAMESTATE->m_fSongBeat), fStopDelta) ); } else // StopSegment being modified is m_Timing.m_StopSegments[i] { @@ -1801,7 +1801,8 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, int* iAnswers ) unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) + // XXX + if( m_pSong->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) break; } if ( i == m_pSong->m_Timing.m_StopSegments.size() ) @@ -2071,7 +2072,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) float fDeltaBeats = fNewClipboardBeats - fOldClipboardBeats; float fNewClipboardEndBeat = m_NoteFieldEdit.m_fBeginMarker + fNewClipboardBeats; NoteDataUtil::ShiftRows( m_NoteDataEdit, BeatToNoteRow(m_NoteFieldEdit.m_fBeginMarker), BeatToNoteRow(fDeltaBeats) ); - m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_fBeginMarker, m_NoteFieldEdit.m_fEndMarker ); + m_pSong->m_Timing.ScaleRegion( fScale, BeatToNoteRow(m_NoteFieldEdit.m_fBeginMarker), BeatToNoteRow(m_NoteFieldEdit.m_fEndMarker) ); HandleAreaMenuChoice( paste_at_begin_marker, NULL ); @@ -2199,10 +2200,10 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) NoteDataUtil::ShiftRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(-1) ); break; case shift_pauses_forward: - m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat, 1 ); + m_pSong->m_Timing.ShiftRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(+1) ); break; case shift_pauses_backward: - m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat, -1 ); + m_pSong->m_Timing.ShiftRows( BeatToNoteRow(GAMESTATE->m_fSongBeat), BeatToNoteRow(-1) ); break; // MD 11/02/03 - Converting selected region to a pause of the same length. case convert_beat_to_pause: @@ -2218,26 +2219,26 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) BeatToNoteRow(m_NoteFieldEdit.m_fBeginMarker) + 1, BeatToNoteRow(-m_NoteFieldEdit.m_fEndMarker+m_NoteFieldEdit.m_fBeginMarker) ); - m_pSong->m_Timing.ShiftRows( m_NoteFieldEdit.m_fBeginMarker + 0.003f, - (-m_NoteFieldEdit.m_fEndMarker+m_NoteFieldEdit.m_fBeginMarker) + m_pSong->m_Timing.ShiftRows( BeatToNoteRow(m_NoteFieldEdit.m_fBeginMarker) + 1, + BeatToNoteRow(-m_NoteFieldEdit.m_fEndMarker+m_NoteFieldEdit.m_fBeginMarker) ); unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - float fStart = m_pSong->m_Timing.GetElapsedTimeFromBeat(m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat); + float fStart = m_pSong->m_Timing.GetElapsedTimeFromBeat(NoteRowToBeat(m_pSong->m_Timing.m_StopSegments[i].m_iStartRow)); float fEnd = fStart + m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds; if( fStart > fMarkerEnd || fEnd < fMarkerStart ) continue; else { - if (fStart > fMarkerStart) - m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat = m_NoteFieldEdit.m_fBeginMarker; + if( fStart > fMarkerStart ) + m_pSong->m_Timing.m_StopSegments[i].m_iStartRow = BeatToNoteRow(m_NoteFieldEdit.m_fBeginMarker); m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds = fStopLength; break; } } if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no BPMSegment at the current beat - m_pSong->AddStopSegment( StopSegment(m_NoteFieldEdit.m_fBeginMarker, fStopLength) ); + m_pSong->AddStopSegment( StopSegment(BeatToNoteRow(m_NoteFieldEdit.m_fBeginMarker), fStopLength) ); m_NoteFieldEdit.m_fEndMarker = -1; break; } @@ -2255,7 +2256,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) unsigned i; for( i=0; im_Timing.m_StopSegments.size(); i++ ) { - if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat ) + if( m_pSong->m_Timing.m_StopSegments[i].m_iStartRow == BeatToNoteRow(GAMESTATE->m_fSongBeat) ) break; } @@ -2271,7 +2272,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers ) // don't move the step from where it is, just move everything later m_NoteDataEdit.ConvertHoldNotesTo2sAnd3s(); NoteDataUtil::ShiftRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopLength) ); - m_pSong->m_Timing.ShiftRows( GAMESTATE->m_fSongBeat + 0.003f, fStopLength ); + m_pSong->m_Timing.ShiftRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopLength) ); m_NoteDataEdit.Convert2sAnd3sToHoldNotes(); } diff --git a/stepmania/src/ScreenGameplay.cpp b/stepmania/src/ScreenGameplay.cpp index 8906418508..ba7505bc14 100644 --- a/stepmania/src/ScreenGameplay.cpp +++ b/stepmania/src/ScreenGameplay.cpp @@ -1829,9 +1829,9 @@ void ScreenGameplay::Input( const DeviceInput& DeviceI, const InputEventType typ fOffsetDelta *= 10; BPMSegment& seg = GAMESTATE->m_pCurSong->GetBPMSegmentAtBeat( GAMESTATE->m_fSongBeat ); - seg.m_fBPM += fOffsetDelta; + seg.m_iBPS += BeatToNoteRow(fOffsetDelta); - m_textDebug.SetText( ssprintf("Cur BPM = %.2f", seg.m_fBPM) ); + m_textDebug.SetText( ssprintf("Cur BPM = %.2f", seg.GetBPM()) ); m_textDebug.StopTweening(); m_textDebug.SetDiffuse( RageColor(1,1,1,1) ); m_textDebug.BeginTweening( 3 ); // sleep diff --git a/stepmania/src/Song.cpp b/stepmania/src/Song.cpp index c4389e2b79..0636e63fb2 100644 --- a/stepmania/src/Song.cpp +++ b/stepmania/src/Song.cpp @@ -524,8 +524,8 @@ void Song::TidyUpData() } /* Make sure the first BPM segment starts at beat 0. */ - if( m_Timing.m_BPMSegments[0].m_fStartBeat != 0 ) - m_Timing.m_BPMSegments[0].m_fStartBeat = 0; + if( m_Timing.m_BPMSegments[0].m_iStartIndex != 0 ) + m_Timing.m_BPMSegments[0].m_iStartIndex = 0; if( m_fMusicSampleStartSeconds == -1 || diff --git a/stepmania/src/TimingData.cpp b/stepmania/src/TimingData.cpp index 1fc813f704..7b58a310ab 100644 --- a/stepmania/src/TimingData.cpp +++ b/stepmania/src/TimingData.cpp @@ -3,6 +3,17 @@ #include "PrefsManager.h" #include "RageUtil.h" #include "RageLog.h" +#include "NoteTypes.h" + +void BPMSegment::SetBPM( float f ) +{ + m_iBPS = BeatToNoteRow( f / 60.0f ); +} + +float BPMSegment::GetBPM() const +{ + return NoteRowToBeat(m_iBPS * 60); +} TimingData::TimingData() { @@ -11,7 +22,7 @@ TimingData::TimingData() static int CompareBPMSegments(const BPMSegment &seg1, const BPMSegment &seg2) { - return seg1.m_fStartBeat < seg2.m_fStartBeat; + return seg1.m_iStartIndex < seg2.m_iStartIndex; } void SortBPMSegmentsArray( vector &arrayBPMSegments ) @@ -21,7 +32,7 @@ void SortBPMSegmentsArray( vector &arrayBPMSegments ) static int CompareStopSegments(const StopSegment &seg1, const StopSegment &seg2) { - return seg1.m_fStartBeat < seg2.m_fStartBeat; + return seg1.m_iStartRow < seg2.m_iStartRow; } void SortStopSegmentsArray( vector &arrayStopSegments ) @@ -31,14 +42,16 @@ void SortStopSegmentsArray( vector &arrayStopSegments ) void TimingData::GetActualBPM( float &fMinBPMOut, float &fMaxBPMOut ) const { - fMaxBPMOut = 0; - fMinBPMOut = 100000; // inf + int iMinBPS = MAX_NOTE_ROW; + int iMaxBPS = 0; for( unsigned i=0; i= fBeat ) + if( m_BPMSegments[i].m_iStartIndex >= iNoteRow ) break; - if( i == m_BPMSegments.size() || - fabsf(m_BPMSegments[i].m_fStartBeat-fBeat) > 0.001f ) + if( i == m_BPMSegments.size() || m_BPMSegments[i].m_iStartIndex == iNoteRow ) { // There is no BPMSegment at the specified beat. If the BPM being set differs // from the last BPMSegment's BPM, create a new BPMSegment. - if( i == 0 || fabsf(m_BPMSegments[i-1].m_fBPM - fBPM) > 0.009f ) - AddBPMSegment( BPMSegment(fBeat, fBPM) ); + if( i == 0 || m_BPMSegments[i-1].m_iBPS != iBPS ) + AddBPMSegment( BPMSegment(iNoteRow, iBPS) ); } else // BPMSegment being modified is m_BPMSegments[i] { - if( i > 0 && fabsf(m_BPMSegments[i-1].m_fBPM - fBPM) < 0.009f ) + if( i > 0 && m_BPMSegments[i-1].m_iBPS == iBPS ) m_BPMSegments.erase( m_BPMSegments.begin()+i, m_BPMSegments.begin()+i+1); else - m_BPMSegments[i].m_fBPM = fBPM; + m_BPMSegments[i].m_iBPS = iBPS; } } void TimingData::SetStopAtBeat( float fBeat, float fSeconds ) { + int iRow = BeatToNoteRow( fBeat ); unsigned i; for( i=0; i 0 ) - AddStopSegment( StopSegment(fBeat, fSeconds) ); + AddStopSegment( StopSegment(iRow, fSeconds) ); } else // StopSegment being modified is m_StopSegments[i] { @@ -103,37 +118,60 @@ void TimingData::SetStopAtBeat( float fBeat, float fSeconds ) } /* Multiply the BPM in the range [fStartBeat,fEndBeat) by fFactor. */ -void TimingData::MultiplyBPMInBeatRange( float fStartBeat, float fEndBeat, float fFactor ) +void TimingData::MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ) { - /* Record the BPM at fEndBeat, so we can make sure it doesn't change. */ - float fEndBPM = GetBPMAtBeat( fEndBeat ); - - /* Set the first beat. */ - SetBPMAtBeat( fStartBeat, GetBPMAtBeat(fStartBeat) * fFactor ); - /* Change all other BPM segments in this range. */ for( unsigned i=0; i fStartBeat && m_BPMSegments[i].m_fStartBeat < fEndBeat ) - m_BPMSegments[i].m_fBPM *= fFactor; + { + const int iStartIndexThisSegment = m_BPMSegments[i].m_iStartIndex; + const bool bIsLastBPMSegment = i==m_BPMSegments.size()-1; + const int iStartIndexNextSegment = bIsLastBPMSegment ? 40000/*inf*/ : m_BPMSegments[i+1].m_iStartIndex; - /* Don't change the BPM at the end of the range. */ - SetBPMAtBeat( fEndBeat, fEndBPM ); + if( iStartIndexThisSegment <= iStartIndex && iStartIndexNextSegment <= iStartIndex ) + continue; + + /* If this BPM segment crosses the beginning of the range, split it into two. */ + if( iStartIndexThisSegment < iStartIndex && iStartIndexNextSegment > iStartIndex ) + { + BPMSegment b = m_BPMSegments[i]; + b.m_iStartIndex = iStartIndexNextSegment; + m_BPMSegments.insert( m_BPMSegments.begin()+i+1, b ); + + /* Don't apply the BPM change to the first half of the segment we just split, + * since it lies outside the range. */ + continue; + } + + /* If this BPM segment crosses the end of the range, split it into two. */ + if( iStartIndexThisSegment < iEndIndex && iStartIndexNextSegment > iEndIndex ) + { + BPMSegment b = m_BPMSegments[i]; + b.m_iStartIndex = iEndIndex; + m_BPMSegments.insert( m_BPMSegments.begin()+i+1, b ); + } + else if( iStartIndexNextSegment > iEndIndex ) + continue; + + m_BPMSegments[i].m_iBPS = lrintf( m_BPMSegments[i].m_iBPS * fFactor ); + } } float TimingData::GetBPMAtBeat( float fBeat ) const { + int iIndex = BeatToNoteRow( fBeat ); unsigned i; for( i=0; i fBeat ) + if( m_BPMSegments[i+1].m_iStartIndex > iIndex ) break; - return m_BPMSegments[i].m_fBPM; + return m_BPMSegments[i].GetBPM(); } BPMSegment& TimingData::GetBPMSegmentAtBeat( float fBeat ) { + int iIndex = BeatToNoteRow( fBeat ); unsigned i; for( i=0; i fBeat ) + if( m_BPMSegments[i+1].m_iStartIndex > iIndex ) break; return m_BPMSegments[i]; } @@ -150,21 +188,25 @@ void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatO for( unsigned i=0; i= m_StopSegments[j].m_fStartBeat ) + if( !bIsFirstBPMSegment && iStartRowThisSegment >= m_StopSegments[j].m_iStartRow ) continue; - if( !bIsLastBPMSegment && m_StopSegments[j].m_fStartBeat > fStartBeatNextSegment ) + if( !bIsLastBPMSegment && m_StopSegments[j].m_iStartRow > iStartRowNextSegment ) continue; // this freeze lies within this BPMSegment - const float fBeatsSinceStartOfSegment = m_StopSegments[j].m_fStartBeat - fStartBeatThisSegment; + const int iRowsBeatsSinceStartOfSegment = m_StopSegments[j].m_iStartRow - iStartRowThisSegment; + const float fBeatsSinceStartOfSegment = NoteRowToBeat(iRowsBeatsSinceStartOfSegment); const float fFreezeStartSecond = fBeatsSinceStartOfSegment / fBPS; if( fFreezeStartSecond >= fElapsedTime ) @@ -176,7 +218,7 @@ void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatO if( fFreezeStartSecond >= fElapsedTime ) { /* The time lies within the stop. */ - fBeatOut = m_StopSegments[j].m_fStartBeat; + fBeatOut = NoteRowToBeat(m_StopSegments[j].m_iStartRow); fBPSOut = fBPS; bFreezeOut = true; return; @@ -206,10 +248,11 @@ float TimingData::GetElapsedTimeFromBeat( float fBeat ) const fElapsedTime -= PREFSMAN->m_fGlobalOffsetSeconds; fElapsedTime -= m_fBeat0OffsetInSeconds; + int iRow = BeatToNoteRow(fBeat); for( unsigned j=0; j=, not >. */ - if( m_StopSegments[j].m_fStartBeat >= fBeat ) + if( m_StopSegments[j].m_iStartRow >= iRow ) break; fElapsedTime += m_StopSegments[j].m_fStopSeconds; } @@ -217,7 +260,7 @@ float TimingData::GetElapsedTimeFromBeat( float fBeat ) const for( unsigned i=0; i 0 ); - ASSERT( fStartBeat >= 0 ); - ASSERT( fStartBeat < fEndBeat ); + ASSERT( iStartIndex >= 0 ); + ASSERT( iStartIndex < iEndIndex ); unsigned ix = 0; for ( ix = 0; ix < m_BPMSegments.size(); ix++ ) { - const float fSegStart = m_BPMSegments[ix].m_fStartBeat; - if( fSegStart < fStartBeat ) + const int iSegStart = m_BPMSegments[ix].m_iStartIndex; + if( iSegStart < iStartIndex ) continue; - else if( fSegStart > fEndBeat ) - m_BPMSegments[ix].m_fStartBeat += (fEndBeat - fStartBeat) * (fScale - 1); + else if( iSegStart > iEndIndex ) + m_BPMSegments[ix].m_iStartIndex += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) ); else - m_BPMSegments[ix].m_fStartBeat = (fSegStart - fStartBeat) * fScale + fStartBeat; + m_BPMSegments[ix].m_iStartIndex = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex; } for( ix = 0; ix < m_StopSegments.size(); ix++ ) { - const float fSegStart = m_StopSegments[ix].m_fStartBeat; - if( fSegStart < fStartBeat ) + const int iSegStartRow = m_StopSegments[ix].m_iStartRow; + if( iSegStartRow < iStartIndex ) continue; - else if( fSegStart > fEndBeat ) - m_StopSegments[ix].m_fStartBeat += (fEndBeat - fStartBeat) * (fScale - 1); + else if( iSegStartRow > iEndIndex ) + m_StopSegments[ix].m_iStartRow += lrintf((iEndIndex - iStartIndex) * (fScale - 1)); else - m_StopSegments[ix].m_fStartBeat = (fSegStart - fStartBeat) * fScale + fStartBeat; + m_StopSegments[ix].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; } } -void TimingData::ShiftRows( float fStartBeat, float fBeatsToShift ) +void TimingData::ShiftRows( int iStartRow, int iRowsToShift ) { unsigned ix = 0; for( ix = 0; ix < m_BPMSegments.size(); ix++ ) { - float &fSegStart = m_BPMSegments[ix].m_fStartBeat; - if( fSegStart < fStartBeat ) + int &iSegStart = m_BPMSegments[ix].m_iStartIndex; + if( iSegStart < iStartRow ) continue; - fSegStart += fBeatsToShift; - fSegStart = max( fSegStart, fStartBeat ); + iSegStart += iRowsToShift; + iSegStart = max( iSegStart, iStartRow ); } for( ix = 0; ix < m_StopSegments.size(); ix++ ) { - float &fSegStart = m_StopSegments[ix].m_fStartBeat; - if( fSegStart < fStartBeat ) + int &iSegStartRow = m_StopSegments[ix].m_iStartRow; + if( iSegStartRow < iStartRow ) continue; - fSegStart += fBeatsToShift; - fSegStart = max( fSegStart, fStartBeat ); + iSegStartRow += iRowsToShift; + iSegStartRow = max( iSegStartRow, iStartRow ); } } diff --git a/stepmania/src/TimingData.h b/stepmania/src/TimingData.h index b6232bac6d..efe657df74 100644 --- a/stepmania/src/TimingData.h +++ b/stepmania/src/TimingData.h @@ -3,19 +3,24 @@ #ifndef TIMING_DATA_H #define TIMING_DATA_H +#include "NoteTypes.h" + struct BPMSegment { - BPMSegment() { m_fStartBeat = m_fBPM = -1; }; - BPMSegment( float s, float b ) { m_fStartBeat = s; m_fBPM = b; }; - float m_fStartBeat; - float m_fBPM; + BPMSegment() { m_iStartIndex = -1; m_iBPS = -1; } + BPMSegment( int s, int b ) { m_iStartIndex = s; m_iBPS = b; } + int m_iStartIndex; + int m_iBPS; /* rows per second */ + + void SetBPM( float f ); + float GetBPM() const; }; struct StopSegment { - StopSegment() { m_fStartBeat = m_fStopSeconds = -1; }; - StopSegment( float s, float f ) { m_fStartBeat = s; m_fStopSeconds = f; }; - float m_fStartBeat; + StopSegment() { m_fStopSeconds = -1; m_iStartRow = -1; } + StopSegment( int s, float f ) { m_iStartRow = s; m_fStopSeconds = f; } + int m_iStartRow; float m_fStopSeconds; }; @@ -28,7 +33,7 @@ public: float GetBPMAtBeat( float fBeat ) const; void SetBPMAtBeat( float fBeat, float fBPM ); void SetStopAtBeat( float fBeat, float fSeconds ); - void MultiplyBPMInBeatRange( float fStartBeat, float fEndBeat, float fFactor ); + void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor ); void AddBPMSegment( const BPMSegment &seg ); void AddStopSegment( const StopSegment &seg ); BPMSegment& GetBPMSegmentAtBeat( float fBeat ); @@ -54,8 +59,8 @@ public: // of the range that was deleted (say if rows 1680-1728 are deleted, and // a BPM change or a stop occurs at row 1704, we'll move it to row // 1680). - void ScaleRegion( float fScale = 1, float fStartBeat = 0, float fEndBeat = 99999 ); - void ShiftRows( float fStartBeat, float fBeatsToShift ); + void ScaleRegion( float fScale = 1, int iStartRow = 0, int iEndRow = MAX_NOTE_ROW ); + void ShiftRows( int iStartRow, int iRowsToShift ); CString m_sFile; // informational only vector m_BPMSegments; // this must be sorted before gameplay