/* Return the minimum tap score of a row.  If the row isn't complete (not all
 * taps have been hit), return TNS_None or TNS_Miss. */
TapNoteScore NoteDataWithScoring::MinTapNoteScore( const NoteData &in, unsigned row, PlayerNumber plnum )
{
	//LOG->Trace("Hey I'm NoteDataWithScoring::MinTapNoteScore");
	TapNoteScore score = TNS_W1;
	for( int t=0; t<in.GetNumTracks(); t++ )
	{
		// Ignore mines (and fake arrows), or the score will always be TNS_None.
		const TapNote &tn = in.GetTapNote( t, row );
		if (tn.type == TapNoteType_Empty ||
			tn.type == TapNoteType_Mine ||
			tn.type == TapNoteType_Fake ||
			tn.type == TapNoteType_AutoKeysound ||
			( plnum != PlayerNumber_Invalid && tn.pn != plnum ) )
			continue;
		score = min( score, tn.result.tns );
	}

	//LOG->Trace( ssprintf("OMG score is?? %s",TapNoteScoreToString(score).c_str()) );
	return score;
}
Ejemplo n.º 2
0
void ScoreKeeperNormal::GetRowCounts( const NoteData &nd, int iRow,
					  int &iNumHitContinueCombo, int &iNumHitMaintainCombo,
					  int &iNumBreakCombo )
{
	iNumHitContinueCombo = iNumHitMaintainCombo = iNumBreakCombo = 0;
	for( int track = 0; track < nd.GetNumTracks(); ++track )
	{
		const TapNote &tn = nd.GetTapNote( track, iRow );

		if( tn.type != TapNoteType_Tap && tn.type != TapNoteType_HoldHead && tn.type != TapNoteType_Lift )
			continue;
		TapNoteScore tns = tn.result.tns;
		if( tns >= m_MinScoreToContinueCombo )
			++iNumHitContinueCombo;
		else if( tns >= m_MinScoreToMaintainCombo )
			++iNumHitMaintainCombo;
		else
			++iNumBreakCombo;
	}
}
Ejemplo n.º 3
0
static StepsType DetermineStepsType( int iPlayer, const NoteData &nd, const RString &sPath )
{
	ASSERT( NUM_PMS_TRACKS == nd.GetNumTracks() );

	bool bTrackHasNote[NUM_NON_AUTO_KEYSOUND_TRACKS];
	ZERO( bTrackHasNote );

	int iLastRow = nd.GetLastRow();
	for( int t=0; t<NUM_NON_AUTO_KEYSOUND_TRACKS; t++ )
	{
		for( int r=0; r<=iLastRow; r++ )
		{
			if( nd.GetTapNote(t, r).type != TapNote::empty )
			{
				bTrackHasNote[t] = true;
				break;				
			}
		}
	}

	int iNumNonEmptyTracks = 0;
	for( int t=0; t<NUM_NON_AUTO_KEYSOUND_TRACKS; t++ )
		if( bTrackHasNote[t] )
			iNumNonEmptyTracks++;

	switch( iPlayer )
	{
	case 1:
		switch( iNumNonEmptyTracks ) 
		{
			case 5:		return StepsType_popn_five;
			case 9:		return StepsType_popn_nine;
			default:	return StepsType_Invalid;
		}
	default:
		LOG->UserLog( "Song file", sPath, "has an invalid #PLAYER value %d.", iPlayer );
		return StepsType_Invalid;
	}
}
Ejemplo n.º 4
0
static bool LoadFromBMSFile( const RString &sPath, const NameToData_t &mapNameToData, Steps &out,
			     const MeasureToTimeSig_t &sigAdjustments, const map<RString,int> &idToKeySoundIndex )
{
	LOG->Trace( "Steps::LoadFromBMSFile( '%s' )", sPath.c_str() );

	out.m_StepsType = StepsType_Invalid;

	// BMS player code.  Fill in below and use to determine StepsType.
	int iPlayer = -1;
	RString sData;
	if( GetTagFromMap( mapNameToData, "#player", sData ) )
		iPlayer = atoi(sData);
	if( GetTagFromMap( mapNameToData, "#playlevel", sData ) )
		out.SetMeter( atoi(sData) );

	NoteData ndNotes;
	ndNotes.SetNumTracks( NUM_BMS_TRACKS );

	/* Read time signatures.  Note that these can differ across files in the same
	 * song. */
	MeasureToTimeSig_t mapMeasureToTimeSig;
	ReadTimeSigs( mapNameToData, mapMeasureToTimeSig );

	int iHoldStarts[NUM_BMS_TRACKS];
	int iHoldPrevs[NUM_BMS_TRACKS];
	
	for( int i = 0; i < NUM_BMS_TRACKS; ++i )
	{
		iHoldStarts[i] = -1;
		iHoldPrevs[i] = -1;
	}
	
	NameToData_t::const_iterator it;
	for( it = mapNameToData.lower_bound("#00000"); it != mapNameToData.end(); ++it )
	{
		const RString &sName = it->first;
		if( sName.size() != 6 || sName[0] != '#' || !IsAnInt( sName.substr(1, 5) ) )
			 continue;

		// this is step or offset data.  Looks like "#00705"
		int iMeasureNo = atoi( sName.substr(1,3).c_str() );
		int iRawTrackNum = atoi( sName.substr(4,2).c_str() );
		int iRowNo = GetMeasureStartRow( mapMeasureToTimeSig, iMeasureNo, sigAdjustments );
		float fBeatsPerMeasure = GetBeatsPerMeasure( mapMeasureToTimeSig, iMeasureNo, sigAdjustments );
		const RString &sNoteData = it->second;

		vector<TapNote> vTapNotes;
		for( size_t i=0; i+1<sNoteData.size(); i+=2 )
		{
			RString sNoteId = sNoteData.substr( i, 2 );
			if( sNoteId != "00" )
			{
				vTapNotes.push_back( TAP_ORIGINAL_TAP );
				map<RString,int>::const_iterator it = idToKeySoundIndex.find( sNoteId );
				if( it != idToKeySoundIndex.end() )
					vTapNotes.back().iKeysoundIndex = it->second;
			}
			else
			{
				vTapNotes.push_back( TAP_EMPTY );
			}
		}

		const unsigned iNumNotesInThisMeasure = vTapNotes.size();
		for( unsigned j=0; j<iNumNotesInThisMeasure; j++ )
		{
			float fPercentThroughMeasure = (float)j/(float)iNumNotesInThisMeasure;
			
			int row = iRowNo + lrintf( fPercentThroughMeasure * fBeatsPerMeasure * ROWS_PER_BEAT );
			
			// some BMS files seem to have funky alignment, causing us to write gigantic cache files.
			// Try to correct for this by quantizing.
			row = Quantize( row, ROWS_PER_MEASURE/64 );
			
			BmsTrack bmsTrack;
			bool bIsHold;
			if( ConvertRawTrackToTapNote(iRawTrackNum, bmsTrack, bIsHold) )
			{
				TapNote &tn = vTapNotes[j];
				if( tn.type != TapNote::empty )
				{
					if( bmsTrack == BMS_AUTO_KEYSOUND_1 )
					{
						// shift the auto keysound as far right as possible
						int iLastEmptyTrack = -1;
						if( ndNotes.GetTapLastEmptyTrack(row, iLastEmptyTrack)  &&
						    iLastEmptyTrack >= BMS_AUTO_KEYSOUND_1 )
						{
							tn.type = TapNote::autoKeysound;
							bmsTrack = (BmsTrack)iLastEmptyTrack;
						}
						else
						{
							// no room for this note.  Drop it.
							continue;
						}
					}
					else if( bIsHold )
					{
						if( iHoldStarts[bmsTrack] == -1 )
						{
							// Start of a hold.
							iHoldStarts[bmsTrack] = row;
							iHoldPrevs[bmsTrack] = row;
						}
						else
						{
							// We're continuing a hold.
							iHoldPrevs[bmsTrack] = row;
						}
						continue;
					}
				}
				if( iHoldStarts[bmsTrack] != -1 )
				{
					// This is ending a hold.
					const int iBegin = iHoldStarts[bmsTrack];
					const int iEnd = iHoldPrevs[bmsTrack];
					
					if( iBegin < iEnd )
						ndNotes.AddHoldNote( bmsTrack, iBegin, iEnd, TAP_ORIGINAL_HOLD_HEAD );
					else
						ndNotes.SetTapNote( bmsTrack, iBegin, TAP_ORIGINAL_TAP );
					iHoldStarts[bmsTrack] = -1;
					iHoldPrevs[bmsTrack] = -1;
				}
				// Don't bother inserting empty taps.
				if( tn.type != TapNote::empty )
					ndNotes.SetTapNote( bmsTrack, row, tn );
			}
		}
	}

	// We're done reading in all of the BMS values. Time to check for any unfinished holds.
	for( int iTrack = 0; iTrack < NUM_BMS_TRACKS; ++iTrack )
	{
		const int iBegin = iHoldStarts[iTrack];
		const int iEnd = iHoldPrevs[iTrack];
				
		if( iBegin == -1 )
			continue;
		if( iBegin < iEnd )
			ndNotes.AddHoldNote( iTrack, iBegin, iEnd, TAP_ORIGINAL_HOLD_HEAD );
		else
			ndNotes.SetTapNote( iTrack, iBegin, TAP_ORIGINAL_TAP );
	}		

	out.m_StepsType = DetermineStepsType( iPlayer, ndNotes, sPath );
	if( out.m_StepsType == StepsType_beat_single5 && GetTagFromMap( mapNameToData, "#title", sData ) )
	{
		/* Hack: guess at 6-panel. */
		
		// extract the Steps description (looks like 'Music <BASIC>')
		const size_t iOpenBracket = sData.find_first_of( "<(" );
		const size_t iCloseBracket = sData.find_first_of( ">)", iOpenBracket );
		
		// if there's a 6 in the description, it's probably part of "6panel" or "6-panel"		
		if( sData.find('6', iOpenBracket) < iCloseBracket )
			out.m_StepsType = StepsType_dance_solo;
	}
	
	if( out.m_StepsType == StepsType_Invalid )
	{
		LOG->UserLog( "Song file", sPath, "has an unknown steps type" );
		return false;
	}


	// shift all of the autokeysound tracks onto the main tracks
	for( int t=BMS_AUTO_KEYSOUND_1; t<BMS_AUTO_KEYSOUND_1+NUM_AUTO_KEYSOUND_TRACKS; t++ )
	{
		FOREACH_NONEMPTY_ROW_IN_TRACK( ndNotes, t, row )
		{
			TapNote tn = ndNotes.GetTapNote( t, row );
			int iEmptyTrack;
			if( ndNotes.GetTapFirstEmptyTrack(row, iEmptyTrack) )
			{
				ndNotes.SetTapNote( iEmptyTrack, row, tn );
				ndNotes.SetTapNote( t, row, TAP_EMPTY );
			}
			else
			{
				LOG->UserLog( "Song file", sPath, "has no room to shift the autokeysound tracks." );
			}
		}
	}
Ejemplo n.º 5
0
static StepsType DetermineStepsType( int iPlayer, const NoteData &nd, const RString &sPath )
{
	ASSERT( NUM_BMS_TRACKS == nd.GetNumTracks() );

	bool bTrackHasNote[NUM_NON_AUTO_KEYSOUND_TRACKS];
	ZERO( bTrackHasNote );

	int iLastRow = nd.GetLastRow();
	for( int t=0; t<NUM_NON_AUTO_KEYSOUND_TRACKS; t++ )
	{
		for( int r=0; r<=iLastRow; r++ )
		{
			if( nd.GetTapNote(t, r).type != TapNote::empty )
			{
				bTrackHasNote[t] = true;
				break;				
			}
		}
	}

	int iNumNonEmptyTracks = 0;
	for( int t=0; t<NUM_NON_AUTO_KEYSOUND_TRACKS; t++ )
		if( bTrackHasNote[t] )
			iNumNonEmptyTracks++;

	switch( iPlayer )
	{
	case 1:	// "1 player"		
		/* Track counts:
		 * 4 - dance 4-panel
		 * 5 - pop 5-key
		 * 6 - dance 6-panel, beat 5-key
		 * 8 - beat 7-key
		 * 9 - popn 9-key */
		switch( iNumNonEmptyTracks ) 
		{
		case 4:		return StepsType_dance_single;
		case 5:		return StepsType_popn_five;
		case 6:
			// FIXME: There's no way to distinguish between these types.
			// They use the same tracks.  Assume it's a Beat type since they
			// are more common.
			//return StepsType_dance_solo;
			return StepsType_beat_single5;
		case 8:		return StepsType_beat_single7;
		case 9:		return StepsType_popn_nine;
		default:	return StepsType_Invalid;
		}
	case 2:	// couple/battle
		return StepsType_dance_couple;
	case 3:	// double
		/* Track counts:
		 * 8 - dance Double
		 * 12 - beat Double 5-key
		 * 16 - beat Double 7-key */
		switch( iNumNonEmptyTracks ) 
		{
		case 8:		return StepsType_beat_single7;
		case 12:	return StepsType_beat_double5;
		case 16:	return StepsType_beat_double7;
		default:	return StepsType_Invalid;
		}
	default:
		LOG->UserLog( "Song file", sPath, "has an invalid #PLAYER value %d.", iPlayer );
		return StepsType_Invalid;
	}
}
Ejemplo n.º 6
0
static void WriteDWINotesField( RageFile &f, const Steps &out, int start )
{
	NoteData notedata;
	out.GetNoteData( notedata );
	NoteDataUtil::InsertHoldTails( notedata );

	const int iLastMeasure = int( notedata.GetLastBeat()/BEATS_PER_MEASURE );
	for( int m=0; m<=iLastMeasure; m++ )	// foreach measure
	{
		NoteType nt = NoteDataUtil::GetSmallestNoteTypeForMeasure( notedata, m );

		double fCurrentIncrementer = 0;
		switch( nt )
		{
		case NOTE_TYPE_4TH:
		case NOTE_TYPE_8TH:	
			fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
			break;
		case NOTE_TYPE_12TH:
		case NOTE_TYPE_24TH:
			f.Write( "[" );
			fCurrentIncrementer = 1.0/24 * BEATS_PER_MEASURE;
			break;
		case NOTE_TYPE_16TH:
			f.Write( "(" );
			fCurrentIncrementer = 1.0/16 * BEATS_PER_MEASURE;
			break;
		case NOTE_TYPE_32ND:
		case NOTE_TYPE_64TH:
			f.Write( "{" );
			fCurrentIncrementer = 1.0/64 * BEATS_PER_MEASURE;
			break;
		case NOTE_TYPE_48TH:
		case NOTE_TYPE_192ND:
		case NoteType_Invalid:
			// since, for whatever reason, the only way to do
			// 48ths is through a block of 192nds...
			f.Write(  "`" );
			fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
			break;
		default:
			ASSERT_M(0, ssprintf("nt = %d",nt) );
			break;
		}

		double fFirstBeatInMeasure = m * BEATS_PER_MEASURE;
		double fLastBeatInMeasure = (m+1) * BEATS_PER_MEASURE;

		for( double b=fFirstBeatInMeasure; b<=fLastBeatInMeasure-1/64.0f; b+=fCurrentIncrementer )	// need the -0.0001 to account for rounding errors
		{
			int row = BeatToNoteRow( (float)b );

			RString str;
			switch( out.m_StepsType )
			{
			case StepsType_dance_single:
			case StepsType_dance_couple:
			case StepsType_dance_double:
				str = NotesToDWIString( 
					notedata.GetTapNote(start+0, row), 
					notedata.GetTapNote(start+1, row),
					notedata.GetTapNote(start+2, row),
					notedata.GetTapNote(start+3, row) );

				// Blank out the notes so we don't write them again if the incrementer is small
				notedata.SetTapNote(start+0, row, TAP_EMPTY);
				notedata.SetTapNote(start+1, row, TAP_EMPTY);
				notedata.SetTapNote(start+2, row, TAP_EMPTY);
				notedata.SetTapNote(start+3, row, TAP_EMPTY);
				break;
			case StepsType_dance_solo:
				str = NotesToDWIString( 
					notedata.GetTapNote(0, row),
					notedata.GetTapNote(1, row),
					notedata.GetTapNote(2, row),
					notedata.GetTapNote(3, row),
					notedata.GetTapNote(4, row),
					notedata.GetTapNote(5, row) );

				// Blank out the notes so we don't write them again if the incrementer is small
				notedata.SetTapNote(start+0, row, TAP_EMPTY);
				notedata.SetTapNote(start+1, row, TAP_EMPTY);
				notedata.SetTapNote(start+2, row, TAP_EMPTY);
				notedata.SetTapNote(start+3, row, TAP_EMPTY);
				notedata.SetTapNote(start+4, row, TAP_EMPTY);
				notedata.SetTapNote(start+5, row, TAP_EMPTY);
				break;
			default:
				ASSERT(0);	// not a type supported by DWI.  We shouldn't have called in here if that's the case
			}
			f.Write( str );
		}

		switch( nt )
		{
		case NOTE_TYPE_4TH:
		case NOTE_TYPE_8TH:	
			break;
		case NOTE_TYPE_12TH:
		case NOTE_TYPE_24TH:
			f.Write( "]" );
			break;
		case NOTE_TYPE_16TH:
			f.Write( ")" );
			break;
		case NOTE_TYPE_32ND:
		case NOTE_TYPE_64TH:
			f.Write( "}" );
			break;
		case NOTE_TYPE_48TH:
		case NOTE_TYPE_192ND:
		case NoteType_Invalid:
			f.Write( "'" );
			break;
		default:
			ASSERT(0);
			// fall though
		}
		f.PutLine( "" );
	}
}
Ejemplo n.º 7
0
static NoteData ParseNoteData(RString &step1, RString &step2,
			      Steps &out, const RString &path)
{
	g_mapDanceNoteToNoteDataColumn.clear();
	switch( out.m_StepsType )
	{
		case StepsType_dance_single:
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
			break;
		case StepsType_dance_double:
		case StepsType_dance_couple:
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 1;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 2;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 3;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_LEFT] = 4;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_DOWN] = 5;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_UP] = 6;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD2_RIGHT] = 7;
			break;
		case StepsType_dance_solo:
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_LEFT] = 0;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPLEFT] = 1;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_DOWN] = 2;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UP] = 3;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_UPRIGHT] = 4;
			g_mapDanceNoteToNoteDataColumn[DANCE_NOTE_PAD1_RIGHT] = 5;
			break;
			DEFAULT_FAIL( out.m_StepsType );
	}
	
	NoteData newNoteData;
	newNoteData.SetNumTracks( g_mapDanceNoteToNoteDataColumn.size() );
	
	for( int pad=0; pad<2; pad++ )		// foreach pad
	{
		RString sStepData;
		switch( pad )
		{
			case 0:
				sStepData = step1;
				break;
			case 1:
				if( step2 == "" )	// no data
					continue;	// skip
				sStepData = step2;
				break;
				DEFAULT_FAIL( pad );
		}
		
		sStepData.Replace("\n", "");
		sStepData.Replace("\r", "");
		sStepData.Replace("\t", "");
		sStepData.Replace(" ", "");
		
		double fCurrentBeat = 0;
		double fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
		
		for( size_t i=0; i<sStepData.size(); )
		{
			char c = sStepData[i++];
			switch( c )
			{
					// begins a series
				case '(':
					fCurrentIncrementer = 1.0/16 * BEATS_PER_MEASURE;
					break;
				case '[':
					fCurrentIncrementer = 1.0/24 * BEATS_PER_MEASURE;
					break;
				case '{':
					fCurrentIncrementer = 1.0/64 * BEATS_PER_MEASURE;
					break;
				case '`':
					fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
					break;
					
					// ends a series
				case ')':
				case ']':
				case '}':
				case '\'':
				case '>':
					fCurrentIncrementer = 1.0/8 * BEATS_PER_MEASURE;
					break;
					
				default:	// this is a note character
				{
					if( c == '!' )
					{
						LOG->UserLog(
							     "Song file",
							     path,
							     "has an unexpected character: '!'." );
						continue;
					}
					
					bool jump = false;
					if( c == '<' )
					{
						/* Arr.  Is this a jump or a 1/192 marker? */
						if( Is192( sStepData, i ) )
						{
							fCurrentIncrementer = 1.0/192 * BEATS_PER_MEASURE;
							break;
						}
						
						/* It's a jump.
						 * We need to keep reading notes until we hit a >. */
						jump = true;
						i++;
					}
					
					const int iIndex = BeatToNoteRow( (float)fCurrentBeat );
					i--;
					do {
						c = sStepData[i++];
						
						if( jump && c == '>' )
							break;
						
						int iCol1, iCol2;
						DWIcharToNoteCol(
								 c,
								 (GameController)pad,
								 iCol1,
								 iCol2,
								 path );
						
						if( iCol1 != -1 )
							newNoteData.SetTapNote(iCol1,
									       iIndex,
									       TAP_ORIGINAL_TAP);
						if( iCol2 != -1 )
							newNoteData.SetTapNote(iCol2,
									       iIndex,
									       TAP_ORIGINAL_TAP);
						
						if(i>=sStepData.length())
						{
							break;
							//we ran out of data
							//while looking for the ending > mark
						}
						
						if( sStepData[i] == '!' )
						{
							i++;
							const char holdChar = sStepData[i++];
							
							DWIcharToNoteCol(holdChar,
									 (GameController)pad,
									 iCol1,
									 iCol2,
									 path );
							
							if( iCol1 != -1 )
								newNoteData.SetTapNote(iCol1,
										       iIndex,
										       TAP_ORIGINAL_HOLD_HEAD);
							if( iCol2 != -1 )
								newNoteData.SetTapNote(iCol2,
										       iIndex,
										       TAP_ORIGINAL_HOLD_HEAD);
						}
					}
					while( jump );
					fCurrentBeat += fCurrentIncrementer;
				}
					break;
			}
		}
	}
	
	/* Fill in iDuration. */
	for( int t=0; t<newNoteData.GetNumTracks(); ++t )
	{
		FOREACH_NONEMPTY_ROW_IN_TRACK( newNoteData, t, iHeadRow )
		{
			TapNote tn = newNoteData.GetTapNote( t, iHeadRow  );
			if( tn.type != TapNote::hold_head )
				continue;
			
			int iTailRow = iHeadRow;
			bool bFound = false;
			while( !bFound && newNoteData.GetNextTapNoteRowForTrack(t, iTailRow) )
			{
				const TapNote &TailTap = newNoteData.GetTapNote( t, iTailRow );
				if( TailTap.type == TapNote::empty )
					continue;
				
				newNoteData.SetTapNote( t, iTailRow, TAP_EMPTY );
				tn.iDuration = iTailRow - iHeadRow;
				newNoteData.SetTapNote( t, iHeadRow, tn );
				bFound = true;
			}
			
			if( !bFound )
			{
				/* The hold was never closed.  */
				LOG->UserLog("Song file",
					     path,
					     "failed to close a hold note in \"%s\" on track %i", 
					     DifficultyToString(out.GetDifficulty()).c_str(),
					     t);
				
				newNoteData.SetTapNote( t, iHeadRow, TAP_EMPTY );
			}
		}
	}