comparison snes_spc/SPC_DSP.cpp @ 0:e38dacceb958

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