[Scummvm-git-logs] scummvm master -> 8915aa3277b930921bded9fd0fdd96979708ca9a

NMIError noreply at scummvm.org
Tue Nov 7 21:07:00 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
8915aa3277 Revert "ULTIMA/NUVIE: Rework music code"


Commit: 8915aa3277b930921bded9fd0fdd96979708ca9a
    https://github.com/scummvm/scummvm/commit/8915aa3277b930921bded9fd0fdd96979708ca9a
Author: Coen Rampen (crampen at gmail.com)
Date: 2023-11-07T22:06:52+01:00

Commit Message:
Revert "ULTIMA/NUVIE: Rework music code"

This reverts commit 911173f34e28a470ea11eda6625ab323ff4014cd.

Changed paths:
  R engines/ultima/nuvie/sound/mididrv_m_adlib.cpp
  R engines/ultima/nuvie/sound/mididrv_m_adlib.h
  R engines/ultima/nuvie/sound/mididrv_m_mt32.cpp
  R engines/ultima/nuvie/sound/mididrv_m_mt32.h
  R engines/ultima/nuvie/sound/midiparser_m.cpp
  R engines/ultima/nuvie/sound/midiparser_m.h
  R engines/ultima/nuvie/sound/song_filename.cpp
  R engines/ultima/nuvie/sound/song_filename.h
    audio/adlib_ms.cpp
    audio/adlib_ms.h
    audio/midiparser.h
    engines/ultima/module.mk
    engines/ultima/nuvie/nuvie.cpp
    engines/ultima/nuvie/sound/song.h
    engines/ultima/nuvie/sound/sound.h
    engines/ultima/nuvie/sound/sound_manager.cpp
    engines/ultima/nuvie/sound/sound_manager.h


diff --git a/audio/adlib_ms.cpp b/audio/adlib_ms.cpp
index 3b866cd21b9..56942d62c8c 100644
--- a/audio/adlib_ms.cpp
+++ b/audio/adlib_ms.cpp
@@ -400,7 +400,6 @@ MidiDriver_ADLIB_Multisource::MidiDriver_ADLIB_Multisource(OPL::Config::OplType
 		_isOpen(false),
 		_accuracyMode(ACCURACY_MODE_SB16_WIN95),
 		_allocationMode(ALLOCATION_MODE_DYNAMIC),
-		_instrumentWriteMode(INSTRUMENT_WRITE_MODE_NOTE_ON),
 		_rhythmModeIgnoreNoteOffs(false),
 		_defaultChannelVolume(0),
 		_noteSelect(NOTE_SELECT_MODE_0),
@@ -691,10 +690,8 @@ void MidiDriver_ADLIB_Multisource::noteOn(uint8 channel, uint8 note, uint8 veloc
 		activeNote->instrumentId = instrument.instrumentId;
 		activeNote->instrumentDef = instrument.instrumentDef;
 
-		if (_instrumentWriteMode == INSTRUMENT_WRITE_MODE_NOTE_ON) {
-			// Write out the instrument definition, volume and panning.
-			writeInstrument(oplChannel, instrument);
-		}
+		// Write out the instrument definition, volume and panning.
+		writeInstrument(oplChannel, instrument);
 
 		// Calculate and write frequency and block and write key on bit.
 		writeFrequency(oplChannel, instrument.instrumentDef->rhythmType);
@@ -765,41 +762,6 @@ void MidiDriver_ADLIB_Multisource::controlChange(uint8 channel, uint8 controller
 void MidiDriver_ADLIB_Multisource::programChange(uint8 channel, uint8 program, uint8 source) {
 	// Just set the MIDI program value; this event does not affect active notes.
 	_controlData[source][channel].program = program;
-
-	if (_instrumentWriteMode == INSTRUMENT_WRITE_MODE_PROGRAM_CHANGE && !(_rhythmMode && channel == MIDI_RHYTHM_CHANNEL)) {
-		InstrumentInfo instrument = determineInstrument(channel, source, 0);
-
-		if (!instrument.instrumentDef || instrument.instrumentDef->isEmpty()) {
-			// Instrument definition contains no data.
-			return;
-		}
-
-		_activeNotesMutex.lock();
-
-		// Determine the OPL channel to use and the active note data to update.
-		uint8 oplChannel = 0xFF;
-		ActiveNote *activeNote = nullptr;
-		// Allocate a melodic OPL channel.
-		oplChannel = allocateOplChannel(channel, source, instrument.instrumentId);
-		if (oplChannel != 0xFF) {
-			activeNote = &_activeNotes[oplChannel];
-			if (activeNote->noteActive) {
-				// Turn off the note currently playing on this OPL channel or
-				// rhythm instrument.
-				writeKeyOff(oplChannel, instrument.instrumentDef->rhythmType);
-			}
-
-			// Update the active note data.
-			activeNote->channel = channel;
-			activeNote->source = source;
-			activeNote->instrumentId = instrument.instrumentId;
-			activeNote->instrumentDef = instrument.instrumentDef;
-
-			writeInstrument(oplChannel, instrument);
-		}
-
-		_activeNotesMutex.unlock();
-	}
 }
 
 void MidiDriver_ADLIB_Multisource::channelAftertouch(uint8 channel, uint8 pressure, uint8 source) {
diff --git a/audio/adlib_ms.h b/audio/adlib_ms.h
index 29f7017d2b2..53231123c0a 100644
--- a/audio/adlib_ms.h
+++ b/audio/adlib_ms.h
@@ -279,26 +279,6 @@ public:
 		ALLOCATION_MODE_STATIC
 	};
 
-	/**
-	 * The available modes for writing the instrument definition to a channel.
-	 */
-	enum InstrumentWriteMode {
-		/**
-		 * Will write the instrument definition before each note on event.
-		 * Works with both dynamic and static channel allocation modes, but
-		 * is less efficient and resets all parameters of the instrument when
-		 * a note is played.
-		 */
-		INSTRUMENT_WRITE_MODE_NOTE_ON,
-		/**
-		 * Will write the instrument definition after a program change event.
-		 * This will only work with a static channel allocation mode. It will
-		 * write the instrument only once for many notes and allows parameters
-		 * of the instrument to be changed for the following notes.
-		 */
-		INSTRUMENT_WRITE_MODE_PROGRAM_CHANGE
-	};
-
 	/**
 	 * The available modes for the OPL note select setting.
 	 */
@@ -1094,7 +1074,7 @@ protected:
 	 * calculated and written. Use type undefined to calculate volume for a
 	 * melodic instrument.
 	 */
-	virtual void writeVolume(uint8 oplChannel, uint8 operatorNum, OplInstrumentRhythmType rhythmType = RHYTHM_TYPE_UNDEFINED);
+	void writeVolume(uint8 oplChannel, uint8 operatorNum, OplInstrumentRhythmType rhythmType = RHYTHM_TYPE_UNDEFINED);
 	/**
 	 * Calculates the panning for the specified OPL channel or rhythm type
 	 * (@see calculatePanning) and writes the new value to the OPL registers.
@@ -1146,8 +1126,6 @@ protected:
 	AccuracyMode _accuracyMode;
 	// Controls the OPL channel allocation behavior.
 	ChannelAllocationMode _allocationMode;
-	// Controls when the instrument definitions are written.
-	InstrumentWriteMode _instrumentWriteMode;
 	// Controls response to rhythm note off events when rhythm mode is active.
 	bool _rhythmModeIgnoreNoteOffs;
 
diff --git a/audio/midiparser.h b/audio/midiparser.h
index f15391b276b..4a2ee4eb4dc 100644
--- a/audio/midiparser.h
+++ b/audio/midiparser.h
@@ -446,7 +446,7 @@ public:
 	virtual void setMidiDriver(MidiDriver_BASE *driver) { _driver = driver; }
 	void setTimerRate(uint32 rate) { _timerRate = rate; }
 	virtual void setTempo(uint32 tempo);
-	virtual void onTimer();
+	void onTimer();
 
 	bool isPlaying() const { return (_position._playPos != 0 && _doParse); }
 	/**
diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index 7c2985082ad..bd09a519b2e 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -334,14 +334,10 @@ MODULE_OBJS := \
 	nuvie/script/script_cutscene.o \
 	nuvie/sound/adlib_sfx_manager.o \
 	nuvie/sound/custom_sfx_manager.o \
-	nuvie/sound/mididrv_m_adlib.o \
-	nuvie/sound/mididrv_m_mt32.o \
-	nuvie/sound/midiparser_m.o \
 	nuvie/sound/origin_fx_adib_driver.o \
 	nuvie/sound/pc_speaker_sfx_manager.o \
 	nuvie/sound/song.o \
 	nuvie/sound/song_adplug.o \
-	nuvie/sound/song_filename.o \
 	nuvie/sound/sound_manager.o \
 	nuvie/sound/towns_sfx_manager.o \
 	nuvie/sound/adplug/adplug_player.o \
diff --git a/engines/ultima/nuvie/nuvie.cpp b/engines/ultima/nuvie/nuvie.cpp
index 11cf1e7ad57..5a4b9754808 100644
--- a/engines/ultima/nuvie/nuvie.cpp
+++ b/engines/ultima/nuvie/nuvie.cpp
@@ -234,7 +234,19 @@ void NuvieEngine::syncSoundSettings() {
 	if (!_soundManager)
 		return;
 
-	_soundManager->syncSoundSettings();
+	_soundManager->set_audio_enabled(
+		!ConfMan.hasKey("mute") || !ConfMan.getBool("mute"));
+	_soundManager->set_sfx_enabled(
+		!ConfMan.hasKey("sfx_mute") || !ConfMan.getBool("sfx_mute"));
+	_soundManager->set_music_enabled(
+		!ConfMan.hasKey("music_mute") || !ConfMan.getBool("music_mute"));
+	_soundManager->set_speech_enabled(
+		!ConfMan.hasKey("speech_mute") || !ConfMan.getBool("speech_mute"));
+
+	_soundManager->set_sfx_volume(ConfMan.hasKey("sfx_volume") ?
+		ConfMan.getInt("sfx_volume") : 255);
+	_soundManager->set_music_volume(ConfMan.hasKey("music_volume") ?
+		ConfMan.getInt("music_volume") : 255);
 }
 
 bool NuvieEngine::canLoadGameStateCurrently(bool isAutosave) {
diff --git a/engines/ultima/nuvie/sound/mididrv_m_adlib.cpp b/engines/ultima/nuvie/sound/mididrv_m_adlib.cpp
deleted file mode 100644
index 54cc51eabf9..00000000000
--- a/engines/ultima/nuvie/sound/mididrv_m_adlib.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "mididrv_m_adlib.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-const uint16 MidiDriver_M_AdLib::FNUM_VALUES[24] = {
-	0x0, 0x158, 0x182, 0x1B0, 0x1CC, 0x203, 0x241, 0x286, 
-	0x0, 0x16A, 0x196, 0x1C7, 0x1E4, 0x21E, 0x25F, 0x2A8, 
-	0x0, 0x147, 0x16E, 0x19A, 0x1B5, 0x1E9, 0x224, 0x266
-};
-
-MidiDriver_M_AdLib::MidiDriver_M_AdLib() : MidiDriver_ADLIB_Multisource(OPL::Config::kOpl2, 60) {
-	_modulationDepth = MODULATION_DEPTH_LOW;
-	_vibratoDepth = VIBRATO_DEPTH_LOW;
-	_allocationMode = ALLOCATION_MODE_STATIC;
-	_instrumentWriteMode = INSTRUMENT_WRITE_MODE_PROGRAM_CHANGE;
-
-	Common::fill(_slideValues, _slideValues + ARRAYSIZE(_slideValues), 0);
-	Common::fill(_vibratoDepths, _vibratoDepths + ARRAYSIZE(_vibratoDepths), 0);
-	Common::fill(_vibratoFactors, _vibratoFactors + ARRAYSIZE(_vibratoFactors), 0);
-	Common::fill(_vibratoCurrentDepths, _vibratoCurrentDepths + ARRAYSIZE(_vibratoCurrentDepths), 0);
-	Common::fill(_vibratoDirections, _vibratoDirections + ARRAYSIZE(_vibratoDirections), VIBRATO_DIRECTION_RISING);
-	Common::fill(_fadeDirections, _fadeDirections + ARRAYSIZE(_fadeDirections), FADE_DIRECTION_NONE);
-	Common::fill(_fadeStepDelays, _fadeStepDelays + ARRAYSIZE(_fadeStepDelays), 0);
-	Common::fill(_fadeCurrentDelays, _fadeCurrentDelays + ARRAYSIZE(_fadeCurrentDelays), 0);
-
-	_instrumentBank = new OplInstrumentDefinition[16];
-}
-
-MidiDriver_M_AdLib::~MidiDriver_M_AdLib() {
-	delete[] _instrumentBank;
-}
-
-void MidiDriver_M_AdLib::send(int8 source, uint32 b) {
-	byte command = b & 0xF0;
-	byte channel = b & 0x0F;
-	byte data = (b >> 8) & 0xFF;
-
-	ActiveNote *activeNote;
-	//uint16 channelOffset;
-	//uint16 frequency;
-	switch (command) {
-	case 0x00: // Note off
-		// The original driver always writes both F-num registers with the 
-		// supplied note value; it does not check what the active note value 
-		// is. The standard noteOff implementation checks if the active note 
-		// value matches an active note on the data channel. If the note off 
-		// does not match the active note, this could cause a hanging note.
-		// None of the Ultima 6 tracks seem to have this problem however.
-
-		/* DEBUG: Write Ax register
-		// Calculate the frequency.
-		channelOffset = determineChannelRegisterOffset(channel);
-		frequency = calculateFrequency(channel, source, data);
-
-		// Write the low 8 frequency bits.
-		writeRegister(OPL_REGISTER_BASE_FNUMLOW + channelOffset, frequency & 0xFF);
-		*/
-
-		noteOff(channel, data, 0, source);
-		break;
-
-	case 0x10: // Note on
-		// Stop vibrato (if active)
-		_vibratoDirections[channel] = VIBRATO_DIRECTION_RISING;
-		_vibratoCurrentDepths[channel] = 0;
-
-		// The original driver always writes a note off before a note on, even 
-		// if there is no note active. The standard noteOn implementation only 
-		// writes a note off if a note is active. This causes no audible
-		// difference however.
-
-		/* DEBUG: Write note off
-		_activeNotesMutex.lock();
-
-		// Melodic instrument.
-		activeNote = &_activeNotes[channel];
-		
-		// Calculate the frequency.
-		channelOffset = determineChannelRegisterOffset(channel);
-		frequency = calculateFrequency(channel, source, data);
-		activeNote->oplFrequency = frequency;
-
-		// Write the low 8 frequency bits.
-		writeRegister(OPL_REGISTER_BASE_FNUMLOW + channelOffset, frequency & 0xFF);
-		// Write the high 2 frequency bits and block and add the key on bit.
-		writeRegister(OPL_REGISTER_BASE_FNUMHIGH_BLOCK_KEYON + channelOffset, frequency >> 8);
-
-		// Update the active note data.
-		activeNote->noteActive = false;
-		activeNote->noteSustained = false;
-		// Register the current note counter value when turning off a note.
-		activeNote->noteCounterValue = _noteCounter;
-
-		_activeNotesMutex.unlock();
-		*/
-
-		noteOn(channel, data, 0x7F, source);
-		break;
-
-	case 0x20: // Set pitch
-		// If a note is already active on this channel, this will just update 
-		// the pitch. Otherwise it is the same as a Note on.
-
-		_activeNotesMutex.lock();
-
-		// Determine the OPL channel to use and the active note data to update.
-		uint8 oplChannel;
-		oplChannel = 0xFF;
-		activeNote = nullptr;
-		// Allocate a melodic OPL channel.
-		oplChannel = allocateOplChannel(channel, source, 0);
-		if (oplChannel != 0xFF)
-			activeNote = &_activeNotes[oplChannel];
-
-		if (activeNote != nullptr) {
-			if (!activeNote->noteActive) {
-				// If there is no note active currently, treat this as a
-				// regular note on.
-				noteOn(channel, data, 0x7F, source);
-			} else {
-				// If there is a note active, only update the frequency.
-				activeNote->note = data;
-				activeNote->oplNote = data;
-				// Calculate and write frequency and block and write key on bit.
-				writeFrequency(oplChannel);
-			}
-		}
-
-		_activeNotesMutex.unlock();
-
-		break;
-
-	case 0x30: // Set level
-		// This directly writes the OPL level register of the carrier operator. 
-		// This can also write the key scale level bits.
-		// Note that the control data volume field is used for an OPL level 
-		// value, not for a MIDI channel volume value as usual.
-
-		// Stop fade (if active)
-		_fadeDirections[channel] = FADE_DIRECTION_NONE;
-
-		_controlData[source][channel].volume = data;
-		if (_activeNotes[channel].instrumentDef)
-			writeVolume(channel, 1);
-
-		break;
-
-	case 0x40: // Set modulation
-		modulation(channel, data, source);
-		break;
-
-	case 0x50: // Set slide
-		// Start or stop a pitch slide. The slide is processed by onTimer.
-		_slideValues[channel] = (int8)data;
-		break;
-
-	case 0x60: // Set vibrato
-		// Turns vibrato on or off or modifies the parameters. High nibble 
-		// is the vibrato depth, low nibble is the vibrato factor. The vibrato
-		// is processed by onTimer.
-		_vibratoDepths[channel] = data >> 4;
-		_vibratoFactors[channel] = data & 0xF;
-		break;
-
-	case 0x70: // Program change
-		programChange(channel, data, source);
-		break;
-
-	case 0x80: // Subcommand
-		uint8 subcommand;
-		subcommand = channel;
-		switch (subcommand) {
-		case 0x1: // Call subroutine
-		case 0x2: // Delay
-			// These are handled by the parser.
-			break;
-
-		case 0x3: // Load instrument
-			// This should be sent to the driver as a meta event.
-			warning("MidiDriver_M_AdLib::send - Received load instrument as command");
-			break;
-
-		case 0x5: // Fade out
-		case 0x6: // Fade in
-			// Starts a volume fade in or out. The high nibble of the data byte
-			// is the channel, the low nibble is the fade delay. The fade is
-			// processed by onTimer.
-
-			channel = data >> 4;
-			_fadeDirections[channel] = (subcommand == 0x5 ? FADE_DIRECTION_FADE_OUT : FADE_DIRECTION_FADE_IN);
-			uint8 delay;
-			delay = (data & 0xF) + 1;
-			_fadeStepDelays[channel] = _fadeCurrentDelays[channel] = delay;
-			break;
-
-		default: // Unknown subcommand
-			break;
-		}
-		break;
-
-	case 0xE0: // Set loop point
-	case 0xF0: // Return
-		// These are handled by the parser.
-		break;
-
-	default: // Unknown command
-		break;
-	}
-}
-
-void MidiDriver_M_AdLib::metaEvent(int8 source, byte type, byte* data, uint16 length) {
-	if (type == 0x3) {
-		// Load instrument
-		// This loads an OPL instrument definition into the bank. The first 
-		// byte is the instrument bank number. The next 11 bytes contain the 
-		// instrument parameters.
-
-		if (length < 12) {
-			warning("Received a load instrument event with insufficient data length");
-			return;
-		}
-
-		byte instrumentNumber = data[0];
-		assert(instrumentNumber < 16);
-		OplInstrumentDefinition *instrument = &_instrumentBank[instrumentNumber];
-
-		instrument->fourOperator = false;
-		instrument->rhythmType = RHYTHM_TYPE_UNDEFINED;
-
-		instrument->operator0.freqMultMisc = data[1];
-		instrument->operator0.level = data[2];
-		instrument->operator0.decayAttack = data[3];
-		instrument->operator0.releaseSustain = data[4];
-		instrument->operator0.waveformSelect = data[5];
-
-		instrument->operator1.freqMultMisc = data[6];
-		instrument->operator1.level = data[7];
-		instrument->operator1.decayAttack = data[8];
-		instrument->operator1.releaseSustain = data[9];
-		instrument->operator1.waveformSelect = data[10];
-
-		instrument->connectionFeedback0 = data[11];
-	}
-}
-
-void MidiDriver_M_AdLib::programChange(uint8 channel, uint8 program, uint8 source) {
-	assert(program < 16);
-
-	// Changing the instrument overwrites the current volume and modulation
-	// settings.
-	_controlData[source][channel].volume = _instrumentBank[program].operator1.level;
-	_controlData[source][channel].modulation = _instrumentBank[program].operator0.level;
-
-	// Note that this will turn off an active note on the channel if there is
-	// one. The original driver does not do this. Changing the instrument while
-	// a note is playing would be strange though; none of the tracks in
-	// Ultima 6 seem to do this.
-	MidiDriver_ADLIB_Multisource::programChange(channel, program, source);
-}
-
-void MidiDriver_M_AdLib::modulation(uint8 channel, uint8 modulation, uint8 source) {
-	// This directly writes the OPL level register of the modulator
-	// operator.
-
-	// Note that the control data modulation field is used for an OPL level
-	// value, not for a MIDI channel modulation value as usual.
-	_controlData[source][channel].modulation = modulation;
-
-	uint16 registerOffset = determineOperatorRegisterOffset(channel, 0);
-	writeRegister(OPL_REGISTER_BASE_LEVEL + registerOffset, modulation);
-}
-
-uint8 MidiDriver_M_AdLib::allocateOplChannel(uint8 channel, uint8 source, uint8 instrumentId) {
-	// Allocation of M data channels to OPL output channels is simply 1 on 1.
-	return channel;
-}
-
-uint16 MidiDriver_M_AdLib::calculateFrequency(uint8 channel, uint8 source, uint8 note) {
-	// An M note value consist of a note lookup value in the low 5 bits and
-	// a block (octave) value in the high 3 bits.
-	uint8 fnumIndex = note & 0x1F;
-	assert(fnumIndex < 24);
-
-	uint16 oplFrequency = FNUM_VALUES[fnumIndex];
-	uint8 block = note >> 5;
-
-	return oplFrequency | (block << 10);
-}
-
-uint8 MidiDriver_M_AdLib::calculateUnscaledVolume(uint8 channel, uint8 source, uint8 velocity, OplInstrumentDefinition& instrumentDef, uint8 operatorNum) {
-	// M directy uses OPL level values, so no calculation is necessary.
-	return _controlData[source][channel].volume & OPL_MASK_LEVEL;
-}
-
-void MidiDriver_M_AdLib::writeVolume(uint8 oplChannel, uint8 operatorNum, OplInstrumentRhythmType rhythmType) {
-	ActiveNote *activeNote = (rhythmType == RHYTHM_TYPE_UNDEFINED ? &_activeNotes[oplChannel] : &_activeRhythmNotes[rhythmType - 1]);
-
-	// Calculate operator volume.
-	uint16 registerOffset = determineOperatorRegisterOffset(
-		oplChannel, operatorNum, rhythmType, activeNote->instrumentDef->fourOperator);
-	uint8 level = calculateVolume(activeNote->channel, activeNote->source, activeNote->velocity,
-								  *activeNote->instrumentDef, operatorNum);
-
-	// Add key scaling level from the last written volume or modulation value
-	// to the calculated level.
-	MidiChannelControlData *controlData = &_controlData[activeNote->source][activeNote->channel];
-	uint8 ksl = (operatorNum == 0 ? controlData->modulation : controlData->volume) & ~OPL_MASK_LEVEL;
-	writeRegister(OPL_REGISTER_BASE_LEVEL + registerOffset, level | ksl);
-}
-
-void MidiDriver_M_AdLib::deinitSource(uint8 source) {
-	// Reset effects status.
-	Common::fill(_slideValues, _slideValues + ARRAYSIZE(_slideValues), 0);
-	Common::fill(_vibratoFactors, _vibratoFactors + ARRAYSIZE(_vibratoFactors), 0);
-	Common::fill(_vibratoCurrentDepths, _vibratoCurrentDepths + ARRAYSIZE(_vibratoCurrentDepths), 0);
-	Common::fill(_vibratoDirections, _vibratoDirections + ARRAYSIZE(_vibratoDirections), VIBRATO_DIRECTION_RISING);
-	Common::fill(_fadeDirections, _fadeDirections + ARRAYSIZE(_fadeDirections), FADE_DIRECTION_NONE);
-
-	MidiDriver_ADLIB_Multisource::deinitSource(source);
-}
-
-void MidiDriver_M_AdLib::onTimer() {
-	MidiDriver_ADLIB_Multisource::onTimer();
-
-	_activeNotesMutex.lock();
-
-	// Process effects.
-	for (int i = 8; i >= 0; i--) {
-		ActiveNote *activeNote = &_activeNotes[i];
-
-		if (_slideValues[i] != 0) {
-			// Process slide. A slide continually increases or decreases the
-			// note frequency until it is turned off.
-
-			// Increase or decrease the OPL frequency by the slide value.
-			// Note that this can potentially over- or underflow the OPL
-			// frequency, but there is no bounds checking in the original
-			// driver either.
-			activeNote->oplFrequency += _slideValues[i];
-
-			// Write the low 8 frequency bits.
-			uint16 channelOffset = determineChannelRegisterOffset(i);
-			writeRegister(OPL_REGISTER_BASE_FNUMLOW + channelOffset, activeNote->oplFrequency & 0xFF);
-			// Write the high 2 frequency bits and block and add the key on bit.
-			writeRegister(OPL_REGISTER_BASE_FNUMHIGH_BLOCK_KEYON + channelOffset,
-				(activeNote->oplFrequency >> 8) | (activeNote->noteActive ? OPL_MASK_KEYON : 0));
-		} else if (_vibratoFactors[i] > 0 && activeNote->noteActive) {
-			// Process vibrato. Vibrato will alternately increase and decrease
-			// the frequency up to the maximum depth.
-			// The depth is the difference between the minimum and maximum
-			// frequency change, so a positive number, twice the amplitude.
-			// The current depth is converted to the actual frequency offset by
-			// subtracting half the total depth. The offset is then multiplied
-			// by the vibrato factor.
-			// Note that current depth starts at 0, so minimum depth, rather
-			// than at neutral (half depth).
-
-			// Flip vibrato direction if the maximum or minimum depth has been reached.
-			if (_vibratoCurrentDepths[i] >= _vibratoDepths[i]) {
-				_vibratoDirections[i] = VIBRATO_DIRECTION_FALLING;
-			} else if (_vibratoCurrentDepths[i] == 0) {
-				_vibratoDirections[i] = VIBRATO_DIRECTION_RISING;
-			}
-
-			// Update current depth.
-			if (_vibratoDirections[i] == VIBRATO_DIRECTION_FALLING) {
-				_vibratoCurrentDepths[i]--;
-			} else {
-				_vibratoCurrentDepths[i]++;
-			}
-
-			// Convert the depth to an OPL frequency offset.
-			int vibratoOffset = _vibratoCurrentDepths[i] - (_vibratoDepths[i] >> 1);
-			vibratoOffset *= _vibratoFactors[i];
-
-			uint16 frequency = activeNote->oplFrequency + vibratoOffset;
-
-			// Write the low 8 frequency bits.
-			uint16 channelOffset = determineChannelRegisterOffset(i);
-			writeRegister(OPL_REGISTER_BASE_FNUMLOW + channelOffset, frequency & 0xFF);
-			// Write the high 2 frequency bits and block and add the key on bit.
-			writeRegister(OPL_REGISTER_BASE_FNUMHIGH_BLOCK_KEYON + channelOffset,
-				(frequency >> 8) | (activeNote->noteActive ? OPL_MASK_KEYON : 0));
-		}
-
-		if (_fadeDirections[i] != FADE_DIRECTION_NONE && --_fadeCurrentDelays[i] == 0) {
-			// Process fade. A fade will continually increase or decrease the 
-			// level (volume) until the maximum or minimum volume is reached.
-			// Then the fade is stopped. A delay determines the speed of the
-			// fade by increasing the number of ticks between each increase or
-			// decrease.
-
-			// Reset delay.
-			_fadeCurrentDelays[i] = _fadeStepDelays[i];
-
-			// Calculate new channel level.
-			int newChannelLevel = _controlData[activeNote->source][i].volume + (_fadeDirections[i] == FADE_DIRECTION_FADE_IN ? -1 : 1);
-			if (newChannelLevel < 0 || newChannelLevel > 0x3F) {
-				// Minimum or maximum level reached. Stop the fade.
-				newChannelLevel = (newChannelLevel < 0) ? 0 : 0x3F;
-				_fadeDirections[i] = FADE_DIRECTION_NONE;
-			}
-
-			// Apply the new volume.
-			_controlData[activeNote->source][i].volume = newChannelLevel;
-			writeVolume(i, 1);
-		}
-	}
-
-	_activeNotesMutex.unlock();
-}
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
diff --git a/engines/ultima/nuvie/sound/mididrv_m_adlib.h b/engines/ultima/nuvie/sound/mididrv_m_adlib.h
deleted file mode 100644
index a1404c051db..00000000000
--- a/engines/ultima/nuvie/sound/mididrv_m_adlib.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef NUVIE_SOUND_MIDIDRV_M_ADLIB_H
-#define NUVIE_SOUND_MIDIDRV_M_ADLIB_H
-
-#include "audio/adlib_ms.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-/**
- * M driver for AdLib (OPL2).
- * This driver supports several effects by adjusting OPL frequency and level
- * values based on timer ticks: slide, vibrato and fade in/out. Only vibrato is
- * used by the tracks in Ultima 6.
- */
-class MidiDriver_M_AdLib : public MidiDriver_ADLIB_Multisource {
-protected:
-	// The direction of a volume fade: in (increase) or out (decrease).
-	enum FadeDirection {
-		FADE_DIRECTION_NONE,
-		FADE_DIRECTION_FADE_IN,
-		FADE_DIRECTION_FADE_OUT
-	};
-
-	// The current direction of vibrato pitch change.
-	enum VibratoDirection {
-		VIBRATO_DIRECTION_RISING,
-		VIBRATO_DIRECTION_FALLING
-	};
-
-	// Converts M note values to OPL frequency (F-num) values.
-	static const uint16 FNUM_VALUES[24];
-
-public:
-	MidiDriver_M_AdLib();
-	~MidiDriver_M_AdLib();
-
-	using MidiDriver_Multisource::send;
-	void send(int8 source, uint32 b) override;
-	void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
-
-protected:
-	void programChange(uint8 channel, uint8 program, uint8 source) override;
-	void modulation(uint8 channel, uint8 modulation, uint8 source) override;
-
-	uint8 allocateOplChannel(uint8 channel, uint8 source, uint8 instrumentId) override;
-	uint16 calculateFrequency(uint8 channel, uint8 source, uint8 note) override;
-	uint8 calculateUnscaledVolume(uint8 channel, uint8 source, uint8 velocity, OplInstrumentDefinition &instrumentDef, uint8 operatorNum) override;
-	void writeVolume(uint8 oplChannel, uint8 operatorNum, OplInstrumentRhythmType rhythmType = RHYTHM_TYPE_UNDEFINED) override;
-
-	void deinitSource(uint8 source) override;
-
-	void onTimer() override;
-
-	// Number of F-num units each channel will increase/decrease each tick.
-	int8 _slideValues[9];
-	// Maximum number of F-num units the frequency will be changed by vibrato,
-	// before applying the factor, for each channel. This is the difference
-	// between the lowest and highest value (so twice the amplitude).
-	uint8 _vibratoDepths[9];
-	// Multiplication factor for vibrato F-num values for each channel.
-	uint8 _vibratoFactors[9];
-	// The current "progression" of vibrato through the cycle for each channel.
-	// This is before the vibrato factor is applied.
-	uint8 _vibratoCurrentDepths[9];
-	// The current direction in which the vibrato is progressing for each
-	// channel (rising or falling frequency).
-	VibratoDirection _vibratoDirections[9];
-	// The direction of the fade currently active on each channel (in or out).
-	// NONE indicates no fade is active.
-	FadeDirection _fadeDirections[9];
-	// The delay in ticks between each level increase or decrease for each
-	// channel.
-	uint8 _fadeStepDelays[9];
-	// The current fade delay counter value for each channel.
-	uint8 _fadeCurrentDelays[9];
-};
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
-
-#endif
diff --git a/engines/ultima/nuvie/sound/mididrv_m_mt32.cpp b/engines/ultima/nuvie/sound/mididrv_m_mt32.cpp
deleted file mode 100644
index a7c8b25e590..00000000000
--- a/engines/ultima/nuvie/sound/mididrv_m_mt32.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "mididrv_m_mt32.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-const uint8 MidiDriver_M_MT32::MIDI_NOTE_MAP[] = {
-	0x00, 0x0C, 0x0E, 0x10, 0x11, 0x13, 0x15, 0x17,
-	0x00, 0x0D, 0x0F, 0x11, 0x12, 0x14, 0x16, 0x18,
-	0x00, 0x0B, 0x0D, 0x0F, 0x10, 0x12, 0x14, 0x16
-};
-
-MidiDriver_M_MT32::MidiDriver_M_MT32() : MidiDriver_MT32GM(MT_MT32) {
-	Common::fill(_mInstrumentMidiChannels, _mInstrumentMidiChannels + sizeof(_mInstrumentMidiChannels), 1);
-	Common::fill(_mInstrumentMapping, _mInstrumentMapping + sizeof(_mInstrumentMapping), 0);
-}
-
-MidiDriver_M_MT32::~MidiDriver_M_MT32() { }
-
-int MidiDriver_M_MT32::open(MidiDriver *driver, bool nativeMT32) {
-	int result = MidiDriver_MT32GM::open(driver, nativeMT32);
-	if (result == 0)
-		setInstrumentRemapping(_mInstrumentMapping);
-
-	return result;
-}
-
-void MidiDriver_M_MT32::send(int8 source, uint32 b) {
-	if (!_isOpen) {
-		// During the opening of the driver, some MIDI commands are sent to
-		// initialize the device. These are not M commands so they are sent
-		// straight to the device.
-		MidiDriver_MT32GM::send(source, b);
-		return;
-	}
-
-	byte mCommand = b & 0xF0;
-	if (mCommand >= 0x80) {
-		// These commands are either handled by the parser (call, return,
-		// set loop point, delay) or are not implemented for MT-32
-		// (load instrument, fade). Not all of them have the channel in the
-		// low nibble, so they are filtered out here.
-		return;
-	}
-	byte dataChannel = b & 0x0F;
-	byte data = (b >> 8) & 0xFF;
-
-	MChannelData &mChannelData = _mChannelData[dataChannel];
-
-	// Get the MIDI output channel assigned to this M data channel.
-	int8 outputChannel = source < 0 ? dataChannel : mapSourceChannel(source, dataChannel);
-	if (outputChannel < 0) {
-		warning("MidiDriver_M_MT32::send - Could not map data channel %i to an output channel", dataChannel);
-		return;
-	}
-
-	MidiChannelControlData &controlData = *_controlData[outputChannel];
-
-	byte midiNote;
-	byte mNote;
-	// Convert M to MIDI events
-	switch (mCommand) {
-	case 0x00: // Note off
-		mNote = data & 0x1F;
-		assert(mNote < 24);
-		midiNote = MIDI_NOTE_MAP[mNote] + ((data >> 5) * 12);
-		noteOnOff(outputChannel, MIDI_COMMAND_NOTE_OFF, midiNote, mChannelData.velocity, source, controlData);
-		mChannelData.activeNote = -1;
-		break;
-	case 0x10: // Note on
-	case 0x20: // Set pitch
-		// In the original driver, for Note on events, Note off is explicitly
-		// called first to turn off the previous note. However, the Note off
-		// event is not sent if there is no note active. For Set pitch,
-		// Note off is not explicitly called; Note on is called directly.
-		// However, Note on turns off any active notes first before sending the
-		// Note on event. So despite the different code paths, these events
-		// effectively do the same thing: turn off the currently active note on
-		// the channel, if there is one, then play the new note on the next
-		// tick.
-
-		if (mChannelData.activeNote >= 0) {
-			noteOnOff(outputChannel, MIDI_COMMAND_NOTE_OFF, mChannelData.activeNote, mChannelData.velocity, source, controlData);
-			mChannelData.activeNote = -1;
-		}
-
-		mNote = data & 0x1F;
-		assert(mNote < 24);
-		midiNote = MIDI_NOTE_MAP[mNote] + ((data >> 5) * 12);
-		// The new note is queued for playback on the next timer tick
-		// (see onTimer).
-		if (mChannelData.queuedNote >= 0) {
-			warning("MidiDriver_M_MT32::send - Note on on channel %i while a note is already queued", dataChannel);
-		}
-		mChannelData.queuedNote = midiNote;
-
-		break;
-	case 0x30: // Set level
-		// The OPL level is converted to a MIDI note velocity, which is used
-		// for notes subsequently played on the M channel. The active note is
-		// not affected.
-		mChannelData.velocity = (0x3F - (data & 0x3F)) * 1.5;
-		break;
-	case 0x70: // Program change
-		// When instrument assignments are set on the driver, each M instrument
-		// is assigned to a fixed MIDI output channel. When a program change
-		// event is encountered on an M channel, the MIDI output channel of
-		// that M channel is changed to the MIDI channel assigned to the new M
-		// instrument.
-		uint8 newOutputChannel;
-		assert(data < 16);
-		newOutputChannel = _mInstrumentMidiChannels[data];
-		if (newOutputChannel < 0) {
-			warning("MidiDriver_M_MT32::send - Received program change for unmapped instrument %i", data);
-			break;
-		}
-		if (newOutputChannel != outputChannel && mChannelData.activeNote >= 0) {
-			// Turn off the active note.
-			noteOnOff(outputChannel, MIDI_COMMAND_NOTE_OFF, mChannelData.activeNote, mChannelData.velocity, source, controlData);
-			mChannelData.activeNote = -1;
-		}
-		_channelMap[source][dataChannel] = newOutputChannel;
-		// Because the assignment of instruments to output channels is fixed,
-		// a program change for each channel could be sent once when setting
-		// instrument assignments. However, the original driver sends a program
-		// change every time the instrument on an M channel is changed.
-		programChange(newOutputChannel, data, source, controlData);
-		break;
-	default:
-		// Modulation, slide and vibrato are not implemented for MT-32.
-		break;
-	}
-}
-
-void MidiDriver_M_MT32::metaEvent(int8 source, byte type, byte *data, uint16 length) {
-	// Load instrument is ignored for MT-32; instruments are set using
-	// setInstrumentAssignments.
-}
-
-void MidiDriver_M_MT32::setInstrumentAssignments(const MInstrumentAssignment *assignments) {
-	// Each M instrument used in the played track (up to 16) should get a MIDI
-	// output channel and a MIDI instrument assigned to it. The MIDI instrument
-	// is set on the output channel and when an M data channel switches to the
-	// corresponding M instrument, the data channel is mapped to that output
-	// channel.
-	for (int i = 0; i < 16; i++) {
-		_mInstrumentMidiChannels[i] = assignments[i].midiChannel;
-		_mInstrumentMapping[i] = assignments[i].midiInstrument;
-	}
-}
-
-void MidiDriver_M_MT32::stopAllNotes(bool stopSustainedNotes) {
-	MidiDriver_MT32GM::stopAllNotes();
-
-	// Clear active and queued notes.
-	for (int i = 0; i < 9; i++) {
-		_mChannelData[i].activeNote = -1;
-		_mChannelData[i].queuedNote = -1;
-	}
-}
-
-void MidiDriver_M_MT32::onTimer() {
-	// Play the queued notes for each M channel.
-	for (int i = 0; i < 9; i++) {
-		if (_mChannelData[i].queuedNote >= 0) {
-			int8 outputChannel = mapSourceChannel(0, i);
-			if (outputChannel < 0) {
-				warning("MidiDriver_M_MT32::onTimer - Could not map data channel %i to an output channel", i);
-				continue;
-			}
-			MidiChannelControlData &controlData = *_controlData[outputChannel];
-			noteOnOff(outputChannel, MIDI_COMMAND_NOTE_ON, _mChannelData[i].queuedNote, _mChannelData[i].velocity, 0, controlData);
-			_mChannelData[i].activeNote = _mChannelData[i].queuedNote;
-			_mChannelData[i].queuedNote = -1;
-		}
-	}
-
-	MidiDriver_MT32GM::onTimer();
-}
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
diff --git a/engines/ultima/nuvie/sound/mididrv_m_mt32.h b/engines/ultima/nuvie/sound/mididrv_m_mt32.h
deleted file mode 100644
index 03c377e5832..00000000000
--- a/engines/ultima/nuvie/sound/mididrv_m_mt32.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef NUVIE_SOUND_MIDIDRV_M_MT32_H
-#define NUVIE_SOUND_MIDIDRV_M_MT32_H
-
-#include "audio/mt32gm.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-// An assignment of a MIDI instrument to a MIDI output channel. M data channels
-// using this instrument will be mapped to the specified MIDI channel.
-struct MInstrumentAssignment {
-	int8 midiChannel = -1;
-	uint8 midiInstrument = 0;
-};
-
-/**
- * M driver for the Roland MT-32.
- * The M format is focused on OPL2 and conversion to MIDI is rudimentary. Only
- * note on/off, channel volume (using note velocity) and program change are
- * implemented by the original driver.
- * A mapping of M instruments to MIDI instruments must be set using
- * setInstrumentAssignments before starting playback of a track.
- */
-class MidiDriver_M_MT32 : public MidiDriver_MT32GM {
-protected:
-	/**
-	 * Playback status information for an M channel.
-	 * Note that although this data applies to an M data channel, the values
-	 * are MIDI note and velocity values.
-	 */
-	struct MChannelData {
-		// The MIDI note currently played on this channel.
-		int8 activeNote = -1;
-		// The MIDI note velocity currently used on this channel.
-		uint8 velocity = 0;
-		// The MIDI note queued for playback on this channel.
-		int8 queuedNote = -1;
-	};
-
-	// Converts M note values to MIDI notes.
-	static const uint8 MIDI_NOTE_MAP[24];
-
-public:
-	MidiDriver_M_MT32();
-	~MidiDriver_M_MT32();
-
-	using MidiDriver_MT32GM::open;
-	int open(MidiDriver *driver, bool nativeMT32) override;
-
-	using MidiDriver_MT32GM::send;
-	void send(int8 source, uint32 b) override;
-	void metaEvent(int8 source, byte type, byte *data, uint16 length) override;
-
-	/**
-	 * Sets the assignments of the 16 M instruments to the MIDI instruments and
-	 * MIDI output channels they should use.
-	 * 
-	 * @param assignments An instrument assignment array of length 16
-	 */
-	void setInstrumentAssignments(const MInstrumentAssignment *assignments);
-
-	void stopAllNotes(bool stopSustainedNotes) override;
-
-protected:
-	void onTimer() override;
-
-	MChannelData _mChannelData[9];
-	// Mapping of M instrument numbers to MIDI output channels
-	int8 _mInstrumentMidiChannels[16];
-	// Mapping of M instrument numbers to MIDI instrument numbers
-	uint8 _mInstrumentMapping[16];
-};
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
-
-#endif
diff --git a/engines/ultima/nuvie/sound/midiparser_m.cpp b/engines/ultima/nuvie/sound/midiparser_m.cpp
deleted file mode 100644
index 1813f329181..00000000000
--- a/engines/ultima/nuvie/sound/midiparser_m.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "midiparser_m.h"
-
-#include "audio/mididrv.h"
-#include "audio/midiparser.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-MidiParser_M::MidiParser_M(int8 source) : MidiParser(source) {
-	// M uses a fixed timer frequency of 60 Hz, or 16.667 ms per tick.
-	_psecPerTick = 16667;
-
-	_trackLength = 0;
-
-	_loopPoint = nullptr;
-	_loopStack = new Common::FixedStack<LoopData, 16>();
-}
-
-MidiParser_M::~MidiParser_M() {
-	delete _loopStack;
-}
-
-bool MidiParser_M::loadMusic(byte* data, uint32 size) {
-	unloadMusic();
-
-	// M uses only 1 track.
-	_tracks[0] = data;
-	_numTracks = 1;
-	_trackLength = size;
-
-	// The global loop defaults to the start of the M data.
-	_loopPoint = data;
-
-	resetTracking();
-	setTrack(0);
-
-	return true;
-}
-
-void MidiParser_M::unloadMusic() {
-	MidiParser::unloadMusic();
-	_trackLength = 0;
-
-	_loopPoint = nullptr;
-	_loopStack->clear();
-}
-
-// MidiParser::onTimer does some checks based on MIDI note on/off command bytes
-// which have a different meaning in M, so those checks are removed here.
-void MidiParser_M::onTimer() {
-	uint32 endTime;
-	uint32 eventTime;
-
-	if (!_position._playPos || !_driver || !_doParse || _pause || !_driver->isReady(_source))
-		return;
-
-	_abortParse = false;
-	endTime = _position._playTime + _timerRate;
-
-	bool loopEvent = false;
-	while (!_abortParse) {
-		EventInfo &info = _nextEvent;
-
-		eventTime = _position._lastEventTime + info.delta * _psecPerTick;
-		if (eventTime > endTime)
-			break;
-
-		if (!info.noop) {
-			// Process the next info.
-			bool ret = processEvent(info);
-			if (!ret)
-				return;
-		}
-
-		loopEvent |= info.loop;
-
-		if (!_abortParse) {
-			_position._lastEventTime = eventTime;
-			_position._lastEventTick += info.delta;
-			parseNextEvent(_nextEvent);
-		}
-	}
-
-	if (!_abortParse) {
-		_position._playTime = endTime;
-		_position._playTick = (_position._playTime - _position._lastEventTime) / _psecPerTick + _position._lastEventTick;
-		if (loopEvent) {
-			// One of the processed events has looped (part of) the MIDI data.
-			// Infinite looping will cause the tracker to overflow eventually.
-			// Reset the tracker positions to prevent this from happening.
-			_position._playTime -= _position._lastEventTime;
-			_position._lastEventTime = 0;
-			_position._playTick -= _position._lastEventTick;
-			_position._lastEventTick = 0;
-		}
-	}
-}
-
-bool MidiParser_M::processEvent(const EventInfo& info, bool fireEvents) {
-	if (info.command() == 0x8 && info.channel() == 0x1) {
-		// Call subroutine
-		LoopData loopData { };
-		loopData.returnPos = _position._playPos;
-		loopData.numLoops = info.ext.data[0];
-		uint16 startOffset = READ_LE_UINT16(info.ext.data + 1);
-		assert(startOffset < _trackLength);
-		loopData.startPos = _tracks[0] + startOffset;
-		_loopStack->push(loopData);
-		_position._playPos = loopData.startPos;
-	} else if (info.command() == 0xE) {
-		// Set loop point
-		_loopPoint = _position._playPos;
-	} else if (info.command() == 0xF) {
-		// Return
-		if (_loopStack->empty()) {
-			// Global loop: return to the global loop point
-			_position._playPos = _loopPoint;
-		} else {
-			// Subroutine loop
-			LoopData *loopData = &_loopStack->top();
-			if (loopData->numLoops > 1) {
-				// Return to the start of the subroutine data
-				loopData->numLoops--;
-				_position._playPos = loopData->startPos;
-			} else {
-				// Return to the call position
-				_position._playPos = loopData->returnPos;
-				_loopStack->pop();
-			}
-		}
-	} else if (info.command() == 0x8 && info.channel() == 0x3) {
-		// Load instrument
-		if (fireEvents) {
-			// Send the instrument data as a meta event
-			sendMetaEventToDriver(info.ext.type, info.ext.data, (uint16)info.length);
-		}
-	} else if (fireEvents) {
-		// Other events are handled by the driver
-		sendToDriver(info.event, info.basic.param1, info.basic.param2);
-	}
-
-	return true;
-}
-
-void MidiParser_M::parseNextEvent(EventInfo &info) {
-	assert(_position._playPos - _tracks[0] < _trackLength);
-	info.start = _position._playPos;
-	info.event = *(_position._playPos++);
-	info.delta = 0;
-	info.basic.param1 = 0;
-	info.basic.param2 = 0;
-	info.noop = false;
-	info.loop = false;
-
-	switch (info.command()) {
-	case 0x0: // Note off
-	case 0x1: // Note on
-	case 0x2: // Set pitch
-	case 0x3: // Set level
-	case 0x4: // Set modulation
-	case 0x5: // Set slide
-	case 0x6: // Set vibrato
-	case 0x7: // Program change
-		// These commands all have 1 data byte.
-		info.basic.param1 = *(_position._playPos++);
-		break;
-
-	case 0x8: // Subcommand
-		switch (info.channel()) {
-		case 0x1: // Call subroutine
-			// This command specifies the number of loops (1 byte) and an
-			// offset in the M data to jump to (2 bytes).
-			info.ext.type = info.channel();
-			info.length = 3;
-			info.ext.data = _position._playPos;
-			_position._playPos += info.length;
-			break;
-		case 0x2: // Delay
-			// This command is used to specify a delta time between the
-			// previous and the next event. It does nothing otherwise.
-			info.delta = *(_position._playPos++);
-			info.noop = true;
-			break;
-		case 0x3: // Load instrument
-			// This command specifies the instrument bank slot in which the
-			// instrument should be loaded (1 byte) plus an OPL instrument
-			// definition (11 bytes).
-			info.ext.type = info.channel();
-			info.length = 12;
-			info.ext.data = _position._playPos;
-			_position._playPos += info.length;
-			break;
-		case 0x5: // Fade out
-		case 0x6: // Fade in
-			// These commands have 1 data byte.
-			info.basic.param1 = *(_position._playPos++);
-			break;
-		default:
-			info.noop = true;
-			break;
-		}
-		break;
-
-	case 0xE: // Set loop point
-		// This command does not have any data bytes.
-		break;
-
-	case 0xF: // Return
-		// This command does not have any data bytes.
-		info.loop = true;
-		break;
-
-	default:
-		info.noop = true;
-		break;
-	}
-}
-
-void MidiParser_M::allNotesOff() {
-	if (_driver) {
-		_driver->stopAllNotes();
-	}
-}
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
diff --git a/engines/ultima/nuvie/sound/midiparser_m.h b/engines/ultima/nuvie/sound/midiparser_m.h
deleted file mode 100644
index 7f6bc6b4ed2..00000000000
--- a/engines/ultima/nuvie/sound/midiparser_m.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef NUVIE_SOUND_MIDIPARSER_M_H
-#define NUVIE_SOUND_MIDIPARSER_M_H
-
-#include "audio/midiparser.h"
-
-#include "common/stack.h"
-#include "common/util.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-/**
- * A parser for the music format M, used by Times Of Lore, Bad Blood and
- * Ultima 6.
- * This format is not really a MIDI format; it targets the OPL2 chip. However,
- * it has several things in common with MIDI: it is a stream of events, it has
- * note on and note off events and events similar to MIDI controllers, the high
- * nibble of the first event byte is the command while the low nibble is
- * usually the channel.
- * The commands are different. M does not use the status byte / data byte
- * convention and delta times are specified using a wait command. It uses
- * channels 0-8, corresponding to the 9 OPL2 channels. OPL rhythm mode is not
- * used.
- */
-class MidiParser_M : public MidiParser {
-protected:
-	struct LoopData {
-		byte numLoops;
-		byte *startPos;
-		byte *returnPos;
-	};
-
-public:
-	MidiParser_M(int8 source = -1);
-	~MidiParser_M();
-
-	bool loadMusic(byte *data, uint32 size) override;
-	void unloadMusic() override;
-	void onTimer() override;
-
-protected:
-	bool processEvent(const EventInfo &info, bool fireEvents = true) override;
-	void parseNextEvent(EventInfo &info) override;
-
-	void allNotesOff() override;
-
-	uint32 _trackLength;
-
-	// The point in the MIDI data where the global loop (not using the stack)
-	// has started and will return.
-	byte *_loopPoint;
-
-	// A stack of nested loops, similar to a call stack. A call command will
-	// specify an offset where the parser should jump to (startPus), plus a
-	// number of times the data from this offset up to the return command should
-	// be repeated (numLoops). Then the parser resumes with the command after
-	// the call command (returnPos). A maximum depth of 16 levels is supported.
-	Common::FixedStack<LoopData, 16> *_loopStack;
-};
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
-
-#endif
diff --git a/engines/ultima/nuvie/sound/song.h b/engines/ultima/nuvie/sound/song.h
index ad9bc92f31b..c7c33e43295 100644
--- a/engines/ultima/nuvie/sound/song.h
+++ b/engines/ultima/nuvie/sound/song.h
@@ -33,9 +33,6 @@ public:
 	virtual bool Init(const char *filename) {
 		return false;
 	}
-	virtual bool Init(const char *path, const char *fileId) {
-		return false;
-	}
 	bool Play(bool looping = false) override {
 		return false;
 	}
@@ -49,8 +46,8 @@ public:
 		return false;
 	}
 
-	void SetTitle(const char *title) {
-		if (title) m_Title = title;    // SB-X
+	void SetName(const char *name) {
+		if (name) m_Filename = name;    // SB-X
 	}
 private:
 
diff --git a/engines/ultima/nuvie/sound/song_filename.cpp b/engines/ultima/nuvie/sound/song_filename.cpp
deleted file mode 100644
index a31be1b655b..00000000000
--- a/engines/ultima/nuvie/sound/song_filename.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#include "ultima/nuvie/core/nuvie_defs.h"
-#include "ultima/nuvie/sound/adplug/emu_opl.h"
-#include "ultima/nuvie/sound/adplug/u6m.h"
-#include "ultima/nuvie/sound/song_filename.h"
-#include "ultima/nuvie/sound/sound_manager.h"
-#include "ultima/nuvie/nuvie.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-SongFilename::~SongFilename() {
-}
-
-bool SongFilename::Init(const char *path, const char *fileId) {
-	return Init(path, fileId, 0);
-}
-
-bool SongFilename::Init(const char *filename, const char *fileId, uint16 song_num) {
-	if (filename == NULL)
-		return false;
-
-	m_Filename = filename; // SB-X
-	m_FileId = fileId;
-
-	return true;
-}
-
-bool SongFilename::Play(bool looping) {
-	return true;
-}
-
-bool SongFilename::Stop() {
-	return true;
-}
-
-bool SongFilename::SetVolume(uint8 volume) {
-	return true;
-}
-
-bool SongFilename::FadeOut(float seconds) {
-	return false;
-}
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
diff --git a/engines/ultima/nuvie/sound/song_filename.h b/engines/ultima/nuvie/sound/song_filename.h
deleted file mode 100644
index 5fe5ba5318a..00000000000
--- a/engines/ultima/nuvie/sound/song_filename.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-#ifndef NUVIE_SOUND_SONG_FILENAME_H
-#define NUVIE_SOUND_SONG_FILENAME_H
-
-#include "ultima/nuvie/sound/song.h"
-
-namespace Ultima {
-namespace Nuvie {
-
-class SongFilename : public Song {
-public:
-	~SongFilename() override;
-	bool Init(const char *path, const char *fileId);
-	bool Init(const char *path, const char *fileId, uint16 song_num);
-	bool Play(bool looping = false) override;
-	bool Stop() override;
-	bool SetVolume(uint8 volume) override;
-	bool FadeOut(float seconds) override;
-};
-
-} // End of namespace Nuvie
-} // End of namespace Ultima
-
-#endif
diff --git a/engines/ultima/nuvie/sound/sound.h b/engines/ultima/nuvie/sound/sound.h
index 874d615a8cb..06d685e0191 100644
--- a/engines/ultima/nuvie/sound/sound.h
+++ b/engines/ultima/nuvie/sound/sound.h
@@ -43,17 +43,9 @@ public:
 	string GetName() {
 		return m_Filename;
 	}
-	string GetTitle() {
-		return m_Title;
-	}
-	string GetId() {
-		return m_FileId;
-	}
 protected:
 	string m_Filename;
-	string m_Title;
-	string m_FileId;
-	//	static SoundManager *gpSM;
+//	static SoundManager *gpSM;
 };
 
 class SoundCollection {
diff --git a/engines/ultima/nuvie/sound/sound_manager.cpp b/engines/ultima/nuvie/sound/sound_manager.cpp
index 118811ad3a7..a0f4bfe1ca6 100644
--- a/engines/ultima/nuvie/sound/sound_manager.cpp
+++ b/engines/ultima/nuvie/sound/sound_manager.cpp
@@ -24,7 +24,7 @@
 #include "ultima/nuvie/core/u6_objects.h"
 #include "ultima/nuvie/sound/sound_manager.h"
 #include "ultima/nuvie/sound/adplug/emu_opl.h"
-#include "ultima/nuvie/sound/song_filename.h"
+#include "ultima/nuvie/sound/song_adplug.h"
 #include "ultima/nuvie/core/game.h"
 #include "ultima/nuvie/core/player.h"
 #include "ultima/nuvie/gui/widgets/map_window.h"
@@ -34,12 +34,8 @@
 #include "ultima/nuvie/sound/pc_speaker_sfx_manager.h"
 #include "ultima/nuvie/sound/towns_sfx_manager.h"
 #include "ultima/nuvie/sound/custom_sfx_manager.h"
-#include "ultima/nuvie/files/u6_lzw.h"
-
 #include "audio/mixer.h"
-
 #include "common/algorithm.h"
-#include "common/config-manager.h"
 
 namespace Ultima {
 namespace Nuvie {
@@ -59,21 +55,7 @@ static const ObjSfxLookup u6_obj_lookup_tbl[] = {
 	{OBJ_U6_WATER_WHEEL, NUVIE_SFX_WATER_WHEEL}
 };
 
-// This is the default MT-32 instrument mapping specified in MIDI.DAT
-const SoundManager::SongMT32InstrumentMapping SoundManager::DEFAULT_MT32_INSTRUMENT_MAPPING[12] = {
-	{'1', "ultima.m",	{{1,  25}, {2,  50}, {3,  24}, {4,  27}}},
-	{'2', "bootup.m",	{{1,  37}, {2,  38}}},
-	{'3', "intro.m",	{{1,  61}, {2,  60}, {3,  55}, {4, 117}, {5, 117}}},
-	{'4', "create.m",	{{1,   6}, {2,   1}, {3,  33}}},
-	{'5', "forest.m",	{{1,  59}, {2,  60}}},
-	{'6', "hornpipe.m",	{{1,  87}, {2,  60}, {3,  59}}},
-	{'7', "engage.m",	{{1,  49}, {2,  26}, {3,  18}, {4,  16}}},
-	{'8', "stones.m",	{{1,   6}, {2,  32}}},
-	{'9', "dungeon.m",	{{1,  37}, {2, 113}, {3,  55}}},
-	{'0', "brit.m",		{{1,  12}}},
-	{'-', "gargoyle.m",	{{1,  38}, {2,   5}}},
-	{'=', "end.m",		{{1,  38}, {2,  12}, {3,  50}, {4,  94}}}
-};
+
 
 bool SoundManager::g_MusicFinished;
 
@@ -94,35 +76,12 @@ SoundManager::SoundManager(Audio::Mixer *mixer) : _mixer(mixer) {
 	m_SfxManager = NULL;
 
 	opl = NULL;
-
-	_midiDriver = nullptr;
-	_mt32MidiDriver = nullptr;
-	_midiParser = nullptr;
-	_deviceType = MT_NULL;
-	_musicData = nullptr;
-	_mt32InstrumentMapping = nullptr;
 }
 
 SoundManager::~SoundManager() {
 	// Stop all mixing
 	_mixer->stopAll();
 
-	musicPause();
-
-	if (_midiDriver) {
-		_midiDriver->setTimerCallback(nullptr, nullptr);
-		_midiDriver->close();
-	}
-
-	Common::StackLock lock(_musicMutex);
-
-	if (_midiParser) {
-		delete _midiParser;
-	}
-	if (_midiDriver) {
-		delete _midiDriver;
-	}
-
 	//thanks to wjp for this one
 	while (!m_Songs.empty()) {
 		delete *(m_Songs.begin());
@@ -151,12 +110,38 @@ bool SoundManager::nuvieStartup(Configuration *config) {
 	Std::string music_cfg_file; //full path and filename to music.cfg
 	Std::string sound_dir;
 	Std::string sfx_style;
+	bool val;
 
 	m_Config = config;
 
+	m_Config->value("config/mute", val, false);
+	audio_enabled = !val;
 	m_Config->value("config/GameType", game_type);
 	m_Config->value("config/audio/stop_music_on_group_change", stop_music_on_group_change, true);
 
+	/*  if(audio_enabled == false) // commented out to allow toggling
+	     {
+	      music_enabled = false;
+	      sfx_enabled = false;
+	      music_volume = 0;
+	      sfx_volume = 0;
+	      mixer = NULL;
+	      return false;
+	     }*/
+
+	m_Config->value("config/music_mute", val, false);
+	music_enabled = !val;
+	m_Config->value("config/sfx_mute", val, false);
+	sfx_enabled = !val;
+
+	int volume;
+
+	m_Config->value("config/music_volume", volume, Audio::Mixer::kMaxChannelVolume);
+	music_volume = clamp(volume, 0, 255);
+
+	m_Config->value("config/sfx_volume", volume, Audio::Mixer::kMaxChannelVolume);
+	sfx_volume = clamp(volume, 0, 255);
+
 	config_key = config_get_game_key(config);
 	config_key.append("/music");
 	config->value(config_key, music_style, "native");
@@ -169,82 +154,42 @@ bool SoundManager::nuvieStartup(Configuration *config) {
 	config_key.append("/sounddir");
 	config->value(config_key, sound_dir, "");
 
+	if (game_type == NUVIE_GAME_U6) { // FM-Towns speech
+		config->value("config/speech_mute", val, false);
+		speech_enabled = !val;
+	} else {
+		speech_enabled = false;
+	}
+
 	if (!initAudio()) {
 		return false;
 	}
 
-	if (music_style == "native") {
-		if (game_type == NUVIE_GAME_U6)
-			LoadNativeU6Songs(); //FIX need to handle MD & SE music too.
-	} else if (music_style == "custom")
-		LoadCustomSongs(sound_dir);
-	else
-		DEBUG(0, LEVEL_WARNING, "Unknown music style '%s'\n", music_style.c_str());
+//  if(music_enabled)  // commented out to allow toggling
+	{
+		if (music_style == "native") {
+			if (game_type == NUVIE_GAME_U6)
+				LoadNativeU6Songs(); //FIX need to handle MD & SE music too.
+		} else if (music_style == "custom")
+			LoadCustomSongs(sound_dir);
+		else
+			DEBUG(0, LEVEL_WARNING, "Unknown music style '%s'\n", music_style.c_str());
 
-	musicPlayFrom("random");
+		musicPlayFrom("random");
+	}
 
-	//LoadObjectSamples(sound_dir);
-	//LoadTileSamples(sound_dir);
-	LoadSfxManager(sfx_style);
+//  if(sfx_enabled)  // commented out to allow toggling
+	{
+		//LoadObjectSamples(sound_dir);
+		//LoadTileSamples(sound_dir);
+		LoadSfxManager(sfx_style);
+	}
 
 	return true;
 }
 
 bool SoundManager::initAudio() {
-	assert(!_midiDriver);
-
-	int devFlags = MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32;
-	if (game_type == NUVIE_GAME_U6)
-		// CMS, Tandy and SSI are only supported by Ultima 6 DOS.
-		devFlags |= MDT_CMS | MDT_PCJR | MDT_C64;
-
-	// Check the type of device that the user has configured.
-	MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(devFlags);
-	_deviceType = MidiDriver::getMusicType(dev);
-
-	if (_deviceType == MT_GM && ConfMan.getBool("native_mt32"))
-		_deviceType = MT_MT32;
-
-	switch (_deviceType) {
-	case MT_ADLIB:
-		_midiDriver = new MidiDriver_M_AdLib();
-		break;
-	case MT_MT32:
-	case MT_GM:
-		_midiDriver = _mt32MidiDriver = new MidiDriver_M_MT32();
-		// TODO Parse MIDI.DAT
-		_mt32InstrumentMapping = DEFAULT_MT32_INSTRUMENT_MAPPING;
-		break;
-	case MT_CMS:
-	case MT_PCJR:
-	case MT_C64:
-	default:
-		// TODO Implement these
-		_midiDriver = new MidiDriver_NULL_Multisource();
-		break;
-	}
-	_midiDriver->property(MidiDriver::PROP_USER_VOLUME_SCALING, true);
-
-	// TODO Only Ultima 6 M format is supported.
-	_midiParser = new MidiParser_M(0);
-	_midiParser->property(MidiParser::mpDisableAutoStartPlayback, true);
-
-	// Open the MIDI driver(s).
-	int returnCode = _midiDriver->open();
-	if (returnCode != 0) {
-		warning("SoundManager::initAudio - Failed to open M music driver - error code %d.", returnCode);
-		return false;
-	}
-
-	syncSoundSettings();
-
-	// Connect the driver and the parser.
-	_midiParser->setMidiDriver(_midiDriver);
-	_midiParser->setTimerRate(_midiDriver->getBaseTempo());
-	_midiDriver->setTimerCallback(_midiParser, &_midiParser->timerCallback);
-
-	//opl = new CEmuopl(_mixer->getOutputRate(), true, true);
-
+	opl = new CEmuopl(_mixer->getOutputRate(), true, true);
 	return true;
 }
 
@@ -252,55 +197,46 @@ bool SoundManager::LoadNativeU6Songs() {
 	Song *song;
 
 	string filename;
-	string fileId;
 
-	fileId = "brit.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
+	config_get_path(m_Config, "brit.m", filename);
+	song = new SongAdPlug(_mixer, opl);
 // loadSong(song, filename.c_str());
-	loadSong(song, filename.c_str(), fileId.c_str(), "Rule Britannia");
+	loadSong(song, filename.c_str(), "Rule Britannia");
 	groupAddSong("random", song);
 
-	fileId = "forest.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Wanderer (Forest)");
+	config_get_path(m_Config, "forest.m", filename);
+	song = new SongAdPlug(_mixer, opl);
+	loadSong(song, filename.c_str(), "Wanderer (Forest)");
 	groupAddSong("random", song);
 
-	fileId = "stones.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Stones");
+	config_get_path(m_Config, "stones.m", filename);
+	song = new SongAdPlug(_mixer, opl);
+	loadSong(song, filename.c_str(), "Stones");
 	groupAddSong("random", song);
 
-	fileId = "ultima.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Ultima VI Theme");
+	config_get_path(m_Config, "ultima.m", filename);
+	song = new SongAdPlug(_mixer, opl);
+	loadSong(song, filename.c_str(), "Ultima VI Theme");
 	groupAddSong("random", song);
 
-	fileId = "engage.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Engagement and Melee");
+	config_get_path(m_Config, "engage.m", filename);
+	song = new SongAdPlug(_mixer, opl);
+	loadSong(song, filename.c_str(), "Engagement and Melee");
 	groupAddSong("combat", song);
 
-	fileId = "hornpipe.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Captain Johne's Hornpipe");
+	config_get_path(m_Config, "hornpipe.m", filename);
+	song = new SongAdPlug(_mixer, opl);
+	loadSong(song, filename.c_str(), "Captain Johne's Hornpipe");
 	groupAddSong("boat", song);
 
-	fileId = "gargoyle.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Audchar Gargl Zenmur");
+	config_get_path(m_Config, "gargoyle.m", filename);
+	song = new SongAdPlug(_mixer, opl);
+	loadSong(song, filename.c_str(), "Audchar Gargl Zenmur");
 	groupAddSong("gargoyle", song);
 
-	fileId = "dungeon.m";
-	config_get_path(m_Config, fileId, filename);
-	song = new SongFilename();
-	loadSong(song, filename.c_str(), fileId.c_str(), "Dungeon");
+	config_get_path(m_Config, "dungeon.m", filename);
+	song = new SongAdPlug(_mixer, opl);
+	loadSong(song, filename.c_str(), "Dungeon");
 	groupAddSong("dungeon", song);
 
 	return true;
@@ -332,10 +268,8 @@ bool SoundManager::LoadCustomSongs(string sound_dir) {
 
 		song = (Song *)SongExists(token2);
 		if (song == NULL) {
-			// Note: the base class Song does not have an implementation for
-			// Init, so loading custom songs does not work.
 			song = new Song;
-			if (!loadSong(song, filename.c_str(), token2))
+			if (!loadSong(song, filename.c_str()))
 				continue; //error loading song
 		}
 
@@ -348,8 +282,8 @@ bool SoundManager::LoadCustomSongs(string sound_dir) {
 	return true;
 }
 
-bool SoundManager::loadSong(Song *song, const char *filename, const char *fileId) {
-	if (song->Init(filename, fileId)) {
+bool SoundManager::loadSong(Song *song, const char *filename) {
+	if (song->Init(filename)) {
 		m_Songs.push_back(song);       //add it to our global list
 		return true;
 	} else {
@@ -360,9 +294,9 @@ bool SoundManager::loadSong(Song *song, const char *filename, const char *fileId
 }
 
 // (SB-X)
-bool SoundManager::loadSong(Song *song, const char *filename, const char *fileId, const char *title) {
-	if (loadSong(song, filename, fileId) == true) {
-		song->SetTitle(title);
+bool SoundManager::loadSong(Song *song, const char *filename, const char *title) {
+	if (loadSong(song, filename) == true) {
+		song->SetName(title);
 		return true;
 	}
 	return false;
@@ -546,8 +480,6 @@ bool SoundManager::LoadSfxManager(string sfx_style) {
 }
 
 void SoundManager::musicPlayFrom(string group) {
-	Common::StackLock lock(_musicMutex);
-
 	if (!music_enabled || !audio_enabled)
 		return;
 	if (m_CurrentGroup != group) {
@@ -558,55 +490,25 @@ void SoundManager::musicPlayFrom(string group) {
 }
 
 void SoundManager::musicPause() {
-	Common::StackLock lock(_musicMutex);
-
-	if (m_pCurrentSong != NULL && _midiParser->isPlaying()) {
-		_midiParser->stopPlaying();
+//Mix_PauseMusic();
+	if (m_pCurrentSong != NULL) {
+		m_pCurrentSong->Stop();
 	}
 }
 
 /* don't call if audio or music is disabled */
 void SoundManager::musicPlay() {
-	Common::StackLock lock(_musicMutex);
-
-	if (m_pCurrentSong != NULL && _midiParser->isPlaying()) {
-		// Already playing a song.
-		return;
-	}
+// Mix_ResumeMusic();
 
-	// (SB-X) Get a new song if stopped.
+// (SB-X) Get a new song if stopped.
 	if (m_pCurrentSong == NULL)
 		m_pCurrentSong = RequestSong(m_CurrentGroup);
 
 	if (m_pCurrentSong != NULL) {
-		DEBUG(0, LEVEL_INFORMATIONAL, "assigning new song! '%s'\n", m_pCurrentSong->GetName().c_str());
-
-		// TODO Only Ultima 6 LZW format is supported.
-		uint32 decompressed_filesize;
-		U6Lzw lzw;
-
-		_musicData = lzw.decompress_file(m_pCurrentSong->GetName(), decompressed_filesize);
-
-		bool result = _midiParser->loadMusic(_musicData, decompressed_filesize);
-		if (result) {
-			_midiDriver->deinitSource(0);
-
-			if (_mt32MidiDriver) {
-				for (int i = 0; i < 12; i++) {
-					if (!strcmp(m_pCurrentSong->GetId().c_str(), DEFAULT_MT32_INSTRUMENT_MAPPING[i].filename)) {
-						_mt32MidiDriver->setInstrumentAssignments(DEFAULT_MT32_INSTRUMENT_MAPPING[i].instrumentMapping);
-						break;
-					}
-				}
-			}
-
-			result = _midiParser->startPlaying();
-			g_MusicFinished = false;
-		}
-		if (!result) {
-			DEBUG(0, LEVEL_ERROR, "play failed!\n");
-		}
+		m_pCurrentSong->Play();
+		m_pCurrentSong->SetVolume(music_volume);
 	}
+
 }
 
 void SoundManager::musicPlay(const char *filename, uint16 song_num) {
@@ -616,10 +518,8 @@ void SoundManager::musicPlay(const char *filename, uint16 song_num) {
 		return;
 
 	config_get_path(m_Config, filename, path);
-	SongFilename *song = new SongFilename();
-	song->Init(path.c_str(), filename, song_num);
-
-	Common::StackLock lock(_musicMutex);
+	SongAdPlug *song = new SongAdPlug(_mixer, opl);
+	song->Init(path.c_str(), song_num);
 
 	musicStop();
 	m_pCurrentSong = song;
@@ -629,14 +529,8 @@ void SoundManager::musicPlay(const char *filename, uint16 song_num) {
 
 // (SB-X) Stop the current song so a new song will play when resumed.
 void SoundManager::musicStop() {
-	Common::StackLock lock(_musicMutex);
-
 	musicPause();
 	m_pCurrentSong = NULL;
-	if (_musicData) {
-		delete _musicData;
-		_musicData = nullptr;
-	}
 }
 
 Std::list < SoundManagerSfx >::iterator SoundManagerSfx_find(Std::list < SoundManagerSfx >::iterator first, Std::list < SoundManagerSfx >::iterator last, const SfxIdType &value) {
@@ -766,13 +660,26 @@ void SoundManager::update_map_sfx() {
 
 void SoundManager::update() {
 	if (music_enabled && audio_enabled && g_MusicFinished) {
-		Common::StackLock lock(_musicMutex);
+		g_MusicFinished = false;
+		if (m_pCurrentSong != NULL) {
+			m_pCurrentSong->Stop();
+		}
 
-		musicPause();
-		musicPlay();
+		if (m_CurrentGroup.length() > 0)
+			m_pCurrentSong = SoundManager::RequestSong(m_CurrentGroup);
+
+		if (m_pCurrentSong) {
+			DEBUG(0, LEVEL_INFORMATIONAL, "assigning new song! '%s'\n", m_pCurrentSong->GetName().c_str());
+			if (!m_pCurrentSong->Play(false)) {
+				DEBUG(0, LEVEL_ERROR, "play failed!\n");
+			}
+			m_pCurrentSong->SetVolume(music_volume);
+		}
 	}
+
 }
 
+
 Sound *SoundManager::SongExists(string name) {
 	Std::list < Sound * >::iterator it;
 	for (it = m_Songs.begin(); it != m_Songs.end(); ++it) {
@@ -872,24 +779,6 @@ bool SoundManager::playSfx(uint16 sfx_id, bool async) {
 	return false;
 }
 
-void SoundManager::syncSoundSettings() {
-	set_audio_enabled(
-		!ConfMan.hasKey("mute") || !ConfMan.getBool("mute"));
-	set_sfx_enabled(
-		!ConfMan.hasKey("sfx_mute") || !ConfMan.getBool("sfx_mute"));
-	// TODO Music is disabled for SE and MD for now
-	set_music_enabled(game_type == NUVIE_GAME_U6 && 
-		(!ConfMan.hasKey("music_mute") || !ConfMan.getBool("music_mute")));
-	set_speech_enabled(game_type == NUVIE_GAME_U6 && 
-		(!ConfMan.hasKey("speech_mute") || !ConfMan.getBool("speech_mute")));
-
-	set_sfx_volume(ConfMan.hasKey("sfx_volume") ? clamp(ConfMan.getInt("sfx_volume"), 0, 255) : 255);
-	set_music_volume(ConfMan.hasKey("music_volume") ? clamp(ConfMan.getInt("music_volume"), 0, 255) : 255);
-
-	if (_midiDriver)
-		_midiDriver->syncSoundSettings();
-}
-
 void SoundManager::set_audio_enabled(bool val) {
 	audio_enabled = val;
 	if (audio_enabled && music_enabled)
diff --git a/engines/ultima/nuvie/sound/sound_manager.h b/engines/ultima/nuvie/sound/sound_manager.h
index 8a6bf04a1d4..ab306789636 100644
--- a/engines/ultima/nuvie/sound/sound_manager.h
+++ b/engines/ultima/nuvie/sound/sound_manager.h
@@ -30,20 +30,13 @@
 //-make samples fade in & out according to distance
 //-try and use original .m files
 
-#include "mididrv_m_adlib.h"
-#include "mididrv_m_mt32.h"
-#include "midiparser_m.h"
-
 #include "ultima/nuvie/sound/sound.h"
 #include "ultima/nuvie/sound/song.h"
 #include "ultima/nuvie/core/nuvie_defs.h"
 #include "ultima/nuvie/conf/configuration.h"
 #include "ultima/nuvie/files/nuvie_io_file.h"
 #include "ultima/nuvie/sound/sfx.h"
-
 #include "audio/mixer.h"
-#include "audio/mididrv.h"
-#include "common/mutex.h"
 
 namespace Ultima {
 namespace Nuvie {
@@ -60,15 +53,6 @@ struct SoundManagerSfx {
 } ;
 
 class SoundManager {
-private:
-	struct SongMT32InstrumentMapping {
-		char midiDatId;
-		const char *filename;
-		MInstrumentAssignment instrumentMapping[16];
-	};
-
-	const static SongMT32InstrumentMapping DEFAULT_MT32_INSTRUMENT_MAPPING[12];
-
 public:
 	SoundManager(Audio::Mixer *mixer);
 	~SoundManager();
@@ -89,9 +73,6 @@ public:
 	bool isSoundPLaying(Audio::SoundHandle handle);
 
 	bool playSfx(uint16 sfx_id, bool async = false);
-
-	void syncSoundSettings();
-
 	bool is_audio_enabled() {
 		return audio_enabled;
 	}
@@ -131,8 +112,8 @@ public:
 private:
 	bool LoadCustomSongs(string scriptname);
 	bool LoadNativeU6Songs();
-	bool loadSong(Song *song, const char *filename, const char *fileId);
-	bool loadSong(Song *song, const char *filename, const char *fileId, const char *title);
+	bool loadSong(Song *song, const char *filename);
+	bool loadSong(Song *song, const char *filename, const char *title);
 	bool groupAddSong(const char *group, Song *song);
 
 	//bool LoadObjectSamples(string sound_dir);
@@ -175,14 +156,6 @@ private:
 
 	CEmuopl *opl;
 
-	MidiDriver_Multisource *_midiDriver;
-	MidiDriver_M_MT32 *_mt32MidiDriver;
-	MidiParser_M *_midiParser;
-	MusicType _deviceType;
-	byte *_musicData;
-	const SongMT32InstrumentMapping *_mt32InstrumentMapping;
-	Common::Mutex _musicMutex;
-
 	int game_type; //FIXME there's a nuvie_game_t, but almost everything uses int game_type (or gametype)
 
 public:




More information about the Scummvm-git-logs mailing list