33 namespace YM2413Burczynski {
53 static constexpr
int DV(
double x) {
return int(
x / 0.1875); }
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),
60 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.000),DV( 0.000),DV( 0.000),
64 DV( 0.000),DV( 0.750),DV( 1.125),DV( 1.500),
65 DV( 1.875),DV( 2.250),DV( 2.625),DV( 3.000),
67 DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
68 DV( 0.000),DV( 1.125),DV( 1.875),DV( 2.625),
69 DV( 3.000),DV( 3.750),DV( 4.125),DV( 4.500),
70 DV( 4.875),DV( 5.250),DV( 5.625),DV( 6.000),
72 DV( 0.000),DV( 0.000),DV( 0.000),DV( 1.875),
73 DV( 3.000),DV( 4.125),DV( 4.875),DV( 5.625),
74 DV( 6.000),DV( 6.750),DV( 7.125),DV( 7.500),
75 DV( 7.875),DV( 8.250),DV( 8.625),DV( 9.000),
77 DV( 0.000),DV( 0.000),DV( 3.000),DV( 4.875),
78 DV( 6.000),DV( 7.125),DV( 7.875),DV( 8.625),
79 DV( 9.000),DV( 9.750),DV(10.125),DV(10.500),
80 DV(10.875),DV(11.250),DV(11.625),DV(12.000),
82 DV( 0.000),DV( 3.000),DV( 6.000),DV( 7.875),
83 DV( 9.000),DV(10.125),DV(10.875),DV(11.625),
84 DV(12.000),DV(12.750),DV(13.125),DV(13.500),
85 DV(13.875),DV(14.250),DV(14.625),DV(15.000),
87 DV( 0.000),DV( 6.000),DV( 9.000),DV(10.875),
88 DV(12.000),DV(13.125),DV(13.875),DV(14.625),
89 DV(15.000),DV(15.750),DV(16.125),DV(16.500),
90 DV(16.875),DV(17.250),DV(17.625),DV(18.000),
92 DV( 0.000),DV( 9.000),DV(12.000),DV(13.875),
93 DV(15.000),DV(16.125),DV(16.875),DV(17.625),
94 DV(18.000),DV(18.750),DV(19.125),DV(19.500),
95 DV(19.875),DV(20.250),DV(20.625),DV(21.000)
100 static constexpr
int SC(
int db) {
return int(
double(db) /
ENV_STEP); }
102 SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
103 SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(15)
110 { 0,1, 0,1, 0,1, 0,1, },
111 { 0,1, 0,1, 1,1, 0,1, },
112 { 0,1, 1,1, 0,1, 1,1, },
113 { 0,1, 1,1, 1,1, 1,1, },
115 { 1,1, 1,1, 1,1, 1,1, },
116 { 1,1, 1,2, 1,1, 1,2, },
117 { 1,2, 1,2, 1,2, 1,2, },
118 { 1,2, 2,2, 1,2, 2,2, },
120 { 2,2, 2,2, 2,2, 2,2, },
121 { 2,2, 2,4, 2,2, 2,4, },
122 { 2,4, 2,4, 2,4, 2,4, },
123 { 2,4, 4,4, 2,4, 4,4, },
125 { 4,4, 4,4, 4,4, 4,4, },
126 { 8,8, 8,8, 8,8, 8,8, },
127 { 0,0, 0,0, 0,0, 0,0, },
135 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
162 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 static constexpr uint8_t ML(
double x) {
return uint8_t(2 *
x); }
207 ML( 0.50), ML( 1.00), ML( 2.00), ML( 3.00),
208 ML( 4.00), ML( 5.00), ML( 6.00), ML( 7.00),
209 ML( 8.00), ML( 9.00), ML(10.00), ML(10.00),
210 ML(12.00), ML(12.00), ML(15.00), ML(15.00),
219 std::array<int, TL_TAB_LEN> result = {};
221 double m = (1 << 16) / cstd::exp2<6>((
x + 1) * (
ENV_STEP / 4.0) / 8.0);
227 n = (n >> 1) + (n & 1);
229 for (
auto i :
xrange(11)) {
231 result[
x * 2 + 1 + i * 2 *
TL_RES_LEN] = -(n >> i);
240 std::array<unsigned, SIN_LEN * 2> result = {};
244 double m = cstd::sin<2>(((i * 2) + 1) *
M_PI /
SIN_LEN);
245 int n = int(
cstd::round(cstd::log2<8, 3>(m) * -256.0));
252 result[
SIN_LEN / 2 + i] = result[i] | 1;
255 result[i +
SIN_LEN] = result[i];
336 { 0, 0, 0, 0, 0, 0, 0, 0, },
339 { 1, 0, 0, 0,-1, 0, 0, 0, },
342 { 2, 1, 0,-1,-2,-1, 0, 1, },
345 { 3, 1, 0,-1,-3,-1, 0, 1, },
348 { 4, 2, 0,-2,-4,-2, 0, 2, },
351 { 5, 2, 0,-2,-5,-2, 0, 2, },
354 { 6, 3, 0,-3,-6,-3, 0, 3, },
357 { 7, 3, 0,-3,-7,-3, 0, 3, },
365 constexpr uint8_t
table[16 + 3][8] = {
368 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
369 { 0x61, 0x61, 0x1e, 0x17, 0xf0, 0x7f, 0x00, 0x17 },
370 { 0x13, 0x41, 0x16, 0x0e, 0xfd, 0xf4, 0x23, 0x23 },
371 { 0x03, 0x01, 0x9a, 0x04, 0xf3, 0xf3, 0x13, 0xf3 },
372 { 0x11, 0x61, 0x0e, 0x07, 0xfa, 0x64, 0x70, 0x17 },
373 { 0x22, 0x21, 0x1e, 0x06, 0xf0, 0x76, 0x00, 0x28 },
374 { 0x21, 0x22, 0x16, 0x05, 0xf0, 0x71, 0x00, 0x18 },
375 { 0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x17, 0x17 },
376 { 0x23, 0x21, 0x2d, 0x16, 0x90, 0x90, 0x00, 0x07 },
377 { 0x21, 0x21, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 },
378 { 0x21, 0x21, 0x0b, 0x1a, 0x85, 0xa0, 0x70, 0x07 },
379 { 0x23, 0x01, 0x83, 0x10, 0xff, 0xb4, 0x10, 0xf4 },
380 { 0x97, 0xc1, 0x20, 0x07, 0xff, 0xf4, 0x22, 0x22 },
381 { 0x61, 0x00, 0x0c, 0x05, 0xc2, 0xf6, 0x40, 0x44 },
382 { 0x01, 0x01, 0x56, 0x03, 0x94, 0xc2, 0x03, 0x12 },
383 { 0x21, 0x01, 0x89, 0x03, 0xf1, 0xe4, 0xf0, 0x23 },
390 { 0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },
391 { 0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },
392 { 0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },
395 static constexpr
FreqIndex fnumToIncrement(
int block_fnum)
399 const int block = (block_fnum & 0x1C00) >> 10;
400 return FreqIndex(block_fnum & 0x03FF) >> (11 - block);
411 if (!(eg_cnt & eg_mask_dp)) {
412 egOut += eg_sel_dp[(eg_cnt >> eg_sh_dp) & 7];
422 if (!(eg_cnt & eg_mask_ar)) {
424 (~egOut * eg_sel_ar[(eg_cnt >> eg_sh_ar) & 7]) >> 2;
433 if (!(eg_cnt & eg_mask_dr)) {
434 egOut += eg_sel_dr[(eg_cnt >> eg_sh_dr) & 7];
453 if (!(eg_cnt & eg_mask_rr)) {
454 egOut += eg_sel_rr[(eg_cnt >> eg_sh_rr) & 7];
467 const bool sustain = !eg_sustain || channel.
isSustained();
468 const unsigned mask = sustain ? eg_mask_rs : eg_mask_rr;
469 if (!(eg_cnt &
mask)) {
470 const uint8_t shift = sustain ? eg_sh_rs : eg_sh_rr;
471 const uint8_t* sel = sustain ? eg_sel_rs : eg_sel_rr;
472 egOut += sel[(eg_cnt >> shift) & 7];
492 phase += fnumToIncrement(
499 return phase.
toInt();
502 inline void Slot::updateTotalLevel(
Channel& channel)
507 inline void Slot::updateAttackRate(
int kcodeScaled)
509 if ((ar + kcodeScaled) < (16 + 62)) {
516 eg_mask_ar = (1 << eg_sh_ar) - 1;
519 inline void Slot::updateDecayRate(
int kcodeScaled)
523 eg_mask_dr = (1 << eg_sh_dr) - 1;
526 inline void Slot::updateReleaseRate(
int kcodeScaled)
530 eg_mask_rr = (1 << eg_sh_rr) - 1;
534 unsigned lfo_am,
int phase2)
537 int env = (TLL + egOut2 + (lfo_am & AMmask)) << 5;
538 int p = env + wavetable[phase2 &
SIN_MASK];
543 unsigned lfo_pm,
unsigned lfo_am)
548 phase2 += (op1_out[0] + op1_out[1]) >> fb_shift;
551 op1_out[0] = op1_out[1];
553 op1_out[1] =
calcOutput(channel, eg_cnt, carrier, lfo_am, phase2);
554 return op1_out[0] << 1;
602 static constexpr
int genPhaseHighHat(
int phaseM7,
int phaseC8,
int noise_rng)
607 if (phaseC8 & 0x28) {
612 const bool bit7 = (phaseM7 & 0x80) != 0;
613 const bool bit3 = (phaseM7 & 0x08) != 0;
614 const bool bit2 = (phaseM7 & 0x04) != 0;
615 return bool((bit2 ^ bit7) | bit3);
619 return hi ? (0x200 | 0xD0) : (0xD0 >> 2);
621 return hi ? (0x200 | (0xD0 >> 2)) : 0xD0;
625 static constexpr
int genPhaseSnare(
int phaseM7,
int noise_rng)
629 return ((phaseM7 & 0x100) + 0x100)
630 ^ ((noise_rng & 1) << 8);
633 static constexpr
int genPhaseCymbal(
int phaseM7,
int phaseC8)
636 if (phaseC8 & 0x28) {
641 const bool bit7 = (phaseM7 & 0x80) != 0;
642 const bool bit3 = (phaseM7 & 0x08) != 0;
643 const bool bit2 = (phaseM7 & 0x04) != 0;
644 return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
652 ar = dr = rr = KSR = ksl = mul = 0;
653 fb_shift = op1_out[0] = op1_out[1] = 0;
654 TL = TLL = egOut = sl = 0;
655 eg_sh_dp = eg_sh_ar = eg_sh_dr = eg_sh_rr = eg_sh_rs = 0;
656 eg_sel_dp = eg_sel_ar = eg_sel_dr = eg_sel_rr = eg_sel_rs =
eg_inc[0];
657 eg_mask_dp = eg_mask_ar = eg_mask_dr = eg_mask_rr = eg_mask_rs = 0;
660 key = AMmask = vib = 0;
726 AMmask = value ? ~0 : 0;
732 updateTotalLevel(channel);
737 ksl = value ? (3 - value) : 31;
738 updateTotalLevel(channel);
748 fb_shift = value ? 8 - value : 0;
753 int kcodeScaled = channel.
getKeyCode() >> KSR;
754 ar = value ? 16 + (value << 2) : 0;
755 updateAttackRate(kcodeScaled);
760 int kcodeScaled = channel.
getKeyCode() >> KSR;
761 dr = value ? 16 + (value << 2) : 0;
762 updateDecayRate(kcodeScaled);
767 int kcodeScaled = channel.
getKeyCode() >> KSR;
768 rr = value ? 16 + (value << 2) : 0;
769 updateReleaseRate(kcodeScaled);
779 updateTotalLevel(channel);
796 const int kcodeScaled = channel.
getKeyCode() >> KSR;
797 updateAttackRate(kcodeScaled);
798 updateDecayRate(kcodeScaled);
799 updateReleaseRate(kcodeScaled);
801 const int rs = channel.
isSustained() ? 16 + (5 << 2) : 16 + (7 << 2);
805 const int dp = 16 + (13 << 2);
809 eg_mask_rs = (1 << eg_sh_rs) - 1;
810 eg_mask_dp = (1 << eg_sh_dp) - 1;
816 block_fnum = ksl_base = 0;
822 if (block_fnum == block_fnum_)
return;
823 block_fnum = block_fnum_;
825 ksl_base =
ksl_tab[block_fnum >> 5];
826 fc = fnumToIncrement(block_fnum * 2);
861 return (block_fnum & 0x0F00) >> 8;
924 for (
auto part :
xrange(8)) {
930 : lfo_am_cnt(0), lfo_pm_cnt(0)
933 for (
const auto& e :
tlTab) std::cout << e <<
'\n';
935 for (
const auto& e :
sinTab) std::cout << e <<
'\n';
938 memset(reg, 0,
sizeof(reg));
945 void YM2413::updateCustomInstrument(
int part, uint8_t value)
948 inst_tab[0][part] = value;
951 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
952 Channel& channel = channels[ch];
953 if ((reg[0x30 + ch] & 0xF0) == 0) {
959 void YM2413::setRhythmFlags(uint8_t old)
961 Channel& ch6 = channels[6];
962 Channel& ch7 = channels[7];
963 Channel& ch8 = channels[8];
966 uint8_t flags = reg[0x0E];
967 if ((flags ^ old) & 0x20) {
970 ch6.updateInstrument(inst_tab[16]);
972 ch7.updateInstrument(inst_tab[17]);
973 ch7.mod.setTotalLevel(ch7, (reg[0x37] >> 4) << 2);
975 ch8.updateInstrument(inst_tab[18]);
976 ch8.mod.setTotalLevel(ch8, (reg[0x38] >> 4) << 2);
978 ch6.updateInstrument(inst_tab[reg[0x36] >> 4]);
979 ch7.updateInstrument(inst_tab[reg[0x37] >> 4]);
980 ch8.updateInstrument(inst_tab[reg[0x38] >> 4]);
1016 for (
auto instrument :
xrange(19)) {
1022 for (
int i = 0x3F; i >= 0x10; --i) {
1030 void YM2413::resetOperators()
1032 for (
auto& ch : channels) {
1033 ch.mod.resetOperators();
1034 ch.car.resetOperators();
1038 bool YM2413::isRhythm()
const
1040 return (reg[0x0E] & 0x20) != 0;
1043 Channel& YM2413::getChannelForReg(uint8_t r)
1045 uint8_t chan = (r & 0x0F) % 9;
1046 return channels[chan];
1051 return 1.0f / 2048.0f;
1061 unsigned channelActiveBits = 0;
1063 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
1064 if (channels[ch].car.isActive()) {
1065 channelActiveBits |= 1 << ch;
1071 std::fill_n(bufs + 6, 3,
nullptr);
1072 for (
auto ch :
xrange(6, 9)) {
1073 if (channels[ch].car.isActive()) {
1074 channelActiveBits |= 1 << ch;
1076 bufs[ch + 3] =
nullptr;
1079 if (channels[7].mod.isActive()) {
1080 channelActiveBits |= 1 << (7 + 9);
1084 if (channels[8].mod.isActive()) {
1085 channelActiveBits |= 1 << (8 + 9);
1090 std::fill_n(bufs + 9, 5,
nullptr);
1093 if (channelActiveBits) {
1108 for (
auto i :
xrange(num)) {
1118 unsigned lfo_pm = lfo_pm_cnt.
toInt() & 7;
1120 for (
auto ch :
xrange(isRhythm() ? 6 : 9)) {
1121 Channel& channel = channels[ch];
1122 int fm = channel.
mod.
calc_slot_mod(channel, eg_cnt,
false, lfo_pm, lfo_am);
1123 if ((channelActiveBits >> ch) & 1) {
1124 bufs[ch][i] += channel.
calcOutput(eg_cnt, lfo_pm, lfo_am, fm);
1135 Channel& channel6 = channels[6];
1136 int fm = channel6.
mod.
calc_slot_mod(channels[6], eg_cnt,
true, lfo_pm, lfo_am);
1137 if (channelActiveBits & (1 << 6)) {
1138 bufs[ 9][i] += 2 * channel6.
calcOutput(eg_cnt, lfo_pm, lfo_am, fm);
1145 (void)channels[7].car.calc_phase(channels[7], lfo_pm);
1146 int phaseM7 = channels[7].mod.calc_phase(channels[7], lfo_pm);
1147 int phaseC8 = channels[8].car.calc_phase(channels[8], lfo_pm);
1148 int phaseM8 = channels[8].mod.calc_phase(channels[8], lfo_pm);
1151 if (channelActiveBits & (1 << 7)) {
1152 Slot& SLOT7_2 = channels[7].car;
1153 bufs[10][i] += 2 * SLOT7_2.
calcOutput(channels[7], eg_cnt,
true, lfo_am, genPhaseSnare(phaseM7, noise_rng));
1157 if (channelActiveBits & (1 << 8)) {
1158 Slot& SLOT8_2 = channels[8].car;
1159 bufs[11][i] += 2 * SLOT8_2.
calcOutput(channels[8], eg_cnt,
true, lfo_am, genPhaseCymbal(phaseM7, phaseC8));
1163 if (channelActiveBits & (1 << (7 + 9))) {
1164 Slot& SLOT7_1 = channels[7].mod;
1165 bufs[12][i] += 2 * SLOT7_1.
calcOutput(channels[7], eg_cnt,
true, lfo_am, genPhaseHighHat(phaseM7, phaseC8, noise_rng));
1169 if (channelActiveBits & (1 << (8 + 9))) {
1170 Slot& SLOT8_1 = channels[8].mod;
1171 bufs[13][i] += 2 * SLOT8_1.
calcOutput(channels[8], eg_cnt,
true, lfo_am, phaseM8);
1200 if (noise_rng & 1) {
1201 noise_rng ^= 0x800302;
1210 registerLatch = value;
1212 writeReg(registerLatch & 0x3f, value);
1221 void YM2413::writeReg(uint8_t r, uint8_t v)
1223 uint8_t old = reg[r];
1238 updateCustomInstrument(r, v);
1241 setRhythmFlags(old);
1248 Channel& ch = getChannelForReg(r);
1249 ch.setFrequencyLow(v);
1254 Channel& ch = getChannelForReg(r);
1257 ch.setSustain((v & 0x20) != 0);
1261 ch.setFrequencyHigh(v & 0x0F);
1265 Channel& ch = getChannelForReg(r);
1266 ch.car.setTotalLevel(ch, (v & 0x0F) << 2);
1271 uint8_t chan = (r & 0x0F) % 9;
1272 if (isRhythm() && (chan >= 6)) {
1276 ch.mod.setTotalLevel(ch, (v >> 4) << 2);
1279 if ((old & 0xF0) != (v & 0xF0)) {
1280 ch.updateInstrument(inst_tab[v >> 4]);
1297 static constexpr std::initializer_list<enum_string<YM2413Burczynski::Slot::EnvelopeState>> envelopeStateInfo = {
1307 namespace YM2413Burczynski {
1313 template<
typename Archive>
1324 a.serialize(
"phase", phase,
1330 "eg_sustain", eg_sustain,
1331 "fb_shift", fb_shift,
1352 template<
typename Archive>
1365 "ksl_base", ksl_base,
1378 template<
typename Archive>
1381 if (a.versionBelow(version, 2)) a.beginTag(
"YM2413Core");
1382 a.serialize(
"registers", reg);
1383 if (a.versionBelow(version, 2)) a.endTag(
"YM2413Core");
1386 a.serialize_blob(
"user_instrument", inst_tab[0], 8);
1387 a.serialize(
"channels", channels,
1389 "noise_rng", noise_rng,
1390 "lfo_am_cnt", lfo_am_cnt,
1391 "lfo_pm_cnt", lfo_pm_cnt);
1392 if (a.versionAtLeast(version, 4)) {
1393 a.serialize(
"registerLatch", registerLatch);
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
constexpr void addQuantum()
Increase this value with the smallest possible amount.
void setSustain(bool sustained)
FreqIndex getFrequencyIncrement() const
void updateInstrumentPart(int part, uint8_t value)
Sets some synthesis parameters as specified by the instrument.
void setFrequencyLow(uint8_t value)
Changes the lower 8 bits of the frequency for this channel.
void serialize(Archive &ar, unsigned version)
uint8_t getKeyCode() const
int getKeyScaleLevelBase() const
void setFrequency(int block_fnum)
Sets the frequency for this channel.
void updateInstrument(const uint8_t *inst)
Sets all synthesis parameters as specified by the instrument.
void setFrequencyHigh(uint8_t value)
Changes the higher 4 bits of the frequency for this channel.
int calcOutput(unsigned eg_cnt, unsigned lfo_pm, unsigned lfo_am, int fm)
Calculate the value of the current sample produced by this channel.
void setSustainLevel(uint8_t value)
Sets the sustain level [0..15].
EnvelopeState
Envelope Generator phases Note: These are ordered: phase constants are compared in the code.
void updateFrequency(Channel &channel)
Called by Channel when block_fnum changes.
void setEnvelopeSustained(bool value)
Sets the envelope type of the current instrument.
void setKeyOff(KeyPart part)
void setKeyOnOff(KeyPart part, bool enabled)
void setAttackRate(const Channel &channel, uint8_t value)
Sets the attack rate [0..15].
int calcOutput(Channel &channel, unsigned eg_cnt, bool carrier, unsigned lfo_am, int phase)
void setTotalLevel(Channel &channel, uint8_t value)
Sets the total level: [0..63].
void setFrequencyMultiplier(uint8_t value)
Sets the frequency multiplier [0..15].
void setReleaseRate(const Channel &channel, uint8_t value)
Sets the release rate [0..15].
void setWaveform(uint8_t value)
Sets the waveform: 0 = sinus, 1 = half sinus, half silence.
int calc_envelope(Channel &channel, unsigned eg_cnt, bool carrier)
void serialize(Archive &ar, unsigned version)
void setVibrato(bool value)
Enables (true) or disables (false) vibrato.
int calc_phase(Channel &channel, unsigned lfo_pm)
void setAmplitudeModulation(bool value)
Enables (true) or disables (false) amplitude modulation.
void setKeyOn(KeyPart part)
void setDecayRate(const Channel &channel, uint8_t value)
Sets the decay rate [0..15].
void setKeyScaleLevel(Channel &channel, uint8_t value)
Sets the key scale level: 0->0 / 1->1.5 / 2->3.0 / 3->6.0 dB/OCT.
void setFeedbackShift(uint8_t value)
Sets the amount of feedback [0..7].
bool isActive() const
Does this slot currently produce an output signal?
int calc_slot_mod(Channel &channel, unsigned eg_cnt, bool carrier, unsigned lfo_pm, unsigned lfo_am)
void setKeyScaleRate(bool value)
Sets the key scale rate: true->0, false->2.
void updateGenerators(Channel &channel)
Update phase increment counter of operator.
void writePort(bool port, uint8_t value, int offset) override
Write to the YM2413 register/data port.
void serialize(Archive &ar, unsigned version)
void reset() override
Reset this YM2413 core.
void pokeReg(uint8_t reg, uint8_t value) override
Write to a YM2413 register (for debug).
float getAmplificationFactor() const override
Returns normalization factor.
void generateChannels(float *bufs[9+5], unsigned num) override
uint8_t peekReg(uint8_t reg) const override
Read from a YM2413 register (for debug).
Abstract interface for the YM2413 core.
static constexpr int CLOCK_FREQ
Input clock frequency.
constexpr double round(double x)
constexpr uint8_t eg_rate_select[16+64+16]
constexpr int MAX_ATT_INDEX
constexpr uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS]
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations.
constexpr uint8_t table[16+3][8]
constexpr double ENV_STEP
constexpr int MIN_ATT_INDEX
constexpr signed char lfo_pm_table[8][8]
constexpr uint8_t mul_tab[16]
constexpr int ksl_tab[8 *16]
constexpr int LFO_AM_TAB_ELEMENTS
constexpr uint8_t eg_inc[15][8]
constexpr uint8_t eg_rate_shift[16+64+16]
constexpr unsigned const *const waveform[2]
This file implemented 3 utility functions:
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
constexpr KeyMatrixPosition x
Keyboard bindings.
constexpr nibble mask[4][13]
auto copy(InputRange &&range, OutputIter out)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
constexpr auto xrange(T e)