ref: 8e62a8d877b3c17035aa8fe0e353c5429812a318
parent: 6fbd6eafb3dec01401a033eae2e2ec7a2d00ec1c
author: Simon Howard <[email protected]>
date: Fri Jan 29 14:17:56 EST 2010
When doing a MUS to MID conversion, allocate MIDI channels so that the lowest-numbered MIDI channels are used before higher-numbered ones. Fixes ear-piercing whistle sound in the MAP05 music when playing with timidity and EAWPATS (thanks entryway / HackNeyed). Subversion-branch: /trunk/chocolate-doom Subversion-revision: 1831
--- 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
--- 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 @@
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 @@
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 @@
// 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,21 +523,8 @@
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)
{