2007-05-30 21:56:52 +00:00
|
|
|
/* 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.
|
2006-03-05 05:14:20 +00:00
|
|
|
*
|
2021-12-26 18:47:58 +01:00
|
|
|
* 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.
|
2014-02-18 02:34:24 +01:00
|
|
|
*
|
2006-03-05 05:14:20 +00:00
|
|
|
* 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.
|
2014-02-18 02:34:24 +01:00
|
|
|
*
|
2006-03-05 05:14:20 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
2021-12-26 18:47:58 +01:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2006-03-05 05:14:20 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2006-03-05 05:14:20 +00:00
|
|
|
|
2011-04-24 11:34:27 +03:00
|
|
|
#include "common/debug.h"
|
|
|
|
#include "common/textconsole.h"
|
2006-03-05 05:14:20 +00:00
|
|
|
#include "common/util.h"
|
2012-09-20 01:57:53 +02:00
|
|
|
#include "scumm/scumm.h"
|
2022-10-02 14:46:34 +02:00
|
|
|
#include "scumm/imuse/imuse_internal.h"
|
2006-03-05 05:14:20 +00:00
|
|
|
|
|
|
|
namespace Scumm {
|
|
|
|
|
|
|
|
////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// IMuse Part implementation
|
|
|
|
//
|
|
|
|
////////////////////////////////////////
|
|
|
|
|
|
|
|
Part::Part() {
|
|
|
|
_slot = 0;
|
2021-11-13 23:40:38 +02:00
|
|
|
_next = nullptr;
|
|
|
|
_prev = nullptr;
|
|
|
|
_mc = nullptr;
|
|
|
|
_player = nullptr;
|
2006-03-05 05:14:20 +00:00
|
|
|
_pitchbend = 0;
|
|
|
|
_pitchbend_factor = 0;
|
2022-10-07 19:48:57 +02:00
|
|
|
_volControlSensitivity = 127;
|
2006-03-05 05:14:20 +00:00
|
|
|
_transpose = 0;
|
|
|
|
_transpose_eff = 0;
|
|
|
|
_vol = 0;
|
|
|
|
_vol_eff = 0;
|
|
|
|
_detune = 0;
|
|
|
|
_detune_eff = 0;
|
|
|
|
_pan = 0;
|
|
|
|
_pan_eff = 0;
|
2022-10-04 04:28:37 +02:00
|
|
|
_polyphony = 0;
|
2006-03-05 05:14:20 +00:00
|
|
|
_on = false;
|
|
|
|
_modwheel = 0;
|
|
|
|
_pedal = false;
|
|
|
|
_pri = 0;
|
|
|
|
_pri_eff = 0;
|
|
|
|
_chan = 0;
|
|
|
|
_effect_level = 0;
|
|
|
|
_chorus = 0;
|
|
|
|
_percussion = 0;
|
|
|
|
_bank = 0;
|
|
|
|
_unassigned_instrument = false;
|
|
|
|
}
|
|
|
|
|
2017-11-29 00:06:12 -06:00
|
|
|
void Part::saveLoadWithSerializer(Common::Serializer &ser) {
|
2006-03-05 05:14:20 +00:00
|
|
|
int num;
|
2017-11-29 00:06:12 -06:00
|
|
|
if (ser.isSaving()) {
|
2006-03-05 05:14:20 +00:00
|
|
|
num = (_next ? (_next - _se->_parts + 1) : 0);
|
2017-11-29 00:06:12 -06:00
|
|
|
ser.syncAsUint16LE(num);
|
2006-03-05 05:14:20 +00:00
|
|
|
|
|
|
|
num = (_prev ? (_prev - _se->_parts + 1) : 0);
|
2017-11-29 00:06:12 -06:00
|
|
|
ser.syncAsUint16LE(num);
|
2006-03-05 05:14:20 +00:00
|
|
|
|
|
|
|
num = (_player ? (_player - _se->_players + 1) : 0);
|
2017-11-29 00:06:12 -06:00
|
|
|
ser.syncAsUint16LE(num);
|
2006-03-05 05:14:20 +00:00
|
|
|
} else {
|
2017-11-29 00:06:12 -06:00
|
|
|
ser.syncAsUint16LE(num);
|
2021-11-13 23:40:38 +02:00
|
|
|
_next = (num ? &_se->_parts[num - 1] : nullptr);
|
2006-03-05 05:14:20 +00:00
|
|
|
|
2017-11-29 00:06:12 -06:00
|
|
|
ser.syncAsUint16LE(num);
|
2021-11-13 23:40:38 +02:00
|
|
|
_prev = (num ? &_se->_parts[num - 1] : nullptr);
|
2006-03-05 05:14:20 +00:00
|
|
|
|
2017-11-29 00:06:12 -06:00
|
|
|
ser.syncAsUint16LE(num);
|
2021-11-13 23:40:38 +02:00
|
|
|
_player = (num ? &_se->_players[num - 1] : nullptr);
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
2017-11-29 00:06:12 -06:00
|
|
|
|
|
|
|
ser.syncAsSint16LE(_pitchbend, VER(8));
|
|
|
|
ser.syncAsByte(_pitchbend_factor, VER(8));
|
|
|
|
ser.syncAsSByte(_transpose, VER(8));
|
|
|
|
ser.syncAsByte(_vol, VER(8));
|
|
|
|
ser.syncAsSByte(_detune, VER(8));
|
|
|
|
ser.syncAsSByte(_pan, VER(8));
|
|
|
|
ser.syncAsByte(_on, VER(8));
|
|
|
|
ser.syncAsByte(_modwheel, VER(8));
|
|
|
|
ser.syncAsByte(_pedal, VER(8));
|
|
|
|
ser.skip(1, VER(8), VER(16)); // _program
|
|
|
|
ser.syncAsByte(_pri, VER(8));
|
|
|
|
ser.syncAsByte(_chan, VER(8));
|
|
|
|
ser.syncAsByte(_effect_level, VER(8));
|
|
|
|
ser.syncAsByte(_chorus, VER(8));
|
|
|
|
ser.syncAsByte(_percussion, VER(8));
|
|
|
|
ser.syncAsByte(_bank, VER(8));
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::set_detune(int8 detune) {
|
2012-10-01 03:01:21 +02:00
|
|
|
// Sam&Max does not have detune, so we just ignore this here. We still get
|
|
|
|
// this called, since Sam&Max uses the same controller for a different
|
|
|
|
// purpose.
|
2022-10-04 04:28:37 +02:00
|
|
|
if (_se->_newSystem)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_detune_eff = clamp((_detune = detune) + _player->getDetune(), -128, 127);
|
2022-10-07 20:27:06 +02:00
|
|
|
sendDetune();
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::pitchBend(int16 value) {
|
|
|
|
_pitchbend = value;
|
2009-09-18 15:54:39 +00:00
|
|
|
sendPitchBend();
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::volume(byte value) {
|
2022-10-07 19:48:57 +02:00
|
|
|
_vol = value;
|
|
|
|
sendVolume(0);
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::set_pri(int8 pri) {
|
|
|
|
_pri_eff = clamp((_pri = pri) + _player->getPriority(), 0, 255);
|
|
|
|
if (_mc)
|
|
|
|
_mc->priority(_pri_eff);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::set_pan(int8 pan) {
|
|
|
|
_pan_eff = clamp((_pan = pan) + _player->getPan(), -64, 63);
|
2009-09-18 15:54:39 +00:00
|
|
|
sendPanPosition(_pan_eff + 0x40);
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
2022-10-04 04:28:37 +02:00
|
|
|
void Part::set_polyphony(byte val) {
|
|
|
|
if (!_se->_newSystem)
|
|
|
|
return;
|
|
|
|
_polyphony = val;
|
|
|
|
if (_mc)
|
|
|
|
_mc->controlChange(17, val);
|
2022-10-02 14:46:34 +02:00
|
|
|
}
|
|
|
|
|
2022-09-08 22:41:06 +02:00
|
|
|
void Part::set_transpose(int8 transpose, int8 clipRangeLow, int8 clipRangeHi) {
|
|
|
|
if (_se->_game_id == GID_TENTACLE && (transpose > 24 || transpose < -24))
|
|
|
|
return;
|
|
|
|
|
2011-05-22 18:25:29 +02:00
|
|
|
_transpose = transpose;
|
2022-09-08 22:41:06 +02:00
|
|
|
// The Amiga versions have a signed/unsigned bug which makes the check for _transpose == -128 impossible. They actually check for
|
2022-09-08 20:46:33 +02:00
|
|
|
// a value of 128 with a signed int8 (a signed int8 can never be 128). The playback depends on this being implemented exactly
|
|
|
|
// like in the original driver. I found this bug with the WinUAE debugger. The DOS versions do not have that bug.
|
2022-09-13 19:52:46 +02:00
|
|
|
_transpose_eff = (_se->_soundType != MDT_AMIGA && _transpose == -128) ? 0 : transpose_clamp(_transpose + _player->getTranspose(), clipRangeLow, clipRangeHi);
|
2022-10-07 20:27:06 +02:00
|
|
|
sendTranspose();
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::sustain(bool value) {
|
|
|
|
_pedal = value;
|
|
|
|
if (_mc)
|
|
|
|
_mc->sustain(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::modulationWheel(byte value) {
|
|
|
|
_modwheel = value;
|
|
|
|
if (_mc)
|
|
|
|
_mc->modulationWheel(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::chorusLevel(byte value) {
|
|
|
|
_chorus = value;
|
|
|
|
if (_mc)
|
|
|
|
_mc->chorusLevel(value);
|
|
|
|
}
|
|
|
|
|
2009-09-18 15:12:27 +00:00
|
|
|
void Part::effectLevel(byte value) {
|
2006-03-05 05:14:20 +00:00
|
|
|
_effect_level = value;
|
2009-09-18 15:54:39 +00:00
|
|
|
sendEffectLevel(value);
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::fix_after_load() {
|
2022-09-13 19:52:46 +02:00
|
|
|
int lim = (_se->_game_id == GID_TENTACLE || _se->_soundType == MDT_AMIGA|| _se->isNativeMT32()) ? 12 : 24;
|
2022-09-08 22:41:06 +02:00
|
|
|
set_transpose(_transpose, -lim, lim);
|
2006-03-05 05:14:20 +00:00
|
|
|
volume(_vol);
|
|
|
|
set_detune(_detune);
|
|
|
|
set_pri(_pri);
|
|
|
|
set_pan(_pan);
|
|
|
|
sendAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::pitchBendFactor(byte value) {
|
|
|
|
if (value > 12)
|
|
|
|
return;
|
|
|
|
pitchBend(0);
|
|
|
|
_pitchbend_factor = value;
|
2022-10-07 15:32:23 +02:00
|
|
|
if (_mc)
|
2006-03-05 05:14:20 +00:00
|
|
|
_mc->pitchBendFactor(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::set_onoff(bool on) {
|
|
|
|
if (_on != on) {
|
|
|
|
_on = on;
|
|
|
|
if (!on)
|
|
|
|
off();
|
|
|
|
if (!_percussion)
|
|
|
|
_player->_se->reallocateMidiChannels(_player->getMidiDriver());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-11 22:53:41 +02:00
|
|
|
void Part::set_instrument(byte *data) {
|
2022-09-13 19:52:46 +02:00
|
|
|
if (_se->_soundType == MDT_PCSPK)
|
2011-07-10 05:28:20 +02:00
|
|
|
_instrument.pcspk(data);
|
|
|
|
else
|
|
|
|
_instrument.adlib(data);
|
2011-07-08 04:43:45 +02:00
|
|
|
|
2006-03-05 05:14:20 +00:00
|
|
|
if (clearToTransmit())
|
|
|
|
_instrument.send(_mc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::load_global_instrument(byte slot) {
|
2011-07-10 05:21:25 +02:00
|
|
|
_player->_se->copyGlobalInstrument(slot, &_instrument);
|
2006-03-05 05:14:20 +00:00
|
|
|
if (clearToTransmit())
|
|
|
|
_instrument.send(_mc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::noteOn(byte note, byte velocity) {
|
|
|
|
if (!_on)
|
|
|
|
return;
|
|
|
|
|
|
|
|
MidiChannel *mc = _mc;
|
|
|
|
|
|
|
|
// DEBUG
|
|
|
|
if (_unassigned_instrument && !_percussion) {
|
|
|
|
_unassigned_instrument = false;
|
|
|
|
if (!_instrument.isValid()) {
|
|
|
|
debug(0, "[%02d] No instrument specified", (int)_chan);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mc && _instrument.isValid()) {
|
|
|
|
mc->noteOn(note, velocity);
|
|
|
|
} else if (_percussion) {
|
|
|
|
mc = _player->getMidiDriver()->getPercussionChannel();
|
|
|
|
if (!mc)
|
|
|
|
return;
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2022-10-04 04:28:37 +02:00
|
|
|
if (_vol_eff != _se->_rhyState.vol)
|
2006-03-05 05:14:20 +00:00
|
|
|
mc->volume(_vol_eff);
|
2022-10-04 04:28:37 +02:00
|
|
|
|
|
|
|
if (_se->_newSystem) {
|
|
|
|
if (_pri_eff != _se->_rhyState.prio)
|
|
|
|
mc->priority(_pri_eff);
|
|
|
|
if (_polyphony != _se->_rhyState.poly)
|
|
|
|
mc->controlChange(17, _polyphony);
|
|
|
|
|
|
|
|
} else if ((note < 35) && (!_player->_se->isNativeMT32())) {
|
2006-03-05 05:14:20 +00:00
|
|
|
note = Instrument::_gmRhythmMap[note];
|
2022-10-04 04:28:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
_se->_rhyState = IMuseInternal::RhyState(_vol_eff, _polyphony, _pri_eff);
|
2006-03-05 05:14:20 +00:00
|
|
|
|
|
|
|
mc->noteOn(note, velocity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::noteOff(byte note) {
|
|
|
|
if (!_on)
|
|
|
|
return;
|
|
|
|
|
|
|
|
MidiChannel *mc = _mc;
|
|
|
|
if (mc) {
|
|
|
|
mc->noteOff(note);
|
|
|
|
} else if (_percussion) {
|
|
|
|
mc = _player->getMidiDriver()->getPercussionChannel();
|
|
|
|
if (mc)
|
|
|
|
mc->noteOff(note);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 19:19:14 +02:00
|
|
|
void Part::init(bool useNativeMT32) {
|
2021-11-13 23:40:38 +02:00
|
|
|
_player = nullptr;
|
|
|
|
_next = nullptr;
|
|
|
|
_prev = nullptr;
|
|
|
|
_mc = nullptr;
|
2022-09-15 19:19:14 +02:00
|
|
|
_instrument.setNativeMT32Mode(useNativeMT32);
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::setup(Player *player) {
|
|
|
|
_player = player;
|
|
|
|
|
|
|
|
_percussion = (player->isMIDI() && _chan == 9); // true;
|
|
|
|
_on = true;
|
|
|
|
_pri_eff = player->getPriority();
|
|
|
|
_pri = 0;
|
|
|
|
_vol = 127;
|
|
|
|
_vol_eff = player->getEffectiveVolume();
|
|
|
|
_pan = clamp(player->getPan(), -64, 63);
|
|
|
|
_transpose_eff = player->getTranspose();
|
|
|
|
_transpose = 0;
|
|
|
|
_detune = 0;
|
|
|
|
_detune_eff = player->getDetune();
|
2022-10-07 15:32:23 +02:00
|
|
|
_pitchbend_factor = 2;
|
2022-10-07 19:48:57 +02:00
|
|
|
_volControlSensitivity = 127;
|
2022-10-06 16:50:46 +02:00
|
|
|
_polyphony = 1;
|
2006-03-05 05:14:20 +00:00
|
|
|
_pitchbend = 0;
|
2009-09-18 15:54:12 +00:00
|
|
|
_effect_level = player->_se->isNativeMT32() ? 127 : 64;
|
2006-03-05 05:14:20 +00:00
|
|
|
_instrument.clear();
|
|
|
|
_unassigned_instrument = true;
|
|
|
|
_chorus = 0;
|
|
|
|
_modwheel = 0;
|
|
|
|
_bank = 0;
|
|
|
|
_pedal = false;
|
2021-11-13 23:40:38 +02:00
|
|
|
_mc = nullptr;
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::uninit() {
|
|
|
|
if (!_player)
|
|
|
|
return;
|
|
|
|
off();
|
|
|
|
_player->removePart(this);
|
2021-11-13 23:40:38 +02:00
|
|
|
_player = nullptr;
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Part::off() {
|
|
|
|
if (_mc) {
|
|
|
|
_mc->allNotesOff();
|
|
|
|
_mc->release();
|
2021-11-13 23:40:38 +02:00
|
|
|
_mc = nullptr;
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Part::clearToTransmit() {
|
|
|
|
if (_mc)
|
|
|
|
return true;
|
|
|
|
if (_instrument.isValid())
|
|
|
|
_player->_se->reallocateMidiChannels(_player->getMidiDriver());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::sendAll() {
|
|
|
|
if (!clearToTransmit())
|
|
|
|
return;
|
2009-09-18 15:54:12 +00:00
|
|
|
|
2022-10-06 16:50:46 +02:00
|
|
|
_mc->pitchBendFactor(_pitchbend_factor);
|
2019-07-14 20:44:25 +02:00
|
|
|
sendTranspose();
|
2022-09-07 18:56:16 +02:00
|
|
|
sendDetune();
|
2006-03-05 05:14:20 +00:00
|
|
|
sendPitchBend();
|
|
|
|
_mc->volume(_vol_eff);
|
|
|
|
_mc->sustain(_pedal);
|
|
|
|
_mc->modulationWheel(_modwheel);
|
2009-09-18 15:54:39 +00:00
|
|
|
sendPanPosition(_pan_eff + 0x40);
|
2022-10-04 04:28:37 +02:00
|
|
|
sendPolyphony();
|
2009-09-18 15:54:12 +00:00
|
|
|
|
2006-03-05 05:14:20 +00:00
|
|
|
if (_instrument.isValid())
|
|
|
|
_instrument.send(_mc);
|
2009-09-18 15:54:12 +00:00
|
|
|
|
|
|
|
// We need to send the effect level after setting up the instrument
|
|
|
|
// otherwise the reverb setting for MT-32 will be overwritten.
|
2009-09-18 15:54:39 +00:00
|
|
|
sendEffectLevel(_effect_level);
|
2009-09-18 15:54:12 +00:00
|
|
|
|
2006-03-05 05:14:20 +00:00
|
|
|
_mc->chorusLevel(_chorus);
|
|
|
|
_mc->priority(_pri_eff);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::sendPitchBend() {
|
2022-10-07 19:48:57 +02:00
|
|
|
if (_se->_newSystem && !_pitchbend_factor) {
|
|
|
|
sendVolumeFade();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-04-30 14:02:37 +02:00
|
|
|
if (_mc)
|
|
|
|
_mc->pitchBend(_pitchbend);
|
2019-07-14 20:44:25 +02:00
|
|
|
}
|
|
|
|
|
2022-10-07 19:48:57 +02:00
|
|
|
void Part::sendVolume(int8 fadeModifier) {
|
|
|
|
uint16 vol = (_vol + fadeModifier + 1) * _player->getEffectiveVolume();
|
|
|
|
|
|
|
|
if (_se->_newSystem)
|
|
|
|
vol = (vol * (_volControlSensitivity + 1)) >> 7;
|
|
|
|
|
|
|
|
_vol_eff = vol >> 7;
|
|
|
|
|
|
|
|
if (_mc)
|
|
|
|
_mc->volume(_vol_eff);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::sendVolumeFade() {
|
|
|
|
int16 fadeModifier = ((((_pitchbend >= 0) ? 127 - _vol : _vol) + 1) * _pitchbend) >> 7;
|
|
|
|
sendVolume(fadeModifier);
|
|
|
|
}
|
|
|
|
|
2019-07-14 20:44:25 +02:00
|
|
|
void Part::sendTranspose() {
|
|
|
|
if (!_mc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_mc->transpose(_transpose_eff);
|
2006-03-05 05:14:20 +00:00
|
|
|
}
|
|
|
|
|
2022-09-07 18:56:16 +02:00
|
|
|
void Part::sendDetune() {
|
|
|
|
if (!_mc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
_mc->detune(_detune_eff);
|
|
|
|
}
|
|
|
|
|
2006-03-05 05:14:20 +00:00
|
|
|
void Part::programChange(byte value) {
|
|
|
|
_bank = 0;
|
|
|
|
_instrument.program(value, _player->isMT32());
|
|
|
|
if (clearToTransmit())
|
|
|
|
_instrument.send(_mc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::set_instrument(uint b) {
|
|
|
|
_bank = (byte)(b >> 8);
|
|
|
|
if (_bank)
|
|
|
|
error("Non-zero instrument bank selection. Please report this");
|
2012-09-20 01:57:53 +02:00
|
|
|
// HACK: Horrible hack to allow tracing of program change source.
|
2012-09-20 12:00:13 -04:00
|
|
|
// The Mac m68k versions of MI2 and Indy4 use a different program "bank"
|
2012-09-20 01:57:53 +02:00
|
|
|
// when it gets program change events through the iMuse SysEx handler.
|
|
|
|
// We emulate this by introducing a special instrument, which sets
|
|
|
|
// the instrument via sysEx_customInstrument. This seems to be
|
|
|
|
// exclusively used for special sound effects like the "spit" sound.
|
2012-09-20 11:58:04 -04:00
|
|
|
if (g_scumm->isMacM68kIMuse()) {
|
2012-09-20 01:57:53 +02:00
|
|
|
_instrument.macSfx(b);
|
|
|
|
} else {
|
|
|
|
_instrument.program((byte)b, _player->isMT32());
|
|
|
|
}
|
2006-03-05 05:14:20 +00:00
|
|
|
if (clearToTransmit())
|
|
|
|
_instrument.send(_mc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Part::allNotesOff() {
|
|
|
|
if (!_mc)
|
|
|
|
return;
|
|
|
|
_mc->allNotesOff();
|
|
|
|
}
|
|
|
|
|
2009-09-18 15:54:39 +00:00
|
|
|
void Part::sendPanPosition(uint8 value) {
|
2009-09-18 15:12:27 +00:00
|
|
|
if (!_mc)
|
|
|
|
return;
|
|
|
|
|
2021-02-28 01:28:23 -08:00
|
|
|
// As described in bug report #1849 "MI2: Minor problems in native MT-32 mode"
|
2009-09-18 15:12:27 +00:00
|
|
|
// the original iMuse MT-32 driver did revert the panning. So we do the same
|
|
|
|
// here in our code to have correctly panned sound output.
|
|
|
|
if (_player->_se->isNativeMT32())
|
|
|
|
value = 127 - value;
|
|
|
|
|
|
|
|
_mc->panPosition(value);
|
|
|
|
}
|
|
|
|
|
2009-09-18 15:54:39 +00:00
|
|
|
void Part::sendEffectLevel(uint8 value) {
|
2009-09-18 15:54:12 +00:00
|
|
|
if (!_mc)
|
|
|
|
return;
|
2022-10-04 04:28:37 +02:00
|
|
|
_mc->effectLevel(value);
|
|
|
|
}
|
2009-09-18 15:54:12 +00:00
|
|
|
|
2022-10-04 04:28:37 +02:00
|
|
|
void Part::sendPolyphony() {
|
|
|
|
if (!_mc || !_se->_newSystem)
|
|
|
|
return;
|
|
|
|
_mc->controlChange(17, _polyphony);
|
2009-09-18 15:54:12 +00:00
|
|
|
}
|
|
|
|
|
2006-03-05 05:14:20 +00:00
|
|
|
} // End of namespace Scumm
|