diff --git a/src/ScreenEdit.cpp b/src/ScreenEdit.cpp index 25952588cc..49c10825ec 100644 --- a/src/ScreenEdit.cpp +++ b/src/ScreenEdit.cpp @@ -3455,7 +3455,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns else NoteDataUtil::DeleteRows( m_NoteDataEdit, m_NoteFieldEdit.m_iBeginMarker, -iDeltaRows ); - m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker ); + m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true ); HandleAreaMenuChoice( paste_at_begin_marker ); @@ -3479,12 +3479,6 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector &iAns } m_NoteFieldEdit.m_iEndMarker = iNewClipboardEndRow; - - float fPriorBPM = m_pSong->GetBPMAtBeat( NoteRowToBeat(iNewClipboardEndRow + 1) ); - float fOldBPM = m_pSong->GetBPMAtBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) ); - float fNewBPM = fOldBPM * fScale; - m_pSong->m_Timing.SetBPMAtRow( m_NoteFieldEdit.m_iBeginMarker, fNewBPM ); - m_pSong->m_Timing.SetBPMAtRow( iNewClipboardEndRow, fPriorBPM ); } break; case play: diff --git a/src/TimingData.cpp b/src/TimingData.cpp index d1ff6ce5c3..9704ac00c3 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -611,12 +611,12 @@ float TimingData::GetElapsedTimeFromBeatNoOffset( float fBeat ) const return fElapsedTime; } -void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex ) +void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool bAdjustBPM ) { ASSERT( fScale > 0 ); ASSERT( iStartIndex >= 0 ); ASSERT( iStartIndex < iEndIndex ); - + for ( unsigned i = 0; i < m_BPMSegments.size(); i++ ) { const int iSegStart = m_BPMSegments[i].m_iStartRow; @@ -638,6 +638,31 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex ) else m_StopSegments[i].m_iStartRow = lrintf((iSegStartRow - iStartIndex) * fScale) + iStartIndex; } + + // adjust BPM changes to preserve timing + if( bAdjustBPM ) + { + int iNewEndIndex = lrintf( (iEndIndex - iStartIndex) * fScale ) + iStartIndex; + float fEndBPMBeforeScaling = GetBPMAtRow(iNewEndIndex); + + // adjust BPM changes "between" iStartIndex and iNewEndIndex + for ( unsigned i = 0; i < m_BPMSegments.size(); i++ ) + { + const int iSegStart = m_BPMSegments[i].m_iStartRow; + if( iSegStart <= iStartIndex ) + continue; + else if( iSegStart >= iNewEndIndex ) + continue; + else + m_BPMSegments[i].m_fBPS *= fScale; + } + + // set BPM at iStartIndex and iNewEndIndex. + SetBPMAtRow( iStartIndex, GetBPMAtRow(iStartIndex) * fScale ); + SetBPMAtRow( iNewEndIndex, fEndBPMBeforeScaling ); + + } + } void TimingData::InsertRows( int iStartRow, int iRowsToAdd ) diff --git a/src/TimingData.h b/src/TimingData.h index d15703b7d5..655a9087fb 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -1073,7 +1073,7 @@ public: */ bool operator!=( const TimingData &other ) { return !operator==(other); } - void ScaleRegion( float fScale = 1, int iStartRow = 0, int iEndRow = MAX_NOTE_ROW ); + void ScaleRegion( float fScale = 1, int iStartRow = 0, int iEndRow = MAX_NOTE_ROW, bool bAdjustBPM = false ); void InsertRows( int iStartRow, int iRowsToAdd ); void DeleteRows( int iStartRow, int iRowsToDelete );