aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/softseq
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sfx/softseq')
-rw-r--r--engines/sci/sfx/softseq/adlib.cpp827
-rw-r--r--engines/sci/sfx/softseq/amiga.cpp676
-rw-r--r--engines/sci/sfx/softseq/mididriver.h110
-rw-r--r--engines/sci/sfx/softseq/pcjr.cpp209
-rw-r--r--engines/sci/sfx/softseq/pcjr.h84
5 files changed, 0 insertions, 1906 deletions
diff --git a/engines/sci/sfx/softseq/adlib.cpp b/engines/sci/sfx/softseq/adlib.cpp
deleted file mode 100644
index 11802917a2..0000000000
--- a/engines/sci/sfx/softseq/adlib.cpp
+++ /dev/null
@@ -1,827 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sci/sci.h"
-
-#include "sound/fmopl.h"
-#include "sound/softsynth/emumidi.h"
-
-#include "sci/resource.h"
-#include "sci/sfx/softseq/mididriver.h"
-
-namespace Sci {
-
-#ifdef __DC__
-#define STEREO false
-#else
-#define STEREO true
-#endif
-
-// FIXME: We don't seem to be sending the polyphony init data, so disable this for now
-#define ADLIB_DISABLE_VOICE_MAPPING
-
-class MidiDriver_Adlib : public MidiDriver_Emulated {
-public:
- enum {
- kVoices = 9,
- kRhythmKeys = 62
- };
-
- MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15), _rhythmKeyMap(0), _opl(0) { }
- virtual ~MidiDriver_Adlib() { }
-
- // MidiDriver
- int open(bool isSCI0);
- void close();
- void send(uint32 b);
- MidiChannel *allocateChannel() { return NULL; }
- MidiChannel *getPercussionChannel() { return NULL; }
-
- // AudioStream
- bool isStereo() const { return _stereo; }
- int getRate() const { return _mixer->getOutputRate(); }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
-
- void setVolume(byte volume);
- void playSwitch(bool play);
- bool loadResource(const byte *data, uint size);
- virtual uint32 property(int prop, uint32 param);
-
-private:
- enum ChannelID {
- kLeftChannel = 1,
- kRightChannel = 2
- };
-
- struct AdlibOperator {
- bool amplitudeMod;
- bool vibrato;
- bool envelopeType;
- bool kbScaleRate;
- byte frequencyMult; // (0-15)
- byte kbScaleLevel; // (0-3)
- byte totalLevel; // (0-63, 0=max, 63=min)
- byte attackRate; // (0-15)
- byte decayRate; // (0-15)
- byte sustainLevel; // (0-15)
- byte releaseRate; // (0-15)
- byte waveForm; // (0-3)
- };
-
- struct AdlibModulator {
- byte feedback; // (0-7)
- bool algorithm;
- };
-
- struct AdlibPatch {
- AdlibOperator op[2];
- AdlibModulator mod;
- };
-
- struct Channel {
- uint8 patch; // Patch setting
- uint8 volume; // Channel volume (0-63)
- uint8 pan; // Pan setting (0-127, 64 is center)
- uint8 holdPedal; // Hold pedal setting (0 to 63 is off, 127 to 64 is on)
- uint8 extraVoices; // The number of additional voices this channel optimally needs
- uint16 pitchWheel; // Pitch wheel setting (0-16383, 8192 is center)
- uint8 lastVoice; // Last voice used for this MIDI channel
- bool enableVelocity; // Enable velocity control (SCI0)
-
- Channel() : patch(0), volume(63), pan(64), holdPedal(0), extraVoices(0),
- pitchWheel(8192), lastVoice(0), enableVelocity(false) { }
- };
-
- struct AdlibVoice {
- int8 channel; // MIDI channel that this voice is assigned to or -1
- int8 note; // Currently playing MIDI note or -1
- int patch; // Currently playing patch or -1
- uint8 velocity; // Note velocity
- bool isSustained; // Flag indicating a note that is being sustained by the hold pedal
- uint16 age; // Age of the current note
-
- AdlibVoice() : channel(-1), note(-1), patch(-1), velocity(0), isSustained(false), age(0) { }
- };
-
- bool _stereo;
- bool _isSCI0;
- OPL::OPL *_opl;
- bool _playSwitch;
- int _masterVolume;
- Channel _channels[MIDI_CHANNELS];
- AdlibVoice _voices[kVoices];
- byte *_rhythmKeyMap;
- Common::Array<AdlibPatch> _patches;
-
- void loadInstrument(const byte *ins);
- void voiceOn(int voice, int note, int velocity);
- void voiceOff(int voice);
- void setPatch(int voice, int patch);
- void setNote(int voice, int note, bool key);
- void setVelocity(int voice);
- void setOperator(int oper, AdlibOperator &op);
- void setRegister(int reg, int value, int channels = kLeftChannel | kRightChannel);
- void renewNotes(int channel, bool key);
- void noteOn(int channel, int note, int velocity);
- void noteOff(int channel, int note);
- int findVoice(int channel);
- void voiceMapping(int channel, int voices);
- void assignVoices(int channel, int voices);
- void releaseVoices(int channel, int voices);
- void donateVoices();
- int findVoiceBasic(int channel);
- void setVelocityReg(int regOffset, int velocity, int kbScaleLevel, int pan);
- int calcVelocity(int voice, int op);
-};
-
-class MidiPlayer_Adlib : public MidiPlayer {
-public:
- MidiPlayer_Adlib() { _driver = new MidiDriver_Adlib(g_system->getMixer()); }
- int open(ResourceManager *resMan);
- int getPlayMask(SciVersion soundVersion);
- int getPolyphony() const { return MidiDriver_Adlib::kVoices; }
- bool hasRhythmChannel() const { return false; }
- void setVolume(byte volume) { static_cast<MidiDriver_Adlib *>(_driver)->setVolume(volume); }
- void playSwitch(bool play) { static_cast<MidiDriver_Adlib *>(_driver)->playSwitch(play); }
- void loadInstrument(int idx, byte *data);
-};
-
-static const byte registerOffset[MidiDriver_Adlib::kVoices] = {
- 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12
-};
-
-static const byte velocityMap1[64] = {
- 0x00, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x12, 0x13,
- 0x14, 0x16, 0x17, 0x18, 0x1a, 0x1b, 0x1c, 0x1d,
- 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
- 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2d, 0x2d, 0x2e,
- 0x2f, 0x30, 0x31, 0x32, 0x32, 0x33, 0x34, 0x34,
- 0x35, 0x36, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3a,
- 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d,
- 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f
-};
-
-static const byte velocityMap2[64] = {
- 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a,
- 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x21,
- 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
- 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x2f, 0x30,
- 0x31, 0x32, 0x32, 0x33, 0x34, 0x34, 0x35, 0x36,
- 0x36, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a, 0x3a,
- 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d,
- 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f
-};
-
-static const int ym3812_note[13] = {
- 0x157, 0x16b, 0x181, 0x198, 0x1b0, 0x1ca,
- 0x1e5, 0x202, 0x220, 0x241, 0x263, 0x287,
- 0x2ae
-};
-
-int MidiDriver_Adlib::open(bool isSCI0) {
- int rate = _mixer->getOutputRate();
-
- _stereo = STEREO;
-
- debug(3, "ADLIB: Starting driver in %s mode", (isSCI0 ? "SCI0" : "SCI1"));
- _isSCI0 = isSCI0;
-
- _opl = OPL::Config::create(isStereo() ? OPL::Config::kDualOpl2 : OPL::Config::kOpl2);
-
- // Try falling back to mono, thus plain OPL2 emualtor, when no Dual OPL2 is available.
- if (!_opl && _stereo) {
- _stereo = false;
- _opl = OPL::Config::create(OPL::Config::kOpl2);
- }
-
- if (!_opl)
- return -1;
-
- _opl->init(rate);
-
- setRegister(0xBD, 0);
- setRegister(0x08, 0);
- setRegister(0x01, 0x20);
-
- MidiDriver_Emulated::open();
-
- _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, false);
-
- return 0;
-}
-
-void MidiDriver_Adlib::close() {
- _mixer->stopHandle(_mixerSoundHandle);
-
- delete _opl;
- delete[] _rhythmKeyMap;
-}
-
-void MidiDriver_Adlib::setVolume(byte volume) {
- _masterVolume = volume;
- renewNotes(-1, true);
-}
-
-// MIDI messages can be found at http://www.midi.org/techspecs/midimessages.php
-void MidiDriver_Adlib::send(uint32 b) {
- byte command = b & 0xf0;
- byte channel = b & 0xf;
- byte op1 = (b >> 8) & 0xff;
- byte op2 = (b >> 16) & 0xff;
-
- switch (command) {
- case 0x80:
- noteOff(channel, op1);
- break;
- case 0x90:
- noteOn(channel, op1, op2);
- break;
- case 0xe0:
- _channels[channel].pitchWheel = (op1 & 0x7f) | ((op2 & 0x7f) << 7);
- renewNotes(channel, true);
- break;
- case 0xb0:
- switch (op1) {
- case 0x07:
- _channels[channel].volume = op2 >> 1;
- renewNotes(channel, true);
- break;
- case 0x0a:
- _channels[channel].pan = op2;
- renewNotes(channel, true);
- break;
- case 0x40:
- _channels[channel].holdPedal = op2;
- if (op2 == 0) {
- for (int i = 0; i < kVoices; i++) {
- if ((_voices[i].channel == channel) && _voices[i].isSustained)
- voiceOff(i);
- }
- }
- break;
- case 0x4b:
-#ifndef ADLIB_DISABLE_VOICE_MAPPING
- voiceMapping(channel, op2);
-#endif
- break;
- case 0x4e:
- // FIXME: this flag should be set to 0 when a new song is started
- debug(3, "ADLIB: Setting velocity control flag for channel %i to %i", channel, op2);
- _channels[channel].enableVelocity = op2;
- break;
- case SCI_MIDI_CHANNEL_NOTES_OFF:
- for (int i = 0; i < kVoices; i++)
- if ((_voices[i].channel == channel) && (_voices[i].note != -1))
- voiceOff(i);
- break;
- default:
- //warning("ADLIB: ignoring MIDI command %02x %02x %02x", command | channel, op1, op2);
- break;
- }
- break;
- case 0xc0:
- _channels[channel].patch = op1;
- break;
- // The original adlib driver from sierra ignores aftertouch completely, so should we
- case 0xa0: // Polyphonic key pressure (aftertouch)
- case 0xd0: // Channel pressure (aftertouch)
- break;
- case 0xf0: // SysEx, ignore it
- break;
- default:
- warning("ADLIB: Unknown event %02x", command);
- }
-}
-
-void MidiDriver_Adlib::generateSamples(int16 *data, int len) {
- if (isStereo())
- len <<= 1;
- _opl->readBuffer(data, len);
-
- // Increase the age of the notes
- for (int i = 0; i < kVoices; i++) {
- if (_voices[i].note != -1)
- _voices[i].age++;
- }
-}
-
-void MidiDriver_Adlib::loadInstrument(const byte *ins) {
- AdlibPatch patch;
-
- // Set data for the operators
- for (int i = 0; i < 2; i++) {
- const byte *op = ins + i * 13;
- patch.op[i].kbScaleLevel = op[0] & 0x3;
- patch.op[i].frequencyMult = op[1] & 0xf;
- patch.op[i].attackRate = op[3] & 0xf;
- patch.op[i].sustainLevel = op[4] & 0xf;
- patch.op[i].envelopeType = op[5];
- patch.op[i].decayRate = op[6] & 0xf;
- patch.op[i].releaseRate = op[7] & 0xf;
- patch.op[i].totalLevel = op[8] & 0x3f;
- patch.op[i].amplitudeMod = op[9];
- patch.op[i].vibrato = op[10];
- patch.op[i].kbScaleRate = op[11];
- }
- patch.op[0].waveForm = ins[26] & 0x3;
- patch.op[1].waveForm = ins[27] & 0x3;
-
- // Set data for the modulator
- patch.mod.feedback = ins[2] & 0x7;
- patch.mod.algorithm = !ins[12]; // Flag is inverted
-
- _patches.push_back(patch);
-}
-
-void MidiDriver_Adlib::voiceMapping(int channel, int voices) {
- int curVoices = 0;
-
- for (int i = 0; i < kVoices; i++)
- if (_voices[i].channel == channel)
- curVoices++;
-
- curVoices += _channels[channel].extraVoices;
-
- if (curVoices < voices) {
- debug(3, "ADLIB: assigning %i additional voices to channel %i", voices - curVoices, channel);
- assignVoices(channel, voices - curVoices);
- } else if (curVoices > voices) {
- debug(3, "ADLIB: releasing %i voices from channel %i", curVoices - voices, channel);
- releaseVoices(channel, curVoices - voices);
- donateVoices();
- }
-}
-
-void MidiDriver_Adlib::assignVoices(int channel, int voices) {
- assert(voices > 0);
-
- for (int i = 0; i < kVoices; i++)
- if (_voices[i].channel == -1) {
- _voices[i].channel = channel;
- if (--voices == 0)
- return;
- }
-
- _channels[channel].extraVoices += voices;
-}
-
-void MidiDriver_Adlib::releaseVoices(int channel, int voices) {
- if (_channels[channel].extraVoices >= voices) {
- _channels[channel].extraVoices -= voices;
- return;
- }
-
- voices -= _channels[channel].extraVoices;
- _channels[channel].extraVoices = 0;
-
- for (int i = 0; i < kVoices; i++) {
- if ((_voices[i].channel == channel) && (_voices[i].note == -1)) {
- _voices[i].channel = -1;
- if (--voices == 0)
- return;
- }
- }
-
- for (int i = 0; i < kVoices; i++) {
- if (_voices[i].channel == channel) {
- voiceOff(i);
- _voices[i].channel = -1;
- if (--voices == 0)
- return;
- }
- }
-}
-
-void MidiDriver_Adlib::donateVoices() {
- int freeVoices = 0;
-
- for (int i = 0; i < kVoices; i++)
- if (_voices[i].channel == -1)
- freeVoices++;
-
- if (freeVoices == 0)
- return;
-
- for (int i = 0; i < MIDI_CHANNELS; i++) {
- if (_channels[i].extraVoices >= freeVoices) {
- assignVoices(i, freeVoices);
- _channels[i].extraVoices -= freeVoices;
- return;
- } else if (_channels[i].extraVoices > 0) {
- assignVoices(i, _channels[i].extraVoices);
- freeVoices -= _channels[i].extraVoices;
- _channels[i].extraVoices = 0;
- }
- }
-}
-
-void MidiDriver_Adlib::renewNotes(int channel, bool key) {
- for (int i = 0; i < kVoices; i++) {
- // Update all notes playing this channel
- if ((channel == -1) || (_voices[i].channel == channel)) {
- if (_voices[i].note != -1)
- setNote(i, _voices[i].note, key);
- }
- }
-}
-
-void MidiDriver_Adlib::noteOn(int channel, int note, int velocity) {
- if (velocity == 0)
- return noteOff(channel, note);
-
- velocity >>= 1;
-
- // Check for playable notes
- if ((note < 12) || (note > 107))
- return;
-
- for (int i = 0; i < kVoices; i++) {
- if ((_voices[i].channel == channel) && (_voices[i].note == note)) {
- voiceOff(i);
- voiceOn(i, note, velocity);
- return;
- }
- }
-
-#ifdef ADLIB_DISABLE_VOICE_MAPPING
- int voice = findVoiceBasic(channel);
-#else
- int voice = findVoice(channel);
-#endif
-
- if (voice == -1) {
- debug(3, "ADLIB: failed to find free voice assigned to channel %i", channel);
- return;
- }
-
- voiceOn(voice, note, velocity);
-}
-
-// FIXME: Temporary, see comment at top of file regarding ADLIB_DISABLE_VOICE_MAPPING
-int MidiDriver_Adlib::findVoiceBasic(int channel) {
- int voice = -1;
- int oldestVoice = -1;
- int oldestAge = -1;
-
- // Try to find a voice assigned to this channel that is free (round-robin)
- for (int i = 0; i < kVoices; i++) {
- int v = (_channels[channel].lastVoice + i + 1) % kVoices;
-
- if (_voices[v].note == -1) {
- voice = v;
- break;
- }
-
- // We also keep track of the oldest note in case the search fails
- if (_voices[v].age > oldestAge) {
- oldestAge = _voices[v].age;
- oldestVoice = v;
- }
- }
-
- if (voice == -1) {
- if (oldestVoice != -1) {
- voiceOff(oldestVoice);
- voice = oldestVoice;
- } else {
- return -1;
- }
- }
-
- _voices[voice].channel = channel;
- _channels[channel].lastVoice = voice;
- return voice;
-}
-
-int MidiDriver_Adlib::findVoice(int channel) {
- int voice = -1;
- int oldestVoice = -1;
- uint32 oldestAge = 0;
-
- // Try to find a voice assigned to this channel that is free (round-robin)
- for (int i = 0; i < kVoices; i++) {
- int v = (_channels[channel].lastVoice + i + 1) % kVoices;
-
- if (_voices[v].channel == channel) {
- if (_voices[v].note == -1) {
- voice = v;
- break;
- }
-
- // We also keep track of the oldest note in case the search fails
- // Notes started in the current time slice will not be selected
- if (_voices[v].age > oldestAge) {
- oldestAge = _voices[v].age;
- oldestVoice = v;
- }
- }
- }
-
- if (voice == -1) {
- if (oldestVoice != -1) {
- voiceOff(oldestVoice);
- voice = oldestVoice;
- } else {
- return -1;
- }
- }
-
- _channels[channel].lastVoice = voice;
- return voice;
-}
-
-void MidiDriver_Adlib::noteOff(int channel, int note) {
- for (int i = 0; i < kVoices; i++) {
- if ((_voices[i].channel == channel) && (_voices[i].note == note)) {
- if (_channels[channel].holdPedal)
- _voices[i].isSustained = true;
- else
- voiceOff(i);
- return;
- }
- }
-}
-
-void MidiDriver_Adlib::voiceOn(int voice, int note, int velocity) {
- int channel = _voices[voice].channel;
- int patch;
-
- _voices[voice].age = 0;
-
- if ((channel == 9) && _rhythmKeyMap) {
- patch = CLIP(note, 27, 88) + 101;
- } else {
- patch = _channels[channel].patch;
- }
-
- // Set patch if different from current patch
- if ((patch != _voices[voice].patch) && _playSwitch)
- setPatch(voice, patch);
-
- _voices[voice].velocity = velocity;
- setNote(voice, note, true);
-}
-
-void MidiDriver_Adlib::voiceOff(int voice) {
- _voices[voice].isSustained = false;
- setNote(voice, _voices[voice].note, 0);
- _voices[voice].note = -1;
- _voices[voice].age = 0;
-}
-
-void MidiDriver_Adlib::setNote(int voice, int note, bool key) {
- int channel = _voices[voice].channel;
- int n, fre, oct;
- float delta;
- int bend = _channels[channel].pitchWheel;
-
- if ((channel == 9) && _rhythmKeyMap) {
- note = _rhythmKeyMap[CLIP(note, 27, 88) - 27];
- }
-
- _voices[voice].note = note;
-
- delta = 0;
-
- n = note % 12;
-
- if (bend < 8192)
- bend = 8192 - bend;
- delta = (float)pow(2.0, (bend % 8192) / 8192.0);
-
- if (bend > 8192)
- fre = (int)(ym3812_note[n] * delta);
- else
- fre = (int)(ym3812_note[n] / delta);
-
- oct = note / 12 - 1;
-
- if (oct < 0)
- oct = 0;
-
- if (oct > 7)
- oct = 7;
-
- setRegister(0xA0 + voice, fre & 0xff);
- setRegister(0xB0 + voice, (key << 5) | (oct << 2) | (fre >> 8));
-
- setVelocity(voice);
-}
-
-void MidiDriver_Adlib::setVelocity(int voice) {
- AdlibPatch &patch = _patches[_voices[voice].patch];
- int pan = _channels[_voices[voice].channel].pan;
- setVelocityReg(registerOffset[voice] + 3, calcVelocity(voice, 1), patch.op[1].kbScaleLevel, pan);
-
- // In AM mode we need to set the level for both operators
- if (_patches[_voices[voice].patch].mod.algorithm == 1)
- setVelocityReg(registerOffset[voice], calcVelocity(voice, 0), patch.op[0].kbScaleLevel, pan);
-}
-
-int MidiDriver_Adlib::calcVelocity(int voice, int op) {
- if (_isSCI0) {
- int velocity = _masterVolume;
-
- if (velocity > 0)
- velocity += 3;
-
- if (velocity > 15)
- velocity = 15;
-
- int insVelocity;
- if (_channels[_voices[voice].channel].enableVelocity)
- insVelocity = _voices[voice].velocity;
- else
- insVelocity = 63 - _patches[_voices[voice].patch].op[op].totalLevel;
-
- // Note: Later SCI0 has a static table that is close to this formula, but not exactly the same.
- // Early SCI0 does (velocity * (insVelocity / 15))
- return velocity * insVelocity / 15;
- } else {
- AdlibOperator &oper = _patches[_voices[voice].patch].op[op];
- int velocity = _channels[_voices[voice].channel].volume + 1;
- velocity = velocity * (velocityMap1[_voices[voice].velocity] + 1) / 64;
- velocity = velocity * (_masterVolume + 1) / 16;
-
- if (--velocity < 0)
- velocity = 0;
-
- return velocityMap2[velocity] * (63 - oper.totalLevel) / 63;
- }
-}
-
-void MidiDriver_Adlib::setVelocityReg(int regOffset, int velocity, int kbScaleLevel, int pan) {
- if (!_playSwitch)
- velocity = 0;
-
- if (isStereo()) {
- int velLeft = velocity;
- int velRight = velocity;
-
- if (pan > 0x40)
- velLeft = velLeft * (0x7f - pan) / 0x3f;
- else if (pan < 0x40)
- velRight = velRight * pan / 0x40;
-
- setRegister(0x40 + regOffset, (kbScaleLevel << 6) | (63 - velLeft), kLeftChannel);
- setRegister(0x40 + regOffset, (kbScaleLevel << 6) | (63 - velRight), kRightChannel);
- } else {
- setRegister(0x40 + regOffset, (kbScaleLevel << 6) | (63 - velocity));
- }
-}
-
-void MidiDriver_Adlib::setPatch(int voice, int patch) {
- if ((patch < 0) || ((uint)patch >= _patches.size())) {
- warning("ADLIB: Invalid patch %i requested", patch);
- patch = 0;
- }
-
- _voices[voice].patch = patch;
- AdlibModulator &mod = _patches[patch].mod;
-
- // Set the common settings for both operators
- setOperator(registerOffset[voice], _patches[patch].op[0]);
- setOperator(registerOffset[voice] + 3, _patches[patch].op[1]);
-
- // Set the additional settings for the modulator
- byte algorithm = mod.algorithm ? 1 : 0;
- setRegister(0xC0 + voice, (mod.feedback << 1) | algorithm);
-}
-
-void MidiDriver_Adlib::setOperator(int reg, AdlibOperator &op) {
- setRegister(0x40 + reg, (op.kbScaleLevel << 6) | op.totalLevel);
- setRegister(0x60 + reg, (op.attackRate << 4) | op.decayRate);
- setRegister(0x80 + reg, (op.sustainLevel << 4) | op.releaseRate);
- setRegister(0x20 + reg, (op.amplitudeMod << 7) | (op.vibrato << 6)
- | (op.envelopeType << 5) | (op.kbScaleRate << 4) | op.frequencyMult);
- setRegister(0xE0 + reg, op.waveForm);
-}
-
-void MidiDriver_Adlib::setRegister(int reg, int value, int channels) {
- if (channels & kLeftChannel) {
- _opl->write(0x220, reg);
- _opl->write(0x221, value);
- }
-
- if (isStereo()) {
- if (channels & kRightChannel) {
- _opl->write(0x222, reg);
- _opl->write(0x223, value);
- }
- }
-}
-
-void MidiDriver_Adlib::playSwitch(bool play) {
- _playSwitch = play;
- renewNotes(-1, play);
-}
-
-bool MidiDriver_Adlib::loadResource(const byte *data, uint size) {
- if ((size != 1344) && (size != 2690) && (size != 5382)) {
- warning("ADLIB: Unsupported patch format (%i bytes)", size);
- return false;
- }
-
- for (int i = 0; i < 48; i++)
- loadInstrument(data + (28 * i));
-
- if (size == 2690) {
- for (int i = 48; i < 96; i++)
- loadInstrument(data + 2 + (28 * i));
- } else if (size == 5382) {
- for (int i = 48; i < 190; i++)
- loadInstrument(data + (28 * i));
- _rhythmKeyMap = new byte[kRhythmKeys];
- memcpy(_rhythmKeyMap, data + 5320, kRhythmKeys);
- }
-
- return true;
-}
-
-uint32 MidiDriver_Adlib::property(int prop, uint32 param) {
- switch(prop) {
- case MIDI_PROP_MASTER_VOLUME:
- if (param != 0xffff)
- _masterVolume = param;
- return _masterVolume;
- default:
- break;
- }
- return 0;
-}
-
-
-int MidiPlayer_Adlib::open(ResourceManager *resMan) {
- assert(resMan != NULL);
-
- // Load up the patch.003 file, parse out the instruments
- Resource *res = resMan->findResource(ResourceId(kResourceTypePatch, 3), 0);
- bool ok = false;
-
- if (res) {
- ok = static_cast<MidiDriver_Adlib *>(_driver)->loadResource(res->data, res->size);
- } else {
- // Early SCI0 games have the sound bank embedded in the adlib driver
-
- Common::File f;
-
- if (f.open("ADL.DRV")) {
- int size = f.size();
- const uint patchSize = 1344;
-
- if ((size == 5684) || (size == 5720) || (size == 5727)) {
- byte *buf = new byte[patchSize];
-
- if (f.seek(0x45a) && (f.read(buf, patchSize) == patchSize))
- ok = static_cast<MidiDriver_Adlib *>(_driver)->loadResource(buf, patchSize);
-
- delete[] buf;
- }
- }
- }
-
- if (!ok) {
- warning("ADLIB: Failed to load patch.003");
- return -1;
- }
-
- return static_cast<MidiDriver_Adlib *>(_driver)->open(getSciVersion() <= SCI_VERSION_0_LATE);
-}
-
-int MidiPlayer_Adlib::getPlayMask(SciVersion soundVersion) {
- return (soundVersion == SCI_VERSION_0_EARLY) ? 0x01 : 0x04;
-}
-
-MidiPlayer *MidiPlayer_Adlib_create() {
- return new MidiPlayer_Adlib();
-}
-
-MidiDriver *MidiDriver_Adlib_create() {
- return new MidiDriver_Adlib(g_system->getMixer());
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/sfx/softseq/amiga.cpp b/engines/sci/sfx/softseq/amiga.cpp
deleted file mode 100644
index d16e82fab5..0000000000
--- a/engines/sci/sfx/softseq/amiga.cpp
+++ /dev/null
@@ -1,676 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sound/softsynth/emumidi.h"
-#include "sci/sfx/softseq/mididriver.h"
-
-#include "common/file.h"
-#include "common/frac.h"
-#include "common/util.h"
-
-namespace Sci {
-
-/* #define DEBUG */
-
-// Frequencies for every note
-// FIXME Store only one octave
-static const int freq_table[] = {
- 58, 62, 65, 69, 73, 78, 82, 87,
- 92, 98, 104, 110, 117, 124, 131, 139,
- 147, 156, 165, 175, 185, 196, 208, 220,
- 234, 248, 262, 278, 294, 312, 331, 350,
- 371, 393, 417, 441, 468, 496, 525, 556,
- 589, 625, 662, 701, 743, 787, 834, 883,
- 936, 992, 1051, 1113, 1179, 1250, 1324, 1403,
- 1486, 1574, 1668, 1767, 1872, 1984, 2102, 2227,
- 2359, 2500, 2648, 2806, 2973, 3149, 3337, 3535,
- 3745, 3968, 4204, 4454, 4719, 5000, 5297, 5612,
- 5946, 6299, 6674, 7071, 7491, 7937, 8408, 8908,
- 9438, 10000, 10594, 11224, 11892, 12599, 13348, 14142,
- 14983, 15874, 16817, 17817, 18877, 20000, 21189, 22449,
- 23784, 25198, 26696, 28284, 29966, 31748, 33635, 35635,
- 37754, 40000, 42378, 44898, 47568, 50396, 53393, 56568,
- 59932, 63496, 67271, 71271, 75509, 80000, 84757, 89796
-};
-
-class MidiDriver_Amiga : public MidiDriver_Emulated {
-public:
- enum {
- kVoices = 4
- };
-
- MidiDriver_Amiga(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { }
- virtual ~MidiDriver_Amiga() { }
-
- // MidiDriver
- int open();
- void close();
- void send(uint32 b);
- MidiChannel *allocateChannel() { return NULL; }
- MidiChannel *getPercussionChannel() { return NULL; }
-
- // AudioStream
- bool isStereo() const { return true; }
- int getRate() const { return _mixer->getOutputRate(); }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
-
- void setVolume(byte volume);
- void playSwitch(bool play);
- virtual uint32 property(int prop, uint32 param);
-
-private:
- enum {
- kModeLoop = 1 << 0, // Instrument looping flag
- kModePitch = 1 << 1 // Instrument pitch changes flag
- };
-
- enum {
- kChannels = 10,
- kBaseFreq = 20000, // Samplerate of the instrument bank
- kPanLeft = 91,
- kPanRight = 164
- };
-
- struct Channel {
- int instrument;
- int volume;
- int pan;
- };
-
- struct Envelope {
- int length; // Phase period length in samples
- int delta; // Velocity delta per period
- int target; // Target velocity
- };
-
- struct Voice {
- int instrument;
- int note;
- int note_velocity;
- int velocity;
- int envelope;
- int envelope_samples; // Number of samples till next envelope event
- int decay;
- int looping;
- int hw_channel;
- frac_t offset;
- frac_t rate;
- };
-
- struct Instrument {
- char name[30];
- int mode;
- int size; // Size of non-looping part in bytes
- int loop_size; // Starting offset and size of loop in bytes
- int transpose; // Transpose value in semitones
- Envelope envelope[4]; // Envelope
- int8 *samples;
- int8 *loop;
- };
-
- struct Bank {
- char name[30];
- uint size;
- Instrument *instruments[256];
- };
-
- bool _playSwitch;
- int _masterVolume;
- int _frequency;
- Envelope _envDecay;
- Bank _bank; // Instrument bank
-
- Channel _channels[MIDI_CHANNELS];
- /* Internal channels */
- Voice _voices[kChannels];
-
- void setEnvelope(Voice *channel, Envelope *envelope, int phase);
- int interpolate(int8 *samples, frac_t offset);
- void playInstrument(int16 *dest, Voice *channel, int count);
- void changeInstrument(int channel, int instrument);
- void stopChannel(int ch);
- void stopNote(int ch, int note);
- void startNote(int ch, int note, int velocity);
- Instrument *readInstrument(Common::File &file, int *id);
-};
-
-void MidiDriver_Amiga::setEnvelope(Voice *channel, Envelope *envelope, int phase) {
- channel->envelope = phase;
- channel->envelope_samples = envelope[phase].length;
-
- if (phase == 0)
- channel->velocity = channel->note_velocity / 2;
- else
- channel->velocity = envelope[phase - 1].target;
-}
-
-int MidiDriver_Amiga::interpolate(int8 *samples, frac_t offset) {
- int x = fracToInt(offset);
- int diff = (samples[x + 1] - samples[x]) << 8;
-
- return (samples[x] << 8) + fracToInt(diff * (offset & FRAC_LO_MASK));
-}
-
-void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) {
- int index = 0;
- int vol = _channels[channel->hw_channel].volume;
- Instrument *instrument = _bank.instruments[channel->instrument];
-
- while (1) {
- /* Available source samples until end of segment */
- frac_t lin_avail;
- int seg_end, rem, i, amount;
- int8 *samples;
-
- if (channel->looping) {
- samples = instrument->loop;
- seg_end = instrument->loop_size;
- } else {
- samples = instrument->samples;
- seg_end = instrument->size;
- }
-
- lin_avail = intToFrac(seg_end) - channel->offset;
-
- rem = count - index;
-
- /* Amount of destination samples that we will compute this iteration */
- amount = lin_avail / channel->rate;
-
- if (lin_avail % channel->rate)
- amount++;
-
- if (amount > rem)
- amount = rem;
-
- /* Stop at next envelope event */
- if ((channel->envelope_samples != -1) && (amount > channel->envelope_samples))
- amount = channel->envelope_samples;
-
- for (i = 0; i < amount; i++) {
- dest[index++] = interpolate(samples, channel->offset) * channel->velocity / 64 * channel->note_velocity * vol / (127 * 127);
- channel->offset += channel->rate;
- }
-
- if (channel->envelope_samples != -1)
- channel->envelope_samples -= amount;
-
- if (channel->envelope_samples == 0) {
- Envelope *envelope;
- int delta, target, velocity;
-
- if (channel->decay)
- envelope = &_envDecay;
- else
- envelope = &instrument->envelope[channel->envelope];
-
- delta = envelope->delta;
- target = envelope->target;
- velocity = channel->velocity - envelope->delta;
-
- /* Check whether we have reached the velocity target for the current phase */
- if ((delta >= 0 && velocity <= target) || (delta < 0 && velocity >= target)) {
- channel->velocity = target;
-
- /* Stop note after velocity has dropped to 0 */
- if (target == 0) {
- channel->note = -1;
- break;
- } else
- switch (channel->envelope) {
- case 0:
- case 2:
- /* Go to next phase */
- setEnvelope(channel, instrument->envelope, channel->envelope + 1);
- break;
- case 1:
- case 3:
- /* Stop envelope */
- channel->envelope_samples = -1;
- break;
- }
- } else {
- /* We haven't reached the target yet */
- channel->envelope_samples = envelope->length;
- channel->velocity = velocity;
- }
- }
-
- if (index == count)
- break;
-
- if (fracToInt(channel->offset) >= seg_end) {
- if (instrument->mode & kModeLoop) {
- /* Loop the samples */
- channel->offset -= intToFrac(seg_end);
- channel->looping = 1;
- } else {
- /* All samples have been played */
- channel->note = -1;
- break;
- }
- }
- }
-}
-
-void MidiDriver_Amiga::changeInstrument(int channel, int instrument) {
-#ifdef DEBUG
- if (_bank.instruments[instrument])
- printf("[sfx:seq:amiga] Setting channel %i to \"%s\" (%i)\n", channel, _bank.instruments[instrument]->name, instrument);
- else
- warning("[sfx:seq:amiga] instrument %i does not exist (channel %i)", instrument, channel);
-#endif
- _channels[channel].instrument = instrument;
-}
-
-void MidiDriver_Amiga::stopChannel(int ch) {
- int i;
-
- /* Start decay phase for note on this hw channel, if any */
- for (i = 0; i < kChannels; i++)
- if (_voices[i].note != -1 && _voices[i].hw_channel == ch && !_voices[i].decay) {
- /* Trigger fast decay envelope */
- _voices[i].decay = 1;
- _voices[i].envelope_samples = _envDecay.length;
- break;
- }
-}
-
-void MidiDriver_Amiga::stopNote(int ch, int note) {
- int channel;
- Instrument *instrument;
-
- for (channel = 0; channel < kChannels; channel++)
- if (_voices[channel].note == note && _voices[channel].hw_channel == ch && !_voices[channel].decay)
- break;
-
- if (channel == kChannels) {
-#ifdef DEBUG
- warning("[sfx:seq:amiga] cannot stop note %i on channel %i", note, ch);
-#endif
- return;
- }
-
- instrument = _bank.instruments[_voices[channel].instrument];
-
- /* Start the envelope phases for note-off if looping is on and envelope is enabled */
- if ((instrument->mode & kModeLoop) && (instrument->envelope[0].length != 0))
- setEnvelope(&_voices[channel], instrument->envelope, 2);
-}
-
-void MidiDriver_Amiga::startNote(int ch, int note, int velocity) {
- Instrument *instrument;
- int channel;
-
- if (_channels[ch].instrument < 0 || _channels[ch].instrument > 255) {
- warning("[sfx:seq:amiga] invalid instrument %i on channel %i", _channels[ch].instrument, ch);
- return;
- }
-
- instrument = _bank.instruments[_channels[ch].instrument];
-
- if (!instrument) {
- warning("[sfx:seq:amiga] instrument %i does not exist", _channels[ch].instrument);
- return;
- }
-
- for (channel = 0; channel < kChannels; channel++)
- if (_voices[channel].note == -1)
- break;
-
- if (channel == kChannels) {
- warning("[sfx:seq:amiga] could not find a free channel");
- return;
- }
-
- stopChannel(ch);
-
- if (instrument->mode & kModePitch) {
- int fnote = note + instrument->transpose;
-
- if (fnote < 0 || fnote > 127) {
- warning("[sfx:seq:amiga] illegal note %i\n", fnote);
- return;
- }
-
- /* Compute rate for note */
- _voices[channel].rate = doubleToFrac(freq_table[fnote] / (double) _frequency);
- } else
- _voices[channel].rate = doubleToFrac(kBaseFreq / (double) _frequency);
-
- _voices[channel].instrument = _channels[ch].instrument;
- _voices[channel].note = note;
- _voices[channel].note_velocity = velocity;
-
- if ((instrument->mode & kModeLoop) && (instrument->envelope[0].length != 0))
- setEnvelope(&_voices[channel], instrument->envelope, 0);
- else {
- _voices[channel].velocity = 64;
- _voices[channel].envelope_samples = -1;
- }
-
- _voices[channel].offset = 0;
- _voices[channel].hw_channel = ch;
- _voices[channel].decay = 0;
- _voices[channel].looping = 0;
-}
-
-MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &file, int *id) {
- Instrument *instrument;
- byte header[61];
- int size;
- int seg_size[3];
- int loop_offset;
- int i;
-
- if (file.read(header, 61) < 61) {
- warning("[sfx:seq:amiga] failed to read instrument header");
- return NULL;
- }
-
- instrument = new Instrument;
-
- seg_size[0] = READ_BE_UINT16(header + 35) * 2;
- seg_size[1] = READ_BE_UINT16(header + 41) * 2;
- seg_size[2] = READ_BE_UINT16(header + 47) * 2;
-
- instrument->mode = header[33];
- instrument->transpose = (int8) header[34];
- for (i = 0; i < 4; i++) {
- int length = (int8) header[49 + i];
-
- if (length == 0 && i > 0)
- length = 256;
-
- instrument->envelope[i].length = length * _frequency / 60;
- instrument->envelope[i].delta = (int8)header[53 + i];
- instrument->envelope[i].target = header[57 + i];
- }
- /* Final target must be 0 */
- instrument->envelope[3].target = 0;
-
- loop_offset = READ_BE_UINT32(header + 37) & ~1;
- size = seg_size[0] + seg_size[1] + seg_size[2];
-
- *id = READ_BE_UINT16(header);
-
- strncpy(instrument->name, (char *) header + 2, 29);
- instrument->name[29] = 0;
-#ifdef DEBUG
- printf("[sfx:seq:amiga] Reading instrument %i: \"%s\" (%i bytes)\n",
- *id, instrument->name, size);
- printf(" Mode: %02x\n", instrument->mode);
- printf(" Looping: %s\n", instrument->mode & kModeLoop ? "on" : "off");
- printf(" Pitch changes: %s\n", instrument->mode & kModePitch ? "on" : "off");
- printf(" Segment sizes: %i %i %i\n", seg_size[0], seg_size[1], seg_size[2]);
- printf(" Segment offsets: 0 %i %i\n", loop_offset, read_int32(header + 43));
-#endif
- instrument->samples = (int8 *) malloc(size + 1);
- if (file.read(instrument->samples, size) < (unsigned int)size) {
- warning("[sfx:seq:amiga] failed to read instrument samples");
- free(instrument->samples);
- delete instrument;
- return NULL;
- }
-
- if (instrument->mode & kModeLoop) {
- if (loop_offset + seg_size[1] > size) {
-#ifdef DEBUG
- warning("[sfx:seq:amiga] looping samples extend %i bytes past end of sample block",
- loop_offset + seg_size[1] - size);
-#endif
- seg_size[1] = size - loop_offset;
- }
-
- if (seg_size[1] < 0) {
- warning("[sfx:seq:amiga] invalid looping point");
- free(instrument->samples);
- delete instrument;
- return NULL;
- }
-
- instrument->size = seg_size[0];
- instrument->loop_size = seg_size[1];
-
- instrument->loop = (int8*)malloc(instrument->loop_size + 1);
- memcpy(instrument->loop, instrument->samples + loop_offset, instrument->loop_size);
-
- instrument->samples[instrument->size] = instrument->loop[0];
- instrument->loop[instrument->loop_size] = instrument->loop[0];
- } else {
- instrument->loop = NULL;
- instrument->size = size;
- instrument->samples[instrument->size] = 0;
- }
-
- return instrument;
-}
-
-uint32 MidiDriver_Amiga::property(int prop, uint32 param) {
- switch(prop) {
- case MIDI_PROP_MASTER_VOLUME:
- if (param != 0xffff)
- _masterVolume = param;
- return _masterVolume;
- default:
- break;
- }
- return 0;
-}
-
-int MidiDriver_Amiga::open() {
- _frequency = _mixer->getOutputRate();
- _envDecay.length = _frequency / (32 * 64);
- _envDecay.delta = 1;
- _envDecay.target = 0;
-
- Common::File file;
- byte header[40];
-
- if (!file.open("bank.001")) {
- warning("[sfx:seq:amiga] file bank.001 not found");
- return Common::kUnknownError;
- }
-
- if (file.read(header, 40) < 40) {
- warning("[sfx:seq:amiga] failed to read header of file bank.001");
- return Common::kUnknownError;
- }
-
- for (uint i = 0; i < 256; i++)
- _bank.instruments[i] = NULL;
-
- for (uint i = 0; i < kChannels; i++) {
- _voices[i].note = -1;
- _voices[i].hw_channel = 0;
- }
-
- for (uint i = 0; i < MIDI_CHANNELS; i++) {
- _channels[i].instrument = -1;
- _channels[i].volume = 127;
- _channels[i].pan = (i % 4 == 0 || i % 4 == 3 ? kPanLeft : kPanRight);
- }
-
- _bank.size = READ_BE_UINT16(header + 38);
- strncpy(_bank.name, (char *) header + 8, 29);
- _bank.name[29] = 0;
-#ifdef DEBUG
- printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name);
-#endif
-
- for (uint i = 0; i < _bank.size; i++) {
- int id;
- Instrument *instrument = readInstrument(file, &id);
-
- if (!instrument) {
- warning("[sfx:seq:amiga] failed to read bank.001");
- return Common::kUnknownError;
- }
-
- if (id < 0 || id > 255) {
- warning("[sfx:seq:amiga] Error: instrument ID out of bounds");
- return Common::kUnknownError;
- }
-
- _bank.instruments[id] = instrument;
- }
-
- MidiDriver_Emulated::open();
-
- _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, false);
-
- return Common::kNoError;
-}
-
-void MidiDriver_Amiga::close() {
- _mixer->stopHandle(_mixerSoundHandle);
-
- for (uint i = 0; i < _bank.size; i++) {
- if (_bank.instruments[i]) {
- if (_bank.instruments[i]->loop)
- free(_bank.instruments[i]->loop);
- free(_bank.instruments[i]->samples);
- delete _bank.instruments[i];
- }
- }
-}
-
-void MidiDriver_Amiga::playSwitch(bool play) {
- _playSwitch = play;
-}
-
-void MidiDriver_Amiga::setVolume(byte volume_) {
- _masterVolume = volume_;
-}
-
-void MidiDriver_Amiga::send(uint32 b) {
- byte command = b & 0xf0;
- byte channel = b & 0xf;
- byte op1 = (b >> 8) & 0xff;
- byte op2 = (b >> 16) & 0xff;
-
- switch (command) {
- case 0x80:
- stopNote(channel, op1);
- break;
- case 0x90:
- if (op2 > 0)
- startNote(channel, op1, op2);
- else
- stopNote(channel, op1);
- break;
- case 0xb0:
- switch (op1) {
- case 0x07:
- _channels[channel].volume = op2;
- break;
- case 0x0a:
-#ifdef DEBUG
- warning("[sfx:seq:amiga] ignoring pan 0x%02x event for channel %i", op2, channel);
-#endif
- break;
- case 0x7b:
- stopChannel(channel);
- break;
- default:
- warning("[sfx:seq:amiga] unknown control event 0x%02x", op1);
- }
- break;
- case 0xc0:
- changeInstrument(channel, op1);
- break;
- default:
- warning("[sfx:seq:amiga] unknown event %02x", command);
- }
-}
-
-void MidiDriver_Amiga::generateSamples(int16 *data, int len) {
- if (len == 0)
- return;
-
- int16 *buffers = (int16*)malloc(len * 2 * kChannels);
-
- memset(buffers, 0, len * 2 * kChannels);
-
- /* Generate samples for all notes */
- for (int i = 0; i < kChannels; i++)
- if (_voices[i].note >= 0)
- playInstrument(buffers + i * len, &_voices[i], len);
-
- if (isStereo()) {
- for (int j = 0; j < len; j++) {
- int mixedl = 0, mixedr = 0;
-
- /* Mix and pan */
- for (int i = 0; i < kChannels; i++) {
- mixedl += buffers[i * len + j] * (256 - _channels[_voices[i].hw_channel].pan);
- mixedr += buffers[i * len + j] * _channels[_voices[i].hw_channel].pan;
- }
-
- /* Adjust volume */
- data[2 * j] = mixedl * _masterVolume >> 13;
- data[2 * j + 1] = mixedr * _masterVolume >> 13;
- }
- } else {
- for (int j = 0; j < len; j++) {
- int mixed = 0;
-
- /* Mix */
- for (int i = 0; i < kChannels; i++)
- mixed += buffers[i * len + j];
-
- /* Adjust volume */
- data[j] = mixed * _masterVolume >> 6;
- }
- }
-
- free(buffers);
-}
-
-class MidiPlayer_Amiga : public MidiPlayer {
-public:
- MidiPlayer_Amiga() { _driver = new MidiDriver_Amiga(g_system->getMixer()); }
- int getPlayMask(SciVersion soundVersion);
- int getPolyphony() const { return MidiDriver_Amiga::kVoices; }
- bool hasRhythmChannel() const { return false; }
- void setVolume(byte volume) { static_cast<MidiDriver_Amiga *>(_driver)->setVolume(volume); }
- void playSwitch(bool play) { static_cast<MidiDriver_Amiga *>(_driver)->playSwitch(play); }
- void loadInstrument(int idx, byte *data);
-};
-
-MidiPlayer *MidiPlayer_Amiga_create() {
- return new MidiPlayer_Amiga();
-}
-
-int MidiPlayer_Amiga::getPlayMask(SciVersion soundVersion) {
- if (soundVersion == SCI_VERSION_0_EARLY)
- error("No amiga support for sci0early");
-
- return 0x40;
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/sfx/softseq/mididriver.h b/engines/sci/sfx/softseq/mididriver.h
deleted file mode 100644
index df0532d732..0000000000
--- a/engines/sci/sfx/softseq/mididriver.h
+++ /dev/null
@@ -1,110 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef SCI_SFX_SOFTSEQ_MIDIDRIVER_H
-#define SCI_SFX_SOFTSEQ_MIDIDRIVER_H
-
-#include "sci/sci.h"
-#include "sound/mididrv.h"
-#include "sound/softsynth/emumidi.h"
-#include "common/error.h"
-
-namespace Sci {
-
-class ResourceManager;
-
-enum {
- MIDI_CHANNELS = 16,
- MIDI_PROP_MASTER_VOLUME = 0
-};
-
-
-#define MIDI_RHYTHM_CHANNEL 9
-
-/* Special SCI sound stuff */
-
-#define SCI_MIDI_TIME_EXPANSION_PREFIX 0xF8
-#define SCI_MIDI_TIME_EXPANSION_LENGTH 240
-
-#define SCI_MIDI_EOT 0xFC
-#define SCI_MIDI_SET_SIGNAL 0xCF
-#define SCI_MIDI_SET_POLYPHONY 0x4B
-#define SCI_MIDI_RESET_ON_SUSPEND 0x4C
-#define SCI_MIDI_CHANNEL_MUTE 0x4E
-#define SCI_MIDI_SET_REVERB 0x50
-#define SCI_MIDI_HOLD 0x52
-#define SCI_MIDI_CUMULATIVE_CUE 0x60
-#define SCI_MIDI_CHANNEL_SOUND_OFF 0x78 /* all-sound-off for Bn */
-#define SCI_MIDI_CHANNEL_NOTES_OFF 0x7B /* all-notes-off for Bn */
-
-#define SCI_MIDI_SET_SIGNAL_LOOP 0x7F
-/* If this is the parameter of 0xCF, the loop point is set here */
-
-#define SCI_MIDI_CONTROLLER(status) ((status & 0xF0) == 0xB0)
-
-class MidiPlayer : public MidiDriver {
-protected:
- MidiDriver *_driver;
-public:
- int open() {
- ResourceManager *resMan = ((SciEngine *)g_engine)->getResourceManager(); // HACK
- return open(resMan);
- }
- virtual int open(ResourceManager *resMan) { return _driver->open(); }
- virtual void close() { _driver->close(); }
- virtual void send(uint32 b) { _driver->send(b); }
- uint32 getBaseTempo() { return _driver->getBaseTempo(); }
- virtual bool hasRhythmChannel() const = 0;
- MidiChannel *allocateChannel() { return _driver->allocateChannel(); }
- MidiChannel *getPercussionChannel() { return _driver->getPercussionChannel(); }
- void setTimerCallback(void *timer_param, Common::TimerManager::TimerProc timer_proc) { _driver->setTimerCallback(timer_param, timer_proc); }
-
- virtual int getPlayMask(SciVersion soundVersion) = 0;
- virtual int getPolyphony() const = 0;
-
- virtual void setVolume(byte volume) {
- if(_driver)
- _driver->property(MIDI_PROP_MASTER_VOLUME, volume);
- }
-
- virtual int getVolume() {
- return _driver ? _driver->property(MIDI_PROP_MASTER_VOLUME, 0xffff) : 0;
- }
-
- virtual void playSwitch(bool play) {
- if (!play) {
- // Send "All Sound Off" on all channels
- for (int i = 0; i < MIDI_CHANNELS; ++i)
- _driver->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0);
- }
- }
-};
-
-extern MidiPlayer *MidiPlayer_Adlib_create();
-extern MidiPlayer *MidiPlayer_Amiga_create();
-
-} // End of namespace Sci
-
-#endif // SCI_SFX_SOFTSEQ_MIDIDRIVER_H
diff --git a/engines/sci/sfx/softseq/pcjr.cpp b/engines/sci/sfx/softseq/pcjr.cpp
deleted file mode 100644
index a80a188751..0000000000
--- a/engines/sci/sfx/softseq/pcjr.cpp
+++ /dev/null
@@ -1,209 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sci/sfx/softseq/mididriver.h"
-#include "sci/sfx/softseq/pcjr.h"
-
-namespace Sci {
-
-#define FREQUENCY 44100
-#define VOLUME_SHIFT 3
-
-#define BASE_NOTE 129 // A10
-#define BASE_OCTAVE 10 // A10, as I said
-
-const static int freq_table[12] = { // A4 is 440Hz, halftone map is x |-> ** 2^(x/12)
- 28160, // A10
- 29834,
- 31608,
- 33488,
- 35479,
- 37589,
- 39824,
- 42192,
- 44701,
- 47359,
- 50175,
- 53159
-};
-
-static inline int get_freq(int note) {
- int halftone_delta = note - BASE_NOTE;
- int oct_diff = ((halftone_delta + BASE_OCTAVE * 12) / 12) - BASE_OCTAVE;
- int halftone_index = (halftone_delta + (12 * 100)) % 12 ;
- int freq = (!note) ? 0 : freq_table[halftone_index] / (1 << (-oct_diff));
-
- return freq;
-}
-
-void MidiDriver_PCJr::send(uint32 b) {
- byte command = b & 0xff;
- byte op1 = (b >> 8) & 0xff;
- byte op2 = (b >> 16) & 0xff;
- int i;
- int mapped_chan = -1;
- int chan_nr = command & 0xf;
-
- // First, test for channel having been assigned already
- if (_channels_assigned & (1 << chan_nr)) {
- // Already assigned this channel number:
- for (i = 0; i < _channels_nr; i++)
- if (_chan_nrs[i] == chan_nr) {
- mapped_chan = i;
- break;
- }
- } else if ((command & 0xe0) == 0x80) {
- // Assign new channel round-robin
-
- // Mark channel as unused:
- if (_chan_nrs[_channel_assigner] >= 0)
- _channels_assigned &= ~(1 << _chan_nrs[_channel_assigner]);
-
- // Remember channel:
- _chan_nrs[_channel_assigner] = chan_nr;
- // Mark channel as used
- _channels_assigned |= (1 << _chan_nrs[_channel_assigner]);
-
- // Save channel for use later in this call:
- mapped_chan = _channel_assigner;
- // Round-ropin iterate channel assigner:
- _channel_assigner = (_channel_assigner + 1) % _channels_nr;
- }
-
- if (mapped_chan == -1)
- return;
-
- switch (command & 0xf0) {
-
- case 0x80:
- if (op1 == _notes[mapped_chan])
- _notes[mapped_chan] = 0;
- break;
-
- case 0x90:
- if (!op2) {
- if (op1 == _notes[mapped_chan])
- _notes[mapped_chan] = 0;
- } else {
- _notes[mapped_chan] = op1;
- _volumes[mapped_chan] = op2;
- }
- break;
-
- case 0xb0:
- if ((op1 == SCI_MIDI_CHANNEL_NOTES_OFF) || (op1 == SCI_MIDI_CHANNEL_SOUND_OFF))
- _notes[mapped_chan] = 0;
- break;
-
- default:
- debug(2, "Unused MIDI command %02x %02x %02x", command, op1, op2);
- break; /* ignore */
- }
-}
-
-void MidiDriver_PCJr::generateSamples(int16 *data, int len) {
- int i;
- int chan;
- int freq[kMaxChannels];
-
- for (chan = 0; chan < _channels_nr; chan++)
- freq[chan] = get_freq(_notes[chan]);
-
- for (i = 0; i < len; i++) {
- int16 result = 0;
-
- for (chan = 0; chan < _channels_nr; chan++)
- if (_notes[chan]) {
- int volume = (_global_volume * _volumes[chan])
- >> VOLUME_SHIFT;
-
- _freq_count[chan] += freq[chan];
- while (_freq_count[chan] >= (FREQUENCY << 1))
- _freq_count[chan] -= (FREQUENCY << 1);
-
- if (_freq_count[chan] - freq[chan] < 0) {
- /* Unclean rising edge */
- int l = volume << 1;
- result += -volume + (l * _freq_count[chan]) / freq[chan];
- } else if (_freq_count[chan] >= FREQUENCY
- && _freq_count[chan] - freq[chan] < FREQUENCY) {
- /* Unclean falling edge */
- int l = volume << 1;
- result += volume - (l * (_freq_count[chan] - FREQUENCY)) / freq[chan];
- } else {
- if (_freq_count[chan] < FREQUENCY)
- result += volume;
- else
- result += -volume;
- }
- }
- data[i] = result;
- }
-}
-
-int MidiDriver_PCJr::open(int channels) {
- if (_isOpen)
- return MERR_ALREADY_OPEN;
-
- if (channels > kMaxChannels)
- return -1;
-
- _channels_nr = channels;
- _global_volume = 100;
- for (int i = 0; i < _channels_nr; i++) {
- _volumes[i] = 100;
- _notes[i] = 0;
- _freq_count[i] = 0;
- _chan_nrs[i] = -1;
- }
- _channel_assigner = 0;
- _channels_assigned = 0;
-
- MidiDriver_Emulated::open();
-
- _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1);
-
- return 0;
-}
-
-void MidiDriver_PCJr::close() {
- _mixer->stopHandle(_mixerSoundHandle);
-}
-
-int MidiPlayer_PCJr::getPlayMask(SciVersion soundVersion) {
- if (soundVersion == SCI_VERSION_0_EARLY)
- return 0x10; // FIXME: Not correct
-
- return 0x10;
-}
-
-int MidiPlayer_PCSpeaker::getPlayMask(SciVersion soundVersion) {
- if (soundVersion == SCI_VERSION_0_EARLY)
- return 0x02;
-
- return 0x20;
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/sfx/softseq/pcjr.h b/engines/sci/sfx/softseq/pcjr.h
deleted file mode 100644
index 60032817fd..0000000000
--- a/engines/sci/sfx/softseq/pcjr.h
+++ /dev/null
@@ -1,84 +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 2
- * 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#include "sci/sfx/softseq/mididriver.h"
-
-namespace Sci {
-
-class MidiDriver_PCJr : public MidiDriver_Emulated {
-public:
- friend class MidiPlayer_PCJr;
-
- enum {
- kMaxChannels = 3
- };
-
- MidiDriver_PCJr(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) { }
- ~MidiDriver_PCJr() { }
-
- // MidiDriver
- int open() { return open(kMaxChannels); }
- void close();
- void send(uint32 b);
- MidiChannel *allocateChannel() { return NULL; }
- MidiChannel *getPercussionChannel() { return NULL; }
-
- // AudioStream
- bool isStereo() const { return false; }
- int getRate() const { return _mixer->getOutputRate(); }
-
- // MidiDriver_Emulated
- void generateSamples(int16 *buf, int len);
-
- int open(int channels);
-private:
- int _channels_nr;
- int _global_volume; // Base volume
- int _volumes[kMaxChannels];
- int _notes[kMaxChannels]; // Current halftone, or 0 if off
- int _freq_count[kMaxChannels];
- int _channel_assigner;
- int _channels_assigned;
- int _chan_nrs[kMaxChannels];
-};
-
-class MidiPlayer_PCJr : public MidiPlayer {
-public:
- MidiPlayer_PCJr() { _driver = new MidiDriver_PCJr(g_system->getMixer()); }
- int open(ResourceManager *resMan) { return static_cast<MidiDriver_PCJr *>(_driver)->open(getPolyphony()); }
- int getPlayMask(SciVersion soundVersion);
- int getPolyphony() const { return 3; }
- bool hasRhythmChannel() const { return false; }
- void setVolume(byte volume) { static_cast<MidiDriver_PCJr *>(_driver)->_global_volume = volume; }
-};
-
-class MidiPlayer_PCSpeaker : public MidiPlayer_PCJr {
-public:
- int getPlayMask(SciVersion soundVersion);
- int getPolyphony() const { return 1; }
-};
-
-} // End of namespace Sci
-