openMSX
YM2413Okazaki.cc
Go to the documentation of this file.
1 /*
2  * Based on:
3  * emu2413.c -- YM2413 emulator written by Mitsutaka Okazaki 2001
4  * heavily rewritten to fit openMSX structure
5  */
6 
7 #include "YM2413Okazaki.hh"
8 #include "Math.hh"
9 #include "cstd.hh"
10 #include "enumerate.hh"
11 #include "inline.hh"
12 #include "one_of.hh"
13 #include "ranges.hh"
14 #include "serialize.hh"
15 #include "unreachable.hh"
16 #include "xrange.hh"
17 #include <array>
18 #include <cstring>
19 #include <cassert>
20 #include <iostream>
21 
22 namespace openmsx {
23 namespace YM2413Okazaki {
24 
25 // Number of bits in 'PhaseModulation' fixed point type.
26 constexpr int PM_FP_BITS = 8;
27 
28 // Dynamic range (Accuracy of sin table)
29 constexpr int DB_BITS = 8;
30 constexpr int DB_MUTE = 1 << DB_BITS;
31 constexpr int DBTABLEN = 4 * DB_MUTE; // enough to not have to check for overflow
32 
33 constexpr double DB_STEP = 48.0 / DB_MUTE;
34 constexpr double EG_STEP = 0.375;
35 constexpr double TL_STEP = 0.75;
36 
37 // Size of Sintable ( 8 -- 18 can be used, but 9 recommended.)
38 constexpr int PG_BITS = 9;
39 constexpr int PG_WIDTH = 1 << PG_BITS;
40 constexpr int PG_MASK = PG_WIDTH - 1;
41 
42 // Phase increment counter
43 constexpr int DP_BITS = 18;
44 constexpr int DP_BASE_BITS = DP_BITS - PG_BITS;
45 
46 // Dynamic range of envelope
47 constexpr int EG_BITS = 7;
48 
49 // Bits for linear value
50 constexpr int DB2LIN_AMP_BITS = 8;
52 
53 // Bits for Amp modulator
54 constexpr int AM_PG_BITS = 8;
55 constexpr int AM_PG_WIDTH = 1 << AM_PG_BITS;
56 constexpr int AM_DP_BITS = 16;
57 constexpr int AM_DP_WIDTH = 1 << AM_DP_BITS;
58 constexpr int AM_DP_MASK = AM_DP_WIDTH - 1;
59 
60 // LFO Amplitude Modulation table (verified on real YM3812)
61 // 27 output levels (triangle waveform);
62 // 1 level takes one of: 192, 256 or 448 samples
63 //
64 // Length: 210 elements.
65 // Each of the elements has to be repeated
66 // exactly 64 times (on 64 consecutive samples).
67 // The whole table takes: 64 * 210 = 13440 samples.
68 //
69 // Verified on real YM3812 (OPL2), but I believe it's the same for YM2413
70 // because it closely matches the YM2413 AM parameters:
71 // speed = 3.7Hz
72 // depth = 4.875dB
73 // Also this approach can be easily implemented in HW, the previous one (see SVN
74 // history) could not.
75 constexpr unsigned LFO_AM_TAB_ELEMENTS = 210;
76 
77 // Extra (derived) constants
79 constexpr EnvPhaseIndex EG_DP_INF = EnvPhaseIndex(1 << 8); // as long as it's bigger
80 
81 // LFO Phase Modulation table (copied from Burczynski core)
82 constexpr signed char pmTable[8][8] =
83 {
84  { 0, 0, 0, 0, 0, 0, 0, 0, }, // FNUM = 000xxxxxx
85  { 0, 0, 1, 0, 0, 0,-1, 0, }, // FNUM = 001xxxxxx
86  { 0, 1, 2, 1, 0,-1,-2,-1, }, // FNUM = 010xxxxxx
87  { 0, 1, 3, 1, 0,-1,-3,-1, }, // FNUM = 011xxxxxx
88  { 0, 2, 4, 2, 0,-2,-4,-2, }, // FNUM = 100xxxxxx
89  { 0, 2, 5, 2, 0,-2,-5,-2, }, // FNUM = 101xxxxxx
90  { 0, 3, 6, 3, 0,-3,-6,-3, }, // FNUM = 110xxxxxx
91  { 0, 3, 7, 3, 0,-3,-7,-3, }, // FNUM = 111xxxxxx
92 };
93 
94 // LFO Amplitude Modulation table (verified on real YM3812)
95 constexpr unsigned char lfo_am_table[LFO_AM_TAB_ELEMENTS] = {
96  0,0,0,0,0,0,0,
97  1,1,1,1,
98  2,2,2,2,
99  3,3,3,3,
100  4,4,4,4,
101  5,5,5,5,
102  6,6,6,6,
103  7,7,7,7,
104  8,8,8,8,
105  9,9,9,9,
106  10,10,10,10,
107  11,11,11,11,
108  12,12,12,12,
109  13,13,13,13,
110  14,14,14,14,
111  15,15,15,15,
112  16,16,16,16,
113  17,17,17,17,
114  18,18,18,18,
115  19,19,19,19,
116  20,20,20,20,
117  21,21,21,21,
118  22,22,22,22,
119  23,23,23,23,
120  24,24,24,24,
121  25,25,25,25,
122  26,26,26,
123  25,25,25,25,
124  24,24,24,24,
125  23,23,23,23,
126  22,22,22,22,
127  21,21,21,21,
128  20,20,20,20,
129  19,19,19,19,
130  18,18,18,18,
131  17,17,17,17,
132  16,16,16,16,
133  15,15,15,15,
134  14,14,14,14,
135  13,13,13,13,
136  12,12,12,12,
137  11,11,11,11,
138  10,10,10,10,
139  9,9,9,9,
140  8,8,8,8,
141  7,7,7,7,
142  6,6,6,6,
143  5,5,5,5,
144  4,4,4,4,
145  3,3,3,3,
146  2,2,2,2,
147  1,1,1,1,
148 };
149 
150 // ML-table
151 constexpr uint8_t mlTable[16] = {
152  1, 1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 7*2,
153  8*2, 9*2, 10*2, 10*2, 12*2, 12*2, 15*2, 15*2
154 };
155 
156 // dB to linear table (used by Slot)
157 // dB(0 .. DB_MUTE-1) -> linear(0 .. DB2LIN_AMP_WIDTH)
158 // indices in range:
159 // [0, DB_MUTE ) actual values, from max to min
160 // [DB_MUTE, DBTABLEN) filled with min val (to allow some overflow in index)
161 // [DBTABLEN, 2*DBTABLEN) as above but for negative output values
162 constexpr auto dB2LinTab = [] {
163  std::array<int, 2 * DBTABLEN> result = {};
164  for (int i : xrange(DB_MUTE - 1)) {
165  result[i] = int(double((1 << DB2LIN_AMP_BITS) - 1) *
166  cstd::pow<5, 3>(10, -double(i) * DB_STEP / 20));
167  }
168  result[DB_MUTE - 1] = 0;
169  for (auto i : xrange(DB_MUTE, DBTABLEN)) {
170  result[i] = 0;
171  }
172  for (auto i : xrange(DBTABLEN)) {
173  result[i + DBTABLEN] = -result[i];
174  }
175  return result;
176 }();
177 
178 // Linear to Log curve conversion table (for Attack rate)
179 constexpr auto arAdjustTab = [] {
180  std::array<unsigned, 1 << EG_BITS> result = {};
181  result[0] = (1 << EG_BITS) - 1;
182  constexpr double l127 = cstd::log<5, 4>(127.0);
183  for (int i : xrange(1, 1 << EG_BITS)) {
184  result[i] = unsigned(double(1 << EG_BITS) - 1 -
185  ((1 << EG_BITS) - 1) * cstd::log<5, 4>(double(i)) / l127);
186  }
187  return result;
188 }();
189 
190 // KSL + TL Table values are in range [0, 112]
191 constexpr auto tllTab = [] {
192  std::array<std::array<uint8_t, 16 * 8>, 4> result = {};
193 
194  // Processed version of Table III-5 from the Application Manual.
195  constexpr unsigned klTable[16] = {
196  0, 24, 32, 37, 40, 43, 45, 47, 48, 50, 51, 52, 53, 54, 55, 56
197  };
198  // Note: KL [0..3] results in {0.0, 1.5, 3.0, 6.0} dB/oct.
199  // This is different from Y8950 and YMF262 which have {0, 3, 1.5, 6}.
200  // (2nd and 3rd elements are swapped). Verified on real YM2413.
201 
202  for (auto freq : xrange(16 * 8u)) {
203  unsigned fnum = freq % 16;
204  unsigned block = freq / 16;
205  int tmp = 2 * klTable[fnum] - 16 * (7 - block);
206  for (auto KL : xrange(4)) {
207  unsigned t = (tmp <= 0 || KL == 0) ? 0 : (tmp >> (3 - KL));
208  assert(t <= 112);
209  result[KL][freq] = t;
210  }
211  }
212  return result;
213 }();
214 
215 // WaveTable for each envelope amp
216 // values are in range [0, DB_MUTE) (for positive values)
217 // or [0, DB_MUTE) + DBTABLEN (for negative values)
218 constexpr auto fullSinTable = [] {
219  auto lin2db = [](double d) {
220  // lin(+0.0 .. +1.0) to dB(DB_MUTE-1 .. 0)
221  return (d == 0)
222  ? DB_MUTE - 1
223  : std::min(-int(20.0 * cstd::log10<5, 2>(d) / DB_STEP), DB_MUTE - 1); // 0 - 127
224  };
225 
226  std::array<unsigned, PG_WIDTH> result = {};
227  for (auto i : xrange(PG_WIDTH / 4)) {
228  result[i] = lin2db(cstd::sin<2>(double(2.0 * M_PI) * i / PG_WIDTH));
229  }
230  for (auto i : xrange(PG_WIDTH / 4)) {
231  result[PG_WIDTH / 2 - 1 - i] = result[i];
232  }
233  for (auto i : xrange(PG_WIDTH / 2)) {
234  result[PG_WIDTH / 2 + i] = DBTABLEN + result[i];
235  }
236  return result;
237 }();
238 constexpr auto halfSinTable = [] {
239  std::array<unsigned, PG_WIDTH> result = {};
240  for (auto i : xrange(PG_WIDTH / 2)) {
241  result[i] = fullSinTable[i];
242  }
243  for (auto i : xrange(PG_WIDTH / 2, PG_WIDTH)) {
244  result[i] = fullSinTable[0];
245  }
246  return result;
247 }();
248 constexpr unsigned const * const waveform[2] = {fullSinTable.data(), halfSinTable.data()};
249 
250 // Phase incr table for attack, decay and release
251 // note: original code had indices swapped. It also had
252 // a separate table for attack
253 // 17.15 fixed point
254 constexpr auto dPhaseDrTab = [] {
255  std::array<std::array<int, 16>, 16> result = {};
256  for (auto Rks : xrange(16)) {
257  result[Rks][0] = 0;
258  for (auto DR : xrange(1, 16)) {
259  unsigned RM = std::min(DR + (Rks >> 2), 15);
260  unsigned RL = Rks & 3;
261  result[Rks][DR] =
262  ((RL + 4) << EP_FP_BITS) >> (16 - RM);
263  }
264  }
265  return result;
266 }();
267 
268 // Sustain level (17.15 fixed point)
269 constexpr auto slTab = [] {
270  std::array<unsigned, 16> result = {};
271  //for (auto [i, r] : enumerate(result)) { msvc bug
272  for (int i = 0; i < 16; ++i) {
273  double x = (i == 15) ? 48.0 : (3.0 * i);
274  result[i] = int(x / EG_STEP) << EP_FP_BITS;
275  }
276  return result;
277 }();
278 
279 //
280 // Helper functions
281 //
282 static constexpr int EG2DB(int d)
283 {
284  return d * int(EG_STEP / DB_STEP);
285 }
286 static constexpr unsigned TL2EG(unsigned d)
287 {
288  assert(d < 64); // input is in range [0..63]
289  return d * int(TL_STEP / EG_STEP);
290 }
291 
292 static constexpr unsigned DB_POS(double x)
293 {
294  int result = int(x / DB_STEP);
295  assert(0 <= result);
296  assert(result < DB_MUTE);
297  return result;
298 }
299 static constexpr unsigned DB_NEG(double x)
300 {
301  return DBTABLEN + DB_POS(x);
302 }
303 
304 static constexpr bool BIT(unsigned s, unsigned b)
305 {
306  return (s >> b) & 1;
307 }
308 
309 //
310 // Patch
311 //
313  : AMPM(0), EG(false), AR(0), DR(0), RR(0)
314 {
315  setKR(0);
316  setML(0);
317  setKL(0);
318  setTL(0);
319  setWF(0);
320  setFB(0);
321  setSL(0);
322 }
323 
324 void Patch::initModulator(const uint8_t* data)
325 {
326  AMPM = (data[0] >> 6) & 3;
327  EG = (data[0] >> 5) & 1;
328  setKR ((data[0] >> 4) & 1);
329  setML ((data[0] >> 0) & 15);
330  setKL ((data[2] >> 6) & 3);
331  setTL ((data[2] >> 0) & 63);
332  setWF ((data[3] >> 3) & 1);
333  setFB ((data[3] >> 0) & 7);
334  AR = (data[4] >> 4) & 15;
335  DR = (data[4] >> 0) & 15;
336  setSL ((data[6] >> 4) & 15);
337  RR = (data[6] >> 0) & 15;
338 }
339 
340 void Patch::initCarrier(const uint8_t* data)
341 {
342  AMPM = (data[1] >> 6) & 3;
343  EG = (data[1] >> 5) & 1;
344  setKR ((data[1] >> 4) & 1);
345  setML ((data[1] >> 0) & 15);
346  setKL ((data[3] >> 6) & 3);
347  setTL (0);
348  setWF ((data[3] >> 4) & 1);
349  setFB (0);
350  AR = (data[5] >> 4) & 15;
351  DR = (data[5] >> 0) & 15;
352  setSL ((data[7] >> 4) & 15);
353  RR = (data[7] >> 0) & 15;
354 }
355 
356 void Patch::setKR(uint8_t value)
357 {
358  KR = value ? 8 : 10;
359 }
360 void Patch::setML(uint8_t value)
361 {
362  ML = mlTable[value];
363 }
364 void Patch::setKL(uint8_t value)
365 {
366  KL = tllTab[value].data();
367 }
368 void Patch::setTL(uint8_t value)
369 {
370  assert(value < 64);
371  assert(TL2EG(value) < 256);
372  TL = TL2EG(value);
373 }
374 void Patch::setWF(uint8_t value)
375 {
376  WF = waveform[value];
377 }
378 void Patch::setFB(uint8_t value)
379 {
380  FB = value ? 8 - value : 0;
381 }
382 void Patch::setSL(uint8_t value)
383 {
384  SL = slTab[value];
385 }
386 
387 
388 //
389 // Slot
390 //
392 {
393  cPhase = 0;
394  ranges::fill(dPhase, 0);
395  output = 0;
396  feedback = 0;
398  dPhaseDRTableRks = dPhaseDrTab[0].data();
399  tll = 0;
400  sustain = false;
401  volume = TL2EG(0);
402  slot_on_flag = 0;
403 }
404 
405 void Slot::updatePG(unsigned freq)
406 {
407  // Pre-calculate all phase-increments. The 8 different values are for
408  // the 8 steps of the PM stuff (for mod and car phase calculation).
409  // When PM isn't used then dPhase[0] is used (pmTable[.][0] == 0).
410  // The original Okazaki core calculated the PM stuff in a different
411  // way. This algorithm was copied from the Burczynski core because it
412  // is much more suited for a (cheap) hardware calculation.
413  unsigned fnum = freq & 511;
414  unsigned block = freq / 512;
415  for (auto [pm, dP] : enumerate(dPhase)) {
416  unsigned tmp = ((2 * fnum + pmTable[fnum >> 6][pm]) * patch.ML) << block;
417  dP = tmp >> (21 - DP_BITS);
418  }
419 }
420 
421 void Slot::updateTLL(unsigned freq, bool actAsCarrier)
422 {
423  tll = patch.KL[freq >> 5] + (actAsCarrier ? volume : patch.TL);
424 }
425 
426 void Slot::updateRKS(unsigned freq)
427 {
428  unsigned rks = freq >> patch.KR;
429  assert(rks < 16);
430  dPhaseDRTableRks = dPhaseDrTab[rks].data();
431 }
432 
434 {
435  switch (state) {
436  case ATTACK:
437  // Original code had separate table for AR, the values in
438  // this table were 12 times bigger than the values in the
439  // dPhaseDRTableRks table, expect for the value for AR=15.
440  // But when AR=15, the value doesn't matter.
441  //
442  // This factor 12 can also be seen in the attack/decay rates
443  // table in the ym2413 application manual (table III-7, page
444  // 13). For other chips like OPL1, OPL3 this ratio seems to be
445  // different.
447  dPhaseDRTableRks[patch.AR] * 12);
448  break;
449  case DECAY:
451  break;
452  case SUSTAIN:
454  break;
455  case RELEASE: {
456  unsigned idx = sustain ? 5
457  : (patch.EG ? patch.RR
458  : 7);
460  break;
461  }
462  case SETTLE:
463  // Value based on ym2413 application manual:
464  // - p10: (envelope graph)
465  // DP: 10ms
466  // - p13: (table III-7 attack and decay rates)
467  // Rate 12-0 -> 10.22ms
468  // Rate 12-1 -> 8.21ms
469  // Rate 12-2 -> 6.84ms
470  // Rate 12-3 -> 5.87ms
471  // The datasheet doesn't say anything about key-scaling for
472  // this state (in fact it doesn't say much at all about this
473  // state). Experiments showed that the with key-scaling the
474  // output matches closer the real HW. Also all other states use
475  // key-scaling.
477  break;
478  case SUSHOLD:
479  case FINISH:
481  break;
482  }
483 }
484 
485 void Slot::updateAll(unsigned freq, bool actAsCarrier)
486 {
487  updatePG(freq);
488  updateTLL(freq, actAsCarrier);
489  updateRKS(freq);
490  updateEG(); // EG should be updated last
491 }
492 
494 {
495  state = state_;
496  switch (state) {
497  case ATTACK:
498  eg_phase_max = (patch.AR == 15) ? EnvPhaseIndex(0) : EG_DP_MAX;
499  break;
500  case DECAY:
502  break;
503  case SUSHOLD:
505  break;
506  case SETTLE:
507  case SUSTAIN:
508  case RELEASE:
510  break;
511  case FINISH:
514  break;
515  }
516  updateEG();
517 }
518 
519 bool Slot::isActive() const
520 {
521  return state != FINISH;
522 }
523 
524 // Slot key on
526 {
528  eg_phase = EnvPhaseIndex(0);
529  cPhase = 0;
530 }
531 
532 // Slot key on, without resetting the phase
534 {
536  eg_phase = EnvPhaseIndex(0);
537 }
538 
539 // Slot key off
541 {
542  if (state == FINISH) return; // already in off state
543  if (state == ATTACK) {
545  }
547 }
548 
549 
550 // Change a rhythm voice
551 void Slot::setPatch(const Patch& newPatch)
552 {
553  patch = newPatch; // copy data
554  if ((state == SUSHOLD) && (patch.EG == 0)) {
556  }
557  setEnvelopeState(state); // recalc eg_phase_max
558 }
559 
560 // Set new volume based on 4-bit register value (0-15).
561 void Slot::setVolume(unsigned value)
562 {
563  // '<< 2' to transform 4 bits to the same range as the 6 bits TL field
564  volume = TL2EG(value << 2);
565 }
566 
567 
568 //
569 // Channel
570 //
571 
573 {
574  car.sibling = &mod; // car needs a pointer to its sibling
575  mod.sibling = nullptr; // mod doesn't need this pointer
576 }
577 
578 void Channel::reset(YM2413& ym2413)
579 {
580  mod.reset();
581  car.reset();
582  setPatch(0, ym2413);
583 }
584 
585 // Change a voice
586 void Channel::setPatch(unsigned num, YM2413& ym2413)
587 {
588  mod.setPatch(ym2413.getPatch(num, false));
589  car.setPatch(ym2413.getPatch(num, true));
590 }
591 
592 // Set sustain parameter
593 void Channel::setSustain(bool sustain, bool modActAsCarrier)
594 {
595  car.sustain = sustain;
596  if (modActAsCarrier) {
597  mod.sustain = sustain;
598  }
599 }
600 
601 // Channel key on
603 {
604  // TODO Should we also test mod.slot_on_flag?
605  // Should we set mod.slot_on_flag?
606  // Can make a difference for channel 7/8 in rythm mode.
607  if (!car.slot_on_flag) {
609  // this will shortly set both car and mod to ATTACK state
610  }
611  car.slot_on_flag |= 1;
612  mod.slot_on_flag |= 1;
613 }
614 
615 // Channel key off
617 {
618  // Note: no mod.slotOff() in original code!!!
619  if (car.slot_on_flag) {
620  car.slot_on_flag &= ~1;
621  mod.slot_on_flag &= ~1;
622  if (!car.slot_on_flag) {
623  car.slotOff();
624  }
625  }
626 }
627 
628 
629 //
630 // YM2413
631 //
632 
633 static constexpr uint8_t inst_data[16 + 3][8] = {
634  { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, // user instrument
635  { 0x61,0x61,0x1e,0x17,0xf0,0x7f,0x00,0x17 }, // violin
636  { 0x13,0x41,0x16,0x0e,0xfd,0xf4,0x23,0x23 }, // guitar
637  { 0x03,0x01,0x9a,0x04,0xf3,0xf3,0x13,0xf3 }, // piano
638  { 0x11,0x61,0x0e,0x07,0xfa,0x64,0x70,0x17 }, // flute
639  { 0x22,0x21,0x1e,0x06,0xf0,0x76,0x00,0x28 }, // clarinet
640  { 0x21,0x22,0x16,0x05,0xf0,0x71,0x00,0x18 }, // oboe
641  { 0x21,0x61,0x1d,0x07,0x82,0x80,0x17,0x17 }, // trumpet
642  { 0x23,0x21,0x2d,0x16,0x90,0x90,0x00,0x07 }, // organ
643  { 0x21,0x21,0x1b,0x06,0x64,0x65,0x10,0x17 }, // horn
644  { 0x21,0x21,0x0b,0x1a,0x85,0xa0,0x70,0x07 }, // synthesizer
645  { 0x23,0x01,0x83,0x10,0xff,0xb4,0x10,0xf4 }, // harpsichord
646  { 0x97,0xc1,0x20,0x07,0xff,0xf4,0x22,0x22 }, // vibraphone
647  { 0x61,0x00,0x0c,0x05,0xc2,0xf6,0x40,0x44 }, // synthesizer bass
648  { 0x01,0x01,0x56,0x03,0x94,0xc2,0x03,0x12 }, // acoustic bass
649  { 0x21,0x01,0x89,0x03,0xf1,0xe4,0xf0,0x23 }, // electric guitar
650  { 0x07,0x21,0x14,0x00,0xee,0xf8,0xff,0xf8 },
651  { 0x01,0x31,0x00,0x00,0xf8,0xf7,0xf8,0xf7 },
652  { 0x25,0x11,0x00,0x00,0xf8,0xfa,0xf8,0x55 }
653 };
654 
656 {
657  if (false) {
658  for (const auto& e : dB2LinTab) std::cout << e << ' ';
659  std::cout << '\n';
660 
661  for (const auto& e : arAdjustTab) std::cout << e << ' ';
662  std::cout << '\n';
663 
664  for (auto i : xrange(4)) {
665  for (auto j : xrange(16 * 8)) {
666  std::cout << int(tllTab[i][j]) << ' ';
667  }
668  std::cout << '\n';
669  }
670  std::cout << '\n';
671 
672  for (const auto& e : fullSinTable) std::cout << e << ' ';
673  std::cout << '\n';
674  for (const auto& e : halfSinTable) std::cout << e << ' ';
675  std::cout << '\n';
676 
677  for (auto i : xrange(16)) {
678  for (auto j : xrange(16)) {
679  std::cout << dPhaseDrTab[i][j] << ' ';
680  }
681  std::cout << '\n';
682  }
683  std::cout << '\n';
684 
685  for (const auto& e : slTab) std::cout << e << ' ';
686  std::cout << '\n';
687  }
688 
689  memset(reg, 0, sizeof(reg)); // avoid UMR
690 
691  for (auto i : xrange(16 + 3)) {
692  patches[i][0].initModulator(inst_data[i]);
693  patches[i][1].initCarrier (inst_data[i]);
694  }
695 
696  reset();
697 }
698 
699 // Reset whole of OPLL except patch data
701 {
702  pm_phase = 0;
703  am_phase = 0;
704  noise_seed = 0xFFFF;
705 
706  for (auto& ch : channels) {
707  ch.reset(*this);
708  }
709  for (auto i : xrange(0x40)) {
710  writeReg(i, 0);
711  }
712  registerLatch = 0;
713 }
714 
715 // Drum key on
716 void YM2413::keyOn_BD()
717 {
718  Channel& ch6 = channels[6];
719  if (!ch6.car.slot_on_flag) {
721  // this will shortly set both car and mod to ATTACK state
722  }
723  ch6.car.slot_on_flag |= 2;
724  ch6.mod.slot_on_flag |= 2;
725 }
726 void YM2413::keyOn_HH()
727 {
728  // TODO do these also use the SETTLE stuff?
729  Channel& ch7 = channels[7];
730  if (!ch7.mod.slot_on_flag) {
731  ch7.mod.slotOn2();
732  }
733  ch7.mod.slot_on_flag |= 2;
734 }
735 void YM2413::keyOn_SD()
736 {
737  Channel& ch7 = channels[7];
738  if (!ch7.car.slot_on_flag) {
739  ch7.car.slotOn();
740  }
741  ch7.car.slot_on_flag |= 2;
742 }
743 void YM2413::keyOn_TOM()
744 {
745  Channel& ch8 = channels[8];
746  if (!ch8.mod.slot_on_flag) {
747  ch8.mod.slotOn();
748  }
749  ch8.mod.slot_on_flag |= 2;
750 }
751 void YM2413::keyOn_CYM()
752 {
753  Channel& ch8 = channels[8];
754  if (!ch8.car.slot_on_flag) {
755  ch8.car.slotOn2();
756  }
757  ch8.car.slot_on_flag |= 2;
758 }
759 
760 // Drum key off
761 void YM2413::keyOff_BD()
762 {
763  Channel& ch6 = channels[6];
764  if (ch6.car.slot_on_flag) {
765  ch6.car.slot_on_flag &= ~2;
766  ch6.mod.slot_on_flag &= ~2;
767  if (!ch6.car.slot_on_flag) {
768  ch6.car.slotOff();
769  }
770  }
771 }
772 void YM2413::keyOff_HH()
773 {
774  Channel& ch7 = channels[7];
775  if (ch7.mod.slot_on_flag) {
776  ch7.mod.slot_on_flag &= ~2;
777  if (!ch7.mod.slot_on_flag) {
778  ch7.mod.slotOff();
779  }
780  }
781 }
782 void YM2413::keyOff_SD()
783 {
784  Channel& ch7 = channels[7];
785  if (ch7.car.slot_on_flag) {
786  ch7.car.slot_on_flag &= ~2;
787  if (!ch7.car.slot_on_flag) {
788  ch7.car.slotOff();
789  }
790  }
791 }
792 void YM2413::keyOff_TOM()
793 {
794  Channel& ch8 = channels[8];
795  if (ch8.mod.slot_on_flag) {
796  ch8.mod.slot_on_flag &= ~2;
797  if (!ch8.mod.slot_on_flag) {
798  ch8.mod.slotOff();
799  }
800  }
801 }
802 void YM2413::keyOff_CYM()
803 {
804  Channel& ch8 = channels[8];
805  if (ch8.car.slot_on_flag) {
806  ch8.car.slot_on_flag &= ~2;
807  if (!ch8.car.slot_on_flag) {
808  ch8.car.slotOff();
809  }
810  }
811 }
812 
813 void YM2413::setRhythmFlags(uint8_t old)
814 {
815  Channel& ch6 = channels[6];
816  Channel& ch7 = channels[7];
817  Channel& ch8 = channels[8];
818 
819  // flags = X | X | mode | BD | SD | TOM | TC | HH
820  uint8_t flags = reg[0x0E];
821  if ((flags ^ old) & 0x20) {
822  if (flags & 0x20) {
823  // OFF -> ON
824  ch6.setPatch(16, *this);
825  ch7.setPatch(17, *this);
826  ch7.mod.setVolume(reg[0x37] >> 4);
827  ch8.setPatch(18, *this);
828  ch8.mod.setVolume(reg[0x38] >> 4);
829  } else {
830  // ON -> OFF
831  ch6.setPatch(reg[0x36] >> 4, *this);
832  keyOff_BD();
833  ch7.setPatch(reg[0x37] >> 4, *this);
834  keyOff_SD();
835  keyOff_HH();
836  ch8.setPatch(reg[0x38] >> 4, *this);
837  keyOff_TOM();
838  keyOff_CYM();
839  }
840  }
841  if (flags & 0x20) {
842  if (flags & 0x10) keyOn_BD(); else keyOff_BD();
843  if (flags & 0x08) keyOn_SD(); else keyOff_SD();
844  if (flags & 0x04) keyOn_TOM(); else keyOff_TOM();
845  if (flags & 0x02) keyOn_CYM(); else keyOff_CYM();
846  if (flags & 0x01) keyOn_HH(); else keyOff_HH();
847  }
848 
849  unsigned freq6 = getFreq(6);
850  ch6.mod.updateAll(freq6, false);
851  ch6.car.updateAll(freq6, true);
852  unsigned freq7 = getFreq(7);
853  ch7.mod.updateAll(freq7, isRhythm());
854  ch7.car.updateAll(freq7, true);
855  unsigned freq8 = getFreq(8);
856  ch8.mod.updateAll(freq8, isRhythm());
857  ch8.car.updateAll(freq8, true);
858 }
859 
860 void YM2413::update_key_status()
861 {
862  for (auto [i, ch] : enumerate(channels)) {
863  int slot_on = (reg[0x20 + i] & 0x10) ? 1 : 0;
864  ch.mod.slot_on_flag = slot_on;
865  ch.car.slot_on_flag = slot_on;
866  }
867  if (isRhythm()) {
868  Channel& ch6 = channels[6];
869  ch6.mod.slot_on_flag |= (reg[0x0e] & 0x10) ? 2 : 0; // BD1
870  ch6.car.slot_on_flag |= (reg[0x0e] & 0x10) ? 2 : 0; // BD2
871  Channel& ch7 = channels[7];
872  ch7.mod.slot_on_flag |= (reg[0x0e] & 0x01) ? 2 : 0; // HH
873  ch7.car.slot_on_flag |= (reg[0x0e] & 0x08) ? 2 : 0; // SD
874  Channel& ch8 = channels[8];
875  ch8.mod.slot_on_flag |= (reg[0x0e] & 0x04) ? 2 : 0; // TOM
876  ch8.car.slot_on_flag |= (reg[0x0e] & 0x02) ? 2 : 0; // CYM
877  }
878 }
879 
880 // Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI)
881 static constexpr int wave2_8pi(int e)
882 {
883  int shift = SLOT_AMP_BITS - PG_BITS - 2;
884  if (shift > 0) {
885  return e >> shift;
886  } else {
887  return e << -shift;
888  }
889 }
890 
891 // PG
892 ALWAYS_INLINE unsigned Slot::calc_phase(unsigned lfo_pm)
893 {
894  cPhase += dPhase[lfo_pm];
895  return cPhase >> DP_BASE_BITS;
896 }
897 
898 // EG
899 void Slot::calc_envelope_outline(unsigned& out)
900 {
901  switch (state) {
902  case ATTACK:
903  out = 0;
904  eg_phase = EnvPhaseIndex(0);
906  break;
907  case DECAY:
910  break;
911  case SUSTAIN:
912  case RELEASE:
914  break;
915  case SETTLE:
916  // Comment copied from Burczynski code (didn't verify myself):
917  // When CARRIER envelope gets down to zero level, phases in
918  // BOTH operators are reset (at the same time?).
919  slotOn();
920  sibling->slotOn();
921  break;
922  case SUSHOLD:
923  case FINISH:
924  default:
925  UNREACHABLE;
926  break;
927  }
928 }
929 template<bool HAS_AM, bool FIXED_ENV>
930 ALWAYS_INLINE unsigned Slot::calc_envelope(int lfo_am, unsigned fixed_env)
931 {
932  assert(!FIXED_ENV || (state == one_of(SUSHOLD, FINISH)));
933 
934  if constexpr (FIXED_ENV) {
935  unsigned out = fixed_env;
936  if constexpr (HAS_AM) {
937  out += lfo_am; // [0, 768)
938  out |= 3;
939  } else {
940  // out |= 3 is already done in calc_fixed_env()
941  }
942  return out;
943  } else {
944  unsigned out = eg_phase.toInt(); // in range [0, 128]
945  if (state == ATTACK) {
946  out = arAdjustTab[out]; // [0, 128]
947  }
948  eg_phase += eg_dPhase;
949  if (eg_phase >= eg_phase_max) {
951  }
952  out = EG2DB(out + tll); // [0, 732]
953  if constexpr (HAS_AM) {
954  out += lfo_am; // [0, 758]
955  }
956  return out | 3;
957  }
958 }
959 template<bool HAS_AM> unsigned Slot::calc_fixed_env() const
960 {
961  assert(state == one_of(SUSHOLD, FINISH));
962  assert(eg_dPhase == EnvPhaseIndex(0));
963  unsigned out = eg_phase.toInt(); // in range [0, 128)
964  out = EG2DB(out + tll); // [0, 480)
965  if constexpr (!HAS_AM) {
966  out |= 3;
967  }
968  return out;
969 }
970 
971 // CARRIER
972 template<bool HAS_AM, bool FIXED_ENV>
973 ALWAYS_INLINE int Slot::calc_slot_car(unsigned lfo_pm, int lfo_am, int fm, unsigned fixed_env)
974 {
975  int phase = calc_phase(lfo_pm) + wave2_8pi(fm);
976  unsigned egOut = calc_envelope<HAS_AM, FIXED_ENV>(lfo_am, fixed_env);
977  int newOutput = dB2LinTab[patch.WF[phase & PG_MASK] + egOut];
978  output = (output + newOutput) >> 1;
979  return output;
980 }
981 
982 // MODULATOR
983 template<bool HAS_AM, bool HAS_FB, bool FIXED_ENV>
984 ALWAYS_INLINE int Slot::calc_slot_mod(unsigned lfo_pm, int lfo_am, unsigned fixed_env)
985 {
986  assert((patch.FB != 0) == HAS_FB);
987  unsigned phase = calc_phase(lfo_pm);
988  unsigned egOut = calc_envelope<HAS_AM, FIXED_ENV>(lfo_am, fixed_env);
989  if constexpr (HAS_FB) {
990  phase += wave2_8pi(feedback) >> patch.FB;
991  }
992  int newOutput = dB2LinTab[patch.WF[phase & PG_MASK] + egOut];
993  feedback = (output + newOutput) >> 1;
994  output = newOutput;
995  return feedback;
996 }
997 
998 // TOM (ch8 mod)
1000 {
1001  unsigned phase = calc_phase(0);
1002  unsigned egOut = calc_envelope<false, false>(0, 0);
1003  return dB2LinTab[patch.WF[phase & PG_MASK] + egOut];
1004 }
1005 
1006 // SNARE (ch7 car)
1008 {
1009  unsigned phase = calc_phase(0);
1010  unsigned egOut = calc_envelope<false, false>(0, 0);
1011  return BIT(phase, 7)
1012  ? dB2LinTab[(noise ? DB_POS(0.0) : DB_POS(15.0)) + egOut]
1013  : dB2LinTab[(noise ? DB_NEG(0.0) : DB_NEG(15.0)) + egOut];
1014 }
1015 
1016 // TOP-CYM (ch8 car)
1017 ALWAYS_INLINE int Slot::calc_slot_cym(unsigned phase7, unsigned phase8)
1018 {
1019  unsigned egOut = calc_envelope<false, false>(0, 0);
1020  unsigned dbOut = (((BIT(phase7, PG_BITS - 8) ^
1021  BIT(phase7, PG_BITS - 1)) |
1022  BIT(phase7, PG_BITS - 7)) ^
1023  ( BIT(phase8, PG_BITS - 7) &
1024  !BIT(phase8, PG_BITS - 5)))
1025  ? DB_NEG(3.0)
1026  : DB_POS(3.0);
1027  return dB2LinTab[dbOut + egOut];
1028 }
1029 
1030 // HI-HAT (ch7 mod)
1031 ALWAYS_INLINE int Slot::calc_slot_hat(unsigned phase7, unsigned phase8, bool noise)
1032 {
1033  unsigned egOut = calc_envelope<false, false>(0, 0);
1034  unsigned dbOut = (((BIT(phase7, PG_BITS - 8) ^
1035  BIT(phase7, PG_BITS - 1)) |
1036  BIT(phase7, PG_BITS - 7)) ^
1037  ( BIT(phase8, PG_BITS - 7) &
1038  !BIT(phase8, PG_BITS - 5)))
1039  ? (noise ? DB_NEG(12.0) : DB_NEG(24.0))
1040  : (noise ? DB_POS(12.0) : DB_POS(24.0));
1041  return dB2LinTab[dbOut + egOut];
1042 }
1043 
1045 {
1046  return 1.0f / (1 << DB2LIN_AMP_BITS);
1047 }
1048 
1049 bool YM2413::isRhythm() const
1050 {
1051  return (reg[0x0E] & 0x20) != 0;
1052 }
1053 
1054 unsigned YM2413::getFreq(unsigned channel) const
1055 {
1056  // combined fnum (=9bit) and block (=3bit)
1057  assert(channel < 9);
1058  return reg[0x10 + channel] | ((reg[0x20 + channel] & 0x0F) << 8);
1059 }
1060 
1061 Patch& YM2413::getPatch(unsigned instrument, bool carrier)
1062 {
1063  return patches[instrument][carrier];
1064 }
1065 
1066 template<unsigned FLAGS>
1067 ALWAYS_INLINE void YM2413::calcChannel(Channel& ch, float* buf, unsigned num)
1068 {
1069  // VC++ requires explicit conversion to bool. Compiler bug??
1070  const bool HAS_CAR_PM = (FLAGS & 1) != 0;
1071  const bool HAS_CAR_AM = (FLAGS & 2) != 0;
1072  const bool HAS_MOD_PM = (FLAGS & 4) != 0;
1073  const bool HAS_MOD_AM = (FLAGS & 8) != 0;
1074  const bool HAS_MOD_FB = (FLAGS & 16) != 0;
1075  const bool HAS_CAR_FIXED_ENV = (FLAGS & 32) != 0;
1076  const bool HAS_MOD_FIXED_ENV = (FLAGS & 64) != 0;
1077 
1078  assert(((ch.car.patch.AMPM & 1) != 0) == HAS_CAR_PM);
1079  assert(((ch.car.patch.AMPM & 2) != 0) == HAS_CAR_AM);
1080  assert(((ch.mod.patch.AMPM & 1) != 0) == HAS_MOD_PM);
1081  assert(((ch.mod.patch.AMPM & 2) != 0) == HAS_MOD_AM);
1082 
1083  unsigned tmp_pm_phase = pm_phase;
1084  unsigned tmp_am_phase = am_phase;
1085  unsigned car_fixed_env = 0; // dummy
1086  unsigned mod_fixed_env = 0; // dummy
1087  if constexpr (HAS_CAR_FIXED_ENV) {
1088  car_fixed_env = ch.car.calc_fixed_env<HAS_CAR_AM>();
1089  }
1090  if constexpr (HAS_MOD_FIXED_ENV) {
1091  mod_fixed_env = ch.mod.calc_fixed_env<HAS_MOD_AM>();
1092  }
1093 
1094  unsigned sample = 0;
1095  do {
1096  unsigned lfo_pm = 0;
1097  if constexpr (HAS_CAR_PM || HAS_MOD_PM) {
1098  // Copied from Burczynski:
1099  // There are only 8 different steps for PM, and each
1100  // step lasts for 1024 samples. This results in a PM
1101  // freq of 6.1Hz (but datasheet says it's 6.4Hz).
1102  ++tmp_pm_phase;
1103  lfo_pm = (tmp_pm_phase >> 10) & 7;
1104  }
1105  int lfo_am = 0; // avoid warning
1106  if constexpr (HAS_CAR_AM || HAS_MOD_AM) {
1107  ++tmp_am_phase;
1108  if (tmp_am_phase == (LFO_AM_TAB_ELEMENTS * 64)) {
1109  tmp_am_phase = 0;
1110  }
1111  lfo_am = lfo_am_table[tmp_am_phase / 64];
1112  }
1113  int fm = ch.mod.calc_slot_mod<HAS_MOD_AM, HAS_MOD_FB, HAS_MOD_FIXED_ENV>(
1114  HAS_MOD_PM ? lfo_pm : 0, lfo_am, mod_fixed_env);
1115  buf[sample] += ch.car.calc_slot_car<HAS_CAR_AM, HAS_CAR_FIXED_ENV>(
1116  HAS_CAR_PM ? lfo_pm : 0, lfo_am, fm, car_fixed_env);
1117  ++sample;
1118  } while (sample < num);
1119 }
1120 
1121 void YM2413::generateChannels(float* bufs[9 + 5], unsigned num)
1122 {
1123  assert(num != 0);
1124 
1125  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1126  Channel& ch = channels[i];
1127  if (ch.car.isActive()) {
1128  // Below we choose between 128 specialized versions of
1129  // calcChannel(). This allows to move a lot of
1130  // conditional code out of the inner-loop.
1131  bool carFixedEnv = ch.car.state == one_of(SUSHOLD, FINISH);
1132  bool modFixedEnv = ch.mod.state == one_of(SUSHOLD, FINISH);
1133  if (ch.car.state == SETTLE) {
1134  modFixedEnv = false;
1135  }
1136  unsigned flags = ( ch.car.patch.AMPM << 0) |
1137  ( ch.mod.patch.AMPM << 2) |
1138  ((ch.mod.patch.FB != 0) << 4) |
1139  ( carFixedEnv << 5) |
1140  ( modFixedEnv << 6);
1141  switch (flags) {
1142  case 0: calcChannel< 0>(ch, bufs[i], num); break;
1143  case 1: calcChannel< 1>(ch, bufs[i], num); break;
1144  case 2: calcChannel< 2>(ch, bufs[i], num); break;
1145  case 3: calcChannel< 3>(ch, bufs[i], num); break;
1146  case 4: calcChannel< 4>(ch, bufs[i], num); break;
1147  case 5: calcChannel< 5>(ch, bufs[i], num); break;
1148  case 6: calcChannel< 6>(ch, bufs[i], num); break;
1149  case 7: calcChannel< 7>(ch, bufs[i], num); break;
1150  case 8: calcChannel< 8>(ch, bufs[i], num); break;
1151  case 9: calcChannel< 9>(ch, bufs[i], num); break;
1152  case 10: calcChannel< 10>(ch, bufs[i], num); break;
1153  case 11: calcChannel< 11>(ch, bufs[i], num); break;
1154  case 12: calcChannel< 12>(ch, bufs[i], num); break;
1155  case 13: calcChannel< 13>(ch, bufs[i], num); break;
1156  case 14: calcChannel< 14>(ch, bufs[i], num); break;
1157  case 15: calcChannel< 15>(ch, bufs[i], num); break;
1158  case 16: calcChannel< 16>(ch, bufs[i], num); break;
1159  case 17: calcChannel< 17>(ch, bufs[i], num); break;
1160  case 18: calcChannel< 18>(ch, bufs[i], num); break;
1161  case 19: calcChannel< 19>(ch, bufs[i], num); break;
1162  case 20: calcChannel< 20>(ch, bufs[i], num); break;
1163  case 21: calcChannel< 21>(ch, bufs[i], num); break;
1164  case 22: calcChannel< 22>(ch, bufs[i], num); break;
1165  case 23: calcChannel< 23>(ch, bufs[i], num); break;
1166  case 24: calcChannel< 24>(ch, bufs[i], num); break;
1167  case 25: calcChannel< 25>(ch, bufs[i], num); break;
1168  case 26: calcChannel< 26>(ch, bufs[i], num); break;
1169  case 27: calcChannel< 27>(ch, bufs[i], num); break;
1170  case 28: calcChannel< 28>(ch, bufs[i], num); break;
1171  case 29: calcChannel< 29>(ch, bufs[i], num); break;
1172  case 30: calcChannel< 30>(ch, bufs[i], num); break;
1173  case 31: calcChannel< 31>(ch, bufs[i], num); break;
1174  case 32: calcChannel< 32>(ch, bufs[i], num); break;
1175  case 33: calcChannel< 33>(ch, bufs[i], num); break;
1176  case 34: calcChannel< 34>(ch, bufs[i], num); break;
1177  case 35: calcChannel< 35>(ch, bufs[i], num); break;
1178  case 36: calcChannel< 36>(ch, bufs[i], num); break;
1179  case 37: calcChannel< 37>(ch, bufs[i], num); break;
1180  case 38: calcChannel< 38>(ch, bufs[i], num); break;
1181  case 39: calcChannel< 39>(ch, bufs[i], num); break;
1182  case 40: calcChannel< 40>(ch, bufs[i], num); break;
1183  case 41: calcChannel< 41>(ch, bufs[i], num); break;
1184  case 42: calcChannel< 42>(ch, bufs[i], num); break;
1185  case 43: calcChannel< 43>(ch, bufs[i], num); break;
1186  case 44: calcChannel< 44>(ch, bufs[i], num); break;
1187  case 45: calcChannel< 45>(ch, bufs[i], num); break;
1188  case 46: calcChannel< 46>(ch, bufs[i], num); break;
1189  case 47: calcChannel< 47>(ch, bufs[i], num); break;
1190  case 48: calcChannel< 48>(ch, bufs[i], num); break;
1191  case 49: calcChannel< 49>(ch, bufs[i], num); break;
1192  case 50: calcChannel< 50>(ch, bufs[i], num); break;
1193  case 51: calcChannel< 51>(ch, bufs[i], num); break;
1194  case 52: calcChannel< 52>(ch, bufs[i], num); break;
1195  case 53: calcChannel< 53>(ch, bufs[i], num); break;
1196  case 54: calcChannel< 54>(ch, bufs[i], num); break;
1197  case 55: calcChannel< 55>(ch, bufs[i], num); break;
1198  case 56: calcChannel< 56>(ch, bufs[i], num); break;
1199  case 57: calcChannel< 57>(ch, bufs[i], num); break;
1200  case 58: calcChannel< 58>(ch, bufs[i], num); break;
1201  case 59: calcChannel< 59>(ch, bufs[i], num); break;
1202  case 60: calcChannel< 60>(ch, bufs[i], num); break;
1203  case 61: calcChannel< 61>(ch, bufs[i], num); break;
1204  case 62: calcChannel< 62>(ch, bufs[i], num); break;
1205  case 63: calcChannel< 63>(ch, bufs[i], num); break;
1206  case 64: calcChannel< 64>(ch, bufs[i], num); break;
1207  case 65: calcChannel< 65>(ch, bufs[i], num); break;
1208  case 66: calcChannel< 66>(ch, bufs[i], num); break;
1209  case 67: calcChannel< 67>(ch, bufs[i], num); break;
1210  case 68: calcChannel< 68>(ch, bufs[i], num); break;
1211  case 69: calcChannel< 69>(ch, bufs[i], num); break;
1212  case 70: calcChannel< 70>(ch, bufs[i], num); break;
1213  case 71: calcChannel< 71>(ch, bufs[i], num); break;
1214  case 72: calcChannel< 72>(ch, bufs[i], num); break;
1215  case 73: calcChannel< 73>(ch, bufs[i], num); break;
1216  case 74: calcChannel< 74>(ch, bufs[i], num); break;
1217  case 75: calcChannel< 75>(ch, bufs[i], num); break;
1218  case 76: calcChannel< 76>(ch, bufs[i], num); break;
1219  case 77: calcChannel< 77>(ch, bufs[i], num); break;
1220  case 78: calcChannel< 78>(ch, bufs[i], num); break;
1221  case 79: calcChannel< 79>(ch, bufs[i], num); break;
1222  case 80: calcChannel< 80>(ch, bufs[i], num); break;
1223  case 81: calcChannel< 81>(ch, bufs[i], num); break;
1224  case 82: calcChannel< 82>(ch, bufs[i], num); break;
1225  case 83: calcChannel< 83>(ch, bufs[i], num); break;
1226  case 84: calcChannel< 84>(ch, bufs[i], num); break;
1227  case 85: calcChannel< 85>(ch, bufs[i], num); break;
1228  case 86: calcChannel< 86>(ch, bufs[i], num); break;
1229  case 87: calcChannel< 87>(ch, bufs[i], num); break;
1230  case 88: calcChannel< 88>(ch, bufs[i], num); break;
1231  case 89: calcChannel< 89>(ch, bufs[i], num); break;
1232  case 90: calcChannel< 90>(ch, bufs[i], num); break;
1233  case 91: calcChannel< 91>(ch, bufs[i], num); break;
1234  case 92: calcChannel< 92>(ch, bufs[i], num); break;
1235  case 93: calcChannel< 93>(ch, bufs[i], num); break;
1236  case 94: calcChannel< 94>(ch, bufs[i], num); break;
1237  case 95: calcChannel< 95>(ch, bufs[i], num); break;
1238  case 96: calcChannel< 96>(ch, bufs[i], num); break;
1239  case 97: calcChannel< 97>(ch, bufs[i], num); break;
1240  case 98: calcChannel< 98>(ch, bufs[i], num); break;
1241  case 99: calcChannel< 99>(ch, bufs[i], num); break;
1242  case 100: calcChannel<100>(ch, bufs[i], num); break;
1243  case 101: calcChannel<101>(ch, bufs[i], num); break;
1244  case 102: calcChannel<102>(ch, bufs[i], num); break;
1245  case 103: calcChannel<103>(ch, bufs[i], num); break;
1246  case 104: calcChannel<104>(ch, bufs[i], num); break;
1247  case 105: calcChannel<105>(ch, bufs[i], num); break;
1248  case 106: calcChannel<106>(ch, bufs[i], num); break;
1249  case 107: calcChannel<107>(ch, bufs[i], num); break;
1250  case 108: calcChannel<108>(ch, bufs[i], num); break;
1251  case 109: calcChannel<109>(ch, bufs[i], num); break;
1252  case 110: calcChannel<110>(ch, bufs[i], num); break;
1253  case 111: calcChannel<111>(ch, bufs[i], num); break;
1254  case 112: calcChannel<112>(ch, bufs[i], num); break;
1255  case 113: calcChannel<113>(ch, bufs[i], num); break;
1256  case 114: calcChannel<114>(ch, bufs[i], num); break;
1257  case 115: calcChannel<115>(ch, bufs[i], num); break;
1258  case 116: calcChannel<116>(ch, bufs[i], num); break;
1259  case 117: calcChannel<117>(ch, bufs[i], num); break;
1260  case 118: calcChannel<118>(ch, bufs[i], num); break;
1261  case 119: calcChannel<119>(ch, bufs[i], num); break;
1262  case 120: calcChannel<120>(ch, bufs[i], num); break;
1263  case 121: calcChannel<121>(ch, bufs[i], num); break;
1264  case 122: calcChannel<122>(ch, bufs[i], num); break;
1265  case 123: calcChannel<123>(ch, bufs[i], num); break;
1266  case 124: calcChannel<124>(ch, bufs[i], num); break;
1267  case 125: calcChannel<125>(ch, bufs[i], num); break;
1268  case 126: calcChannel<126>(ch, bufs[i], num); break;
1269  case 127: calcChannel<127>(ch, bufs[i], num); break;
1270  default: UNREACHABLE;
1271  }
1272  } else {
1273  bufs[i] = nullptr;
1274  }
1275  }
1276  // update AM, PM unit
1277  pm_phase += num;
1278  am_phase = (am_phase + num) % (LFO_AM_TAB_ELEMENTS * 64);
1279 
1280  if (isRhythm()) {
1281  bufs[6] = nullptr;
1282  bufs[7] = nullptr;
1283  bufs[8] = nullptr;
1284 
1285  Channel& ch6 = channels[6];
1286  Channel& ch7 = channels[7];
1287  Channel& ch8 = channels[8];
1288 
1289  unsigned old_noise = noise_seed;
1290  unsigned old_cPhase7 = ch7.mod.cPhase;
1291  unsigned old_cPhase8 = ch8.car.cPhase;
1292 
1293  if (ch6.car.isActive()) {
1294  for (auto sample : xrange(num)) {
1295  bufs[ 9][sample] += 2 *
1296  ch6.car.calc_slot_car<false, false>(
1297  0, 0, ch6.mod.calc_slot_mod<
1298  false, false, false>(0, 0, 0), 0);
1299  }
1300  } else {
1301  bufs[9] = nullptr;
1302  }
1303 
1304  if (ch7.car.isActive()) {
1305  for (auto sample : xrange(num)) {
1306  noise_seed >>= 1;
1307  bool noise_bit = noise_seed & 1;
1308  if (noise_bit) noise_seed ^= 0x8003020;
1309  bufs[10][sample] +=
1310  -2 * ch7.car.calc_slot_snare(noise_bit);
1311  }
1312  } else {
1313  bufs[10] = nullptr;
1314  }
1315 
1316  if (ch8.car.isActive()) {
1317  for (auto sample : xrange(num)) {
1318  unsigned phase7 = ch7.mod.calc_phase(0);
1319  unsigned phase8 = ch8.car.calc_phase(0);
1320  bufs[11][sample] +=
1321  -2 * ch8.car.calc_slot_cym(phase7, phase8);
1322  }
1323  } else {
1324  bufs[11] = nullptr;
1325  }
1326 
1327  if (ch7.mod.isActive()) {
1328  // restore noise, ch7/8 cPhase
1329  noise_seed = old_noise;
1330  ch7.mod.cPhase = old_cPhase7;
1331  ch8.car.cPhase = old_cPhase8;
1332  for (auto sample : xrange(num)) {
1333  noise_seed >>= 1;
1334  bool noise_bit = noise_seed & 1;
1335  if (noise_bit) noise_seed ^= 0x8003020;
1336  unsigned phase7 = ch7.mod.calc_phase(0);
1337  unsigned phase8 = ch8.car.calc_phase(0);
1338  bufs[12][sample] +=
1339  2 * ch7.mod.calc_slot_hat(phase7, phase8, noise_bit);
1340  }
1341  } else {
1342  bufs[12] = nullptr;
1343  }
1344 
1345  if (ch8.mod.isActive()) {
1346  for (auto sample : xrange(num)) {
1347  bufs[13][sample] += 2 * ch8.mod.calc_slot_tom();
1348  }
1349  } else {
1350  bufs[13] = nullptr;
1351  }
1352  } else {
1353  bufs[ 9] = nullptr;
1354  bufs[10] = nullptr;
1355  bufs[11] = nullptr;
1356  bufs[12] = nullptr;
1357  bufs[13] = nullptr;
1358  }
1359 }
1360 
1361 void YM2413::writePort(bool port, uint8_t value, int /*offset*/)
1362 {
1363  if (port == 0) {
1364  registerLatch = value;
1365  } else {
1366  writeReg(registerLatch & 0x3f, value);
1367  }
1368 }
1369 
1370 void YM2413::pokeReg(uint8_t r, uint8_t data)
1371 {
1372  writeReg(r, data);
1373 }
1374 
1375 void YM2413::writeReg(uint8_t r, uint8_t data)
1376 {
1377  assert(r < 0x40);
1378 
1379  switch (r) {
1380  case 0x00: {
1381  reg[r] = data;
1382  patches[0][0].AMPM = (data >> 6) & 3;
1383  patches[0][0].EG = (data >> 5) & 1;
1384  patches[0][0].setKR ((data >> 4) & 1);
1385  patches[0][0].setML ((data >> 0) & 15);
1386  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1387  if ((reg[0x30 + i] & 0xF0) == 0) {
1388  Channel& ch = channels[i];
1389  ch.setPatch(0, *this); // TODO optimize
1390  unsigned freq = getFreq(i);
1391  ch.mod.updatePG (freq);
1392  ch.mod.updateRKS(freq);
1393  ch.mod.updateEG();
1394  }
1395  }
1396  break;
1397  }
1398  case 0x01: {
1399  reg[r] = data;
1400  patches[0][1].AMPM = (data >> 6) & 3;
1401  patches[0][1].EG = (data >> 5) & 1;
1402  patches[0][1].setKR ((data >> 4) & 1);
1403  patches[0][1].setML ((data >> 0) & 15);
1404  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1405  if ((reg[0x30 + i] & 0xF0) == 0) {
1406  Channel& ch = channels[i];
1407  ch.setPatch(0, *this); // TODO optimize
1408  unsigned freq = getFreq(i);
1409  ch.car.updatePG (freq);
1410  ch.car.updateRKS(freq);
1411  ch.car.updateEG();
1412  }
1413  }
1414  break;
1415  }
1416  case 0x02: {
1417  reg[r] = data;
1418  patches[0][0].setKL((data >> 6) & 3);
1419  patches[0][0].setTL((data >> 0) & 63);
1420  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1421  if ((reg[0x30 + i] & 0xF0) == 0) {
1422  Channel& ch = channels[i];
1423  ch.setPatch(0, *this); // TODO optimize
1424  bool actAsCarrier = (i >= 7) && isRhythm();
1425  assert(!actAsCarrier); (void)actAsCarrier;
1426  ch.mod.updateTLL(getFreq(i), false);
1427  }
1428  }
1429  break;
1430  }
1431  case 0x03: {
1432  reg[r] = data;
1433  patches[0][1].setKL((data >> 6) & 3);
1434  patches[0][1].setWF((data >> 4) & 1);
1435  patches[0][0].setWF((data >> 3) & 1);
1436  patches[0][0].setFB((data >> 0) & 7);
1437  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1438  if ((reg[0x30 + i] & 0xF0) == 0) {
1439  Channel& ch = channels[i];
1440  ch.setPatch(0, *this); // TODO optimize
1441  }
1442  }
1443  break;
1444  }
1445  case 0x04: {
1446  reg[r] = data;
1447  patches[0][0].AR = (data >> 4) & 15;
1448  patches[0][0].DR = (data >> 0) & 15;
1449  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1450  if ((reg[0x30 + i] & 0xF0) == 0) {
1451  Channel& ch = channels[i];
1452  ch.setPatch(0, *this); // TODO optimize
1453  ch.mod.updateEG();
1454  if (ch.mod.state == ATTACK) {
1455  ch.mod.setEnvelopeState(ATTACK);
1456  }
1457  }
1458  }
1459  break;
1460  }
1461  case 0x05: {
1462  reg[r] = data;
1463  patches[0][1].AR = (data >> 4) & 15;
1464  patches[0][1].DR = (data >> 0) & 15;
1465  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1466  if ((reg[0x30 + i] & 0xF0) == 0) {
1467  Channel& ch = channels[i];
1468  ch.setPatch(0, *this); // TODO optimize
1469  ch.car.updateEG();
1470  if (ch.car.state == ATTACK) {
1471  ch.car.setEnvelopeState(ATTACK);
1472  }
1473  }
1474  }
1475  break;
1476  }
1477  case 0x06: {
1478  reg[r] = data;
1479  patches[0][0].setSL((data >> 4) & 15);
1480  patches[0][0].RR = (data >> 0) & 15;
1481  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1482  if ((reg[0x30 + i] & 0xF0) == 0) {
1483  Channel& ch = channels[i];
1484  ch.setPatch(0, *this); // TODO optimize
1485  ch.mod.updateEG();
1486  if (ch.mod.state == DECAY) {
1487  ch.mod.setEnvelopeState(DECAY);
1488  }
1489  }
1490  }
1491  break;
1492  }
1493  case 0x07: {
1494  reg[r] = data;
1495  patches[0][1].setSL((data >> 4) & 15);
1496  patches[0][1].RR = (data >> 0) & 15;
1497  for (auto i : xrange(isRhythm() ? 6 : 9)) {
1498  if ((reg[0x30 + i] & 0xF0) == 0) {
1499  Channel& ch = channels[i];
1500  ch.setPatch(0, *this); // TODO optimize
1501  ch.car.updateEG();
1502  if (ch.car.state == DECAY) {
1503  ch.car.setEnvelopeState(DECAY);
1504  }
1505  }
1506  }
1507  break;
1508  }
1509  case 0x0E: {
1510  uint8_t old = reg[r];
1511  reg[r] = data;
1512  setRhythmFlags(old);
1513  break;
1514  }
1515  case 0x19: case 0x1A: case 0x1B: case 0x1C:
1516  case 0x1D: case 0x1E: case 0x1F:
1517  r -= 9; // verified on real YM2413
1518  [[fallthrough]];
1519  case 0x10: case 0x11: case 0x12: case 0x13: case 0x14:
1520  case 0x15: case 0x16: case 0x17: case 0x18: {
1521  reg[r] = data;
1522  unsigned cha = r & 0x0F; assert(cha < 9);
1523  Channel& ch = channels[cha];
1524  bool actAsCarrier = (cha >= 7) && isRhythm();
1525  unsigned freq = getFreq(cha);
1526  ch.mod.updateAll(freq, actAsCarrier);
1527  ch.car.updateAll(freq, true);
1528  break;
1529  }
1530  case 0x29: case 0x2A: case 0x2B: case 0x2C:
1531  case 0x2D: case 0x2E: case 0x2F:
1532  r -= 9; // verified on real YM2413
1533  [[fallthrough]];
1534  case 0x20: case 0x21: case 0x22: case 0x23: case 0x24:
1535  case 0x25: case 0x26: case 0x27: case 0x28: {
1536  reg[r] = data;
1537  unsigned cha = r & 0x0F; assert(cha < 9);
1538  Channel& ch = channels[cha];
1539  bool modActAsCarrier = (cha >= 7) && isRhythm();
1540  ch.setSustain((data >> 5) & 1, modActAsCarrier);
1541  if (data & 0x10) {
1542  ch.keyOn();
1543  } else {
1544  ch.keyOff();
1545  }
1546  unsigned freq = getFreq(cha);
1547  ch.mod.updateAll(freq, modActAsCarrier);
1548  ch.car.updateAll(freq, true);
1549  break;
1550  }
1551  case 0x39: case 0x3A: case 0x3B: case 0x3C:
1552  case 0x3D: case 0x3E: case 0x3F:
1553  r -= 9; // verified on real YM2413
1554  [[fallthrough]];
1555  case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
1556  case 0x35: case 0x36: case 0x37: case 0x38: {
1557  reg[r] = data;
1558  unsigned cha = r & 0x0F; assert(cha < 9);
1559  Channel& ch = channels[cha];
1560  if (isRhythm() && (cha >= 6)) {
1561  if (cha > 6) {
1562  // channel 7 or 8 in rythm mode
1563  ch.mod.setVolume(data >> 4);
1564  }
1565  } else {
1566  ch.setPatch(data >> 4, *this);
1567  }
1568  ch.car.setVolume(data & 15);
1569  bool actAsCarrier = (cha >= 7) && isRhythm();
1570  unsigned freq = getFreq(cha);
1571  ch.mod.updateAll(freq, actAsCarrier);
1572  ch.car.updateAll(freq, true);
1573  break;
1574  }
1575  default:
1576  break;
1577  }
1578 }
1579 
1580 uint8_t YM2413::peekReg(uint8_t r) const
1581 {
1582  return reg[r];
1583 }
1584 
1585 } // namespace YM2413Okazaki
1586 
1587 static constexpr std::initializer_list<enum_string<YM2413Okazaki::EnvelopeState>> envelopeStateInfo = {
1588  { "ATTACK", YM2413Okazaki::ATTACK },
1589  { "DECAY", YM2413Okazaki::DECAY },
1590  { "SUSHOLD", YM2413Okazaki::SUSHOLD },
1591  { "SUSTAIN", YM2413Okazaki::SUSTAIN },
1592  { "RELEASE", YM2413Okazaki::RELEASE },
1593  { "SETTLE", YM2413Okazaki::SETTLE },
1594  { "FINISH", YM2413Okazaki::FINISH }
1595 };
1597 
1598 namespace YM2413Okazaki {
1599 
1600 // version 1: initial version
1601 // version 2: don't serialize "type / actAsCarrier" anymore, it's now
1602 // a calculated value
1603 // version 3: don't serialize slot_on_flag anymore
1604 // version 4: don't serialize volume anymore
1605 template<typename Archive>
1606 void Slot::serialize(Archive& ar, unsigned /*version*/)
1607 {
1608  ar.serialize("feedback", feedback,
1609  "output", output,
1610  "cphase", cPhase,
1611  "state", state,
1612  "eg_phase", eg_phase,
1613  "sustain", sustain);
1614 
1615  // These are restored by calls to
1616  // updateAll(): eg_dPhase, dPhaseDRTableRks, tll, dPhase
1617  // setEnvelopeState(): eg_phase_max
1618  // setPatch(): patch
1619  // setVolume(): volume
1620  // update_key_status(): slot_on_flag
1621 }
1622 
1623 // version 1: initial version
1624 // version 2: removed patch_number, freq
1625 template<typename Archive>
1626 void Channel::serialize(Archive& ar, unsigned /*version*/)
1627 {
1628  ar.serialize("mod", mod,
1629  "car", car);
1630 }
1631 
1632 
1633 // version 1: initial version
1634 // version 2: 'registers' are moved here (no longer serialized in base class)
1635 // version 3: no longer serialize 'user_patch_mod' and 'user_patch_car'
1636 // version 4: added 'registerLatch'
1637 template<typename Archive>
1638 void YM2413::serialize(Archive& ar, unsigned version)
1639 {
1640  if (ar.versionBelow(version, 2)) ar.beginTag("YM2413Core");
1641  ar.serialize("registers", reg);
1642  if (ar.versionBelow(version, 2)) ar.endTag("YM2413Core");
1643 
1644  // no need to serialize patches[]
1645  // patches[0] is restored from registers, the others are read-only
1646  ar.serialize("channels", channels,
1647  "pm_phase", pm_phase,
1648  "am_phase", am_phase,
1649  "noise_seed", noise_seed);
1650 
1651  if constexpr (Archive::IS_LOADER) {
1652  patches[0][0].initModulator(&reg[0]);
1653  patches[0][1].initCarrier (&reg[0]);
1654  for (auto [i, ch] : enumerate(channels)) {
1655  // restore patch
1656  unsigned p = ((i >= 6) && isRhythm())
1657  ? unsigned(16 + (i - 6))
1658  : (reg[0x30 + i] >> 4);
1659  ch.setPatch(p, *this); // before updateAll()
1660  // restore volume
1661  ch.car.setVolume(reg[0x30 + i] & 15);
1662  if (isRhythm() && (i >= 7)) { // ch 7/8 rythm
1663  ch.mod.setVolume(reg[0x30 + i] >> 4);
1664  }
1665  // sync various variables
1666  bool actAsCarrier = (i >= 7) && isRhythm();
1667  unsigned freq = getFreq(unsigned(i));
1668  ch.mod.updateAll(freq, actAsCarrier);
1669  ch.car.updateAll(freq, true);
1670  ch.mod.setEnvelopeState(ch.mod.state);
1671  ch.car.setEnvelopeState(ch.car.state);
1672  }
1673  update_key_status();
1674  }
1675  if (ar.versionAtLeast(version, 4)) {
1676  ar.serialize("registerLatch", registerLatch);
1677  } else {
1678  // could be restored from MSXMusicBase, worth the effort?
1679  }
1680 }
1681 
1682 } // namespace YM2413Okazaki
1683 
1684 using YM2413Okazaki::YM2413;
1687 
1688 } // namespace openmsx
#define M_PI
Definition: Math.hh:27
TclObject t
Definition: one_of.hh:7
static constexpr FixedPoint create(int value)
Create new fixed point object from given representation.
Definition: FixedPoint.hh:44
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
Definition: FixedPoint.hh:76
Abstract interface for the YM2413 core.
Definition: YM2413Core.hh:27
void serialize(Archive &ar, unsigned version)
void setSustain(bool sustain, bool modActAsCarrier)
void setPatch(unsigned num, YM2413 &ym2413)
void setSL(uint8_t value)
Sets sustain level [0..15].
void setFB(uint8_t value)
Sets the amount of feedback [0..7].
Patch()
Creates an uninitialized Patch object; call initXXX() before use.
void initCarrier(const uint8_t *data)
void setTL(uint8_t value)
Set volume (total level) [0..63].
void initModulator(const uint8_t *data)
void setKL(uint8_t value)
Sets Key scale level [0..3].
void setML(uint8_t value)
Sets the frequency multiplier factor [0..15].
void setWF(uint8_t value)
Set waveform [0..1].
void setKR(uint8_t value)
Sets the Key Scale of Rate (0 or 1).
void serialize(Archive &ar, unsigned version)
void setVolume(unsigned value)
int calc_slot_mod(unsigned lfo_pm, int lfo_am, unsigned fixed_env)
void setPatch(const Patch &patch)
void updateTLL(unsigned freq, bool actAsCarrier)
void calc_envelope_outline(unsigned &out)
void updatePG(unsigned freq)
void updateRKS(unsigned freq)
void setEnvelopeState(EnvelopeState state)
unsigned calc_envelope(int lfo_am, unsigned fixed_env)
unsigned calc_phase(unsigned lfo_pm)
unsigned calc_fixed_env() const
int calc_slot_hat(unsigned phase7, unsigned phase8, bool noise)
int calc_slot_cym(unsigned phase7, unsigned phase8)
int calc_slot_car(unsigned lfo_pm, int lfo_am, int fm, unsigned fixed_env)
void updateAll(unsigned freq, bool actAsCarrier)
void generateChannels(float *bufs[9+5], unsigned num) override
uint8_t peekReg(uint8_t reg) const override
Read from a YM2413 register (for debug).
void serialize(Archive &ar, unsigned version)
void writePort(bool port, uint8_t value, int offset) override
Write to the YM2413 register/data port.
void pokeReg(uint8_t reg, uint8_t data) override
Write to a YM2413 register (for debug).
float getAmplificationFactor() const override
Returns normalization factor.
void reset() override
Reset this YM2413 core.
Patch & getPatch(unsigned instrument, bool carrier)
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition: enumerate.hh:28
#define ALWAYS_INLINE
Definition: inline.hh:16
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:269
constexpr EnvPhaseIndex EG_DP_MAX
constexpr uint8_t mlTable[16]
constexpr auto fullSinTable
constexpr int SLOT_AMP_BITS
constexpr int DB2LIN_AMP_BITS
constexpr auto halfSinTable
constexpr unsigned char lfo_am_table[LFO_AM_TAB_ELEMENTS]
constexpr int EP_FP_BITS
constexpr unsigned LFO_AM_TAB_ELEMENTS
constexpr int AM_PG_WIDTH
constexpr signed char pmTable[8][8]
constexpr auto dB2LinTab
constexpr EnvPhaseIndex EG_DP_INF
constexpr int DP_BASE_BITS
constexpr int DBTABLEN
constexpr int AM_DP_MASK
constexpr double TL_STEP
constexpr double DB_STEP
constexpr int AM_DP_WIDTH
constexpr auto arAdjustTab
constexpr unsigned const *const waveform[2]
FixedPoint< EP_FP_BITS > EnvPhaseIndex
constexpr int AM_DP_BITS
constexpr auto dPhaseDrTab
constexpr int PG_WIDTH
constexpr double EG_STEP
constexpr int PM_FP_BITS
constexpr int AM_PG_BITS
This file implemented 3 utility functions:
Definition: Autofire.cc:9
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:118
void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:226
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:998
#define UNREACHABLE
Definition: unreachable.hh:38
constexpr auto xrange(T e)
Definition: xrange.hh:155