openMSX
YM2413Burczynski.cc
Go to the documentation of this file.
1 /*
2  *
3  * File: ym2413.c - software implementation of YM2413
4  * FM sound generator type OPLL
5  *
6  * Copyright (C) 2002 Jarek Burczynski
7  *
8  * Version 1.0
9  *
10  *
11  * TODO:
12  * - make sure of the sinus amplitude bits
13  * - make sure of the EG resolution bits (looks like the biggest
14  * modulation index generated by the modulator is 123, 124 = no modulation)
15  * - find proper algorithm for attack phase of EG
16  * - tune up instruments ROM
17  * - support sample replay in test mode (it is NOT as simple as setting bit 0
18  * in register 0x0f and using register 0x10 for sample data).
19  * Which games use this feature ?
20  */
21 
22 #include "YM2413Burczynski.hh"
23 #include "Math.hh"
24 #include "cstd.hh"
25 #include "serialize.hh"
26 #include <array>
27 #include <cstring>
28 #include <iostream>
29 
30 namespace openmsx {
31 namespace YM2413Burczynski {
32 
33 // envelope output entries
34 constexpr int ENV_BITS = 10;
35 constexpr double ENV_STEP = 128.0 / (1 << ENV_BITS);
36 
37 constexpr int MAX_ATT_INDEX = (1 << (ENV_BITS - 2)) - 1; // 255
38 constexpr int MIN_ATT_INDEX = 0;
39 
40 // sinwave entries
41 constexpr int SIN_BITS = 10;
42 constexpr int SIN_LEN = 1 << SIN_BITS;
43 constexpr int SIN_MASK = SIN_LEN - 1;
44 
45 constexpr int TL_RES_LEN = 256; // 8 bits addressing (real chip)
46 
47 // key scale level
48 // table is 3dB/octave, DV converts this into 6dB/octave
49 // 0.1875 is bit 0 weight of the envelope counter (volume) expressed
50 // in the 'decibel' scale
51 static constexpr int DV(double x) { return int(x / 0.1875); }
52 constexpr int ksl_tab[8 * 16] =
53 {
54  // OCT 0
55  DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
56  DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
57  DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
58  DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
59  // OCT 1
60  DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
61  DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
62  DV( 0.000),DV( 0.750),DV( 1.125),DV( 1.500),
63  DV( 1.875),DV( 2.250),DV( 2.625),DV( 3.000),
64  // OCT 2
65  DV( 0.000),DV( 0.000),DV( 0.000),DV( 0.000),
66  DV( 0.000),DV( 1.125),DV( 1.875),DV( 2.625),
67  DV( 3.000),DV( 3.750),DV( 4.125),DV( 4.500),
68  DV( 4.875),DV( 5.250),DV( 5.625),DV( 6.000),
69  // OCT 3
70  DV( 0.000),DV( 0.000),DV( 0.000),DV( 1.875),
71  DV( 3.000),DV( 4.125),DV( 4.875),DV( 5.625),
72  DV( 6.000),DV( 6.750),DV( 7.125),DV( 7.500),
73  DV( 7.875),DV( 8.250),DV( 8.625),DV( 9.000),
74  // OCT 4
75  DV( 0.000),DV( 0.000),DV( 3.000),DV( 4.875),
76  DV( 6.000),DV( 7.125),DV( 7.875),DV( 8.625),
77  DV( 9.000),DV( 9.750),DV(10.125),DV(10.500),
78  DV(10.875),DV(11.250),DV(11.625),DV(12.000),
79  // OCT 5
80  DV( 0.000),DV( 3.000),DV( 6.000),DV( 7.875),
81  DV( 9.000),DV(10.125),DV(10.875),DV(11.625),
82  DV(12.000),DV(12.750),DV(13.125),DV(13.500),
83  DV(13.875),DV(14.250),DV(14.625),DV(15.000),
84  // OCT 6
85  DV( 0.000),DV( 6.000),DV( 9.000),DV(10.875),
86  DV(12.000),DV(13.125),DV(13.875),DV(14.625),
87  DV(15.000),DV(15.750),DV(16.125),DV(16.500),
88  DV(16.875),DV(17.250),DV(17.625),DV(18.000),
89  // OCT 7
90  DV( 0.000),DV( 9.000),DV(12.000),DV(13.875),
91  DV(15.000),DV(16.125),DV(16.875),DV(17.625),
92  DV(18.000),DV(18.750),DV(19.125),DV(19.500),
93  DV(19.875),DV(20.250),DV(20.625),DV(21.000)
94 };
95 
96 // sustain level table (3dB per step)
97 // 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,45 (dB)
98 static constexpr int SC(int db) { return int(double(db) / ENV_STEP); }
99 constexpr int sl_tab[16] = {
100  SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
101  SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(15)
102 };
103 
104 constexpr uint8_t eg_inc[15][8] =
105 {
106  // cycle: 0 1 2 3 4 5 6 7
107 
108  /* 0 */ { 0,1, 0,1, 0,1, 0,1, }, // rates 00..12 0 (increment by 0 or 1)
109  /* 1 */ { 0,1, 0,1, 1,1, 0,1, }, // rates 00..12 1
110  /* 2 */ { 0,1, 1,1, 0,1, 1,1, }, // rates 00..12 2
111  /* 3 */ { 0,1, 1,1, 1,1, 1,1, }, // rates 00..12 3
112 
113  /* 4 */ { 1,1, 1,1, 1,1, 1,1, }, // rate 13 0 (increment by 1)
114  /* 5 */ { 1,1, 1,2, 1,1, 1,2, }, // rate 13 1
115  /* 6 */ { 1,2, 1,2, 1,2, 1,2, }, // rate 13 2
116  /* 7 */ { 1,2, 2,2, 1,2, 2,2, }, // rate 13 3
117 
118  /* 8 */ { 2,2, 2,2, 2,2, 2,2, }, // rate 14 0 (increment by 2)
119  /* 9 */ { 2,2, 2,4, 2,2, 2,4, }, // rate 14 1
120  /*10 */ { 2,4, 2,4, 2,4, 2,4, }, // rate 14 2
121  /*11 */ { 2,4, 4,4, 2,4, 4,4, }, // rate 14 3
122 
123  /*12 */ { 4,4, 4,4, 4,4, 4,4, }, // rates 15 0, 15 1, 15 2, 15 3 (incr by 4)
124  /*13 */ { 8,8, 8,8, 8,8, 8,8, }, // rates 15 2, 15 3 for attack
125  /*14 */ { 0,0, 0,0, 0,0, 0,0, }, // infinity rates for attack and decay(s)
126 };
127 
128 // note that there is no value 13 in this table - it's directly in the code
129 constexpr uint8_t eg_rate_select[16 + 64 + 16] =
130 {
131  // Envelope Generator rates (16 + 64 rates + 16 RKS)
132  // 16 infinite time rates
133  14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
134 
135  // rates 00-12
136  0, 1, 2, 3,
137  0, 1, 2, 3,
138  0, 1, 2, 3,
139  0, 1, 2, 3,
140  0, 1, 2, 3,
141  0, 1, 2, 3,
142  0, 1, 2, 3,
143  0, 1, 2, 3,
144  0, 1, 2, 3,
145  0, 1, 2, 3,
146  0, 1, 2, 3,
147  0, 1, 2, 3,
148  0, 1, 2, 3,
149 
150  // rate 13
151  4, 5, 6, 7,
152 
153  // rate 14
154  8, 9,10,11,
155 
156  // rate 15
157  12,12,12,12,
158 
159  // 16 dummy rates (same as 15 3)
160  12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
161 };
162 
163 // rate 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
164 // shift 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0
165 // mask 8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7, 3, 1, 0, 0, 0
166 
167 constexpr uint8_t eg_rate_shift[16 + 64 + 16] =
168 {
169  // Envelope Generator counter shifts (16 + 64 rates + 16 RKS)
170  // 16 infinite time rates
171  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172 
173  // rates 00-12
174  13,13,13,13,
175  12,12,12,12,
176  11,11,11,11,
177  10,10,10,10,
178  9, 9, 9, 9,
179  8, 8, 8, 8,
180  7, 7, 7, 7,
181  6, 6, 6, 6,
182  5, 5, 5, 5,
183  4, 4, 4, 4,
184  3, 3, 3, 3,
185  2, 2, 2, 2,
186  1, 1, 1, 1,
187 
188  // rate 13
189  0, 0, 0, 0,
190 
191  // rate 14
192  0, 0, 0, 0,
193 
194  // rate 15
195  0, 0, 0, 0,
196 
197  // 16 dummy rates (same as 15 3)
198  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 };
200 
201 // multiple table
202 static constexpr uint8_t ML(double x) { return uint8_t(2 * x); }
203 constexpr uint8_t mul_tab[16] =
204 {
205  ML( 0.50), ML( 1.00), ML( 2.00), ML( 3.00),
206  ML( 4.00), ML( 5.00), ML( 6.00), ML( 7.00),
207  ML( 8.00), ML( 9.00), ML(10.00), ML(10.00),
208  ML(12.00), ML(12.00), ML(15.00), ML(15.00),
209 };
210 
211 // TL_TAB_LEN is calculated as:
212 // 11 - sinus amplitude bits (Y axis)
213 // 2 - sinus sign bit (Y axis)
214 // TL_RES_LEN - sinus resolution (X axis)
215 constexpr int TL_TAB_LEN = 11 * 2 * TL_RES_LEN;
216 constexpr auto tlTab = [] {
217  std::array<int, TL_TAB_LEN> result = {};
218  for (int x = 0; x < TL_RES_LEN; ++x) {
219  double m = (1 << 16) / cstd::exp2<6>((x + 1) * (ENV_STEP / 4.0) / 8.0);
220 
221  // we never reach (1 << 16) here due to the (x + 1)
222  // result fits within 16 bits at maximum
223  int n = int(m); // 16 bits here
224  n >>= 4; // 12 bits here
225  n = (n >> 1) + (n & 1); // round to nearest
226  // 11 bits here (rounded)
227  for (int i = 0; i < 11; ++i) {
228  result[x * 2 + 0 + i * 2 * TL_RES_LEN] = n >> i;
229  result[x * 2 + 1 + i * 2 * TL_RES_LEN] = -(n >> i);
230  }
231  }
232  return result;
233 }();
234 
235 // sin waveform table in 'decibel' scale
236 // two waveforms on OPLL type chips
237 constexpr auto sinTab = [] {
238  std::array<unsigned, SIN_LEN * 2> result = {};
239  for (int i = 0; i < SIN_LEN / 4; ++i) {
240  // checked on real hardware, see also
241  // http://docs.google.com/Doc?id=dd8kqn9f_13cqjkf4gp
242  double m = cstd::sin<2>(((i * 2) + 1) * M_PI / SIN_LEN);
243  int n = int(cstd::round(cstd::log2<8, 3>(m) * -256.0));
244  result[i] = 2 * n;
245  }
246  for (int i = 0; i < SIN_LEN / 4; ++i) {
247  result[SIN_LEN / 4 + i] = result[SIN_LEN / 4 - 1 - i];
248  }
249  for (int i = 0; i < SIN_LEN / 2; ++i) {
250  result[SIN_LEN / 2 + i] = result[i] | 1;
251  }
252  for (int i = 0; i < SIN_LEN / 2; ++i) {
253  result[i + SIN_LEN] = result[i];
254  }
255  for (int i = 0; i < SIN_LEN / 2; ++i) {
256  result[i + SIN_LEN + SIN_LEN / 2] = TL_TAB_LEN;
257  }
258  return result;
259 }();
260 
261 // LFO Amplitude Modulation table (verified on real YM3812)
262 // 27 output levels (triangle waveform);
263 // 1 level takes one of: 192, 256 or 448 samples
264 //
265 // Length: 210 elements.
266 //
267 // Each of the elements has to be repeated
268 // exactly 64 times (on 64 consecutive samples).
269 // The whole table takes: 64 * 210 = 13440 samples.
270 //
271 // We use data>>1, until we find what it really is on real chip...
272 
273 constexpr int LFO_AM_TAB_ELEMENTS = 210;
274 constexpr uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS] =
275 {
276  0,0,0,0,0,0,0,
277  1,1,1,1,
278  2,2,2,2,
279  3,3,3,3,
280  4,4,4,4,
281  5,5,5,5,
282  6,6,6,6,
283  7,7,7,7,
284  8,8,8,8,
285  9,9,9,9,
286  10,10,10,10,
287  11,11,11,11,
288  12,12,12,12,
289  13,13,13,13,
290  14,14,14,14,
291  15,15,15,15,
292  16,16,16,16,
293  17,17,17,17,
294  18,18,18,18,
295  19,19,19,19,
296  20,20,20,20,
297  21,21,21,21,
298  22,22,22,22,
299  23,23,23,23,
300  24,24,24,24,
301  25,25,25,25,
302  26,26,26,
303  25,25,25,25,
304  24,24,24,24,
305  23,23,23,23,
306  22,22,22,22,
307  21,21,21,21,
308  20,20,20,20,
309  19,19,19,19,
310  18,18,18,18,
311  17,17,17,17,
312  16,16,16,16,
313  15,15,15,15,
314  14,14,14,14,
315  13,13,13,13,
316  12,12,12,12,
317  11,11,11,11,
318  10,10,10,10,
319  9,9,9,9,
320  8,8,8,8,
321  7,7,7,7,
322  6,6,6,6,
323  5,5,5,5,
324  4,4,4,4,
325  3,3,3,3,
326  2,2,2,2,
327  1,1,1,1
328 };
329 
330 // LFO Phase Modulation table (verified on real YM2413)
331 constexpr signed char lfo_pm_table[8][8] =
332 {
333  // FNUM2/FNUM = 0 00xxxxxx (0x0000)
334  { 0, 0, 0, 0, 0, 0, 0, 0, },
335 
336  // FNUM2/FNUM = 0 01xxxxxx (0x0040)
337  { 1, 0, 0, 0,-1, 0, 0, 0, },
338 
339  // FNUM2/FNUM = 0 10xxxxxx (0x0080)
340  { 2, 1, 0,-1,-2,-1, 0, 1, },
341 
342  // FNUM2/FNUM = 0 11xxxxxx (0x00C0)
343  { 3, 1, 0,-1,-3,-1, 0, 1, },
344 
345  // FNUM2/FNUM = 1 00xxxxxx (0x0100)
346  { 4, 2, 0,-2,-4,-2, 0, 2, },
347 
348  // FNUM2/FNUM = 1 01xxxxxx (0x0140)
349  { 5, 2, 0,-2,-5,-2, 0, 2, },
350 
351  // FNUM2/FNUM = 1 10xxxxxx (0x0180)
352  { 6, 3, 0,-3,-6,-3, 0, 3, },
353 
354  // FNUM2/FNUM = 1 11xxxxxx (0x01C0)
355  { 7, 3, 0,-3,-7,-3, 0, 3, },
356 };
357 
358 // This is not 100% perfect yet but very close
359 //
360 // - multi parameters are 100% correct (instruments and drums)
361 // - LFO PM and AM enable are 100% correct
362 // - waveform DC and DM select are 100% correct
363 constexpr uint8_t table[16 + 3][8] = {
364  // MULT MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR
365  // 0 1 2 3 4 5 6 7
366  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user instrument
367  { 0x61, 0x61, 0x1e, 0x17, 0xf0, 0x7f, 0x00, 0x17 }, // violin
368  { 0x13, 0x41, 0x16, 0x0e, 0xfd, 0xf4, 0x23, 0x23 }, // guitar
369  { 0x03, 0x01, 0x9a, 0x04, 0xf3, 0xf3, 0x13, 0xf3 }, // piano
370  { 0x11, 0x61, 0x0e, 0x07, 0xfa, 0x64, 0x70, 0x17 }, // flute
371  { 0x22, 0x21, 0x1e, 0x06, 0xf0, 0x76, 0x00, 0x28 }, // clarinet
372  { 0x21, 0x22, 0x16, 0x05, 0xf0, 0x71, 0x00, 0x18 }, // oboe
373  { 0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x17, 0x17 }, // trumpet
374  { 0x23, 0x21, 0x2d, 0x16, 0x90, 0x90, 0x00, 0x07 }, // organ
375  { 0x21, 0x21, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 }, // horn
376  { 0x21, 0x21, 0x0b, 0x1a, 0x85, 0xa0, 0x70, 0x07 }, // synthesizer
377  { 0x23, 0x01, 0x83, 0x10, 0xff, 0xb4, 0x10, 0xf4 }, // harpsichord
378  { 0x97, 0xc1, 0x20, 0x07, 0xff, 0xf4, 0x22, 0x22 }, // vibraphone
379  { 0x61, 0x00, 0x0c, 0x05, 0xc2, 0xf6, 0x40, 0x44 }, // synthesizer bass
380  { 0x01, 0x01, 0x56, 0x03, 0x94, 0xc2, 0x03, 0x12 }, // acoustic bass
381  { 0x21, 0x01, 0x89, 0x03, 0xf1, 0xe4, 0xf0, 0x23 }, // electric guitar
382  // drum instruments definitions
383  // MULTI MULTI modTL xxx AR/DR AR/DR SL/RR SL/RR
384  // 0 1 2 3 4 5 6 7
385  //{ 0x07, 0x21, 0x14, 0x00, 0xee, 0xf8, 0xff, 0xf8 },
386  //{ 0x01, 0x31, 0x00, 0x00, 0xf8, 0xf7, 0xf8, 0xf7 },
387  //{ 0x25, 0x11, 0x00, 0x00, 0xf8, 0xfa, 0xf8, 0x55 }
388  { 0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },// BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed)
389  { 0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },// HH(multi verified), SD(multi not used)
390  { 0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },// TOM(multi,env verified), TOP CYM(multi verified, env verified)
391 };
392 
393 static inline FreqIndex fnumToIncrement(int block_fnum)
394 {
395  // OPLL (YM2413) phase increment counter = 18bit
396  // Chip works with 10.10 fixed point, while we use 16.16.
397  const int block = (block_fnum & 0x1C00) >> 10;
398  return FreqIndex(block_fnum & 0x03FF) >> (11 - block);
399 }
400 
401 inline int Slot::calc_envelope(Channel& channel, unsigned eg_cnt, bool carrier)
402 {
403  switch (state) {
404  case EG_DUMP:
405  // Dump phase is performed by both operators in each channel.
406  // When CARRIER envelope gets down to zero level, phases in BOTH
407  // operators are reset (at the same time?).
408  // TODO: That sounds logical, but it does not match the implementation.
409  if (!(eg_cnt & eg_mask_dp)) {
410  egout += eg_sel_dp[(eg_cnt >> eg_sh_dp) & 7];
411  if (egout >= MAX_ATT_INDEX) {
412  egout = MAX_ATT_INDEX;
413  setEnvelopeState(EG_ATTACK);
414  phase = FreqIndex(0); // restart Phase Generator
415  }
416  }
417  break;
418 
419  case EG_ATTACK:
420  if (!(eg_cnt & eg_mask_ar)) {
421  egout +=
422  (~egout * eg_sel_ar[(eg_cnt >> eg_sh_ar) & 7]) >> 2;
423  if (egout <= MIN_ATT_INDEX) {
424  egout = MIN_ATT_INDEX;
425  setEnvelopeState(EG_DECAY);
426  }
427  }
428  break;
429 
430  case EG_DECAY:
431  if (!(eg_cnt & eg_mask_dr)) {
432  egout += eg_sel_dr[(eg_cnt >> eg_sh_dr) & 7];
433  if (egout >= sl) {
434  setEnvelopeState(EG_SUSTAIN);
435  }
436  }
437  break;
438 
439  case EG_SUSTAIN:
440  // this is important behaviour:
441  // one can change percusive/non-percussive modes on the fly and
442  // the chip will remain in sustain phase
443  // - verified on real YM3812
444  if (eg_sustain) {
445  // non-percussive mode (sustained tone)
446  // do nothing
447  } else {
448  // percussive mode
449  // during sustain phase chip adds Release Rate (in
450  // percussive mode)
451  if (!(eg_cnt & eg_mask_rr)) {
452  egout += eg_sel_rr[(eg_cnt >> eg_sh_rr) & 7];
453  if (egout >= MAX_ATT_INDEX) {
454  egout = MAX_ATT_INDEX;
455  }
456  }
457  // else do nothing in sustain phase
458  }
459  break;
460 
461  case EG_RELEASE:
462  // Exclude modulators in melody channels from performing anything in
463  // this mode.
464  if (carrier) {
465  const bool sustain = !eg_sustain || channel.isSustained();
466  const unsigned mask = sustain ? eg_mask_rs : eg_mask_rr;
467  if (!(eg_cnt & mask)) {
468  const uint8_t shift = sustain ? eg_sh_rs : eg_sh_rr;
469  const uint8_t* sel = sustain ? eg_sel_rs : eg_sel_rr;
470  egout += sel[(eg_cnt >> shift) & 7];
471  if (egout >= MAX_ATT_INDEX) {
472  egout = MAX_ATT_INDEX;
473  setEnvelopeState(EG_OFF);
474  }
475  }
476  }
477  break;
478 
479  case EG_OFF:
480  break;
481  }
482  return egout;
483 }
484 
485 inline int Slot::calc_phase(Channel& channel, unsigned lfo_pm)
486 {
487  if (vib) {
488  const int lfo_fn_table_index_offset = lfo_pm_table
489  [(channel.getBlockFNum() & 0x01FF) >> 6][lfo_pm];
490  phase += fnumToIncrement(
491  channel.getBlockFNum() * 2 + lfo_fn_table_index_offset
492  ) * mul;
493  } else {
494  // LFO phase modulation disabled for this operator
495  phase += freq;
496  }
497  return phase.toInt();
498 }
499 
500 inline void Slot::updateTotalLevel(Channel& channel)
501 {
502  TLL = TL + (channel.getKeyScaleLevelBase() >> ksl);
503 }
504 
505 inline void Slot::updateAttackRate(int kcodeScaled)
506 {
507  if ((ar + kcodeScaled) < (16 + 62)) {
508  eg_sh_ar = eg_rate_shift[ar + kcodeScaled];
509  eg_sel_ar = eg_inc[eg_rate_select[ar + kcodeScaled]];
510  } else {
511  eg_sh_ar = 0;
512  eg_sel_ar = eg_inc[13];
513  }
514  eg_mask_ar = (1 << eg_sh_ar) - 1;
515 }
516 
517 inline void Slot::updateDecayRate(int kcodeScaled)
518 {
519  eg_sh_dr = eg_rate_shift[dr + kcodeScaled];
520  eg_sel_dr = eg_inc[eg_rate_select[dr + kcodeScaled]];
521  eg_mask_dr = (1 << eg_sh_dr) - 1;
522 }
523 
524 inline void Slot::updateReleaseRate(int kcodeScaled)
525 {
526  eg_sh_rr = eg_rate_shift[rr + kcodeScaled];
527  eg_sel_rr = eg_inc[eg_rate_select[rr + kcodeScaled]];
528  eg_mask_rr = (1 << eg_sh_rr) - 1;
529 }
530 
531 inline int Slot::calcOutput(Channel& channel, unsigned eg_cnt, bool carrier,
532  unsigned lfo_am, int phase2)
533 {
534  int egout2 = calc_envelope(channel, eg_cnt, carrier);
535  int env = (TLL + egout2 + (lfo_am & AMmask)) << 5;
536  int p = env + wavetable[phase2 & SIN_MASK];
537  return p < TL_TAB_LEN ? tlTab[p] : 0;
538 }
539 
540 inline int Slot::calc_slot_mod(Channel& channel, unsigned eg_cnt, bool carrier,
541  unsigned lfo_pm, unsigned lfo_am)
542 {
543  // Compute phase.
544  int phase2 = calc_phase(channel, lfo_pm);
545  if (fb_shift) {
546  phase2 += (op1_out[0] + op1_out[1]) >> fb_shift;
547  }
548  // Shift output in 2-place buffer.
549  op1_out[0] = op1_out[1];
550  // Calculate operator output.
551  op1_out[1] = calcOutput(channel, eg_cnt, carrier, lfo_am, phase2);
552  return op1_out[0] << 1;
553 }
554 
555 inline int Channel::calcOutput(unsigned eg_cnt, unsigned lfo_pm, unsigned lfo_am, int fm)
556 {
557  int phase = car.calc_phase(*this, lfo_pm) + fm;
558  return car.calcOutput(*this, eg_cnt, true, lfo_am, phase);
559 }
560 
561 
562 // Operators used in the rhythm sounds generation process:
563 //
564 // Envelope Generator:
565 //
566 // channel operator register number Bass High Snare Tom Top
567 // / slot number TL ARDR SLRR Wave Drum Hat Drum Tom Cymbal
568 // 6 / 0 12 50 70 90 f0 +
569 // 6 / 1 15 53 73 93 f3 +
570 // 7 / 0 13 51 71 91 f1 +
571 // 7 / 1 16 54 74 94 f4 +
572 // 8 / 0 14 52 72 92 f2 +
573 // 8 / 1 17 55 75 95 f5 +
574 //
575 // Phase Generator:
576 //
577 // channel operator register number Bass High Snare Tom Top
578 // / slot number MULTIPLE Drum Hat Drum Tom Cymbal
579 // 6 / 0 12 30 +
580 // 6 / 1 15 33 +
581 // 7 / 0 13 31 + + +
582 // 7 / 1 16 34 ----- n o t u s e d -----
583 // 8 / 0 14 32 +
584 // 8 / 1 17 35 + +
585 //
586 // channel operator register number Bass High Snare Tom Top
587 // number number BLK/FNUM2 FNUM Drum Hat Drum Tom Cymbal
588 // 6 12,15 B6 A6 +
589 // 7 13,16 B7 A7 + + +
590 // 8 14,17 B8 A8 + + +
591 
592 // Phase generation is based on:
593 // HH (13) channel 7->slot 1 combined with channel 8->slot 2
594 // (same combination as TOP CYMBAL but different output phases)
595 // SD (16) channel 7->slot 1
596 // TOM (14) channel 8->slot 1
597 // TOP (17) channel 7->slot 1 combined with channel 8->slot 2
598 // (same combination as HIGH HAT but different output phases)
599 
600 static inline int genPhaseHighHat(int phaseM7, int phaseC8, int noise_rng)
601 {
602  // hi == phase >= 0x200
603  bool hi;
604  // enable gate based on frequency of operator 2 in channel 8
605  if (phaseC8 & 0x28) {
606  hi = true;
607  } else {
608  // base frequency derived from operator 1 in channel 7
609  // VC++ requires explicit conversion to bool. Compiler bug??
610  const bool bit7 = (phaseM7 & 0x80) != 0;
611  const bool bit3 = (phaseM7 & 0x08) != 0;
612  const bool bit2 = (phaseM7 & 0x04) != 0;
613  hi = (bit2 ^ bit7) | bit3;
614  }
615  if (noise_rng & 1) {
616  return hi ? (0x200 | 0xD0) : (0xD0 >> 2);
617  } else {
618  return hi ? (0x200 | (0xD0 >> 2)) : 0xD0;
619  }
620 }
621 
622 static inline int genPhaseSnare(int phaseM7, int noise_rng)
623 {
624  // base frequency derived from operator 1 in channel 7
625  // noise bit XOR'es phase by 0x100
626  return ((phaseM7 & 0x100) + 0x100)
627  ^ ((noise_rng & 1) << 8);
628 }
629 
630 static inline int genPhaseCymbal(int phaseM7, int phaseC8)
631 {
632  // enable gate based on frequency of operator 2 in channel 8
633  if (phaseC8 & 0x28) {
634  return 0x300;
635  } else {
636  // base frequency derived from operator 1 in channel 7
637  // VC++ requires explicit conversion to bool. Compiler bug??
638  const bool bit7 = (phaseM7 & 0x80) != 0;
639  const bool bit3 = (phaseM7 & 0x08) != 0;
640  const bool bit2 = (phaseM7 & 0x04) != 0;
641  return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
642  }
643 }
644 
645 
647  : phase(0), freq(0)
648 {
649  ar = dr = rr = KSR = ksl = mul = 0;
650  fb_shift = op1_out[0] = op1_out[1] = 0;
651  TL = TLL = egout = sl = 0;
652  eg_sh_dp = eg_sh_ar = eg_sh_dr = eg_sh_rr = eg_sh_rs = 0;
653  eg_sel_dp = eg_sel_ar = eg_sel_dr = eg_sel_rr = eg_sel_rs = eg_inc[0];
654  eg_mask_dp = eg_mask_ar = eg_mask_dr = eg_mask_rr = eg_mask_rs = 0;
655  eg_sustain = false;
656  setEnvelopeState(EG_OFF);
657  key = AMmask = vib = 0;
658  wavetable = &sinTab[0 * SIN_LEN];
659 }
660 
662 {
663  if (!key) {
664  // do NOT restart Phase Generator (verified on real YM2413)
665  setEnvelopeState(EG_DUMP);
666  }
667  key |= part;
668 }
669 
671 {
672  if (key) {
673  key &= ~part;
674  if (!key) {
675  if (isActive()) {
676  setEnvelopeState(EG_RELEASE);
677  }
678  }
679  }
680 }
681 
682 void Slot::setKeyOnOff(KeyPart part, bool enabled)
683 {
684  if (enabled) {
685  setKeyOn(part);
686  } else {
687  setKeyOff(part);
688  }
689 }
690 
691 bool Slot::isActive() const
692 {
693  return state != EG_OFF;
694 }
695 
696 void Slot::setEnvelopeState(EnvelopeState state_)
697 {
698  state = state_;
699 }
700 
701 void Slot::setFrequencyMultiplier(uint8_t value)
702 {
703  mul = mul_tab[value];
704 }
705 
706 void Slot::setKeyScaleRate(bool value)
707 {
708  KSR = value ? 0 : 2;
709 }
710 
712 {
713  eg_sustain = value;
714 }
715 
716 void Slot::setVibrato(bool value)
717 {
718  vib = value;
719 }
720 
722 {
723  AMmask = value ? ~0 : 0;
724 }
725 
726 void Slot::setTotalLevel(Channel& channel, uint8_t value)
727 {
728  TL = value << (ENV_BITS - 2 - 7); // 7 bits TL (bit 6 = always 0)
729  updateTotalLevel(channel);
730 }
731 
732 void Slot::setKeyScaleLevel(Channel& channel, uint8_t value)
733 {
734  ksl = value ? (3 - value) : 31;
735  updateTotalLevel(channel);
736 }
737 
738 void Slot::setWaveform(uint8_t value)
739 {
740  wavetable = &sinTab[value * SIN_LEN];
741 }
742 
743 void Slot::setFeedbackShift(uint8_t value)
744 {
745  fb_shift = value ? 8 - value : 0;
746 }
747 
748 void Slot::setAttackRate(const Channel& channel, uint8_t value)
749 {
750  int kcodeScaled = channel.getKeyCode() >> KSR;
751  ar = value ? 16 + (value << 2) : 0;
752  updateAttackRate(kcodeScaled);
753 }
754 
755 void Slot::setDecayRate(const Channel& channel, uint8_t value)
756 {
757  int kcodeScaled = channel.getKeyCode() >> KSR;
758  dr = value ? 16 + (value << 2) : 0;
759  updateDecayRate(kcodeScaled);
760 }
761 
762 void Slot::setReleaseRate(const Channel& channel, uint8_t value)
763 {
764  int kcodeScaled = channel.getKeyCode() >> KSR;
765  rr = value ? 16 + (value << 2) : 0;
766  updateReleaseRate(kcodeScaled);
767 }
768 
769 void Slot::setSustainLevel(uint8_t value)
770 {
771  sl = sl_tab[value];
772 }
773 
775 {
776  updateTotalLevel(channel);
777  updateGenerators(channel);
778 }
779 
781 {
782  wavetable = &sinTab[0 * SIN_LEN];
783  setEnvelopeState(EG_OFF);
784  egout = MAX_ATT_INDEX;
785 }
786 
788 {
789  // (frequency) phase increment counter
790  freq = channel.getFrequencyIncrement() * mul;
791 
792  // calculate envelope generator rates
793  const int kcodeScaled = channel.getKeyCode() >> KSR;
794  updateAttackRate(kcodeScaled);
795  updateDecayRate(kcodeScaled);
796  updateReleaseRate(kcodeScaled);
797 
798  const int rs = channel.isSustained() ? 16 + (5 << 2) : 16 + (7 << 2);
799  eg_sh_rs = eg_rate_shift[rs + kcodeScaled];
800  eg_sel_rs = eg_inc[eg_rate_select[rs + kcodeScaled]];
801 
802  const int dp = 16 + (13 << 2);
803  eg_sh_dp = eg_rate_shift[dp + kcodeScaled];
804  eg_sel_dp = eg_inc[eg_rate_select[dp + kcodeScaled]];
805 
806  eg_mask_rs = (1 << eg_sh_rs) - 1;
807  eg_mask_dp = (1 << eg_sh_dp) - 1;
808 }
809 
811  : fc(0)
812 {
813  block_fnum = ksl_base = 0;
814  sus = false;
815 }
816 
817 void Channel::setFrequency(int block_fnum_)
818 {
819  if (block_fnum == block_fnum_) return;
820  block_fnum = block_fnum_;
821 
822  ksl_base = ksl_tab[block_fnum >> 5];
823  fc = fnumToIncrement(block_fnum * 2);
824 
825  // Refresh Total Level and frequency counter in both SLOTs of this channel.
826  mod.updateFrequency(*this);
827  car.updateFrequency(*this);
828 }
829 
830 void Channel::setFrequencyLow(uint8_t value)
831 {
832  setFrequency((block_fnum & 0x0F00) | value);
833 }
834 
835 void Channel::setFrequencyHigh(uint8_t value)
836 {
837  setFrequency((value << 8) | (block_fnum & 0x00FF));
838 }
839 
841 {
842  return block_fnum;
843 }
844 
846 {
847  return fc;
848 }
849 
851 {
852  return ksl_base;
853 }
854 
855 uint8_t Channel::getKeyCode() const
856 {
857  // BLK 2,1,0 bits -> bits 3,2,1 of kcode, FNUM MSB -> kcode LSB
858  return (block_fnum & 0x0F00) >> 8;
859 }
860 
862 {
863  return sus;
864 }
865 
866 void Channel::setSustain(bool sustained)
867 {
868  sus = sustained;
869 }
870 
871 void Channel::updateInstrumentPart(int part, uint8_t value)
872 {
873  switch (part) {
874  case 0:
875  mod.setFrequencyMultiplier(value & 0x0F);
876  mod.setKeyScaleRate((value & 0x10) != 0);
877  mod.setEnvelopeSustained((value & 0x20) != 0);
878  mod.setVibrato((value & 0x40) != 0);
879  mod.setAmplitudeModulation((value & 0x80) != 0);
880  mod.updateGenerators(*this);
881  break;
882  case 1:
883  car.setFrequencyMultiplier(value & 0x0F);
884  car.setKeyScaleRate((value & 0x10) != 0);
885  car.setEnvelopeSustained((value & 0x20) != 0);
886  car.setVibrato((value & 0x40) != 0);
887  car.setAmplitudeModulation((value & 0x80) != 0);
888  car.updateGenerators(*this);
889  break;
890  case 2:
891  mod.setKeyScaleLevel(*this, value >> 6);
892  mod.setTotalLevel(*this, value & 0x3F);
893  break;
894  case 3:
895  mod.setWaveform((value & 0x08) >> 3);
896  mod.setFeedbackShift(value & 0x07);
897  car.setKeyScaleLevel(*this, value >> 6);
898  car.setWaveform((value & 0x10) >> 4);
899  break;
900  case 4:
901  mod.setAttackRate(*this, value >> 4);
902  mod.setDecayRate(*this, value & 0x0F);
903  break;
904  case 5:
905  car.setAttackRate(*this, value >> 4);
906  car.setDecayRate(*this, value & 0x0F);
907  break;
908  case 6:
909  mod.setSustainLevel(value >> 4);
910  mod.setReleaseRate(*this, value & 0x0F);
911  break;
912  case 7:
913  car.setSustainLevel(value >> 4);
914  car.setReleaseRate(*this, value & 0x0F);
915  break;
916  }
917 }
918 
919 void Channel::updateInstrument(const uint8_t* inst)
920 {
921  for (int part = 0; part < 8; ++part) {
922  updateInstrumentPart(part, inst[part]);
923  }
924 }
925 
927  : lfo_am_cnt(0), lfo_pm_cnt(0)
928 {
929  if (false) {
930  for (auto& e : tlTab) std::cout << e << '\n';
931  std::cout << '\n';
932  for (auto& e : sinTab) std::cout << e << '\n';
933  }
934 
935  memset(reg, 0, sizeof(reg)); // avoid UMR
936  eg_cnt = 0;
937  noise_rng = 0;
938 
939  reset();
940 }
941 
942 void YM2413::updateCustomInstrument(int part, uint8_t value)
943 {
944  // Update instrument definition.
945  inst_tab[0][part] = value;
946 
947  // Update every channel that has instrument 0 selected.
948  const int numMelodicChannels = isRhythm() ? 6 : 9;
949  for (int ch = 0; ch < numMelodicChannels; ++ch) {
950  Channel& channel = channels[ch];
951  if ((reg[0x30 + ch] & 0xF0) == 0) {
952  channel.updateInstrumentPart(part, value);
953  }
954  }
955 }
956 
957 void YM2413::setRhythmFlags(uint8_t old)
958 {
959  Channel& ch6 = channels[6];
960  Channel& ch7 = channels[7];
961  Channel& ch8 = channels[8];
962 
963  // flags = X | X | mode | BD | SD | TOM | TC | HH
964  uint8_t flags = reg[0x0E];
965  if ((flags ^ old) & 0x20) {
966  if (flags & 0x20) { // OFF -> ON
967  // Bass drum.
968  ch6.updateInstrument(inst_tab[16]);
969  // High hat and snare drum.
970  ch7.updateInstrument(inst_tab[17]);
971  ch7.mod.setTotalLevel(ch7, (reg[0x37] >> 4) << 2); // High hat
972  // Tom-tom and top cymbal.
973  ch8.updateInstrument(inst_tab[18]);
974  ch8.mod.setTotalLevel(ch8, (reg[0x38] >> 4) << 2); // Tom-tom
975  } else { // ON -> OFF
976  ch6.updateInstrument(inst_tab[reg[0x36] >> 4]);
977  ch7.updateInstrument(inst_tab[reg[0x37] >> 4]);
978  ch8.updateInstrument(inst_tab[reg[0x38] >> 4]);
979  // BD key off
980  ch6.mod.setKeyOff(Slot::KEY_RHYTHM);
981  ch6.car.setKeyOff(Slot::KEY_RHYTHM);
982  // HH key off
983  ch7.mod.setKeyOff(Slot::KEY_RHYTHM);
984  // SD key off
985  ch7.car.setKeyOff(Slot::KEY_RHYTHM);
986  // TOM key off
987  ch8.mod.setKeyOff(Slot::KEY_RHYTHM);
988  // TOP-CY off
989  ch8.car.setKeyOff(Slot::KEY_RHYTHM);
990  }
991  }
992  if (flags & 0x20) {
993  // BD key on/off
994  ch6.mod.setKeyOnOff(Slot::KEY_RHYTHM, (flags & 0x10) != 0);
995  ch6.car.setKeyOnOff(Slot::KEY_RHYTHM, (flags & 0x10) != 0);
996  // HH key on/off
997  ch7.mod.setKeyOnOff(Slot::KEY_RHYTHM, (flags & 0x01) != 0);
998  // SD key on/off
999  ch7.car.setKeyOnOff(Slot::KEY_RHYTHM, (flags & 0x08) != 0);
1000  // TOM key on/off
1001  ch8.mod.setKeyOnOff(Slot::KEY_RHYTHM, (flags & 0x04) != 0);
1002  // TOP-CY key on/off
1003  ch8.car.setKeyOnOff(Slot::KEY_RHYTHM, (flags & 0x02) != 0);
1004  }
1005 }
1006 
1008 {
1009  eg_cnt = 0;
1010  noise_rng = 1; // noise shift register
1011  idleSamples = 0;
1012 
1013  // setup instruments table
1014  for (int instrument = 0; instrument < 19; ++instrument) {
1015  for (int part = 0; part < 8; ++part) {
1016  inst_tab[instrument][part] = table[instrument][part];
1017  }
1018  }
1019 
1020  // reset with register write
1021  writeReg(0x0F, 0); // test reg
1022  for (int i = 0x3F; i >= 0x10; --i) {
1023  writeReg(i, 0);
1024  }
1025  registerLatch = 0;
1026 
1027  resetOperators();
1028 }
1029 
1030 void YM2413::resetOperators()
1031 {
1032  for (auto& ch : channels) {
1033  ch.mod.resetOperators();
1034  ch.car.resetOperators();
1035  }
1036 }
1037 
1038 bool YM2413::isRhythm() const
1039 {
1040  return (reg[0x0E] & 0x20) != 0;
1041 }
1042 
1043 Channel& YM2413::getChannelForReg(uint8_t r)
1044 {
1045  uint8_t chan = (r & 0x0F) % 9; // verified on real YM2413
1046  return channels[chan];
1047 }
1048 
1050 {
1051  return 1.0f / 2048.0f;
1052 }
1053 
1054 void YM2413::generateChannels(float* bufs[9 + 5], unsigned num)
1055 {
1056  // TODO make channelActiveBits a member and
1057  // keep it up-to-date all the time
1058 
1059  // bits 0-8 -> ch[0-8].car
1060  // bits 9-17 -> ch[0-8].mod (only ch7 and ch8 used)
1061  unsigned channelActiveBits = 0;
1062 
1063  const int numMelodicChannels = isRhythm() ? 6 : 9;
1064  for (int ch = 0; ch < numMelodicChannels; ++ch) {
1065  if (channels[ch].car.isActive()) {
1066  channelActiveBits |= 1 << ch;
1067  } else {
1068  bufs[ch] = nullptr;
1069  }
1070  }
1071  if (isRhythm()) {
1072  bufs[6] = nullptr;
1073  bufs[7] = nullptr;
1074  bufs[8] = nullptr;
1075  for (int ch = 6; ch < 9; ++ch) {
1076  if (channels[ch].car.isActive()) {
1077  channelActiveBits |= 1 << ch;
1078  } else {
1079  bufs[ch + 3] = nullptr;
1080  }
1081  }
1082  if (channels[7].mod.isActive()) {
1083  channelActiveBits |= 1 << (7 + 9);
1084  } else {
1085  bufs[12] = nullptr;
1086  }
1087  if (channels[8].mod.isActive()) {
1088  channelActiveBits |= 1 << (8 + 9);
1089  } else {
1090  bufs[13] = nullptr;
1091  }
1092  } else {
1093  bufs[ 9] = nullptr;
1094  bufs[10] = nullptr;
1095  bufs[11] = nullptr;
1096  bufs[12] = nullptr;
1097  bufs[13] = nullptr;
1098  }
1099 
1100  if (channelActiveBits) {
1101  idleSamples = 0;
1102  } else {
1103  if (idleSamples > (CLOCK_FREQ / (72 * 5))) {
1104  // Optimization:
1105  // idle for over 1/5s = 200ms
1106  // we don't care that noise / AM / PM isn't exactly
1107  // in sync with the real HW when music resumes
1108  // Alternative:
1109  // implement an efficient advance(n) method
1110  return;
1111  }
1112  idleSamples += num;
1113  }
1114 
1115  for (unsigned i = 0; i < num; ++i) {
1116  // Amplitude modulation: 27 output levels (triangle waveform)
1117  // 1 level takes one of: 192, 256 or 448 samples
1118  // One entry from LFO_AM_TABLE lasts for 64 samples
1119  lfo_am_cnt.addQuantum();
1120  if (lfo_am_cnt == LFOAMIndex(LFO_AM_TAB_ELEMENTS)) {
1121  // lfo_am_table is 210 elements long
1122  lfo_am_cnt = LFOAMIndex(0);
1123  }
1124  unsigned lfo_am = lfo_am_table[lfo_am_cnt.toInt()] >> 1;
1125  unsigned lfo_pm = lfo_pm_cnt.toInt() & 7;
1126 
1127  for (int ch = 0; ch < numMelodicChannels; ++ch) {
1128  Channel& channel = channels[ch];
1129  int fm = channel.mod.calc_slot_mod(channel, eg_cnt, false, lfo_pm, lfo_am);
1130  if ((channelActiveBits >> ch) & 1) {
1131  bufs[ch][i] += channel.calcOutput(eg_cnt, lfo_pm, lfo_am, fm);
1132  }
1133  }
1134  if (isRhythm()) {
1135  // Bass Drum (verified on real YM3812):
1136  // - depends on the channel 6 'connect' register:
1137  // when connect = 0 it works the same as in normal (non-rhythm) mode
1138  // (op1->op2->out)
1139  // when connect = 1 _only_ operator 2 is present on output (op2->out),
1140  // operator 1 is ignored
1141  // - output sample always is multiplied by 2
1142  Channel& channel6 = channels[6];
1143  int fm = channel6.mod.calc_slot_mod(channels[6], eg_cnt, true, lfo_pm, lfo_am);
1144  if (channelActiveBits & (1 << 6)) {
1145  bufs[ 9][i] += 2 * channel6.calcOutput(eg_cnt, lfo_pm, lfo_am, fm);
1146  }
1147 
1148  // TODO: Skip phase generation if output will 0 anyway.
1149  // Possible by passing phase generator as a template parameter to
1150  // calcOutput.
1151 
1152  /* phaseC7 */channels[7].car.calc_phase(channels[7], lfo_pm);
1153  int phaseM7 = channels[7].mod.calc_phase(channels[7], lfo_pm);
1154  int phaseC8 = channels[8].car.calc_phase(channels[8], lfo_pm);
1155  int phaseM8 = channels[8].mod.calc_phase(channels[8], lfo_pm);
1156 
1157  // Snare Drum (verified on real YM3812)
1158  if (channelActiveBits & (1 << 7)) {
1159  Slot& SLOT7_2 = channels[7].car;
1160  bufs[10][i] += 2 * SLOT7_2.calcOutput(channels[7], eg_cnt, true, lfo_am, genPhaseSnare(phaseM7, noise_rng));
1161  }
1162 
1163  // Top Cymbal (verified on real YM2413)
1164  if (channelActiveBits & (1 << 8)) {
1165  Slot& SLOT8_2 = channels[8].car;
1166  bufs[11][i] += 2 * SLOT8_2.calcOutput(channels[8], eg_cnt, true, lfo_am, genPhaseCymbal(phaseM7, phaseC8));
1167  }
1168 
1169  // High Hat (verified on real YM3812)
1170  if (channelActiveBits & (1 << (7 + 9))) {
1171  Slot& SLOT7_1 = channels[7].mod;
1172  bufs[12][i] += 2 * SLOT7_1.calcOutput(channels[7], eg_cnt, true, lfo_am, genPhaseHighHat(phaseM7, phaseC8, noise_rng));
1173  }
1174 
1175  // Tom Tom (verified on real YM3812)
1176  if (channelActiveBits & (1 << (8 + 9))) {
1177  Slot& SLOT8_1 = channels[8].mod;
1178  bufs[13][i] += 2 * SLOT8_1.calcOutput(channels[8], eg_cnt, true, lfo_am, phaseM8);
1179  }
1180  }
1181 
1182  // Vibrato: 8 output levels (triangle waveform)
1183  // 1 level takes 1024 samples
1184  lfo_pm_cnt.addQuantum();
1185 
1186  ++eg_cnt;
1187 
1188  // The Noise Generator of the YM3812 is 23-bit shift register.
1189  // Period is equal to 2^23-2 samples.
1190  // Register works at sampling frequency of the chip, so output
1191  // can change on every sample.
1192  //
1193  // Output of the register and input to the bit 22 is:
1194  // bit0 XOR bit14 XOR bit15 XOR bit22
1195  //
1196  // Simply use bit 22 as the noise output.
1197 
1198  // int j = ((noise_rng >> 0) ^ (noise_rng >> 14) ^
1199  // (noise_rng >> 15) ^ (noise_rng >> 22)) & 1;
1200  // noise_rng = (j << 22) | (noise_rng >> 1);
1201  //
1202  // Instead of doing all the logic operations above, we
1203  // use a trick here (and use bit 0 as the noise output).
1204  // The difference is only that the noise bit changes one
1205  // step ahead. This doesn't matter since we don't know
1206  // what is real state of the noise_rng after the reset.
1207  if (noise_rng & 1) {
1208  noise_rng ^= 0x800302;
1209  }
1210  noise_rng >>= 1;
1211  }
1212 }
1213 
1214 void YM2413::writePort(bool port, uint8_t value, int /*offset*/)
1215 {
1216  if (port == 0) {
1217  registerLatch = value;
1218  } else {
1219  writeReg(registerLatch & 0x3f, value);
1220  }
1221 }
1222 
1223 void YM2413::pokeReg(uint8_t r, uint8_t v)
1224 {
1225  writeReg(r, v);
1226 }
1227 
1228 void YM2413::writeReg(uint8_t r, uint8_t v)
1229 {
1230  uint8_t old = reg[r];
1231  reg[r] = v;
1232 
1233  switch (r & 0xF0) {
1234  case 0x00: { // 00-0F: control
1235  switch (r & 0x0F) {
1236  case 0x00: // AM/VIB/EGTYP/KSR/MULTI (modulator)
1237  case 0x01: // AM/VIB/EGTYP/KSR/MULTI (carrier)
1238  case 0x02: // Key Scale Level, Total Level (modulator)
1239  case 0x03: // Key Scale Level, carrier waveform, modulator waveform,
1240  // Feedback
1241  case 0x04: // Attack, Decay (modulator)
1242  case 0x05: // Attack, Decay (carrier)
1243  case 0x06: // Sustain, Release (modulator)
1244  case 0x07: // Sustain, Release (carrier)
1245  updateCustomInstrument(r, v);
1246  break;
1247  case 0x0E:
1248  setRhythmFlags(old);
1249  break;
1250  }
1251  break;
1252  }
1253  case 0x10: {
1254  // 10-18: FNUM 0-7
1255  Channel& ch = getChannelForReg(r);
1256  ch.setFrequencyLow(v);
1257  break;
1258  }
1259  case 0x20: {
1260  // 20-28: suson, keyon, block, FNUM 8
1261  Channel& ch = getChannelForReg(r);
1262  ch.mod.setKeyOnOff(Slot::KEY_MAIN, (v & 0x10) != 0);
1263  ch.car.setKeyOnOff(Slot::KEY_MAIN, (v & 0x10) != 0);
1264  ch.setSustain((v & 0x20) != 0);
1265  // Note: When changing the frequency, a new value for RS is
1266  // computed using the sustain value, so make sure the new
1267  // sustain value is committed first.
1268  ch.setFrequencyHigh(v & 0x0F);
1269  break;
1270  }
1271  case 0x30: { // inst 4 MSBs, VOL 4 LSBs
1272  Channel& ch = getChannelForReg(r);
1273  ch.car.setTotalLevel(ch, (v & 0x0F) << 2);
1274 
1275  // Check wether we are in rhythm mode and handle instrument/volume
1276  // register accordingly.
1277 
1278  uint8_t chan = (r & 0x0F) % 9; // verified on real YM2413
1279  if (isRhythm() && (chan >= 6)) {
1280  if (chan > 6) {
1281  // channel 7 or 8 in ryhthm mode
1282  // modulator envelope is HH(chan=7) or TOM(chan=8).
1283  ch.mod.setTotalLevel(ch, (v >> 4) << 2);
1284  }
1285  } else {
1286  if ((old & 0xF0) != (v & 0xF0)) {
1287  ch.updateInstrument(inst_tab[v >> 4]);
1288  }
1289  }
1290  break;
1291  }
1292  default:
1293  break;
1294  }
1295 }
1296 
1297 uint8_t YM2413::peekReg(uint8_t r) const
1298 {
1299  return reg[r];
1300 }
1301 
1302 } // namespace Burczynsk
1303 
1304 static std::initializer_list<enum_string<YM2413Burczynski::Slot::EnvelopeState>> envelopeStateInfo = {
1305  { "DUMP", YM2413Burczynski::Slot::EG_DUMP },
1306  { "ATTACK", YM2413Burczynski::Slot::EG_ATTACK },
1307  { "DECAY", YM2413Burczynski::Slot::EG_DECAY },
1308  { "SUSTAIN", YM2413Burczynski::Slot::EG_SUSTAIN },
1309  { "RELEASE", YM2413Burczynski::Slot::EG_RELEASE },
1311 };
1313 
1314 namespace YM2413Burczynski {
1315 
1316 // version 1: initial version
1317 // version 2: - removed kcodeScaled
1318 // - calculated more members from other state
1319 // (TLL, freq, eg_sel_*, eg_sh_*)
1320 template<typename Archive>
1321 void Slot::serialize(Archive& a, unsigned /*version*/)
1322 {
1323  // TODO some of the serialized members here could be calculated from
1324  // other members
1325  int waveform = (wavetable == &sinTab[0]) ? 0 : 1;
1326  a.serialize("waveform", waveform);
1327  if (a.isLoader()) {
1329  }
1330 
1331  a.serialize("phase", phase,
1332  "TL", TL,
1333  "volume", egout,
1334  "sl", sl,
1335  "state", state,
1336  "op1_out", op1_out,
1337  "eg_sustain", eg_sustain,
1338  "fb_shift", fb_shift,
1339  "key", key,
1340  "ar", ar,
1341  "dr", dr,
1342  "rr", rr,
1343  "KSR", KSR,
1344  "ksl", ksl,
1345  "mul", mul,
1346  "AMmask", AMmask,
1347  "vib", vib);
1348 
1349  // These are calculated by updateTotalLevel()
1350  // TLL
1351  // These are calculated by updateGenerators()
1352  // freq, eg_sh_ar, eg_sel_ar, eg_sh_dr, eg_sel_dr, eg_sh_rr, eg_sel_rr
1353  // eg_sh_rs, eg_sel_rs, eg_sh_dp, eg_sel_dp
1354 }
1355 
1356 // version 1: original version
1357 // version 2: removed kcode
1358 // version 3: removed instvol_r
1359 template<typename Archive>
1360 void Channel::serialize(Archive& a, unsigned /*version*/)
1361 {
1362  // mod/car were originally an array, keep serializing as such for bwc
1363  Slot slots[2] = { mod, car };
1364  a.serialize("slots", slots);
1365  if (a.isLoader()) {
1366  mod = slots[0];
1367  car = slots[1];
1368  }
1369 
1370  a.serialize("block_fnum", block_fnum,
1371  "fc", fc,
1372  "ksl_base", ksl_base,
1373  "sus", sus);
1374 
1375  if (a.isLoader()) {
1376  mod.updateFrequency(*this);
1377  car.updateFrequency(*this);
1378  }
1379 }
1380 
1381 // version 1: initial version
1382 // version 2: 'registers' are moved here (no longer serialized in base class)
1383 // version 3: removed 'rhythm' variable
1384 // version 4: added 'registerLatch'
1385 template<typename Archive>
1386 void YM2413::serialize(Archive& a, unsigned version)
1387 {
1388  if (a.versionBelow(version, 2)) a.beginTag("YM2413Core");
1389  a.serialize("registers", reg);
1390  if (a.versionBelow(version, 2)) a.endTag("YM2413Core");
1391 
1392  // only serialize user instrument
1393  a.serialize_blob("user_instrument", inst_tab[0], 8);
1394  a.serialize("channels", channels,
1395  "eg_cnt", eg_cnt,
1396  "noise_rng", noise_rng,
1397  "lfo_am_cnt", lfo_am_cnt,
1398  "lfo_pm_cnt", lfo_pm_cnt);
1399  if (a.versionAtLeast(version, 4)) {
1400  a.serialize("registerLatch", registerLatch);
1401  } else {
1402  // could be restored from MSXMusicBase, worth the effort?
1403  }
1404  // don't serialize idleSamples, it's only an optimization
1405 }
1406 
1407 } // namespace Burczynsk
1408 
1412 
1413 } // namespace openmsx
openmsx::YM2413Burczynski::SIN_MASK
constexpr int SIN_MASK
Definition: YM2413Burczynski.cc:43
openmsx::YM2413Burczynski::Channel::Channel
Channel()
Definition: YM2413Burczynski.cc:810
openmsx::YM2413Burczynski::Slot::isActive
bool isActive() const
Does this slot currently produce an output signal?
Definition: YM2413Burczynski.cc:691
openmsx::YM2413Burczynski::Channel::updateInstrument
void updateInstrument(const uint8_t *inst)
Sets all synthesis parameters as specified by the instrument.
Definition: YM2413Burczynski.cc:919
openmsx::YM2413Burczynski::Slot::setFrequencyMultiplier
void setFrequencyMultiplier(uint8_t value)
Sets the frequency multiplier [0..15].
Definition: YM2413Burczynski.cc:701
openmsx::YM2413Burczynski::YM2413::peekReg
uint8_t peekReg(uint8_t reg) const override
Read from a YM2413 register (for debug).
Definition: YM2413Burczynski.cc:1297
openmsx::YM2413Burczynski::Slot::serialize
void serialize(Archive &ar, unsigned version)
Definition: YM2413Burczynski.cc:1321
openmsx::YM2413Burczynski::SIN_LEN
constexpr int SIN_LEN
Definition: YM2413Burczynski.cc:42
openmsx::YM2413Burczynski::lfo_am_table
constexpr uint8_t lfo_am_table[LFO_AM_TAB_ELEMENTS]
Definition: YM2413Burczynski.cc:274
cstd::round
constexpr double round(double x)
Definition: cstd.hh:324
openmsx::YM2413Burczynski::Slot::calc_slot_mod
int calc_slot_mod(Channel &channel, unsigned eg_cnt, bool carrier, unsigned lfo_pm, unsigned lfo_am)
Definition: YM2413Burczynski.cc:540
serialize.hh
openmsx::YM2413Burczynski::Channel::setFrequencyHigh
void setFrequencyHigh(uint8_t value)
Changes the higher 4 bits of the frequency for this channel.
Definition: YM2413Burczynski.cc:835
openmsx::YM2413Burczynski::Slot::EG_ATTACK
@ EG_ATTACK
Definition: YM2413Burczynski.hh:110
openmsx::YM2413Burczynski::YM2413::reset
void reset() override
Reset this YM2413 core.
Definition: YM2413Burczynski.cc:1007
openmsx::YM2413Burczynski::Slot::setDecayRate
void setDecayRate(const Channel &channel, uint8_t value)
Sets the decay rate [0..15].
Definition: YM2413Burczynski.cc:755
openmsx::YM2413Burczynski::Channel::updateInstrumentPart
void updateInstrumentPart(int part, uint8_t value)
Sets some synthesis parameters as specified by the instrument.
Definition: YM2413Burczynski.cc:871
cstd.hh
openmsx::YM2413Burczynski::YM2413::YM2413
YM2413()
Definition: YM2413Burczynski.cc:926
openmsx::YM2413Burczynski::Channel::getBlockFNum
int getBlockFNum() const
Definition: YM2413Burczynski.cc:840
openmsx::YM2413Burczynski::Channel::getFrequencyIncrement
FreqIndex getFrequencyIncrement() const
Definition: YM2413Burczynski.cc:845
openmsx::YM2413Burczynski::ENV_STEP
constexpr double ENV_STEP
Definition: YM2413Burczynski.cc:35
openmsx::SERIALIZE_ENUM
SERIALIZE_ENUM(CassettePlayer::State, stateInfo)
openmsx::YM2413Burczynski::Slot::updateGenerators
void updateGenerators(Channel &channel)
Update phase increment counter of operator.
Definition: YM2413Burczynski.cc:787
openmsx::YM2413Burczynski::Slot::calc_phase
int calc_phase(Channel &channel, unsigned lfo_pm)
Definition: YM2413Burczynski.cc:485
openmsx::YM2413Burczynski::Slot::setKeyScaleLevel
void setKeyScaleLevel(Channel &channel, uint8_t value)
Sets the key scale level: 0->0 / 1->1.5 / 2->3.0 / 3->6.0 dB/OCT.
Definition: YM2413Burczynski.cc:732
openmsx::YM2413Burczynski::Channel::getKeyScaleLevelBase
int getKeyScaleLevelBase() const
Definition: YM2413Burczynski.cc:850
openmsx::FixedPoint::addQuantum
void addQuantum()
Increase this value with the smallest possible amount.
Definition: FixedPoint.hh:217
openmsx::YM2413Burczynski::Slot::setReleaseRate
void setReleaseRate(const Channel &channel, uint8_t value)
Sets the release rate [0..15].
Definition: YM2413Burczynski.cc:762
openmsx::FixedPoint::toInt
constexpr int toInt() const
Returns the integer part (rounded down) of this fixed point number.
Definition: FixedPoint.hh:76
openmsx::YM2413Burczynski::mul_tab
constexpr uint8_t mul_tab[16]
Definition: YM2413Burczynski.cc:203
openmsx::YM2413Burczynski::sl_tab
constexpr int sl_tab[16]
Definition: YM2413Burczynski.cc:99
openmsx::YM2413Burczynski::Slot::setVibrato
void setVibrato(bool value)
Enables (true) or disables (false) vibrato.
Definition: YM2413Burczynski.cc:716
openmsx::YM2413Burczynski::table
constexpr uint8_t table[16+3][8]
Definition: YM2413Burczynski.cc:363
openmsx::YM2413Okazaki::waveform
constexpr unsigned const *const waveform[2]
Definition: YM2413Okazaki.cc:246
openmsx::YM2413Burczynski::TL_RES_LEN
constexpr int TL_RES_LEN
Definition: YM2413Burczynski.cc:45
openmsx::YM2413Burczynski::Slot::KeyPart
KeyPart
Definition: YM2413Burczynski.hh:36
openmsx::YM2413Burczynski::Channel::getKeyCode
uint8_t getKeyCode() const
Definition: YM2413Burczynski.cc:855
openmsx::YM2413Burczynski::ENV_BITS
constexpr int ENV_BITS
Definition: YM2413Burczynski.cc:34
openmsx::YM2413Burczynski::Slot::calc_envelope
int calc_envelope(Channel &channel, unsigned eg_cnt, bool carrier)
Definition: YM2413Burczynski.cc:401
openmsx::YM2413Burczynski::Slot::setKeyOn
void setKeyOn(KeyPart part)
Definition: YM2413Burczynski.cc:661
M_PI
#define M_PI
Definition: Math.hh:27
openmsx::YM2413Burczynski::Slot::setWaveform
void setWaveform(uint8_t value)
Sets the waveform: 0 = sinus, 1 = half sinus, half silence.
Definition: YM2413Burczynski.cc:738
openmsx::YM2413Burczynski::Channel::mod
Slot mod
Definition: YM2413Burczynski.hh:212
openmsx::YM2413Burczynski::MIN_ATT_INDEX
constexpr int MIN_ATT_INDEX
Definition: YM2413Burczynski.cc:38
openmsx::YM2413Burczynski::Slot::EnvelopeState
EnvelopeState
Envelope Generator phases Note: These are ordered: phase constants are compared in the code.
Definition: YM2413Burczynski.hh:109
openmsx::YM2413Burczynski::Channel::setFrequencyLow
void setFrequencyLow(uint8_t value)
Changes the lower 8 bits of the frequency for this channel.
Definition: YM2413Burczynski.cc:830
openmsx::YM2413Burczynski::Slot::EG_OFF
@ EG_OFF
Definition: YM2413Burczynski.hh:110
openmsx::YM2413Burczynski::Slot::KEY_MAIN
@ KEY_MAIN
Definition: YM2413Burczynski.hh:36
openmsx::YM2413Burczynski::Channel::calcOutput
int calcOutput(unsigned eg_cnt, unsigned lfo_pm, unsigned lfo_am, int fm)
Calculate the value of the current sample produced by this channel.
Definition: YM2413Burczynski.cc:555
openmsx::YM2413Core::CLOCK_FREQ
static constexpr int CLOCK_FREQ
Input clock frequency.
Definition: YM2413Core.hh:40
openmsx::YM2413Burczynski::Slot::setAttackRate
void setAttackRate(const Channel &channel, uint8_t value)
Sets the attack rate [0..15].
Definition: YM2413Burczynski.cc:748
openmsx::YM2413Burczynski::Slot::setSustainLevel
void setSustainLevel(uint8_t value)
Sets the sustain level [0..15].
Definition: YM2413Burczynski.cc:769
openmsx::YM2413Okazaki::EnvelopeState
EnvelopeState
Definition: YM2413Okazaki.hh:16
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::YM2413Burczynski::TL_TAB_LEN
constexpr int TL_TAB_LEN
Definition: YM2413Burczynski.cc:215
openmsx::YM2413Burczynski::Slot
Definition: YM2413Burczynski.hh:18
openmsx::YM2413Burczynski::eg_rate_shift
constexpr uint8_t eg_rate_shift[16+64+16]
Definition: YM2413Burczynski.cc:167
openmsx::YM2413Burczynski::ksl_tab
constexpr int ksl_tab[8 *16]
Definition: YM2413Burczynski.cc:52
openmsx::YM2413Burczynski::Channel::setFrequency
void setFrequency(int block_fnum)
Sets the frequency for this channel.
Definition: YM2413Burczynski.cc:817
openmsx::YM2413Burczynski::Slot::setKeyOnOff
void setKeyOnOff(KeyPart part, bool enabled)
Definition: YM2413Burczynski.cc:682
openmsx::YM2413Burczynski::Channel::serialize
void serialize(Archive &ar, unsigned version)
Definition: YM2413Burczynski.cc:1360
openmsx::YM2413Burczynski::YM2413::generateChannels
void generateChannels(float *bufs[9+5], unsigned num) override
Definition: YM2413Burczynski.cc:1054
openmsx::YM2413Burczynski::Slot::EG_DECAY
@ EG_DECAY
Definition: YM2413Burczynski.hh:110
openmsx::YM2413
Definition: YM2413.hh:16
openmsx::YM2413Burczynski::YM2413::pokeReg
void pokeReg(uint8_t reg, uint8_t value) override
Write to a YM2413 register (for debug).
Definition: YM2413Burczynski.cc:1223
openmsx::YM2413Burczynski::Slot::EG_RELEASE
@ EG_RELEASE
Definition: YM2413Burczynski.hh:110
openmsx::YM2413Burczynski::Channel
Definition: YM2413Burczynski.hh:171
openmsx::YM2413Burczynski::tlTab
constexpr auto tlTab
Definition: YM2413Burczynski.cc:216
openmsx::YM2413Burczynski::Slot::EG_SUSTAIN
@ EG_SUSTAIN
Definition: YM2413Burczynski.hh:110
openmsx::YM2413Burczynski::Slot::setAmplitudeModulation
void setAmplitudeModulation(bool value)
Enables (true) or disables (false) amplitude modulation.
Definition: YM2413Burczynski.cc:721
openmsx::x
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1419
openmsx::YM2413Burczynski::lfo_pm_table
constexpr signed char lfo_pm_table[8][8]
Definition: YM2413Burczynski.cc:331
openmsx::YM2413Burczynski::eg_inc
constexpr uint8_t eg_inc[15][8]
Definition: YM2413Burczynski.cc:104
openmsx::YM2413Burczynski::Slot::calcOutput
int calcOutput(Channel &channel, unsigned eg_cnt, bool carrier, unsigned lfo_am, int phase)
Definition: YM2413Burczynski.cc:531
openmsx::YM2413Burczynski::Slot::updateFrequency
void updateFrequency(Channel &channel)
Called by Channel when block_fnum changes.
Definition: YM2413Burczynski.cc:774
openmsx::YM2413Burczynski::YM2413::serialize
void serialize(Archive &ar, unsigned version)
Definition: YM2413Burczynski.cc:1386
openmsx::YM2413Burczynski::Slot::setKeyScaleRate
void setKeyScaleRate(bool value)
Sets the key scale rate: true->0, false->2.
Definition: YM2413Burczynski.cc:706
openmsx::YM2413Burczynski::YM2413::getAmplificationFactor
float getAmplificationFactor() const override
Returns normalization factor.
Definition: YM2413Burczynski.cc:1049
openmsx::YM2413Core
Abstract interface for the YM2413 core.
Definition: YM2413Core.hh:27
openmsx::YM2413Burczynski::Slot::resetOperators
void resetOperators()
Definition: YM2413Burczynski.cc:780
openmsx::YM2413Burczynski::Channel::isSustained
bool isSustained() const
Definition: YM2413Burczynski.cc:861
openmsx::mask
constexpr nibble mask[4][13]
Definition: RP5C01.cc:33
openmsx::YM2413Burczynski::LFO_AM_TAB_ELEMENTS
constexpr int LFO_AM_TAB_ELEMENTS
Definition: YM2413Burczynski.cc:273
openmsx::YM2413Burczynski::sinTab
constexpr auto sinTab
Definition: YM2413Burczynski.cc:237
openmsx::YM2413Burczynski::Slot::KEY_RHYTHM
@ KEY_RHYTHM
Definition: YM2413Burczynski.hh:36
openmsx::YM2413
YM2413
Definition: YM2413.cc:119
openmsx::YM2413Burczynski::FreqIndex
FixedPoint< 16 > FreqIndex
16.16 fixed point type for frequency calculations.
Definition: YM2413Burczynski.hh:15
openmsx::YM2413Burczynski::eg_rate_select
constexpr uint8_t eg_rate_select[16+64+16]
Definition: YM2413Burczynski.cc:129
openmsx::YM2413Burczynski::Slot::setKeyOff
void setKeyOff(KeyPart part)
Definition: YM2413Burczynski.cc:670
openmsx::YM2413Burczynski::Slot::setEnvelopeSustained
void setEnvelopeSustained(bool value)
Sets the envelope type of the current instrument.
Definition: YM2413Burczynski.cc:711
Math.hh
openmsx::YM2413Burczynski::Slot::EG_DUMP
@ EG_DUMP
Definition: YM2413Burczynski.hh:110
openmsx::YM2413Burczynski::YM2413::writePort
void writePort(bool port, uint8_t value, int offset) override
Write to the YM2413 register/data port.
Definition: YM2413Burczynski.cc:1214
openmsx::YM2413Burczynski::Slot::Slot
Slot()
Definition: YM2413Burczynski.cc:646
openmsx::YM2413Burczynski::Slot::setFeedbackShift
void setFeedbackShift(uint8_t value)
Sets the amount of feedback [0..7].
Definition: YM2413Burczynski.cc:743
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
openmsx::REGISTER_POLYMORPHIC_INITIALIZER
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
openmsx::YM2413Burczynski::Slot::setTotalLevel
void setTotalLevel(Channel &channel, uint8_t value)
Sets the total level: [0..63].
Definition: YM2413Burczynski.cc:726
openmsx::YM2413Burczynski::Channel::car
Slot car
Definition: YM2413Burczynski.hh:213
YM2413Burczynski.hh
openmsx::YM2413Burczynski::MAX_ATT_INDEX
constexpr int MAX_ATT_INDEX
Definition: YM2413Burczynski.cc:37
openmsx::YM2413Burczynski::Channel::setSustain
void setSustain(bool sustained)
Definition: YM2413Burczynski.cc:866
openmsx::FixedPoint< 16 >
openmsx::YM2413Burczynski::SIN_BITS
constexpr int SIN_BITS
Definition: YM2413Burczynski.cc:41