Ticket #9058: opl-experiment.diff
File opl-experiment.diff, 15.7 KB (added by , 14 years ago) |
---|
-
sound/softsynth/adlib.cpp
60 60 AdlibInstrument() { memset(this, 0, sizeof(AdlibInstrument)); } 61 61 }; 62 62 63 class AdlibSoundcard { 64 private: 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 74 public: 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 63 91 class AdlibPart : public MidiChannel { 64 92 friend class MidiDriver_ADLIB; 65 93 … … 575 603 int getRate() const { return _mixer->getOutputRate(); } 576 604 577 605 private: 606 int16 *_sampleBuffer; 607 int _sampleBufferLen; 608 578 609 bool _scummSmallHeader; // FIXME: This flag controls a special mode for SCUMM V3 games 579 610 580 FM_OPL *_opl;581 byte *_adlib_reg_cache;611 int _numCards; 612 AdlibSoundcard *_cards[2]; 582 613 583 614 int _adlib_timer_counter; 584 615 585 uint16 channel_table_2[9];586 616 int _voice_index; 587 617 int _timer_p; 588 618 int _timer_q; 589 uint16 curnote_table[9]; 590 AdlibVoice _voices[9]; 619 620 int _numVoices; 621 AdlibVoice *_voices; 591 622 AdlibPart _parts[32]; 592 623 AdlibPercussionChannel _percussion; 593 624 … … 601 632 void adlib_note_on_ex(int chan, byte note, int mod); 602 633 int adlib_get_reg_value_param(int chan, byte data); 603 634 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 }607 635 void adlib_set_param(int channel, byte param, int value); 608 636 void adlib_key_onoff(int channel); 609 void adlib_write(byte reg, byte value);610 void adlib_playnote(int channel, int note);611 637 612 638 AdlibVoice *allocate_voice(byte pri); 613 639 … … 625 651 void mc_key_on(AdlibVoice *voice, AdlibInstrument *instr, byte note, byte velocity); 626 652 }; 627 653 654 // An emulated Adlib sound card 655 656 AdlibSoundcard::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 670 AdlibSoundcard::~AdlibSoundcard() { 671 OPLDestroy(_opl); 672 free(_adlib_reg_cache); 673 } 674 675 void AdlibSoundcard::adlib_key_off(int chan) { 676 byte reg = chan + 0xB0; 677 adlib_write(reg, adlib_get_reg_value(reg) & ~0x20); 678 } 679 680 void 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 688 void 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 697 int 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 730 void 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 752 void 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 786 void 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 796 void 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 807 void 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 843 void AdlibSoundcard::generateSamples(int16 *data, int len) { 844 YM3812UpdateOne(_opl, data, len); 845 } 846 628 847 // MidiChannel method implementations 629 848 630 849 void AdlibPart::init(MidiDriver_ADLIB *owner, byte channel) { … … 868 1087 869 1088 _scummSmallHeader = false; 870 1089 871 _adlib_reg_cache = 0;872 873 1090 _adlib_timer_counter = 0; 874 1091 _voice_index = 0; 875 for (i = 0; i < ARRAYSIZE(curnote_table); ++i) {876 curnote_table[i] = 0;877 }878 1092 879 1093 for (i = 0; i < ARRAYSIZE(_parts); ++i) { 880 1094 _parts[i].init(this, i + ((i >= 9) ? 1 : 0)); … … 890 1104 891 1105 MidiDriver_Emulated::open(); 892 1106 1107 _sampleBuffer = 0; 1108 _sampleBufferLen = 0; 1109 893 1110 int i; 894 1111 AdlibVoice *voice; 895 1112 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++) { 897 1126 voice->_channel = i; 898 1127 voice->_s11a.s10 = &voice->_s10b; 899 1128 voice->_s11b.s10 = &voice->_s10a; 900 1129 } 901 1130 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);909 1131 create_lookup_table(); 910 1132 911 1133 _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_mixerSoundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, false, true); … … 920 1142 921 1143 _mixer->stopHandle(_mixerSoundHandle); 922 1144 923 uint i;924 for (i = 0; i < ARRAYSIZE(_voices); ++i) {1145 int i; 1146 for (i = 0; i < _numVoices; ++i) { 925 1147 if (_voices[i]._part) 926 1148 mc_off(&_voices[i]); 927 1149 } 928 1150 929 1151 // 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; 931 1159 // YM3812Shutdown(); 932 933 free(_adlib_reg_cache);934 1160 } 935 1161 936 1162 void MidiDriver_ADLIB::send(uint32 b) { … … 1028 1254 1029 1255 // All the code brought over from IMuseAdlib 1030 1256 1031 void MidiDriver_ADLIB::adlib_write(byte reg, byte value) {1032 if (_adlib_reg_cache[reg] == value)1033 return;1034 #ifdef DEBUG_ADLIB1035 debug(6, "%10d: adlib_write[%x] = %x", tick, reg, value);1036 #endif1037 _adlib_reg_cache[reg] = value;1038 1039 OPLWriteReg(_opl, reg, value);1040 }1041 1042 1257 void MidiDriver_ADLIB::generateSamples(int16 *data, int len) { 1043 1258 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 } 1045 1278 } 1046 1279 1047 1280 void MidiDriver_ADLIB::onTimer() { … … 1055 1288 tick++; 1056 1289 #endif 1057 1290 voice = _voices; 1058 for (i = 0; i != ARRAYSIZE(_voices); i++, voice++) {1291 for (i = 0; i != _numVoices; i++, voice++) { 1059 1292 if (!voice->_part) 1060 1293 continue; 1061 1294 if (voice->_duration && (voice->_duration -= 0x11) <= 0) { … … 1133 1366 adlib_key_onoff(voice->_channel); 1134 1367 } 1135 1368 1136 void MidiDriver_ADLIB::adlib_key_off(int chan){ 1137 byte reg = chan + 0xB0; 1138 adlib_write(reg, adlib_get_reg_value(reg) & ~0x20); 1369 void 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); 1139 1374 } 1140 1375 1141 1376 byte MidiDriver_ADLIB::struct10_ontimer(Struct10 *s10, Struct11 *s11) { … … 1182 1417 } 1183 1418 1184 1419 void 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; 1187 1422 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); 1216 1424 } 1217 1425 1218 1426 void 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; 1222 1429 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); 1226 1431 } 1227 1432 1228 1433 void MidiDriver_ADLIB::struct10_setup(Struct10 *s10) { … … 1274 1479 s10->speed_lo_counter = 0; 1275 1480 } 1276 1481 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 else1289 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 1313 1482 int MidiDriver_ADLIB::random_nr(int a) { 1314 1483 static byte _rand_seed = 1; 1315 1484 if (_rand_seed & 1) { … … 1349 1518 AdlibVoice *ac, *best = NULL; 1350 1519 int i; 1351 1520 1352 for (i = 0; i < 9; i++) {1353 if (++_voice_index >= 9)1521 for (i = 0; i < _numVoices; i++) { 1522 if (++_voice_index >= _numVoices) 1354 1523 _voice_index = 0; 1355 1524 ac = &_voices[_voice_index]; 1356 1525 if (!ac->_part) … … 1368 1537 return NULL; 1369 1538 1370 1539 if (best) 1540 { 1541 printf("Evicted %d\n", best - _voices); 1371 1542 mc_off(best); 1543 } 1372 1544 return best; 1373 1545 } 1374 1546 … … 1435 1607 } 1436 1608 1437 1609 void 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; 1439 1612 1440 assert(chan >= 0 && chan < 9); 1613 _cards[card]->adlib_setup_channel(channel, instr, vol_1, vol_2); 1614 } 1441 1615 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); 1616 void MidiDriver_ADLIB::adlib_note_on_ex(int chan, byte note, int mod) { 1617 int card = chan / 9; 1618 int channel = chan % 9; 1448 1619 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); 1457 1621 } 1458 1622 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 1469 1623 void MidiDriver_ADLIB::mc_init_stuff(AdlibVoice *voice, Struct10 * s10, 1470 1624 Struct11 * s11, byte flags, InstrumentExtra * ie) { 1471 1625 AdlibPart *part = voice->_part; … … 1530 1684 } 1531 1685 1532 1686 int 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; 1536 1689 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); 1563 1691 } 1564 1692 1565 1693 void 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); 1571 1698 } 1572 1699 1573 1700