diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | src/mus2mid.c | 91 |
2 files changed, 79 insertions, 14 deletions
@@ -79,6 +79,8 @@ linedef is one sided (thanks Alexander Waldmann). * Key settings in a configuration file that are out of range do not cause a crash (thanks entryway). + * Fix ear-piercing whistle when playing the MAP05 MIDI music + using timidity with EAWPATS (thanks entryway / HackNeyed). libtextscreen: * There is now a second, small textscreen font, so that the diff --git a/src/mus2mid.c b/src/mus2mid.c index f84be548..3fea1462 100644 --- a/src/mus2mid.c +++ b/src/mus2mid.c @@ -32,6 +32,11 @@ #include "memio.h" #include "mus2mid.h" +#define NUM_CHANNELS 16 + +#define MIDI_PERCUSSION_CHAN 9 +#define MUS_PERCUSSION_CHAN 15 + // MUS event codes typedef enum { @@ -100,6 +105,8 @@ static byte mus2midi_translation[] = 0x40, 0x43, 0x78, 0x7B, 0x7E, 0x7F, 0x79 }; +static int channel_map[NUM_CHANNELS]; + // Write timestamp to a MIDI file. static boolean midi_writetime(unsigned int time, MEMFILE *midioutput) @@ -346,6 +353,68 @@ static boolean midi_writechangecontroller_valueless(byte channel, midioutput); } +// Allocate a free MIDI channel. + +static int midi_allocate_channel(void) +{ + int result; + int max; + int i; + + // Find the current highest-allocated channel. + + max = -1; + + for (i=0; i<NUM_CHANNELS; ++i) + { + if (channel_map[i] > max) + { + max = channel_map[i]; + } + } + + // max is now equal to the highest-allocated MIDI channel. We can + // now allocate the next available channel. This also works if + // no channels are currently allocated (max=-1) + + result = max + 1; + + // Don't allocate the MIDI percussion channel! + + if (result == MIDI_PERCUSSION_CHAN) + { + ++result; + } + + return result; +} + +// Given a MUS channel number, get the MIDI channel number to use +// in the outputted file. + +static int midi_get_channel(int mus_channel) +{ + // Find the MIDI channel to use for this MUS channel. + // MUS channel 15 is the percusssion channel. + + if (mus_channel == MUS_PERCUSSION_CHAN) + { + return MIDI_PERCUSSION_CHAN; + } + else + { + // If a MIDI channel hasn't been allocated for this MUS channel + // yet, allocate the next free MIDI channel. + + if (channel_map[mus_channel] == -1) + { + channel_map[mus_channel] = midi_allocate_channel(); + } + + return channel_map[mus_channel]; + } +} + static boolean read_musheader(MEMFILE *file, musheader *header) { boolean result; @@ -402,6 +471,13 @@ boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput) // Used in building up time delays unsigned int timedelay; + // Initialise channel map to mark all channels as unused. + + for (channel=0; channel<NUM_CHANNELS; ++channel) + { + channel_map[channel] = -1; + } + // Grab the header if (!read_musheader(musinput, &musfileheader)) @@ -447,22 +523,9 @@ boolean mus2mid(MEMFILE *musinput, MEMFILE *midioutput) return true; } - channel = eventdescriptor & 0x0F; + channel = midi_get_channel(eventdescriptor & 0x0F); event = eventdescriptor & 0x70; - // Swap channels 15 and 9. - // MIDI channel 9 = percussion. - // MUS channel 15 = percussion. - - if (channel == 15) - { - channel = 9; - } - else if (channel == 9) - { - channel = 15; - } - switch (event) { case mus_releasekey: |