summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rw-r--r--src/mus2mid.c91
2 files changed, 79 insertions, 14 deletions
diff --git a/NEWS b/NEWS
index abe5aa9d..ba7c81b1 100644
--- a/NEWS
+++ b/NEWS
@@ -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: