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); }
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; }
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); }