comparison fast_dsp/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
30 // TODO: add to blargg_endian.h
31 #define GET_LE16SA( addr ) ((BOOST::int16_t) GET_LE16( addr ))
32 #define GET_LE16A( addr ) GET_LE16( addr )
33 #define SET_LE16A( addr, data ) SET_LE16( addr, data )
34
35 static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
36 {
37 0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
38 0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
39 0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
40 0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
41 0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
42 0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x9C,0x4E,0x7B,0xFF,
43 0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
44 0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
45 };
46
47 // if ( io < -32768 ) io = -32768;
48 // if ( io > 32767 ) io = 32767;
49 #define CLAMP16( io )\
50 {\
51 if ( (int16_t) io != io )\
52 io = (io >> 31) ^ 0x7FFF;\
53 }
54
55 // Access global DSP register
56 #define REG(n) m.regs [r_##n]
57
58 // Access voice DSP register
59 #define VREG(r,n) r [v_##n]
60
61 #define WRITE_SAMPLES( l, r, out ) \
62 {\
63 out [0] = l;\
64 out [1] = r;\
65 out += 2;\
66 if ( out >= m.out_end )\
67 {\
68 check( out == m.out_end );\
69 check( m.out_end != &m.extra [extra_size] || \
70 (m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
71 out = m.extra;\
72 m.out_end = &m.extra [extra_size];\
73 }\
74 }\
75
76 void SPC_DSP::set_output( sample_t* out, int size )
77 {
78 require( (size & 1) == 0 ); // must be even
79 if ( !out )
80 {
81 out = m.extra;
82 size = extra_size;
83 }
84 m.out_begin = out;
85 m.out = out;
86 m.out_end = out + size;
87 }
88
89 // Volume registers and efb are signed! Easy to forget int8_t cast.
90 // Prefixes are to avoid accidental use of locals with same names.
91
92 // Interleved gauss table (to improve cache coherency)
93 // interleved_gauss [i] = gauss [(i & 1) * 256 + 255 - (i >> 1 & 0xFF)]
94 static short const interleved_gauss [512] =
95 {
96 370,1305, 366,1305, 362,1304, 358,1304, 354,1304, 351,1304, 347,1304, 343,1303,
97 339,1303, 336,1303, 332,1302, 328,1302, 325,1301, 321,1300, 318,1300, 314,1299,
98 311,1298, 307,1297, 304,1297, 300,1296, 297,1295, 293,1294, 290,1293, 286,1292,
99 283,1291, 280,1290, 276,1288, 273,1287, 270,1286, 267,1284, 263,1283, 260,1282,
100 257,1280, 254,1279, 251,1277, 248,1275, 245,1274, 242,1272, 239,1270, 236,1269,
101 233,1267, 230,1265, 227,1263, 224,1261, 221,1259, 218,1257, 215,1255, 212,1253,
102 210,1251, 207,1248, 204,1246, 201,1244, 199,1241, 196,1239, 193,1237, 191,1234,
103 188,1232, 186,1229, 183,1227, 180,1224, 178,1221, 175,1219, 173,1216, 171,1213,
104 168,1210, 166,1207, 163,1205, 161,1202, 159,1199, 156,1196, 154,1193, 152,1190,
105 150,1186, 147,1183, 145,1180, 143,1177, 141,1174, 139,1170, 137,1167, 134,1164,
106 132,1160, 130,1157, 128,1153, 126,1150, 124,1146, 122,1143, 120,1139, 118,1136,
107 117,1132, 115,1128, 113,1125, 111,1121, 109,1117, 107,1113, 106,1109, 104,1106,
108 102,1102, 100,1098, 99,1094, 97,1090, 95,1086, 94,1082, 92,1078, 90,1074,
109 89,1070, 87,1066, 86,1061, 84,1057, 83,1053, 81,1049, 80,1045, 78,1040,
110 77,1036, 76,1032, 74,1027, 73,1023, 71,1019, 70,1014, 69,1010, 67,1005,
111 66,1001, 65, 997, 64, 992, 62, 988, 61, 983, 60, 978, 59, 974, 58, 969,
112 56, 965, 55, 960, 54, 955, 53, 951, 52, 946, 51, 941, 50, 937, 49, 932,
113 48, 927, 47, 923, 46, 918, 45, 913, 44, 908, 43, 904, 42, 899, 41, 894,
114 40, 889, 39, 884, 38, 880, 37, 875, 36, 870, 36, 865, 35, 860, 34, 855,
115 33, 851, 32, 846, 32, 841, 31, 836, 30, 831, 29, 826, 29, 821, 28, 816,
116 27, 811, 27, 806, 26, 802, 25, 797, 24, 792, 24, 787, 23, 782, 23, 777,
117 22, 772, 21, 767, 21, 762, 20, 757, 20, 752, 19, 747, 19, 742, 18, 737,
118 17, 732, 17, 728, 16, 723, 16, 718, 15, 713, 15, 708, 15, 703, 14, 698,
119 14, 693, 13, 688, 13, 683, 12, 678, 12, 674, 11, 669, 11, 664, 11, 659,
120 10, 654, 10, 649, 10, 644, 9, 640, 9, 635, 9, 630, 8, 625, 8, 620,
121 8, 615, 7, 611, 7, 606, 7, 601, 6, 596, 6, 592, 6, 587, 6, 582,
122 5, 577, 5, 573, 5, 568, 5, 563, 4, 559, 4, 554, 4, 550, 4, 545,
123 4, 540, 3, 536, 3, 531, 3, 527, 3, 522, 3, 517, 2, 513, 2, 508,
124 2, 504, 2, 499, 2, 495, 2, 491, 2, 486, 1, 482, 1, 477, 1, 473,
125 1, 469, 1, 464, 1, 460, 1, 456, 1, 451, 1, 447, 1, 443, 1, 439,
126 0, 434, 0, 430, 0, 426, 0, 422, 0, 418, 0, 414, 0, 410, 0, 405,
127 0, 401, 0, 397, 0, 393, 0, 389, 0, 385, 0, 381, 0, 378, 0, 374,
128 };
129
130
131 //// Counters
132
133 #define RATE( rate, div )\
134 (rate >= div ? rate / div * 8 - 1 : rate - 1)
135
136 static unsigned const counter_mask [32] =
137 {
138 RATE( 2,2), RATE(2048,4), RATE(1536,3),
139 RATE(1280,5), RATE(1024,4), RATE( 768,3),
140 RATE( 640,5), RATE( 512,4), RATE( 384,3),
141 RATE( 320,5), RATE( 256,4), RATE( 192,3),
142 RATE( 160,5), RATE( 128,4), RATE( 96,3),
143 RATE( 80,5), RATE( 64,4), RATE( 48,3),
144 RATE( 40,5), RATE( 32,4), RATE( 24,3),
145 RATE( 20,5), RATE( 16,4), RATE( 12,3),
146 RATE( 10,5), RATE( 8,4), RATE( 6,3),
147 RATE( 5,5), RATE( 4,4), RATE( 3,3),
148 RATE( 2,4),
149 RATE( 1,4)
150 };
151 #undef RATE
152
153 inline void SPC_DSP::init_counter()
154 {
155 // counters start out with this synchronization
156 m.counters [0] = 1;
157 m.counters [1] = 0;
158 m.counters [2] = -0x20u;
159 m.counters [3] = 0x0B;
160
161 int n = 2;
162 for ( int i = 1; i < 32; i++ )
163 {
164 m.counter_select [i] = &m.counters [n];
165 if ( !--n )
166 n = 3;
167 }
168 m.counter_select [ 0] = &m.counters [0];
169 m.counter_select [30] = &m.counters [2];
170 }
171
172 inline void SPC_DSP::run_counter( int i )
173 {
174 int n = m.counters [i];
175 if ( !(n-- & 7) )
176 n -= 6 - i;
177 m.counters [i] = n;
178 }
179
180 #define READ_COUNTER( rate )\
181 (*m.counter_select [rate] & counter_mask [rate])
182
183
184 //// Emulation
185
186 void SPC_DSP::run( int clock_count )
187 {
188 int new_phase = m.phase + clock_count;
189 int count = new_phase >> 5;
190 m.phase = new_phase & 31;
191 if ( !count )
192 return;
193
194 uint8_t* const ram = m.ram;
195 uint8_t const* const dir = &ram [REG(dir) * 0x100];
196 int const slow_gaussian = (REG(pmon) >> 1) | REG(non);
197 int const noise_rate = REG(flg) & 0x1F;
198
199 // Global volume
200 int mvoll = (int8_t) REG(mvoll);
201 int mvolr = (int8_t) REG(mvolr);
202 if ( mvoll * mvolr < m.surround_threshold )
203 mvoll = -mvoll; // eliminate surround
204
205 do
206 {
207 // KON/KOFF reading
208 if ( (m.every_other_sample ^= 1) != 0 )
209 {
210 m.new_kon &= ~m.kon;
211 m.kon = m.new_kon;
212 m.t_koff = REG(koff);
213 }
214
215 run_counter( 1 );
216 run_counter( 2 );
217 run_counter( 3 );
218
219 // Noise
220 if ( !READ_COUNTER( noise_rate ) )
221 {
222 int feedback = (m.noise << 13) ^ (m.noise << 14);
223 m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
224 }
225
226 // Voices
227 int pmon_input = 0;
228 int main_out_l = 0;
229 int main_out_r = 0;
230 int echo_out_l = 0;
231 int echo_out_r = 0;
232 voice_t* v = m.voices;
233 uint8_t* v_regs = m.regs;
234 int vbit = 1;
235 do
236 {
237 #define SAMPLE_PTR(i) GET_LE16A( &dir [VREG(v_regs,srcn) * 4 + i * 2] )
238
239 int brr_header = ram [v->brr_addr];
240 int kon_delay = v->kon_delay;
241
242 // Pitch
243 int pitch = GET_LE16A( &VREG(v_regs,pitchl) ) & 0x3FFF;
244 if ( REG(pmon) & vbit )
245 pitch += ((pmon_input >> 5) * pitch) >> 10;
246
247 // KON phases
248 if ( --kon_delay >= 0 )
249 {
250 v->kon_delay = kon_delay;
251
252 // Get ready to start BRR decoding on next sample
253 if ( kon_delay == 4 )
254 {
255 v->brr_addr = SAMPLE_PTR( 0 );
256 v->brr_offset = 1;
257 v->buf_pos = v->buf;
258 brr_header = 0; // header is ignored on this sample
259 }
260
261 // Envelope is never run during KON
262 v->env = 0;
263 v->hidden_env = 0;
264
265 // Disable BRR decoding until last three samples
266 v->interp_pos = (kon_delay & 3 ? 0x4000 : 0);
267
268 // Pitch is never added during KON
269 pitch = 0;
270 }
271
272 int env = v->env;
273
274 // Gaussian interpolation
275 {
276 int output = 0;
277 VREG(v_regs,envx) = (uint8_t) (env >> 4);
278 if ( env )
279 {
280 // Make pointers into gaussian based on fractional position between samples
281 int offset = (unsigned) v->interp_pos >> 3 & 0x1FE;
282 short const* fwd = interleved_gauss + offset;
283 short const* rev = interleved_gauss + 510 - offset; // mirror left half of gaussian
284
285 int const* in = &v->buf_pos [(unsigned) v->interp_pos >> 12];
286
287 if ( !(slow_gaussian & vbit) ) // 99%
288 {
289 // Faster approximation when exact sample value isn't necessary for pitch mod
290 output = (fwd [0] * in [0] +
291 fwd [1] * in [1] +
292 rev [1] * in [2] +
293 rev [0] * in [3]) >> 11;
294 output = (output * env) >> 11;
295 }
296 else
297 {
298 output = (int16_t) (m.noise * 2);
299 if ( !(REG(non) & vbit) )
300 {
301 output = (fwd [0] * in [0]) >> 11;
302 output += (fwd [1] * in [1]) >> 11;
303 output += (rev [1] * in [2]) >> 11;
304 output = (int16_t) output;
305 output += (rev [0] * in [3]) >> 11;
306
307 CLAMP16( output );
308 output &= ~1;
309 }
310 output = (output * env) >> 11 & ~1;
311 }
312
313 // Output
314 int l = output * v->volume [0];
315 int r = output * v->volume [1];
316
317 main_out_l += l;
318 main_out_r += r;
319
320 if ( REG(eon) & vbit )
321 {
322 echo_out_l += l;
323 echo_out_r += r;
324 }
325 }
326
327 pmon_input = output;
328 VREG(v_regs,outx) = (uint8_t) (output >> 8);
329 }
330
331 // Soft reset or end of sample
332 if ( REG(flg) & 0x80 || (brr_header & 3) == 1 )
333 {
334 v->env_mode = env_release;
335 env = 0;
336 }
337
338 if ( m.every_other_sample )
339 {
340 // KOFF
341 if ( m.t_koff & vbit )
342 v->env_mode = env_release;
343
344 // KON
345 if ( m.kon & vbit )
346 {
347 v->kon_delay = 5;
348 v->env_mode = env_attack;
349 REG(endx) &= ~vbit;
350 }
351 }
352
353 // Envelope
354 if ( !v->kon_delay )
355 {
356 if ( v->env_mode == env_release ) // 97%
357 {
358 env -= 0x8;
359 v->env = env;
360 if ( env <= 0 )
361 {
362 v->env = 0;
363 goto skip_brr; // no BRR decoding for you!
364 }
365 }
366 else // 3%
367 {
368 int rate;
369 int const adsr0 = VREG(v_regs,adsr0);
370 int env_data = VREG(v_regs,adsr1);
371 if ( adsr0 >= 0x80 ) // 97% ADSR
372 {
373 if ( v->env_mode > env_decay ) // 89%
374 {
375 env--;
376 env -= env >> 8;
377 rate = env_data & 0x1F;
378
379 // optimized handling
380 v->hidden_env = env;
381 if ( READ_COUNTER( rate ) )
382 goto exit_env;
383 v->env = env;
384 goto exit_env;
385 }
386 else if ( v->env_mode == env_decay )
387 {
388 env--;
389 env -= env >> 8;
390 rate = (adsr0 >> 3 & 0x0E) + 0x10;
391 }
392 else // env_attack
393 {
394 rate = (adsr0 & 0x0F) * 2 + 1;
395 env += rate < 31 ? 0x20 : 0x400;
396 }
397 }
398 else // GAIN
399 {
400 int mode;
401 env_data = VREG(v_regs,gain);
402 mode = env_data >> 5;
403 if ( mode < 4 ) // direct
404 {
405 env = env_data * 0x10;
406 rate = 31;
407 }
408 else
409 {
410 rate = env_data & 0x1F;
411 if ( mode == 4 ) // 4: linear decrease
412 {
413 env -= 0x20;
414 }
415 else if ( mode < 6 ) // 5: exponential decrease
416 {
417 env--;
418 env -= env >> 8;
419 }
420 else // 6,7: linear increase
421 {
422 env += 0x20;
423 if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
424 env += 0x8 - 0x20; // 7: two-slope linear increase
425 }
426 }
427 }
428
429 // Sustain level
430 if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
431 v->env_mode = env_sustain;
432
433 v->hidden_env = env;
434
435 // unsigned cast because linear decrease going negative also triggers this
436 if ( (unsigned) env > 0x7FF )
437 {
438 env = (env < 0 ? 0 : 0x7FF);
439 if ( v->env_mode == env_attack )
440 v->env_mode = env_decay;
441 }
442
443 if ( !READ_COUNTER( rate ) )
444 v->env = env; // nothing else is controlled by the counter
445 }
446 }
447 exit_env:
448
449 {
450 // Apply pitch
451 int old_pos = v->interp_pos;
452 int interp_pos = (old_pos & 0x3FFF) + pitch;
453 if ( interp_pos > 0x7FFF )
454 interp_pos = 0x7FFF;
455 v->interp_pos = interp_pos;
456
457 // BRR decode if necessary
458 if ( old_pos >= 0x4000 )
459 {
460 // Arrange the four input nybbles in 0xABCD order for easy decoding
461 int nybbles = ram [(v->brr_addr + v->brr_offset) & 0xFFFF] * 0x100 +
462 ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
463
464 // Advance read position
465 int const brr_block_size = 9;
466 int brr_offset = v->brr_offset;
467 if ( (brr_offset += 2) >= brr_block_size )
468 {
469 // Next BRR block
470 int brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
471 assert( brr_offset == brr_block_size );
472 if ( brr_header & 1 )
473 {
474 brr_addr = SAMPLE_PTR( 1 );
475 if ( !v->kon_delay )
476 REG(endx) |= vbit;
477 }
478 v->brr_addr = brr_addr;
479 brr_offset = 1;
480 }
481 v->brr_offset = brr_offset;
482
483 // Decode
484
485 // 0: >>1 1: <<0 2: <<1 ... 12: <<11 13-15: >>4 <<11
486 static unsigned char const shifts [16 * 2] = {
487 13,12,12,12,12,12,12,12,12,12,12, 12, 12, 16, 16, 16,
488 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 11, 11, 11
489 };
490 int const scale = brr_header >> 4;
491 int const right_shift = shifts [scale];
492 int const left_shift = shifts [scale + 16];
493
494 // Write to next four samples in circular buffer
495 int* pos = v->buf_pos;
496 int* end;
497
498 // Decode four samples
499 for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
500 {
501 // Extract upper nybble and scale appropriately
502 int s = ((int16_t) nybbles >> right_shift) << left_shift;
503
504 // Apply IIR filter (8 is the most commonly used)
505 int const filter = brr_header & 0x0C;
506 int const p1 = pos [brr_buf_size - 1];
507 int const p2 = pos [brr_buf_size - 2] >> 1;
508 if ( filter >= 8 )
509 {
510 s += p1;
511 s -= p2;
512 if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
513 {
514 s += p2 >> 4;
515 s += (p1 * -3) >> 6;
516 }
517 else // s += p1 * 0.8984375 - p2 * 0.40625
518 {
519 s += (p1 * -13) >> 7;
520 s += (p2 * 3) >> 4;
521 }
522 }
523 else if ( filter ) // s += p1 * 0.46875
524 {
525 s += p1 >> 1;
526 s += (-p1) >> 5;
527 }
528
529 // Adjust and write sample
530 CLAMP16( s );
531 s = (int16_t) (s * 2);
532 pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
533 }
534
535 if ( pos >= &v->buf [brr_buf_size] )
536 pos = v->buf;
537 v->buf_pos = pos;
538 }
539 }
540 skip_brr:
541 // Next voice
542 vbit <<= 1;
543 v_regs += 0x10;
544 v++;
545 }
546 while ( vbit < 0x100 );
547
548 // Echo position
549 int echo_offset = m.echo_offset;
550 uint8_t* const echo_ptr = &ram [(REG(esa) * 0x100 + echo_offset) & 0xFFFF];
551 if ( !echo_offset )
552 m.echo_length = (REG(edl) & 0x0F) * 0x800;
553 echo_offset += 4;
554 if ( echo_offset >= m.echo_length )
555 echo_offset = 0;
556 m.echo_offset = echo_offset;
557
558 // FIR
559 int echo_in_l = GET_LE16SA( echo_ptr + 0 );
560 int echo_in_r = GET_LE16SA( echo_ptr + 2 );
561
562 int (*echo_hist_pos) [2] = m.echo_hist_pos;
563 if ( ++echo_hist_pos >= &m.echo_hist [echo_hist_size] )
564 echo_hist_pos = m.echo_hist;
565 m.echo_hist_pos = echo_hist_pos;
566
567 echo_hist_pos [0] [0] = echo_hist_pos [8] [0] = echo_in_l;
568 echo_hist_pos [0] [1] = echo_hist_pos [8] [1] = echo_in_r;
569
570 #define CALC_FIR_( i, in ) ((in) * (int8_t) REG(fir + i * 0x10))
571 echo_in_l = CALC_FIR_( 7, echo_in_l );
572 echo_in_r = CALC_FIR_( 7, echo_in_r );
573
574 #define CALC_FIR( i, ch ) CALC_FIR_( i, echo_hist_pos [i + 1] [ch] )
575 #define DO_FIR( i )\
576 echo_in_l += CALC_FIR( i, 0 );\
577 echo_in_r += CALC_FIR( i, 1 );
578 DO_FIR( 0 );
579 DO_FIR( 1 );
580 DO_FIR( 2 );
581 #if defined (__MWERKS__) && __MWERKS__ < 0x3200
582 __eieio(); // keeps compiler from stupidly "caching" things in memory
583 #endif
584 DO_FIR( 3 );
585 DO_FIR( 4 );
586 DO_FIR( 5 );
587 DO_FIR( 6 );
588
589 // Echo out
590 if ( !(REG(flg) & 0x20) )
591 {
592 int l = (echo_out_l >> 7) + ((echo_in_l * (int8_t) REG(efb)) >> 14);
593 int r = (echo_out_r >> 7) + ((echo_in_r * (int8_t) REG(efb)) >> 14);
594
595 // just to help pass more validation tests
596 #if SPC_MORE_ACCURACY
597 l &= ~1;
598 r &= ~1;
599 #endif
600
601 CLAMP16( l );
602 CLAMP16( r );
603
604 SET_LE16A( echo_ptr + 0, l );
605 SET_LE16A( echo_ptr + 2, r );
606 }
607
608 // Sound out
609 int l = (main_out_l * mvoll + echo_in_l * (int8_t) REG(evoll)) >> 14;
610 int r = (main_out_r * mvolr + echo_in_r * (int8_t) REG(evolr)) >> 14;
611
612 CLAMP16( l );
613 CLAMP16( r );
614
615 if ( (REG(flg) & 0x40) )
616 {
617 l = 0;
618 r = 0;
619 }
620
621 sample_t* out = m.out;
622 WRITE_SAMPLES( l, r, out );
623 m.out = out;
624 }
625 while ( --count );
626 }
627
628
629 //// Setup
630
631 void SPC_DSP::mute_voices( int mask )
632 {
633 m.mute_mask = mask;
634 for ( int i = 0; i < voice_count; i++ )
635 {
636 m.voices [i].enabled = (mask >> i & 1) - 1;
637 update_voice_vol( i * 0x10 );
638 }
639 }
640
641 void SPC_DSP::init( void* ram_64k )
642 {
643 m.ram = (uint8_t*) ram_64k;
644 mute_voices( 0 );
645 disable_surround( false );
646 set_output( 0, 0 );
647 reset();
648
649 #ifndef NDEBUG
650 // be sure this sign-extends
651 assert( (int16_t) 0x8000 == -0x8000 );
652
653 // be sure right shift preserves sign
654 assert( (-1 >> 1) == -1 );
655
656 // check clamp macro
657 int i;
658 i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
659 i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
660
661 blargg_verify_byte_order();
662 #endif
663 }
664
665 void SPC_DSP::soft_reset_common()
666 {
667 require( m.ram ); // init() must have been called already
668
669 m.noise = 0x4000;
670 m.echo_hist_pos = m.echo_hist;
671 m.every_other_sample = 1;
672 m.echo_offset = 0;
673 m.phase = 0;
674
675 init_counter();
676 }
677
678 void SPC_DSP::soft_reset()
679 {
680 REG(flg) = 0xE0;
681 soft_reset_common();
682 }
683
684 void SPC_DSP::load( uint8_t const regs [register_count] )
685 {
686 memcpy( m.regs, regs, sizeof m.regs );
687 memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
688
689 // Internal state
690 int i;
691 for ( i = voice_count; --i >= 0; )
692 {
693 voice_t& v = m.voices [i];
694 v.brr_offset = 1;
695 v.buf_pos = v.buf;
696 }
697 m.new_kon = REG(kon);
698
699 mute_voices( m.mute_mask );
700 soft_reset_common();
701 }
702
703 void SPC_DSP::reset() { load( initial_regs ); }