diff options
-rw-r--r-- | src/i_oplmusic.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/src/i_oplmusic.c b/src/i_oplmusic.c index a2bc22d8..f38e7162 100644 --- a/src/i_oplmusic.c +++ b/src/i_oplmusic.c @@ -46,6 +46,9 @@ #define PERCUSSION_LOG_LEN 16 +// TODO: Figure out why this is needed. +#define TEMPO_FUDGE_FACTOR 0.26 + typedef struct { byte tremolo; @@ -103,11 +106,6 @@ typedef struct // Track iterator used to read new events. midi_track_iter_t *iter; - - // Tempo control variables - - unsigned int ticks_per_beat; - unsigned int ms_per_beat; } opl_track_data_t; typedef struct opl_voice_s opl_voice_t; @@ -324,6 +322,11 @@ static unsigned int num_tracks = 0; static unsigned int running_tracks = 0; static boolean song_looping; +// Tempo control variables + +static unsigned int ticks_per_beat; +static unsigned int us_per_beat; + // Mini-log of recently played percussion instruments: static uint8_t last_perc[PERCUSSION_LOG_LEN]; @@ -1017,6 +1020,9 @@ static void PitchBendEvent(opl_track_data_t *track, midi_event_t *event) static void MetaEvent(opl_track_data_t *track, midi_event_t *event) { + byte *data = event->data.meta.data; + unsigned int data_len = event->data.meta.length; + switch (event->data.meta.type) { // Things we can just ignore. @@ -1032,6 +1038,13 @@ static void MetaEvent(opl_track_data_t *track, midi_event_t *event) case MIDI_META_SEQUENCER_SPECIFIC: break; + case MIDI_META_SET_TEMPO: + if (data_len == 3) + { + us_per_beat = (data[0] << 16) | (data[1] << 8) | data[2]; + } + break; + // End of track - actually handled when we run out of events // in the track, see below. @@ -1161,7 +1174,7 @@ static void ScheduleTrack(opl_track_data_t *track) // Get the number of milliseconds until the next event. nticks = MIDI_GetDeltaTime(track->iter); - ms = (nticks * track->ms_per_beat) / track->ticks_per_beat; + ms = (nticks * us_per_beat * TEMPO_FUDGE_FACTOR) / ticks_per_beat; total += ms; // Set a timer to be invoked when the next event is @@ -1190,12 +1203,6 @@ static void StartTrack(midi_file_t *file, unsigned int track_num) track = &tracks[track_num]; track->iter = MIDI_IterateTrack(file, track_num); - track->ticks_per_beat = MIDI_GetFileTimeDivision(file); - - // Default is 120 bpm. - // TODO: this is wrong - - track->ms_per_beat = 500 * 260; for (i=0; i<MIDI_CHANNELS_PER_TRACK; ++i) { @@ -1229,6 +1236,13 @@ static void I_OPL_PlaySong(void *handle, boolean looping) running_tracks = num_tracks; song_looping = looping; + ticks_per_beat = MIDI_GetFileTimeDivision(file); + + // Default is 120 bpm. + // TODO: this is wrong + + us_per_beat = 500 * 1000; + for (i=0; i<num_tracks; ++i) { StartTrack(file, i); |