aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/softseq/adlib.h
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/sfx/softseq/adlib.h')
-rw-r--r--engines/sci/sfx/softseq/adlib.h153
1 files changed, 153 insertions, 0 deletions
diff --git a/engines/sci/sfx/softseq/adlib.h b/engines/sci/sfx/softseq/adlib.h
new file mode 100644
index 0000000000..836a92ef07
--- /dev/null
+++ b/engines/sci/sfx/softseq/adlib.h
@@ -0,0 +1,153 @@
+/* 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/sci_midi.h"
+#include "sound/fmopl.h"
+
+namespace Sci {
+
+class MidiDriver_Adlib : public MidiDriver_Emulated {
+public:
+ enum {
+ kVoices = 9
+ };
+
+ 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
+
+ Channel() : patch(0), volume(63), pan(64), holdPedal(0), extraVoices(0), pitchWheel(8192), lastVoice(0) { }
+ };
+
+ struct AdlibVoice {
+ int8 channel; // MIDI channel that this voice is assigned to or -1
+ int8 note; // Currently playing MIDI note or -1
+ int8 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) { }
+ };
+
+ MidiDriver_Adlib(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer), _playSwitch(true), _masterVolume(15) { }
+ ~MidiDriver_Adlib() { }
+
+ // MidiDriver
+ int open();
+ 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);
+
+private:
+ bool _stereo;
+ FM_OPL *_fmopl[2];
+ bool _playSwitch;
+ int _masterVolume;
+ Channel _channels[MIDI_CHANNELS];
+ AdlibVoice _voices[kVoices];
+ Common::Array<AdlibPatch> _patches;
+
+ void sysEx(const byte *msg, uint16 length);
+ AdlibPatch *loadPatch(byte *data);
+ 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, int velocity);
+ 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 pan, AdlibOperator &op);
+};
+
+class MidiPlayer_Adlib : public MidiPlayer {
+public:
+ MidiPlayer_Adlib() { _driver = new MidiDriver_Adlib(g_system->getMixer()); }
+ int open(ResourceManager *resmgr);
+ int getPlayMask() const { return 0x04; }
+ 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);
+};
+
+} // End of namespace Sci
+