[splittiming] Rewritten to be more modular.

Guess I'll have some fun with this tonight.
This commit is contained in:
Jason Felds
2011-05-11 18:19:39 -04:00
parent 04d45bca1c
commit 68b391481d
+177 -78
View File
@@ -9,6 +9,51 @@
#include "Song.h"
#include "Steps.h"
static void HandleBunki( TimingData &timing, const float fEarlyBPM,
const float fCurBPM, const float fGap,
const float fPos )
{
const float BeatsPerSecond = fEarlyBPM / 60.0f;
const float beat = (fPos + fGap) * BeatsPerSecond;
LOG->Trace( "BPM %f, BPS %f, BPMPos %f, beat %f",
fEarlyBPM, BeatsPerSecond, fPos, beat );
timing.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), fCurBPM) );
}
static bool HandlePipeChars( TimingData &timing, const RString sNoteRow,
const float fCurBeat, int &iTickCount )
{
RString temp = sNoteRow.substr(2,sNoteRow.size()-3);
float numTemp = StringToFloat(temp);
if (BeginsWith(sNoteRow, "|T"))
{
iTickCount = static_cast<int>(numTemp);
timing.SetTickcountAtBeat( fCurBeat, clamp(iTickCount, 0, ROWS_PER_BEAT) );
return true;
}
else if (BeginsWith(sNoteRow, "|B"))
{
timing.SetBPMAtBeat( fCurBeat, numTemp );
return true;
}
else if (BeginsWith(sNoteRow, "|E"))
{
// Finally! the |E| tag is working as it should. I can die happy now -DaisuMaster
float fCurDelay = 60 / timing.GetBPMAtBeat(fCurBeat) * numTemp / iTickCount;
fCurDelay += timing.GetDelayAtRow(BeatToNoteRow(fCurBeat) );
timing.SetStopAtBeat( fCurBeat, fCurDelay, true );
return true;
}
else if (BeginsWith(sNoteRow, "|D"))
{
float fCurDelay = timing.GetStopAtRow(BeatToNoteRow(fCurBeat) );
fCurDelay += numTemp / 1000;
timing.SetStopAtBeat( fCurBeat, fCurDelay, true );
return true;
}
return false;
}
static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song, bool bKIUCompliant )
{
LOG->Trace( "Steps::LoadFromKSFFile( '%s' )", sPath.c_str() );
@@ -25,6 +70,9 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
// According to Aldo_MX, there is a default BPM and it's 60. -aj
bool bDoublesChart = false;
TimingData stepsTiming;
float SMGap1 = 0, SMGap2 = 0, BPM1 = -1, BPMPos2 = -1, BPM2 = -1, BPMPos3 = -1, BPM3 = -1;
for( unsigned i=0; i<msd.GetNumValues(); i++ )
{
@@ -32,8 +80,87 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
RString sValueName = sParams[0];
sValueName.MakeUpper();
// handle the data
if( sValueName=="TICKCOUNT" )
/* handle the data...well, not this data: not related to steps.
* Skips INTRO, MUSICINTRO, TITLEFILE, DISCFILE, SONGFILE. */
if (sValueName=="TITLE" || EndsWith(sValueName, "INTRO")
|| EndsWith(sValueName, "FILE") )
{
;
}
else if( sValueName=="BPM" )
{
BPM1 = StringToFloat(sParams[1]);
stepsTiming.AddBPMSegment( BPMSegment(0, BPM1) );
}
else if( sValueName=="BPM2" )
{
if (bKIUCompliant)
{
BPM2 = StringToFloat( sParams[1] );
}
else
{
// LOG an error.
}
}
else if( sValueName=="BPM3" )
{
if (bKIUCompliant)
{
BPM3 = StringToFloat( sParams[1] );
}
else
{
// LOG an error.
}
}
else if( sValueName=="BUNKI" )
{
if (bKIUCompliant)
{
BPMPos2 = StringToFloat( sParams[1] ) / 100.0f;
}
else
{
// LOG an error.
}
}
else if( sValueName=="BUNKI2" )
{
if (bKIUCompliant)
{
BPMPos3 = StringToFloat( sParams[1] ) / 100.0f;
}
else
{
// LOG an error.
}
}
else if( sValueName=="STARTTIME" )
{
SMGap1 = -StringToFloat( sParams[1] )/100;
stepsTiming.m_fBeat0OffsetInSeconds = SMGap1;
}
// This is currently required for more accurate KIU BPM changes.
else if( sValueName=="STARTTIME2" )
{
if (bKIUCompliant)
{
SMGap2 = -StringToFloat( sParams[1] )/100;
}
else
{
// LOG an error.
}
}
else if ( sValueName=="STARTTIME3" )
{
// STARTTIME3 only ensures this is a KIU compliant simfile.
bKIUCompliant = true;
}
else if( sValueName=="TICKCOUNT" )
{
iTickCount = StringToInt( sParams[1] );
if( iTickCount <= 0 )
@@ -43,12 +170,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
}
out.m_Timing.AddTickcountSegment(TickcountSegment(0, iTickCount));
}
else if( sValueName=="STEP" )
{
RString theSteps = sParams[1];
TrimLeft( theSteps );
split( theSteps, "\n", vNoteRows, true );
}
else if( sValueName=="DIFFICULTY" )
{
out.SetMeter( max(StringToInt(sParams[1]), 0) );
@@ -61,13 +183,34 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
if( sPlayer.find( "double" ) != string::npos )
bDoublesChart = true;
}
// This should always be last.
else if( sValueName=="STEP" )
{
RString theSteps = sParams[1];
TrimLeft( theSteps );
split( theSteps, "\n", vNoteRows, true );
}
}
if( iTickCount == -1 )
{
iTickCount = 2; // Direct Move 0.5 has a default value of 4... -aj
iTickCount = 4;
LOG->UserLog( "Song file", sPath, "doesn't have a TICKCOUNT. Defaulting to %i.", iTickCount );
}
// Prepare BPM stuff already if the file uses KSF syntax.
if( bKIUCompliant )
{
if( BPM2 > 0 && BPMPos2 > 0 )
{
HandleBunki( stepsTiming, BPM1, BPM2, SMGap1, BPMPos2 );
}
if( BPM3 > 0 && BPMPos3 > 0 )
{
HandleBunki( stepsTiming, BPM2, BPM3, SMGap2, BPMPos3 );
}
}
NoteData notedata; // read it into here
@@ -148,6 +291,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
int newTick = -1;
float fCurBeat = 0.0f;
float prevBeat = 0.0f; // Used for hold tails.
for( unsigned r=0; r<vNoteRows.size(); r++ )
{
RString& sRowString = vNoteRows[r];
@@ -157,7 +301,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
continue; // skip
// All 2s indicates the end of the song.
if( sRowString == "2222222222222" )
else if( sRowString == "2222222222222" )
{
// Finish any holds that didn't get...well, finished.
for( t=0; t < notedata.GetNumTracks(); t++ )
@@ -173,30 +317,21 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
break;
}
// Why do this? Rows made with precise DM05 tags can go up to 13 too -DaisuMaster
//if( sRowString.size() != 13 )
//this is wrong in many ways...
/*if( bKIUCompliant )
else if( BeginsWith(sRowString, "|") )
{
LOG->UserLog( "Song file", sPath, "has illegal syntax \"%s\" which can't be in KIU complient files.",
sRowString.c_str() );
return false;
//In other words: you can't mix ksf's with DM05 tags and ksf's without any DM05 tags
//Either one set or another will be read...
}*/
if( BeginsWith(sRowString, "|B") || BeginsWith(sRowString, "|D") || BeginsWith(sRowString, "|E") )
{
// TODO: Update for Split Timing.
continue;
}
else if ( BeginsWith(sRowString, "|T") )
{
RString temp = sRowString.substr(2,sRowString.size()-3);
newTick = StringToInt(temp);
bTickChangeNeeded = true;
out.m_Timing.AddTickcountSegment(TickcountSegment(BeatToNoteRow(fCurBeat), newTick));
if (bKIUCompliant)
{
// Log an error, ignore the line.
continue;
}
if ( !HandlePipeChars( stepsTiming, sRowString, fCurBeat, iTickCount ) )
{
// LOG it first.
}
continue;
}
else
{
// Is this why improper ksf or some kiucompilant ksf mixed with dm05 ksf are ignored?? -DaisuMaster
@@ -273,6 +408,7 @@ static bool LoadFromKSFFile( const RString &sPath, Steps &out, const Song &song,
}
out.SetNoteData( notedata );
out.m_Timing = stepsTiming;
out.TidyUpData();
@@ -468,21 +604,12 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
{
if( BPM2 > 0 && BPMPos2 > 0 )
{
const float BeatsPerSecond = BPM1 / 60.0f;
const float beat = (BPMPos2 + SMGap1) * BeatsPerSecond;
LOG->Trace( "BPM %f, BPS %f, BPMPos2 %f, beat %f",
BPM1, BeatsPerSecond, BPMPos2, beat );
out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM2) );
HandleBunki( out.m_SongTiming, BPM1, BPM2, SMGap1, BPMPos2 );
}
if( BPM3 > 0 && BPMPos3 > 0 )
{
const float BeatsPerSecond = BPM2 / 60.0f;
//The line below isn't perfect, but works better than previous versions.
const float beat = (BPMPos3 + SMGap2) * BeatsPerSecond;
LOG->Trace( "BPM %f, BPS %f, BPMPos3 %f, beat %f",
BPM2, BeatsPerSecond, BPMPos3, beat );
out.m_SongTiming.AddBPMSegment( BPMSegment(BeatToNoteRow(beat), BPM3) );
HandleBunki( out.m_SongTiming, BPM2, BPM3, SMGap2, BPMPos3 );
}
}
else
@@ -510,40 +637,11 @@ static bool LoadGlobalData( const RString &sPath, Song &out, bool &bKIUCompliant
BeginsWith(NoteRowString, "|D") || BeginsWith(NoteRowString, "|E") )
{
bDMRequired = true;
RString temp = NoteRowString.substr(2,NoteRowString.size()-3);
float numTemp = StringToFloat(temp);
if (BeginsWith(NoteRowString, "|T"))
if ( !HandlePipeChars( out.m_SongTiming, NoteRowString, fCurBeat, iTickCount ) )
{
iTickCount = (int)numTemp;
TickcountSegment tcs;
tcs.m_iStartRow = BeatToNoteRow(fCurBeat);
tcs.m_iTicks = iTickCount > ROWS_PER_BEAT ? ROWS_PER_BEAT : iTickCount;
out.m_SongTiming.AddTickcountSegment( tcs );
continue;
}
else if (BeginsWith(NoteRowString, "|B"))
{
float fCurBpm = (float)numTemp;
//out.m_Timing.AddBPMSegment( BPMSegment( BeatToNoteRow(fCurBeat), (float)numTemp ) );
out.m_SongTiming.SetBPMAtBeat( fCurBeat, fCurBpm );
continue;
}
else if (BeginsWith(NoteRowString, "|E"))
{
// Finally! the |E| tag is working as it should. I can die happy now -DaisuMaster
float fCurDelay = 60 / out.m_SongTiming.GetBPMAtBeat(fCurBeat) * (float)numTemp / iTickCount;
fCurDelay += out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) );
out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true );
continue;
}
else if (BeginsWith(NoteRowString, "|D"))
{
float fCurDelay = out.m_SongTiming.GetStopAtRow(BeatToNoteRow(fCurBeat) );
fCurDelay += (float)numTemp / 1000;
out.m_SongTiming.SetStopAtBeat( fCurBeat, fCurDelay, true );
continue;
// LOG it first.
}
continue;
}
else
{
@@ -583,16 +681,17 @@ bool KSFLoader::LoadFromDir( const RString &sDir, Song &out )
ASSERT( arrayKSFFileNames.size() );
bool bKIUCompliant = false;
/* If only the first file is read, it will cause problems for other simfiles with
* different BPM changes and tickcounts. This command will probably have to be
* changed in the future. */
/* With Split Timing, there has to be a backup Song Timing in case
* anything goes wrong. Use the first file found to determine said
* timing, while also establishing whether this file respects the
* Kick It Up syntax. */
if( !LoadGlobalData(out.GetSongDir() + arrayKSFFileNames[0], out, bKIUCompliant) )
return false;
// load the Steps from the rest of the KSF files
for( unsigned i=0; i<arrayKSFFileNames.size(); i++ )
{
Steps* pNewNotes = new Steps;
Steps* pNewNotes = out.CreateSteps();
if( !LoadFromKSFFile(out.GetSongDir() + arrayKSFFileNames[i], *pNewNotes, out, bKIUCompliant) )
{
delete pNewNotes;