mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-25 05:31:00 +00:00
- Added HMP file support.
SVN r2849 (trunk)
This commit is contained in:
parent
46eebe29a4
commit
4397ef3323
3 changed files with 230 additions and 42 deletions
|
@ -463,6 +463,13 @@ MusInfo *I_RegisterSong (const char *filename, BYTE *musiccache, int offset, int
|
||||||
{
|
{
|
||||||
miditype = MIDI_HMI;
|
miditype = MIDI_HMI;
|
||||||
}
|
}
|
||||||
|
// Check for HMP format
|
||||||
|
else
|
||||||
|
if (id[0] == MAKE_ID('H','M','I','M') &&
|
||||||
|
id[1] == MAKE_ID('I','D','I','P'))
|
||||||
|
{
|
||||||
|
miditype = MIDI_HMI;
|
||||||
|
}
|
||||||
// Check for MIDI format
|
// Check for MIDI format
|
||||||
else if (id[0] == MAKE_ID('M','T','h','d'))
|
else if (id[0] == MAKE_ID('M','T','h','d'))
|
||||||
{
|
{
|
||||||
|
|
|
@ -500,6 +500,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
HMISong(const HMISong *original, const char *filename, EMIDIDevice type); // file dump constructor
|
HMISong(const HMISong *original, const char *filename, EMIDIDevice type); // file dump constructor
|
||||||
|
|
||||||
|
void SetupForHMI(int len);
|
||||||
|
void SetupForHMP(int len);
|
||||||
void CheckCaps(int tech);
|
void CheckCaps(int tech);
|
||||||
void DoInitialSetup();
|
void DoInitialSetup();
|
||||||
void DoRestart();
|
void DoRestart();
|
||||||
|
@ -514,6 +516,9 @@ protected:
|
||||||
TrackInfo *FindNextDue ();
|
TrackInfo *FindNextDue ();
|
||||||
void SetTempo(int new_tempo);
|
void SetTempo(int new_tempo);
|
||||||
|
|
||||||
|
static DWORD ReadVarLenHMI(TrackInfo *);
|
||||||
|
static DWORD ReadVarLenHMP(TrackInfo *);
|
||||||
|
|
||||||
struct AutoNoteOff
|
struct AutoNoteOff
|
||||||
{
|
{
|
||||||
DWORD Delay;
|
DWORD Delay;
|
||||||
|
@ -541,6 +546,7 @@ protected:
|
||||||
TrackInfo *Tracks;
|
TrackInfo *Tracks;
|
||||||
TrackInfo *TrackDue;
|
TrackInfo *TrackDue;
|
||||||
TrackInfo *FakeTrack;
|
TrackInfo *FakeTrack;
|
||||||
|
DWORD (*ReadVarLen)(TrackInfo *);
|
||||||
NoteOffQueue NoteOffs;
|
NoteOffQueue NoteOffs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
#define SONG_MAGIC "HMI-MIDISONG061595"
|
#define HMP_NEW_DATE "013195"
|
||||||
|
#define HMI_SONG_MAGIC "HMI-MIDISONG061595"
|
||||||
#define TRACK_MAGIC "HMI-MIDITRACK"
|
#define TRACK_MAGIC "HMI-MIDITRACK"
|
||||||
|
|
||||||
// Used by SendCommand to check for unexpected end-of-track conditions.
|
// Used by SendCommand to check for unexpected end-of-track conditions.
|
||||||
|
@ -53,15 +54,26 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// In song header
|
// In song header
|
||||||
#define DIVISION_OFFSET 0xD2
|
#define HMI_DIVISION_OFFSET 0xD2
|
||||||
#define TRACK_COUNT_OFFSET 0xE4
|
#define HMI_TRACK_COUNT_OFFSET 0xE4
|
||||||
#define TRACK_DIR_PTR_OFFSET 0xE8
|
#define HMI_TRACK_DIR_PTR_OFFSET 0xE8
|
||||||
|
|
||||||
|
#define HMP_DIVISION_OFFSET 0x38
|
||||||
|
#define HMP_TRACK_COUNT_OFFSET 0x30
|
||||||
|
#define HMP_DESIGNATIONS_OFFSET 0x94
|
||||||
|
#define HMP_TRACK_OFFSET_0 0x308 // original HMP
|
||||||
|
#define HMP_TRACK_OFFSET_1 0x388 // newer HMP
|
||||||
|
|
||||||
// In track header
|
// In track header
|
||||||
#define TRACK_DATA_PTR_OFFSET 0x57
|
#define HMITRACK_DATA_PTR_OFFSET 0x57
|
||||||
#define TRACK_DESIGNATION_OFFSET 0x99
|
#define HMITRACK_DESIGNATION_OFFSET 0x99
|
||||||
|
|
||||||
#define NUM_DESIGNATIONS 8
|
#define HMPTRACK_LEN_OFFSET 4
|
||||||
|
#define HMPTRACK_DESIGNATION_OFFSET 8
|
||||||
|
#define HMPTRACK_MIDI_DATA_OFFSET 12
|
||||||
|
|
||||||
|
#define NUM_HMP_DESIGNATIONS 5
|
||||||
|
#define NUM_HMI_DESIGNATIONS 8
|
||||||
|
|
||||||
// MIDI device types for designation
|
// MIDI device types for designation
|
||||||
#define HMI_DEV_GM 0xA000 // Generic General MIDI (not a real device)
|
#define HMI_DEV_GM 0xA000 // Generic General MIDI (not a real device)
|
||||||
|
@ -103,12 +115,13 @@ struct HMISong::TrackInfo
|
||||||
size_t MaxTrackP;
|
size_t MaxTrackP;
|
||||||
DWORD Delay;
|
DWORD Delay;
|
||||||
DWORD PlayedTime;
|
DWORD PlayedTime;
|
||||||
WORD Designation[NUM_DESIGNATIONS];
|
WORD Designation[NUM_HMI_DESIGNATIONS];
|
||||||
bool Enabled;
|
bool Enabled;
|
||||||
bool Finished;
|
bool Finished;
|
||||||
BYTE RunningStatus;
|
BYTE RunningStatus;
|
||||||
|
|
||||||
DWORD ReadVarLen ();
|
DWORD ReadVarLenHMI();
|
||||||
|
DWORD ReadVarLenHMP();
|
||||||
};
|
};
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
@ -139,9 +152,6 @@ extern char MIDI_CommonLengths[15];
|
||||||
HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
||||||
: MIDIStreamer(type), MusHeader(0), Tracks(0)
|
: MIDIStreamer(type), MusHeader(0), Tracks(0)
|
||||||
{
|
{
|
||||||
int p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (ExitEvent == NULL)
|
if (ExitEvent == NULL)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +164,7 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
||||||
}
|
}
|
||||||
MusHeader = new BYTE[len];
|
MusHeader = new BYTE[len];
|
||||||
SongLen = len;
|
SongLen = len;
|
||||||
|
NumTracks = 0;
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
{
|
{
|
||||||
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
if (fread(MusHeader, 1, len, file) != (size_t)len)
|
||||||
|
@ -165,21 +176,59 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do some validation of the MIDI file
|
// Do some validation of the MIDI file
|
||||||
if (memcmp(MusHeader, SONG_MAGIC, sizeof(SONG_MAGIC)) != 0)
|
if (memcmp(MusHeader, HMI_SONG_MAGIC, sizeof(HMI_SONG_MAGIC)) == 0)
|
||||||
return;
|
{
|
||||||
|
SetupForHMI(len);
|
||||||
|
}
|
||||||
|
else if (((DWORD *)MusHeader)[0] == MAKE_ID('H','M','I','M') &&
|
||||||
|
((DWORD *)MusHeader)[1] == MAKE_ID('I','D','I','P'))
|
||||||
|
{
|
||||||
|
SetupForHMP(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// HMISong Destructor
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
HMISong::~HMISong()
|
||||||
|
{
|
||||||
|
if (Tracks != NULL)
|
||||||
|
{
|
||||||
|
delete[] Tracks;
|
||||||
|
}
|
||||||
|
if (MusHeader != NULL)
|
||||||
|
{
|
||||||
|
delete[] MusHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// HMISong :: SetupForHMI
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void HMISong::SetupForHMI(int len)
|
||||||
|
{
|
||||||
|
int i, p;
|
||||||
|
|
||||||
|
ReadVarLen = ReadVarLenHMI;
|
||||||
|
NumTracks = GetShort(MusHeader + HMI_TRACK_COUNT_OFFSET);
|
||||||
|
|
||||||
NumTracks = GetShort(MusHeader + TRACK_COUNT_OFFSET);
|
|
||||||
if (NumTracks <= 0)
|
if (NumTracks <= 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The division is the number of pulses per quarter note (PPQN).
|
// The division is the number of pulses per quarter note (PPQN).
|
||||||
Division = GetShort(MusHeader + DIVISION_OFFSET);
|
Division = GetShort(MusHeader + HMI_DIVISION_OFFSET);
|
||||||
InitialTempo = 4000000;
|
InitialTempo = 4000000;
|
||||||
|
|
||||||
Tracks = new TrackInfo[NumTracks + 1];
|
Tracks = new TrackInfo[NumTracks + 1];
|
||||||
int track_dir = GetInt(MusHeader + TRACK_DIR_PTR_OFFSET);
|
int track_dir = GetInt(MusHeader + HMI_TRACK_DIR_PTR_OFFSET);
|
||||||
|
|
||||||
// Gather information about each track
|
// Gather information about each track
|
||||||
for (i = 0, p = 0; i < NumTracks; ++i)
|
for (i = 0, p = 0; i < NumTracks; ++i)
|
||||||
|
@ -187,7 +236,7 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
||||||
int start = GetInt(MusHeader + track_dir + i*4);
|
int start = GetInt(MusHeader + track_dir + i*4);
|
||||||
int tracklen, datastart;
|
int tracklen, datastart;
|
||||||
|
|
||||||
if (start > len - TRACK_DESIGNATION_OFFSET - 4)
|
if (start > len - HMITRACK_DESIGNATION_OFFSET - 4)
|
||||||
{ // Track is incomplete.
|
{ // Track is incomplete.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -216,7 +265,7 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offset to actual MIDI events.
|
// Offset to actual MIDI events.
|
||||||
datastart = GetInt(MusHeader + start + TRACK_DATA_PTR_OFFSET);
|
datastart = GetInt(MusHeader + start + HMITRACK_DATA_PTR_OFFSET);
|
||||||
tracklen -= datastart;
|
tracklen -= datastart;
|
||||||
if (tracklen <= 0)
|
if (tracklen <= 0)
|
||||||
{
|
{
|
||||||
|
@ -230,9 +279,9 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
||||||
|
|
||||||
// Retrieve track designations. We can't check them yet, since we have not yet
|
// Retrieve track designations. We can't check them yet, since we have not yet
|
||||||
// connected to the MIDI device.
|
// connected to the MIDI device.
|
||||||
for (int ii = 0; ii < NUM_DESIGNATIONS; ++ii)
|
for (int ii = 0; ii < NUM_HMI_DESIGNATIONS; ++ii)
|
||||||
{
|
{
|
||||||
Tracks[p].Designation[ii] = GetShort(MusHeader + start + TRACK_DESIGNATION_OFFSET + ii*2);
|
Tracks[p].Designation[ii] = GetShort(MusHeader + start + HMITRACK_DESIGNATION_OFFSET + ii*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
|
@ -241,29 +290,108 @@ HMISong::HMISong (FILE *file, BYTE *musiccache, int len, EMIDIDevice type)
|
||||||
// In case there were fewer actual chunks in the file than the
|
// In case there were fewer actual chunks in the file than the
|
||||||
// header specified, update NumTracks with the current value of p.
|
// header specified, update NumTracks with the current value of p.
|
||||||
NumTracks = p;
|
NumTracks = p;
|
||||||
|
|
||||||
if (NumTracks == 0)
|
|
||||||
{ // No tracks, so nothing to play
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// HMISong Destructor
|
// HMISong :: SetupForHMP
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
HMISong::~HMISong ()
|
void HMISong::SetupForHMP(int len)
|
||||||
{
|
{
|
||||||
if (Tracks != NULL)
|
int track_data;
|
||||||
|
int i, p;
|
||||||
|
|
||||||
|
ReadVarLen = ReadVarLenHMP;
|
||||||
|
if (MusHeader[8] == 0)
|
||||||
{
|
{
|
||||||
delete[] Tracks;
|
track_data = HMP_TRACK_OFFSET_0;
|
||||||
}
|
}
|
||||||
if (MusHeader != NULL)
|
else if (memcmp(MusHeader + 8, HMP_NEW_DATE, sizeof(HMP_NEW_DATE)) == 0)
|
||||||
{
|
{
|
||||||
delete[] MusHeader;
|
track_data = HMP_TRACK_OFFSET_1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{ // unknown HMIMIDIP version
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NumTracks = GetInt(MusHeader + HMP_TRACK_COUNT_OFFSET);
|
||||||
|
|
||||||
|
if (NumTracks <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The division is the number of pulses per quarter note (PPQN).
|
||||||
|
Division = GetInt(MusHeader + HMP_DIVISION_OFFSET);
|
||||||
|
InitialTempo = 1000000;
|
||||||
|
|
||||||
|
Tracks = new TrackInfo[NumTracks + 1];
|
||||||
|
|
||||||
|
// Gather information about each track
|
||||||
|
for (i = 0, p = 0; i < NumTracks; ++i)
|
||||||
|
{
|
||||||
|
int start = track_data;
|
||||||
|
int tracklen;
|
||||||
|
|
||||||
|
if (start > len - HMPTRACK_MIDI_DATA_OFFSET)
|
||||||
|
{ // Track is incomplete.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracklen = GetInt(MusHeader + start + HMPTRACK_LEN_OFFSET);
|
||||||
|
track_data += tracklen;
|
||||||
|
|
||||||
|
// Clamp incomplete tracks to the end of the file.
|
||||||
|
tracklen = MIN(tracklen, len - start);
|
||||||
|
if (tracklen <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subtract track header size.
|
||||||
|
tracklen -= HMPTRACK_MIDI_DATA_OFFSET;
|
||||||
|
if (tracklen <= 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store track information
|
||||||
|
Tracks[p].TrackBegin = MusHeader + start + HMPTRACK_MIDI_DATA_OFFSET;
|
||||||
|
Tracks[p].TrackP = 0;
|
||||||
|
Tracks[p].MaxTrackP = tracklen;
|
||||||
|
|
||||||
|
// Retrieve track designations. We can't check them yet, since we have not yet
|
||||||
|
// connected to the MIDI device.
|
||||||
|
#if 0
|
||||||
|
// This is completely a guess based on knowledge of how designations work with
|
||||||
|
// 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));
|
||||||
|
|
||||||
|
int designations = HMP_DESIGNATIONS_OFFSET +
|
||||||
|
GetInt(MusHeader + 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("\n");
|
||||||
|
#endif
|
||||||
|
Tracks[p].Designation[0] = HMI_DEV_GM;
|
||||||
|
Tracks[p].Designation[1] = HMI_DEV_GUS;
|
||||||
|
Tracks[p].Designation[2] = HMI_DEV_OPL2;
|
||||||
|
Tracks[p].Designation[3] = 0;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case there were fewer actual chunks in the file than the
|
||||||
|
// header specified, update NumTracks with the current value of p.
|
||||||
|
NumTracks = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -295,7 +423,7 @@ void HMISong::CheckCaps(int tech)
|
||||||
{
|
{
|
||||||
Tracks[i].Enabled = false;
|
Tracks[i].Enabled = false;
|
||||||
// Track designations are stored in a 0-terminated array.
|
// Track designations are stored in a 0-terminated array.
|
||||||
for (int j = 0; j < NUM_DESIGNATIONS && Tracks[i].Designation[j] != 0; ++j)
|
for (int j = 0; j < countof(Tracks[i].Designation) && Tracks[i].Designation[j] != 0; ++j)
|
||||||
{
|
{
|
||||||
if (Tracks[i].Designation[j] == tech)
|
if (Tracks[i].Designation[j] == tech)
|
||||||
{
|
{
|
||||||
|
@ -367,7 +495,7 @@ void HMISong :: DoRestart()
|
||||||
ProcessInitialMetaEvents ();
|
ProcessInitialMetaEvents ();
|
||||||
for (i = 0; i < NumTracks; ++i)
|
for (i = 0; i < NumTracks; ++i)
|
||||||
{
|
{
|
||||||
Tracks[i].Delay = Tracks[i].ReadVarLen();
|
Tracks[i].Delay = ReadVarLen(&Tracks[i]);
|
||||||
}
|
}
|
||||||
Tracks[i].Delay = 0; // for the FakeTrack
|
Tracks[i].Delay = 0; // for the FakeTrack
|
||||||
Tracks[i].Enabled = true;
|
Tracks[i].Enabled = true;
|
||||||
|
@ -534,9 +662,9 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
}
|
}
|
||||||
events += 3;
|
events += 3;
|
||||||
|
|
||||||
if ((event & 0x70) == (MIDI_NOTEON & 0x70))
|
if (ReadVarLen == ReadVarLenHMI && (event & 0x70) == (MIDI_NOTEON & 0x70))
|
||||||
{ // HMI note on events include the time until an implied note off event.
|
{ // HMI note on events include the time until an implied note off event.
|
||||||
NoteOffs.AddNoteOff(track->ReadVarLen(), event & 0x0F, data1);
|
NoteOffs.AddNoteOff(track->ReadVarLenHMI(), event & 0x0F, data1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -546,7 +674,7 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
// anything that played before.
|
// anything that played before.
|
||||||
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
if (event == MIDI_SYSEX || event == MIDI_SYSEXEND)
|
||||||
{
|
{
|
||||||
len = track->ReadVarLen ();
|
len = ReadVarLen(track);
|
||||||
track->TrackP += len;
|
track->TrackP += len;
|
||||||
}
|
}
|
||||||
else if (event == MIDI_META)
|
else if (event == MIDI_META)
|
||||||
|
@ -554,7 +682,7 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
// It's a meta-event
|
// It's a meta-event
|
||||||
event = track->TrackBegin[track->TrackP++];
|
event = track->TrackBegin[track->TrackP++];
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
len = track->ReadVarLen ();
|
len = ReadVarLen(track);
|
||||||
CHECK_FINISHED
|
CHECK_FINISHED
|
||||||
|
|
||||||
if (track->TrackP + len <= track->MaxTrackP)
|
if (track->TrackP + len <= track->MaxTrackP)
|
||||||
|
@ -614,7 +742,7 @@ DWORD *HMISong::SendCommand (DWORD *events, TrackInfo *track, DWORD delay)
|
||||||
}
|
}
|
||||||
if (!track->Finished)
|
if (!track->Finished)
|
||||||
{
|
{
|
||||||
track->Delay = track->ReadVarLen();
|
track->Delay = ReadVarLen(track);
|
||||||
}
|
}
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
@ -644,7 +772,7 @@ void HMISong::ProcessInitialMetaEvents ()
|
||||||
{
|
{
|
||||||
event = track->TrackBegin[track->TrackP+2];
|
event = track->TrackBegin[track->TrackP+2];
|
||||||
track->TrackP += 3;
|
track->TrackP += 3;
|
||||||
len = track->ReadVarLen ();
|
len = ReadVarLen(track);
|
||||||
if (track->TrackP + len <= track->MaxTrackP)
|
if (track->TrackP + len <= track->MaxTrackP)
|
||||||
{
|
{
|
||||||
switch (event)
|
switch (event)
|
||||||
|
@ -673,13 +801,35 @@ void HMISong::ProcessInitialMetaEvents ()
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// HMISong :: TrackInfo :: ReadVarLen
|
// HMISong :: ReadVarLenHMI static
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
DWORD HMISong::ReadVarLenHMI(TrackInfo *track)
|
||||||
|
{
|
||||||
|
return track->ReadVarLenHMI();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// HMISong :: ReadVarLenHMP static
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
DWORD HMISong::ReadVarLenHMP(TrackInfo *track)
|
||||||
|
{
|
||||||
|
return track->ReadVarLenHMP();
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// HMISong :: TrackInfo :: ReadVarLenHMI
|
||||||
//
|
//
|
||||||
// Reads a variable-length SMF number.
|
// Reads a variable-length SMF number.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
DWORD HMISong::TrackInfo::ReadVarLen ()
|
DWORD HMISong::TrackInfo::ReadVarLenHMI()
|
||||||
{
|
{
|
||||||
DWORD time = 0, t = 0x80;
|
DWORD time = 0, t = 0x80;
|
||||||
|
|
||||||
|
@ -691,6 +841,31 @@ DWORD HMISong::TrackInfo::ReadVarLen ()
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// HMISong :: TrackInfo :: ReadVarLenHMP
|
||||||
|
//
|
||||||
|
// Reads a variable-length HMP number. This is similar to the standard SMF
|
||||||
|
// variable length number, except it's stored little-endian, and the high
|
||||||
|
// bit set means the number is done.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
DWORD HMISong::TrackInfo::ReadVarLenHMP()
|
||||||
|
{
|
||||||
|
DWORD time = 0;
|
||||||
|
BYTE t = 0;
|
||||||
|
int off = 0;
|
||||||
|
|
||||||
|
while (!(t & 0x80) && TrackP < MaxTrackP)
|
||||||
|
{
|
||||||
|
t = TrackBegin[TrackP++];
|
||||||
|
time |= (t & 127) << off;
|
||||||
|
off += 7;
|
||||||
|
}
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// HMISong :: NoteOffQueue :: AddNoteOff
|
// HMISong :: NoteOffQueue :: AddNoteOff
|
||||||
|
|
Loading…
Reference in a new issue