- added a method to FileReader to read the contents into an array and used it on the MIDI sources for testing.

This commit is contained in:
Christoph Oelckers 2018-11-02 10:20:12 +01:00 committed by drfrag666
parent a2760d7da2
commit 0357cd451e
5 changed files with 62 additions and 71 deletions

View file

@ -184,6 +184,14 @@ public:
return mReader->Read(buffer, (long)len);
}
TArray<uint8_t> Read()
{
TArray<uint8_t> buffer(mReader->Length, true);
Size length = mReader->Read(&buffer[0], mReader->Length);
if (length < mReader->Length) buffer.Clear();
return buffer;
}
char *Gets(char *strbuf, Size len)
{
return mReader->Gets(strbuf, (int)len);

View file

@ -121,8 +121,7 @@ private:
uint32_t *SendCommand (uint32_t *event, TrackInfo *track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom);
TrackInfo *FindNextDue ();
uint8_t *MusHeader;
int SongLen;
TArray<uint8_t> MusHeader;
TrackInfo *Tracks;
TrackInfo *TrackDue;
int NumTracks;
@ -181,8 +180,7 @@ private:
static uint32_t ReadVarLenHMI(TrackInfo *);
static uint32_t ReadVarLenHMP(TrackInfo *);
uint8_t *MusHeader;
int SongLen;
TArray<uint8_t> MusHeader;
int NumTracks;
TrackInfo *Tracks;
TrackInfo *TrackDue;
@ -218,8 +216,7 @@ private:
uint32_t *SendCommand (uint32_t *event, EventSource track, uint32_t delay, ptrdiff_t room, bool &sysex_noroom);
EventSource FindNextDue();
uint8_t *MusHeader;
int SongLen; // length of the entire file
TArray<uint8_t> MusHeader;
int NumSongs;
TrackInfo *Songs;
TrackInfo *CurrSong;

View file

@ -133,19 +133,17 @@ HMISong::HMISong (FileReader &reader)
{ // Way too small to be HMI.
return;
}
MusHeader = new uint8_t[len];
SongLen = len;
MusHeader = reader.Read();
NumTracks = 0;
if (reader.Read(MusHeader, len) != len)
if (MusHeader.Size() == 0)
return;
// Do some validation of the MIDI file
if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0)
if (memcmp(&MusHeader[0], HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0)
{
SetupForHMI(len);
}
else if (((uint32_t *)MusHeader)[0] == MAKE_ID('H','M','I','M') &&
((uint32_t *)MusHeader)[1] == MAKE_ID('I','D','I','P'))
else if (memcmp(&MusHeader[0], "HMIMIDIP", 8) == 0)
{
SetupForHMP(len);
}
@ -159,14 +157,10 @@ HMISong::HMISong (FileReader &reader)
HMISong::~HMISong()
{
if (Tracks != NULL)
if (Tracks != nullptr)
{
delete[] Tracks;
}
if (MusHeader != NULL)
{
delete[] MusHeader;
}
}
//==========================================================================
@ -179,8 +173,10 @@ void HMISong::SetupForHMI(int len)
{
int i, p;
auto MusPtr = &MusHeader[0];
ReadVarLen = ReadVarLenHMI;
NumTracks = GetShort(MusHeader + HMI_TRACK_COUNT_OFFSET);
NumTracks = GetShort(MusPtr + HMI_TRACK_COUNT_OFFSET);
if (NumTracks <= 0)
{
@ -191,16 +187,16 @@ void HMISong::SetupForHMI(int len)
// HMI files have two values here, a full value and a quarter value. Some games,
// notably Quarantines, have identical values for some reason, so it's safer to
// use the quarter value and multiply it by four than to trust the full value.
Division = GetShort(MusHeader + HMI_DIVISION_OFFSET) << 2;
Division = GetShort(MusPtr + HMI_DIVISION_OFFSET) << 2;
Tempo = InitialTempo = 4000000;
Tracks = new TrackInfo[NumTracks + 1];
int track_dir = GetInt(MusHeader + HMI_TRACK_DIR_PTR_OFFSET);
int track_dir = GetInt(MusPtr + HMI_TRACK_DIR_PTR_OFFSET);
// Gather information about each track
for (i = 0, p = 0; i < NumTracks; ++i)
{
int start = GetInt(MusHeader + track_dir + i*4);
int start = GetInt(MusPtr + track_dir + i*4);
int tracklen, datastart;
if (start > len - HMITRACK_DESIGNATION_OFFSET - 4)
@ -209,7 +205,7 @@ void HMISong::SetupForHMI(int len)
}
// BTW, HMI does not actually check the track header.
if (memcmp(MusHeader + start, TRACK_MAGIC, 13) != 0)
if (memcmp(MusPtr + start, TRACK_MAGIC, 13) != 0)
{
continue;
}
@ -222,7 +218,7 @@ void HMISong::SetupForHMI(int len)
}
else
{
tracklen = GetInt(MusHeader + track_dir + i*4 + 4) - start;
tracklen = GetInt(MusPtr + track_dir + i*4 + 4) - start;
}
// Clamp incomplete tracks to the end of the file.
tracklen = MIN(tracklen, len - start);
@ -232,7 +228,7 @@ void HMISong::SetupForHMI(int len)
}
// Offset to actual MIDI events.
datastart = GetInt(MusHeader + start + HMITRACK_DATA_PTR_OFFSET);
datastart = GetInt(MusPtr + start + HMITRACK_DATA_PTR_OFFSET);
tracklen -= datastart;
if (tracklen <= 0)
{
@ -240,7 +236,7 @@ void HMISong::SetupForHMI(int len)
}
// Store track information
Tracks[p].TrackBegin = MusHeader + start + datastart;
Tracks[p].TrackBegin = MusPtr + start + datastart;
Tracks[p].TrackP = 0;
Tracks[p].MaxTrackP = tracklen;
@ -248,7 +244,7 @@ void HMISong::SetupForHMI(int len)
// connected to the MIDI device.
for (int ii = 0; ii < NUM_HMI_DESIGNATIONS; ++ii)
{
Tracks[p].Designation[ii] = GetShort(MusHeader + start + HMITRACK_DESIGNATION_OFFSET + ii*2);
Tracks[p].Designation[ii] = GetShort(MusPtr + start + HMITRACK_DESIGNATION_OFFSET + ii*2);
}
p++;
@ -270,12 +266,14 @@ void HMISong::SetupForHMP(int len)
int track_data;
int i, p;
auto MusPtr = &MusHeader[0];
ReadVarLen = ReadVarLenHMP;
if (MusHeader[8] == 0)
if (MusPtr[8] == 0)
{
track_data = HMP_TRACK_OFFSET_0;
}
else if (memcmp(MusHeader + 8, HMP_NEW_DATE, sizeof(HMP_NEW_DATE)) == 0)
else if (memcmp(MusPtr + 8, HMP_NEW_DATE, sizeof(HMP_NEW_DATE)) == 0)
{
track_data = HMP_TRACK_OFFSET_1;
}
@ -284,7 +282,7 @@ void HMISong::SetupForHMP(int len)
return;
}
NumTracks = GetInt(MusHeader + HMP_TRACK_COUNT_OFFSET);
NumTracks = GetInt(MusPtr + HMP_TRACK_COUNT_OFFSET);
if (NumTracks <= 0)
{
@ -292,7 +290,7 @@ void HMISong::SetupForHMP(int len)
}
// The division is the number of pulses per quarter note (PPQN).
Division = GetInt(MusHeader + HMP_DIVISION_OFFSET);
Division = GetInt(MusPtr + HMP_DIVISION_OFFSET);
Tempo = InitialTempo = 1000000;
Tracks = new TrackInfo[NumTracks + 1];
@ -308,7 +306,7 @@ void HMISong::SetupForHMP(int len)
break;
}
tracklen = GetInt(MusHeader + start + HMPTRACK_LEN_OFFSET);
tracklen = GetInt(MusPtr + start + HMPTRACK_LEN_OFFSET);
track_data += tracklen;
// Clamp incomplete tracks to the end of the file.
@ -326,7 +324,7 @@ void HMISong::SetupForHMP(int len)
}
// Store track information
Tracks[p].TrackBegin = MusHeader + start + HMPTRACK_MIDI_DATA_OFFSET;
Tracks[p].TrackBegin = MusPtr + start + HMPTRACK_MIDI_DATA_OFFSET;
Tracks[p].TrackP = 0;
Tracks[p].MaxTrackP = tracklen;
@ -337,14 +335,14 @@ void HMISong::SetupForHMP(int len)
// HMI files. Some songs contain nothing but zeroes for this data, so I'd rather
// not go around using it without confirmation.
Printf("Track %d: %d %08x %d: \034I", i, GetInt(MusHeader + start),
GetInt(MusHeader + start + 4), GetInt(MusHeader + start + 8));
Printf("Track %d: %d %08x %d: \034I", i, GetInt(MusPtr + start),
GetInt(MusPtr + start + 4), GetInt(MusPtr + start + 8));
int designations = HMP_DESIGNATIONS_OFFSET +
GetInt(MusHeader + start + HMPTRACK_DESIGNATION_OFFSET) * 4 * NUM_HMP_DESIGNATIONS;
GetInt(MusPtr + start + HMPTRACK_DESIGNATION_OFFSET) * 4 * NUM_HMP_DESIGNATIONS;
for (int ii = 0; ii < NUM_HMP_DESIGNATIONS; ++ii)
{
Printf(" %04x", GetInt(MusHeader + designations + ii*4));
Printf(" %04x", GetInt(MusPtr + designations + ii*4));
}
Printf("\n");
#endif
@ -478,7 +476,7 @@ void HMISong :: DoRestart()
bool HMISong::CheckDone()
{
return TrackDue == NULL;
return TrackDue == nullptr;
}
//==========================================================================
@ -968,7 +966,7 @@ void NoteOffQueue::Heapify()
//
// HMISong :: FindNextDue
//
// Scans every track for the next event to play. Returns NULL if all events
// Scans every track for the next event to play. Returns nullptr if all events
// have been consumed.
//
//==========================================================================
@ -991,7 +989,7 @@ HMISong::TrackInfo *HMISong::FindNextDue ()
}
// Check regular tracks.
track = NULL;
track = nullptr;
best = 0xFFFFFFFF;
for (i = 0; i < NumTracks; ++i)
{

View file

@ -102,13 +102,11 @@ struct MIDISong2::TrackInfo
MIDISong2::MIDISong2 (FileReader &reader)
: MusHeader(0), Tracks(0)
{
int p;
unsigned p;
int i;
SongLen = (int)reader.GetLength();
MusHeader = new uint8_t[SongLen];
if (reader.Read(MusHeader, SongLen) != SongLen)
return;
MusHeader = reader.Read();
if (MusHeader.Size() == 0) return;
// Do some validation of the MIDI file
if (MusHeader[4] != 0 || MusHeader[5] != 0 || MusHeader[6] != 0 || MusHeader[7] != 6)
@ -138,7 +136,7 @@ MIDISong2::MIDISong2 (FileReader &reader)
Tracks = new TrackInfo[NumTracks];
// Gather information about each track
for (i = 0, p = 14; i < NumTracks && p < SongLen + 8; ++i)
for (i = 0, p = 14; i < NumTracks && p < MusHeader.Size() + 8; ++i)
{
uint32_t chunkLen =
(MusHeader[p+4]<<24) |
@ -146,9 +144,9 @@ MIDISong2::MIDISong2 (FileReader &reader)
(MusHeader[p+6]<<8) |
(MusHeader[p+7]);
if (chunkLen + p + 8 > (uint32_t)SongLen)
if (chunkLen + p + 8 > MusHeader.Size())
{ // Track too long, so truncate it
chunkLen = SongLen - p - 8;
chunkLen = MusHeader.Size() - p - 8;
}
if (MusHeader[p+0] == 'M' &&
@ -156,7 +154,7 @@ MIDISong2::MIDISong2 (FileReader &reader)
MusHeader[p+2] == 'r' &&
MusHeader[p+3] == 'k')
{
Tracks[i].TrackBegin = MusHeader + p + 8;
Tracks[i].TrackBegin = &MusHeader[p + 8];
Tracks[i].TrackP = 0;
Tracks[i].MaxTrackP = chunkLen;
}
@ -182,14 +180,10 @@ MIDISong2::MIDISong2 (FileReader &reader)
MIDISong2::~MIDISong2 ()
{
if (Tracks != NULL)
if (Tracks != nullptr)
{
delete[] Tracks;
}
if (MusHeader != NULL)
{
delete[] MusHeader;
}
}
//==========================================================================
@ -277,7 +271,7 @@ void MIDISong2 :: DoRestart()
bool MIDISong2::CheckDone()
{
return TrackDue == NULL;
return TrackDue == nullptr;
}
//==========================================================================
@ -754,7 +748,7 @@ uint32_t MIDISong2::TrackInfo::ReadVarLen ()
//
// MIDISong2 :: FindNextDue
//
// Scans every track for the next event to play. Returns NULL if all events
// Scans every track for the next event to play. Returns nullptr if all events
// have been consumed.
//
//==========================================================================
@ -774,10 +768,10 @@ MIDISong2::TrackInfo *MIDISong2::FindNextDue ()
switch (Format)
{
case 0:
return Tracks[0].Finished ? NULL : Tracks;
return Tracks[0].Finished ? nullptr : Tracks;
case 1:
track = NULL;
track = nullptr;
best = 0xFFFFFFFF;
for (i = 0; i < NumTracks; ++i)
{
@ -798,9 +792,9 @@ MIDISong2::TrackInfo *MIDISong2::FindNextDue ()
{
track++;
}
return track < &Tracks[NumTracks] ? track : NULL;
return track < &Tracks[NumTracks] ? track : nullptr;
}
return NULL;
return nullptr;
}

View file

@ -108,13 +108,11 @@ struct XMISong::TrackInfo
XMISong::XMISong (FileReader &reader)
: MusHeader(0), Songs(0)
{
SongLen = (int)reader.GetLength();
MusHeader = new uint8_t[SongLen];
if (reader.Read(MusHeader, SongLen) != SongLen)
return;
MusHeader = reader.Read();
if (MusHeader.Size() == 0) return;
// Find all the songs in this file.
NumSongs = FindXMIDforms(MusHeader, SongLen, NULL);
NumSongs = FindXMIDforms(&MusHeader[0], MusHeader.Size(), nullptr);
if (NumSongs == 0)
{
return;
@ -132,7 +130,7 @@ XMISong::XMISong (FileReader &reader)
Songs = new TrackInfo[NumSongs];
memset(Songs, 0, sizeof(*Songs) * NumSongs);
FindXMIDforms(MusHeader, SongLen, Songs);
FindXMIDforms(&MusHeader[0], MusHeader.Size(), Songs);
CurrSong = Songs;
DPrintf(DMSG_SPAMMY, "XMI song count: %d\n", NumSongs);
}
@ -145,14 +143,10 @@ XMISong::XMISong (FileReader &reader)
XMISong::~XMISong ()
{
if (Songs != NULL)
if (Songs != nullptr)
{
delete[] Songs;
}
if (MusHeader != NULL)
{
delete[] MusHeader;
}
}
//==========================================================================
@ -176,7 +170,7 @@ int XMISong::FindXMIDforms(const uint8_t *chunk, int len, TrackInfo *songs) cons
{
if (GetNativeInt(chunk + p + 8) == MAKE_ID('X','M','I','D'))
{
if (songs != NULL)
if (songs != nullptr)
{
FoundXMID(chunk + p + 12, chunklen - 4, songs + count);
}