⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trackdata.cpp

📁 游戏编程精粹2第六章源码
💻 CPP
字号:
/* Copyright (C) Scott Patterson, 2001. 
 * All rights reserved worldwide.
 *
 * This software is provided "as is" without express or implied
 * warranties. You may freely copy and compile this source into
 * applications you distribute provided that the copyright text
 * below is included in the resulting source code, for example:
 * "Portions Copyright (C) Scott Patterson, 2001"
 */

// TrackData.cpp

#include "StdAfx.h"
#include "EventData.h"
#include "TrackData.h"
#include "Portable.h"
#include "MIDIDef.h"

void TrackData_t::Init( u8 *pData, int nTrack )
{
	u8 aBuffer[4];
	u8 *pByte;
	u8 *pTrack;
	s32 nTrackLength;
	
	m_pData = pData;

	pTrack = m_pData;
	while (nTrack--)
    {
		pByte = pTrack;
		pByte += 4;
		memcpy(aBuffer,pByte,sizeof(aBuffer));
		nTrackLength = Portable_ConvertStringToS32(aBuffer)+8L;
		pTrack += nTrackLength;
    }

	pByte = pTrack;
	pByte += 4;

	//memcpy(aBuffer,pByte,sizeof(aBuffer));
	//nTrackLength = Portable_ConvertStringToS32(aBuffer);
	pByte += 4;

	m_pCurrent = pByte;
	m_nCurrentCommand = 0x90;
	m_nCurrentCommandLength = 2;
	m_bTrackEnd = false;
	m_bIsTempoTrack = false;
	m_nTempo = 120;
}

u8 TrackData_t::ReadU8()
{
	return(*m_pCurrent++);
}

static const int _CommandLength[8] = {2,2,2,2,1,1,2,0};

int _GetCommandLength(u8 nCmd)
{
	return (_CommandLength[(nCmd >> 4) & 7]);
}

bool TrackData_t::ReadNextEvent( u8 *pnType, s32 *pnTime, u8 *pnStatus, u8 **ppData, u32 *pnLength )
{
	u32 i;
	u8 nNewByte;
	u8 *pBuffer;
    static u8 aBuffer[4];
	
	// read delta-time
	*pnTime=ReadVariableLengthQuantity();
	
	// read command
	nNewByte = ReadU8();
	switch (nNewByte)
    {
	case 0xF0:
	case 0xF7:
        *pnType=MIDIDEF_SYSEXEVENT;
        *pnStatus = nNewByte;
        *pnLength = (u32)ReadVariableLengthQuantity();
        *ppData = m_pCurrent;
        m_pCurrent += *pnLength;
        break;
	case 0xFF:
        *pnType = MIDIDEF_METAEVENT;
        *pnStatus = ReadU8();
        *pnLength = (u32)ReadVariableLengthQuantity();
        *ppData = m_pCurrent;
        m_pCurrent += *pnLength;

        if (*pnStatus == MIDIDEF_METATEMPO)
		{
			u32 nTemp, nTempo;
			nTemp = ((*ppData)[0] << 16) | ((*ppData)[1] << 8) | ((*ppData)[2]);
			nTempo = 60000000L / nTemp;
			m_bIsTempoTrack = true;
			m_nTempo = nTempo;
		}

        if (*pnStatus == MIDIDEF_METAEOT)
		{
			m_bTrackEnd = true;
		}
        break;
	default:
        *pnType = MIDIDEF_MIDIEVENT;
        if (nNewByte & 0x80)
		{
			// running status
			m_nCurrentCommand = nNewByte;
            *pnStatus = m_nCurrentCommand;
            m_nCurrentCommandLength = _GetCommandLength(m_nCurrentCommand);
			*pnLength = m_nCurrentCommandLength;
            for (i=0, pBuffer = aBuffer; i < m_nCurrentCommandLength; i++)
			{
				*pBuffer++ = ReadU8();
			}
            *ppData = (u8 *)aBuffer;
		}
        else
		{
            *pnStatus = m_nCurrentCommand;
            *pnLength = m_nCurrentCommandLength;
            pBuffer = aBuffer;
            *pBuffer++ = nNewByte;
            for (i=1; i < m_nCurrentCommandLength; i++)
			{
				*pBuffer++ = ReadU8();
			}
            *ppData = (u8 *)aBuffer;
		}
        break;
    }
	
	return(!m_bTrackEnd);
}

s32 TrackData_t::ReadVariableLengthQuantity()
{
	s32 nValue;
	u8 nByte;
	
	if ((nValue = ReadU8()) & 0x80)
    {
		nValue &= 0x7F;
		do
		{
			nValue = (nValue << 7) + ((nByte = ReadU8()) & 0x7F);
        } while (nByte & 0x80);
    }
	return nValue;
}

TrackData_t::TrackData_t()
{
	m_pData = 0;
    m_pCurrent = 0;
    m_nCurrentCommand = 0;
    m_nCurrentCommandLength = 0;
	
	m_bTrackEnd = false;
}

TrackData_t::~TrackData_t()
{
	EventDataPtrList_t::iterator iEDL;

	for( iEDL = m_EventDataPtrList.begin(); iEDL != m_EventDataPtrList.end(); ++iEDL )
	{
		delete *iEDL;
	}
}

bool TrackData_t::Load( unsigned char *pData, int nTrack )
{
	bool bMore = true;

	Init( pData, nTrack );

	do
	{
		EventData_t *pEventData = new EventData_t;

		u8	nEventType;
		s32	nEventTime;
		u8	nEventStatus;
		u8  *pnEventData;
		u32	nEventLength;

		bMore = ReadNextEvent(&nEventType,
								  &nEventTime,
								  &nEventStatus,
								  &pnEventData,
								  &nEventLength);

		pEventData->SetEventType( nEventType );
		pEventData->SetEventTime( nEventTime );
		pEventData->SetEventStatus( nEventStatus );
		pEventData->SetEventData( pnEventData, nEventLength );

		// here we determine the runtime command ID for this event
		pEventData->SetRuntimeCommand();

		PushBackEvent( pEventData );

	} while( bMore );

	return true;
}

bool TrackData_t::IsTempoTrack()
{
	return m_bIsTempoTrack;
}

u32 TrackData_t::GetTempo()
{
	return m_nTempo;
}

void TrackData_t::Print()
{
	EventDataPtrList_t::iterator iEDL;

	printf( "  Track: \n" );

	for( iEDL = m_EventDataPtrList.begin(); iEDL != m_EventDataPtrList.end(); ++ iEDL )
	{
		EventData_t *pEventData = *iEDL;

		pEventData->Print();
	}
}

void TrackData_t::PushBackEvent( EventData_t *pEventData )
{
	m_EventDataPtrList.push_back( pEventData );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -