diff options
Diffstat (limited to 'engines/sci/sfx/softseq/amiga.cpp')
-rw-r--r-- | engines/sci/sfx/softseq/amiga.cpp | 525 |
1 files changed, 283 insertions, 242 deletions
diff --git a/engines/sci/sfx/softseq/amiga.cpp b/engines/sci/sfx/softseq/amiga.cpp index 388e5685fd..1910e3b420 100644 --- a/engines/sci/sfx/softseq/amiga.cpp +++ b/engines/sci/sfx/softseq/amiga.cpp @@ -25,93 +25,19 @@ #include "sci/sfx/softseq.h" +#include "sound/softsynth/emumidi.h" +#include "sci/sfx/sci_midi.h" + #include "common/file.h" #include "common/frac.h" #include "common/util.h" namespace Sci { -#define FREQUENCY 44100 -#define CHANNELS_NR 10 -#define HW_CHANNELS_NR 16 - -/* Samplerate of the instrument bank */ -#define BASE_FREQ 20000 - -/* Instrument looping flag */ -#define MODE_LOOP 1 << 0 -/* Instrument pitch changes flag */ -#define MODE_PITCH 1 << 1 - -#define PAN_LEFT 91 -#define PAN_RIGHT 164 - /* #define DEBUG */ -struct envelope_t { - /* Phase period length in samples */ - int length; - /* Velocity delta per period */ - int delta; - /* Target velocity */ - int target; -}; - -/* Fast decay envelope */ -static envelope_t env_decay = {FREQUENCY / (32 * 64), 1, 0}; - -struct instrument_t { - char name[30]; - int mode; - /* Size of non-looping part in bytes */ - int size; - /* Starting offset and size of loop in bytes */ - int loop_size; - /* Transpose value in semitones */ - int transpose; - /* Envelope */ - envelope_t envelope[4]; - int8 *samples; - int8 *loop; -}; - -struct bank_t { - char name[30]; - int size; - instrument_t *instruments[256]; -}; - -struct channel_t { - int instrument; - int note; - int note_velocity; - int velocity; - int envelope; - /* Number of samples till next envelope event */ - int envelope_samples; - int decay; - int looping; - int hw_channel; - frac_t offset; - frac_t rate; -}; - -struct hw_channel_t { - int instrument; - int volume; - int pan; -}; - -/* Instrument bank */ -static bank_t bank; -/* Internal channels */ -static channel_t channels[CHANNELS_NR]; -/* External channels */ -static hw_channel_t hw_channels[HW_CHANNELS_NR]; -/* Overall volume */ -static int volume = 127; - -/* Frequencies for every note */ +// 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, @@ -131,7 +57,110 @@ static const int freq_table[] = { 59932, 63496, 67271, 71271, 75509, 80000, 84757, 89796 }; -static void set_envelope(channel_t *channel, envelope_t *envelope, int phase) { +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; @@ -141,17 +170,17 @@ static void set_envelope(channel_t *channel, envelope_t *envelope, int phase) { channel->velocity = envelope[phase - 1].target; } -static inline int interpolate(int8 *samples, frac_t offset) { +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)); } -static void play_instrument(int16 *dest, channel_t *channel, int count) { +void MidiDriver_Amiga::playInstrument(int16 *dest, Voice *channel, int count) { int index = 0; - int vol = hw_channels[channel->hw_channel].volume; - instrument_t *instrument = bank.instruments[channel->instrument]; + int vol = _channels[channel->hw_channel].volume; + Instrument *instrument = _bank.instruments[channel->instrument]; while (1) { /* Available source samples until end of segment */ @@ -193,11 +222,11 @@ static void play_instrument(int16 *dest, channel_t *channel, int count) { channel->envelope_samples -= amount; if (channel->envelope_samples == 0) { - envelope_t *envelope; + Envelope *envelope; int delta, target, velocity; if (channel->decay) - envelope = &env_decay; + envelope = &_envDecay; else envelope = &instrument->envelope[channel->envelope]; @@ -218,7 +247,7 @@ static void play_instrument(int16 *dest, channel_t *channel, int count) { case 0: case 2: /* Go to next phase */ - set_envelope(channel, instrument->envelope, channel->envelope + 1); + setEnvelope(channel, instrument->envelope, channel->envelope + 1); break; case 1: case 3: @@ -237,7 +266,7 @@ static void play_instrument(int16 *dest, channel_t *channel, int count) { break; if (fracToInt(channel->offset) >= seg_end) { - if (instrument->mode & MODE_LOOP) { + if (instrument->mode & kModeLoop) { /* Loop the samples */ channel->offset -= intToFrac(seg_end); channel->looping = 1; @@ -250,79 +279,79 @@ static void play_instrument(int16 *dest, channel_t *channel, int count) { } } -static void change_instrument(int channel, int instrument) { +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); + 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 - hw_channels[channel].instrument = instrument; + _channels[channel].instrument = instrument; } -static void stop_channel(int ch) { +void MidiDriver_Amiga::stopChannel(int ch) { int i; /* Start decay phase for note on this hw channel, if any */ - for (i = 0; i < CHANNELS_NR; i++) - if (channels[i].note != -1 && channels[i].hw_channel == ch && !channels[i].decay) { + for (i = 0; i < kChannels; i++) + if (_voices[i].note != -1 && _voices[i].hw_channel == ch && !_voices[i].decay) { /* Trigger fast decay envelope */ - channels[i].decay = 1; - channels[i].envelope_samples = env_decay.length; + _voices[i].decay = 1; + _voices[i].envelope_samples = _envDecay.length; break; } } -static void stop_note(int ch, int note) { +void MidiDriver_Amiga::stopNote(int ch, int note) { int channel; - instrument_t *instrument; + Instrument *instrument; - for (channel = 0; channel < CHANNELS_NR; channel++) - if (channels[channel].note == note && channels[channel].hw_channel == ch && !channels[channel].decay) + for (channel = 0; channel < kChannels; channel++) + if (_voices[channel].note == note && _voices[channel].hw_channel == ch && !_voices[channel].decay) break; - if (channel == CHANNELS_NR) { + if (channel == kChannels) { #ifdef DEBUG warning("[sfx:seq:amiga] cannot stop note %i on channel %i", note, ch); #endif return; } - instrument = bank.instruments[channels[channel].instrument]; + instrument = _bank.instruments[_voices[channel].instrument]; /* Start the envelope phases for note-off if looping is on and envelope is enabled */ - if ((instrument->mode & MODE_LOOP) && (instrument->envelope[0].length != 0)) - set_envelope(&channels[channel], instrument->envelope, 2); + if ((instrument->mode & kModeLoop) && (instrument->envelope[0].length != 0)) + setEnvelope(&_voices[channel], instrument->envelope, 2); } -static void start_note(int ch, int note, int velocity) { - instrument_t *instrument; +void MidiDriver_Amiga::startNote(int ch, int note, int velocity) { + Instrument *instrument; int channel; - if (hw_channels[ch].instrument < 0 || hw_channels[ch].instrument > 255) { - warning("[sfx:seq:amiga] invalid instrument %i on channel %i", hw_channels[ch].instrument, ch); + 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[hw_channels[ch].instrument]; + instrument = _bank.instruments[_channels[ch].instrument]; if (!instrument) { - warning("[sfx:seq:amiga] instrument %i does not exist", hw_channels[ch].instrument); + warning("[sfx:seq:amiga] instrument %i does not exist", _channels[ch].instrument); return; } - for (channel = 0; channel < CHANNELS_NR; channel++) - if (channels[channel].note == -1) + for (channel = 0; channel < kChannels; channel++) + if (_voices[channel].note == -1) break; - if (channel == CHANNELS_NR) { + if (channel == kChannels) { warning("[sfx:seq:amiga] could not find a free channel"); return; } - stop_channel(ch); + stopChannel(ch); - if (instrument->mode & MODE_PITCH) { + if (instrument->mode & kModePitch) { int fnote = note + instrument->transpose; if (fnote < 0 || fnote > 127) { @@ -331,40 +360,32 @@ static void start_note(int ch, int note, int velocity) { } /* Compute rate for note */ - channels[channel].rate = doubleToFrac(freq_table[fnote] / (double) FREQUENCY); + _voices[channel].rate = doubleToFrac(freq_table[fnote] / (double) _frequency); } else - channels[channel].rate = doubleToFrac(BASE_FREQ / (double) FREQUENCY); + _voices[channel].rate = doubleToFrac(kBaseFreq / (double) _frequency); - channels[channel].instrument = hw_channels[ch].instrument; - channels[channel].note = note; - channels[channel].note_velocity = velocity; + _voices[channel].instrument = _channels[ch].instrument; + _voices[channel].note = note; + _voices[channel].note_velocity = velocity; - if ((instrument->mode & MODE_LOOP) && (instrument->envelope[0].length != 0)) - set_envelope(&channels[channel], instrument->envelope, 0); + if ((instrument->mode & kModeLoop) && (instrument->envelope[0].length != 0)) + setEnvelope(&_voices[channel], instrument->envelope, 0); else { - channels[channel].velocity = 64; - channels[channel].envelope_samples = -1; + _voices[channel].velocity = 64; + _voices[channel].envelope_samples = -1; } - channels[channel].offset = 0; - channels[channel].hw_channel = ch; - channels[channel].decay = 0; - channels[channel].looping = 0; -} - -static int16 read_int16(byte *data) { - return (data[0] << 8) | data[1]; + _voices[channel].offset = 0; + _voices[channel].hw_channel = ch; + _voices[channel].decay = 0; + _voices[channel].looping = 0; } -static int32 read_int32(byte *data) { - return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; -} - -static instrument_t *read_instrument(Common::File &file, int *id) { - instrument_t *instrument; +MidiDriver_Amiga::Instrument *MidiDriver_Amiga::readInstrument(Common::File &file, int *id) { + Instrument *instrument; byte header[61]; int size; - int seg_size[3]; + int16 seg_size[3]; int loop_offset; int i; @@ -373,11 +394,11 @@ static instrument_t *read_instrument(Common::File &file, int *id) { return NULL; } - instrument = (instrument_t *) malloc(sizeof(instrument_t)); + instrument = new Instrument; - seg_size[0] = read_int16(header + 35) * 2; - seg_size[1] = read_int16(header + 41) * 2; - seg_size[2] = read_int16(header + 47) * 2; + 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]; @@ -387,17 +408,17 @@ static instrument_t *read_instrument(Common::File &file, int *id) { 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].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_int32(header + 37) & ~1; + loop_offset = READ_BE_UINT32(header + 37) & ~1; size = seg_size[0] + seg_size[1] + seg_size[2]; - *id = read_int16(header); + *id = READ_BE_UINT16(header); strncpy(instrument->name, (char *) header + 2, 29); instrument->name[29] = 0; @@ -405,8 +426,8 @@ static instrument_t *read_instrument(Common::File &file, int *id) { 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 & MODE_LOOP ? "on" : "off"); - printf(" Pitch changes: %s\n", instrument->mode & MODE_PITCH ? "on" : "off"); + 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 @@ -418,7 +439,7 @@ static instrument_t *read_instrument(Common::File &file, int *id) { return NULL; } - if (instrument->mode & MODE_LOOP) { + 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", @@ -443,6 +464,7 @@ static instrument_t *read_instrument(Common::File &file, int *id) { 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; } @@ -450,14 +472,26 @@ static instrument_t *read_instrument(Common::File &file, int *id) { return instrument; } -static Common::Error ami_set_option(sfx_softseq_t *self, const char *name, const char *value) { - return Common::kUnknownError; +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; } -static Common::Error ami_init(sfx_softseq_t *self, byte *patch, int patch_len, byte *patch2, int patch2_len) { +int MidiDriver_Amiga::open() { + _frequency = _mixer->getOutputRate(); + _envDecay.length = _frequency / (32 * 64); + _envDecay.delta = 1; + _envDecay.target = 0; + Common::File file; byte header[40]; - int i; if (!file.open("bank.001")) { warning("[sfx:seq:amiga] file bank.001 not found"); @@ -469,29 +503,29 @@ static Common::Error ami_init(sfx_softseq_t *self, byte *patch, int patch_len, b return Common::kUnknownError; } - for (i = 0; i < 256; i++) - bank.instruments[i] = NULL; + for (uint i = 0; i < 256; i++) + _bank.instruments[i] = NULL; - for (i = 0; i < CHANNELS_NR; i++) { - channels[i].note = -1; + for (uint i = 0; i < kChannels; i++) { + _voices[i].note = -1; } - for (i = 0; i < HW_CHANNELS_NR; i++) { - hw_channels[i].instrument = -1; - hw_channels[i].volume = 127; - hw_channels[i].pan = (i % 4 == 0 || i % 4 == 3 ? PAN_LEFT : PAN_RIGHT); + 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_int16(header + 38); - strncpy(bank.name, (char *) header + 8, 29); - bank.name[29] = 0; + _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); + printf("[sfx:seq:amiga] Reading %i instruments from bank \"%s\"\n", _bank.size, _bank.name); #endif - for (i = 0; i < bank.size; i++) { + for (uint i = 0; i < _bank.size; i++) { int id; - instrument_t *instrument = read_instrument(file, &id); + Instrument *instrument = readInstrument(file, &id); if (!instrument) { warning("[sfx:seq:amiga] failed to read bank.001"); @@ -503,124 +537,131 @@ static Common::Error ami_init(sfx_softseq_t *self, byte *patch, int patch_len, b return Common::kUnknownError; } - bank.instruments[id] = instrument; + _bank.instruments[id] = instrument; } + MidiDriver_Emulated::open(); + + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_mixerSoundHandle, this, -1, _mixer->kMaxChannelVolume, 0, false); + return Common::kNoError; } -static void ami_exit(sfx_softseq_t *self) { - int i; +void MidiDriver_Amiga::close() { + _mixer->stopHandle(_mixerSoundHandle); - for (i = 0; i < bank.size; i++) { - if (bank.instruments[i]) { - free(bank.instruments[i]->samples); - free(bank.instruments[i]); + 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]; } } } -static void ami_event(sfx_softseq_t *self, byte command, int argc, byte *argv) { - int channel, oper; +void MidiDriver_Amiga::playSwitch(bool play) { + _playSwitch = play; +} - channel = command & 0x0f; - oper = command & 0xf0; +void MidiDriver_Amiga::setVolume(byte volume_) { + _masterVolume = volume_; +} - if (channel >= HW_CHANNELS_NR) { -#ifdef DEBUG - warning("[sfx:seq:amiga] received event for non-existing channel %i", channel); -#endif - return; - } +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 (oper) { + switch (command) { case 0x90: - if (argv[1] > 0) - start_note(channel, argv[0], argv[1]); + if (op2 > 0) + startNote(channel, op1, op2); else - stop_note(channel, argv[0]); + stopNote(channel, op1); break; case 0xb0: - switch (argv[0]) { + switch (op1) { case 0x07: - hw_channels[channel].volume = argv[1]; + _channels[channel].volume = op2; break; case 0x0a: #ifdef DEBUG - warning("[sfx:seq:amiga] ignoring pan 0x%02x event for channel %i", argv[1], channel); + warning("[sfx:seq:amiga] ignoring pan 0x%02x event for channel %i", op2, channel); #endif break; case 0x7b: - stop_channel(channel); + stopChannel(channel); break; default: - warning("[sfx:seq:amiga] unknown control event 0x%02x", argv[0]); + warning("[sfx:seq:amiga] unknown control event 0x%02x", op1); } break; case 0xc0: - change_instrument(channel, argv[0]); + changeInstrument(channel, op1); break; default: warning("[sfx:seq:amiga] unknown event %02x", command); } } -void ami_poll(sfx_softseq_t *self, byte *dest, int len) { - int i, j; - int16 *buf = (int16 *) dest; - // FIXME: memleak - int16 *buffers = (int16*)malloc(len * 2 * CHANNELS_NR); +void MidiDriver_Amiga::generateSamples(int16 *data, int len) { + if (len == 0) + return; - memset(buffers, 0, len * 2 * CHANNELS_NR); - memset(dest, 0, len * 4); + int16 *buffers = (int16*)malloc(len * 2 * kChannels); - /* Generate samples for all notes */ - for (i = 0; i < CHANNELS_NR; i++) - if (channels[i].note >= 0) - play_instrument(buffers + i * len, &channels[i], len); + memset(buffers, 0, len * 2 * kChannels); - for (j = 0; j < len; j++) { - int mixedl = 0, mixedr = 0; + /* 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; + } - /* Mix and pan */ - for (i = 0; i < CHANNELS_NR; i++) { - mixedl += buffers[i * len + j] * (256 - hw_channels[channels[i].hw_channel].pan); - mixedr += buffers[i * len + j] * hw_channels[channels[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; - /* Adjust volume */ - buf[2 * j] = mixedl * volume >> 16; - buf[2 * j + 1] = mixedr * volume >> 16; - } -} + /* Mix */ + for (int i = 0; i < kChannels; i++) + mixed += buffers[i * len + j]; -void ami_volume(sfx_softseq_t *self, int new_volume) { - volume = new_volume; -} + /* Adjust volume */ + data[j] = mixed * _masterVolume >> 6; + } + } -void ami_allstop(sfx_softseq_t *self) { - int i; - for (i = 0; i < HW_CHANNELS_NR; i++) - stop_channel(i); + free(buffers); } -sfx_softseq_t sfx_softseq_amiga = { - "amiga", - "0.1", - ami_set_option, - ami_init, - ami_exit, - ami_volume, - ami_event, - ami_poll, - ami_allstop, - NULL, - SFX_SEQ_PATCHFILE_NONE, - SFX_SEQ_PATCHFILE_NONE, - 0x40, - 0, /* No rhythm channel (9) */ - HW_CHANNELS_NR, /* # of voices */ - {FREQUENCY, SFX_PCM_STEREO_LR, SFX_PCM_FORMAT_S16_NATIVE} +class MidiPlayer_Amiga : public MidiPlayer { +public: + MidiPlayer_Amiga() { _driver = new MidiDriver_Amiga(g_system->getMixer()); } + int getPlayMask() const { return 0x40; } + 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(); +} + } // End of namespace Sci |