diff -rN -u old-sci1.1/src/include/sfx_iterator.h new-sci1.1/src/include/sfx_iterator.h
--- old-sci1.1/src/include/sfx_iterator.h	2008-02-05 19:32:00.000000000 +0100
+++ new-sci1.1/src/include/sfx_iterator.h	2008-02-05 19:32:00.000000000 +0100
@@ -238,6 +238,7 @@
 #define IT_READER_MASK_LOOP	(1 << 2)
 #define IT_READER_MASK_CUE	(1 << 3)
 #define IT_READER_MASK_PCM	(1 << 4)
+#define IT_READER_MASK_IGNORE   (1 << 5)
 #define IT_READER_MAY_FREE	(1 << 10) /* Free SI_FINISHED iterators */
 #define IT_READER_MAY_CLEAN	(1 << 11)
 	/* MAY_CLEAN: May instantiate cleanup iterators
@@ -247,7 +248,8 @@
 			    | IT_READER_MASK_DELAY	\
 			    | IT_READER_MASK_LOOP	\
 			    | IT_READER_MASK_CUE	\
-			    | IT_READER_MASK_PCM)
+			    | IT_READER_MASK_PCM        \
+			    | IT_READER_MASK_IGNORE)
 
 int
 songit_next(song_iterator_t **it, unsigned char *buf, int *result, int mask);
diff -rN -u old-sci1.1/src/include/sfx_remap.h new-sci1.1/src/include/sfx_remap.h
--- old-sci1.1/src/include/sfx_remap.h	1970-01-01 01:00:00.000000000 +0100
+++ new-sci1.1/src/include/sfx_remap.h	2008-02-05 19:32:00.000000000 +0100
@@ -0,0 +1,18 @@
+#include <sfx_iterator.h>
+
+void remap_add_song(song_iterator_t *it);
+void remap_add_channel(song_iterator_t *it, 
+		       int channel, int polyphony, int importance, int flags);
+void remap_remove_song(song_iterator_t *it);
+void remap_set_song_priority(song_iterator_t *it, int priority);
+void remap_set_polyphony(song_iterator_t *it, int channel, int polyphony);
+void remap_set_controller(song_iterator_t *it, int channel, int controller,
+			  byte param1);
+void remap_set_program(song_iterator_t *it, int channel, int program);
+void remap_set_pitch_bend(song_iterator_t *it, int channel, byte param1, byte param2);
+int remap_translate_hannel(song_iterator_t *it, int channel);
+void remap_note_off(song_iterator_t *it, int channel, int note);
+int remap_note_on(song_iterator_t *it, int channel, int note);
+int remap_query_global_reverb();
+void remap_print_stats();
+void remap_init();
diff -rN -u old-sci1.1/src/sfx/Makefile.am new-sci1.1/src/sfx/Makefile.am
--- old-sci1.1/src/sfx/Makefile.am	2008-02-05 19:32:00.000000000 +0100
+++ new-sci1.1/src/sfx/Makefile.am	2008-02-05 19:32:00.000000000 +0100
@@ -2,7 +2,7 @@
 INCLUDES = -I$(top_srcdir)/src/include
 EXTRA_DIST = timetest.c
 noinst_LIBRARIES = libscisound.a libscisoundlib.a
-libscisound_a_SOURCES = iterator.c songlib.c core.c pcm-iterator.c
+libscisound_a_SOURCES = iterator.c songlib.c core.c pcm-iterator.c remap.c
 libscisoundlib_a_SOURCES = time.c adlib.c
 
 bin_PROGRAMS = test-iterator
diff -rN -u old-sci1.1/src/sfx/core.c new-sci1.1/src/sfx/core.c
--- old-sci1.1/src/sfx/core.c	2008-02-05 19:32:00.000000000 +0100
+++ new-sci1.1/src/sfx/core.c	2008-02-05 19:32:00.000000000 +0100
@@ -535,6 +535,8 @@
 	else
 		sciprintf("[SFX] Using song player '%s', v%s\n", player->name, player->version);
 
+
+	remap_init();
 	_sfx_timer_active = 1;
 }
 
@@ -567,6 +569,7 @@
 		/* See above: This must happen AFTER stopping the mixer */
 		player->exit();
 
+	remap_exit();
 }
 
 static inline int
diff -rN -u old-sci1.1/src/sfx/iterator.c new-sci1.1/src/sfx/iterator.c
--- old-sci1.1/src/sfx/iterator.c	2008-02-05 19:32:00.000000000 +0100
+++ new-sci1.1/src/sfx/iterator.c	2008-02-05 19:32:00.000000000 +0100
@@ -134,28 +134,9 @@
 
 #define PARSE_FLAG_LOOPS_UNLIMITED (1 << 0) /* Unlimited # of loops? */
 #define PARSE_FLAG_PARAMETRIC_CUE (1 << 1) /* Assume that cues take an additional "cue value" argument */
+#define PARSE_FLAG_USE_REMAPPER (1 << 2) /* Run channel numbers through the remapper */
 /* This implements a difference between SCI0 and SCI1 cues. */
 
-void
-_reset_synth_channels(base_song_iterator_t *self, song_iterator_channel_t *channel)
-{
-	int i;
-	byte buf[5];
-	tell_synth_func *tell = sfx_get_player_tell_func();
-
-	for (i = 0; i < MIDI_CHANNELS; i++)
-	{
-		if (channel->saw_notes & (1 << i))
-		{
-			buf[0] = 0xe0 | i; /* Pitch bend */
-			buf[1] = 0x80; /* Wheel center */
-			buf[2] = 0x40;
-			if (tell)
-				tell(3, buf);
-			/* TODO: Reset other controls? */
-		}
-	}
-}
 
 static int
 _parse_sci_midi_command(base_song_iterator_t *self, unsigned char *buf,	int *result,
@@ -203,7 +184,7 @@
 #endif
 
 	buf[0] = cmd;
-
+	
 
 	CHECK_FOR_END(paramsleft);
 	memcpy(buf + 1, self->data + channel->offset, paramsleft);
@@ -229,8 +210,8 @@
 
 	if (cmd == SCI_MIDI_EOT) {
 		/* End of track? */
-		_reset_synth_channels(self, channel);
-		fprintf(stderr, "eot; loops = %d, notesplayed=%d\n", self->loops, channel->notes_played);
+		fprintf(stderr, "eot; channel = %d, loops = %d, notesplayed=%d\n", channel->id, self->loops, channel->notes_played);
+		remap_drop_channel(self, channel->id);
 		if (self->loops > 1 && channel->notes_played) {
 
 			/* If allowed, decrement the number of loops */
@@ -275,6 +256,7 @@
 			return SI_ABSOLUTE_CUE;
 		}
 	} else if (SCI_MIDI_CONTROLLER(cmd)) {
+		remap_set_controller(self, midi_channel, buf[1], buf[2]);
 		switch (buf[1]) {
 
 		case SCI_MIDI_CUMULATIVE_CUE:
@@ -342,6 +324,8 @@
 
 			break;
 		}
+
+		case 0x40:
 		case 0x04: /* UNKNOWN NYI (happens in LSL2 gameshow) */
 		case 0x46: /* UNKNOWN NYI (happens in LSL3 binoculars) */
 		case 0x61: /* UNKNOWN NYI (special for adlib? Iceman) */
@@ -354,20 +338,79 @@
 		case 0x07: /* volume */
 		case 0x0a: /* panpot */
 		case 0x0b: /* expression */
-		case 0x40: /* hold */
 		case 0x79: /* reset all */
 			/* No special treatment neccessary */
 			break;
 
 		}
-		return 0;
+
+		if (!(flags & PARSE_FLAG_USE_REMAPPER))
+			return 0;
+
+		if (remap_translate_channel(self, midi_channel) >= 0)
+		{
+			buf[0] = (buf[0] & 0xf0) | remap_translate_channel(self, midi_channel);
+			return 0;
+		}
+		else
+		{
+			printf("Throwing away command %02x\n", buf[0]);
+			return SI_IGNORE;
+		}
 
 	} else {
-		if ((cmd & 0xf0) == 0x90) /* note on? */
-			channel->notes_played++;
+		if (flags & PARSE_FLAG_USE_REMAPPER)
+		{
+			switch (cmd & 0xf0)
+			{
+			case 0x80 : /* Note off */
+				remap_note_off(self, midi_channel, buf[1]);
+				break;
+			case 0x90 : /* Note on */
+				if (buf[2] > 0) /* Non-zero velocity */
+				{
+					channel->notes_played++;
+					remap_note_on(self, midi_channel, buf[1], buf[2]);
+					break;
+				} else
+				{
+					remap_note_off(self, midi_channel, buf[1]);
+					break;
+				}
+			case 0xa0 : /* Key aftertouch */
+			case 0xd0 : /* Channel aftertouch */
+				break; /* Ignore */
+			case 0xb0 : /* Controller */
+				remap_set_controller(self, midi_channel, buf[1], buf[2]);
+				break;
+			case 0xe0 : /* Pitch bend */
+				remap_set_pitch_bend(self, midi_channel, buf[1], buf[2]);
+			break;
+			case 0xc0 : /* Program change */
+				remap_set_program(self, midi_channel, buf[1]);
+				break;
+			default:
+				fprintf(stderr, "As yet unhandled command %02x\n", cmd);
+				break;
+			}
 
-		/* Process as normal MIDI operation */
-		return 0;
+			if (remap_translate_channel(self, midi_channel) >= 0)
+			{
+				buf[0] = (buf[0] & 0xf0) | remap_translate_channel(self, midi_channel);
+				return 0;
+			}
+			else
+			{
+				printf("Throwing away command %02x\n", buf[0]);
+				return SI_IGNORE;
+			}
+		} else
+		{
+			if (buf[0] & 0xf0 == 0x90 && /* note-on */
+			    buf[2] > 0) /* Non-zero velocity */
+				channel->notes_played++;
+			return 0;
+		}
 	}
 }
 
@@ -706,8 +749,6 @@
 	self->ccc = 0; /* Reset cumulative cue counter */
 	self->active_channels = 1;
 	_base_init_channel(&(self->channel), 0, SCI0_MIDI_OFFSET, self->size);
-	_reset_synth_channels((base_song_iterator_t *) self, 
-			      &(self->channel));
 	self->delay_remaining = 0;
 
 	if (self->data[0] == 2) /* Do we have an embedded PCM? */
@@ -833,6 +874,7 @@
 		return 1;
 	}
 
+	remap_add_song(self);
 	offset++;
 
 	while (SONGDATA(0) != 0xff) { /* End of list? */
@@ -861,25 +903,28 @@
 					= self->data[track_offset] & 0xf;
 				song_iterator_channel_t *channel =
 					&(self->channels[self->channels_nr++]);
+				int bits = self->data[track_offset] & 0xf0;
 
-				if (self->data[track_offset] & 0xf0)
-					printf("Channel %d has mapping bits %02x\n", 
-					       channel_nr, self->data[track_offset] & 0xf0);
+				if (bits)
+					printf("Channel %d has mapping bits %02x\n", channel_nr, bits);
 
-				_reset_synth_channels((base_song_iterator_t *) self, 
-						      channel);
 				_base_init_channel(channel,
 						   channel_nr,
 						   /* Skip over header bytes: */
 						   track_offset + 2,
 						   track_offset + end);
-
+				
 				self->polyphony[self->channels_nr - 1]
 					= SCI1_CHANDATA(-1);
 				self->importance[self->channels_nr - 1] 
 					= self->polyphony[self->channels_nr - 1] >> 4;
 				self->polyphony[self->channels_nr - 1] &= 15;
 					
+				remap_add_channel(self, 
+						  channel_nr, 
+						  self->polyphony[self->channels_nr - 1],
+						  self->importance[self->channels_nr - 1],
+						  bits);
 				channel->playmask = ~0; /* Enable all */
 				self->channel_mask |= (1 << channel_nr);
 
@@ -1066,6 +1111,7 @@
 		chan = _sci1_command_index(self);
 
 		if (chan == COMMAND_INDEX_NONE) {
+			remap_remove_song(self);
 			return SI_FINISHED;
 		}
 
@@ -1092,7 +1138,7 @@
 		retval = _sci_midi_process((base_song_iterator_t *) self,
 					   buf, result,
 					   &(self->channels[chan]),
-					   PARSE_FLAG_LOOPS_UNLIMITED);
+					   PARSE_FLAG_LOOPS_UNLIMITED | PARSE_FLAG_USE_REMAPPER);
 
 		if (retval == SI_LOOP) {
 			self->channels_looped++;
@@ -1898,6 +1944,7 @@
 		    || (retval == SI_RELATIVE_CUE &&
 			(mask & IT_READER_MASK_CUE))
 		    || (retval == SI_PCM && (mask & IT_READER_MASK_PCM))
+		    || (retval == SI_IGNORE && (mask & IT_READER_MASK_IGNORE))
 		    || (retval == SI_FINISHED)
 		    ));
 
diff -rN -u old-sci1.1/src/sfx/remap.c new-sci1.1/src/sfx/remap.c
--- old-sci1.1/src/sfx/remap.c	1970-01-01 01:00:00.000000000 +0100
+++ new-sci1.1/src/sfx/remap.c	2008-02-05 19:32:00.000000000 +0100
@@ -0,0 +1,494 @@
+#include <list.h>
+#include <sfx_player.h>
+#include <sfx_engine.h>
+#include <sfx_iterator_internal.h>
+#include <sfx_remap.h>
+#include <int_hashmap.h>
+#include <sci_midi.h>
+
+#define NO_PLAYING_NOTE 255
+
+/* If this bit is set, the controller mute is initially on */
+#define SCI_CHANNEL_FLAG_CONTROLLER_MUTE 0x40
+
+#define DEBUG_WAIT
+#define DEBUG_ACQUIRE
+#define DEBUG_RELEASE
+
+#define ACQUIRE_LOCK() ++remap_lock; while (remap_lock != 1) { DEBUG_WAIT sci_sched_yield(); } DEBUG_ACQUIRE
+#define RELEASE_LOCK() --remap_lock DEBUG_RELEASE
+
+typedef struct {
+	byte volume[MIDI_CHANNELS];
+	byte pan[MIDI_CHANNELS];
+	byte modulation[MIDI_CHANNELS];
+	byte program[MIDI_CHANNELS];
+	byte reverb[MIDI_CHANNELS];
+	byte damper[MIDI_CHANNELS]; /* That's what the MIDI docs say, not sure though */
+	byte pitchbyte1[MIDI_CHANNELS]; /* Note that we keep the mangled representation of pitch bend */
+	byte pitchbyte2[MIDI_CHANNELS]; /* No point in decoding it, since we'd just have to re-encode it */
+                                     	/* later anyway. */
+
+	int valid;
+
+	int priority;
+	int polyphony[MIDI_CHANNELS];
+	int importance[MIDI_CHANNELS];
+	int flags[MIDI_CHANNELS];
+	int interpreter_mute_count[MIDI_CHANNELS];
+	int controller_mute[MIDI_CHANNELS];
+	int channel_exists[MIDI_CHANNELS];
+} remap_song_t;
+
+static int max_polyphony;
+static int global_reverb;
+static int active_songs;
+static int allocated_songs;
+static int *song_priority_order;
+static remap_song_t *song_entries;
+static int_hash_map_ptr song_map;
+static byte hw_playing_notes[MIDI_CHANNELS];
+static int hw_channel_songs[MIDI_CHANNELS];
+static int hw_channel_log_channels[MIDI_CHANNELS];
+static int remap_lock;
+
+#define SONG_ID int_hash_map_check_value(song_map, it->ID, 0, NULL);
+#define ASSERT_BASIC(x) \
+	if (!(it->flags & SONGIT_FLAG_CLONE)) return x; \
+	if (id < 0) return x;
+#define MUTED(song,channel) (song_entries[song].interpreter_mute_count[channel]|| \
+			     song_entries[song].controller_mute[channel])
+
+typedef struct {
+  int count;
+} sorted_order_t;
+
+void remap_init()
+{
+	song_map = new_int_hash_map();
+	max_polyphony = sfx_get_player_polyphony();
+	allocated_songs = 4;
+	song_priority_order = malloc(allocated_songs * sizeof(int));
+	song_entries = malloc(allocated_songs * sizeof(remap_song_t));
+
+	memset(hw_channel_songs, -1, sizeof(hw_channel_songs));
+	memset(hw_channel_log_channels, -1, sizeof(hw_channel_log_channels));
+}
+
+void remap_exit()
+{
+	free_int_hash_map(song_map);
+}
+
+static
+void _stop_hardware_channel(int hw_channel)
+{
+	tell_synth_func *tell = sfx_get_player_tell_func();
+	byte buffer[4];
+
+	/* All notes off */
+	buffer[0] = 0xb0 | hw_channel;
+	buffer[1] = 0x7b;
+	buffer[2] = 0;
+	tell(3, buffer);
+
+	/* Pitch bend to neutral */
+	buffer[0] = 0xe0 | hw_channel;
+	buffer[1] = 0x80;
+	buffer[2] = 0x40;
+	tell(3, buffer);
+}
+
+static
+void _prepare_hardware_channel(int hw_channel, remap_song_t *song, int log_channel)
+{
+	tell_synth_func *tell = sfx_get_player_tell_func();
+	byte buffer[4];
+
+/* Program change */
+	buffer[0] = 0xc0 | hw_channel;
+	buffer[1] = song->program[log_channel];
+	tell(2, buffer);
+
+/* Modulation */
+	buffer[0] = 0xb0 | hw_channel;
+	buffer[1] = 1;
+	buffer[2] = song->modulation[log_channel];
+	tell(3, buffer);
+
+/* Volume */
+	buffer[0] = 0xb0 | hw_channel;
+	buffer[1] = 7;
+	buffer[2] = song->volume[log_channel];
+	tell(3, buffer);
+
+/* Pan */
+	buffer[0] = 0xb0 | hw_channel;
+	buffer[1] = 10;
+	buffer[2] = song->volume[log_channel];
+	tell(3, buffer);
+
+/* Damper?? */
+	buffer[0] = 0xb0 | hw_channel;
+	buffer[1] = 64;
+	buffer[2] = song->damper[log_channel];
+	tell(3, buffer);
+
+/* Pitch bend */
+	buffer[0] = 0xe0 | hw_channel;
+	buffer[1] = song->pitchbyte1[log_channel];
+	buffer[2] = song->pitchbyte2[log_channel];
+	tell(3, buffer);
+}
+
+static
+void note_songs(void *param, int name, int value)
+{
+  sorted_order_t *order = (sorted_order_t *) param;
+
+  if (!song_entries[value].valid) return;
+  song_priority_order[order->count] = value;
+  order->count++;
+}
+
+static
+int cmp_song_priority(const void *v1, const void *v2)
+{
+	const int *i1 = (const int *) v1;
+	const int *i2 = (const int *) v2;
+
+	/* Place valid songs first */
+	if (song_entries[*i1].valid ^ song_entries[*i2].valid)
+	  return song_entries[*i1].valid-song_entries[*i2].valid;
+
+	/* Then do a straight-forward sort by priority */
+	if (song_entries[*i1].priority > song_entries[*i2].priority) return 1;
+	if (song_entries[*i1].priority < song_entries[*i2].priority) return -1;
+
+	return 0;
+}
+
+static
+int find_free_channel()
+{
+	int i;
+
+	for (i = 0; i < MIDI_CHANNELS - 1; i++)
+		if (hw_channel_log_channels[i] == -1)
+			return i;
+
+	return -1;
+}  
+
+static
+void remap_reassign_voices()
+{
+	int old_hw_channel_songs[MIDI_CHANNELS];
+	int old_hw_channel_log_channels[MIDI_CHANNELS];
+	int priority, song, channel;
+	int notes = 0;
+
+	ACQUIRE_LOCK();
+	memcpy(old_hw_channel_songs, hw_channel_songs, sizeof(hw_channel_songs));
+	memcpy(old_hw_channel_log_channels, hw_channel_log_channels, sizeof(hw_channel_songs));
+
+	memset(hw_channel_songs, -1, sizeof(hw_channel_songs));
+	memset(hw_channel_log_channels, -1, sizeof(hw_channel_log_channels));
+
+	for (priority = 0; priority < 16; priority++)
+	{
+		for (song = 0; song < active_songs; song++)
+		{
+			for (channel = 0; channel < MIDI_CHANNELS - 1; channel++)
+			{
+				int try_channel = channel;
+
+				if (!song_entries[song].channel_exists[channel])
+					continue;
+				if (song_entries[song].importance[channel] != priority)
+					continue;
+				if (hw_channel_songs[try_channel] == song &&
+				    hw_channel_songs[try_channel] == channel)
+				{
+					printf("Overdrevet mærkeligt!\n");
+					continue;
+				}
+				if (hw_channel_songs[try_channel] >= 0)
+				{
+					try_channel = find_free_channel();
+					printf("Remapped song %d channel %d to %d\n", song, channel, try_channel);
+					printf("%d,%d was there already\n", 
+					       hw_channel_songs[channel],
+					       hw_channel_log_channels[channel]);
+				}
+				if (try_channel < 0)
+				{
+					printf("Out of remapped channels assigning song %d channel %d!\n",
+					       song, channel);
+					continue;
+				}
+
+				printf("Assigning song %d channel %d to %d\n", song, channel, try_channel);
+				hw_channel_songs[try_channel] = song;
+				hw_channel_log_channels[try_channel] = channel;
+				notes += song_entries[song].polyphony[channel];
+				
+				if (hw_channel_songs[try_channel] != old_hw_channel_songs[try_channel] ||
+				    hw_channel_log_channels[try_channel] != old_hw_channel_log_channels[try_channel])
+				{
+					_stop_hardware_channel(try_channel);
+					_prepare_hardware_channel(try_channel, &song_entries[song], channel);
+				}
+			}
+		}
+	}
+	RELEASE_LOCK();
+}
+
+static
+void remap_adjust_sorted_order()
+{
+	sorted_order_t t = {0};
+
+	apply_to_int_hash_map(song_map, &t, note_songs);
+	qsort(song_priority_order, t.count, sizeof(int), cmp_song_priority);
+	active_songs = t.count;
+}
+
+
+
+void remap_add_song(song_iterator_t *it)
+{
+	char was_added;
+	int id;
+
+	if (!(it->flags & SONGIT_FLAG_CLONE)) return;
+	id = int_hash_map_check_value(song_map, it->ID, 1, &was_added);
+
+	if (id > allocated_songs - 1)
+	{
+		int i;
+
+		allocated_songs += 8;
+		song_entries = realloc(song_entries, allocated_songs*sizeof(remap_song_t));
+		song_priority_order = realloc(song_entries, allocated_songs*sizeof(int));
+
+		for (i = allocated_songs - 8; i < allocated_songs; i++)
+		{
+			song_entries[i].valid = 0;
+			song_priority_order[i] = -1;
+		}
+	}
+
+	memset(song_entries[id].volume, 127, sizeof(byte)*MIDI_CHANNELS);
+	memset(song_entries[id].pan, 64, sizeof(byte)*MIDI_CHANNELS);
+	memset(song_entries[id].modulation, 0, sizeof(byte)*MIDI_CHANNELS);
+	memset(song_entries[id].program, 0, sizeof(byte)*MIDI_CHANNELS);
+	memset(song_entries[id].reverb, 0, sizeof(byte)*MIDI_CHANNELS);
+	memset(song_entries[id].damper, 0, sizeof(byte)*MIDI_CHANNELS);
+	memset(song_entries[id].pitchbyte1, 0x80, sizeof(byte)*MIDI_CHANNELS);
+	memset(song_entries[id].pitchbyte2, 0x40, sizeof(byte)*MIDI_CHANNELS);
+
+	memset(song_entries[id].polyphony, 0, sizeof(int)*MIDI_CHANNELS);
+	memset(song_entries[id].importance, 0, sizeof(int)*MIDI_CHANNELS);
+	memset(song_entries[id].channel_exists, 0, sizeof(int)*MIDI_CHANNELS);
+
+	song_entries[id].priority = it->priority;
+	song_entries[id].valid = 1;
+	remap_adjust_sorted_order();
+}
+
+void remap_add_channel(song_iterator_t *it, 
+		       int channel, int polyphony, int importance, int flags)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+
+	if (song_entries[id].channel_exists[channel])
+		printf("Trying to add an already existing channnel. This will sound funny.\n");
+
+	song_entries[id].channel_exists[channel] = 1;
+	song_entries[id].polyphony[channel] = polyphony;
+	song_entries[id].importance[channel] = importance;
+	song_entries[id].flags[channel] = flags;
+
+	if (song_entries[id].flags[channel] & SCI_CHANNEL_FLAG_CONTROLLER_MUTE)
+		song_entries[id].controller_mute[channel] = 1;
+
+//	remap_reassign_voices();
+}
+
+void remap_drop_channel(song_iterator_t *it, int channel)
+{
+	int id = SONG_ID;
+	int i;
+
+	ASSERT_BASIC();
+
+	for (i = 0; i < MIDI_CHANNELS; i++)
+		if (hw_channel_songs[i] == id &&
+		    hw_channel_log_channels[i] == channel)
+			_stop_hardware_channel(i);
+
+	song_entries[id].channel_exists[channel] = 0;
+}
+
+void remap_remove_song(song_iterator_t *it)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+
+	int_hash_map_remove_value(song_map, it->ID);
+	song_entries[id].valid = 0;
+	remap_adjust_sorted_order();
+	remap_reassign_voices();
+}
+
+void remap_set_song_priority(song_iterator_t *it, int priority)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+
+	song_entries[id].priority = priority;
+	remap_adjust_sorted_order();
+	remap_reassign_voices();
+}
+
+int remap_note_on(song_iterator_t *it, int channel, int note)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+	return channel;
+}
+
+void remap_note_off(song_iterator_t *it, int channel, int note)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+}
+
+int remap_translate_channel(song_iterator_t *it, int channel)
+{
+	int id = SONG_ID;
+	int i;
+
+//	ASSERT_BASIC(-1);
+	if (channel == 15) return 15;
+
+	for (i = 0; i < MIDI_CHANNELS; i++)
+		if (hw_channel_songs[i] == id &&
+		    hw_channel_log_channels[i] == channel)
+		{
+			return i;
+		}
+
+	printf("remap_translate_channel: no match for song %d channel %d\n", id, channel);
+	return -1;
+}
+
+void remap_set_polyphony(song_iterator_t *it, int channel, int polyphony)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+	song_entries[id].polyphony[channel] = polyphony;
+	song_entries[id].importance[channel] = ((sci1_song_iterator_t *) it)->importance[channel];
+	remap_reassign_voices();
+}
+
+static inline
+void _remap_mute_channel(song_iterator_t *it, int channel, int interpreter, int toggle)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+	if (interpreter)
+	{
+		if (!toggle)
+		{
+			if (song_entries[id].interpreter_mute_count[id])
+				song_entries[id].interpreter_mute_count[id]--;
+		} else
+		{
+			song_entries[id].interpreter_mute_count[id]++;
+		}
+	}
+	else
+	{
+		song_entries[id].controller_mute[channel] = toggle;
+	}
+
+
+	remap_reassign_voices();
+		
+}
+
+void remap_mute_channel(song_iterator_t *it, int channel, int toggle)
+{
+	_remap_mute_channel(it, channel, 1, toggle);
+}
+void remap_set_controller(song_iterator_t *it, int channel, int controller, byte param1)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+	switch (controller)
+	  {
+	  case 1 :
+		  song_entries[id].modulation[channel] = param1;
+		  break;
+	  case 7 :
+		  song_entries[id].volume[channel] = param1;
+		  break;
+	  case 10 :
+		  song_entries[id].pan[channel] = param1;
+		  break;
+	  case 64 :
+		  song_entries[id].damper[channel] = param1;
+		  break;
+	  case SCI_MIDI_SET_POLYPHONY :
+		  remap_set_polyphony(it, channel, param1);
+		  break;
+	  case SCI_MIDI_SET_REVERB :
+		  song_entries[id].reverb[channel] = param1;
+		  break;
+	  case SCI_MIDI_CHANNEL_MUTE :
+		  _remap_mute_channel(it, channel, 0, param1);
+		  break;
+	  default :
+		  fprintf(stderr, "Unhandled controller in remap: %x\n", controller);
+		  break;
+	  }
+}
+
+void remap_set_program(song_iterator_t *it, int channel, int program)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+	song_entries[id].program[channel] = program;
+}
+
+void remap_set_pitch_bend(song_iterator_t *it, int channel, byte param1, byte param2)
+{
+	int id = SONG_ID;
+
+	ASSERT_BASIC();
+	song_entries[id].pitchbyte1[channel] = param1;
+	song_entries[id].pitchbyte2[channel] = param2;
+}
+
+int remap_set_global_reverb(int reverb)
+{
+	global_reverb = reverb;
+}
+
+int remap_query_global_reverb()
+{
+	return global_reverb;
+}

