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