Ticket #8281: ym2612.rev2.diff

File ym2612.rev2.diff, 21.9 KB (added by SF/jamieson630, 21 years ago)

YM2612 implementation, rev 2

  • scummvm/backends/midi/ym2612.cpp

    RCS file: /cvsroot/scummvm/scummvm/backends/midi/ym2612.cpp,v
    retrieving revision 1.1
    diff -u -r1.1 ym2612.cpp
     
    2222 * $Header: /cvsroot/scummvm/scummvm/backends/midi/ym2612.cpp,v 1.1 2003/10/05 15:34:53 jamieson630 Exp $
    2323 */
    2424
    25 // Real implementation coming soon! :)
    26 
     25#include <math.h>
     26#include <string>
     27#include "common/util.h"
    2728#include "sound/mididrv.h"
     29#include "sound/mixer.h"
    2830
    29 MidiDriver *MidiDriver_YM2612_create(SoundMixer *mixer) {
     31////////////////////////////////////////
     32//
     33// Miscellaneous
     34//
     35////////////////////////////////////////
     36
     37#define BASE_FREQ 250
     38#define FIXP_SHIFT  16
     39
     40#ifdef _MSC_VER
     41        typedef __int64 int64;
     42#else
     43        #include <stdint.h>
     44        typedef int64_t int64;
     45#endif
     46
     47static int *sintbl = 0;
     48static int *powtbl = 0;
     49static int *frequencyTable = 0;
     50static int *keycodeTable = 0;
     51static int *keyscaleTable = 0;
     52static int *attackOut = 0;
     53
     54////////////////////////////////////////
     55//
     56// Class declarations
     57//
     58////////////////////////////////////////
     59
     60class Operator2612;
     61class Voice2612;
     62class MidiChannel_YM2612;
     63class MidiDriver_YM2612_Internal;
     64
     65class Operator2612 {
     66protected:
     67        enum State { _s_ready, _s_attacking, _s_decaying, _s_sustaining, _s_releasing };
     68        State _state;
     69        int64 _currentLevel;
     70        int _frequency;
     71        int _phase;
     72        int _lastOutput;
     73        int _feedbackLevel;
     74        int _detune;
     75        int _multiple;
     76        int64 _totalLevel;
     77        int _keyScale;
     78        int _velocity;
     79        int _specifiedTotalLevel;
     80        int _specifiedAttackRate;
     81        int _specifiedDecayRate;
     82        int _specifiedSustainLevel;
     83        int _specifiedSustainRate;
     84        int _specifiedReleaseRate;
     85        int _tickCount;
     86        int _attackTime;
     87        int64 _decayRate;
     88        int64 _sustainLevel;
     89        int64 _sustainRate;
     90        int64 _releaseRate;
     91
     92public:
     93        Operator2612();
     94        ~Operator2612();
     95        void feedbackLevel(int level);
     96        void setInstrument(byte const *instrument);
     97        void velocity(int velo);
     98        void keyOn();
     99        void keyOff();
     100        void frequency(int freq);
     101        int nextTick(int rate, int phaseShift);
     102};
     103
     104class Voice2612 {
     105protected:
     106        enum { _numOfOperators = 4 };
     107        Operator2612 *_opr;
     108        int _rate;
     109        int _velocity;
     110        int _control7;
     111        int _note;
     112        int _frequencyOffs;
     113        int _frequency;
     114        int _algorithm;
     115
     116public:
     117        Voice2612();
     118        ~Voice2612();
     119        void setControlParameter(int control, int value);
     120        void setInstrument(byte const *instrument);
     121        void rate(int r) { _rate = r;}
     122        void velocity(int velo);
     123        void nextTick(int *outbuf, int buflen);
     124        void noteOn(int n, int onVelo);
     125        bool noteOff(int note);
     126        void pitchBend(int value);
     127        void recalculateFrequency();
     128};
     129
     130class MidiChannel_YM2612 : public MidiChannel {
     131protected:
     132        Voice2612 *_voice;
     133
     134public:
     135        MidiChannel_YM2612();
     136        virtual ~MidiChannel_YM2612();
     137
     138        // MidiChannel interface
     139        MidiDriver *device() { return 0; }
     140        byte getNumber() { return 0; }
     141        void release() { }
     142        void send(uint32 b) { }
     143        void noteOff(byte note);
     144        void noteOn(byte note, byte onVelo);
     145        void programChange(byte program) { }
     146        void pitchBend(int16 value);
     147        void controlChange(byte control, byte value);
     148        void pitchBendFactor(byte value) { }
     149        void sysEx_customInstrument(uint32 type, byte *instr);
     150
     151        void nextTick(int *outbuf, int buflen);
     152        void rate(int r);
     153};
     154
     155class MidiDriver_YM2612 : public MidiDriver {
     156protected:
     157        MidiChannel_YM2612 *_channel[16];
     158        int _volume;
     159        int _rate;
     160
     161        bool _isOpen;
     162        SoundMixer *_mixer;
     163        typedef void TimerCallback(void *);
     164        TimerCallback *_timer_proc;
     165        void *_timer_param;
     166        int _next_tick;
     167        int _samples_per_tick;
     168
     169protected:
     170        static void createLookupTables();
     171        void nextTick(int16 *buf1, int buflen);
     172        int volume(int val = -1) { if (val >= 0) _volume = val; return _volume; }
     173        void rate(int r);
     174
     175        void generate_samples(int16 *buf, int len);
     176        static void premix_proc(void *param, int16 *buf, uint len);
     177
     178public:
     179        MidiDriver_YM2612(SoundMixer *mixer);
     180        virtual ~MidiDriver_YM2612();
     181
     182        int open();
     183        void close();
     184        void send(uint32 b);
     185        void send(byte channel, uint32 b); // Supports higher than channel 15
     186        uint32 property(int prop, uint32 param) { return 0; }
     187
     188        void setPitchBendRange(byte channel, uint range) { }
     189        void sysEx(byte *msg, uint16 length);
     190
     191        void setTimerCallback(void *timer_param, void (*timer_proc)(void *));
     192        uint32 getBaseTempo() { return 1000000 / BASE_FREQ; }
     193
     194        MidiChannel *allocateChannel() { return 0; }
     195        MidiChannel *getPercussionChannel() { return 0; }
     196};
     197
     198////////////////////////////////////////
     199//
     200// Operator2612 implementation
     201//
     202////////////////////////////////////////
     203
     204Operator2612::Operator2612() {
     205        _state = _s_ready;
     206        _currentLevel = ((int64)0x7f << 31);
     207        _phase = 0;
     208        _lastOutput = 0;
     209        _feedbackLevel = 0;
     210        _detune = 0;
     211        _multiple = 1;
     212        _specifiedTotalLevel = 127;
     213        _keyScale = 0;
     214        _specifiedAttackRate = 0;
     215        _specifiedDecayRate = 0;
     216        _specifiedSustainRate = 0;
     217        _specifiedReleaseRate = 15;
     218        velocity(0);
     219}
     220
     221Operator2612::~Operator2612()
     222{ }
     223
     224void Operator2612::velocity(int velo) {
     225        _velocity = velo;
     226        _totalLevel = (((int64)_specifiedTotalLevel << 31) +
     227                      ((int64)(127-_velocity) << 29));
     228        _sustainLevel = ((int64)_specifiedSustainLevel << (31+2));
     229}
     230
     231void Operator2612::feedbackLevel(int level) {
     232        _feedbackLevel = level;
     233}
     234
     235void Operator2612::setInstrument(byte const *instrument) {
     236        _detune = (instrument[8] >> 4) & 7;
     237        _multiple = instrument[8] & 15;
     238        _specifiedTotalLevel = instrument[12] & 127;
     239        _keyScale = (instrument[16] >> 6) & 3;
     240        _specifiedAttackRate = instrument[16] & 31;
     241        _specifiedDecayRate = instrument[20] & 31;
     242        _specifiedSustainRate = instrument[24] & 31;
     243        _specifiedSustainLevel = (instrument[28] >> 4) & 15;
     244        _specifiedReleaseRate = instrument[28] & 15;
     245        _state = _s_ready; // ËÜʪ¤Ç¤Ï¤É¤¦¤Ê¤Î¤«¤Ê?
     246        velocity(_velocity);
     247}
     248
     249void Operator2612::keyOn() {
     250        _state = _s_attacking;
     251        _tickCount = 0;
     252        _phase = 0;                     // ¤É¤¦¤â¡¢¼ÂºÝ¤³¤¦¤é¤·¤¤
     253        _currentLevel = ((int64)0x7f << 31); // ¤³¤ì¤â¡¢¼ÂºÝ¤³¤¦¤é¤·¤¤
     254}
     255
     256void Operator2612::keyOff() {
     257        if (_state != _s_ready)
     258                _state = _s_releasing;
     259}
     260
     261void Operator2612::frequency(int freq) {
     262        int r;
     263
     264        _frequency = freq;
     265
     266        r = _specifiedAttackRate;
     267        if (r != 0) {
     268                r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
     269                if (r >= 64)
     270                r = 63; // ¤¹¤ë¤Ù¤­¤Ê¤ó¤À¤í¤¦¤È¤Ï»×¤¦¤ó¤À¤±¤É (ÀÖp.207)
     271        }
     272#if 0
     273        _attackRate = 0x80;
     274        _attackRate *= powtbl[(r&3) << 7];
     275        _attackRate <<= 16 + (r >> 2);
     276        _attackRate >>= 1;
     277        _attackRate /= 9;  // r == 4 ¤Î¤È¤­¡¢0-96db ¤¬ 8970.24ms
     278        //_attackRate /= 4;  // r == 4 ¤Î¤È¤­¡¢0-96db ¤¬ 8970.24ms
     279#else
     280        {
     281                r = 63 - r;
     282                int64 t;
     283                if (_specifiedTotalLevel >= 128)
     284                        t = 0;
     285                else {
     286                        t = powtbl[(r&3) << 7];
     287                        t <<= (r >> 2);
     288                        t *= 41;                        // r == 20 ¤Î¤È¤­¡¢0-96[db] ¤¬ 10.01[ms] == 41.00096
     289                        t >>= (15 + 5);
     290                        t *= 127 - _specifiedTotalLevel;
     291                        t /= 127;
     292                }
     293                _attackTime = t;                // 1 ÉÃ == (1 << 12)
     294        }
     295#endif
     296
     297        r = _specifiedDecayRate;
     298        if (r != 0) {
     299                r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
     300                if (r >= 64)
     301                        r = 63;
     302        }
     303        _decayRate = 0x80;
     304        _decayRate *= powtbl[(r&3) << 7];
     305        _decayRate <<= 16 + (r >> 2);
     306        _decayRate >>= 1;
     307        _decayRate /= 124;      // r == 4 ¤Î¤È¤­¡¢0-96db ¤¬ 123985.92ms
     308
     309        r = _specifiedSustainRate;
     310        if (r != 0) {
     311                r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
     312                if (r >= 64)
     313                        r = 63;
     314        }
     315        _sustainRate = 0x80;
     316        _sustainRate *= powtbl[(r&3) << 7];
     317        _sustainRate <<= 16 + (r >> 2);
     318        _sustainRate >>= 1;
     319        _sustainRate /= 124;
     320
     321        r = _specifiedReleaseRate;
     322        if (r != 0) {
     323                r = r * 2 + 1;          // ¤³¤Î¥¿¥¤¥ß¥ó¥°¤ÇÎɤ¤¤Î¤«¤ï¤«¤é¤ó
     324                r = r * 2 + (keyscaleTable[freq/262205] >> (3-_keyScale));
     325                // KS ¤Ë¤è¤ëÊäÀµ¤Ï¤¢¤ë¤é¤·¤¤¡£ÀÖp.206 ¤Ç¤Ïµ­½Ò¤µ¤ì¤Æ¤Ê¤¤¤±¤É¡£
     326                if (r >= 64)
     327                        r = 63;
     328        }
     329        _releaseRate = 0x80;
     330        _releaseRate *= powtbl[(r&3) << 7];
     331        _releaseRate <<= 16 + (r >> 2);
     332        _releaseRate >>= 1;
     333        _releaseRate /= 124;
     334}
     335
     336int Operator2612::nextTick(int rate, int phaseShift) {
     337        // sampling ¤Ò¤È¤Äʬ¿Ê¤á¤ë
     338        switch (_state) {
     339        case _s_ready:
     340                return 0;
     341                break;
     342        case _s_attacking:
     343                ++_tickCount;
     344                if (_attackTime <= 0) {
     345                        _currentLevel = 0;
     346                        _state = _s_decaying;
     347                } else {
     348                        int i = ((int64)_tickCount << (12+10)) / ((int64)rate * _attackTime);
     349                        if (i >= 1024) {
     350                                _currentLevel = 0;
     351                                _state = _s_decaying;
     352                        } else {
     353                                _currentLevel = attackOut[i];
     354                                _currentLevel <<= 31 - 8;
     355                        }
     356                }
     357                break;
     358        case _s_decaying:
     359                _currentLevel += _decayRate / rate;
     360                if (_currentLevel >= _sustainLevel) {
     361                        _currentLevel = _sustainLevel;
     362                        _state = _s_sustaining;
     363                }
     364                break;
     365        case _s_sustaining:
     366                _currentLevel += _sustainRate / rate;
     367                if (_currentLevel >= ((int64)0x7f << 31)) {
     368                        _currentLevel = ((int64)0x7f << 31);
     369                        _state = _s_ready;
     370                }
     371                break;
     372        case _s_releasing:
     373                _currentLevel += _releaseRate / rate;
     374                if (_currentLevel >= ((int64)0x7f << 31)) {
     375                        _currentLevel = ((int64)0x7f << 31);
     376                        _state = _s_ready;
     377                }
     378                break;
     379        default:
     380                // ¤³¤³¤Ë¤ÏÍè¤Ê¤¤¤Ï¤º
     381                break;
     382        };
     383
     384        int64 level = _currentLevel + _totalLevel;
     385        int64 output = 0;
     386        if (level < ((int64)0x7f << 31)) {
     387                int const feedback[] = {
     388                        0,
     389                        0x400 / 16,
     390                        0x400 / 8,
     391                        0x400 / 4,
     392                        0x400 / 2,
     393                        0x400,
     394                        0x400 * 2,
     395                        0x400 * 4,
     396                };
     397
     398                _phase &= 0x3ffff;
     399                phaseShift >>= 2;               // Àµ¤·¤¤ÊÑÄ´Î̤Ï?  3 ¤¸¤ã¾®¤µ¤¹¤®¤Ç 2 ¤¸¤ãÂ礭¤¤¤è¤¦¤Ê¡£
     400                phaseShift += (((int64)(_lastOutput) * feedback[_feedbackLevel]) >> 16); // Àµ¤·¤¤ÊÑÄ´Î̤Ï?  16¤«¤é17¤Î´Ö¤Î¤è¤¦¤À¤±¤É¡£
     401                output = sintbl[((_phase >> 7) + phaseShift) & 0x7ff];
     402                output >>= (level >> 34);       // Àµ¤·¤¤¸º¿êÎ̤Ï?
     403                output *= powtbl[511 - ((level>>25)&511)];
     404                output >>= 16;
     405                output >>= 1;
     406
     407                if (_multiple > 0)
     408                        _phase += (_frequency * _multiple) / rate;
     409                else
     410                        _phase += _frequency / (rate << 1);
     411        }
     412
     413        _lastOutput = output;
     414        return output;
     415}
     416
     417////////////////////////////////////////
     418//
     419// Voice2612 implementation
     420//
     421////////////////////////////////////////
     422
     423Voice2612::Voice2612() {
     424        _control7 = 127;
     425        _note = 40;
     426        _frequency = 440;
     427        _frequencyOffs = 0x2000;
     428        _algorithm = 7;
     429        _opr = new Operator2612[_numOfOperators];
     430        velocity(0);
     431}
     432
     433Voice2612::~Voice2612() {
     434        delete [] _opr;
     435}
     436
     437void Voice2612::velocity(int velo) {
     438        _velocity = velo;
     439#if 0
     440        int v = (velo * _control7) >> 7; // ¤³¤ì¤À¤ÈÀºÅÙÎɤ¯¤Ê¤¤¤Ç¤¹¤Í
     441#else
     442        int v = velo + (_control7 - 127) * 4;
     443#endif
     444        bool iscarrier[8][4] = {
     445                { false, false, false,  true, }, //0
     446                { false, false, false,  true, }, //1
     447                { false, false, false,  true, }, //2
     448                { false, false, false,  true, }, //3
     449                { false,  true, false,  true, }, //4
     450                { false,  true,  true,  true, }, //5
     451                { false,  true,  true,  true, }, //6
     452                {  true,  true,  true,  true, }, //7
     453        };
     454        int opr;
     455        for (opr = 0; opr < 4; opr++)
     456                if (iscarrier[_algorithm][opr])
     457                        _opr[opr].velocity(v);
     458                else
     459                        _opr[opr].velocity(127);
     460}
     461
     462void Voice2612::setControlParameter(int control, int value) {
     463        switch (control) {
     464        case 7:
     465                _control7 = value;
     466                velocity(_velocity);
     467                break;
     468        case 123:
     469                // All notes off
     470                noteOff(_note);
     471        };
     472}
     473
     474void Voice2612::setInstrument(byte const *instrument) {
     475        if (instrument == NULL)
     476                return;
     477
     478        _algorithm = instrument[32] & 7;
     479        _opr[0].feedbackLevel((instrument[32] >> 3) & 7);
     480        _opr[1].feedbackLevel(0);
     481        _opr[2].feedbackLevel(0);
     482        _opr[3].feedbackLevel(0);
     483        _opr[0].setInstrument(instrument + 0);
     484        _opr[1].setInstrument(instrument + 2);
     485        _opr[2].setInstrument(instrument + 1);
     486        _opr[3].setInstrument(instrument + 3);
     487}
     488
     489void Voice2612::nextTick(int *outbuf, int buflen) {
     490        if (_velocity == 0)
     491                return;
     492
     493        int i;
     494        for (i = 0; i < buflen; ++i) {
     495                int d = 0;
     496                int d1, d2, d3, d4;
     497                switch (_algorithm) {
     498                case 0:
     499                        d1 = _opr[0].nextTick(_rate, 0);
     500                        d2 = _opr[1].nextTick(_rate, d1);
     501                        d3 = _opr[2].nextTick(_rate, d2);
     502                        d4 = _opr[3].nextTick(_rate, d3);
     503                        d = d4;
     504                        break;
     505                case 1:
     506                        d1 = _opr[0].nextTick(_rate, 0);
     507                        d2 = _opr[1].nextTick(_rate, 0);
     508                        d3 = _opr[2].nextTick(_rate, d1+d2);
     509                        d4 = _opr[3].nextTick(_rate, d3);
     510                        d = d4;
     511                        break;
     512                case 2:
     513                        d1 = _opr[0].nextTick(_rate, 0);
     514                        d2 = _opr[1].nextTick(_rate, 0);
     515                        d3 = _opr[2].nextTick(_rate, d2);
     516                        d4 = _opr[3].nextTick(_rate, d1+d3);
     517                        d = d4;
     518                        break;
     519                case 3:
     520                        d1 = _opr[0].nextTick(_rate, 0);
     521                        d2 = _opr[1].nextTick(_rate, d1);
     522                        d3 = _opr[2].nextTick(_rate, 0);
     523                        d4 = _opr[3].nextTick(_rate, d2+d3);
     524                        d = d4;
     525                        break;
     526                case 4:
     527                        d1 = _opr[0].nextTick(_rate, 0);
     528                        d2 = _opr[1].nextTick(_rate, d1);
     529                        d3 = _opr[2].nextTick(_rate, 0);
     530                        d4 = _opr[3].nextTick(_rate, d3);
     531                        d = d2 + d4;
     532                        break;
     533                case 5:
     534                        d1 = _opr[0].nextTick(_rate, 0);
     535                        d2 = _opr[1].nextTick(_rate, d1);
     536                        d3 = _opr[2].nextTick(_rate, d1);
     537                        d4 = _opr[3].nextTick(_rate, d1);
     538                        d = d2 + d3 + d4;
     539                        break;
     540                case 6:
     541                        d1 = _opr[0].nextTick(_rate, 0);
     542                        d2 = _opr[1].nextTick(_rate, d1);
     543                        d3 = _opr[2].nextTick(_rate, 0);
     544                        d4 = _opr[3].nextTick(_rate, 0);
     545                        d = d2 + d3 + d4;
     546                        break;
     547                case 7:
     548                        d1 = _opr[0].nextTick(_rate, 0);
     549                        d2 = _opr[1].nextTick(_rate, 0);
     550                        d3 = _opr[2].nextTick(_rate, 0);
     551                        d4 = _opr[3].nextTick(_rate, 0);
     552                        d = d1 + d2 + d3 + d4;
     553                        break;
     554                default:
     555                        break;
     556                };
     557
     558                outbuf[i] += d;
     559        }
     560}
     561
     562void Voice2612::noteOn(int n, int onVelo) {
     563        _note = n;
     564        velocity(onVelo);
     565        recalculateFrequency();
     566        int i;
     567        for (i = 0; i < _numOfOperators; i++)
     568                _opr[i].keyOn();
     569}
     570
     571bool Voice2612::noteOff(int note) {
     572        if (_note != note)
     573                return false;
     574        int i;
     575        for (i = 0; i < _numOfOperators; i++)
     576                _opr[i].keyOff();
     577        return true;
     578}
     579
     580void Voice2612::pitchBend(int value) {
     581        _frequencyOffs = value;
     582        recalculateFrequency();
     583}
     584
     585void Voice2612::recalculateFrequency() {
     586        // MIDI ¤È¤â°ã¤¦¤·....
     587        // ¤É¤¦¤¤¤¦»ÅÍͤʤó¤À¤í¤¦¤«?
     588        // ¤È»×¤Ã¤¿¤é¡¢¤Ê¤ó¤È¡¢¤³¤ì (¢­) ¤¬Àµ²ò¤é¤·¤¤¡£
     589        int64 basefreq = frequencyTable[_note];
     590        int cfreq = frequencyTable[_note - (_note % 12)];
     591        int oct = _note / 12;
     592        int fnum = (basefreq << 13) / cfreq; // OPL ¤Î fnum ¤ÈƱ¤¸¤è¤¦¤Ê¤â¤Î¡£
     593        fnum += _frequencyOffs - 0x2000;
     594        if (fnum < 0x2000) {
     595                fnum += 0x2000;
     596                oct--;
     597        }
     598        if (fnum >= 0x4000) {
     599                fnum -= 0x2000;
     600                oct++;
     601        }
     602
     603        // _frequency ¤ÏºÇ½ªÅª¤Ë¥Ð¥¤¥¢¥¹ 256*1024 ÇÜ
     604        _frequency = (frequencyTable[oct*12] * (int64)fnum) >> (13 - 10);
     605
     606        int i;
     607        for (i = 0; i < _numOfOperators; i++)
     608                _opr[i].frequency(_frequency);
     609}
     610
     611////////////////////////////////////////
     612//
     613// MidiChannel_YM2612
     614//
     615////////////////////////////////////////
     616
     617MidiChannel_YM2612::MidiChannel_YM2612() {
     618        _voice = new Voice2612;
     619}
     620
     621MidiChannel_YM2612::~MidiChannel_YM2612() {
     622        delete _voice;
     623}
     624
     625void MidiChannel_YM2612::noteOn(byte note, byte onVelo) {
     626        _voice->noteOn(note, onVelo);
     627}
     628
     629void MidiChannel_YM2612::noteOff(byte note) {
     630        _voice->noteOff(note);
     631}
     632
     633void MidiChannel_YM2612::controlChange(byte control, byte value) {
     634  // ¤¤¤¤¤Î¤«¤³¤ì¤Ç?
     635        _voice->setControlParameter(control, value);
     636}
     637
     638void MidiChannel_YM2612::sysEx_customInstrument(uint32 type, byte *fmInst) {
     639        if (type == 'EUP ')
     640                _voice->setInstrument(fmInst);
     641}
     642
     643void MidiChannel_YM2612::pitchBend(int16 value) {
     644  // ¤¤¤¤¤Î¤«¤³¤ì¤Ç?
     645        _voice->pitchBend(value);
     646}
     647
     648void MidiChannel_YM2612::nextTick(int *outbuf, int buflen) {
     649        _voice->nextTick(outbuf, buflen);
     650}
     651
     652void MidiChannel_YM2612::rate(int r) {
     653        _voice->rate(r);
     654}
     655
     656////////////////////////////////////////
     657//
     658// MidiDriver_YM2612
     659//
     660////////////////////////////////////////
     661
     662MidiDriver_YM2612::MidiDriver_YM2612(SoundMixer *mixer) :
     663_mixer(mixer)
     664{
     665        _isOpen = false;
     666        _timer_proc = 0;
     667        _timer_param = 0;
     668        _next_tick = 0;
     669        _samples_per_tick = (_mixer->getOutputRate() << FIXP_SHIFT) / BASE_FREQ;
     670
     671        createLookupTables();
     672        _volume = 256;
     673        int i;
     674        for (i = 0; i < ARRAYSIZE(_channel); i++)
     675                _channel[i] = new MidiChannel_YM2612;
     676        rate(_mixer->getOutputRate());
     677}
     678
     679MidiDriver_YM2612::~MidiDriver_YM2612() {
     680        int i;
     681        for (i = 0; i < ARRAYSIZE(_channel); i++)
     682                delete _channel[i];
     683        delete sintbl;
     684        delete powtbl;
     685        delete frequencyTable;
     686        delete keycodeTable;
     687        delete keyscaleTable;
     688        delete attackOut;
     689        sintbl = powtbl = frequencyTable = keycodeTable = keyscaleTable = attackOut = 0;
     690}
     691
     692int MidiDriver_YM2612::open() {
     693        if (_isOpen)
     694                return MERR_ALREADY_OPEN;
     695        _mixer->setupPremix(premix_proc, this);
     696        _isOpen = true;
    30697        return 0;
     698}
     699
     700void MidiDriver_YM2612::close() {
     701        if (!_isOpen)
     702                return;
     703        _isOpen = false;
     704
     705        // Detach the premix callback handler
     706        _mixer->setupPremix(0, 0);
     707}
     708
     709void MidiDriver_YM2612::setTimerCallback(void *timer_param, void (*timer_proc)(void *)) {
     710        _timer_proc = (TimerCallback *) timer_proc;
     711        _timer_param = timer_param;
     712}
     713
     714void MidiDriver_YM2612::send(uint32 b) {
     715        send(b & 0xF, b & 0xFFFFFFF0);
     716}
     717
     718void MidiDriver_YM2612::send(byte chan, uint32 b) {
     719        //byte param3 = (byte) ((b >> 24) & 0xFF);
     720        byte param2 = (byte) ((b >> 16) & 0xFF);
     721        byte param1 = (byte) ((b >>  8) & 0xFF);
     722        byte cmd    = (byte) (b & 0xF0);
     723        if (chan > ARRAYSIZE(_channel))
     724                return;
     725
     726        switch (cmd) {
     727        case 0x80:// Note Off
     728                _channel[chan]->noteOff(param1);
     729                break;
     730        case 0x90: // Note On
     731                _channel[chan]->noteOn(param1, param2);
     732                break;
     733        case 0xA0: // Aftertouch
     734                break; // Not supported.
     735        case 0xB0: // Control Change
     736                _channel[chan]->controlChange(param1, param2);
     737                break;
     738        case 0xC0: // Program Change
     739                _channel[chan]->programChange(param1);
     740                break;
     741        case 0xD0: // Channel Pressure
     742                break; // Not supported.
     743        case 0xE0: // Pitch Bend
     744                _channel[chan]->pitchBend((param1 | (param2 << 7)) - 0x2000);
     745                break;
     746        case 0xF0: // SysEx
     747                // We should never get here! SysEx information has to be
     748                // sent via high-level semantic methods.
     749                warning("MidiDriver_YM2612: Receiving SysEx command on a send() call");
     750                break;
     751
     752        default:
     753                warning("MidiDriver_YM2612: Unknown send() command 0x%02X", cmd);
     754        }
     755}
     756
     757void MidiDriver_YM2612::sysEx(byte *msg, uint16 length) {
     758        if (msg[0] != 0x7C || msg[1] >= ARRAYSIZE(_channel))
     759                return;
     760        _channel[msg[1]]->sysEx_customInstrument('EUP ', &msg[2]);
     761}
     762
     763void MidiDriver_YM2612::premix_proc(void *param, int16 *buf, uint len) {
     764        ((MidiDriver_YM2612 *) param)->generate_samples(buf, len);
     765}
     766
     767void MidiDriver_YM2612::generate_samples(int16 *data, int len) {
     768        int step;
     769
     770        int16 *origData = data;
     771        uint origLen = len;
     772
     773        do {
     774                step = len;
     775                if (step > (_next_tick >> FIXP_SHIFT))
     776                        step = (_next_tick >> FIXP_SHIFT);
     777                nextTick(data, step);
     778
     779                _next_tick -= step << FIXP_SHIFT;
     780                if (!(_next_tick >> FIXP_SHIFT)) {
     781                        if (_timer_proc)
     782                                (*_timer_proc)(_timer_param);
     783                        _next_tick += _samples_per_tick;
     784                }
     785                data += step * 2; // Stereo means * 2
     786                len -= step;
     787        } while (len);
     788}
     789
     790void MidiDriver_YM2612::nextTick(int16 *buf1, int buflen) {
     791        int *buf0 = new int [buflen];
     792        memset(buf0, 0, sizeof(buf0[0]) * buflen);
     793
     794        int i;
     795        for (i = 0; i < ARRAYSIZE(_channel); i++)
     796                _channel[i]->nextTick(buf0, buflen);
     797
     798        for (i = 0; i < buflen; ++i)
     799                buf1[i*2+1] = buf1[i*2] = ((buf0[i] * volume()) >> 10) & 0xffff;
     800        delete [] buf0;
     801}
     802
     803void MidiDriver_YM2612::rate(int r)
     804{
     805        _rate = r;
     806        int i;
     807        for (i = 0; i < ARRAYSIZE(_channel); i++)
     808                _channel[i]->rate(r);
     809}
     810
     811#define M_PI 3.14159265358979323846
     812void MidiDriver_YM2612::createLookupTables() {
     813        {
     814                int i;
     815                sintbl = new int [2048];
     816                for (i = 0; i < 2048; i++)
     817                        sintbl[i] = (int)(0xffff * sin(i/2048.0*2.0*M_PI));
     818        }
     819
     820        {
     821                int i;
     822                powtbl = new int [1025];
     823                for (i = 0; i <= 1024; i++)
     824                        powtbl[i] = (int)(0x10000 * pow(2.0, (i-512)/512.0));
     825        }
     826
     827        {
     828                int i;
     829                int block;
     830
     831                int const fnum[] = {
     832                        0x026a, 0x028f, 0x02b6, 0x02df,
     833                        0x030b, 0x0339, 0x036a, 0x039e,
     834                        0x03d5, 0x0410, 0x044e, 0x048f,
     835                };
     836
     837                // (int)(880.0 * 256.0 * pow(2.0, (note-0x51)/12.0)); // ¥Ð¥¤¥¢¥¹ 256 ÇÜ
     838                // 0x45 ¤¬ 440Hz (a4)¡¢0x51 ¤¬ 880Hz (a5) ¤é¤·¤¤
     839                frequencyTable = new int [120];
     840                for (block = -1; block < 9; block++) {
     841                        for (i = 0; i < 12; i++) {
     842                                double freq = fnum[i] * (166400.0 / 3) * pow(2.0, block-21);
     843                                frequencyTable[(block+1)*12+i] = (int)(256.0 * freq);
     844                        }
     845                }
     846
     847                keycodeTable = new int [120];
     848                // detune Î̤η׻»¤ä KS ¤Ë¤è¤ë rate ÊÑ´¹¤Ë»È¤¦¤ó¤¸¤ã¤Ê¤¤¤«¤Ê
     849                for (block = -1; block < 9; block++) {
     850                        for (i = 0; i < 12; i++) {
     851                                // see p.204
     852                                int  f8 = (fnum[i] >>  7) & 1;
     853                                int  f9 = (fnum[i] >>  8) & 1;
     854                                int f10 = (fnum[i] >>  9) & 1;
     855                                int f11 = (fnum[i] >> 10) & 1;
     856                                int  n4 = f11;
     857                                int  n3 = f11&(f10|f9|f8) | (~f11&f10&f9&f8);
     858                                int note = n4*2 + n3;
     859                                // see p.207
     860                                keycodeTable[(block+1)*12+i] = block*4 + note;
     861                        }
     862                }
     863        }
     864
     865        {
     866                int freq;
     867                keyscaleTable = new int [8192];
     868                keyscaleTable[0] = 0;
     869                for (freq = 1; freq < 8192; freq++) {
     870                        keyscaleTable[freq] = (int)(log((double)freq) / 9.03 * 32.0) - 1;
     871                        // 8368[Hz] (o9c) ¤Ç 32¤¯¤é¤¤¡£9.03 =:= ln 8368
     872                }
     873        }
     874
     875        {
     876                int i;
     877                attackOut = new int [1024];
     878                for (i = 0; i < 1024; i++)
     879                        attackOut[i] = (int)(((0x7fff+0x03a5)*30.0) / (30.0+i)) - 0x03a5;
     880        }
     881}
     882
     883////////////////////////////////////////
     884//
     885// MidiDriver_YM2612 factory
     886//
     887////////////////////////////////////////
     888
     889MidiDriver *MidiDriver_YM2612_create(SoundMixer *mixer) {
     890        return new MidiDriver_YM2612(mixer);
    31891}