Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/alt/dsp/SPC_DSP.cpp
2 views
1
// snes_spc 0.9.0. http://www.slack.net/~ant/
2
3
#include "SPC_DSP.h"
4
5
#include "blargg_endian.h"
6
#include <string.h>
7
8
/* Copyright (C) 2007 Shay Green. This module is free software; you
9
can redistribute it and/or modify it under the terms of the GNU Lesser
10
General Public License as published by the Free Software Foundation; either
11
version 2.1 of the License, or (at your option) any later version. This
12
module is distributed in the hope that it will be useful, but WITHOUT ANY
13
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
15
details. You should have received a copy of the GNU Lesser General Public
16
License along with this module; if not, write to the Free Software Foundation,
17
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
18
19
#include "blargg_source.h"
20
21
#ifdef BLARGG_ENABLE_OPTIMIZER
22
#include BLARGG_ENABLE_OPTIMIZER
23
#endif
24
25
#if INT_MAX < 0x7FFFFFFF
26
#error "Requires that int type have at least 32 bits"
27
#endif
28
29
// TODO: add to blargg_endian.h
30
#define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr ))
31
#define GET_LE16A( addr ) GET_LE16( addr )
32
#define SET_LE16A( addr, data ) SET_LE16( addr, data )
33
34
static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
35
{
36
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
37
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
38
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
39
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
40
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
41
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
42
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,
43
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
44
45
// 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
46
// 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
47
// 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
48
// 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
49
// 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
50
// 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF,
51
// 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
52
// 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
53
};
54
55
// if ( io < -32768 ) io = -32768;
56
// if ( io > 32767 ) io = 32767;
57
#define CLAMP16( io )\
58
{\
59
if ( (int16_t) io != io )\
60
io = (io >> 31) ^ 0x7FFF;\
61
}
62
63
// Access global DSP register
64
#define REG(n) m.regs [r_##n]
65
66
// Access voice DSP register
67
#define VREG(r,n) r [v_##n]
68
69
#define WRITE_SAMPLES( l, r, out ) \
70
{\
71
out [0] = l;\
72
out [1] = r;\
73
out += 2;\
74
if ( out >= m.out_end )\
75
{\
76
check( out == m.out_end );\
77
check( m.out_end != &m.extra [extra_size] || \
78
(m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
79
out = m.extra;\
80
m.out_end = &m.extra [extra_size];\
81
}\
82
}\
83
84
void SPC_DSP::set_output( sample_t* out, int size )
85
{
86
require( (size & 1) == 0 ); // must be even
87
if ( !out )
88
{
89
out = m.extra;
90
size = extra_size;
91
}
92
m.out_begin = out;
93
m.out = out;
94
m.out_end = out + size;
95
}
96
97
// Volume registers and efb are signed! Easy to forget int8_t cast.
98
// Prefixes are to avoid accidental use of locals with same names.
99
100
// Gaussian interpolation
101
102
static short const gauss [512] =
103
{
104
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
106
2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5,
107
6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
108
11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 16, 16, 17, 17,
109
18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26, 27, 27,
110
28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 36, 36, 37, 38, 39, 40,
111
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
112
58, 59, 60, 61, 62, 64, 65, 66, 67, 69, 70, 71, 73, 74, 76, 77,
113
78, 80, 81, 83, 84, 86, 87, 89, 90, 92, 94, 95, 97, 99, 100, 102,
114
104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
115
134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
116
171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
117
212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
118
260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
119
314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
120
374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
121
439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
122
508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
123
582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
124
659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
125
737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
126
816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
127
894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
128
969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
129
1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
130
1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
131
1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
132
1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
133
1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
134
1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
135
1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
136
};
137
138
inline int SPC_DSP::interpolate( voice_t const* v )
139
{
140
// Make pointers into gaussian based on fractional position between samples
141
int offset = v->interp_pos >> 4 & 0xFF;
142
short const* fwd = gauss + 255 - offset;
143
short const* rev = gauss + offset; // mirror left half of gaussian
144
145
int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
146
int out;
147
out = (fwd [ 0] * in [0]) >> 11;
148
out += (fwd [256] * in [1]) >> 11;
149
out += (rev [256] * in [2]) >> 11;
150
out = (int16_t) out;
151
out += (rev [ 0] * in [3]) >> 11;
152
153
CLAMP16( out );
154
out &= ~1;
155
return out;
156
}
157
158
159
//// Counters
160
161
int const simple_counter_range = 2048 * 5 * 3; // 30720
162
163
static unsigned const counter_rates [32] =
164
{
165
simple_counter_range + 1, // never fires
166
2048, 1536,
167
1280, 1024, 768,
168
640, 512, 384,
169
320, 256, 192,
170
160, 128, 96,
171
80, 64, 48,
172
40, 32, 24,
173
20, 16, 12,
174
10, 8, 6,
175
5, 4, 3,
176
2,
177
1
178
};
179
180
static unsigned const counter_offsets [32] =
181
{
182
1, 0, 1040,
183
536, 0, 1040,
184
536, 0, 1040,
185
536, 0, 1040,
186
536, 0, 1040,
187
536, 0, 1040,
188
536, 0, 1040,
189
536, 0, 1040,
190
536, 0, 1040,
191
536, 0, 1040,
192
0,
193
0
194
};
195
196
inline void SPC_DSP::init_counter()
197
{
198
m.counter = 0;
199
}
200
201
inline void SPC_DSP::run_counters()
202
{
203
if ( --m.counter < 0 )
204
m.counter = simple_counter_range - 1;
205
}
206
207
inline unsigned SPC_DSP::read_counter( int rate )
208
{
209
return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate];
210
}
211
212
213
//// Envelope
214
215
inline void SPC_DSP::run_envelope( voice_t* const v )
216
{
217
int env = v->env;
218
if ( v->env_mode == env_release ) // 60%
219
{
220
if ( (env -= 0x8) < 0 )
221
env = 0;
222
v->env = env;
223
}
224
else
225
{
226
int rate;
227
int env_data = VREG(v->regs,adsr1);
228
if ( m.t_adsr0 & 0x80 ) // 99% ADSR
229
{
230
if ( v->env_mode >= env_decay ) // 99%
231
{
232
env--;
233
env -= env >> 8;
234
rate = env_data & 0x1F;
235
if ( v->env_mode == env_decay ) // 1%
236
rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10;
237
}
238
else // env_attack
239
{
240
rate = (m.t_adsr0 & 0x0F) * 2 + 1;
241
env += rate < 31 ? 0x20 : 0x400;
242
}
243
}
244
else // GAIN
245
{
246
int mode;
247
env_data = VREG(v->regs,gain);
248
mode = env_data >> 5;
249
if ( mode < 4 ) // direct
250
{
251
env = env_data * 0x10;
252
rate = 31;
253
}
254
else
255
{
256
rate = env_data & 0x1F;
257
if ( mode == 4 ) // 4: linear decrease
258
{
259
env -= 0x20;
260
}
261
else if ( mode < 6 ) // 5: exponential decrease
262
{
263
env--;
264
env -= env >> 8;
265
}
266
else // 6,7: linear increase
267
{
268
env += 0x20;
269
if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
270
env += 0x8 - 0x20; // 7: two-slope linear increase
271
}
272
}
273
}
274
275
// Sustain level
276
if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
277
v->env_mode = env_sustain;
278
279
v->hidden_env = env;
280
281
// unsigned cast because linear decrease going negative also triggers this
282
if ( (unsigned) env > 0x7FF )
283
{
284
env = (env < 0 ? 0 : 0x7FF);
285
if ( v->env_mode == env_attack )
286
v->env_mode = env_decay;
287
}
288
289
if ( !read_counter( rate ) )
290
v->env = env; // nothing else is controlled by the counter
291
}
292
}
293
294
295
//// BRR Decoding
296
297
inline void SPC_DSP::decode_brr( voice_t* v )
298
{
299
// Arrange the four input nybbles in 0xABCD order for easy decoding
300
int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
301
302
int const header = m.t_brr_header;
303
304
// Write to next four samples in circular buffer
305
int* pos = &v->buf [v->buf_pos];
306
int* end;
307
if ( (v->buf_pos += 4) >= brr_buf_size )
308
v->buf_pos = 0;
309
310
// Decode four samples
311
for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
312
{
313
// Extract nybble and sign-extend
314
int s = (int16_t) nybbles >> 12;
315
316
// Shift sample based on header
317
int const shift = header >> 4;
318
s = (s << shift) >> 1;
319
if ( shift >= 0xD ) // handle invalid range
320
s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0)
321
322
// Apply IIR filter (8 is the most commonly used)
323
int const filter = header & 0x0C;
324
int const p1 = pos [brr_buf_size - 1];
325
int const p2 = pos [brr_buf_size - 2] >> 1;
326
if ( filter >= 8 )
327
{
328
s += p1;
329
s -= p2;
330
if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
331
{
332
s += p2 >> 4;
333
s += (p1 * -3) >> 6;
334
}
335
else // s += p1 * 0.8984375 - p2 * 0.40625
336
{
337
s += (p1 * -13) >> 7;
338
s += (p2 * 3) >> 4;
339
}
340
}
341
else if ( filter ) // s += p1 * 0.46875
342
{
343
s += p1 >> 1;
344
s += (-p1) >> 5;
345
}
346
347
// Adjust and write sample
348
CLAMP16( s );
349
s = (int16_t) (s * 2);
350
pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
351
}
352
}
353
354
355
//// Misc
356
357
#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n()
358
359
MISC_CLOCK( 27 )
360
{
361
m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON
362
}
363
MISC_CLOCK( 28 )
364
{
365
m.t_non = REG(non);
366
m.t_eon = REG(eon);
367
m.t_dir = REG(dir);
368
}
369
MISC_CLOCK( 29 )
370
{
371
if ( (m.every_other_sample ^= 1) != 0 )
372
m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read
373
}
374
MISC_CLOCK( 30 )
375
{
376
if ( m.every_other_sample )
377
{
378
m.kon = m.new_kon;
379
m.t_koff = REG(koff) | m.mute_mask;
380
}
381
382
run_counters();
383
384
// Noise
385
if ( !read_counter( REG(flg) & 0x1F ) )
386
{
387
int feedback = (m.noise << 13) ^ (m.noise << 14);
388
m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
389
}
390
}
391
392
393
//// Voices
394
395
#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v )
396
397
inline VOICE_CLOCK( V1 )
398
{
399
m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4;
400
m.t_srcn = VREG(v->regs,srcn);
401
}
402
inline VOICE_CLOCK( V2 )
403
{
404
// Read sample pointer (ignored if not needed)
405
uint8_t const* entry = &m.ram [m.t_dir_addr];
406
if ( !v->kon_delay )
407
entry += 2;
408
m.t_brr_next_addr = GET_LE16A( entry );
409
410
m.t_adsr0 = VREG(v->regs,adsr0);
411
412
// Read pitch, spread over two clocks
413
m.t_pitch = VREG(v->regs,pitchl);
414
}
415
inline VOICE_CLOCK( V3a )
416
{
417
m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8;
418
}
419
inline VOICE_CLOCK( V3b )
420
{
421
// Read BRR header and byte
422
m.t_brr_byte = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF];
423
m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking
424
}
425
VOICE_CLOCK( V3c )
426
{
427
// Pitch modulation using previous voice's output
428
if ( m.t_pmon & v->vbit )
429
m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10;
430
431
if ( v->kon_delay )
432
{
433
// Get ready to start BRR decoding on next sample
434
if ( v->kon_delay == 5 )
435
{
436
v->brr_addr = m.t_brr_next_addr;
437
v->brr_offset = 1;
438
v->buf_pos = 0;
439
m.t_brr_header = 0; // header is ignored on this sample
440
m.kon_check = true;
441
}
442
443
// Envelope is never run during KON
444
v->env = 0;
445
v->hidden_env = 0;
446
447
// Disable BRR decoding until last three samples
448
v->interp_pos = 0;
449
if ( --v->kon_delay & 3 )
450
v->interp_pos = 0x4000;
451
452
// Pitch is never added during KON
453
m.t_pitch = 0;
454
}
455
456
// Gaussian interpolation
457
{
458
int output = interpolate( v );
459
460
// Noise
461
if ( m.t_non & v->vbit )
462
output = (int16_t) (m.noise * 2);
463
464
// Apply envelope
465
m.t_output = (output * v->env) >> 11 & ~1;
466
v->t_envx_out = (uint8_t) (v->env >> 4);
467
}
468
469
// Immediate silence due to end of sample or soft reset
470
if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 )
471
{
472
v->env_mode = env_release;
473
v->env = 0;
474
}
475
476
if ( m.every_other_sample )
477
{
478
// KOFF
479
if ( m.t_koff & v->vbit )
480
v->env_mode = env_release;
481
482
// KON
483
if ( m.kon & v->vbit )
484
{
485
v->kon_delay = 5;
486
v->env_mode = env_attack;
487
}
488
}
489
490
// Run envelope for next sample
491
if ( !v->kon_delay )
492
run_envelope( v );
493
}
494
inline void SPC_DSP::voice_output( voice_t const* v, int ch )
495
{
496
// Apply left/right volume
497
int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7;
498
499
// Add to output total
500
m.t_main_out [ch] += amp;
501
CLAMP16( m.t_main_out [ch] );
502
503
// Optionally add to echo total
504
if ( m.t_eon & v->vbit )
505
{
506
m.t_echo_out [ch] += amp;
507
CLAMP16( m.t_echo_out [ch] );
508
}
509
}
510
VOICE_CLOCK( V4 )
511
{
512
// Decode BRR
513
m.t_looped = 0;
514
if ( v->interp_pos >= 0x4000 )
515
{
516
decode_brr( v );
517
518
if ( (v->brr_offset += 2) >= brr_block_size )
519
{
520
// Start decoding next BRR block
521
assert( v->brr_offset == brr_block_size );
522
v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
523
if ( m.t_brr_header & 1 )
524
{
525
v->brr_addr = m.t_brr_next_addr;
526
m.t_looped = v->vbit;
527
}
528
v->brr_offset = 1;
529
530
//assume we're going to access the whole block
531
cdlInfo.currFlags = eCDLog_Flags_BRR;
532
for(int i=0;i<9;i++)
533
cdlInfo.set(eCDLog_AddrType_APURAM, (v->brr_addr+i) & 0xFFFF);
534
}
535
}
536
537
// Apply pitch
538
v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
539
540
// Keep from getting too far ahead (when using pitch modulation)
541
if ( v->interp_pos > 0x7FFF )
542
v->interp_pos = 0x7FFF;
543
544
// Output left
545
voice_output( v, 0 );
546
}
547
inline VOICE_CLOCK( V5 )
548
{
549
// Output right
550
voice_output( v, 1 );
551
552
// ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier
553
int endx_buf = REG(endx) | m.t_looped;
554
555
// Clear bit in ENDX if KON just began
556
if ( v->kon_delay == 5 )
557
endx_buf &= ~v->vbit;
558
m.endx_buf = (uint8_t) endx_buf;
559
}
560
inline VOICE_CLOCK( V6 )
561
{
562
(void) v; // avoid compiler warning about unused v
563
m.outx_buf = (uint8_t) (m.t_output >> 8);
564
}
565
inline VOICE_CLOCK( V7 )
566
{
567
// Update ENDX
568
REG(endx) = m.endx_buf;
569
570
m.envx_buf = v->t_envx_out;
571
}
572
inline VOICE_CLOCK( V8 )
573
{
574
// Update OUTX
575
VREG(v->regs,outx) = m.outx_buf;
576
}
577
inline VOICE_CLOCK( V9 )
578
{
579
// Update ENVX
580
VREG(v->regs,envx) = m.envx_buf;
581
}
582
583
// Most voices do all these in one clock, so make a handy composite
584
inline VOICE_CLOCK( V3 )
585
{
586
voice_V3a( v );
587
voice_V3b( v );
588
voice_V3c( v );
589
}
590
591
// Common combinations of voice steps on different voices. This greatly reduces
592
// code size and allows everything to be inlined in these functions.
593
VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); }
594
VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); }
595
VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); }
596
597
598
//// Echo
599
600
// Current echo buffer pointer for left/right channel
601
#define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2])
602
603
// Sample in echo history buffer, where 0 is the oldest
604
#define ECHO_FIR( i ) (m.echo_hist_pos [i])
605
606
// Calculate FIR point for left/right channel
607
#define CALC_FIR( i, ch ) ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6)
608
609
#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n()
610
611
inline void SPC_DSP::echo_read( int ch )
612
{
613
int s = GET_LE16SA( ECHO_PTR( ch ) );
614
// second copy simplifies wrap-around handling
615
ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1;
616
}
617
618
ECHO_CLOCK( 22 )
619
{
620
// History
621
if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] )
622
m.echo_hist_pos = m.echo_hist;
623
624
m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF;
625
echo_read( 0 );
626
627
// FIR (using l and r temporaries below helps compiler optimize)
628
int l = CALC_FIR( 0, 0 );
629
int r = CALC_FIR( 0, 1 );
630
631
m.t_echo_in [0] = l;
632
m.t_echo_in [1] = r;
633
}
634
ECHO_CLOCK( 23 )
635
{
636
int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 );
637
int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 );
638
639
m.t_echo_in [0] += l;
640
m.t_echo_in [1] += r;
641
642
echo_read( 1 );
643
}
644
ECHO_CLOCK( 24 )
645
{
646
int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 );
647
int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 );
648
649
m.t_echo_in [0] += l;
650
m.t_echo_in [1] += r;
651
}
652
ECHO_CLOCK( 25 )
653
{
654
int l = m.t_echo_in [0] + CALC_FIR( 6, 0 );
655
int r = m.t_echo_in [1] + CALC_FIR( 6, 1 );
656
657
l = (int16_t) l;
658
r = (int16_t) r;
659
660
l += (int16_t) CALC_FIR( 7, 0 );
661
r += (int16_t) CALC_FIR( 7, 1 );
662
663
CLAMP16( l );
664
CLAMP16( r );
665
666
m.t_echo_in [0] = l & ~1;
667
m.t_echo_in [1] = r & ~1;
668
}
669
inline int SPC_DSP::echo_output( int ch )
670
{
671
int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) +
672
(int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7);
673
CLAMP16( out );
674
return out;
675
}
676
ECHO_CLOCK( 26 )
677
{
678
// Left output volumes
679
// (save sample for next clock so we can output both together)
680
m.t_main_out [0] = echo_output( 0 );
681
682
// Echo feedback
683
int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7);
684
int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7);
685
686
CLAMP16( l );
687
CLAMP16( r );
688
689
m.t_echo_out [0] = l & ~1;
690
m.t_echo_out [1] = r & ~1;
691
}
692
ECHO_CLOCK( 27 )
693
{
694
// Output
695
int l = m.t_main_out [0];
696
int r = echo_output( 1 );
697
m.t_main_out [0] = 0;
698
m.t_main_out [1] = 0;
699
700
// TODO: global muting isn't this simple (turns DAC on and off
701
// or something, causing small ~37-sample pulse when first muted)
702
if ( REG(flg) & 0x40 )
703
{
704
l = 0;
705
r = 0;
706
}
707
708
// Output sample to DAC
709
#ifdef SPC_DSP_OUT_HOOK
710
SPC_DSP_OUT_HOOK( l, r );
711
#else
712
sample_t* out = m.out;
713
WRITE_SAMPLES( l, r, out );
714
m.out = out;
715
#endif
716
}
717
ECHO_CLOCK( 28 )
718
{
719
m.t_echo_enabled = REG(flg);
720
}
721
inline void SPC_DSP::echo_write( int ch )
722
{
723
if ( !(m.t_echo_enabled & 0x20) )
724
SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] );
725
m.t_echo_out [ch] = 0;
726
}
727
ECHO_CLOCK( 29 )
728
{
729
m.t_esa = REG(esa);
730
731
if ( !m.echo_offset )
732
m.echo_length = (REG(edl) & 0x0F) * 0x800;
733
734
m.echo_offset += 4;
735
if ( m.echo_offset >= m.echo_length )
736
m.echo_offset = 0;
737
738
// Write left echo
739
echo_write( 0 );
740
741
m.t_echo_enabled = REG(flg);
742
}
743
ECHO_CLOCK( 30 )
744
{
745
// Write right echo
746
echo_write( 1 );
747
}
748
749
750
//// Timing
751
752
// Execute clock for a particular voice
753
#define V( clock, voice ) voice_##clock( &m.voices [voice] );
754
755
/* The most common sequence of clocks uses composite operations
756
for efficiency. For example, the following are equivalent to the
757
individual steps on the right:
758
759
V(V7_V4_V1,2) -> V(V7,2) V(V4,3) V(V1,5)
760
V(V8_V5_V2,2) -> V(V8,2) V(V5,3) V(V2,4)
761
V(V9_V6_V3,2) -> V(V9,2) V(V6,3) V(V3,4) */
762
763
// Voice 0 1 2 3 4 5 6 7
764
#define GEN_DSP_TIMING \
765
PHASE( 0) V(V5,0)V(V2,1)\
766
PHASE( 1) V(V6,0)V(V3,1)\
767
PHASE( 2) V(V7_V4_V1,0)\
768
PHASE( 3) V(V8_V5_V2,0)\
769
PHASE( 4) V(V9_V6_V3,0)\
770
PHASE( 5) V(V7_V4_V1,1)\
771
PHASE( 6) V(V8_V5_V2,1)\
772
PHASE( 7) V(V9_V6_V3,1)\
773
PHASE( 8) V(V7_V4_V1,2)\
774
PHASE( 9) V(V8_V5_V2,2)\
775
PHASE(10) V(V9_V6_V3,2)\
776
PHASE(11) V(V7_V4_V1,3)\
777
PHASE(12) V(V8_V5_V2,3)\
778
PHASE(13) V(V9_V6_V3,3)\
779
PHASE(14) V(V7_V4_V1,4)\
780
PHASE(15) V(V8_V5_V2,4)\
781
PHASE(16) V(V9_V6_V3,4)\
782
PHASE(17) V(V1,0) V(V7,5)V(V4,6)\
783
PHASE(18) V(V8_V5_V2,5)\
784
PHASE(19) V(V9_V6_V3,5)\
785
PHASE(20) V(V1,1) V(V7,6)V(V4,7)\
786
PHASE(21) V(V8,6)V(V5,7) V(V2,0) /* t_brr_next_addr order dependency */\
787
PHASE(22) V(V3a,0) V(V9,6)V(V6,7) echo_22();\
788
PHASE(23) V(V7,7) echo_23();\
789
PHASE(24) V(V8,7) echo_24();\
790
PHASE(25) V(V3b,0) V(V9,7) echo_25();\
791
PHASE(26) echo_26();\
792
PHASE(27) misc_27(); echo_27();\
793
PHASE(28) misc_28(); echo_28();\
794
PHASE(29) misc_29(); echo_29();\
795
PHASE(30) misc_30();V(V3c,0) echo_30();\
796
PHASE(31) V(V4,0) V(V1,2)\
797
798
#if !SPC_DSP_CUSTOM_RUN
799
800
void SPC_DSP::run( int clocks_remain )
801
{
802
require( clocks_remain > 0 );
803
804
int const phase = m.phase;
805
m.phase = (phase + clocks_remain) & 31;
806
switch ( phase )
807
{
808
loop:
809
810
#define PHASE( n ) if ( n && !--clocks_remain ) break; case n:
811
GEN_DSP_TIMING
812
#undef PHASE
813
814
if ( --clocks_remain )
815
goto loop;
816
}
817
}
818
819
#endif
820
821
822
//// Setup
823
824
void SPC_DSP::init( void* ram_64k )
825
{
826
m.ram = (uint8_t*) ram_64k;
827
mute_voices( 0 );
828
disable_surround( false );
829
set_output( 0, 0 );
830
reset();
831
832
#ifndef NDEBUG
833
// be sure this sign-extends
834
assert( (int16_t) 0x8000 == -0x8000 );
835
836
// be sure right shift preserves sign
837
assert( (-1 >> 1) == -1 );
838
839
// check clamp macro
840
int i;
841
i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
842
i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
843
844
blargg_verify_byte_order();
845
#endif
846
}
847
848
void SPC_DSP::soft_reset_common()
849
{
850
require( m.ram ); // init() must have been called already
851
852
m.noise = 0x4000;
853
m.echo_hist_pos = m.echo_hist;
854
m.every_other_sample = 1;
855
m.echo_offset = 0;
856
m.phase = 0;
857
858
init_counter();
859
}
860
861
void SPC_DSP::soft_reset()
862
{
863
REG(flg) = 0xE0;
864
soft_reset_common();
865
}
866
867
void SPC_DSP::load( uint8_t const regs [register_count] )
868
{
869
memcpy( m.regs, regs, sizeof m.regs );
870
memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
871
872
// Internal state
873
for ( int i = voice_count; --i >= 0; )
874
{
875
voice_t* v = &m.voices [i];
876
v->brr_offset = 1;
877
v->vbit = 1 << i;
878
v->regs = &m.regs [i * 0x10];
879
}
880
m.new_kon = REG(kon);
881
m.t_dir = REG(dir);
882
m.t_esa = REG(esa);
883
884
soft_reset_common();
885
}
886
887
void SPC_DSP::reset() { load( initial_regs ); }
888
889
890
//// State save/load
891
892
#if !SPC_NO_COPY_STATE_FUNCS
893
894
void SPC_State_Copier::copy( void* state, size_t size )
895
{
896
func( buf, state, size );
897
}
898
899
int SPC_State_Copier::copy_int( int state, int size )
900
{
901
BOOST::uint8_t s [2];
902
SET_LE16( s, state );
903
func( buf, &s, size );
904
return GET_LE16( s );
905
}
906
907
void SPC_State_Copier::skip( int count )
908
{
909
if ( count > 0 )
910
{
911
char temp [64];
912
memset( temp, 0, sizeof temp );
913
do
914
{
915
int n = sizeof temp;
916
if ( n > count )
917
n = count;
918
count -= n;
919
func( buf, temp, n );
920
}
921
while ( count );
922
}
923
}
924
925
void SPC_State_Copier::extra()
926
{
927
int n = 0;
928
SPC_State_Copier& copier = *this;
929
SPC_COPY( uint8_t, n );
930
skip( n );
931
}
932
933
void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
934
{
935
SPC_State_Copier copier( io, copy );
936
937
// DSP registers
938
copier.copy( m.regs, register_count );
939
940
// Internal state
941
942
// Voices
943
int i;
944
for ( i = 0; i < voice_count; i++ )
945
{
946
voice_t* v = &m.voices [i];
947
948
// BRR buffer
949
int i;
950
for ( i = 0; i < brr_buf_size; i++ )
951
{
952
int s = v->buf [i];
953
SPC_COPY( int16_t, s );
954
v->buf [i] = v->buf [i + brr_buf_size] = s;
955
}
956
957
SPC_COPY( uint16_t, v->interp_pos );
958
SPC_COPY( uint16_t, v->brr_addr );
959
SPC_COPY( uint16_t, v->env );
960
SPC_COPY( int16_t, v->hidden_env );
961
SPC_COPY( uint8_t, v->buf_pos );
962
SPC_COPY( uint8_t, v->brr_offset );
963
SPC_COPY( uint8_t, v->kon_delay );
964
{
965
int m = v->env_mode;
966
SPC_COPY( uint8_t, m );
967
v->env_mode = (enum env_mode_t) m;
968
}
969
SPC_COPY( uint8_t, v->t_envx_out );
970
971
copier.extra();
972
}
973
974
// Echo history
975
for ( i = 0; i < echo_hist_size; i++ )
976
{
977
int j;
978
for ( j = 0; j < 2; j++ )
979
{
980
int s = m.echo_hist_pos [i] [j];
981
SPC_COPY( int16_t, s );
982
m.echo_hist [i] [j] = s; // write back at offset 0
983
}
984
}
985
m.echo_hist_pos = m.echo_hist;
986
memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] );
987
988
// Misc
989
SPC_COPY( uint8_t, m.every_other_sample );
990
SPC_COPY( uint8_t, m.kon );
991
992
SPC_COPY( uint16_t, m.noise );
993
SPC_COPY( uint16_t, m.counter );
994
SPC_COPY( uint16_t, m.echo_offset );
995
SPC_COPY( uint16_t, m.echo_length );
996
SPC_COPY( uint8_t, m.phase );
997
998
SPC_COPY( uint8_t, m.new_kon );
999
SPC_COPY( uint8_t, m.endx_buf );
1000
SPC_COPY( uint8_t, m.envx_buf );
1001
SPC_COPY( uint8_t, m.outx_buf );
1002
1003
SPC_COPY( uint8_t, m.t_pmon );
1004
SPC_COPY( uint8_t, m.t_non );
1005
SPC_COPY( uint8_t, m.t_eon );
1006
SPC_COPY( uint8_t, m.t_dir );
1007
SPC_COPY( uint8_t, m.t_koff );
1008
1009
SPC_COPY( uint16_t, m.t_brr_next_addr );
1010
SPC_COPY( uint8_t, m.t_adsr0 );
1011
SPC_COPY( uint8_t, m.t_brr_header );
1012
SPC_COPY( uint8_t, m.t_brr_byte );
1013
SPC_COPY( uint8_t, m.t_srcn );
1014
SPC_COPY( uint8_t, m.t_esa );
1015
SPC_COPY( uint8_t, m.t_echo_enabled );
1016
1017
SPC_COPY( int16_t, m.t_main_out [0] );
1018
SPC_COPY( int16_t, m.t_main_out [1] );
1019
SPC_COPY( int16_t, m.t_echo_out [0] );
1020
SPC_COPY( int16_t, m.t_echo_out [1] );
1021
SPC_COPY( int16_t, m.t_echo_in [0] );
1022
SPC_COPY( int16_t, m.t_echo_in [1] );
1023
1024
SPC_COPY( uint16_t, m.t_dir_addr );
1025
SPC_COPY( uint16_t, m.t_pitch );
1026
SPC_COPY( int16_t, m.t_output );
1027
SPC_COPY( uint16_t, m.t_echo_ptr );
1028
SPC_COPY( uint8_t, m.t_looped );
1029
1030
copier.extra();
1031
}
1032
#endif
1033
1034