OXYGENHUB
◆ main openmsx / src / sound / YM2413Burczynski.cc
39.4 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
e8555c89 Andy McCall 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
24
#include "Math.hh"
25
#include "cstd.hh"
26
#include "narrow.hh"
27
#include "ranges.hh"
28
#include "serialize.hh"
29
#include "xrange.hh"
30
31
#include <algorithm>
32
#include <array>
33
#include <cstdint>
34
#include <iostream>
35
#include <utility>
36
37
namespace openmsx {
38
namespace YM2413Burczynski {
39
40
// envelope output entries
41
static constexpr int ENV_BITS = 10;
42
static constexpr double ENV_STEP = 128.0 / (1 << ENV_BITS);
43
44
static constexpr int MAX_ATT_INDEX = (1 << (ENV_BITS - 2)) - 1; // 255
45
static constexpr int MIN_ATT_INDEX = 0;
46
47
static constexpr 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
53
static constexpr int DV(double x) { return narrow_cast<int>(x / 0.1875); }
54
static constexpr std::array<int, 8 * 16> ksl_tab =
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)
100
static constexpr int SC(int db) { return int(double(db) / ENV_STEP); }
101
static constexpr std::array<int, 16> sl_tab = {
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
106
static constexpr std::array eg_inc =
107
{
108
	//                       cycle: 0 1  2 3  4 5  6 7
109
	/* 0 */ std::array<uint8_t, 8>{ 0,1, 0,1, 0,1, 0,1, }, // rates 00..12 0 (increment by 0 or 1)
110
	/* 1 */ std::array<uint8_t, 8>{ 0,1, 0,1, 1,1, 0,1, }, // rates 00..12 1
111
	/* 2 */ std::array<uint8_t, 8>{ 0,1, 1,1, 0,1, 1,1, }, // rates 00..12 2
112
	/* 3 */ std::array<uint8_t, 8>{ 0,1, 1,1, 1,1, 1,1, }, // rates 00..12 3
113
114
	/* 4 */ std::array<uint8_t, 8>{ 1,1, 1,1, 1,1, 1,1, }, // rate 13 0 (increment by 1)
115
	/* 5 */ std::array<uint8_t, 8>{ 1,1, 1,2, 1,1, 1,2, }, // rate 13 1
116
	/* 6 */ std::array<uint8_t, 8>{ 1,2, 1,2, 1,2, 1,2, }, // rate 13 2
117
	/* 7 */ std::array<uint8_t, 8>{ 1,2, 2,2, 1,2, 2,2, }, // rate 13 3
118
119
	/* 8 */ std::array<uint8_t, 8>{ 2,2, 2,2, 2,2, 2,2, }, // rate 14 0 (increment by 2)
120
	/* 9 */ std::array<uint8_t, 8>{ 2,2, 2,4, 2,2, 2,4, }, // rate 14 1
121
	/*10 */ std::array<uint8_t, 8>{ 2,4, 2,4, 2,4, 2,4, }, // rate 14 2
122
	/*11 */ std::array<uint8_t, 8>{ 2,4, 4,4, 2,4, 4,4, }, // rate 14 3
123
124
	/*12 */ std::array<uint8_t, 8>{ 4,4, 4,4, 4,4, 4,4, }, // rates 15 0, 15 1, 15 2, 15 3 (incr by 4)
125
	/*13 */ std::array<uint8_t, 8>{ 8,8, 8,8, 8,8, 8,8, }, // rates 15 2, 15 3 for attack
126
	/*14 */ std::array<uint8_t, 8>{ 0,0, 0,0, 0,0, 0,0, }, // infinity rates for attack and decay(s)
127
};
128
129
// note that there is no value 13 in this table - it's directly in the code
130
static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_select =
131
{
132
	// Envelope Generator rates (16 + 64 rates + 16 RKS)
133
	// 16 infinite time rates
134
	14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
135
136
	// rates 00-12
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
	 0, 1, 2, 3,
150
151
	// rate 13
152
	 4, 5, 6, 7,
153
154
	// rate 14
155
	 8, 9,10,11,
156
157
	// rate 15
158
	12,12,12,12,
159
160
	// 16 dummy rates (same as 15 3)
161
	12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
162
};
163
164
// rate  0,    1,    2,    3,    4,   5,   6,   7,  8,  9, 10, 11, 12, 13, 14, 15
165
// shift 13,   12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0
166
// mask  8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0
167
168
static constexpr std::array<uint8_t, 16 + 64 + 16> eg_rate_shift =
169
{
170
	// Envelope Generator counter shifts (16 + 64 rates + 16 RKS)
171
	// 16 infinite time rates
172
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
173
174
	// rates 00-12
175
	13,13,13,13,
176
	12,12,12,12,
177
	11,11,11,11,
178
	10,10,10,10,
179
	 9, 9, 9, 9,
180
	 8, 8, 8, 8,
181
	 7, 7, 7, 7,
182
	 6, 6, 6, 6,
183
	 5, 5, 5, 5,
184
	 4, 4, 4, 4,
185
	 3, 3, 3, 3,
186
	 2, 2, 2, 2,
187
	 1, 1, 1, 1,
188
189
	// rate 13
190
	 0, 0, 0, 0,
191
192
	// rate 14
193
	 0, 0, 0, 0,
194
195
	// rate 15
196
	 0, 0, 0, 0,
197
198
	// 16 dummy rates (same as 15 3)
199
	 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200
};
201
202
// multiple table
203
static constexpr uint8_t ML(double x) { return uint8_t(2 * x); }
204
static constexpr std::array<uint8_t, 16> mul_tab =
205
{
206
	ML( 0.50), ML( 1.00), ML( 2.00), ML( 3.00),
207
	ML( 4.00), ML( 5.00), ML( 6.00), ML( 7.00),
208
	ML( 8.00), ML( 9.00), ML(10.00), ML(10.00),
209
	ML(12.00), ML(12.00), ML(15.00), ML(15.00),
210
};
211
212
//  TL_TAB_LEN is calculated as:
213
//  11 - sinus amplitude bits     (Y axis)
214
//  2  - sinus sign bit           (Y axis)
215
//  TL_RES_LEN - sinus resolution (X axis)
216
static constexpr int TL_TAB_LEN = 11 * 2 * TL_RES_LEN;
217
static constexpr auto tlTab = [] {
218
	std::array<int, TL_TAB_LEN> result = {};
219
	for (auto x : xrange(TL_RES_LEN)) {
220
		double m = (1 << 16) / cstd::exp2<6>((x + 1) * (ENV_STEP / 4.0) / 8.0);
221
222
		// we never reach (1 << 16) here due to the (x + 1)
223
		// result fits within 16 bits at maximum
224
		auto n = int(m); // 16 bits here
225
		n >>= 4;        // 12 bits here
226
		n = (n >> 1) + (n & 1); // round to nearest
227
		// 11 bits here (rounded)
228
		for (auto i : xrange(11)) {
229
			result[x * 2 + 0 + i * 2 * TL_RES_LEN] = n >> i;
230
			result[x * 2 + 1 + i * 2 * TL_RES_LEN] = -(n >> i);
231
		}
232
	}
233
	return result;
234
}();
235
236
// sin waveform table in 'decibel' scale
237
// two waveforms on OPLL type chips
238
static constexpr auto sinTab = [] {
239
	std::array<std::array<unsigned, SIN_LEN>, 2> result = {};
240
	for (auto i : xrange(SIN_LEN / 4)) {
241
		// checked on real hardware, see also
242
		//   http://docs.google.com/Doc?id=dd8kqn9f_13cqjkf4gp
243
		double m = cstd::sin<2>(narrow_cast<double>((i * 2) + 1) * Math::pi / SIN_LEN);
244
		auto n = int(cstd::round(cstd::log2<8, 3>(m) * -256.0));
245
		result[0][i] = 2 * n;
246
	}
247
	for (auto i : xrange(SIN_LEN / 4)) {
248
		result[0][SIN_LEN / 4 + i] = result[0][SIN_LEN / 4 - 1 - i];
249
	}
250
	for (auto i : xrange(SIN_LEN / 2)) {
251
		result[0][SIN_LEN / 2 + i] = result[0][i] | 1;
252
	}
253
	for (auto i : xrange(SIN_LEN / 2)) {
254
		result[1][i] = result[0][i];
255
	}
256
	for (auto i : xrange(SIN_LEN / 2)) {
257
		result[1][i + SIN_LEN / 2] = TL_TAB_LEN;
258
	}
259
	return result;
260
}();
261
262
// LFO Amplitude Modulation table (verified on real YM3812)
263
// 27 output levels (triangle waveform);
264
// 1 level takes one of: 192, 256 or 448 samples
265
//
266
// Length: 210 elements.
267
//
268
//  Each of the elements has to be repeated
269
//  exactly 64 times (on 64 consecutive samples).
270
//  The whole table takes: 64 * 210 = 13440 samples.
271
//
272
// We use data>>1, until we find what it really is on real chip...
273
274
static constexpr int LFO_AM_TAB_ELEMENTS = 210;
275
static constexpr std::array<uint8_t, LFO_AM_TAB_ELEMENTS> lfo_am_table =
276
{
277
	0,0,0,0,0,0,0,
278
	1,1,1,1,
279
	2,2,2,2,
280
	3,3,3,3,
281
	4,4,4,4,
282
	5,5,5,5,
283
	6,6,6,6,
284
	7,7,7,7,
285
	8,8,8,8,
286
	9,9,9,9,
287
	10,10,10,10,
288
	11,11,11,11,
289
	12,12,12,12,
290
	13,13,13,13,
291
	14,14,14,14,
292
	15,15,15,15,
293
	16,16,16,16,
294
	17,17,17,17,
295
	18,18,18,18,
296
	19,19,19,19,
297
	20,20,20,20,
298
	21,21,21,21,
299
	22,22,22,22,
300
	23,23,23,23,
301
	24,24,24,24,
302
	25,25,25,25,
303
	26,26,26,
304
	25,25,25,25,
305
	24,24,24,24,
306
	23,23,23,23,
307
	22,22,22,22,
308
	21,21,21,21,
309
	20,20,20,20,
310
	19,19,19,19,
311
	18,18,18,18,
312
	17,17,17,17,
313
	16,16,16,16,
314
	15,15,15,15,
315
	14,14,14,14,
316
	13,13,13,13,
317
	12,12,12,12,
318
	11,11,11,11,
319
	10,10,10,10,
320
	9,9,9,9,
321
	8,8,8,8,
322
	7,7,7,7,
323
	6,6,6,6,
324
	5,5,5,5,
325
	4,4,4,4,
326
	3,3,3,3,
327
	2,2,2,2,
328
	1,1,1,1
329
};
330
331
// LFO Phase Modulation table (verified on real YM2413)
332
static constexpr std::array lfo_pm_table =
333
{
334
	// FNUM2/FNUM = 0 00xxxxxx (0x0000)
335
	std::array<int8_t, 8>{ 0, 0, 0, 0, 0, 0, 0, 0, },
336
337
	// FNUM2/FNUM = 0 01xxxxxx (0x0040)
338
	std::array<int8_t, 8>{ 1, 0, 0, 0,-1, 0, 0, 0, },
339
340
	// FNUM2/FNUM = 0 10xxxxxx (0x0080)
341
	std::array<int8_t, 8>{ 2, 1, 0,-1,-2,-1, 0, 1, },
342
343
	// FNUM2/FNUM = 0 11xxxxxx (0x00C0)
344
	std::array<int8_t, 8>{ 3, 1, 0,-1,-3,-1, 0, 1, },
345
346
	// FNUM2/FNUM = 1 00xxxxxx (0x0100)
347
	std::array<int8_t, 8>{ 4, 2, 0,-2,-4,-2, 0, 2, },
348
349
	// FNUM2/FNUM = 1 01xxxxxx (0x0140)
350
	std::array<int8_t, 8>{ 5, 2, 0,-2,-5,-2, 0, 2, },
351
352
	// FNUM2/FNUM = 1 10xxxxxx (0x0180)
353
	std::array<int8_t, 8>{ 6, 3, 0,-3,-6,-3, 0, 3, },
354
355
	// FNUM2/FNUM = 1 11xxxxxx (0x01C0)
356
	std::array<int8_t, 8>{ 7, 3, 0,-3,-7,-3, 0, 3, },
357
};
358
359
// This is not 100% perfect yet but very close
360
//
361
// - multi parameters are 100% correct (instruments and drums)
362
// - LFO PM and AM enable are 100% correct
363
// - waveform DC and DM select are 100% correct
364
static constexpr std::array table = {
365
	//                     MULT  MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR
366
	//                       0     1     2     3     4     5     6     7
367
	std::array<uint8_t, 8>{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user instrument
368
	std::array<uint8_t, 8>{ 0x61, 0x61, 0x1e, 0x17, 0xf0, 0x7f, 0x00, 0x17 }, // violin
369
	std::array<uint8_t, 8>{ 0x13, 0x41, 0x16, 0x0e, 0xfd, 0xf4, 0x23, 0x23 }, // guitar
370
	std::array<uint8_t, 8>{ 0x03, 0x01, 0x9a, 0x04, 0xf3, 0xf3, 0x13, 0xf3 }, // piano
371
	std::array<uint8_t, 8>{ 0x11, 0x61, 0x0e, 0x07, 0xfa, 0x64, 0x70, 0x17 }, // flute
372
	std::array<uint8_t, 8>{ 0x22, 0x21, 0x1e, 0x06, 0xf0, 0x76, 0x00, 0x28 }, // clarinet
373
	std::array<uint8_t, 8>{ 0x21, 0x22, 0x16, 0x05, 0xf0, 0x71, 0x00, 0x18 }, // oboe
374
	std::array<uint8_t, 8>{ 0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x17, 0x17 }, // trumpet
375
	std::array<uint8_t, 8>{ 0x23, 0x21, 0x2d, 0x16, 0x90, 0x90, 0x00, 0x07 }, // organ
376
	std::array<uint8_t, 8>{ 0x21, 0x21, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 }, // horn
377
	std::array<uint8_t, 8>{ 0x21, 0x21, 0x0b, 0x1a, 0x85, 0xa0, 0x70, 0x07 }, // synthesizer
378
	std::array<uint8_t, 8>{ 0x23, 0x01, 0x83, 0x10, 0xff, 0xb4, 0x10, 0xf4 }, // harpsichord
379
	std::array<uint8_t, 8>{ 0x97, 0xc1, 0x20, 0x07, 0xff, 0xf4, 0x22, 0x22 }, // vibraphone
380
	std::array<uint8_t, 8>{ 0x61, 0x00, 0x0c, 0x05, 0xc2, 0xf6, 0x40, 0x44 }, // synthesizer bass
381
	std::array<uint8_t, 8>{ 0x01, 0x01, 0x56, 0x03, 0x94, 0xc2, 0x03, 0x12 }, // acoustic bass
382
	std::array<uint8_t, 8>{ 0x21, 0x01, 0x89, 0x03, 0xf1, 0xe4, 0xf0, 0x23 }, // electric guitar
383
	//                     drum instruments definitions
384
	//                     MULTI MULTI modTL  xxx  AR/DR AR/DR SL/RR SL/RR
385
	//                       0     1     2     3     4     5     6     7
386
	//                    { 0x07, 0x21, 0x14, 0x00, 0xee, 0xf8, 0xff, 0xf8 },
387
	//                    { 0x01, 0x31, 0x00, 0x00, 0xf8, 0xf7, 0xf8, 0xf7 },
388
	//                    { 0x25, 0x11, 0x00, 0x00, 0xf8, 0xfa, 0xf8, 0x55 }
389
	std::array<uint8_t, 8>{ 0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },// BD(multi verified, modTL verified, mod env - verified(close), carr. env verified)
390
	std::array<uint8_t, 8>{ 0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },// HH(multi verified), SD(multi not used)
391
	std::array<uint8_t, 8>{ 0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },// TOM(multi,env verified), TOP CYM(multi verified, env verified)
392
};
393
394
static constexpr FreqIndex fnumToIncrement(int block_fnum)
395
{
396
	// OPLL (YM2413) phase increment counter = 18bit
397
	// Chip works with 10.10 fixed point, while we use 16.16.
398
	const int block = (block_fnum & 0x1C00) >> 10;
399
	return FreqIndex(block_fnum & 0x03FF) >> (11 - block);
400
}
401
402
inline int Slot::calc_envelope(const Channel& channel, unsigned eg_cnt, bool carrier)
403
{
404
	switch (state) {
405
	using enum EnvelopeState;
406
	case 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(ATTACK);
416
				phase = FreqIndex(0); // restart Phase Generator
417
			}
418
		}
419
		break;
420
421
	case 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(DECAY);
428
			}
429
		}
430
		break;
431
432
	case 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(SUSTAIN);
437
			}
438
		}
439
		break;
440
441
	case 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
				egOut = std::min(egOut, MAX_ATT_INDEX);
456
			}
457
			// else do nothing in sustain phase
458
		}
459
		break;
460
461
	case 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
				std::span<const uint8_t, 8> 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(OFF);
474
				}
475
			}
476
		}
477
		break;
478
479
	case OFF:
480
		break;
481
	}
482
	return egOut;
483
}
484
485
inline int Slot::calc_phase(const Channel& channel, unsigned lfo_pm)
486
{
487
	if (vib) {
488
		auto lfo_fn_table_index_offset = narrow<int>(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(const 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(const Channel& channel, unsigned eg_cnt, bool carrier,
532
                            unsigned lfo_am, int phase2)
533
{
534
	int egOut2 = calc_envelope(channel, eg_cnt, carrier);
535
	auto env = narrow<unsigned>((TLL + egOut2 + (lfo_am & AMmask)) << 5);
536
	unsigned p = env + waveTable[phase2 & SIN_MASK];
537
	return p < TL_TAB_LEN ? tlTab[p] : 0;
538
}
539
540
inline int Slot::calc_slot_mod(const 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 constexpr int genPhaseHighHat(int phaseM7, int phaseC8, int noise_rng)
601
{
602
	// hi == phase >= 0x200
603
	// enable gate based on frequency of operator 2 in channel 8
604
	bool hi = [&] {
605
		if (phaseC8 & 0x28) {
606
			return 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
			return bool((bit2 ^ bit7) | bit3);
614
		}
615
	}();
616
	if (noise_rng & 1) {
617
		return hi ? (0x200 | 0xD0) : (0xD0 >> 2);
618
	} else {
619
		return hi ? (0x200 | (0xD0 >> 2)) : 0xD0;
620
	}
621
}
622
623
static constexpr int genPhaseSnare(int phaseM7, int noise_rng)
624
{
625
	// base frequency derived from operator 1 in channel 7
626
	// noise bit XOR'es phase by 0x100
627
	return ((phaseM7 & 0x100) + 0x100)
628
	     ^ ((noise_rng & 1) << 8);
629
}
630
631
static constexpr int genPhaseCymbal(int phaseM7, int phaseC8)
632
{
633
	// enable gate based on frequency of operator 2 in channel 8
634
	if (phaseC8 & 0x28) {
635
		return 0x300;
636
	} else {
637
		// base frequency derived from operator 1 in channel 7
638
		// VC++ requires explicit conversion to bool. Compiler bug??
639
		const bool bit7 = (phaseM7 & 0x80) != 0;
640
		const bool bit3 = (phaseM7 & 0x08) != 0;
641
		const bool bit2 = (phaseM7 & 0x04) != 0;
642
		return ((bit2 != bit7) || bit3) ? 0x300 : 0x100;
643
	}
644
}
645
646
647
Slot::Slot()
648
	: waveTable(sinTab[0])
649
	, eg_sel_dp(eg_inc[0]), eg_sel_ar(eg_inc[0]), eg_sel_dr(eg_inc[0])
650
	, eg_sel_rr(eg_inc[0]), eg_sel_rs(eg_inc[0])
651
{
652
	setEnvelopeState(EnvelopeState::OFF);
653
}
654
655
void Slot::setKeyOn(KeyPart part)
656
{
657
	if (!key) {
658
		// do NOT restart Phase Generator (verified on real YM2413)
659
		setEnvelopeState(EnvelopeState::DUMP);
660
	}
661
	key |= std::to_underlying(part);
662
}
663
664
void Slot::setKeyOff(KeyPart part)
665
{
666
	if (key) {
667
		key &= ~std::to_underlying(part);
668
		if (!key && isActive()) {
669
			setEnvelopeState(EnvelopeState::RELEASE);
670
		}
671
	}
672
}
673
674
void Slot::setKeyOnOff(KeyPart part, bool enabled)
675
{
676
	if (enabled) {
677
		setKeyOn(part);
678
	} else {
679
		setKeyOff(part);
680
	}
681
}
682
683
bool Slot::isActive() const
684
{
685
	return state != EnvelopeState::OFF;
686
}
687
688
void Slot::setEnvelopeState(EnvelopeState state_)
689
{
690
	state = state_;
691
}
692
693
void Slot::setFrequencyMultiplier(uint8_t value)
694
{
695
	mul = mul_tab[value];
696
}
697
698
void Slot::setKeyScaleRate(bool value)
699
{
700
	KSR = value ? 0 : 2;
701
}
702
703
void Slot::setEnvelopeSustained(bool value)
704
{
705
	eg_sustain = value;
706
}
707
708
void Slot::setVibrato(bool value)
709
{
710
	vib = value;
711
}
712
713
void Slot::setAmplitudeModulation(bool value)
714
{
715
	AMmask = value ? ~0 : 0;
716
}
717
718
void Slot::setTotalLevel(const Channel& channel, uint8_t value)
719
{
720
	TL = value << (ENV_BITS - 2 - 7); // 7 bits TL (bit 6 = always 0)
721
	updateTotalLevel(channel);
722
}
723
724
void Slot::setKeyScaleLevel(const Channel& channel, uint8_t value)
725
{
726
	ksl = value ? (3 - value) : 31;
727
	updateTotalLevel(channel);
728
}
729
730
void Slot::setWaveform(uint8_t value)
731
{
732
	waveTable = sinTab[value];
733
}
734
735
void Slot::setFeedbackShift(uint8_t value)
736
{
737
	fb_shift = value ? 8 - value : 0;
738
}
739
740
void Slot::setAttackRate(const Channel& channel, uint8_t value)
741
{
742
	int kcodeScaled = channel.getKeyCode() >> KSR;
743
	ar = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
744
	updateAttackRate(kcodeScaled);
745
}
746
747
void Slot::setDecayRate(const Channel& channel, uint8_t value)
748
{
749
	int kcodeScaled = channel.getKeyCode() >> KSR;
750
	dr = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
751
	updateDecayRate(kcodeScaled);
752
}
753
754
void Slot::setReleaseRate(const Channel& channel, uint8_t value)
755
{
756
	int kcodeScaled = channel.getKeyCode() >> KSR;
757
	rr = value ? narrow<uint8_t>(16 + (value << 2)) : 0;
758
	updateReleaseRate(kcodeScaled);
759
}
760
761
void Slot::setSustainLevel(uint8_t value)
762
{
763
	sl = sl_tab[value];
764
}
765
766
void Slot::updateFrequency(const Channel& channel)
767
{
768
	updateTotalLevel(channel);
769
	updateGenerators(channel);
770
}
771
772
void Slot::resetOperators()
773
{
774
	waveTable = sinTab[0];
775
	setEnvelopeState(EnvelopeState::OFF);
776
	egOut = MAX_ATT_INDEX;
777
}
778
779
void Slot::updateGenerators(const Channel& channel)
780
{
781
	// (frequency) phase increment counter
782
	freq = channel.getFrequencyIncrement() * mul;
783
784
	// calculate envelope generator rates
785
	const int kcodeScaled = channel.getKeyCode() >> KSR;
786
	updateAttackRate(kcodeScaled);
787
	updateDecayRate(kcodeScaled);
788
	updateReleaseRate(kcodeScaled);
789
790
	const int rs = channel.isSustained() ? 16 + (5 << 2) : 16 + (7 << 2);
791
	eg_sh_rs  = eg_rate_shift[rs + kcodeScaled];
792
	eg_sel_rs = eg_inc[eg_rate_select[rs + kcodeScaled]];
793
794
	const int dp = 16 + (13 << 2);
795
	eg_sh_dp  = eg_rate_shift[dp + kcodeScaled];
796
	eg_sel_dp = eg_inc[eg_rate_select[dp + kcodeScaled]];
797
798
	eg_mask_rs = (1 << eg_sh_rs) - 1;
799
	eg_mask_dp = (1 << eg_sh_dp) - 1;
800
}
801
802
void Channel::setFrequency(int block_fnum_)
803
{
804
	if (block_fnum == block_fnum_) return;
805
	block_fnum = block_fnum_;
806
807
	ksl_base = ksl_tab[block_fnum >> 5];
808
	fc       = fnumToIncrement(block_fnum * 2);
809
810
	// Refresh Total Level and frequency counter in both SLOTs of this channel.
811
	mod.updateFrequency(*this);
812
	car.updateFrequency(*this);
813
}
814
815
void Channel::setFrequencyLow(uint8_t value)
816
{
817
	setFrequency((block_fnum & 0x0F00) | value);
818
}
819
820
void Channel::setFrequencyHigh(uint8_t value)
821
{
822
	setFrequency((value << 8) | (block_fnum & 0x00FF));
823
}
824
825
int Channel::getBlockFNum() const
826
{
827
	return block_fnum;
828
}
829
830
FreqIndex Channel::getFrequencyIncrement() const
831
{
832
	return fc;
833
}
834
835
int Channel::getKeyScaleLevelBase() const
836
{
837
	return ksl_base;
838
}
839
840
uint8_t Channel::getKeyCode() const
841
{
842
	// BLK 2,1,0 bits -> bits 3,2,1 of kcode, FNUM MSB -> kcode LSB
843
	return (block_fnum & 0x0F00) >> 8;
844
}
845
846
bool Channel::isSustained() const
847
{
848
	return sus;
849
}
850
851
void Channel::setSustain(bool sustained)
852
{
853
	sus = sustained;
854
}
855
856
void Channel::updateInstrumentPart(int part, uint8_t value)
857
{
858
	switch (part) {
859
	case 0:
860
		mod.setFrequencyMultiplier(value & 0x0F);
861
		mod.setKeyScaleRate((value & 0x10) != 0);
862
		mod.setEnvelopeSustained((value & 0x20) != 0);
863
		mod.setVibrato((value & 0x40) != 0);
864
		mod.setAmplitudeModulation((value & 0x80) != 0);
865
		mod.updateGenerators(*this);
866
		break;
867
	case 1:
868
		car.setFrequencyMultiplier(value & 0x0F);
869
		car.setKeyScaleRate((value & 0x10) != 0);
870
		car.setEnvelopeSustained((value & 0x20) != 0);
871
		car.setVibrato((value & 0x40) != 0);
872
		car.setAmplitudeModulation((value & 0x80) != 0);
873
		car.updateGenerators(*this);
874
		break;
875
	case 2:
876
		mod.setKeyScaleLevel(*this, value >> 6);
877
		mod.setTotalLevel(*this, value & 0x3F);
878
		break;
879
	case 3:
880
		mod.setWaveform((value & 0x08) >> 3);
881
		mod.setFeedbackShift(value & 0x07);
882
		car.setKeyScaleLevel(*this, value >> 6);
883
		car.setWaveform((value & 0x10) >> 4);
884
		break;
885
	case 4:
886
		mod.setAttackRate(*this, value >> 4);
887
		mod.setDecayRate(*this, value & 0x0F);
888
		break;
889
	case 5:
890
		car.setAttackRate(*this, value >> 4);
891
		car.setDecayRate(*this, value & 0x0F);
892
		break;
893
	case 6:
894
		mod.setSustainLevel(value >> 4);
895
		mod.setReleaseRate(*this, value & 0x0F);
896
		break;
897
	case 7:
898
		car.setSustainLevel(value >> 4);
899
		car.setReleaseRate(*this, value & 0x0F);
900
		break;
901
	}
902
}
903
904
void Channel::updateInstrument(std::span<const uint8_t, 8> inst)
905
{
906
	for (auto part : xrange(8)) {
907
		updateInstrumentPart(part, inst[part]);
908
	}
909
}
910
911
YM2413::YM2413()
912
{
913
	if (false) {
914
		for (const auto& e : tlTab) std::cout << e << '\n';
915
		std::cout << '\n';
916
		for (const auto& s : sinTab) {
917
			for (const auto& e : s) std::cout << e << '\n';
918
		}
919
	}
920
921
	std::ranges::fill(reg, 0); // avoid UMR
922
	eg_cnt = 0;
923
	noise_rng = 0;
924
925
	reset();
926
}
927
928
void YM2413::updateCustomInstrument(int part, uint8_t value)
929
{
930
	// Update instrument definition.
931
	inst_tab[0][part] = value;
932
933
	// Update every channel that has instrument 0 selected.
934
	for (auto ch : xrange(isRhythm() ? 6 : 9)) {
935
		Channel& channel = channels[ch];
936
		if ((reg[0x30 + ch] & 0xF0) == 0) {
937
			channel.updateInstrumentPart(part, value);
938
		}
939
	}
940
}
941
942
void YM2413::setRhythmFlags(uint8_t old)
943
{
944
	Channel& ch6 = channels[6];
945
	Channel& ch7 = channels[7];
946
	Channel& ch8 = channels[8];
947
948
	// flags = X | X | mode | BD | SD | TOM | TC | HH
949
	using enum Slot::KeyPart;
950
	uint8_t flags = reg[0x0E];
951
	if ((flags ^ old) & 0x20) {
952
		if (flags & 0x20) { // OFF -> ON
953
			// Bass drum.
954
			ch6.updateInstrument(inst_tab[16]);
955
			// High hat and snare drum.
956
			ch7.updateInstrument(inst_tab[17]);
957
			ch7.mod.setTotalLevel(ch7, uint8_t((reg[0x37] >> 4) << 2)); // High hat
958
			// Tom-tom and top cymbal.
959
			ch8.updateInstrument(inst_tab[18]);
960
			ch8.mod.setTotalLevel(ch8, uint8_t((reg[0x38] >> 4) << 2)); // Tom-tom
961
		} else { // ON -> OFF
962
			ch6.updateInstrument(inst_tab[reg[0x36] >> 4]);
963
			ch7.updateInstrument(inst_tab[reg[0x37] >> 4]);
964
			ch8.updateInstrument(inst_tab[reg[0x38] >> 4]);
965
966
			// BD key off
967
			ch6.mod.setKeyOff(RHYTHM);
968
			ch6.car.setKeyOff(RHYTHM);
969
			// HH key off
970
			ch7.mod.setKeyOff(RHYTHM);
971
			// SD key off
972
			ch7.car.setKeyOff(RHYTHM);
973
			// TOM key off
974
			ch8.mod.setKeyOff(RHYTHM);
975
			// TOP-CY off
976
			ch8.car.setKeyOff(RHYTHM);
977
		}
978
	}
979
	if (flags & 0x20) {
980
		// BD key on/off
981
		ch6.mod.setKeyOnOff(RHYTHM, (flags & 0x10) != 0);
982
		ch6.car.setKeyOnOff(RHYTHM, (flags & 0x10) != 0);
983
		// HH key on/off
984
		ch7.mod.setKeyOnOff(RHYTHM, (flags & 0x01) != 0);
985
		// SD key on/off
986
		ch7.car.setKeyOnOff(RHYTHM, (flags & 0x08) != 0);
987
		// TOM key on/off
988
		ch8.mod.setKeyOnOff(RHYTHM, (flags & 0x04) != 0);
989
		// TOP-CY key on/off
990
		ch8.car.setKeyOnOff(RHYTHM, (flags & 0x02) != 0);
991
	}
992
}
993
994
void YM2413::reset()
995
{
996
	eg_cnt    = 0;
997
	noise_rng = 1;    // noise shift register
998
	idleSamples = 0;
999
1000
	// setup instruments table
1001
	inst_tab = table;
1002
1003
	// reset with register write
1004
	writeReg(0x0F, 0); // test reg
1005
	for (uint8_t i = 0x3F; i >= 0x10; --i) {
1006
		writeReg(i, 0);
1007
	}
1008
	registerLatch = 0;
1009
1010
	resetOperators();
1011
}
1012
1013
void YM2413::resetOperators()
1014
{
1015
	for (auto& ch : channels) {
1016
		ch.mod.resetOperators();
1017
		ch.car.resetOperators();
1018
	}
1019
}
1020
1021
bool YM2413::isRhythm() const
1022
{
1023
	return (reg[0x0E] & 0x20) != 0;
1024
}
1025
1026
Channel& YM2413::getChannelForReg(uint8_t r)
1027
{
1028
	uint8_t chan = (r & 0x0F) % 9; // verified on real YM2413
1029
	return channels[chan];
1030
}
1031
1032
float YM2413::getAmplificationFactor() const
1033
{
1034
	return 1.0f / 2048.0f;
1035
}
1036
1037
void YM2413::generateChannels(std::span<float*, 9 + 5> bufs, unsigned num)
1038
{
1039
	// TODO make channelActiveBits a member and
1040
	//      keep it up-to-date all the time
1041
1042
	// bits 0-8  -> ch[0-8].car
1043
	// bits 9-17 -> ch[0-8].mod (only ch7 and ch8 used)
1044
	unsigned channelActiveBits = 0;
1045
1046
	for (auto ch : xrange(isRhythm() ? 6 : 9)) {
1047
		if (channels[ch].car.isActive()) {
1048
			channelActiveBits |= 1 << ch;
1049
		} else {
1050
			bufs[ch] = nullptr;
1051
		}
1052
	}
1053
	if (isRhythm()) {
1054
		std::ranges::fill(subspan<3>(bufs, 6), nullptr);
1055
		for (auto ch : xrange(6, 9)) {
1056
			if (channels[ch].car.isActive()) {
1057
				channelActiveBits |= 1 << ch;
1058
			} else {
1059
				bufs[ch + 3] = nullptr;
1060
			}
1061
		}
1062
		if (channels[7].mod.isActive()) {
1063
			channelActiveBits |= 1 << (7 + 9);
1064
		} else {
1065
			bufs[12] = nullptr;
1066
		}
1067
		if (channels[8].mod.isActive()) {
1068
			channelActiveBits |= 1 << (8 + 9);
1069
		} else {
1070
			bufs[13] = nullptr;
1071
		}
1072
	} else {
1073
		std::ranges::fill(subspan<5>(bufs, 9), nullptr);
1074
	}
1075
1076
	if (channelActiveBits) {
1077
		idleSamples = 0;
1078
	} else {
1079
		if (idleSamples > (CLOCK_FREQ / (72 * 5))) {
1080
			// Optimization:
1081
			//   idle for over 1/5s = 200ms
1082
			//   we don't care that noise / AM / PM isn't exactly
1083
			//   in sync with the real HW when music resumes
1084
			// Alternative:
1085
			//   implement an efficient advance(n) method
1086
			return;
1087
		}
1088
		idleSamples += num;
1089
	}
1090
1091
	for (auto i : xrange(num)) {
1092
		// Amplitude modulation: 27 output levels (triangle waveform)
1093
		// 1 level takes one of: 192, 256 or 448 samples
1094
		// One entry from LFO_AM_TABLE lasts for 64 samples
1095
		lfo_am_cnt.addQuantum();
1096
		if (lfo_am_cnt == LFOAMIndex(LFO_AM_TAB_ELEMENTS)) {
1097
			// lfo_am_table is 210 elements long
1098
			lfo_am_cnt = LFOAMIndex(0);
1099
		}
1100
		unsigned lfo_am = lfo_am_table[lfo_am_cnt.toInt()] >> 1;
1101
		unsigned lfo_pm = lfo_pm_cnt.toInt() & 7;
1102
1103
		for (auto ch : xrange(isRhythm() ? 6 : 9)) {
1104
			Channel& channel = channels[ch];
1105
			int fm = channel.mod.calc_slot_mod(channel, eg_cnt, false, lfo_pm, lfo_am);
1106
			if ((channelActiveBits >> ch) & 1) {
1107
				bufs[ch][i] += narrow_cast<float>(channel.calcOutput(eg_cnt, lfo_pm, lfo_am, fm));
1108
			}
1109
		}
1110
		if (isRhythm()) {
1111
			// Bass Drum (verified on real YM3812):
1112
			//  - depends on the channel 6 'connect' register:
1113
			//    when connect = 0 it works the same as in normal (non-rhythm) mode
1114
			//                     (op1->op2->out)
1115
			//    when connect = 1 _only_ operator 2 is present on output (op2->out),
1116
			//                     operator 1 is ignored
1117
			//  - output sample always is multiplied by 2
1118
			Channel& channel6 = channels[6];
1119
			int fm = channel6.mod.calc_slot_mod(channels[6], eg_cnt, true, lfo_pm, lfo_am);
1120
			if (channelActiveBits & (1 << 6)) {
1121
				bufs[ 9][i] += narrow_cast<float>(2 * channel6.calcOutput(eg_cnt, lfo_pm, lfo_am, fm));
1122
			}
1123
1124
			// TODO: Skip phase generation if output will 0 anyway.
1125
			//       Possible by passing phase generator as a template parameter to
1126
			//       calcOutput.
1127
1128
			/*C7*/  (void)channels[7].car.calc_phase(channels[7], lfo_pm);
1129
			int phaseM7 = channels[7].mod.calc_phase(channels[7], lfo_pm);
1130
			int phaseC8 = channels[8].car.calc_phase(channels[8], lfo_pm);
1131
			int phaseM8 = channels[8].mod.calc_phase(channels[8], lfo_pm);
1132
1133
			// Snare Drum (verified on real YM3812)
1134
			if (channelActiveBits & (1 << 7)) {
1135
				Slot& SLOT7_2 = channels[7].car;
1136
				bufs[10][i] += narrow_cast<float>(2 * SLOT7_2.calcOutput(channels[7], eg_cnt, true, lfo_am, genPhaseSnare(phaseM7, noise_rng)));
1137
			}
1138
1139
			// Top Cymbal (verified on real YM2413)
1140
			if (channelActiveBits & (1 << 8)) {
1141
				Slot& SLOT8_2 = channels[8].car;
1142
				bufs[11][i] += narrow_cast<float>(2 * SLOT8_2.calcOutput(channels[8], eg_cnt, true, lfo_am, genPhaseCymbal(phaseM7, phaseC8)));
1143
			}
1144
1145
			// High Hat (verified on real YM3812)
1146
			if (channelActiveBits & (1 << (7 + 9))) {
1147
				Slot& SLOT7_1 = channels[7].mod;
1148
				bufs[12][i] += narrow_cast<float>(2 * SLOT7_1.calcOutput(channels[7], eg_cnt, true, lfo_am, genPhaseHighHat(phaseM7, phaseC8, noise_rng)));
1149
			}
1150
1151
			// Tom Tom (verified on real YM3812)
1152
			if (channelActiveBits & (1 << (8 + 9))) {
1153
				Slot& SLOT8_1 = channels[8].mod;
1154
				bufs[13][i] += narrow_cast<float>(2 * SLOT8_1.calcOutput(channels[8], eg_cnt, true, lfo_am, phaseM8));
1155
			}
1156
		}
1157
1158
		// Vibrato: 8 output levels (triangle waveform)
1159
		// 1 level takes 1024 samples
1160
		lfo_pm_cnt.addQuantum();
1161
1162
		++eg_cnt;
1163
1164
		// The Noise Generator of the YM3812 is 23-bit shift register.
1165
		// Period is equal to 2^23-2 samples.
1166
		// Register works at sampling frequency of the chip, so output
1167
		// can change on every sample.
1168
		//
1169
		// Output of the register and input to the bit 22 is:
1170
		// bit0 XOR bit14 XOR bit15 XOR bit22
1171
		//
1172
		// Simply use bit 22 as the noise output.
1173
1174
		//  int j = ((noise_rng >>  0) ^ (noise_rng >> 14) ^
1175
		//           (noise_rng >> 15) ^ (noise_rng >> 22)) & 1;
1176
		//  noise_rng = (j << 22) | (noise_rng >> 1);
1177
		//
1178
		//    Instead of doing all the logic operations above, we
1179
		//    use a trick here (and use bit 0 as the noise output).
1180
		//    The difference is only that the noise bit changes one
1181
		//    step ahead. This doesn't matter since we don't know
1182
		//    what is real state of the noise_rng after the reset.
1183
		if (noise_rng & 1) {
1184
			noise_rng ^= 0x800302;
1185
		}
1186
		noise_rng >>= 1;
1187
	}
1188
}
1189
1190
void YM2413::writePort(bool port, uint8_t value, int /*offset*/)
1191
{
1192
	if (port == 0) {
1193
		registerLatch = value;
1194
	} else {
1195
		writeReg(registerLatch & 0x3f, value);
1196
	}
1197
}
1198
1199
void YM2413::pokeReg(uint8_t r, uint8_t v)
1200
{
1201
	writeReg(r, v);
1202
}
1203
1204
void YM2413::writeReg(uint8_t r, uint8_t v)
1205
{
1206
	uint8_t old = reg[r];
1207
	reg[r] = v;
1208
1209
	switch (r & 0xF0) {
1210
	case 0x00: { // 00-0F: control
1211
		switch (r & 0x0F) {
1212
		case 0x00:  // AM/VIB/EGTYP/KSR/MULTI (modulator)
1213
		case 0x01:  // AM/VIB/EGTYP/KSR/MULTI (carrier)
1214
		case 0x02:  // Key Scale Level, Total Level (modulator)
1215
		case 0x03:  // Key Scale Level, carrier waveform, modulator waveform,
1216
		            // Feedback
1217
		case 0x04:  // Attack, Decay (modulator)
1218
		case 0x05:  // Attack, Decay (carrier)
1219
		case 0x06:  // Sustain, Release (modulator)
1220
		case 0x07:  // Sustain, Release (carrier)
1221
			updateCustomInstrument(r, v);
1222
			break;
1223
		case 0x0E:
1224
			setRhythmFlags(old);
1225
			break;
1226
		}
1227
		break;
1228
	}
1229
	case 0x10: {
1230
		// 10-18: FNUM 0-7
1231
		Channel& ch = getChannelForReg(r);
1232
		ch.setFrequencyLow(v);
1233
		break;
1234
	}
1235
	case 0x20: {
1236
		// 20-28: susOn, keyOn, block, FNUM 8
1237
		Channel& ch = getChannelForReg(r);
1238
		ch.mod.setKeyOnOff(Slot::KeyPart::MAIN, (v & 0x10) != 0);
1239
		ch.car.setKeyOnOff(Slot::KeyPart::MAIN, (v & 0x10) != 0);
1240
		ch.setSustain((v & 0x20) != 0);
1241
		// Note: When changing the frequency, a new value for RS is
1242
		//       computed using the sustain value, so make sure the new
1243
		//       sustain value is committed first.
1244
		ch.setFrequencyHigh(v & 0x0F);
1245
		break;
1246
	}
1247
	case 0x30: { // inst 4 MSBs, VOL 4 LSBs
1248
		Channel& ch = getChannelForReg(r);
1249
		ch.car.setTotalLevel(ch, uint8_t((v & 0x0F) << 2));
1250
1251
		// Check wether we are in rhythm mode and handle instrument/volume
1252
		// register accordingly.
1253
1254
		uint8_t chan = (r & 0x0F) % 9; // verified on real YM2413
1255
		if (isRhythm() && (chan >= 6)) {
1256
			if (chan > 6) {
1257
				// channel 7 or 8 in rythm mode
1258
				// modulator envelope is HH(chan=7) or TOM(chan=8).
1259
				ch.mod.setTotalLevel(ch, uint8_t((v >> 4) << 2));
1260
			}
1261
		} else {
1262
			if ((old & 0xF0) != (v & 0xF0)) {
1263
				ch.updateInstrument(inst_tab[v >> 4]);
1264
			}
1265
		}
1266
		break;
1267
	}
1268
	default:
1269
		break;
1270
	}
1271
}
1272
1273
std::span<const uint8_t, 64> YM2413::peekRegs() const
1274
{
1275
	return reg;
1276
}
1277
1278
} // namespace YM2413Burczynski
1279
1280
static constexpr auto envelopeStateInfo = std::to_array<enum_string<YM2413Burczynski::Slot::EnvelopeState>>({
1281
	{ "DUMP",    YM2413Burczynski::Slot::EnvelopeState::DUMP    },
1282
	{ "ATTACK",  YM2413Burczynski::Slot::EnvelopeState::ATTACK  },
1283
	{ "DECAY",   YM2413Burczynski::Slot::EnvelopeState::DECAY   },
1284
	{ "SUSTAIN", YM2413Burczynski::Slot::EnvelopeState::SUSTAIN },
1285
	{ "RELEASE", YM2413Burczynski::Slot::EnvelopeState::RELEASE },
1286
	{ "OFF",     YM2413Burczynski::Slot::EnvelopeState::OFF     },
1287
});
1288
SERIALIZE_ENUM(YM2413Burczynski::Slot::EnvelopeState, envelopeStateInfo);
1289
1290
namespace YM2413Burczynski {
1291
1292
// version 1: initial version
1293
// version 2: - removed kcodeScaled
1294
//            - calculated more members from other state
1295
//              (TLL, freq, eg_sel_*, eg_sh_*)
1296
template<typename Archive>
1297
void Slot::serialize(Archive& a, unsigned /*version*/)
1298
{
1299
	// TODO some of the serialized members here could be calculated from
1300
	//      other members
1301
	uint8_t waveform = (waveTable.data() == sinTab[0].data()) ? 0 : 1;
1302
	a.serialize("waveform", waveform);
1303
	if constexpr (Archive::IS_LOADER) {
1304
		setWaveform(waveform);
1305
	}
1306
1307
	a.serialize("phase",      phase,
1308
	            "TL",         TL,
1309
	            "volume",     egOut,
1310
	            "sl",         sl,
1311
	            "state",      state,
1312
	            "op1_out",    op1_out,
1313
	            "eg_sustain", eg_sustain,
1314
	            "fb_shift",   fb_shift,
1315
	            "key",        key,
1316
	            "ar",         ar,
1317
	            "dr",         dr,
1318
	            "rr",         rr,
1319
	            "KSR",        KSR,
1320
	            "ksl",        ksl,
1321
	            "mul",        mul,
1322
	            "AMmask",     AMmask,
1323
	            "vib",        vib);
1324
1325
	// These are calculated by updateTotalLevel()
1326
	//   TLL
1327
	// These are calculated by updateGenerators()
1328
	//   freq, eg_sh_ar, eg_sel_ar, eg_sh_dr, eg_sel_dr, eg_sh_rr, eg_sel_rr
1329
	//   eg_sh_rs, eg_sel_rs, eg_sh_dp, eg_sel_dp
1330
}
1331
1332
// version 1: original version
1333
// version 2: removed kcode
1334
// version 3: removed instvol_r
1335
template<typename Archive>
1336
void Channel::serialize(Archive& a, unsigned /*version*/)
1337
{
1338
	// mod/car were originally an array, keep serializing as such for bwc
1339
	std::array<Slot, 2> slots = {mod, car};
1340
	a.serialize("slots", slots);
1341
	if constexpr (Archive::IS_LOADER) {
1342
		mod = slots[0];
1343
		car = slots[1];
1344
	}
1345
1346
	a.serialize("block_fnum", block_fnum,
1347
	            "fc",         fc,
1348
	            "ksl_base",   ksl_base,
1349
	            "sus",        sus);
1350
1351
	if constexpr (Archive::IS_LOADER) {
1352
		mod.updateFrequency(*this);
1353
		car.updateFrequency(*this);
1354
	}
1355
}
1356
1357
// version 1: initial version
1358
// version 2: 'registers' are moved here (no longer serialized in base class)
1359
// version 3: removed 'rhythm' variable
1360
// version 4: added 'registerLatch'
1361
template<typename Archive>
1362
void YM2413::serialize(Archive& a, unsigned version)
1363
{
1364
	if (a.versionBelow(version, 2)) a.beginTag("YM2413Core");
1365
	a.serialize("registers", reg);
1366
	if (a.versionBelow(version, 2)) a.endTag("YM2413Core");
1367
1368
	// only serialize user instrument
1369
	a.serialize_blob("user_instrument", inst_tab[0]);
1370
	a.serialize("channels",   channels,
1371
	            "eg_cnt",     eg_cnt,
1372
	            "noise_rng",  noise_rng,
1373
	            "lfo_am_cnt", lfo_am_cnt,
1374
	            "lfo_pm_cnt", lfo_pm_cnt);
1375
	if (a.versionAtLeast(version, 4)) {
1376
		a.serialize("registerLatch", registerLatch);
1377
	} else {
1378
		// could be restored from MSXMusicBase, worth the effort?
1379
	}
1380
	// don't serialize idleSamples, it's only an optimization
1381
}
1382
1383
} // namespace YM2413Burczynski
1384
1385
using YM2413Burczynski::YM2413;
1386
INSTANTIATE_SERIALIZE_METHODS(YM2413);
1387
REGISTER_POLYMORPHIC_INITIALIZER(YM2413Core, YM2413, "YM2413-Jarek-Burczynski");
1388
1389
} // namespace openmsx