Add NoteData "compression".

This commit is contained in:
Glenn Maynard
2002-12-13 01:23:26 +00:00
parent 48970a9cb6
commit 3cfb72fb58
2 changed files with 114 additions and 5 deletions
+100 -3
View File
@@ -31,6 +31,7 @@ NoteData::NoteData()
void NoteData::Init()
{
m_iNumTracks = 0;
TapRowDivisor = 1;
}
NoteData::~NoteData()
@@ -101,6 +102,8 @@ void NoteData::LoadFromSMNoteDataString( CString sSMNoteData )
}
}
this->Convert2sAnd3sToHoldNotes();
Compress();
}
CString NoteData::GetSMNoteDataString()
@@ -195,6 +198,19 @@ void NoteData::CopyRange( NoteData* pFrom, int iFromIndexBegin, int iFromIndexEn
this->Convert4sToHoldNotes();
}
void NoteData::Config( const NoteData &From )
{
m_iNumTracks = From.m_iNumTracks;
TapRowDivisor = From.TapRowDivisor;
}
void NoteData::CopyAll( NoteData* pFrom )
{
Config(*pFrom);
m_HoldNotes.clear();
CopyRange( pFrom, 0, MAX_TAP_NOTE_ROWS );
}
void NoteData::AddHoldNote( HoldNote add )
{
ASSERT( add.m_fStartBeat>=0 && add.m_fEndBeat>=0 );
@@ -312,7 +328,7 @@ float NoteData::GetLastBeat()
int i;
for( i = int(m_TapNotes[0].size()); i>=0; i-- ) // iterate back to front
for( i = TapRowDivisor * int(m_TapNotes[0].size()); i>=0; i-- ) // iterate back to front
{
if( !IsRowEmpty(i) )
{
@@ -589,7 +605,7 @@ void NoteData::Turn( PlayerOptions::TurnType tt )
}
NoteData tempNoteData; // write into here as we tranform
tempNoteData.m_iNumTracks = m_iNumTracks;
tempNoteData.Config(*this);
this->ConvertHoldNotesTo2sAnd3s();
@@ -613,7 +629,7 @@ void NoteData::Turn( PlayerOptions::TurnType tt )
// clear tempNoteData because we're going to use it as a scratch buffer again
tempNoteData.Init();
tempNoteData.m_iNumTracks = this->m_iNumTracks;
tempNoteData.Config(*this);
// copy all HoldNotes before copying taps
for( int i=0; i<this->GetNumHoldNotes(); i++ )
@@ -899,6 +915,7 @@ void NoteData::LoadTransformed( NoteData* pOriginal, int iNewNumTracks, const in
pOriginal->ConvertHoldNotesTo4s();
Config(*pOriginal);
m_iNumTracks = iNewNumTracks;
// copy tracks
@@ -921,6 +938,7 @@ void NoteData::LoadTransformedSlidingWindow( NoteData* pOriginal, int iNewNumTra
Init();
pOriginal->ConvertHoldNotesTo4s();
Config(*pOriginal);
m_iNumTracks = iNewNumTracks;
int iCurTrackOffset = 0;
@@ -1044,6 +1062,85 @@ void NoteData::MoveTapNoteTrack(int dest, int src)
void NoteData::SetTapNote(int track, int row, TapNote t)
{
if(row < 0) return;
Decompress();
PadTapNotes(row);
m_TapNotes[track][row]=t;
}
void NoteData::SetDivisor(int div)
{
if(div == TapRowDivisor)
return;
int src_step = div,
dst_step = TapRowDivisor;
/* I think this should work to go from one divisor to another, but
* I havn't tested it and don't see a need. */
ASSERT(src_step == 1 || dst_step == 1);
for(int t=0; t < m_iNumTracks; t++)
{
vector<TapNote> TapNotes = m_TapNotes[t];
/* Try to make sure the memory is actually released. */
int dst_size = m_TapNotes[0].size() * dst_step / src_step;
m_TapNotes[t].clear();
m_TapNotes[t] = vector<TapNote>(dst_size, TAP_EMPTY);
unsigned src_row = 0, dst_row = 0;
while(src_row < TapNotes.size() && dst_row < m_TapNotes[t].size())
{
m_TapNotes[t][dst_row] = TapNotes[src_row];
dst_row += dst_step;
src_row += src_step;
}
}
TapRowDivisor = div;
}
void NoteData::Compress()
{
/* We could optimize a little by being able to compress compressed data,
* but let's not bother for now. */
Decompress();
/* Find the largest divisor; the largest D such that all notes M such that
* (M%D) != 0 are empty. */
const int max_divisor = 64;
bool *ok = new bool[max_divisor];
memset(ok, 1, sizeof(ok));
int t, row, rows = GetLastRow();
for(t=0; t < m_iNumTracks; t++)
{
for(row = 0; row < rows; ++row)
{
/* If there's nothing here, then it doesn't make any divisors invalid. */
if(GetTapNote(t, row) == TAP_EMPTY)
continue;
for(int div = 2; div < max_divisor; ++div)
{
if((row % div) != 0) ok[div] = false;
}
}
}
ASSERT(ok[1]);
int best_div = max_divisor-1;
while(!ok[best_div])
best_div--;
delete [] ok;
SetDivisor(best_div);
}
void NoteData::Decompress()
{
SetDivisor(1);
}
+14 -2
View File
@@ -27,9 +27,15 @@ class NoteData
{
/* Keep this aligned, so that they all have the same size. */
vector<TapNote> m_TapNotes[MAX_NOTE_TRACKS];
int TapRowDivisor;
void SetDivisor(int div);
vector<HoldNote> m_HoldNotes;
/* Set up to hold the data in From; same number of tracks, same
* divisor. Doesn't allocate or copy anything. */
void Config( const NoteData &From );
public:
NoteData();
~NoteData();
@@ -37,13 +43,19 @@ public:
int m_iNumTracks;
void Compress();
void Decompress();
/* Return the note at the given track and row. Row may be out of
* range; pretend the song goes on with TAP_EMPTYs indefinitely. */
inline TapNote GetTapNote(unsigned track, unsigned row) const
{
if((row % TapRowDivisor) != 0) return TapNote(TAP_EMPTY);
row /= TapRowDivisor;
if(row < 0 || row >= m_TapNotes[track].size()) return TapNote(TAP_EMPTY);
return m_TapNotes[track][row];
}
int GetTapNoteIncrement() const { return TapRowDivisor; }
void MoveTapNoteTrack(int dest, int src);
/* Pad m_TapNotes so it includes the row "rows". */
void PadTapNotes(int rows);
@@ -55,8 +67,8 @@ public:
void ClearRange( int iNoteIndexBegin, int iNoteIndexEnd );
void ClearAll() { ClearRange( 0, MAX_TAP_NOTE_ROWS ); };
void CopyRange( NoteData* pFrom, int iFromIndexBegin, int iFromIndexEnd, int iToIndexBegin = -1 );
void CopyAll( NoteData* pFrom ) { m_iNumTracks = pFrom->m_iNumTracks; m_HoldNotes.clear(); CopyRange( pFrom, 0, MAX_TAP_NOTE_ROWS ); };
void CopyAll( NoteData* pFrom );
inline bool IsRowEmpty( int index )
{
for( int t=0; t<m_iNumTracks; t++ )