[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