34namespace YM2413Burczynski {
37static constexpr int ENV_BITS = 10;
38static constexpr double ENV_STEP = 128.0 / (1 << ENV_BITS);
40static constexpr int MAX_ATT_INDEX = (1 << (ENV_BITS - 2)) - 1;
41static constexpr int MIN_ATT_INDEX = 0;
43static constexpr int TL_RES_LEN = 256;
49static constexpr int DV(
double x) {
return narrow_cast<int>(x / 0.1875); }
50static constexpr std::array<int, 8 * 16> ksl_tab =
53 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
54 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
55 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
56 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
58 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
59 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
60 DV( 0.000),DV( 0.750),DV( 1.125),DV( 1.500),
61 DV( 1.875),DV( 2.250),DV( 2.625),DV( 3.000),
63 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
64 DV( 0.000),DV( 1.125),DV( 1.875),DV( 2.625),
65 DV( 3.000),DV( 3.750),DV( 4.125),DV( 4.500),
66 DV( 4.875),DV( 5.250),DV( 5.625),DV( 6.000),
68 DV( 0.000),DV( 0.000),DV( 0.000),DV( 1.875),
69 DV( 3.000),DV( 4.125),DV( 4.875),DV( 5.625),
70 DV( 6.000),DV( 6.750),DV( 7.125),DV( 7.500),
71 DV( 7.875),DV( 8.250),DV( 8.625),DV( 9.000),
73 DV( 0.000),DV( 0.000),DV( 3.000),DV( 4.875),
74 DV( 6.000),DV( 7.125),DV( 7.875),DV( 8.625),
75 DV( 9.000),DV( 9.750),DV(10.125),DV(10.500),
76 DV(10.875),DV(11.250),DV(11.625),DV(12.000),
78 DV( 0.000),DV( 3.000),DV( 6.000),DV( 7.875),
79 DV( 9.000),DV(10.125),DV(10.875),DV(11.625),
80 DV(12.000),DV(12.750),DV(13.125),DV(13.500),
81 DV(13.875),DV(14.250),DV(14.625),DV(15.000),
83 DV( 0.000),DV( 6.000),DV( 9.000),DV(10.875),
84 DV(12.000),DV(13.125),DV(13.875),DV(14.625),
85 DV(15.000),DV(15.750),DV(16.125),DV(16.500),
86 DV(16.875),DV(17.250),DV(17.625),DV(18.000),
88 DV( 0.000),DV( 9.000),DV(12.000),DV(13.875),
89 DV(15.000),DV(16.125),DV(16.875),DV(17.625),
90 DV(18.000),DV(18.750),DV(19.125),DV(19.500),
91 DV(19.875),DV(20.250),DV(20.625),DV(21.000)
96static constexpr int SC(
int db) {
return int(
double(db) / ENV_STEP); }
97static constexpr std::array<int, 16> sl_tab = {
98 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
99 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(15)
102static constexpr std::array eg_inc =
105 std::array<uint8_t, 8>{ 0,1, 0,1, 0,1, 0,1, },
106 std::array<uint8_t, 8>{ 0,1, 0,1, 1,1, 0,1, },
107 std::array<uint8_t, 8>{ 0,1, 1,1, 0,1, 1,1, },
108 std::array<uint8_t, 8>{ 0,1, 1,1, 1,1, 1,1, },
110 std::array<uint8_t, 8>{ 1,1, 1,1, 1,1, 1,1, },
111 std::array<uint8_t, 8>{ 1,1, 1,2, 1,1, 1,2, },
112 std::array<uint8_t, 8>{ 1,2, 1,2, 1,2, 1,2, },
113 std::array<uint8_t, 8>{ 1,2, 2,2, 1,2, 2,2, },
115 std::array<uint8_t, 8>{ 2,2, 2,2, 2,2, 2,2, },
116 std::array<uint8_t, 8>{ 2,2, 2,4, 2,2, 2,4, },
117 std::array<uint8_t, 8>{ 2,4, 2,4, 2,4, 2,4, },
118 std::array<uint8_t, 8>{ 2,4, 4,4, 2,4, 4,4, },
120 std::array<uint8_t, 8>{ 4,4, 4,4, 4,4, 4,4, },
121 std::array<uint8_t, 8>{ 8,8, 8,8, 8,8, 8,8, },
122 std::array<uint8_t, 8>{ 0,0, 0,0, 0,0, 0,0, },
126static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_select =
130 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
157 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
164static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_shift =
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
195 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199static constexpr uint8_t ML(
double x) {
return uint8_t(2 * x); }
200static constexpr std::array<uint8_t, 16> mul_tab =
202 ML( 0.50), ML( 1.00), ML( 2.00), ML( 3.00),
203 ML( 4.00), ML( 5.00), ML( 6.00), ML( 7.00),
204 ML( 8.00), ML( 9.00), ML(10.00), ML(10.00),
205 ML(12.00), ML(12.00), ML(15.00), ML(15.00),
212static constexpr int TL_TAB_LEN = 11 * 2 * TL_RES_LEN;
213static constexpr auto tlTab = [] {
214 std::array<int, TL_TAB_LEN> result = {};
215 for (
auto x :
xrange(TL_RES_LEN)) {
216 double m = (1 << 16) / cstd::exp2<6>((x + 1) * (ENV_STEP / 4.0) / 8.0);
222 n = (n >> 1) + (n & 1);
224 for (
auto i :
xrange(11)) {
225 result[x * 2 + 0 + i * 2 * TL_RES_LEN] = n >> i;
226 result[x * 2 + 1 + i * 2 * TL_RES_LEN] = -(n >> i);
234static constexpr auto sinTab = [] {
235 std::array<std::array<unsigned, SIN_LEN>, 2> result = {};
239 double m = cstd::sin<2>(narrow_cast<double>((i * 2) + 1) *
Math::pi /
SIN_LEN);
240 auto n = int(
cstd::round(cstd::log2<8, 3>(m) * -256.0));
241 result[0][i] = 2 * n;
247 result[0][
SIN_LEN / 2 + i] = result[0][i] | 1;
250 result[1][i] = result[0][i];
253 result[1][i +
SIN_LEN / 2] = TL_TAB_LEN;
270static constexpr int LFO_AM_TAB_ELEMENTS = 210;
271static constexpr std::array<uint8_t, LFO_AM_TAB_ELEMENTS> lfo_am_table =
328static constexpr std::array lfo_pm_table =
331 std::array<int8_t, 8>{ 0, 0, 0, 0, 0, 0, 0, 0, },
334 std::array<int8_t, 8>{ 1, 0, 0, 0,-1, 0, 0, 0, },
337 std::array<int8_t, 8>{ 2, 1, 0,-1,-2,-1, 0, 1, },
340 std::array<int8_t, 8>{ 3, 1, 0,-1,-3,-1, 0, 1, },
343 std::array<int8_t, 8>{ 4, 2, 0,-2,-4,-2, 0, 2, },
346 std::array<int8_t, 8>{ 5, 2, 0,-2,-5,-2, 0, 2, },
349 std::array<int8_t, 8>{ 6, 3, 0,-3,-6,-3, 0, 3, },
352 std::array<int8_t, 8>{ 7, 3, 0,-3,-7,-3, 0, 3, },
360static constexpr std::array table = {
363 std::array<uint8_t, 8>{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
364 std::array<uint8_t, 8>{ 0x61, 0x61, 0x1e, 0x17, 0xf0, 0x7f, 0x00, 0x17 },
365 std::array<uint8_t, 8>{ 0x13, 0x41, 0x16, 0x0e, 0xfd, 0xf4, 0x23, 0x23 },
366 std::array<uint8_t, 8>{ 0x03, 0x01, 0x9a, 0x04, 0xf3, 0xf3, 0x13, 0xf3 },
367 std::array<uint8_t, 8>{ 0x11, 0x61, 0x0e, 0x07, 0xfa, 0x64, 0x70, 0x17 },
368 std::array<uint8_t, 8>{ 0x22, 0x21, 0x1e, 0x06, 0xf0, 0x76, 0x00, 0x28 },
369 std::array<uint8_t, 8>{ 0x21, 0x22, 0x16, 0x05, 0xf0, 0x71, 0x00, 0x18 },
370 std::array<uint8_t, 8>{ 0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x17, 0x17 },
371 std::array<uint8_t, 8>{ 0x23, 0x21, 0x2d, 0x16, 0x90, 0x90, 0x00, 0x07 },
372 std::array<uint8_t, 8>{ 0x21, 0x21, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 },
373 std::array<uint8_t, 8>{ 0x21, 0x21, 0x0b, 0x1a, 0x85, 0xa0, 0x70, 0x07 },
374 std::array<uint8_t, 8>{ 0x23, 0x01, 0x83, 0x10, 0xff, 0xb4, 0x10, 0xf4 },
375 std::array<uint8_t, 8>{ 0x97, 0xc1, 0x20, 0x07, 0xff, 0xf4, 0x22, 0x22 },
376 std::array<uint8_t, 8>{ 0x61, 0x00, 0x0c, 0x05, 0xc2, 0xf6, 0x40, 0x44 },
377 std::array<uint8_t, 8>{ 0x01, 0x01, 0x56, 0x03, 0x94, 0xc2, 0x03, 0x12 },
378 std::array<uint8_t, 8>{ 0x21, 0x01, 0x89, 0x03, 0xf1, 0xe4, 0xf0, 0x23 },
385 std::array<uint8_t, 8>{ 0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },
386 std::array<uint8_t, 8>{ 0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },
387 std::array<uint8_t, 8>{ 0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },
390static constexpr FreqIndex fnumToIncrement(
int block_fnum)
394 const int block = (block_fnum & 0x1C00) >> 10;
395 return FreqIndex(block_fnum & 0x03FF) >> (11 - block);
407 if (!(eg_cnt & eg_mask_dp)) {
408 egOut += eg_sel_dp[(eg_cnt >> eg_sh_dp) & 7];
409 if (egOut >= MAX_ATT_INDEX) {
410 egOut = MAX_ATT_INDEX;
418 if (!(eg_cnt & eg_mask_ar)) {
420 (~egOut * eg_sel_ar[(eg_cnt >> eg_sh_ar) & 7]) >> 2;
421 if (egOut <= MIN_ATT_INDEX) {
422 egOut = MIN_ATT_INDEX;
423 setEnvelopeState(
DECAY);
429 if (!(eg_cnt & eg_mask_dr)) {
430 egOut += eg_sel_dr[(eg_cnt >> eg_sh_dr) & 7];
449 if (!(eg_cnt & eg_mask_rr)) {
450 egOut += eg_sel_rr[(eg_cnt >> eg_sh_rr) & 7];
451 if (egOut >= MAX_ATT_INDEX) {
452 egOut = MAX_ATT_INDEX;
463 const bool sustain = !eg_sustain || channel.
isSustained();
464 const unsigned mask = sustain ? eg_mask_rs : eg_mask_rr;
465 if (!(eg_cnt & mask)) {
466 const uint8_t shift = sustain ? eg_sh_rs : eg_sh_rr;
467 std::span<const uint8_t, 8> sel = sustain ? eg_sel_rs : eg_sel_rr;
468 egOut += sel[(eg_cnt >> shift) & 7];
469 if (egOut >= MAX_ATT_INDEX) {
470 egOut = MAX_ATT_INDEX;
471 setEnvelopeState(
OFF);
486 auto lfo_fn_table_index_offset = narrow<int>(lfo_pm_table
488 phase += fnumToIncrement(
495 return phase.
toInt();
498inline void Slot::updateTotalLevel(
const Channel& channel)
503inline void Slot::updateAttackRate(
int kcodeScaled)
505 if ((ar + kcodeScaled) < (16 + 62)) {
506 eg_sh_ar = eg_rate_shift[ar + kcodeScaled];
507 eg_sel_ar = eg_inc[eg_rate_select[ar + kcodeScaled]];
510 eg_sel_ar = eg_inc[13];
512 eg_mask_ar = (1 << eg_sh_ar) - 1;
515inline void Slot::updateDecayRate(
int kcodeScaled)
517 eg_sh_dr = eg_rate_shift[dr + kcodeScaled];
518 eg_sel_dr = eg_inc[eg_rate_select[dr + kcodeScaled]];
519 eg_mask_dr = (1 << eg_sh_dr) - 1;
522inline void Slot::updateReleaseRate(
int kcodeScaled)
524 eg_sh_rr = eg_rate_shift[rr + kcodeScaled];
525 eg_sel_rr = eg_inc[eg_rate_select[rr + kcodeScaled]];
526 eg_mask_rr = (1 << eg_sh_rr) - 1;
530 unsigned lfo_am,
int phase2)
533 auto env = narrow<unsigned>((TLL + egOut2 + (lfo_am & AMmask)) << 5);
534 unsigned p = env + waveTable[phase2 &
SIN_MASK];
535 return p < TL_TAB_LEN ? tlTab[p] : 0;
539 unsigned lfo_pm,
unsigned lfo_am)
544 phase2 += (op1_out[0] + op1_out[1]) >> fb_shift;
547 op1_out[0] = op1_out[1];
549 op1_out[1] =
calcOutput(channel, eg_cnt, carrier, lfo_am, phase2);
550 return op1_out[0] << 1;
598static constexpr int genPhaseHighHat(
int phaseM7,
int phaseC8,
int noise_rng)
603 if (phaseC8 & 0x28) {
608 const bool bit7 = (phaseM7 & 0x80) != 0;
609 const bool bit3 = (phaseM7 & 0x08) != 0;
610 const bool bit2 = (phaseM7 & 0x04) != 0;
611 return bool((bit2 ^ bit7) | bit3);
615 return hi ? (0x200 | 0xD0) : (0xD0 >> 2);
617 return hi ? (0x200 | (0xD0 >> 2)) : 0xD0;
621static constexpr int genPhaseSnare(
int phaseM7,
int noise_rng)
625 return ((phaseM7 & 0x100) + 0x100)
626 ^ ((noise_rng & 1) << 8);
629static constexpr int genPhaseCymbal(
int phaseM7,
int phaseC8)
632 if (phaseC8 & 0x28) {
637 const bool bit7 = (phaseM7 & 0x80) != 0;
638 const bool bit3 = (phaseM7 & 0x08) != 0;
639 const bool bit2 = (phaseM7 & 0x04) != 0;
640 return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
646 : waveTable(sinTab[0])
647 , eg_sel_dp(eg_inc[0]), eg_sel_ar(eg_inc[0]), eg_sel_dr(eg_inc[0])
648 , eg_sel_rr(eg_inc[0]), eg_sel_rs(eg_inc[0])
665 key &= ~to_underlying(part);
686void Slot::setEnvelopeState(EnvelopeState state_)
693 mul = mul_tab[value];
713 AMmask = value ? ~0 : 0;
718 TL = value << (ENV_BITS - 2 - 7);
719 updateTotalLevel(channel);
724 ksl = value ? (3 - value) : 31;
725 updateTotalLevel(channel);
730 waveTable = sinTab[value];
735 fb_shift = value ? 8 - value : 0;
740 int kcodeScaled = channel.
getKeyCode() >> KSR;
741 ar = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
742 updateAttackRate(kcodeScaled);
747 int kcodeScaled = channel.
getKeyCode() >> KSR;
748 dr = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
749 updateDecayRate(kcodeScaled);
754 int kcodeScaled = channel.
getKeyCode() >> KSR;
755 rr = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
756 updateReleaseRate(kcodeScaled);
766 updateTotalLevel(channel);
772 waveTable = sinTab[0];
774 egOut = MAX_ATT_INDEX;
783 const int kcodeScaled = channel.
getKeyCode() >> KSR;
784 updateAttackRate(kcodeScaled);
785 updateDecayRate(kcodeScaled);
786 updateReleaseRate(kcodeScaled);
788 const int rs = channel.
isSustained() ? 16 + (5 << 2) : 16 + (7 << 2);
789 eg_sh_rs = eg_rate_shift[rs + kcodeScaled];
790 eg_sel_rs = eg_inc[eg_rate_select[rs + kcodeScaled]];
792 const int dp = 16 + (13 << 2);
793 eg_sh_dp = eg_rate_shift[dp + kcodeScaled];
794 eg_sel_dp = eg_inc[eg_rate_select[dp + kcodeScaled]];
796 eg_mask_rs = (1 << eg_sh_rs) - 1;
797 eg_mask_dp = (1 << eg_sh_dp) - 1;
802 if (block_fnum == block_fnum_)
return;
803 block_fnum = block_fnum_;
805 ksl_base = ksl_tab[block_fnum >> 5];
806 fc = fnumToIncrement(block_fnum * 2);
841 return (block_fnum & 0x0F00) >> 8;
904 for (
auto part :
xrange(8)) {
912 for (
const auto& e : tlTab) std::cout << e <<
'\n';
914 for (
const auto& s : sinTab) {
915 for (
const auto& e : s) std::cout << e <<
'\n';
926void YM2413::updateCustomInstrument(
int part, uint8_t value)
929 inst_tab[0][part] = value;
932 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
933 Channel& channel = channels[ch];
934 if ((reg[0x30 + ch] & 0xF0) == 0) {
940void YM2413::setRhythmFlags(uint8_t old)
942 Channel& ch6 = channels[6];
943 Channel& ch7 = channels[7];
944 Channel& ch8 = channels[8];
948 uint8_t flags = reg[0x0E];
949 if ((flags ^ old) & 0x20) {
952 ch6.updateInstrument(inst_tab[16]);
954 ch7.updateInstrument(inst_tab[17]);
955 ch7.mod.setTotalLevel(ch7, uint8_t((reg[0x37] >> 4) << 2));
957 ch8.updateInstrument(inst_tab[18]);
958 ch8.mod.setTotalLevel(ch8, uint8_t((reg[0x38] >> 4) << 2));
960 ch6.updateInstrument(inst_tab[reg[0x36] >> 4]);
961 ch7.updateInstrument(inst_tab[reg[0x37] >> 4]);
962 ch8.updateInstrument(inst_tab[reg[0x38] >> 4]);
965 ch6.mod.setKeyOff(RHYTHM);
966 ch6.car.setKeyOff(RHYTHM);
968 ch7.mod.setKeyOff(RHYTHM);
970 ch7.car.setKeyOff(RHYTHM);
972 ch8.mod.setKeyOff(RHYTHM);
974 ch8.car.setKeyOff(RHYTHM);
979 ch6.mod.setKeyOnOff(RHYTHM, (flags & 0x10) != 0);
980 ch6.car.setKeyOnOff(RHYTHM, (flags & 0x10) != 0);
982 ch7.mod.setKeyOnOff(RHYTHM, (flags & 0x01) != 0);
984 ch7.car.setKeyOnOff(RHYTHM, (flags & 0x08) != 0);
986 ch8.mod.setKeyOnOff(RHYTHM, (flags & 0x04) != 0);
988 ch8.car.setKeyOnOff(RHYTHM, (flags & 0x02) != 0);
1003 for (uint8_t i = 0x3F; i >= 0x10; --i) {
1011void YM2413::resetOperators()
1013 for (
auto& ch : channels) {
1014 ch.mod.resetOperators();
1015 ch.car.resetOperators();
1019bool YM2413::isRhythm()
const
1021 return (reg[0x0E] & 0x20) != 0;
1024Channel& YM2413::getChannelForReg(uint8_t r)
1026 uint8_t chan = (r & 0x0F) % 9;
1027 return channels[chan];
1032 return 1.0f / 2048.0f;
1042 unsigned channelActiveBits = 0;
1044 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
1045 if (channels[ch].car.isActive()) {
1046 channelActiveBits |= 1 << ch;
1053 for (
auto ch :
xrange(6, 9)) {
1054 if (channels[ch].car.isActive()) {
1055 channelActiveBits |= 1 << ch;
1057 bufs[ch + 3] =
nullptr;
1060 if (channels[7].mod.isActive()) {
1061 channelActiveBits |= 1 << (7 + 9);
1065 if (channels[8].mod.isActive()) {
1066 channelActiveBits |= 1 << (8 + 9);
1074 if (channelActiveBits) {
1089 for (
auto i :
xrange(num)) {
1094 if (lfo_am_cnt ==
LFOAMIndex(LFO_AM_TAB_ELEMENTS)) {
1098 unsigned lfo_am = lfo_am_table[lfo_am_cnt.
toInt()] >> 1;
1099 unsigned lfo_pm = lfo_pm_cnt.
toInt() & 7;
1101 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
1102 Channel& channel = channels[ch];
1103 int fm = channel.
mod.
calc_slot_mod(channel, eg_cnt,
false, lfo_pm, lfo_am);
1104 if ((channelActiveBits >> ch) & 1) {
1105 bufs[ch][i] += narrow_cast<float>(channel.
calcOutput(eg_cnt, lfo_pm, lfo_am, fm));
1116 Channel& channel6 = channels[6];
1117 int fm = channel6.
mod.
calc_slot_mod(channels[6], eg_cnt,
true, lfo_pm, lfo_am);
1118 if (channelActiveBits & (1 << 6)) {
1119 bufs[ 9][i] += narrow_cast<float>(2 * channel6.
calcOutput(eg_cnt, lfo_pm, lfo_am, fm));
1126 (void)channels[7].car.calc_phase(channels[7], lfo_pm);
1127 int phaseM7 = channels[7].mod.calc_phase(channels[7], lfo_pm);
1128 int phaseC8 = channels[8].car.calc_phase(channels[8], lfo_pm);
1129 int phaseM8 = channels[8].mod.calc_phase(channels[8], lfo_pm);
1132 if (channelActiveBits & (1 << 7)) {
1133 Slot& SLOT7_2 = channels[7].car;
1134 bufs[10][i] += narrow_cast<float>(2 * SLOT7_2.
calcOutput(channels[7], eg_cnt,
true, lfo_am, genPhaseSnare(phaseM7, noise_rng)));
1138 if (channelActiveBits & (1 << 8)) {
1139 Slot& SLOT8_2 = channels[8].car;
1140 bufs[11][i] += narrow_cast<float>(2 * SLOT8_2.
calcOutput(channels[8], eg_cnt,
true, lfo_am, genPhaseCymbal(phaseM7, phaseC8)));
1144 if (channelActiveBits & (1 << (7 + 9))) {
1145 Slot& SLOT7_1 = channels[7].mod;
1146 bufs[12][i] += narrow_cast<float>(2 * SLOT7_1.
calcOutput(channels[7], eg_cnt,
true, lfo_am, genPhaseHighHat(phaseM7, phaseC8, noise_rng)));
1150 if (channelActiveBits & (1 << (8 + 9))) {
1151 Slot& SLOT8_1 = channels[8].mod;
1152 bufs[13][i] += narrow_cast<float>(2 * SLOT8_1.
calcOutput(channels[8], eg_cnt,
true, lfo_am, phaseM8));
1181 if (noise_rng & 1) {
1182 noise_rng ^= 0x800302;
1191 registerLatch = value;
1193 writeReg(registerLatch & 0x3f, value);
1202void YM2413::writeReg(uint8_t r, uint8_t v)
1204 uint8_t old = reg[r];
1219 updateCustomInstrument(r, v);
1222 setRhythmFlags(old);
1229 Channel& ch = getChannelForReg(r);
1230 ch.setFrequencyLow(v);
1235 Channel& ch = getChannelForReg(r);
1238 ch.setSustain((v & 0x20) != 0);
1242 ch.setFrequencyHigh(v & 0x0F);
1246 Channel& ch = getChannelForReg(r);
1247 ch.car.setTotalLevel(ch, uint8_t((v & 0x0F) << 2));
1252 uint8_t chan = (r & 0x0F) % 9;
1253 if (isRhythm() && (chan >= 6)) {
1257 ch.mod.setTotalLevel(ch, uint8_t((v >> 4) << 2));
1260 if ((old & 0xF0) != (v & 0xF0)) {
1261 ch.updateInstrument(inst_tab[v >> 4]);