diff options
author | Jamieson Christian | 2003-10-06 14:08:33 +0000 |
---|---|---|
committer | Jamieson Christian | 2003-10-06 14:08:33 +0000 |
commit | 83ace36fcc3bd256040129db699a6fbd75b6002d (patch) | |
tree | f054fba7bc80ea6e0950e589c4940c408c7ee49a /backends/midi/ym2612.cpp | |
parent | 4ef2541a3afdd88df3266754f00e7d0e9387ea23 (diff) | |
download | scummvm-rg350-83ace36fcc3bd256040129db699a6fbd75b6002d.tar.gz scummvm-rg350-83ace36fcc3bd256040129db699a6fbd75b6002d.tar.bz2 scummvm-rg350-83ace36fcc3bd256040129db699a6fbd75b6002d.zip |
Per-channel polyphony now > 1
svn-id: r10641
Diffstat (limited to 'backends/midi/ym2612.cpp')
-rw-r--r-- | backends/midi/ym2612.cpp | 104 |
1 files changed, 84 insertions, 20 deletions
diff --git a/backends/midi/ym2612.cpp b/backends/midi/ym2612.cpp index f6f072d05c..61d9edf764 100644 --- a/backends/midi/ym2612.cpp +++ b/backends/midi/ym2612.cpp @@ -53,7 +53,7 @@ static int *attackOut = 0; class Operator2612; class Voice2612; class MidiChannel_YM2612; -class MidiDriver_YM2612_Internal; +class MidiDriver_YM2612; class Operator2612 { protected: @@ -96,6 +96,11 @@ public: }; class Voice2612 { +public: + Voice2612 *prev, *next; + bool _in_use; // Fix this. + uint16 _rate; + protected: Operator2612 *_opr[4]; int _velocity; @@ -106,9 +111,6 @@ protected: int _algorithm; public: - uint16 _rate; - -public: Voice2612(); ~Voice2612(); void setControlParameter(int control, int value); @@ -119,14 +121,18 @@ public: bool noteOff(int note); void pitchBend(int value); void recalculateFrequency(); + bool inUse() { return _in_use; } }; class MidiChannel_YM2612 : public MidiChannel { protected: - Voice2612 *_voice; + MidiDriver_YM2612 *_owner; + uint16 _rate; + byte _instrument[48]; + Voice2612 *_voices; public: - MidiChannel_YM2612(); + MidiChannel_YM2612 (MidiDriver_YM2612 *owner); virtual ~MidiChannel_YM2612(); // MidiChannel interface @@ -149,8 +155,10 @@ public: class MidiDriver_YM2612 : public MidiDriver { protected: MidiChannel_YM2612 *_channel[16]; + Voice2612 *_voices[32]; + + int _next_voice; int _volume; - int _rate; bool _isOpen; SoundMixer *_mixer; @@ -170,6 +178,9 @@ protected: static void premix_proc(void *param, int16 *buf, uint len); public: + Voice2612 *allocateVoice(); + +public: MidiDriver_YM2612(SoundMixer *mixer); virtual ~MidiDriver_YM2612(); @@ -419,6 +430,7 @@ void Operator2612::nextTick(uint16 rate, const int *phasebuf, int *outbuf, int b //////////////////////////////////////// Voice2612::Voice2612() { + _in_use = false; _control7 = 127; _note = 40; _frequency = 440; @@ -607,43 +619,80 @@ void Voice2612::recalculateFrequency() { // //////////////////////////////////////// -MidiChannel_YM2612::MidiChannel_YM2612() { - _voice = new Voice2612(); +MidiChannel_YM2612::MidiChannel_YM2612 (MidiDriver_YM2612 *owner) { +// _voice = new Voice2612(); + _owner = owner; + _voices = 0; } MidiChannel_YM2612::~MidiChannel_YM2612() { - delete _voice; +// delete _voice; } void MidiChannel_YM2612::noteOn(byte note, byte onVelo) { - _voice->noteOn(note, onVelo); + Voice2612 *voice = _owner->allocateVoice(); + if (!voice) + return; + voice->_in_use = true; + voice->_rate = _rate; + voice->setInstrument (_instrument); + voice->next = _voices; + voice->prev = 0; + if (_voices) + _voices->prev = voice; + _voices = voice; + voice->noteOn(note, onVelo); } void MidiChannel_YM2612::noteOff(byte note) { - _voice->noteOff(note); + Voice2612 *voice = _voices; + for (; voice; voice = voice->next) { + if (voice->noteOff(note)) { + voice->_in_use = false; + if (voice->next) + voice->next->prev = voice->prev; + if (voice->prev) + voice->prev->next = voice->next; + else + _voices = voice->next; + } + } } void MidiChannel_YM2612::controlChange(byte control, byte value) { // いいのかこれで? - _voice->setControlParameter(control, value); + Voice2612 *voice = _voices; + for (; voice; voice = voice->next) + voice->setControlParameter(control, value); } void MidiChannel_YM2612::sysEx_customInstrument(uint32 type, byte *fmInst) { - if (type == 'EUP ') - _voice->setInstrument(fmInst); + if (type != 'EUP ') + return; + memcpy (_instrument, fmInst, 48); + Voice2612 *voice = _voices; + for (; voice; voice = voice->next) + voice->setInstrument(fmInst); } void MidiChannel_YM2612::pitchBend(int16 value) { // いいのかこれで? - _voice->pitchBend(value); + Voice2612 *voice = _voices; + for (; voice; voice = voice->next) + voice->pitchBend(value); } void MidiChannel_YM2612::nextTick(int *outbuf, int buflen) { - _voice->nextTick(outbuf, buflen); + Voice2612 *voice = _voices; + for (; voice; voice = voice->next) + voice->nextTick(outbuf, buflen); } void MidiChannel_YM2612::rate(uint16 r) { - _voice->_rate = r; + _rate = r; + Voice2612 *voice = _voices; + for (; voice; voice = voice->next) + voice->_rate = r; } //////////////////////////////////////// @@ -660,12 +709,15 @@ _mixer(mixer) _timer_param = 0; _next_tick = 0; _samples_per_tick = (_mixer->getOutputRate() << FIXP_SHIFT) / BASE_FREQ; + _next_voice = 0; createLookupTables(); _volume = 256; int i; + for (i = 0; i < ARRAYSIZE(_voices); i++) + _voices[i] = new Voice2612; for (i = 0; i < ARRAYSIZE(_channel); i++) - _channel[i] = new MidiChannel_YM2612; + _channel[i] = new MidiChannel_YM2612 (this); rate(_mixer->getOutputRate()); } @@ -673,6 +725,8 @@ MidiDriver_YM2612::~MidiDriver_YM2612() { int i; for (i = 0; i < ARRAYSIZE(_channel); i++) delete _channel[i]; + for (i = 0; i < ARRAYSIZE(_voices); i++) + delete _voices[i]; delete sintbl; delete powtbl; delete frequencyTable; @@ -792,7 +846,6 @@ void MidiDriver_YM2612::nextTick(int16 *buf1, int buflen) { void MidiDriver_YM2612::rate(uint16 r) { - _rate = r; int i; for (i = 0; i < ARRAYSIZE(_channel); i++) _channel[i]->rate(r); @@ -870,6 +923,17 @@ void MidiDriver_YM2612::createLookupTables() { } } +Voice2612 *MidiDriver_YM2612::allocateVoice() { + _next_voice %= ARRAYSIZE(_voices); + int oldStart = _next_voice; + do { + if (!_voices[_next_voice++]->inUse()) + return _voices[_next_voice-1]; + _next_voice %= ARRAYSIZE(_voices); + } while (_next_voice != oldStart); + return 0; +} + //////////////////////////////////////// // // MidiDriver_YM2612 factory |