rlm@0: // snes_spc 0.9.0. http://www.slack.net/~ant/ rlm@0: rlm@0: #include "SPC_Filter.h" rlm@0: rlm@0: #include rlm@0: rlm@0: /* Copyright (C) 2007 Shay Green. This module is free software; you rlm@0: can redistribute it and/or modify it under the terms of the GNU Lesser rlm@0: General Public License as published by the Free Software Foundation; either rlm@0: version 2.1 of the License, or (at your option) any later version. This rlm@0: module is distributed in the hope that it will be useful, but WITHOUT ANY rlm@0: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS rlm@0: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more rlm@0: details. You should have received a copy of the GNU Lesser General Public rlm@0: License along with this module; if not, write to the Free Software Foundation, rlm@0: Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ rlm@0: rlm@0: #include "blargg_source.h" rlm@0: rlm@0: void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); } rlm@0: rlm@0: SPC_Filter::SPC_Filter() rlm@0: { rlm@0: gain = gain_unit; rlm@0: bass = bass_norm; rlm@0: clear(); rlm@0: } rlm@0: rlm@0: void SPC_Filter::run( short* io, int count ) rlm@0: { rlm@0: require( (count & 1) == 0 ); // must be even rlm@0: rlm@0: int const gain = this->gain; rlm@0: int const bass = this->bass; rlm@0: chan_t* c = &ch [2]; rlm@0: do rlm@0: { rlm@0: // cache in registers rlm@0: int sum = (--c)->sum; rlm@0: int pp1 = c->pp1; rlm@0: int p1 = c->p1; rlm@0: rlm@0: for ( int i = 0; i < count; i += 2 ) rlm@0: { rlm@0: // Low-pass filter (two point FIR with coeffs 0.25, 0.75) rlm@0: int f = io [i] + p1; rlm@0: p1 = io [i] * 3; rlm@0: rlm@0: // High-pass filter ("leaky integrator") rlm@0: int delta = f - pp1; rlm@0: pp1 = f; rlm@0: int s = sum >> (gain_bits + 2); rlm@0: sum += (delta * gain) - (sum >> bass); rlm@0: rlm@0: // Clamp to 16 bits rlm@0: if ( (short) s != s ) rlm@0: s = (s >> 31) ^ 0x7FFF; rlm@0: rlm@0: io [i] = (short) s; rlm@0: } rlm@0: rlm@0: c->p1 = p1; rlm@0: c->pp1 = pp1; rlm@0: c->sum = sum; rlm@0: ++io; rlm@0: } rlm@0: while ( c != ch ); rlm@0: }