Ticket #9058: opl-experiment.diff

File opl-experiment.diff, 15.7 KB (added by eriktorbjorn, 15 years ago)

Patch against current SVN trunk

  • sound/softsynth/adlib.cpp

     
    6060        AdlibInstrument() { memset(this, 0, sizeof(AdlibInstrument)); }
    6161};
    6262
     63class AdlibSoundcard {
     64private:
     65        FM_OPL *_opl;
     66        byte *_adlib_reg_cache;
     67        uint16 channel_table_2[9];
     68        uint16 curnote_table[9];
     69
     70        byte adlib_get_reg_value(byte reg) {
     71                return _adlib_reg_cache[reg];
     72        }
     73
     74public:
     75        AdlibSoundcard(int rate);
     76        ~AdlibSoundcard();
     77
     78        void adlib_key_off(int chan);
     79        void adlib_note_on(int chan, byte note, int mod);
     80        void adlib_note_on_ex(int chan, byte note, int mod);
     81        int adlib_get_reg_value_param(int chan, byte param);
     82        void adlib_setup_channel(int chan, AdlibInstrument *instr, byte vol_1, byte vol_2);
     83        void adlib_set_param(int channel, byte param, int value);
     84        void adlib_key_onoff(int channel);
     85        void adlib_write(byte reg, byte value);
     86        void adlib_playnote(int channel, int note);
     87
     88        void generateSamples(int16 *data, int len);
     89};
     90
    6391class AdlibPart : public MidiChannel {
    6492        friend class MidiDriver_ADLIB;
    6593
     
    575603        int getRate() const { return _mixer->getOutputRate(); }
    576604
    577605private:
     606        int16 *_sampleBuffer;
     607        int _sampleBufferLen;
     608
    578609        bool _scummSmallHeader; // FIXME: This flag controls a special mode for SCUMM V3 games
    579610
    580         FM_OPL *_opl;
    581         byte *_adlib_reg_cache;
     611        int _numCards;
     612        AdlibSoundcard *_cards[2];
    582613
    583614        int _adlib_timer_counter;
    584615
    585         uint16 channel_table_2[9];
    586616        int _voice_index;
    587617        int _timer_p;
    588618        int _timer_q;
    589         uint16 curnote_table[9];
    590         AdlibVoice _voices[9];
     619
     620        int _numVoices;
     621        AdlibVoice *_voices;
    591622        AdlibPart _parts[32];
    592623        AdlibPercussionChannel _percussion;
    593624
     
    601632        void adlib_note_on_ex(int chan, byte note, int mod);
    602633        int adlib_get_reg_value_param(int chan, byte data);
    603634        void adlib_setup_channel(int chan, AdlibInstrument * instr, byte vol_1, byte vol_2);
    604         byte adlib_get_reg_value(byte reg) {
    605                 return _adlib_reg_cache[reg];
    606         }
    607635        void adlib_set_param(int channel, byte param, int value);
    608636        void adlib_key_onoff(int channel);
    609         void adlib_write(byte reg, byte value);
    610         void adlib_playnote(int channel, int note);
    611637
    612638        AdlibVoice *allocate_voice(byte pri);
    613639
     
    625651        void mc_key_on(AdlibVoice *voice, AdlibInstrument *instr, byte note, byte velocity);
    626652};
    627653
     654// An emulated Adlib sound card
     655
     656AdlibSoundcard::AdlibSoundcard(int rate) {
     657        _opl = makeAdlibOPL(rate);
     658
     659        _adlib_reg_cache = (byte *)calloc(256, 1);
     660
     661        for (int i = 0; i < ARRAYSIZE(curnote_table); ++i) {
     662                curnote_table[i] = 0;
     663        }
     664
     665        adlib_write(1, 0x20);
     666        adlib_write(8, 0x40);
     667        adlib_write(0xBD, 0x00);
     668}
     669
     670AdlibSoundcard::~AdlibSoundcard() {
     671        OPLDestroy(_opl);
     672        free(_adlib_reg_cache);
     673}
     674
     675void AdlibSoundcard::adlib_key_off(int chan) {
     676        byte reg = chan + 0xB0;
     677        adlib_write(reg, adlib_get_reg_value(reg) & ~0x20);
     678}
     679
     680void AdlibSoundcard::adlib_note_on(int chan, byte note, int mod) {
     681        int code;
     682        assert(chan >= 0 && chan < 9);
     683        code = (note << 7) + mod;
     684        curnote_table[chan] = code;
     685        adlib_playnote(chan, (int16)channel_table_2[chan] + code);
     686}
     687
     688void AdlibSoundcard::adlib_note_on_ex(int channel, byte note, int mod) {
     689        int code;
     690        assert(channel >= 0 && channel < 9);
     691        code = (note << 7) + mod;
     692        curnote_table[channel] = code;
     693        channel_table_2[channel] = 0;
     694        adlib_playnote(channel, code);
     695}
     696
     697int AdlibSoundcard::adlib_get_reg_value_param(int chan, byte param) {
     698        const AdlibSetParams *as;
     699        byte val;
     700        byte channel;
     701
     702        assert(chan >= 0 && chan < 9);
     703
     704        if (param <= 12) {
     705                channel = channel_mappings_2[chan];
     706        } else if (param <= 25) {
     707                param -= 13;
     708                channel = channel_mappings[chan];
     709        } else if (param <= 27) {
     710                param -= 13;
     711                channel = chan;
     712        } else if (param == 28) {
     713                return 0xF;
     714        } else if (param == 29) {
     715                return 0x17F;
     716        } else {
     717                return 0;
     718        }
     719
     720        as = &adlib_setparam_table[param];
     721        val = adlib_get_reg_value(channel + as->a);
     722        val &= as->c;
     723        val >>= as->b;
     724        if (as->d)
     725                val = as->d - val;
     726
     727        return val;
     728}
     729
     730void AdlibSoundcard::adlib_setup_channel(int chan, AdlibInstrument *instr, byte vol_1, byte vol_2) {
     731        byte channel;
     732
     733        assert(chan >= 0 && chan < 9);
     734
     735        channel = channel_mappings[chan];
     736        adlib_write(channel + 0x20, instr->mod_characteristic);
     737        adlib_write(channel + 0x40, (instr->mod_scalingOutputLevel | 0x3F) - vol_1 );
     738        adlib_write(channel + 0x60, 0xff & (~instr->mod_attackDecay));
     739        adlib_write(channel + 0x80, 0xff & (~instr->mod_sustainRelease));
     740        adlib_write(channel + 0xE0, instr->mod_waveformSelect);
     741
     742        channel = channel_mappings_2[chan];
     743        adlib_write(channel + 0x20, instr->car_characteristic);
     744        adlib_write(channel + 0x40, (instr->car_scalingOutputLevel | 0x3F) - vol_2 );
     745        adlib_write(channel + 0x60, 0xff & (~instr->car_attackDecay));
     746        adlib_write(channel + 0x80, 0xff & (~instr->car_sustainRelease));
     747        adlib_write(channel + 0xE0, instr->car_waveformSelect);
     748
     749        adlib_write((byte)chan + 0xC0, instr->feedback);
     750}
     751
     752void AdlibSoundcard::adlib_set_param(int channel, byte param, int value) {
     753        const AdlibSetParams *as;
     754        byte reg;
     755
     756        assert(channel >= 0 && channel < 9);
     757
     758        if (param <= 12) {
     759                reg = channel_mappings_2[channel];
     760        } else if (param <= 25) {
     761                param -= 13;
     762                reg = channel_mappings[channel];
     763        } else if (param <= 27) {
     764                param -= 13;
     765                reg = channel;
     766        } else if (param == 28 || param == 29) {
     767                if (param == 28)
     768                        value -= 15;
     769                else
     770                        value -= 383;
     771                value <<= 4;
     772                channel_table_2[channel] = value;
     773                adlib_playnote(channel, curnote_table[channel] + value);
     774                return;
     775        } else {
     776                return;
     777        }
     778
     779        as = &adlib_setparam_table[param];
     780        if (as->d)
     781                value = as->d - value;
     782        reg += as->a;
     783        adlib_write(reg, (adlib_get_reg_value(reg) & ~as->c) | (((byte)value) << as->b));
     784}
     785
     786void AdlibSoundcard::adlib_key_onoff(int channel) {
     787        byte val;
     788        byte reg = channel + 0xB0;
     789        assert(channel >= 0 && channel < 9);
     790
     791        val = adlib_get_reg_value(reg);
     792        adlib_write(reg, val & ~0x20);
     793        adlib_write(reg, val | 0x20);
     794}
     795
     796void AdlibSoundcard::adlib_write(byte reg, byte value) {
     797        if (_adlib_reg_cache[reg] == value)
     798                return;
     799#ifdef DEBUG_ADLIB
     800        debug(6, "%10d: adlib_write[%x] = %x", tick, reg, value);
     801#endif
     802        _adlib_reg_cache[reg] = value;
     803
     804        OPLWriteReg(_opl, reg, value);
     805}
     806
     807void AdlibSoundcard::adlib_playnote(int channel, int note) {
     808        byte old, oct, notex;
     809        int note2;
     810        int i;
     811
     812        note2 = (note >> 7) - 4;
     813        note2 = (note2 < 128) ? note2 : 0;
     814
     815        oct = (note2 / 12);
     816        if (oct > 7)
     817                oct = 7 << 2;
     818        else
     819                oct <<= 2;
     820        notex = note2 % 12 + 3;
     821
     822        old = adlib_get_reg_value(channel + 0xB0);
     823        if (old & 0x20) {
     824                old &= ~0x20;
     825                if (oct > old) {
     826                        if (notex < 6) {
     827                                notex += 12;
     828                                oct -= 4;
     829                        }
     830                } else if (oct < old) {
     831                        if (notex > 11) {
     832                                notex -= 12;
     833                                oct += 4;
     834                        }
     835                }
     836        }
     837
     838        i = (notex << 3) + ((note >> 4) & 0x7);
     839        adlib_write(channel + 0xA0, note_to_f_num[i]);
     840        adlib_write(channel + 0xB0, oct | 0x20);
     841}
     842
     843void AdlibSoundcard::generateSamples(int16 *data, int len) {   
     844        YM3812UpdateOne(_opl, data, len);
     845}
     846
    628847// MidiChannel method implementations
    629848
    630849void AdlibPart::init(MidiDriver_ADLIB *owner, byte channel) {
     
    8681087
    8691088        _scummSmallHeader = false;
    8701089
    871         _adlib_reg_cache = 0;
    872 
    8731090        _adlib_timer_counter = 0;
    8741091        _voice_index = 0;
    875         for (i = 0; i < ARRAYSIZE(curnote_table); ++i) {
    876                 curnote_table[i] = 0;
    877         }
    8781092
    8791093        for (i = 0; i < ARRAYSIZE(_parts); ++i) {
    8801094                _parts[i].init(this, i + ((i >= 9) ? 1 : 0));
     
    8901104
    8911105        MidiDriver_Emulated::open();
    8921106
     1107        _sampleBuffer = 0;
     1108        _sampleBufferLen = 0;
     1109
    8931110        int i;
    8941111        AdlibVoice *voice;
    8951112
    896         for (i = 0, voice = _voices; i != ARRAYSIZE(_voices); i++, voice++) {
     1113        _numCards = 2;
     1114
     1115        if (_numCards > ARRAYSIZE(_cards))
     1116                _numCards = ARRAYSIZE(_cards);
     1117
     1118        _numVoices = 9 * _numCards;
     1119        _voices = new AdlibVoice[_numVoices];
     1120
     1121        for (i = 0; i < _numCards; i++) {
     1122                _cards[i] = new AdlibSoundcard(getRate());
     1123        }
     1124
     1125        for (i = 0, voice = _voices; i != _numVoices; i++, voice++) {
    8971126                voice->_channel = i;
    8981127                voice->_s11a.s10 = &voice->_s10b;
    8991128                voice->_s11b.s10 = &voice->_s10a;
    9001129        }
    9011130
    902         _adlib_reg_cache = (byte *)calloc(256, 1);
    903 
    904         _opl = makeAdlibOPL(getRate());
    905 
    906         adlib_write(1, 0x20);
    907         adlib_write(8, 0x40);
    908         adlib_write(0xBD, 0x00);
    9091131        create_lookup_table();
    9101132
    9111133        _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true);
     
    9201142
    9211143        _mixer->stopHandle(_mixerSoundHandle);
    9221144
    923         uint i;
    924         for (i = 0; i < ARRAYSIZE(_voices); ++i) {
     1145        int i;
     1146        for (i = 0; i < _numVoices; ++i) {
    9251147                if (_voices[i]._part)
    9261148                        mc_off(&_voices[i]);
    9271149        }
    9281150
    9291151        // Turn off the OPL emulation
    930         OPLDestroy(_opl);
     1152        for (i = 0; i < _numCards; ++i) {
     1153                delete _cards[i];
     1154        }
     1155
     1156        delete[] _voices;
     1157        free(_sampleBuffer);
     1158        _sampleBufferLen = 0;
    9311159//      YM3812Shutdown();
    932 
    933         free(_adlib_reg_cache);
    9341160}
    9351161
    9361162void MidiDriver_ADLIB::send(uint32 b) {
     
    10281254
    10291255// All the code brought over from IMuseAdlib
    10301256
    1031 void MidiDriver_ADLIB::adlib_write(byte reg, byte value) {
    1032         if (_adlib_reg_cache[reg] == value)
    1033                 return;
    1034 #ifdef DEBUG_ADLIB
    1035         debug(6, "%10d: adlib_write[%x] = %x", tick, reg, value);
    1036 #endif
    1037         _adlib_reg_cache[reg] = value;
    1038 
    1039         OPLWriteReg(_opl, reg, value);
    1040 }
    1041 
    10421257void MidiDriver_ADLIB::generateSamples(int16 *data, int len) {
    10431258        memset(data, 0, sizeof(int16) * len);
    1044         YM3812UpdateOne(_opl, data, len);
     1259        if (_numCards == 0) {
     1260                _cards[0]->generateSamples(data, len);
     1261        } else {
     1262                if (len > _sampleBufferLen) {
     1263                        _sampleBufferLen = len;
     1264                        _sampleBuffer = (int16 *)realloc(_sampleBuffer, _sampleBufferLen * sizeof(int16));
     1265                }
     1266                for (int i = 0; i < _numCards; i++) {
     1267                        memset(_sampleBuffer, 0, len);
     1268                        _cards[i]->generateSamples(_sampleBuffer, len);
     1269
     1270                        for (int j = 0; j < len; j++) {
     1271                                int val = data[j] + _sampleBuffer[j];
     1272                                if (val > 0x7fff)
     1273                                        val = 0x7fff;
     1274                                data[j] = val;
     1275                        }
     1276                }
     1277        }
    10451278}
    10461279
    10471280void MidiDriver_ADLIB::onTimer() {
     
    10551288                tick++;
    10561289#endif
    10571290                voice = _voices;
    1058                 for (i = 0; i != ARRAYSIZE(_voices); i++, voice++) {
     1291                for (i = 0; i != _numVoices; i++, voice++) {
    10591292                        if (!voice->_part)
    10601293                                continue;
    10611294                        if (voice->_duration && (voice->_duration -= 0x11) <= 0) {
     
    11331366                adlib_key_onoff(voice->_channel);
    11341367}
    11351368
    1136 void MidiDriver_ADLIB::adlib_key_off(int chan){
    1137         byte reg = chan + 0xB0;
    1138         adlib_write(reg, adlib_get_reg_value(reg) & ~0x20);
     1369void MidiDriver_ADLIB::adlib_key_off(int chan) {
     1370        int card = chan / 9;
     1371        int channel = chan % 9;
     1372
     1373        _cards[card]->adlib_key_off(channel);
    11391374}
    11401375
    11411376byte MidiDriver_ADLIB::struct10_ontimer(Struct10 *s10, Struct11 *s11) {
     
    11821417}
    11831418
    11841419void MidiDriver_ADLIB::adlib_set_param(int channel, byte param, int value) {
    1185         const AdlibSetParams *as;
    1186         byte reg;
     1420        int card = channel / 9;
     1421        int chan = channel % 9;
    11871422
    1188         assert(channel >= 0 && channel < 9);
    1189 
    1190         if (param <= 12) {
    1191                 reg = channel_mappings_2[channel];
    1192         } else if (param <= 25) {
    1193                 param -= 13;
    1194                 reg = channel_mappings[channel];
    1195         } else if (param <= 27) {
    1196                 param -= 13;
    1197                 reg = channel;
    1198         } else if (param == 28 || param == 29) {
    1199                 if (param == 28)
    1200                         value -= 15;
    1201                 else
    1202                         value -= 383;
    1203                 value <<= 4;
    1204                 channel_table_2[channel] = value;
    1205                 adlib_playnote(channel, curnote_table[channel] + value);
    1206                 return;
    1207         } else {
    1208                 return;
    1209         }
    1210 
    1211         as = &adlib_setparam_table[param];
    1212         if (as->d)
    1213                 value = as->d - value;
    1214         reg += as->a;
    1215         adlib_write(reg, (adlib_get_reg_value(reg) & ~as->c) | (((byte)value) << as->b));
     1423        _cards[card]->adlib_set_param(chan, param, value);
    12161424}
    12171425
    12181426void MidiDriver_ADLIB::adlib_key_onoff(int channel) {
    1219         byte val;
    1220         byte reg = channel + 0xB0;
    1221         assert(channel >= 0 && channel < 9);
     1427        int card = channel / 9;
     1428        int chan = channel % 9;
    12221429
    1223         val = adlib_get_reg_value(reg);
    1224         adlib_write(reg, val & ~0x20);
    1225         adlib_write(reg, val | 0x20);
     1430        _cards[card]->adlib_key_onoff(chan);
    12261431}
    12271432
    12281433void MidiDriver_ADLIB::struct10_setup(Struct10 *s10) {
     
    12741479        s10->speed_lo_counter = 0;
    12751480}
    12761481
    1277 void MidiDriver_ADLIB::adlib_playnote(int channel, int note) {
    1278         byte old, oct, notex;
    1279         int note2;
    1280         int i;
    1281 
    1282         note2 = (note >> 7) - 4;
    1283         note2 = (note2 < 128) ? note2 : 0;
    1284 
    1285         oct = (note2 / 12);
    1286         if (oct > 7)
    1287                 oct = 7 << 2;
    1288         else
    1289                 oct <<= 2;
    1290         notex = note2 % 12 + 3;
    1291 
    1292         old = adlib_get_reg_value(channel + 0xB0);
    1293         if (old & 0x20) {
    1294                 old &= ~0x20;
    1295                 if (oct > old) {
    1296                         if (notex < 6) {
    1297                                 notex += 12;
    1298                                 oct -= 4;
    1299                         }
    1300                 } else if (oct < old) {
    1301                         if (notex > 11) {
    1302                                 notex -= 12;
    1303                                 oct += 4;
    1304                         }
    1305                 }
    1306         }
    1307 
    1308         i = (notex << 3) + ((note >> 4) & 0x7);
    1309         adlib_write(channel + 0xA0, note_to_f_num[i]);
    1310         adlib_write(channel + 0xB0, oct | 0x20);
    1311 }
    1312 
    13131482int MidiDriver_ADLIB::random_nr(int a) {
    13141483        static byte _rand_seed = 1;
    13151484        if (_rand_seed & 1) {
     
    13491518        AdlibVoice *ac, *best = NULL;
    13501519        int i;
    13511520
    1352         for (i = 0; i < 9; i++) {
    1353                 if (++_voice_index >= 9)
     1521        for (i = 0; i < _numVoices; i++) {
     1522                if (++_voice_index >= _numVoices)
    13541523                        _voice_index = 0;
    13551524                ac = &_voices[_voice_index];
    13561525                if (!ac->_part)
     
    13681537                return NULL;
    13691538
    13701539        if (best)
     1540{
     1541printf("Evicted %d\n", best - _voices);
    13711542                mc_off(best);
     1543}
    13721544        return best;
    13731545}
    13741546
     
    14351607}
    14361608
    14371609void MidiDriver_ADLIB::adlib_setup_channel(int chan, AdlibInstrument *instr, byte vol_1, byte vol_2) {
    1438         byte channel;
     1610        int card = chan / 9;
     1611        int channel = chan % 9;
    14391612
    1440         assert(chan >= 0 && chan < 9);
     1613        _cards[card]->adlib_setup_channel(channel, instr, vol_1, vol_2);
     1614}
    14411615
    1442         channel = channel_mappings[chan];
    1443         adlib_write(channel + 0x20, instr->mod_characteristic);
    1444         adlib_write(channel + 0x40, (instr->mod_scalingOutputLevel | 0x3F) - vol_1 );
    1445         adlib_write(channel + 0x60, 0xff & (~instr->mod_attackDecay));
    1446         adlib_write(channel + 0x80, 0xff & (~instr->mod_sustainRelease));
    1447         adlib_write(channel + 0xE0, instr->mod_waveformSelect);
     1616void MidiDriver_ADLIB::adlib_note_on_ex(int chan, byte note, int mod) {
     1617        int card = chan / 9;
     1618        int channel = chan % 9;
    14481619
    1449         channel = channel_mappings_2[chan];
    1450         adlib_write(channel + 0x20, instr->car_characteristic);
    1451         adlib_write(channel + 0x40, (instr->car_scalingOutputLevel | 0x3F) - vol_2 );
    1452         adlib_write(channel + 0x60, 0xff & (~instr->car_attackDecay));
    1453         adlib_write(channel + 0x80, 0xff & (~instr->car_sustainRelease));
    1454         adlib_write(channel + 0xE0, instr->car_waveformSelect);
    1455 
    1456         adlib_write((byte)chan + 0xC0, instr->feedback);
     1620        _cards[card]->adlib_note_on_ex(channel, note, mod);
    14571621}
    14581622
    1459 void MidiDriver_ADLIB::adlib_note_on_ex(int chan, byte note, int mod)
    1460 {
    1461         int code;
    1462         assert(chan >= 0 && chan < 9);
    1463         code = (note << 7) + mod;
    1464         curnote_table[chan] = code;
    1465         channel_table_2[chan] = 0;
    1466         adlib_playnote(chan, code);
    1467 }
    1468 
    14691623void MidiDriver_ADLIB::mc_init_stuff(AdlibVoice *voice, Struct10 * s10,
    14701624                                                                        Struct11 * s11, byte flags, InstrumentExtra * ie) {
    14711625        AdlibPart *part = voice->_part;
     
    15301684}
    15311685
    15321686int MidiDriver_ADLIB::adlib_get_reg_value_param(int chan, byte param) {
    1533         const AdlibSetParams *as;
    1534         byte val;
    1535         byte channel;
     1687        int card = chan / 9;
     1688        int channel = chan % 9;
    15361689
    1537         assert(chan >= 0 && chan < 9);
    1538 
    1539         if (param <= 12) {
    1540                 channel = channel_mappings_2[chan];
    1541         } else if (param <= 25) {
    1542                 param -= 13;
    1543                 channel = channel_mappings[chan];
    1544         } else if (param <= 27) {
    1545                 param -= 13;
    1546                 channel = chan;
    1547         } else if (param == 28) {
    1548                 return 0xF;
    1549         } else if (param == 29) {
    1550                 return 0x17F;
    1551         } else {
    1552                 return 0;
    1553         }
    1554 
    1555         as = &adlib_setparam_table[param];
    1556         val = adlib_get_reg_value(channel + as->a);
    1557         val &= as->c;
    1558         val >>= as->b;
    1559         if (as->d)
    1560                 val = as->d - val;
    1561 
    1562         return val;
     1690        return _cards[card]->adlib_get_reg_value_param(channel, param);
    15631691}
    15641692
    15651693void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod) {
    1566         int code;
    1567         assert(chan >= 0 && chan < 9);
    1568         code = (note << 7) + mod;
    1569         curnote_table[chan] = code;
    1570         adlib_playnote(chan, (int16) channel_table_2[chan] + code);
     1694        int card = chan / 9;
     1695        int channel = chan % 9;
     1696
     1697        _cards[card]->adlib_note_on(channel, note, mod);
    15711698}
    15721699
    15731700