XMISong::XMISong (FileReader &reader, EMidiDevice type, const char *args)
: MIDIStreamer(type, args), MusHeader(0), Songs(0)
{
	SongLen = reader.GetLength();
	MusHeader = new uint8_t[SongLen];
	if (reader.Read(MusHeader, SongLen) != SongLen)
		return;

	// Find all the songs in this file.
	NumSongs = FindXMIDforms(MusHeader, SongLen, NULL);
	if (NumSongs == 0)
	{
		return;
	}

	// XMIDI files are played with a constant 120 Hz clock rate. While the
	// song may contain tempo events, these are vestigial remnants from the
	// original MIDI file that were not removed by the converter and should
	// be ignored.
	//
	// We can use any combination of Division and Tempo values that work out
	// to be 120 Hz.
	Division = 60;
	InitialTempo = 500000;

	Songs = new TrackInfo[NumSongs];
	memset(Songs, 0, sizeof(*Songs) * NumSongs);
	FindXMIDforms(MusHeader, SongLen, Songs);
	CurrSong = Songs;
	DPrintf(DMSG_SPAMMY, "XMI song count: %d\n", NumSongs);
}
示例#2
0
int XMISong::FindXMIDforms(const BYTE *chunk, int len, TrackInfo *songs) const
{
	int count = 0;

	for (int p = 0; p <= len - 12; )
	{
		int chunktype = GetNativeInt(chunk + p);
		int chunklen = GetBigInt(chunk + p + 4);

		if (chunktype == MAKE_ID('F','O','R','M'))
		{
			if (GetNativeInt(chunk + p + 8) == MAKE_ID('X','M','I','D'))
			{
				if (songs != NULL)
				{
					FoundXMID(chunk + p + 12, chunklen - 4, songs + count);
				}
				count++;
			}
		}
		else if (chunktype == MAKE_ID('C','A','T',' '))
		{
			// Recurse to handle CAT chunks.
			count += FindXMIDforms(chunk + p + 12, chunklen - 4, songs + count);
		}
		// IFF chunks are padded to even byte boundaries to avoid
		// unaligned reads on 68k processors.
		p += 8 + chunklen + (chunklen & 1);
		// Avoid crashes from corrupt chunks which indicate a negative size.
		if (chunklen < 0) p = len;
	}
	return count;
}
示例#3
0
XMISong::XMISong (FILE *file, BYTE *musiccache, int len, EMidiDevice type)
: MIDIStreamer(type), MusHeader(0), Songs(0)
{
#ifdef _WIN32
	if (ExitEvent == NULL)
	{
		return;
	}
#endif
	MusHeader = new BYTE[len];
	SongLen = len;
	if (file != NULL)
	{
		if (fread(MusHeader, 1, len, file) != (size_t)len)
			return;
	}
	else
	{
		memcpy(MusHeader, musiccache, len);
	}

	// Find all the songs in this file.
	NumSongs = FindXMIDforms(MusHeader, len, NULL);
	if (NumSongs == 0)
	{
		return;
	}

	// XMIDI files are played with a constant 120 Hz clock rate. While the
	// song may contain tempo events, these are vestigial remnants from the
	// original MIDI file that were not removed by the converter and should
	// be ignored.
	//
	// We can use any combination of Division and Tempo values that work out
	// to be 120 Hz.
	Division = 60;
	InitialTempo = 500000;

	Songs = new TrackInfo[NumSongs];
	memset(Songs, 0, sizeof(*Songs) * NumSongs);
	FindXMIDforms(MusHeader, len, Songs);
	CurrSong = Songs;
	DPrintf("XMI song count: %d\n", NumSongs);
}