#include "global.h" /* ----------------------------------------------------------------------------- Class: NoteDataUtil Desc: See header. Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved. Chris Danford ----------------------------------------------------------------------------- */ #include "NoteDataUtil.h" #include "RageUtil.h" #include "RageLog.h" #include "PlayerOptions.h" NoteType NoteDataUtil::GetSmallestNoteTypeForMeasure( const NoteData &n, int iMeasureIndex ) { const int iMeasureStartIndex = iMeasureIndex * ROWS_PER_MEASURE; const int iMeasureLastIndex = (iMeasureIndex+1) * ROWS_PER_MEASURE - 1; // probe to find the smallest note type NoteType nt; for( nt=(NoteType)0; nt= NOTE_TYPE_12TH ) iNumChaosNotes++; } float fReturn = iNumChaosNotes / fSongSeconds * 0.5f; return min( fReturn, 1.0f ); } void NoteDataUtil::RemoveHoldNotes(NoteData &in) { vector tracks, rows; // turn all the HoldNotes into TapNotes for( int i=0; i aiTracksLeftToMap; for( t=0; t=0; i-- ) if( fmodf(in.GetHoldNote(i).fStartBeat,1) != 0 ) // doesn't start on a beat in.RemoveHoldNote( i ); } void NoteDataUtil::Wide( NoteData &in, float fStartBeat, float fEndBeat ) { // Make all all quarter notes into jumps. in.ConvertHoldNotesTo4s(); /* Start on an even beat. */ fStartBeat = froundf( fStartBeat, 2 ); int first_row = 0; if( fStartBeat != -1 ) first_row = BeatToNoteRow(fStartBeat); int last_row = in.GetLastRow(); if( fEndBeat != -1 ) last_row = BeatToNoteRow(fEndBeat); for( int i=first_row; i 0 ) { bSpaceAroundIsEmpty = false; break; } if( !bSpaceAroundIsEmpty ) continue; // skip // add a note determinitsitcally int iBeat = (int)roundf( NoteRowToBeat(i) ); int iTrackOfNote = in.GetFirstTrackWithTap(i); int iTrackToAdd = iTrackOfNote + (iBeat%5)-2; // won't be more than 2 tracks away from the existing note CLAMP( iTrackToAdd, 0, in.GetNumTracks()-1 ); if( iTrackToAdd == iTrackOfNote ) iTrackToAdd++; CLAMP( iTrackToAdd, 0, in.GetNumTracks()-1 ); if( iTrackToAdd == iTrackOfNote ) iTrackToAdd--; CLAMP( iTrackToAdd, 0, in.GetNumTracks()-1 ); if( in.GetTapNote(iTrackToAdd, i) != TAP_EMPTY ) { iTrackToAdd = (iTrackToAdd+1) % in.GetNumTracks(); } in.SetTapNote(iTrackToAdd, i, TAP_ADDITION); } in.Convert4sToHoldNotes(); } void NoteDataUtil::Big( NoteData &in, float fStartBeat, float fEndBeat ) { InsertIntelligentTaps(in,1.0f,0.5f,false,fStartBeat,fEndBeat); // add 8ths between 4ths } void NoteDataUtil::Quick( NoteData &in, float fStartBeat, float fEndBeat ) { InsertIntelligentTaps(in,0.5f,0.25f,false,fStartBeat,fEndBeat); // add 16ths between 8ths } void NoteDataUtil::Skippy( NoteData &in, float fStartBeat, float fEndBeat ) { InsertIntelligentTaps(in,1.0f,0.75f,true,fStartBeat,fEndBeat); // add 16ths between 4ths } void NoteDataUtil::InsertIntelligentTaps( NoteData &in, float fBeatInterval, float fInsertBeatOffset, bool bSkippy, float fStartBeat, float fEndBeat ) { ASSERT( fInsertBeatOffset <= fBeatInterval ); in.ConvertHoldNotesTo4s(); /* Start on an integral beat. */ fStartBeat = roundf( fStartBeat ); // Insert a beat in the middle of every fBeatInterval. int first_row = 0; if( fStartBeat != -1 ) first_row = BeatToNoteRow(fStartBeat); int last_row = in.GetLastRow(); if( fEndBeat != -1 ) last_row = BeatToNoteRow(fEndBeat); int rows_per_interval = BeatToNoteRow( fBeatInterval ); int insert_row_offset = BeatToNoteRow( fInsertBeatOffset ); for( int i=first_row; i=7) || (iRowCount>=6 && rand()%2) ) { for( int t=0; t last_row ) continue; // Add a mine right after the hold end.h in.SetTapNote(hn.iTrack,iMineRow,TAP_MINE); // Convert all other notes in this row to mines. for( int t=0; tTrace("index %i", i); int iOldIndex = i; float fOldBeat = NoteRowToBeat( iOldIndex ); float fNewBeat1 = froundf( fOldBeat, fSnapInterval1 ); float fNewBeat2 = froundf( fOldBeat, fSnapInterval2 ); LOG->Trace("oldbeat %.2f, nb1 %.2f, nb2 %.2f", fOldBeat, fNewBeat1, fNewBeat2); bool bNewBeat1IsCloser = fabsf(fNewBeat1-fOldBeat) < fabsf(fNewBeat2-fOldBeat); float fNewBeat = bNewBeat1IsCloser ? fNewBeat1 : fNewBeat2; int iNewIndex = BeatToNoteRow( fNewBeat ); LOG->Trace("closer %i, newbeat %.2f, index %i", bNewBeat1IsCloser, fNewBeat, iNewIndex); for( int c=0; c0; t-- ) // in.GetNumTracks()-1 times { int iTrackEarlier = t; int iTrackLater = (t+1) % in.GetNumTracks(); // swap TapNote tnEarlier = in.GetTapNote(iTrackEarlier, r); TapNote tnLater = in.GetTapNote(iTrackLater, r); in.SetTapNote(iTrackEarlier, r, tnLater); in.SetTapNote(iTrackLater, r, tnEarlier); } } in.Convert4sToHoldNotes(); } struct ValidRow { StepsType st; bool bValidMask[MAX_NOTE_TRACKS]; }; #define T true #define f false const ValidRow g_ValidRows[] = { { STEPS_TYPE_DANCE_DOUBLE, { T,T,T,T,f,f,f,f } }, { STEPS_TYPE_DANCE_DOUBLE, { f,T,T,T,T,f,f,f } }, { STEPS_TYPE_DANCE_DOUBLE, { f,f,f,T,T,T,T,f } }, { STEPS_TYPE_DANCE_DOUBLE, { f,f,f,f,T,T,T,T } }, }; void NoteDataUtil::FixImpossibleRows( NoteData &in, StepsType st ) { vector vpValidRowsToCheck; for( unsigned i=0; i 0 ); NoteData temp; temp.CopyAll( &nd ); nd.ClearAll(); for( int r=0; r<=temp.GetLastRow(); r++ ) { for( int t=0; t 0 ) // add blank rows iPasteAtRow += BeatToNoteRow( fBeatsToShift ); else // delete rows iTakeFromRow += BeatToNoteRow( -fBeatsToShift ); temp.CopyRange( &nd, iTakeFromRow, nd.GetLastRow() ); nd.ClearRange( min(iTakeFromRow,iPasteAtRow), nd.GetLastRow() ); nd.CopyRange( &temp, 0, temp.GetLastRow(), iPasteAtRow ); }