TimingData

This commit is contained in:
Glenn Maynard
2003-12-18 04:48:26 +00:00
parent c4b9fb2f03
commit c1462d88f5
16 changed files with 165 additions and 395 deletions
+2 -2
View File
@@ -343,9 +343,9 @@ void Background::LoadFromSong( Song* pSong )
}
// change BG every BPM change that is at the beginning of a measure
for( unsigned i=0; i<pSong->m_BPMSegments.size(); i++ )
for( unsigned i=0; i<pSong->m_Timing.m_BPMSegments.size(); i++ )
{
const BPMSegment& bpmseg = pSong->m_BPMSegments[i];
const BPMSegment& bpmseg = pSong->m_Timing.m_BPMSegments[i];
if( fmodf(bpmseg.m_fStartBeat, (float)BEATS_PER_MEASURE) != 0 )
continue; // skip
+1 -1
View File
@@ -65,7 +65,7 @@ NotesLoaderSM.cpp NotesLoaderSM.h NotesWriterDWI.cpp NotesWriterDWI.h NotesWrite
PlayerAI.cpp PlayerAI.h PlayerNumber.cpp PlayerNumber.h PlayerOptions.cpp PlayerOptions.h RandomSample.cpp RandomSample.h \
ScoreKeeper.h ScoreKeeperMAX2.cpp ScoreKeeperMAX2.h ScoreKeeperRave.cpp ScoreKeeperRave.h \
Song.cpp song.h SongCacheIndex.cpp SongCacheIndex.h SongOptions.cpp SongOptions.h StageStats.cpp StageStats.h Steps.cpp Steps.h \
Style.h StyleDef.cpp StyleDef.h StyleInput.h TitleSubstitution.cpp TitleSubstitution.h
Style.h StyleDef.cpp StyleDef.h StyleInput.h TimingData.cpp TimingData.h TitleSubstitution.cpp TitleSubstitution.h
FileTypes = IniFile.cpp IniFile.h MsdFile.cpp MsdFile.h
+2 -2
View File
@@ -441,7 +441,7 @@ void NoteField::DrawPrimitives()
//
// BPM text
//
vector<BPMSegment> &aBPMSegments = GAMESTATE->m_pCurSong->m_BPMSegments;
vector<BPMSegment> &aBPMSegments = GAMESTATE->m_pCurSong->m_Timing.m_BPMSegments;
for( i=0; i<aBPMSegments.size(); i++ )
{
if(aBPMSegments[i].m_fStartBeat >= fFirstBeatToDraw &&
@@ -451,7 +451,7 @@ void NoteField::DrawPrimitives()
//
// Freeze text
//
vector<StopSegment> &aStopSegments = GAMESTATE->m_pCurSong->m_StopSegments;
vector<StopSegment> &aStopSegments = GAMESTATE->m_pCurSong->m_Timing.m_StopSegments;
for( i=0; i<aStopSegments.size(); i++ )
{
if(aStopSegments[i].m_fStartBeat >= fFirstBeatToDraw &&
+9 -9
View File
@@ -541,8 +541,8 @@ bool BMSLoader::LoadFromDir( CString sDir, Song &out )
if( fBeatOffset > 10 ) // some BPMs's play the music again at the end. Why? Who knows...
break;
float fBPS;
fBPS = out.m_BPMSegments[0].m_fBPM/60.0f;
out.m_fBeat0OffsetInSeconds = fBeatOffset / fBPS;
fBPS = out.m_Timing.m_BPMSegments[0].m_fBPM/60.0f;
out.m_Timing.m_fBeat0OffsetInSeconds = fBeatOffset / fBPS;
break;
}
case 3: { // bpm change
@@ -659,18 +659,18 @@ bool BMSLoader::LoadFromDir( CString sDir, Song &out )
{
// find the BPM at the time of this freeze
float fBPM = -1;
for( unsigned i=0; i<out.m_BPMSegments.size()-1; i++ )
for( unsigned i=0; i<out.m_Timing.m_BPMSegments.size()-1; i++ )
{
if( out.m_BPMSegments[i].m_fStartBeat <= fFreezeStartBeat &&
out.m_BPMSegments[i+1].m_fStartBeat > fFreezeStartBeat )
if( out.m_Timing.m_BPMSegments[i].m_fStartBeat <= fFreezeStartBeat &&
out.m_Timing.m_BPMSegments[i+1].m_fStartBeat > fFreezeStartBeat )
{
fBPM = out.m_BPMSegments[i].m_fBPM;
fBPM = out.m_Timing.m_BPMSegments[i].m_fBPM;
break;
}
}
// the BPM segment of this beat is the last BPM segment
if( fBPM == -1 )
fBPM = out.m_BPMSegments[out.m_BPMSegments.size()-1].m_fBPM;
fBPM = out.m_Timing.m_BPMSegments[out.m_Timing.m_BPMSegments.size()-1].m_fBPM;
fFreezeSecs = (float)atof(value_data)/(fBPM*0.81f); // I have no idea what units these are in, so I experimented until finding this factor.
break;
@@ -695,9 +695,9 @@ bool BMSLoader::LoadFromDir( CString sDir, Song &out )
}
}
for( i=0; i<out.m_BPMSegments.size(); i++ )
for( i=0; i<out.m_Timing.m_BPMSegments.size(); i++ )
LOG->Trace( "There is a BPM change at beat %f, BPM %f, index %d",
out.m_BPMSegments[i].m_fStartBeat, out.m_BPMSegments[i].m_fBPM, i );
out.m_Timing.m_BPMSegments[i].m_fStartBeat, out.m_Timing.m_BPMSegments[i].m_fBPM, i );
return true;
}
+1 -1
View File
@@ -390,7 +390,7 @@ bool DWILoader::LoadFromDWIFile( CString sPath, Song &out )
else if( 0==stricmp(sValueName,"GAP") )
// the units of GAP is 1/1000 second
out.m_fBeat0OffsetInSeconds = -atoi( sParams[1] ) / 1000.0f;
out.m_Timing.m_fBeat0OffsetInSeconds = -atoi( sParams[1] ) / 1000.0f;
else if( 0==stricmp(sValueName,"SAMPLESTART") )
out.m_fMusicSampleStartSeconds = ParseBrokenDWITimestamp(sParams[1], sParams[2], sParams[3]);
+10 -10
View File
@@ -14,19 +14,19 @@
void KSFLoader::RemoveHoles( NoteData &out, const Song &song )
{
/* Start at the second BPM segment; the first one is already aligned. */
for( unsigned seg = 1; seg < song.m_BPMSegments.size(); ++seg )
for( unsigned seg = 1; seg < song.m_Timing.m_BPMSegments.size(); ++seg )
{
// const float FromBeat = song.m_BPMSegments[seg].m_fStartBeat;
const float FromBeat = song.m_BPMSegments[seg].m_fStartBeat * song.m_BPMSegments[seg].m_fBPM / song.m_BPMSegments[0].m_fBPM;
// const float FromBeat = song.m_Timing.m_BPMSegments[seg].m_fStartBeat;
const float FromBeat = song.m_Timing.m_BPMSegments[seg].m_fStartBeat * song.m_BPMSegments[seg].m_fBPM / song.m_BPMSegments[0].m_fBPM;
const int FromRow = (int) BeatToNoteRow(FromBeat);
const int ToRow = (int) BeatToNoteRow(song.m_BPMSegments[seg].m_fStartBeat);
const int ToRow = (int) BeatToNoteRow(song.m_Timing.m_BPMSegments[seg].m_fStartBeat);
LOG->Trace("from %f (%i) to (%i)", FromBeat, FromRow, ToRow);
// const int ToRow = (int) roundf(FromRow * song.m_BPMSegments[0].m_fBPM / song.m_BPMSegments[seg].m_fBPM);
// const int ToRow = (int) roundf(FromRow * song.m_Timing.m_BPMSegments[0].m_fBPM / song.m_BPMSegments[seg].m_fBPM);
// const int Rows = out.GetLastRow() - FromRow + 1;
// int LastRow;
// if(seg+1 < song.m_BPMSegments().size())
// LastRow = (int) NoteRowToBeat( song.m_BPMSegments[seg+1].m_fStartBeat ) - 1;
// if(seg+1 < song.m_Timing.m_BPMSegments().size())
// LastRow = (int) NoteRowToBeat( song.m_Timing.m_BPMSegments[seg+1].m_fStartBeat ) - 1;
// else
// LastRow = out.GetLastRow();
NoteData tmp;
@@ -41,7 +41,7 @@ void KSFLoader::RemoveHoles( NoteData &out, const Song &song )
for( t = 0; t < notedata.GetNumTracks(); ++t )
{
const float CurBPM = song.GetBPMAtBeat( NoteRowToBeat(row) );
song.m_BPMSegments.size()
song.m_Timing.m_BPMSegments.size()
for( int row = 0; row <= notedata.GetLastRow(); ++row )
{
TapNote tn = notedata.GetTapNote(t, row);
@@ -204,7 +204,7 @@ bool KSFLoader::LoadFromKSFFile( const CString &sPath, Steps &out, const Song &s
}
/* We need to remove holes where the BPM increases. */
// if( song.m_BPMSegments.size() > 1 )
// if( song.m_Timing.m_BPMSegments.size() > 1 )
// RemoveHoles( notedata, song );
out.SetNoteData(&notedata);
@@ -287,7 +287,7 @@ bool KSFLoader::LoadGlobalData( const CString &sPath, Song &out )
else if( 0==stricmp(sValueName,"BUNKI2") )
BPMPos3 = float(atof(sParams[1])) / 100.0f;
else if( 0==stricmp(sValueName,"STARTTIME") )
out.m_fBeat0OffsetInSeconds = -(float)atof(sParams[1])/100;
out.m_Timing.m_fBeat0OffsetInSeconds = -(float)atof(sParams[1])/100;
else if( 0==stricmp(sValueName,"TICKCOUNT") ||
0==stricmp(sValueName,"STEP") ||
0==stricmp(sValueName,"DIFFICULTY"))
+3 -3
View File
@@ -62,8 +62,8 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
{
LOG->Trace( "Song::LoadFromSMFile(%s)", sPath.c_str() );
out.m_BPMSegments.clear();
out.m_StopSegments.clear();
out.m_Timing.m_BPMSegments.clear();
out.m_Timing.m_StopSegments.clear();
MsdFile msd;
bool bResult = msd.ReadFile( sPath );
@@ -165,7 +165,7 @@ bool SMLoader::LoadFromSMFile( CString sPath, Song &out )
}
else if( 0==stricmp(sValueName,"OFFSET") )
out.m_fBeat0OffsetInSeconds = (float)atof( sParams[1] );
out.m_Timing.m_fBeat0OffsetInSeconds = (float)atof( sParams[1] );
else if( 0==stricmp(sValueName,"SELECTABLE") )
{
+11 -11
View File
@@ -344,10 +344,10 @@ 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_BPMSegments[0].m_fStartBeat == 0 );
ASSERT( out.m_Timing.m_BPMSegments[0].m_fStartBeat == 0 );
f.PutLine( ssprintf("#FILE:%s;", out.m_sMusicFile.c_str()) );
f.PutLine( ssprintf("#BPM:%.3f;", out.m_BPMSegments[0].m_fBPM) );
f.PutLine( ssprintf("#GAP:%d;", int(-roundf( out.m_fBeat0OffsetInSeconds*1000 ))) );
f.PutLine( ssprintf("#BPM:%.3f;", out.m_Timing.m_BPMSegments[0].m_fBPM) );
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) );
if( out.m_sCDTitleFile.size() )
@@ -368,29 +368,29 @@ bool NotesWriterDWI::Write( CString sPath, const Song &out )
break;
}
if( !out.m_StopSegments.empty() )
if( !out.m_Timing.m_StopSegments.empty() )
{
f.Write( "#FREEZE:" );
for( unsigned i=0; i<out.m_StopSegments.size(); i++ )
for( unsigned i=0; i<out.m_Timing.m_StopSegments.size(); i++ )
{
const StopSegment &fs = out.m_StopSegments[i];
const StopSegment &fs = out.m_Timing.m_StopSegments[i];
f.Write( ssprintf("%.3f=%.3f", BeatToNoteRow( fs.m_fStartBeat ) * 4.0f / ROWS_PER_BEAT,
roundf(fs.m_fStopSeconds*1000)) );
if( i != out.m_StopSegments.size()-1 )
if( i != out.m_Timing.m_StopSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
}
if( out.m_BPMSegments.size() > 1)
if( out.m_Timing.m_BPMSegments.size() > 1)
{
f.Write( "#CHANGEBPM:" );
for( unsigned i=1; i<out.m_BPMSegments.size(); i++ )
for( unsigned i=1; i<out.m_Timing.m_BPMSegments.size(); i++ )
{
const BPMSegment &bs = out.m_BPMSegments[i];
const BPMSegment &bs = out.m_Timing.m_BPMSegments[i];
f.Write( ssprintf("%.3f=%.3f", BeatToNoteRow( bs.m_fStartBeat ) * 4.0f / ROWS_PER_BEAT, bs.m_fBPM ) );
if( i != out.m_BPMSegments.size()-1 )
if( i != out.m_Timing.m_BPMSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
+7 -7
View File
@@ -23,7 +23,7 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out )
f.PutLine( ssprintf( "#CDTITLE:%s;", out.m_sCDTitleFile.c_str() ) );
f.PutLine( ssprintf( "#MUSIC:%s;", out.m_sMusicFile.c_str() ) );
f.PutLine( ssprintf( "#MUSICLENGTH:%.3f;", out.m_fMusicLengthSeconds ) );
f.PutLine( ssprintf( "#OFFSET:%.3f;", out.m_fBeat0OffsetInSeconds ) );
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 ) );
@@ -58,23 +58,23 @@ void NotesWriterSM::WriteGlobalTags( RageFile &f, const Song &out )
f.Write( "#BPMS:" );
unsigned i;
for( i=0; i<out.m_BPMSegments.size(); i++ )
for( i=0; i<out.m_Timing.m_BPMSegments.size(); i++ )
{
const BPMSegment &bs = out.m_BPMSegments[i];
const BPMSegment &bs = out.m_Timing.m_BPMSegments[i];
f.Write( ssprintf( "%.3f=%.3f", bs.m_fStartBeat, bs.m_fBPM ) );
if( i != out.m_BPMSegments.size()-1 )
if( i != out.m_Timing.m_BPMSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
f.Write( "#STOPS:" );
for( i=0; i<out.m_StopSegments.size(); i++ )
for( i=0; i<out.m_Timing.m_StopSegments.size(); i++ )
{
const StopSegment &fs = out.m_StopSegments[i];
const StopSegment &fs = out.m_Timing.m_StopSegments[i];
f.PutLine( ssprintf( "%.3f=%.3f", fs.m_fStartBeat, fs.m_fStopSeconds ) );
if( i != out.m_StopSegments.size()-1 )
if( i != out.m_Timing.m_StopSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
+1 -1
View File
@@ -874,7 +874,7 @@ void PlayerMinus::HandleAutosync(float fNoteOffset)
const float stddev = calc_stddev(m_fOffset, m_fOffset+SAMPLE_COUNT);
if (stddev < .03 && stddev < fabsf(mean)) { //If they stepped with less than .03 error
GAMESTATE->m_pCurSong->m_fBeat0OffsetInSeconds += mean;
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += mean;
LOG->Trace("Offset corrected by %f. Error in steps: %f seconds.", mean, stddev);
} else
LOG->Trace("Offset NOT corrected. Average offset: %f seconds. Error: %f seconds.", mean, stddev);
+23 -23
View File
@@ -535,7 +535,7 @@ void ScreenEdit::UpdateTextInfo()
sText += ssprintf( "Sub title:\n %s\n", m_pSong->m_sSubTitle.c_str() );
sText += ssprintf( "Tap Steps:\n %d\n", iNumTapNotes );
sText += ssprintf( "Hold Steps:\n %d\n", iNumHoldNotes );
sText += ssprintf( "Beat 0 Offset:\n %.3f secs\n", m_pSong->m_fBeat0OffsetInSeconds );
sText += ssprintf( "Beat 0 Offset:\n %.3f secs\n", m_pSong->m_Timing.m_fBeat0OffsetInSeconds );
sText += ssprintf( "Preview Start:\n %.2f secs\n", m_pSong->m_fMusicSampleStartSeconds );
sText += ssprintf( "Preview Length:\n %.2f secs\n",m_pSong->m_fMusicSampleLengthSeconds );
@@ -973,24 +973,24 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
}
unsigned i;
for( i=0; i<m_pSong->m_StopSegments.size(); i++ )
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
{
if( m_pSong->m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat )
if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat )
break;
}
if( i == m_pSong->m_StopSegments.size() ) // there is no BPMSegment at the current beat
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no BPMSegment at the current beat
{
// create a new StopSegment
if( fStopDelta > 0 )
m_pSong->AddStopSegment( StopSegment(GAMESTATE->m_fSongBeat, fStopDelta) );
}
else // StopSegment being modified is m_StopSegments[i]
else // StopSegment being modified is m_Timing.m_StopSegments[i]
{
m_pSong->m_StopSegments[i].m_fStopSeconds += fStopDelta;
if( m_pSong->m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_StopSegments.erase( m_pSong->m_StopSegments.begin()+i,
m_pSong->m_StopSegments.begin()+i+1);
m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds += fStopDelta;
if( m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds <= 0 )
m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i,
m_pSong->m_Timing.m_StopSegments.begin()+i+1);
}
}
break;
@@ -1015,7 +1015,7 @@ void ScreenEdit::InputEdit( const DeviceInput& DeviceI, const InputEventType typ
case IET_FAST_REPEAT: fOffsetDelta *= 40; break;
}
m_pSong->m_fBeat0OffsetInSeconds += fOffsetDelta;
m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta;
}
break;
case SDLK_LEFTBRACKET:
@@ -1169,7 +1169,7 @@ void ScreenEdit::InputPlay( const DeviceInput& DeviceI, const InputEventType typ
case IET_FAST_REPEAT: fOffsetDelta *= 40; break;
}
m_pSong->m_fBeat0OffsetInSeconds += fOffsetDelta;
m_pSong->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta;
}
break;
}
@@ -1724,19 +1724,19 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers )
(m_NoteFieldEdit.m_fEndMarker-m_NoteFieldEdit.m_fBeginMarker)
);
unsigned i;
for( i=0; i<m_pSong->m_StopSegments.size(); i++ )
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
{
if( m_pSong->m_StopSegments[i].m_fStartBeat == m_NoteFieldEdit.m_fBeginMarker )
if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == m_NoteFieldEdit.m_fBeginMarker )
break;
}
if( i == m_pSong->m_StopSegments.size() ) // there is no BPMSegment at the current beat
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no BPMSegment at the current beat
{
m_pSong->AddStopSegment( StopSegment(GAMESTATE->m_fSongBeat, fStopLength) );
}
else // StopSegment being extended is m_StopSegments[i]
else // StopSegment being extended is m_Timing.m_StopSegments[i]
{
m_pSong->m_StopSegments[i].m_fStopSeconds += fStopLength;
m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds += fStopLength;
}
m_NoteFieldEdit.m_fEndMarker = -1;
break;
@@ -1750,19 +1750,19 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, int* iAnswers )
{
float fBPMatPause = m_pSong->GetBPMAtBeat( GAMESTATE->m_fSongBeat );
unsigned i;
for( i=0; i<m_pSong->m_StopSegments.size(); i++ )
for( i=0; i<m_pSong->m_Timing.m_StopSegments.size(); i++ )
{
if( m_pSong->m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat )
if( m_pSong->m_Timing.m_StopSegments[i].m_fStartBeat == GAMESTATE->m_fSongBeat )
break;
}
if( i == m_pSong->m_StopSegments.size() ) // there is no BPMSegment at the current beat
if( i == m_pSong->m_Timing.m_StopSegments.size() ) // there is no BPMSegment at the current beat
break;
else // StopSegment being modified is m_StopSegments[i]
else // StopSegment being modified is m_Timing.m_StopSegments[i]
{
float fStopLength = m_pSong->m_StopSegments[i].m_fStopSeconds;
m_pSong->m_StopSegments.erase( m_pSong->m_StopSegments.begin()+i,
m_pSong->m_StopSegments.begin()+i+1);
float fStopLength = m_pSong->m_Timing.m_StopSegments[i].m_fStopSeconds;
m_pSong->m_Timing.m_StopSegments.erase( m_pSong->m_Timing.m_StopSegments.begin()+i,
m_pSong->m_Timing.m_StopSegments.begin()+i+1);
fStopLength /= fBPMatPause;
fStopLength *= 60;
// don't move the step from where it is, just move everything later
+6 -6
View File
@@ -257,7 +257,7 @@ ScreenGameplay::ScreenGameplay( CString sName, bool bDemonstration ) : Screen("S
if( GAMESTATE->IsCourseMode() )
g_fOldOffset = -1000;
else
g_fOldOffset = GAMESTATE->m_pCurSong->m_fBeat0OffsetInSeconds;
g_fOldOffset = GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds;
@@ -1512,9 +1512,9 @@ void ScreenGameplay::Input( const DeviceInput& DeviceI, const InputEventType typ
case IET_FAST_REPEAT: fOffsetDelta *= 40; break;
}
GAMESTATE->m_pCurSong->m_fBeat0OffsetInSeconds += fOffsetDelta;
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds += fOffsetDelta;
m_textDebug.SetText( ssprintf("Offset = %.3f", GAMESTATE->m_pCurSong->m_fBeat0OffsetInSeconds) );
m_textDebug.SetText( ssprintf("Offset = %.3f", GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds) );
m_textDebug.StopTweening();
m_textDebug.SetDiffuse( RageColor(1,1,1,1) );
m_textDebug.BeginTweening( 3 ); // sleep
@@ -1614,14 +1614,14 @@ void ScreenGameplay::ShowSavePrompt( ScreenMessage SM_SendWhenDone )
"%s\n",
GAMESTATE->m_pCurSong->GetFullDisplayTitle().c_str() );
if( fabs(GAMESTATE->m_pCurSong->m_fBeat0OffsetInSeconds - g_fOldOffset) > 0.001 )
if( fabs(GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds - g_fOldOffset) > 0.001 )
{
sMessage += ssprintf(
"\n"
"Offset was changed from %.3f to %.3f (%.3f).\n",
g_fOldOffset,
GAMESTATE->m_pCurSong->m_fBeat0OffsetInSeconds,
GAMESTATE->m_pCurSong->m_fBeat0OffsetInSeconds - g_fOldOffset );
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds,
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds - g_fOldOffset );
}
sMessage +=
+19 -200
View File
@@ -28,7 +28,6 @@
#include "TitleSubstitution.h"
#include "BannerCache.h"
#include "Sprite.h"
#include "PrefsManager.h"
#include "arch/arch.h"
#include "RageFile.h"
#include "NoteDataUtil.h"
@@ -54,25 +53,6 @@ const int FILE_CACHE_VERSION = 131; // increment this when Song or Steps changes
const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f;
static int CompareBPMSegments(const BPMSegment &seg1, const BPMSegment &seg2)
{
return seg1.m_fStartBeat < seg2.m_fStartBeat;
}
void SortBPMSegmentsArray( vector<BPMSegment> &arrayBPMSegments )
{
sort( arrayBPMSegments.begin(), arrayBPMSegments.end(), CompareBPMSegments );
}
static int CompareStopSegments(const StopSegment &seg1, const StopSegment &seg2)
{
return seg1.m_fStartBeat < seg2.m_fStartBeat;
}
void SortStopSegmentsArray( vector<StopSegment> &arrayStopSegments )
{
sort( arrayStopSegments.begin(), arrayStopSegments.end(), CompareStopSegments );
}
int CompareBackgroundChanges(const BackgroundChange &seg1, const BackgroundChange &seg2)
{
@@ -91,7 +71,6 @@ void SortBackgroundChangesArray( vector<BackgroundChange> &arrayBackgroundChange
Song::Song()
{
m_bChangedSinceSave = false;
m_fBeat0OffsetInSeconds = 0;
m_fMusicSampleStartSeconds = -1;
m_fMusicSampleLengthSeconds = DEFAULT_MUSIC_SAMPLE_LENGTH;
m_fMusicLengthSeconds = 0;
@@ -124,41 +103,6 @@ void Song::Reset()
}
void Song::AddBPMSegment( BPMSegment seg )
{
m_BPMSegments.push_back( seg );
SortBPMSegmentsArray( m_BPMSegments );
}
void Song::SetBPMAtBeat( float fBeat, float fBPM )
{
unsigned i;
for( i=0; i<m_BPMSegments.size(); i++ )
if( m_BPMSegments[i].m_fStartBeat == fBeat )
break;
if( i == m_BPMSegments.size() ) // there is no BPMSegment at the current beat
{
// create a new BPMSegment
AddBPMSegment( BPMSegment(fBeat, fBPM) );
}
else // BPMSegment being modified is m_BPMSegments[i]
{
if( i > 0 && fabsf(m_BPMSegments[i-1].m_fBPM - fBPM) < 0.009f )
m_BPMSegments.erase( m_BPMSegments.begin()+i,
m_BPMSegments.begin()+i+1);
else
m_BPMSegments[i].m_fBPM = fBPM;
}
}
void Song::AddStopSegment( StopSegment seg )
{
m_StopSegments.push_back( seg );
SortStopSegmentsArray( m_StopSegments );
}
void Song::AddBackgroundChange( BackgroundChange seg )
{
m_BackgroundChanges.push_back( seg );
@@ -171,152 +115,29 @@ void Song::AddLyricSegment( LyricSegment seg )
m_LyricSegments.push_back( seg );
}
float Song::GetMusicStartBeat() const
void Song::GetDisplayBPM( float &fMinBPMOut, float &fMaxBPMOut ) const
{
float fBPS = m_BPMSegments[0].m_fBPM / 60.0f;
return -(PREFSMAN->m_fGlobalOffsetSeconds+m_fBeat0OffsetInSeconds)*fBPS;
};
void Song::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut ) const
{
// LOG->Trace( "GetBeatAndBPSFromElapsedTime( fElapsedTime = %f )", fElapsedTime );
// This function is a nightmare. Don't even try to understand it. :-)
fElapsedTime += PREFSMAN->m_fGlobalOffsetSeconds;
fElapsedTime += m_fBeat0OffsetInSeconds;
for( unsigned i=0; i<m_BPMSegments.size(); i++ ) // foreach BPMSegment
if( m_DisplayBPMType == DISPLAY_SPECIFIED )
{
float fStartBeatThisSegment = m_BPMSegments[i].m_fStartBeat;
bool bIsLastBPMSegment = i==m_BPMSegments.size()-1;
float fStartBeatNextSegment = bIsLastBPMSegment ? 40000/*inf*/ : m_BPMSegments[i+1].m_fStartBeat;
float fBeatsInThisSegment = fStartBeatNextSegment - fStartBeatThisSegment;
float fBPM = m_BPMSegments[i].m_fBPM;
float fBPS = fBPM / 60.0f;
// calculate the number of seconds in this segment
float fSecondsInThisSegment = fBeatsInThisSegment / fBPS;
unsigned j;
for( j=0; j<m_StopSegments.size(); j++ ) // foreach freeze
{
if( fStartBeatThisSegment <= m_StopSegments[j].m_fStartBeat && m_StopSegments[j].m_fStartBeat < fStartBeatNextSegment )
{
// this freeze lies within this BPMSegment
fSecondsInThisSegment += m_StopSegments[j].m_fStopSeconds;
}
}
if( !bIsLastBPMSegment && fElapsedTime > fSecondsInThisSegment )
{
// this BPMSegement is NOT the current segment
fElapsedTime -= fSecondsInThisSegment;
continue;
}
// this BPMSegment IS the current segment
float fBeatEstimate = fStartBeatThisSegment + fElapsedTime*fBPS;
for( j=0; j<m_StopSegments.size(); j++ ) // foreach freeze
{
if( fStartBeatThisSegment > m_StopSegments[j].m_fStartBeat ||
m_StopSegments[j].m_fStartBeat > fStartBeatNextSegment )
continue;
// this freeze lies within this BPMSegment
if( m_StopSegments[j].m_fStartBeat > fBeatEstimate )
break;
fElapsedTime -= m_StopSegments[j].m_fStopSeconds;
// re-estimate
fBeatEstimate = fStartBeatThisSegment + fElapsedTime*fBPS;
if( fBeatEstimate < m_StopSegments[j].m_fStartBeat )
{
fBeatOut = m_StopSegments[j].m_fStartBeat;
fBPSOut = fBPS;
bFreezeOut = true;
return;
}
}
fBeatOut = fBeatEstimate;
fBPSOut = fBPS;
bFreezeOut = false;
return;
fMinBPMOut = m_fSpecifiedBPMMin;
fMaxBPMOut = m_fSpecifiedBPMMax;
}
else
{
m_Timing.GetActualBPM( fMinBPMOut, fMaxBPMOut );
}
}
float Song::GetElapsedTimeFromBeat( float fBeat ) const
CString Song::GetBackgroundAtBeat( float fBeat ) const
{
float fElapsedTime = 0;
fElapsedTime -= PREFSMAN->m_fGlobalOffsetSeconds;
fElapsedTime -= m_fBeat0OffsetInSeconds;
for( unsigned j=0; j<m_StopSegments.size(); j++ ) // foreach freeze
{
if( m_StopSegments[j].m_fStartBeat >= fBeat )
unsigned i;
for( i=0; i<m_BackgroundChanges.size()-1; i++ )
if( m_BackgroundChanges[i+1].m_fStartBeat > fBeat )
break;
fElapsedTime += m_StopSegments[j].m_fStopSeconds;
}
for( unsigned i=0; i<m_BPMSegments.size(); i++ ) // foreach BPMSegment
{
const float fStartBeatThisSegment = m_BPMSegments[i].m_fStartBeat;
const bool bIsLastBPMSegment = i==m_BPMSegments.size()-1;
const float fStartBeatNextSegment = bIsLastBPMSegment ? 40000/*inf*/ : m_BPMSegments[i+1].m_fStartBeat;
const float fBPS = m_BPMSegments[i].m_fBPM / 60.0f;
const float fBeatsInThisSegment = fStartBeatNextSegment - fStartBeatThisSegment;
fElapsedTime += min(fBeat, fBeatsInThisSegment) / fBPS;
fBeat -= fBeatsInThisSegment;
if( fBeat <= 0 )
return fElapsedTime;
}
ASSERT(0);
return fElapsedTime;
#if 0
// This is a super hack, but it's only called from ScreenEdit, so it's OK.
// Writing an inverse function of GetBeatAndBPSFromElapsedTime() uber difficult,
// so do a binary search to get close to the correct elapsed time.
float fElapsedTimeBestGuess = this->m_fMusicLengthSeconds/2; // seconds
float fSecondsToMove = fElapsedTimeBestGuess; // seconds
float fBeatOut, fBPSOut;
bool bFreezeOut;
/* 0.001 gives higher precision and takes about 7 more iterations than
* 0.100. A 90-second song took about 9 iterations; now it takes about
* 16. -glenn */
while( fSecondsToMove > 0.001f )
{
GetBeatAndBPSFromElapsedTime( fElapsedTimeBestGuess, fBeatOut, fBPSOut, bFreezeOut );
/* If this is an exact match, we're done. However, if we're on a
* freeze segment, keep moving backwards until we're off it, so we
* return the time associated with the beginning of the freeze segment
* and not some random place in its middle. */
if( fBeatOut == fBeat && !bFreezeOut)
break;
if( fBeatOut >= fBeat )
fElapsedTimeBestGuess -= fSecondsToMove;
else
fElapsedTimeBestGuess += fSecondsToMove;
fSecondsToMove /= 2;
}
return fElapsedTimeBestGuess;
#endif
return m_BackgroundChanges[i].m_sBGName;
}
CString Song::GetCacheFilePath() const
{
return ssprintf( CACHE_DIR "Songs/%u", GetHashForString(m_sSongDir) );
@@ -686,14 +507,14 @@ void Song::TidyUpData()
if( m_sArtist == "" ) m_sArtist = "Unknown artist";
TranslateTitles();
if( m_BPMSegments.empty() )
if( m_Timing.m_BPMSegments.empty() )
{
/* XXX: Once we have a way to display warnings that the user actually
* cares about (unlike most warnings), this should be one of them. */
LOG->Warn( "No BPM segments specified in '%s%s', default provided.",
m_sSongDir.c_str(), m_sSongFileName.c_str() );
AddBPMSegment( BPMSegment(0, 60) );
m_Timing.AddBPMSegment( BPMSegment(0, 60) );
}
/* Only automatically set the sample time if there was no sample length
@@ -977,12 +798,10 @@ void Song::ReCalculateRadarValuesAndLastBeat()
}
//
// calculate first/last beat
//
/* Many songs have stray, empty song patterns. Ignore them, so
/* Calculate first/last beat.
*
* Many songs have stray, empty song patterns. Ignore them, so
* they don't force the first beat of the whole song to 0. */
if(tempNoteData.GetLastRow() == 0)
continue;
+50 -39
View File
@@ -65,7 +65,7 @@ IntDir=.\../Debug6
TargetDir=\temp\stepmania\Program
TargetName=StepMania-debug
SOURCE="$(InputPath)"
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi
# End Special Build Tool
@@ -82,28 +82,24 @@ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
XBCP=xbecopy.exe
# ADD BASE XBCP /NOLOGO
# ADD XBCP /NOLOGO
XBE=imagebld.exe
# ADD BASE XBE /nologo /stack:0x10000 /debug
# ADD XBE /nologo /stack:0x10000 /debug /out:"../default.xbe"
LINK32=link.exe
# ADD BASE LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /subsystem:xbox /fixed:no /TMP
# ADD LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /nodefaultlib:"libcd" /nodefaultlib:"libcmt" /out:"../StepManiaXbox-debug.exe" /subsystem:xbox /fixed:no /TMP
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
CPP=cl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_XBOX" /D "_DEBUG" /YX /FD /G6 /Ztmp /c
# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /I "SDL_sound-1.0.0" /D "WIN32" /D "_XBOX" /D "_DEBUG" /D "OGG_ONLY" /YX /FD /G6 /Ztmp /c
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /subsystem:xbox /fixed:no /TMP
# ADD LINK32 xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /incremental:no /debug /machine:I386 /nodefaultlib:"libcd" /nodefaultlib:"libcmt" /out:"../StepManiaXbox-debug.exe" /subsystem:xbox /fixed:no /TMP
XBE=imagebld.exe
# ADD BASE XBE /nologo /stack:0x10000 /debug
# ADD XBE /nologo /stack:0x10000 /debug /out:"../default.xbe"
XBCP=xbecopy.exe
# ADD BASE XBCP /NOLOGO
# ADD XBCP /NOLOGO
# Begin Special Build Tool
IntDir=.\Debug
TargetDir=\stepmania\stepmania
TargetName=default
SOURCE="$(InputPath)"
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp \
/Fo$(IntDir)\
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp \
/Fo$(IntDir)\
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi
# End Special Build Tool
@@ -143,7 +139,7 @@ IntDir=.\../Release6
TargetDir=\temp\stepmania\Program
TargetName=StepMania
SOURCE="$(InputPath)"
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi
# End Special Build Tool
@@ -161,31 +157,27 @@ PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania
# PROP Intermediate_Dir "StepMania___Xbox_Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
XBCP=xbecopy.exe
# ADD BASE XBCP /NOLOGO
# ADD XBCP /NOLOGO
XBE=imagebld.exe
# ADD BASE XBE /nologo /stack:0x10000 /debug
# ADD XBE /nologo /testid:"123456" /stack:0x10000 /debug /out:"../default.xbe"
CPP=cl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /D "WIN32" /D "_XBOX" /D "_DEBUG" /Fr /YX"global.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /I "SDL_sound-1.0.0" /D "WIN32" /D "_XBOX" /D "NDEBUG" /YX"global.h" /FD /c
# SUBTRACT CPP /Fr
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 $(intdir)\verstub.obj xapilibd.lib d3d8d.lib d3dx8d.lib xgraphicsd.lib dsoundd.lib dmusicd.lib xnetd.lib xboxkrnl.lib /nologo /pdb:"../debug6/StepMania-debug.pdb" /map /debug /machine:IX86 /nodefaultlib:"libcmtd.lib" /out:"../StepMania-debug.exe"
# SUBTRACT BASE LINK32 /verbose /profile /pdb:none /incremental:no /nodefaultlib
# ADD LINK32 $(intdir)\verstub.obj xapilib.lib d3d8.lib d3dx8.lib xgraphics.lib dsound.lib dmusic.lib xnet.lib xboxkrnl.lib libcmt.lib /nologo /incremental:no /pdb:"../release6xbox/StepMania.pdb" /machine:I386 /nodefaultlib:"libc" /nodefaultlib:"libcmtd" /out:"../StepManiaXbox.exe" /subsystem:xbox /fixed:no /TMP /OPT:REF
# SUBTRACT LINK32 /pdb:none /map /debug
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
CPP=cl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /D "WIN32" /D "_XBOX" /D "_DEBUG" /Fr /YX"global.h" /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "SDL-1.2.5\include" /I "SDL_image-1.2" /I "plib-1.6.0" /I "SDL_sound-1.0.0" /D "WIN32" /D "_XBOX" /D "NDEBUG" /YX"global.h" /FD /c
# SUBTRACT CPP /Fr
XBE=imagebld.exe
# ADD BASE XBE /nologo /stack:0x10000 /debug
# ADD XBE /nologo /testid:"123456" /stack:0x10000 /debug /out:"../default.xbe"
XBCP=xbecopy.exe
# ADD BASE XBCP /NOLOGO
# ADD XBCP /NOLOGO
# Begin Special Build Tool
IntDir=.\StepMania___Xbox_Release
TargetDir=\stepmania\stepmania
TargetName=default
SOURCE="$(InputPath)"
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp \
/Fo$(IntDir)\
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp \
/Fo$(IntDir)\
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi
# End Special Build Tool
@@ -1812,6 +1804,25 @@ SOURCE=.\StyleInput.h
# End Source File
# Begin Source File
SOURCE=.\TimingData.cpp
!IF "$(CFG)" == "StepMania - Win32 Debug"
!ELSEIF "$(CFG)" == "StepMania - Xbox Debug"
!ELSEIF "$(CFG)" == "StepMania - Win32 Release"
!ELSEIF "$(CFG)" == "StepMania - Xbox Release"
!ENDIF
# End Source File
# Begin Source File
SOURCE=.\TimingData.h
# End Source File
# Begin Source File
SOURCE=.\TitleSubstitution.cpp
!IF "$(CFG)" == "StepMania - Win32 Debug"
+6
View File
@@ -764,6 +764,12 @@ cl /Zl /nologo /c verstub.cpp /Fo&quot;$(IntDir)&quot;\
<File
RelativePath="StyleInput.h">
</File>
<File
RelativePath="TimingData.cpp">
</File>
<File
RelativePath="TimingData.h">
</File>
<File
RelativePath="TitleSubstitution.cpp">
</File>
+14 -80
View File
@@ -14,6 +14,8 @@
#include "PlayerNumber.h"
#include "GameConstantsAndTypes.h"
#include "Grade.h"
#include "TimingData.h"
class Steps;
class StyleDef;
class NotesLoader;
@@ -23,22 +25,6 @@ class LyricsLoader;
extern const int FILE_CACHE_VERSION;
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;
};
struct StopSegment
{
StopSegment() { m_fStartBeat = m_fStopSeconds = -1; };
StopSegment( float s, float f ) { m_fStartBeat = s; m_fStopSeconds = f; };
float m_fStartBeat;
float m_fStopSeconds;
};
struct BackgroundChange
{
BackgroundChange() { m_fStartBeat=-1; m_fRate=1; m_bFadeLast=false; m_bRewindMovie=false; m_bLoop=true; };
@@ -134,7 +120,6 @@ public:
CString m_sCredit;
CString m_sMusicFile;
float m_fBeat0OffsetInSeconds;
float m_fMusicLengthSeconds;
float m_fFirstBeat;
float m_fLastBeat;
@@ -144,8 +129,6 @@ public:
float m_fSpecifiedBPMMin;
float m_fSpecifiedBPMMax; // if a range, then Min != Max
float GetMusicStartBeat() const;
CString m_sBannerFile;
CString m_sLyricsFile;
CString m_sBackgroundFile;
@@ -168,73 +151,24 @@ public:
bool Matches(CString sGroup, CString sSong) const;
vector<BPMSegment> m_BPMSegments; // this must be sorted before gameplay
vector<StopSegment> m_StopSegments; // this must be sorted before gameplay
TimingData m_Timing;
vector<BackgroundChange> m_BackgroundChanges; // this must be sorted before gameplay
vector<LyricSegment> m_LyricSegments; // same
void AddBPMSegment( BPMSegment seg );
void AddStopSegment( StopSegment seg );
void AddBPMSegment( const BPMSegment &seg ) { m_Timing.AddBPMSegment( seg ); }
void AddStopSegment( const StopSegment &seg ) { m_Timing.AddStopSegment( seg ); }
void AddBackgroundChange( BackgroundChange seg );
void AddLyricSegment( LyricSegment seg );
void GetDisplayBPM( float &fMinBPMOut, float &fMaxBPMOut ) const
{
if( m_DisplayBPMType == DISPLAY_SPECIFIED )
{
fMinBPMOut = m_fSpecifiedBPMMin;
fMaxBPMOut = m_fSpecifiedBPMMax;
}
else
{
GetActualBPM( fMinBPMOut, fMaxBPMOut );
}
}
void GetActualBPM( float &fMinBPMOut, float &fMaxBPMOut ) const
{
fMaxBPMOut = 0;
fMinBPMOut = 100000; // inf
for( unsigned i=0; i<m_BPMSegments.size(); i++ )
{
const BPMSegment &seg = m_BPMSegments[i];
fMaxBPMOut = max( seg.m_fBPM, fMaxBPMOut );
fMinBPMOut = min( seg.m_fBPM, fMinBPMOut );
}
}
float GetBPMAtBeat( float fBeat ) const
{
unsigned i;
for( i=0; i<m_BPMSegments.size()-1; i++ )
if( m_BPMSegments[i+1].m_fStartBeat > fBeat )
break;
return m_BPMSegments[i].m_fBPM;
}
void SetBPMAtBeat( float fBeat, float fBPM );
BPMSegment& GetBPMSegmentAtBeat( float fBeat )
{
unsigned i;
for( i=0; i<m_BPMSegments.size()-1; i++ )
if( m_BPMSegments[i+1].m_fStartBeat > fBeat )
break;
return m_BPMSegments[i];
};
CString GetBackgroundAtBeat( float fBeat )
{
unsigned i;
for( i=0; i<m_BackgroundChanges.size()-1; i++ )
if( m_BackgroundChanges[i+1].m_fStartBeat > fBeat )
break;
return m_BackgroundChanges[i].m_sBGName;
}
void GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut ) const;
float GetBeatFromElapsedTime( float fElapsedTime ) const // shortcut for places that care only about the beat
{
float fBeat, fThrowAway;
bool bThrowAway;
GetBeatAndBPSFromElapsedTime( fElapsedTime, fBeat, fThrowAway, bThrowAway );
return fBeat;
}
float GetElapsedTimeFromBeat( float fBeat ) const;
void GetDisplayBPM( float &fMinBPMOut, float &fMaxBPMOut ) const;
CString GetBackgroundAtBeat( float fBeat ) const;
float GetBPMAtBeat( float fBeat ) const { return m_Timing.GetBPMAtBeat( fBeat ); }
void SetBPMAtBeat( float fBeat, float fBPM ) { m_Timing.SetBPMAtBeat( fBeat, fBPM ); }
BPMSegment& GetBPMSegmentAtBeat( float fBeat ) { return m_Timing.GetBPMSegmentAtBeat( fBeat ); }
void GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut ) const { m_Timing.GetBeatAndBPSFromElapsedTime( fElapsedTime, fBeatOut, fBPSOut, bFreezeOut ); }
float GetBeatFromElapsedTime( float fElapsedTime ) const { return m_Timing.GetBeatFromElapsedTime( fElapsedTime ); }
float GetElapsedTimeFromBeat( float fBeat ) const { return m_Timing.GetElapsedTimeFromBeat( fBeat ); }