view snes_spc/SPC_DSP.cpp @ 6:a012d31df380

Made convert.pl work in parallel. Restored files in less than 2 minutes!
author Robert McIntyre <rlm@mit.edu>
date Fri, 21 Oct 2011 07:23:22 -0700
parents e38dacceb958
children
line wrap: on
line source
1 // snes_spc 0.9.0. http://www.slack.net/~ant/
3 #include "SPC_DSP.h"
5 #include "blargg_endian.h"
6 #include <string.h>
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 */
19 #include "blargg_source.h"
21 #ifdef BLARGG_ENABLE_OPTIMIZER
22 #include BLARGG_ENABLE_OPTIMIZER
23 #endif
25 #if INT_MAX < 0x7FFFFFFF
26 #error "Requires that int type have at least 32 bits"
27 #endif
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 )
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 };
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 }
54 // Access global DSP register
55 #define REG(n) m.regs [r_##n]
57 // Access voice DSP register
58 #define VREG(r,n) r [v_##n]
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 }\
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 }
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.
91 // Gaussian interpolation
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 };
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
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;
144 CLAMP16( out );
145 out &= ~1;
146 return out;
147 }
150 //// Counters
152 int const simple_counter_range = 2048 * 5 * 3; // 30720
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 };
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 };
187 inline void SPC_DSP::init_counter()
188 {
189 m.counter = 0;
190 }
192 inline void SPC_DSP::run_counters()
193 {
194 if ( --m.counter < 0 )
195 m.counter = simple_counter_range - 1;
196 }
198 inline unsigned SPC_DSP::read_counter( int rate )
199 {
200 return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate];
201 }
204 //// Envelope
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 }
266 // Sustain level
267 if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
268 v->env_mode = env_sustain;
270 v->hidden_env = env;
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 }
280 if ( !read_counter( rate ) )
281 v->env = env; // nothing else is controlled by the counter
282 }
283 }
286 //// BRR Decoding
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];
293 int const header = m.t_brr_header;
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;
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;
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)
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 }
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 }
346 //// Misc
348 #define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n()
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 }
373 run_counters();
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 }
384 //// Voices
386 #define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v )
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 );
401 m.t_adsr0 = VREG(v->regs,adsr0);
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;
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 }
434 // Envelope is never run during KON
435 v->env = 0;
436 v->hidden_env = 0;
438 // Disable BRR decoding until last three samples
439 v->interp_pos = 0;
440 if ( --v->kon_delay & 3 )
441 v->interp_pos = 0x4000;
443 // Pitch is never added during KON
444 m.t_pitch = 0;
445 }
447 // Gaussian interpolation
448 {
449 int output = interpolate( v );
451 // Noise
452 if ( m.t_non & v->vbit )
453 output = (int16_t) (m.noise * 2);
455 // Apply envelope
456 m.t_output = (output * v->env) >> 11 & ~1;
457 v->t_envx_out = (uint8_t) (v->env >> 4);
458 }
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 }
467 if ( m.every_other_sample )
468 {
469 // KOFF
470 if ( m.t_koff & v->vbit )
471 v->env_mode = env_release;
473 // KON
474 if ( m.kon & v->vbit )
475 {
476 v->kon_delay = 5;
477 v->env_mode = env_attack;
478 }
479 }
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;
490 // Add to output total
491 m.t_main_out [ch] += amp;
492 CLAMP16( m.t_main_out [ch] );
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 );
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 }
523 // Apply pitch
524 v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
526 // Keep from getting too far ahead (when using pitch modulation)
527 if ( v->interp_pos > 0x7FFF )
528 v->interp_pos = 0x7FFF;
530 // Output left
531 voice_output( v, 0 );
532 }
533 inline VOICE_CLOCK( V5 )
534 {
535 // Output right
536 voice_output( v, 1 );
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;
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;
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 }
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 }
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); }
584 //// Echo
586 // Current echo buffer pointer for left/right channel
587 #define ECHO_PTR( ch ) (&m.ram [m.t_echo_ptr + ch * 2])
589 // Sample in echo history buffer, where 0 is the oldest
590 #define ECHO_FIR( i ) (m.echo_hist_pos [i])
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)
595 #define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n()
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 }
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;
610 m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF;
611 echo_read( 0 );
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 );
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 );
625 m.t_echo_in [0] += l;
626 m.t_echo_in [1] += r;
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 );
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 );
643 l = (int16_t) l;
644 r = (int16_t) r;
646 l += (int16_t) CALC_FIR( 7, 0 );
647 r += (int16_t) CALC_FIR( 7, 1 );
649 CLAMP16( l );
650 CLAMP16( r );
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 );
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);
672 CLAMP16( l );
673 CLAMP16( r );
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;
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 }
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);
717 if ( !m.echo_offset )
718 m.echo_length = (REG(edl) & 0x0F) * 0x800;
720 m.echo_offset += 4;
721 if ( m.echo_offset >= m.echo_length )
722 m.echo_offset = 0;
724 // Write left echo
725 echo_write( 0 );
727 m.t_echo_enabled = REG(flg);
728 }
729 ECHO_CLOCK( 30 )
730 {
731 // Write right echo
732 echo_write( 1 );
733 }
736 //// Timing
738 // Execute clock for a particular voice
739 #define V( clock, voice ) voice_##clock( &m.voices [voice] );
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:
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) */
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)\
784 #if !SPC_DSP_CUSTOM_RUN
786 void SPC_DSP::run( int clocks_remain )
787 {
788 require( clocks_remain > 0 );
790 int const phase = m.phase;
791 m.phase = (phase + clocks_remain) & 31;
792 switch ( phase )
793 {
794 loop:
796 #define PHASE( n ) if ( n && !--clocks_remain ) break; case n:
797 GEN_DSP_TIMING
798 #undef PHASE
800 if ( --clocks_remain )
801 goto loop;
802 }
803 }
805 #endif
808 //// Setup
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();
818 #ifndef NDEBUG
819 // be sure this sign-extends
820 assert( (int16_t) 0x8000 == -0x8000 );
822 // be sure right shift preserves sign
823 assert( (-1 >> 1) == -1 );
825 // check clamp macro
826 int i;
827 i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
828 i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
830 blargg_verify_byte_order();
831 #endif
832 }
834 void SPC_DSP::soft_reset_common()
835 {
836 require( m.ram ); // init() must have been called already
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;
844 init_counter();
845 }
847 void SPC_DSP::soft_reset()
848 {
849 REG(flg) = 0xE0;
850 soft_reset_common();
851 }
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 );
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);
870 soft_reset_common();
871 }
873 void SPC_DSP::reset() { load( initial_regs ); }
876 //// State save/load
878 #if !SPC_NO_COPY_STATE_FUNCS
880 void SPC_State_Copier::copy( void* state, size_t size )
881 {
882 func( buf, state, size );
883 }
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 }
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 }
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 }
919 void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
920 {
921 SPC_State_Copier copier( io, copy );
923 // DSP registers
924 copier.copy( m.regs, register_count );
926 // Internal state
928 // Voices
929 int i;
930 for ( i = 0; i < voice_count; i++ )
931 {
932 voice_t* v = &m.voices [i];
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 }
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 );
957 copier.extra();
958 }
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] );
974 // Misc
975 SPC_COPY( uint8_t, m.every_other_sample );
976 SPC_COPY( uint8_t, m.kon );
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 );
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 );
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 );
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 );
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] );
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 );
1016 copier.extra();
1018 #endif