aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/softseq/adlib.cpp
diff options
context:
space:
mode:
authorWalter van Niftrik2009-11-05 01:35:43 +0000
committerWalter van Niftrik2009-11-05 01:35:43 +0000
commit20a3c484d546a782999586300482c6985812a291 (patch)
tree004f99c54178c693a9d690664d5e6c6a505ea57e /engines/sci/sfx/softseq/adlib.cpp
parentc720c4b24d15ad790ae81b3621d2790f02c134cb (diff)
downloadscummvm-rg350-20a3c484d546a782999586300482c6985812a291.tar.gz
scummvm-rg350-20a3c484d546a782999586300482c6985812a291.tar.bz2
scummvm-rg350-20a3c484d546a782999586300482c6985812a291.zip
SCI: Converted FreeSCI Amiga sound driver. Some cleanup.
svn-id: r45682
Diffstat (limited to 'engines/sci/sfx/softseq/adlib.cpp')
-rw-r--r--engines/sci/sfx/softseq/adlib.cpp135
1 files changed, 134 insertions, 1 deletions
diff --git a/engines/sci/sfx/softseq/adlib.cpp b/engines/sci/sfx/softseq/adlib.cpp
index e21ddf11f9..a361d33104 100644
--- a/engines/sci/sfx/softseq/adlib.cpp
+++ b/engines/sci/sfx/softseq/adlib.cpp
@@ -27,9 +27,10 @@
#include "sci/sfx/iterator.h"
#include "sound/fmopl.h"
+#include "sound/softsynth/emumidi.h"
#include "sci/resource.h"
-#include "sci/sfx/softseq/adlib.h"
+#include "sci/sfx/sci_midi.h"
namespace Sci {
@@ -42,6 +43,134 @@ namespace Sci {
// 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() 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);
+};
+
static const byte registerOffset[MidiDriver_Adlib::kVoices] = {
0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12
};
@@ -679,4 +808,8 @@ int MidiPlayer_Adlib::open(ResourceManager *resMan) {
return static_cast<MidiDriver_Adlib *>(_driver)->open(getSciVersion() <= SCI_VERSION_0_LATE);
}
+MidiPlayer *MidiPlayer_Adlib_create() {
+ return new MidiPlayer_Adlib();
+}
+
} // End of namespace Sci