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