comparison src/console/Spc_Dsp.cxx @ 316:fb513e10174e trunk

[svn] - merge libconsole-blargg into mainline libconsole: + obsoletes plugins-ugly:sapplug
author nenolod
date Thu, 30 Nov 2006 19:54:33 -0800
parents 3da1b8942b8b
children 986f098da058
comparison
equal deleted inserted replaced
315:2294f3a6f136 316:fb513e10174e
1 1 // Game_Music_Emu 0.5.1. http://www.slack.net/~ant/
2 // Game_Music_Emu 0.3.0. http://www.slack.net/~ant/
3 2
4 // Based on Brad Martin's OpenSPC DSP emulator 3 // Based on Brad Martin's OpenSPC DSP emulator
5 4
6 #include "Spc_Dsp.h" 5 #include "Spc_Dsp.h"
7 6
7 #include "blargg_endian.h"
8 #include <string.h> 8 #include <string.h>
9
10 #include "blargg_endian.h"
11 9
12 /* Copyright (C) 2002 Brad Martin */ 10 /* Copyright (C) 2002 Brad Martin */
13 /* Copyright (C) 2004-2006 Shay Green. This module is free software; you 11 /* Copyright (C) 2004-2006 Shay Green. This module is free software; you
14 can redistribute it and/or modify it under the terms of the GNU Lesser 12 can redistribute it and/or modify it under the terms of the GNU Lesser
15 General Public License as published by the Free Software Foundation; either 13 General Public License as published by the Free Software Foundation; either
16 version 2.1 of the License, or (at your option) any later version. This 14 version 2.1 of the License, or (at your option) any later version. This
17 module is distributed in the hope that it will be useful, but WITHOUT ANY 15 module is distributed in the hope that it will be useful, but WITHOUT ANY
18 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for 17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
20 more details. You should have received a copy of the GNU Lesser General 18 details. You should have received a copy of the GNU Lesser General Public
21 Public License along with this module; if not, write to the Free Software 19 License along with this module; if not, write to the Free Software Foundation,
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 20 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
23 21
24 #include BLARGG_SOURCE_BEGIN 22 #include "blargg_source.h"
23
24 #ifdef BLARGG_ENABLE_OPTIMIZER
25 #include BLARGG_ENABLE_OPTIMIZER
26 #endif
25 27
26 Spc_Dsp::Spc_Dsp( uint8_t* ram_ ) : ram( ram_ ) 28 Spc_Dsp::Spc_Dsp( uint8_t* ram_ ) : ram( ram_ )
27 { 29 {
28 set_gain( 1.0 ); 30 set_gain( 1.0 );
29 mute_voices( 0 ); 31 mute_voices( 0 );
30 disable_surround( false ); 32 disable_surround( false );
31 33
32 BOOST_STATIC_ASSERT( sizeof (g) == register_count && sizeof (voice) == register_count ); 34 BOOST_STATIC_ASSERT( sizeof (g) == register_count && sizeof (voice) == register_count );
35 blargg_verify_byte_order();
33 } 36 }
34 37
35 void Spc_Dsp::mute_voices( int mask ) 38 void Spc_Dsp::mute_voices( int mask )
36 { 39 {
37 for ( int i = 0; i < voice_count; i++ ) 40 for ( int i = 0; i < voice_count; i++ )
65 { 68 {
66 require( (unsigned) i < register_count ); 69 require( (unsigned) i < register_count );
67 70
68 reg [i] = data; 71 reg [i] = data;
69 int high = i >> 4; 72 int high = i >> 4;
70 switch ( i & 0x0f ) 73 switch ( i & 0x0F )
71 { 74 {
72 // voice volume 75 // voice volume
73 case 0: 76 case 0:
74 case 1: { 77 case 1: {
75 short* volume = voice_state [high].volume; 78 short* volume = voice_state [high].volume;
76 int left = (int8_t) reg [i & ~1]; 79 int left = (int8_t) reg [i & ~1];
77 int right = (int8_t) reg [i | 1]; 80 int right = (int8_t) reg [i | 1];
78 volume [0] = left; 81 volume [0] = left;
79 volume [1] = right; 82 volume [1] = right;
80 // kill surround only if signs of volumes differ 83 // kill surround only if enabled and signs of volumes differ
81 if ( left * right < surround_threshold ) 84 if ( left * right < surround_threshold )
82 { 85 {
83 if ( left < 0 ) 86 if ( left < 0 )
84 volume [0] = -left; 87 volume [0] = -left;
85 else 88 else
87 } 90 }
88 break; 91 break;
89 } 92 }
90 93
91 // fir coefficients 94 // fir coefficients
92 case 0x0f: 95 case 0x0F:
93 fir_coeff [high] = (int8_t) data; // sign-extend 96 fir_coeff [high] = (int8_t) data; // sign-extend
94 break; 97 break;
95 } 98 }
96 } 99 }
97 100
98 // This table is for envelope timing. It represents the number of counts 101 // This table is for envelope timing. It represents the number of counts
99 // that should be subtracted from the counter each sample period (32kHz). 102 // that should be subtracted from the counter each sample period (32kHz).
100 // The counter starts at 30720 (0x7800). Each count divides exactly into 103 // The counter starts at 30720 (0x7800). Each count divides exactly into
101 // 0x7800 without remainder. 104 // 0x7800 without remainder.
102 const int env_rate_init = 0x7800; 105 const int env_rate_init = 0x7800;
103 static const short env_rates [0x20] = 106 static short const env_rates [0x20] =
104 { 107 {
105 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C, 108 0x0000, 0x000F, 0x0014, 0x0018, 0x001E, 0x0028, 0x0030, 0x003C,
106 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180, 109 0x0050, 0x0060, 0x0078, 0x00A0, 0x00C0, 0x00F0, 0x0140, 0x0180,
107 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00, 110 0x01E0, 0x0280, 0x0300, 0x03C0, 0x0500, 0x0600, 0x0780, 0x0A00,
108 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800 111 0x0C00, 0x0F00, 0x1400, 0x1800, 0x1E00, 0x2800, 0x3C00, 0x7800
190 193
191 case state_sustain: 194 case state_sustain:
192 // Docs: "SR [is multiplied] by the fixed value 1-1/256." 195 // Docs: "SR [is multiplied] by the fixed value 1-1/256."
193 // Multiplying ENVX by 255/256 every time SUSTAIN is 196 // Multiplying ENVX by 255/256 every time SUSTAIN is
194 // updated. 197 // updated.
195 cnt -= env_rates [raw_voice.adsr [1] & 0x1f]; 198 cnt -= env_rates [raw_voice.adsr [1] & 0x1F];
196 if ( cnt <= 0 ) 199 if ( cnt <= 0 )
197 { 200 {
198 cnt = env_rate_init; 201 cnt = env_rate_init;
199 envx -= ((envx - 1) >> 8) + 1; 202 envx -= ((envx - 1) >> 8) + 1;
200 voice.envx = envx; 203 voice.envx = envx;
338 { 341 {
339 noise_count = env_rate_init; 342 noise_count = env_rate_init;
340 343
341 noise_amp = BOOST::int16_t (noise * 2); 344 noise_amp = BOOST::int16_t (noise * 2);
342 345
346 // TODO: switch to Galios style
343 int feedback = (noise << 13) ^ (noise << 14); 347 int feedback = (noise << 13) ^ (noise << 14);
344 noise = (feedback & 0x4000) | (noise >> 1); 348 noise = (feedback & 0x4000) | (noise >> 1);
345 } 349 }
346 } 350 }
347 351
348 // What is the expected behavior when pitch modulation is enabled on 352 // What is the expected behavior when pitch modulation is enabled on
349 // voice 0? Jurassic Park 2 does this. Assume 0 for now. 353 // voice 0? Jurassic Park 2 does this. Assume 0 for now.
350 long prev_outx = 0; 354 blargg_long prev_outx = 0;
351 355
352 int echol = 0; 356 int echol = 0;
353 int echor = 0; 357 int echor = 0;
354 int left = 0; 358 int left = 0;
355 int right = 0; 359 int right = 0;
365 keys |= vbit; 369 keys |= vbit;
366 voice.addr = GET_LE16( sd [raw_voice.waveform].start ); 370 voice.addr = GET_LE16( sd [raw_voice.waveform].start );
367 voice.block_remain = 1; 371 voice.block_remain = 1;
368 voice.envx = 0; 372 voice.envx = 0;
369 voice.block_header = 0; 373 voice.block_header = 0;
370 voice.fraction = 0x3fff; // decode three samples immediately 374 voice.fraction = 0x3FFF; // decode three samples immediately
371 voice.interp0 = 0; // BRR decoder filter uses previous two samples 375 voice.interp0 = 0; // BRR decoder filter uses previous two samples
372 voice.interp1 = 0; 376 voice.interp1 = 0;
373 377
374 // NOTE: Real SNES does *not* appear to initialize the 378 // NOTE: Real SNES does *not* appear to initialize the
375 // envelope counter to anything in particular. The first 379 // envelope counter to anything in particular. The first
472 delta = (delta >> 14) & ~0x7FF; 476 delta = (delta >> 14) & ~0x7FF;
473 477
474 // One, two and three point IIR filters 478 // One, two and three point IIR filters
475 int smp1 = voice.interp0; 479 int smp1 = voice.interp0;
476 int smp2 = voice.interp1; 480 int smp2 = voice.interp1;
477 switch ( (voice.block_header >> 2) & 3 ) 481 if ( voice.block_header & 8 )
478 { 482 {
479 case 0: 483 delta += smp1;
480 break; 484 delta -= smp2 >> 1;
481 485 if ( !(voice.block_header & 4) )
482 case 1: 486 {
483 delta += smp1 >> 1; 487 delta += (-smp1 - (smp1 >> 1)) >> 5;
484 delta += (-smp1) >> 5;
485 break;
486
487 case 2:
488 delta += smp1;
489 delta += (-(smp1 + (smp1 >> 1))) >> 5;
490 delta -= smp2 >> 1;
491 delta += smp2 >> 5; 488 delta += smp2 >> 5;
492 break; 489 }
493 490 else
494 case 3: 491 {
495 delta += smp1; 492 delta += (-smp1 * 13) >> 7;
496 delta += (-(smp1 + (smp1 << 2) + (smp1 << 3))) >> 7;
497 delta -= smp2 >> 1;
498 delta += (smp2 + (smp2 >> 1)) >> 4; 493 delta += (smp2 + (smp2 >> 1)) >> 4;
499 break; 494 }
495 }
496 else if ( voice.block_header & 4 )
497 {
498 delta += smp1 >> 1;
499 delta += (-smp1) >> 5;
500 } 500 }
501 501
502 voice.interp3 = voice.interp2; 502 voice.interp3 = voice.interp2;
503 voice.interp2 = smp2; 503 voice.interp2 = smp2;
504 voice.interp1 = smp1; 504 voice.interp1 = smp1;
511 rate = (rate * (prev_outx + 32768)) >> 15; 511 rate = (rate * (prev_outx + 32768)) >> 15;
512 512
513 // Gaussian interpolation using most recent 4 samples 513 // Gaussian interpolation using most recent 4 samples
514 int index = voice.fraction >> 2 & 0x3FC; 514 int index = voice.fraction >> 2 & 0x3FC;
515 voice.fraction = (voice.fraction & 0x0FFF) + rate; 515 voice.fraction = (voice.fraction & 0x0FFF) + rate;
516 const BOOST::int16_t* table = (BOOST::int16_t*) ((char*) gauss + index); 516 const BOOST::int16_t* table = (BOOST::int16_t const*) ((char const*) gauss + index);
517 const BOOST::int16_t* table2 = (BOOST::int16_t*) ((char*) gauss + (255*4 - index)); 517 const BOOST::int16_t* table2 = (BOOST::int16_t const*) ((char const*) gauss + (255*4 - index));
518 int s = ((table [0] * voice.interp3) >> 12) + 518 int s = ((table [0] * voice.interp3) >> 12) +
519 ((table [1] * voice.interp2) >> 12); 519 ((table [1] * voice.interp2) >> 12) +
520 s += ((table2 [1] * voice.interp1) >> 12) + 520 ((table2 [1] * voice.interp1) >> 12);
521 // to do: should clamp here 521 s = (BOOST::int16_t) (s * 2);
522 ((table2 [0] * voice.interp0) >> 12); 522 s += (table2 [0] * voice.interp0) >> 11 & ~1;
523 int output = noise_amp; // noise is rarely used 523 int output = clamp_16( s );
524 if ( !(g.noise_enables & vbit) ) 524 if ( g.noise_enables & vbit )
525 output = clamp_16( s * 2 ); 525 output = noise_amp;
526 526
527 // scale output and set outx values 527 // scale output and set outx values
528 output = (output * envx) >> 11 & ~1; 528 output = (output * envx) >> 11 & ~1;
529 529
530 // output and apply muting (by setting voice.enabled to 31) 530 // output and apply muting (by setting voice.enabled to 31)
531 // if voice is externally disabled (not a SNES feature) 531 // if voice is externally disabled (not a SNES feature)
532 int l = (voice.volume [0] * output) >> voice.enabled; 532 int l = (voice.volume [0] * output) >> voice.enabled;
533 int r = (voice.volume [1] * output) >> voice.enabled; 533 int r = (voice.volume [1] * output) >> voice.enabled;
534 prev_outx = output; 534 prev_outx = output;
535 raw_voice.outx = output >> 8; 535 raw_voice.outx = int8_t (output >> 8);
536 if ( g.echo_ons & vbit ) 536 if ( g.echo_ons & vbit )
537 { 537 {
538 echol += l; 538 echol += l;
539 echor += r; 539 echor += r;
540 } 540 }
541 left += l; 541 left += l;
542 right += r; 542 right += r;
543 } 543 }
544 // end of channel loop 544 // end of channel loop
545 545
546 // main volume control 546 // main volume control
561 561
562 // put samples in history ring buffer 562 // put samples in history ring buffer
563 const int fir_offset = this->fir_offset; 563 const int fir_offset = this->fir_offset;
564 short (*fir_pos) [2] = &fir_buf [fir_offset]; 564 short (*fir_pos) [2] = &fir_buf [fir_offset];
565 this->fir_offset = (fir_offset + 7) & 7; // move backwards one step 565 this->fir_offset = (fir_offset + 7) & 7; // move backwards one step
566 fir_pos [0] [0] = fb_left; 566 fir_pos [0] [0] = (short) fb_left;
567 fir_pos [0] [1] = fb_right; 567 fir_pos [0] [1] = (short) fb_right;
568 fir_pos [8] [0] = fb_left; // duplicate at +8 eliminates wrap checking below 568 fir_pos [8] [0] = (short) fb_left; // duplicate at +8 eliminates wrap checking below
569 fir_pos [8] [1] = fb_right; 569 fir_pos [8] [1] = (short) fb_right;
570 570
571 // FIR 571 // FIR
572 fb_left = fb_left * fir_coeff [7] + 572 fb_left = fb_left * fir_coeff [7] +
573 fir_pos [1] [0] * fir_coeff [6] + 573 fir_pos [1] [0] * fir_coeff [6] +
574 fir_pos [2] [0] * fir_coeff [5] + 574 fir_pos [2] [0] * fir_coeff [5] +
606 left = clamp_16( left ); 606 left = clamp_16( left );
607 right = clamp_16( right ); 607 right = clamp_16( right );
608 608
609 int mute = g.flags & 0x40; 609 int mute = g.flags & 0x40;
610 610
611 out_buf [0] = left; 611 out_buf [0] = (short) left;
612 out_buf [1] = right; 612 out_buf [1] = (short) right;
613 out_buf += 2; 613 out_buf += 2;
614 614
615 // muting 615 // muting
616 if ( mute ) 616 if ( mute )
617 { 617 {
661 2, 504, 2, 499, 2, 495, 2, 491, 2, 486, 1, 482, 1, 477, 1, 473, 661 2, 504, 2, 499, 2, 495, 2, 491, 2, 486, 1, 482, 1, 477, 1, 473,
662 1, 469, 1, 464, 1, 460, 1, 456, 1, 451, 1, 447, 1, 443, 1, 439, 662 1, 469, 1, 464, 1, 460, 1, 456, 1, 451, 1, 447, 1, 443, 1, 439,
663 0, 434, 0, 430, 0, 426, 0, 422, 0, 418, 0, 414, 0, 410, 0, 405, 663 0, 434, 0, 430, 0, 426, 0, 422, 0, 418, 0, 414, 0, 410, 0, 405,
664 0, 401, 0, 397, 0, 393, 0, 389, 0, 385, 0, 381, 0, 378, 0, 374, 664 0, 401, 0, 397, 0, 393, 0, 389, 0, 385, 0, 381, 0, 378, 0, 374,
665 }; 665 };
666