Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

midiadlib.cpp

/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/queen/midiadlib.cpp $
 * $Id: midiadlib.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */

#include "common/endian.h"

#include "sound/fmopl.h"
#include "sound/softsynth/emumidi.h"

namespace Queen {

class AdlibMidiChannel;

class AdlibMidiDriver : public MidiDriver_Emulated {
public:

      AdlibMidiDriver(Audio::Mixer *mixer) : MidiDriver_Emulated(mixer) {}
      ~AdlibMidiDriver() {}

      // MidiDriver
      int open();
      void close();
      void send(uint32 b);
      void metaEvent(byte type, byte *data, uint16 length);
      MidiChannel *allocateChannel() { return 0; }
      MidiChannel *getPercussionChannel() { return 0; }

      // AudioStream
      bool isStereo() const { return false; }
      int getRate() const { return _mixer->getOutputRate(); }

      // MidiDriver_Emulated
      void generateSamples(int16 *buf, int len);

private:

      void handleMidiEvent0x90_NoteOn(int channel, int param1, int param2);
      void handleSequencerSpecificMetaEvent1(int channel, const uint8 *data);
      void handleSequencerSpecificMetaEvent2(uint8 value);
      void handleSequencerSpecificMetaEvent3(uint8 value);

      void adlibWrite(uint8 port, uint8 value);
      void adlibSetupCard();
      void adlibSetupChannels(int fl);
      void adlibResetAmpVibratoRhythm(int am, int vib, int kso);
      void adlibResetChannels();
      void adlibSetAmpVibratoRhythm();
      void adlibSetCSMKeyboardSplit();
      void adlibSetNoteMul(int mul);
      void adlibSetWaveformSelect(int fl);
      void adlibSetPitchBend(int channel, int range);
      void adlibPlayNote(int channel);
      uint8 adlibPlayNoteHelper(int channel, int note1, int note2, int oct);
      void adlibTurnNoteOff(int channel);
      void adlibTurnNoteOn(int channel, int note);
      void adlibSetupChannelFromSequence(int channel, const uint8 *src, int fl);
      void adlibSetupChannel(int channel, const uint16 *src, int fl);
      void adlibSetNoteVolume(int channel, int volume);
      void adlibSetupChannelHelper(int channel);
      void adlibSetChannel0x40(int channel);
      void adlibSetChannel0xC0(int channel);
      void adlibSetChannel0x60(int channel);
      void adlibSetChannel0x80(int channel);
      void adlibSetChannel0x20(int channel);
      void adlibSetChannel0xE0(int channel);

      FM_OPL *_opl;
      int _midiNumberOfChannels;
      int _adlibNoteMul;
      int _adlibWaveformSelect;
      int _adlibAMDepthEq48;
      int _adlibVibratoDepthEq14;
      int _adlibRhythmEnabled;
      int _adlibKeyboardSplitOn;
      int _adlibVibratoRhythm;
      uint8 _midiChannelsFreqTable[9];
      uint8 _adlibChannelsLevelKeyScalingTable[11];
      uint8 _adlibSetupChannelSequence1[14 * 18];
      uint16 _adlibSetupChannelSequence2[14];
      int16 _midiChannelsNote2Table[9];
      uint8 _midiChannelsNote1Table[9];
      uint8 _midiChannelsOctTable[9];
      uint16 _adlibChannelsVolume[11];
      uint16 _adlibMetaSequenceData[28];

      static const uint8 _adlibChannelsMappingTable1[];
      static const uint8 _adlibChannelsNoFeedback[];
      static const uint8 _adlibChannelsMappingTable2[];
      static const uint8 _adlibChannelsMappingTable3[];
      static const uint8 _adlibChannelsKeyScalingTable1[];
      static const uint8 _adlibChannelsKeyScalingTable2[];
      static const uint8 _adlibChannelsVolumeTable[];
      static const uint8 _adlibInitSequenceData1[];
      static const uint8 _adlibInitSequenceData2[];
      static const uint8 _adlibInitSequenceData3[];
      static const uint8 _adlibInitSequenceData4[];
      static const uint8 _adlibInitSequenceData5[];
      static const uint8 _adlibInitSequenceData6[];
      static const uint8 _adlibInitSequenceData7[];
      static const uint8 _adlibInitSequenceData8[];
      static const int16 _midiChannelsNoteTable[];
      static const int16 _midiNoteFreqTable[];
};

int AdlibMidiDriver::open() {
      MidiDriver_Emulated::open();
      _opl = makeAdlibOPL(getRate());
      adlibSetupCard();
      for (int i = 0; i < 11; ++i) {
            _adlibChannelsVolume[i] = 0;
            adlibSetNoteVolume(i, 0);
            adlibTurnNoteOff(i);
      }
      _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
      return 0;
}

void AdlibMidiDriver::close() {
      _mixer->stopHandle(_mixerSoundHandle);
      OPLDestroy(_opl);
}

void AdlibMidiDriver::send(uint32 b) {
      int channel = b & 15;
      int cmd = (b >> 4) & 7;
      int param1 = (b >> 8) & 255;
      int param2 = (b >> 16) & 255;
      switch (cmd) {
      case 0:
            adlibTurnNoteOff(channel);
            break;
      case 1:
            handleMidiEvent0x90_NoteOn(channel, param1, param2);
            break;
      case 3:
            break;
      case 5:
            adlibSetNoteVolume(channel, param1);
            _adlibChannelsVolume[channel] = param1;
            break;
      case 6:
            adlibSetPitchBend(channel, param1 | (param2 << 7));
            break;
      default:
//          warning("Unhandled cmd %d channel %d (0x%X)\n", cmd, channel, b);
            break;
      }
}

void AdlibMidiDriver::metaEvent(byte type, byte *data, uint16 length) {
      int event = 0;
      if (length > 4 && READ_BE_UINT32(data) == 0x3F00) {
            event = data[4];
            switch (event) {
            case 1:
                  if (length == 34) {
                        handleSequencerSpecificMetaEvent1(data[5], data + 6);
                        return;
                  }
                  break;
            case 2:
                  if (length == 6) {
                        handleSequencerSpecificMetaEvent2(data[5]);
                        return;
                  }
                  break;
            case 3:
                  if (length == 6) {
                        handleSequencerSpecificMetaEvent3(data[5]);
                        return;
                  }
                  break;
            }
      }
      warning("Unhandled meta event %d len %d", event, length);
}

void AdlibMidiDriver::generateSamples(int16 *data, int len) {
      memset(data, 0, sizeof(int16) * len);
      YM3812UpdateOne(_opl, data, len);
}

void AdlibMidiDriver::handleSequencerSpecificMetaEvent1(int channel, const uint8 *data) {
      for (int i = 0; i < 28; ++i) {
            _adlibMetaSequenceData[i] = data[i];
      }
      if (_midiNumberOfChannels > channel) {
            const uint8 *p;
            if (_adlibRhythmEnabled) {
                  p = &_adlibChannelsKeyScalingTable2[channel * 2];
            } else {
                  p = &_adlibChannelsKeyScalingTable1[channel * 2];
            }
            adlibSetupChannel(p[0], _adlibMetaSequenceData, _adlibMetaSequenceData[26]);
            if (p[1] != 255) {
                  adlibSetupChannel(p[1], _adlibMetaSequenceData + 13, _adlibMetaSequenceData[27]);
            }
      }
}

void AdlibMidiDriver::handleSequencerSpecificMetaEvent2(uint8 value) {
      _adlibRhythmEnabled = value;
      _midiNumberOfChannels = _adlibRhythmEnabled ? 11 : 9;
      adlibSetAmpVibratoRhythm();
}

void AdlibMidiDriver::handleSequencerSpecificMetaEvent3(uint8 value) {
      adlibSetNoteMul(value);
}

void AdlibMidiDriver::handleMidiEvent0x90_NoteOn(int channel, int param1, int param2) { // note, volume
      if (param2 == 0) {
            adlibTurnNoteOff(channel);
            _adlibChannelsVolume[channel] = param2;
      } else {
            adlibSetNoteVolume(channel, param2);
            _adlibChannelsVolume[channel] = param2;
            adlibTurnNoteOff(channel);
            adlibTurnNoteOn(channel, param1);
      }
}

void AdlibMidiDriver::adlibWrite(uint8 port, uint8 value) {
      OPLWriteReg(_opl, port, value);
}

void AdlibMidiDriver::adlibSetupCard() {
      for (int i = 1; i <= 0xF5; ++i) {
            adlibWrite(i, 0);
      }
      adlibWrite(4, 6);
      for (int i = 0; i < 9; ++i) {
            _midiChannelsNote2Table[i] = 8192;
            _midiChannelsOctTable[i] = 0;
            _midiChannelsNote1Table[i] = 0;
            _midiChannelsFreqTable[i] = 0;
      }
      memset(_adlibChannelsLevelKeyScalingTable, 127, 11);
      adlibSetupChannels(0);
      adlibResetAmpVibratoRhythm(0, 0, 0);
      adlibSetNoteMul(1);
      adlibSetWaveformSelect(1);
}

void AdlibMidiDriver::adlibSetupChannels(int fl) {
      if (fl != 0) {
            _midiChannelsNote1Table[8] = 24;
            _midiChannelsNote2Table[8] = 8192;
            adlibPlayNote(8);
            _midiChannelsNote1Table[7] = 31;
            _midiChannelsNote2Table[7] = 8192;
            adlibPlayNote(7);
      }
      _adlibRhythmEnabled = fl;
      _midiNumberOfChannels = fl ? 11 : 9;
      _adlibVibratoRhythm = 0;
      _adlibAMDepthEq48 = 0;
      _adlibVibratoDepthEq14 = 0;
      _adlibKeyboardSplitOn = 0;
      adlibResetChannels();
      adlibSetAmpVibratoRhythm();
}

void AdlibMidiDriver::adlibResetAmpVibratoRhythm(int am, int vib, int kso) {
      _adlibAMDepthEq48 = am;
      _adlibVibratoDepthEq14 = vib;
      _adlibKeyboardSplitOn = kso;
      adlibSetAmpVibratoRhythm();
      adlibSetCSMKeyboardSplit();
}

void AdlibMidiDriver::adlibResetChannels() {
      for (int i = 0; i < 18; ++i) {
            adlibSetupChannelFromSequence(i, _adlibChannelsNoFeedback[i] ? _adlibInitSequenceData2 : _adlibInitSequenceData1, 0);
      }
      if (_adlibRhythmEnabled) {
            adlibSetupChannelFromSequence(12, _adlibInitSequenceData3, 0);
            adlibSetupChannelFromSequence(15, _adlibInitSequenceData4, 0);
            adlibSetupChannelFromSequence(16, _adlibInitSequenceData5, 0);
            adlibSetupChannelFromSequence(14, _adlibInitSequenceData6, 0);
            adlibSetupChannelFromSequence(17, _adlibInitSequenceData7, 0);
            adlibSetupChannelFromSequence(13, _adlibInitSequenceData8, 0);
      }
}

void AdlibMidiDriver::adlibSetAmpVibratoRhythm() {
      uint8 value = 0;
      if (_adlibAMDepthEq48) {
            value |= 0x80;
      }
      if (_adlibVibratoDepthEq14) {
            value |= 0x40;
      }
      if (_adlibRhythmEnabled) {
            value |= 0x20;
      }
      adlibWrite(0xBD, value | _adlibVibratoRhythm);
}

void AdlibMidiDriver::adlibSetCSMKeyboardSplit() {
      uint8 value = _adlibKeyboardSplitOn ? 0x40 : 0;
      adlibWrite(8, value);
}

void AdlibMidiDriver::adlibSetNoteMul(int mul) {
      if (mul > 12) {
            mul = 12;
      } else if (mul < 1) {
            mul = 1;
      }
      _adlibNoteMul = mul;
}

void AdlibMidiDriver::adlibSetWaveformSelect(int fl) {
      _adlibWaveformSelect = fl ? 0x20 : 0;
      for (int i = 0; i < 18; ++i) {
            adlibWrite(0xE0 + _adlibChannelsMappingTable1[i], 0);
      }
      adlibWrite(1, _adlibWaveformSelect);
}

void AdlibMidiDriver::adlibSetPitchBend(int channel, int range) {
      if ((_adlibRhythmEnabled && channel <= 6) || channel < 9) {
            if (range > 16383) {
                  range = 16383;
            }
            _midiChannelsNote2Table[channel] = range;
            adlibPlayNote(channel);
      }
}

void AdlibMidiDriver::adlibPlayNote(int channel) {
      _midiChannelsFreqTable[channel] = adlibPlayNoteHelper(channel, _midiChannelsNote1Table[channel], _midiChannelsNote2Table[channel], _midiChannelsOctTable[channel]);
}

uint8 AdlibMidiDriver::adlibPlayNoteHelper(int channel, int note1, int note2, int oct) {
      int n = ((note2 * _midiChannelsNoteTable[channel]) >> 8) - 8192;
      if (n != 0) {
            n >>= 5;
            n *= _adlibNoteMul;
      }
      n += (note1 << 8) + 8;
      n >>= 4;
      if (n < 0) {
            n = 0;
      } else if (n > 1535) {
            n = 1535;
      }
      int index = (((n >> 4) % 12) << 4) | (n & 0xF);
      int f = _midiNoteFreqTable[index];
      int o = (n >> 4) / 12 - 1;
      if (f < 0) {
            ++o;
      }
      if (o < 0) {
            ++o;
            f >>= 1;
      }
      adlibWrite(0xA0 + channel, f & 0xFF);
      int value = ((f >> 8) & 3) | (o << 2) | oct;
      adlibWrite(0xB0 + channel, value);
      return value;
}

void AdlibMidiDriver::adlibTurnNoteOff(int channel) {
      if ((_adlibRhythmEnabled && channel <= 6) || channel < 9) {
            _midiChannelsOctTable[channel] = 0;
            _midiChannelsFreqTable[channel] &= ~0x20;
            adlibWrite(0xB0 + channel, _midiChannelsFreqTable[channel]);
      } else if (_adlibRhythmEnabled && channel <= 10) {
            _adlibVibratoRhythm &= ~(1 << (4 - (channel - 6)));
            adlibSetAmpVibratoRhythm();
      }
}

void AdlibMidiDriver::adlibTurnNoteOn(int channel, int note) {
      note -= 12;
      if (note < 0) {
            note = 0;
      }
      if ((_adlibRhythmEnabled && channel <= 6) || channel < 9) {
            _midiChannelsNote1Table[channel] = note;
            _midiChannelsOctTable[channel] = 0x20;
            adlibPlayNote(channel);
      } else if (_adlibRhythmEnabled && channel <= 10) {
            if (channel == 6) {
                  _midiChannelsNote1Table[6] = note;
                  adlibPlayNote(channel);
            } else if (channel == 8 && _midiChannelsNote1Table[8] == note) {
                  _midiChannelsNote1Table[8] = note;
                  _midiChannelsNote1Table[7] = note + 7;
                  adlibPlayNote(8);
                  adlibPlayNote(7);
            }
            _adlibVibratoRhythm = 1 << (4 - (channel - 6));
            adlibSetAmpVibratoRhythm();
      }
}

void AdlibMidiDriver::adlibSetupChannelFromSequence(int channel, const uint8 *src, int fl) {
      for (int i = 0; i < 13; ++i) {
            _adlibSetupChannelSequence2[i] = src[i];
      }
      adlibSetupChannel(channel, _adlibSetupChannelSequence2, fl);
}

void AdlibMidiDriver::adlibSetupChannel(int channel, const uint16 *src, int fl) {
      for (int i = 0; i < 13; ++i) {
            _adlibSetupChannelSequence1[14 * channel + i] = src[i];
      }
      _adlibSetupChannelSequence1[14 * channel + 13] = fl & 3;
      adlibSetupChannelHelper(channel);
}

void AdlibMidiDriver::adlibSetNoteVolume(int channel, int volume) {
      if (_midiNumberOfChannels > channel) {
            if (volume > 127) {
                  volume = 127;
            }
            _adlibChannelsLevelKeyScalingTable[channel] = volume;
            const uint8 *p;
            if (_adlibRhythmEnabled) {
                  p = &_adlibChannelsKeyScalingTable2[channel * 2];
            } else {
                  p = &_adlibChannelsKeyScalingTable1[channel * 2];
            }
            adlibSetChannel0x40(p[0]);
            if (p[1] != 255) {
                  adlibSetChannel0x40(p[1]);
            }
      }
}

void AdlibMidiDriver::adlibSetupChannelHelper(int channel) {
      adlibSetAmpVibratoRhythm();
      adlibSetCSMKeyboardSplit();
      adlibSetChannel0x40(channel);
      adlibSetChannel0xC0(channel);
      adlibSetChannel0x60(channel);
      adlibSetChannel0x80(channel);
      adlibSetChannel0x20(channel);
      adlibSetChannel0xE0(channel);
}

void AdlibMidiDriver::adlibSetChannel0x40(int channel) {
      int index, value, fl;

      if (_adlibRhythmEnabled) {
            index = _adlibChannelsMappingTable3[channel];
      } else {
            index = _adlibChannelsMappingTable2[channel];
      }
      value = 63 - (_adlibSetupChannelSequence1[channel * 14 + 8] & 63);
      fl = 0;
      if (_adlibRhythmEnabled && index > 6) {
            fl = -1;
      }
      if (_adlibChannelsNoFeedback[channel] || _adlibSetupChannelSequence1[channel * 14 + 12] == 0 || fl != 0) {
            value = ((_adlibChannelsLevelKeyScalingTable[index] * value) + 64) >> 7;
      }
      value = (_adlibChannelsVolumeTable[index] * value * 2) >> 8;
      if (value > 63) {
            value = 63;
      }
      value = 63 - value;
      value |= _adlibSetupChannelSequence1[channel * 14] << 6;
      adlibWrite(0x40 + _adlibChannelsMappingTable1[channel], value);
}

void AdlibMidiDriver::adlibSetChannel0xC0(int channel) {
      if (_adlibChannelsNoFeedback[channel] == 0) {
            const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
            uint8 value = p[2] << 1;
            if (p[12] == 0) {
                  value |= 1;
            }
            adlibWrite(0xC0 + _adlibChannelsMappingTable2[channel], value);
      }
}

void AdlibMidiDriver::adlibSetChannel0x60(int channel) {
      const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
      uint8 value = (p[3] << 4) | (p[6] & 15);
      adlibWrite(0x60 + _adlibChannelsMappingTable1[channel], value);
}

void AdlibMidiDriver::adlibSetChannel0x80(int channel) {
      const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
      uint8 value = (p[4] << 4) | (p[7] & 15);
      adlibWrite(0x80 + _adlibChannelsMappingTable1[channel], value);
}

void AdlibMidiDriver::adlibSetChannel0x20(int channel) {
      const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
      uint8 value = p[1] & 15;
      if (p[9]) {
            value |= 0x80;
      }
      if (p[10]) {
            value |= 0x40;
      }
      if (p[5]) {
            value |= 0x20;
      }
      if (p[11]) {
            value |= 0x10;
      }
      adlibWrite(0x20 + _adlibChannelsMappingTable1[channel], value);
}

void AdlibMidiDriver::adlibSetChannel0xE0(int channel) {
      uint8 value = 0;
      if (_adlibWaveformSelect) {
            const uint8 *p = &_adlibSetupChannelSequence1[channel * 14];
            value = p[13] & 3;
      }
      adlibWrite(0xE0 + _adlibChannelsMappingTable1[channel], value);
}

const uint8 AdlibMidiDriver::_adlibChannelsMappingTable1[] = {
      0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21
};

const uint8 AdlibMidiDriver::_adlibChannelsNoFeedback[] = {
      0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1
};

const uint8 AdlibMidiDriver::_adlibChannelsMappingTable2[] = {
      0, 1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 7, 8, 6, 7, 8
};

const uint8 AdlibMidiDriver::_adlibChannelsMappingTable3[] = {
      0, 1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 10, 8, 6, 7, 9
};

const uint8 AdlibMidiDriver::_adlibChannelsKeyScalingTable1[] = {
      0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 13, 16, 14, 17
};

const uint8 AdlibMidiDriver::_adlibChannelsKeyScalingTable2[] = {
      0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 255, 14, 255, 17, 255, 13, 255
};

const uint8 AdlibMidiDriver::_adlibChannelsVolumeTable[] = {
      128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData1[] = {
      1, 1, 3, 15, 5, 0, 1, 3, 15, 0, 0, 0, 1, 0
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData2[] = {
      0, 1, 1, 15, 7, 0, 2, 4, 0, 0, 0, 1, 0, 0
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData3[] = {
      0, 0, 0, 10, 4, 0, 8, 12, 11, 0, 0, 0, 1, 0
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData4[] = {
      0, 0, 0, 13, 4, 0, 6, 15, 0, 0, 0, 0, 1, 0
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData5[] = {
      0, 12, 0, 15, 11, 0, 8, 5, 0, 0, 0, 0, 0, 0
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData6[] = {
      0, 4, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData7[] = {
      0, 1, 0, 15, 11, 0, 5, 5, 0, 0, 0, 0, 0, 0
};

const uint8 AdlibMidiDriver::_adlibInitSequenceData8[] = {
      0, 1, 0, 15, 11, 0, 7, 5, 0, 0, 0, 0, 0, 0
};

const int16 AdlibMidiDriver::_midiChannelsNoteTable[] = {
      256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256
};

const int16 AdlibMidiDriver::_midiNoteFreqTable[] = {
       690,  692,  695,  697,  700,  702,  705,  707,  710,  713,  715,  718,
       720,  723,  726,  728,  731,  733,  736,  739,  741,  744,  747,  749,
       752,  755,  758,  760,  763,  766,  769,  771,  774,  777,  780,  783,
       785,  788,  791,  794,  797,  800,  803,  806,  809,  811,  814,  817,
       820,  823,  826,  829,  832,  835,  838,  841,  844,  847,  850,  854,
       857,  860,  863,  866,  869,  872,  875,  879,  882,  885,  888,  891,
       895,  898,  901,  904,  908,  911,  914,  917,  921,  924,  927,  931,
       934,  937,  941,  944,  948,  951,  955,  958,  961,  965,  968,  972,
       975,  979,  983,  986,  990,  993,  997, 1000, 1004, 1008, 1011, 1015,
      1019, 1022, -511, -509, -507, -505, -504, -502, -500, -498, -496, -494,
      -492, -490, -488, -486, -484, -482, -480, -479, -477, -475, -473, -471,
      -469, -467, -465, -463, -460, -458, -456, -454, -452, -450, -448, -446,
      -444, -442, -440, -438, -436, -433, -431, -429, -427, -425, -423, -420,
      -418, -416, -414, -412, -409, -407, -405, -403, -401, -398, -396, -394,
      -391, -389, -387, -385, -382, -380, -378, -375, -373, -371, -368, -366,
      -363, -361, -359, -356, -354, -351, -349, -347, -344, -342, -339, -337
};

MidiDriver *C_Player_CreateAdlibMidiDriver(Audio::Mixer *mixer) {
      return new AdlibMidiDriver(mixer);
}

} // End of namespace Queen

Generated by  Doxygen 1.6.0   Back to index