37namespace YM2413Burczynski {
40static constexpr int ENV_BITS = 10;
41static constexpr double ENV_STEP = 128.0 / (1 << ENV_BITS);
43static constexpr int MAX_ATT_INDEX = (1 << (ENV_BITS - 2)) - 1;
44static constexpr int MIN_ATT_INDEX = 0;
46static constexpr int TL_RES_LEN = 256;
52static constexpr int DV(
double x) {
return narrow_cast<int>(x / 0.1875); }
53static constexpr std::array<int, 8 * 16> ksl_tab =
56 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
57 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),
61 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
62 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
63 DV( 0.000),DV( 0.750),DV( 1.125),DV( 1.500),
64 DV( 1.875),DV( 2.250),DV( 2.625),DV( 3.000),
66 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
67 DV( 0.000),DV( 1.125),DV( 1.875),DV( 2.625),
68 DV( 3.000),DV( 3.750),DV( 4.125),DV( 4.500),
69 DV( 4.875),DV( 5.250),DV( 5.625),DV( 6.000),
71 DV( 0.000),DV( 0.000),DV( 0.000),DV( 1.875),
72 DV( 3.000),DV( 4.125),DV( 4.875),DV( 5.625),
73 DV( 6.000),DV( 6.750),DV( 7.125),DV( 7.500),
74 DV( 7.875),DV( 8.250),DV( 8.625),DV( 9.000),
76 DV( 0.000),DV( 0.000),DV( 3.000),DV( 4.875),
77 DV( 6.000),DV( 7.125),DV( 7.875),DV( 8.625),
78 DV( 9.000),DV( 9.750),DV(10.125),DV(10.500),
79 DV(10.875),DV(11.250),DV(11.625),DV(12.000),
81 DV( 0.000),DV( 3.000),DV( 6.000),DV( 7.875),
82 DV( 9.000),DV(10.125),DV(10.875),DV(11.625),
83 DV(12.000),DV(12.750),DV(13.125),DV(13.500),
84 DV(13.875),DV(14.250),DV(14.625),DV(15.000),
86 DV( 0.000),DV( 6.000),DV( 9.000),DV(10.875),
87 DV(12.000),DV(13.125),DV(13.875),DV(14.625),
88 DV(15.000),DV(15.750),DV(16.125),DV(16.500),
89 DV(16.875),DV(17.250),DV(17.625),DV(18.000),
91 DV( 0.000),DV( 9.000),DV(12.000),DV(13.875),
92 DV(15.000),DV(16.125),DV(16.875),DV(17.625),
93 DV(18.000),DV(18.750),DV(19.125),DV(19.500),
94 DV(19.875),DV(20.250),DV(20.625),DV(21.000)
99static constexpr int SC(
int db) {
return int(
double(db) / ENV_STEP); }
100static constexpr std::array<int, 16> sl_tab = {
101 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
102 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(15)
105static constexpr std::array eg_inc =
108 std::array<uint8_t, 8>{ 0,1, 0,1, 0,1, 0,1, },
109 std::array<uint8_t, 8>{ 0,1, 0,1, 1,1, 0,1, },
110 std::array<uint8_t, 8>{ 0,1, 1,1, 0,1, 1,1, },
111 std::array<uint8_t, 8>{ 0,1, 1,1, 1,1, 1,1, },
113 std::array<uint8_t, 8>{ 1,1, 1,1, 1,1, 1,1, },
114 std::array<uint8_t, 8>{ 1,1, 1,2, 1,1, 1,2, },
115 std::array<uint8_t, 8>{ 1,2, 1,2, 1,2, 1,2, },
116 std::array<uint8_t, 8>{ 1,2, 2,2, 1,2, 2,2, },
118 std::array<uint8_t, 8>{ 2,2, 2,2, 2,2, 2,2, },
119 std::array<uint8_t, 8>{ 2,2, 2,4, 2,2, 2,4, },
120 std::array<uint8_t, 8>{ 2,4, 2,4, 2,4, 2,4, },
121 std::array<uint8_t, 8>{ 2,4, 4,4, 2,4, 4,4, },
123 std::array<uint8_t, 8>{ 4,4, 4,4, 4,4, 4,4, },
124 std::array<uint8_t, 8>{ 8,8, 8,8, 8,8, 8,8, },
125 std::array<uint8_t, 8>{ 0,0, 0,0, 0,0, 0,0, },
129static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_select =
133 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
160 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
167static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_shift =
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202static constexpr uint8_t ML(
double x) {
return uint8_t(2 * x); }
203static constexpr std::array<uint8_t, 16> mul_tab =
205 ML( 0.50), ML( 1.00), ML( 2.00), ML( 3.00),
206 ML( 4.00), ML( 5.00), ML( 6.00), ML( 7.00),
207 ML( 8.00), ML( 9.00), ML(10.00), ML(10.00),
208 ML(12.00), ML(12.00), ML(15.00), ML(15.00),
215static constexpr int TL_TAB_LEN = 11 * 2 * TL_RES_LEN;
216static constexpr auto tlTab = [] {
217 std::array<int, TL_TAB_LEN> result = {};
218 for (
auto x :
xrange(TL_RES_LEN)) {
219 double m = (1 << 16) / cstd::exp2<6>((x + 1) * (ENV_STEP / 4.0) / 8.0);
225 n = (n >> 1) + (n & 1);
227 for (
auto i :
xrange(11)) {
228 result[x * 2 + 0 + i * 2 * TL_RES_LEN] = n >> i;
229 result[x * 2 + 1 + i * 2 * TL_RES_LEN] = -(n >> i);
237static constexpr auto sinTab = [] {
238 std::array<std::array<unsigned, SIN_LEN>, 2> result = {};
242 double m = cstd::sin<2>(narrow_cast<double>((i * 2) + 1) *
Math::pi /
SIN_LEN);
243 auto n = int(
cstd::round(cstd::log2<8, 3>(m) * -256.0));
244 result[0][i] = 2 * n;
250 result[0][
SIN_LEN / 2 + i] = result[0][i] | 1;
253 result[1][i] = result[0][i];
256 result[1][i +
SIN_LEN / 2] = TL_TAB_LEN;
273static constexpr int LFO_AM_TAB_ELEMENTS = 210;
274static constexpr std::array<uint8_t, LFO_AM_TAB_ELEMENTS> lfo_am_table =
331static constexpr std::array lfo_pm_table =
334 std::array<int8_t, 8>{ 0, 0, 0, 0, 0, 0, 0, 0, },
337 std::array<int8_t, 8>{ 1, 0, 0, 0,-1, 0, 0, 0, },
340 std::array<int8_t, 8>{ 2, 1, 0,-1,-2,-1, 0, 1, },
343 std::array<int8_t, 8>{ 3, 1, 0,-1,-3,-1, 0, 1, },
346 std::array<int8_t, 8>{ 4, 2, 0,-2,-4,-2, 0, 2, },
349 std::array<int8_t, 8>{ 5, 2, 0,-2,-5,-2, 0, 2, },
352 std::array<int8_t, 8>{ 6, 3, 0,-3,-6,-3, 0, 3, },
355 std::array<int8_t, 8>{ 7, 3, 0,-3,-7,-3, 0, 3, },
363static constexpr std::array table = {
366 std::array<uint8_t, 8>{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
367 std::array<uint8_t, 8>{ 0x61, 0x61, 0x1e, 0x17, 0xf0, 0x7f, 0x00, 0x17 },
368 std::array<uint8_t, 8>{ 0x13, 0x41, 0x16, 0x0e, 0xfd, 0xf4, 0x23, 0x23 },
369 std::array<uint8_t, 8>{ 0x03, 0x01, 0x9a, 0x04, 0xf3, 0xf3, 0x13, 0xf3 },
370 std::array<uint8_t, 8>{ 0x11, 0x61, 0x0e, 0x07, 0xfa, 0x64, 0x70, 0x17 },
371 std::array<uint8_t, 8>{ 0x22, 0x21, 0x1e, 0x06, 0xf0, 0x76, 0x00, 0x28 },
372 std::array<uint8_t, 8>{ 0x21, 0x22, 0x16, 0x05, 0xf0, 0x71, 0x00, 0x18 },
373 std::array<uint8_t, 8>{ 0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x17, 0x17 },
374 std::array<uint8_t, 8>{ 0x23, 0x21, 0x2d, 0x16, 0x90, 0x90, 0x00, 0x07 },
375 std::array<uint8_t, 8>{ 0x21, 0x21, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 },
376 std::array<uint8_t, 8>{ 0x21, 0x21, 0x0b, 0x1a, 0x85, 0xa0, 0x70, 0x07 },
377 std::array<uint8_t, 8>{ 0x23, 0x01, 0x83, 0x10, 0xff, 0xb4, 0x10, 0xf4 },
378 std::array<uint8_t, 8>{ 0x97, 0xc1, 0x20, 0x07, 0xff, 0xf4, 0x22, 0x22 },
379 std::array<uint8_t, 8>{ 0x61, 0x00, 0x0c, 0x05, 0xc2, 0xf6, 0x40, 0x44 },
380 std::array<uint8_t, 8>{ 0x01, 0x01, 0x56, 0x03, 0x94, 0xc2, 0x03, 0x12 },
381 std::array<uint8_t, 8>{ 0x21, 0x01, 0x89, 0x03, 0xf1, 0xe4, 0xf0, 0x23 },
388 std::array<uint8_t, 8>{ 0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },
389 std::array<uint8_t, 8>{ 0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },
390 std::array<uint8_t, 8>{ 0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },
393static constexpr FreqIndex fnumToIncrement(
int block_fnum)
397 const int block = (block_fnum & 0x1C00) >> 10;
398 return FreqIndex(block_fnum & 0x03FF) >> (11 - block);
410 if (!(eg_cnt & eg_mask_dp)) {
411 egOut += eg_sel_dp[(eg_cnt >> eg_sh_dp) & 7];
412 if (egOut >= MAX_ATT_INDEX) {
413 egOut = MAX_ATT_INDEX;
421 if (!(eg_cnt & eg_mask_ar)) {
423 (~egOut * eg_sel_ar[(eg_cnt >> eg_sh_ar) & 7]) >> 2;
424 if (egOut <= MIN_ATT_INDEX) {
425 egOut = MIN_ATT_INDEX;
426 setEnvelopeState(
DECAY);
432 if (!(eg_cnt & eg_mask_dr)) {
433 egOut += eg_sel_dr[(eg_cnt >> eg_sh_dr) & 7];
452 if (!(eg_cnt & eg_mask_rr)) {
453 egOut += eg_sel_rr[(eg_cnt >> eg_sh_rr) & 7];
454 if (egOut >= MAX_ATT_INDEX) {
455 egOut = MAX_ATT_INDEX;
466 const bool sustain = !eg_sustain || channel.
isSustained();
467 const unsigned mask = sustain ? eg_mask_rs : eg_mask_rr;
468 if (!(eg_cnt & mask)) {
469 const uint8_t shift = sustain ? eg_sh_rs : eg_sh_rr;
470 std::span<const uint8_t, 8> sel = sustain ? eg_sel_rs : eg_sel_rr;
471 egOut += sel[(eg_cnt >> shift) & 7];
472 if (egOut >= MAX_ATT_INDEX) {
473 egOut = MAX_ATT_INDEX;
474 setEnvelopeState(
OFF);
489 auto lfo_fn_table_index_offset = narrow<int>(lfo_pm_table
491 phase += fnumToIncrement(
498 return phase.
toInt();
501inline void Slot::updateTotalLevel(
const Channel& channel)
506inline void Slot::updateAttackRate(
int kcodeScaled)
508 if ((ar + kcodeScaled) < (16 + 62)) {
509 eg_sh_ar = eg_rate_shift[ar + kcodeScaled];
510 eg_sel_ar = eg_inc[eg_rate_select[ar + kcodeScaled]];
513 eg_sel_ar = eg_inc[13];
515 eg_mask_ar = (1 << eg_sh_ar) - 1;
518inline void Slot::updateDecayRate(
int kcodeScaled)
520 eg_sh_dr = eg_rate_shift[dr + kcodeScaled];
521 eg_sel_dr = eg_inc[eg_rate_select[dr + kcodeScaled]];
522 eg_mask_dr = (1 << eg_sh_dr) - 1;
525inline void Slot::updateReleaseRate(
int kcodeScaled)
527 eg_sh_rr = eg_rate_shift[rr + kcodeScaled];
528 eg_sel_rr = eg_inc[eg_rate_select[rr + kcodeScaled]];
529 eg_mask_rr = (1 << eg_sh_rr) - 1;
533 unsigned lfo_am,
int phase2)
536 auto env = narrow<unsigned>((TLL + egOut2 + (lfo_am & AMmask)) << 5);
537 unsigned p = env + waveTable[phase2 &
SIN_MASK];
538 return p < TL_TAB_LEN ? tlTab[p] : 0;
542 unsigned lfo_pm,
unsigned lfo_am)
547 phase2 += (op1_out[0] + op1_out[1]) >> fb_shift;
550 op1_out[0] = op1_out[1];
552 op1_out[1] =
calcOutput(channel, eg_cnt, carrier, lfo_am, phase2);
553 return op1_out[0] << 1;
601static constexpr int genPhaseHighHat(
int phaseM7,
int phaseC8,
int noise_rng)
606 if (phaseC8 & 0x28) {
611 const bool bit7 = (phaseM7 & 0x80) != 0;
612 const bool bit3 = (phaseM7 & 0x08) != 0;
613 const bool bit2 = (phaseM7 & 0x04) != 0;
614 return bool((bit2 ^ bit7) | bit3);
618 return hi ? (0x200 | 0xD0) : (0xD0 >> 2);
620 return hi ? (0x200 | (0xD0 >> 2)) : 0xD0;
624static constexpr int genPhaseSnare(
int phaseM7,
int noise_rng)
628 return ((phaseM7 & 0x100) + 0x100)
629 ^ ((noise_rng & 1) << 8);
632static constexpr int genPhaseCymbal(
int phaseM7,
int phaseC8)
635 if (phaseC8 & 0x28) {
640 const bool bit7 = (phaseM7 & 0x80) != 0;
641 const bool bit3 = (phaseM7 & 0x08) != 0;
642 const bool bit2 = (phaseM7 & 0x04) != 0;
643 return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
649 : waveTable(sinTab[0])
650 , eg_sel_dp(eg_inc[0]), eg_sel_ar(eg_inc[0]), eg_sel_dr(eg_inc[0])
651 , eg_sel_rr(eg_inc[0]), eg_sel_rs(eg_inc[0])
662 key |= std::to_underlying(part);
668 key &=
~std::to_underlying(part);
689void Slot::setEnvelopeState(EnvelopeState state_)
696 mul = mul_tab[value];
716 AMmask = value ? ~0 : 0;
721 TL = value << (ENV_BITS - 2 - 7);
722 updateTotalLevel(channel);
727 ksl = value ? (3 - value) : 31;
728 updateTotalLevel(channel);
733 waveTable = sinTab[value];
738 fb_shift = value ? 8 - value : 0;
743 int kcodeScaled = channel.
getKeyCode() >> KSR;
744 ar = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
745 updateAttackRate(kcodeScaled);
750 int kcodeScaled = channel.
getKeyCode() >> KSR;
751 dr = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
752 updateDecayRate(kcodeScaled);
757 int kcodeScaled = channel.
getKeyCode() >> KSR;
758 rr = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
759 updateReleaseRate(kcodeScaled);
769 updateTotalLevel(channel);
775 waveTable = sinTab[0];
777 egOut = MAX_ATT_INDEX;
786 const int kcodeScaled = channel.
getKeyCode() >> KSR;
787 updateAttackRate(kcodeScaled);
788 updateDecayRate(kcodeScaled);
789 updateReleaseRate(kcodeScaled);
791 const int rs = channel.
isSustained() ? 16 + (5 << 2) : 16 + (7 << 2);
792 eg_sh_rs = eg_rate_shift[rs + kcodeScaled];
793 eg_sel_rs = eg_inc[eg_rate_select[rs + kcodeScaled]];
795 const int dp = 16 + (13 << 2);
796 eg_sh_dp = eg_rate_shift[dp + kcodeScaled];
797 eg_sel_dp = eg_inc[eg_rate_select[dp + kcodeScaled]];
799 eg_mask_rs = (1 << eg_sh_rs) - 1;
800 eg_mask_dp = (1 << eg_sh_dp) - 1;
805 if (block_fnum == block_fnum_)
return;
806 block_fnum = block_fnum_;
808 ksl_base = ksl_tab[block_fnum >> 5];
809 fc = fnumToIncrement(block_fnum * 2);
844 return (block_fnum & 0x0F00) >> 8;
907 for (
auto part :
xrange(8)) {
915 for (
const auto& e : tlTab) std::cout << e <<
'\n';
917 for (
const auto& s : sinTab) {
918 for (
const auto& e : s) std::cout << e <<
'\n';
929void YM2413::updateCustomInstrument(
int part, uint8_t value)
932 inst_tab[0][part] = value;
935 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
936 Channel& channel = channels[ch];
937 if ((reg[0x30 + ch] & 0xF0) == 0) {
943void YM2413::setRhythmFlags(uint8_t old)
945 Channel& ch6 = channels[6];
946 Channel& ch7 = channels[7];
947 Channel& ch8 = channels[8];
951 uint8_t flags = reg[0x0E];
952 if ((flags ^ old) & 0x20) {
955 ch6.updateInstrument(inst_tab[16]);
957 ch7.updateInstrument(inst_tab[17]);
958 ch7.mod.setTotalLevel(ch7, uint8_t((reg[0x37] >> 4) << 2));
960 ch8.updateInstrument(inst_tab[18]);
961 ch8.mod.setTotalLevel(ch8, uint8_t((reg[0x38] >> 4) << 2));
963 ch6.updateInstrument(inst_tab[reg[0x36] >> 4]);
964 ch7.updateInstrument(inst_tab[reg[0x37] >> 4]);
965 ch8.updateInstrument(inst_tab[reg[0x38] >> 4]);
968 ch6.mod.setKeyOff(RHYTHM);
969 ch6.car.setKeyOff(RHYTHM);
971 ch7.mod.setKeyOff(RHYTHM);
973 ch7.car.setKeyOff(RHYTHM);
975 ch8.mod.setKeyOff(RHYTHM);
977 ch8.car.setKeyOff(RHYTHM);
982 ch6.mod.setKeyOnOff(RHYTHM, (flags & 0x10) != 0);
983 ch6.car.setKeyOnOff(RHYTHM, (flags & 0x10) != 0);
985 ch7.mod.setKeyOnOff(RHYTHM, (flags & 0x01) != 0);
987 ch7.car.setKeyOnOff(RHYTHM, (flags & 0x08) != 0);
989 ch8.mod.setKeyOnOff(RHYTHM, (flags & 0x04) != 0);
991 ch8.car.setKeyOnOff(RHYTHM, (flags & 0x02) != 0);
1006 for (uint8_t i = 0x3F; i >= 0x10; --i) {
1014void YM2413::resetOperators()
1016 for (
auto& ch : channels) {
1017 ch.mod.resetOperators();
1018 ch.car.resetOperators();
1022bool YM2413::isRhythm()
const
1024 return (reg[0x0E] & 0x20) != 0;
1027Channel& YM2413::getChannelForReg(uint8_t r)
1029 uint8_t chan = (r & 0x0F) % 9;
1030 return channels[chan];
1035 return 1.0f / 2048.0f;
1045 unsigned channelActiveBits = 0;
1047 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
1048 if (channels[ch].car.isActive()) {
1049 channelActiveBits |= 1 << ch;
1056 for (
auto ch :
xrange(6, 9)) {
1057 if (channels[ch].car.isActive()) {
1058 channelActiveBits |= 1 << ch;
1060 bufs[ch + 3] =
nullptr;
1063 if (channels[7].mod.isActive()) {
1064 channelActiveBits |= 1 << (7 + 9);
1068 if (channels[8].mod.isActive()) {
1069 channelActiveBits |= 1 << (8 + 9);
1077 if (channelActiveBits) {
1092 for (
auto i :
xrange(num)) {
1097 if (lfo_am_cnt ==
LFOAMIndex(LFO_AM_TAB_ELEMENTS)) {
1101 unsigned lfo_am = lfo_am_table[lfo_am_cnt.
toInt()] >> 1;
1102 unsigned lfo_pm = lfo_pm_cnt.
toInt() & 7;
1104 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
1105 Channel& channel = channels[ch];
1106 int fm = channel.
mod.
calc_slot_mod(channel, eg_cnt,
false, lfo_pm, lfo_am);
1107 if ((channelActiveBits >> ch) & 1) {
1108 bufs[ch][i] += narrow_cast<float>(channel.
calcOutput(eg_cnt, lfo_pm, lfo_am, fm));
1119 Channel& channel6 = channels[6];
1120 int fm = channel6.
mod.
calc_slot_mod(channels[6], eg_cnt,
true, lfo_pm, lfo_am);
1121 if (channelActiveBits & (1 << 6)) {
1122 bufs[ 9][i] += narrow_cast<float>(2 * channel6.
calcOutput(eg_cnt, lfo_pm, lfo_am, fm));
1129 (void)channels[7].car.calc_phase(channels[7], lfo_pm);
1130 int phaseM7 = channels[7].mod.calc_phase(channels[7], lfo_pm);
1131 int phaseC8 = channels[8].car.calc_phase(channels[8], lfo_pm);
1132 int phaseM8 = channels[8].mod.calc_phase(channels[8], lfo_pm);
1135 if (channelActiveBits & (1 << 7)) {
1136 Slot& SLOT7_2 = channels[7].car;
1137 bufs[10][i] += narrow_cast<float>(2 * SLOT7_2.
calcOutput(channels[7], eg_cnt,
true, lfo_am, genPhaseSnare(phaseM7, noise_rng)));
1141 if (channelActiveBits & (1 << 8)) {
1142 Slot& SLOT8_2 = channels[8].car;
1143 bufs[11][i] += narrow_cast<float>(2 * SLOT8_2.
calcOutput(channels[8], eg_cnt,
true, lfo_am, genPhaseCymbal(phaseM7, phaseC8)));
1147 if (channelActiveBits & (1 << (7 + 9))) {
1148 Slot& SLOT7_1 = channels[7].mod;
1149 bufs[12][i] += narrow_cast<float>(2 * SLOT7_1.
calcOutput(channels[7], eg_cnt,
true, lfo_am, genPhaseHighHat(phaseM7, phaseC8, noise_rng)));
1153 if (channelActiveBits & (1 << (8 + 9))) {
1154 Slot& SLOT8_1 = channels[8].mod;
1155 bufs[13][i] += narrow_cast<float>(2 * SLOT8_1.
calcOutput(channels[8], eg_cnt,
true, lfo_am, phaseM8));
1184 if (noise_rng & 1) {
1185 noise_rng ^= 0x800302;
1194 registerLatch = value;
1196 writeReg(registerLatch & 0x3f, value);
1205void YM2413::writeReg(uint8_t r, uint8_t v)
1207 uint8_t old = reg[r];
1222 updateCustomInstrument(r, v);
1225 setRhythmFlags(old);
1232 Channel& ch = getChannelForReg(r);
1233 ch.setFrequencyLow(v);
1238 Channel& ch = getChannelForReg(r);
1241 ch.setSustain((v & 0x20) != 0);
1245 ch.setFrequencyHigh(v & 0x0F);
1249 Channel& ch = getChannelForReg(r);
1250 ch.car.setTotalLevel(ch, uint8_t((v & 0x0F) << 2));
1255 uint8_t chan = (r & 0x0F) % 9;
1256 if (isRhythm() && (chan >= 6)) {
1260 ch.mod.setTotalLevel(ch, uint8_t((v >> 4) << 2));
1263 if ((old & 0xF0) != (v & 0xF0)) {
1264 ch.updateInstrument(inst_tab[v >> 4]);