blob: 5d7f9421896ac574bcc2df3e16b08de76e4b6ef1 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
// snes_spc 0.9.0. http://www.slack.net/~ant/
#include "SPC_Filter.h"
/* Copyright (C) 2007 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
#include "blargg_source.h"
void SPC_Filter::clear() { memset( ch, 0, sizeof ch ); }
SPC_Filter::SPC_Filter()
{
enabled = true;
gain = gain_unit;
bass = bass_norm;
clear();
}
void SPC_Filter::run( short io [], int count )
{
require( (count & 1) == 0 ); // must be even
int const gain = this->gain;
if ( enabled )
{
int const bass = this->bass;
chan_t* c = &ch [2];
do
{
// cache in registers
int sum = (--c)->sum;
int pp1 = c->pp1;
int p1 = c->p1;
for ( int i = 0; i < count; i += 2 )
{
// Low-pass filter (two point FIR with coeffs 0.25, 0.75)
int f = io [i] + p1;
p1 = io [i] * 3;
// High-pass filter ("leaky integrator")
int delta = f - pp1;
pp1 = f;
int s = sum >> (gain_bits + 2);
sum += (delta * gain) - (sum >> bass);
// Clamp to 16 bits
if ( (short) s != s )
s = (s >> 31) ^ 0x7FFF;
io [i] = (short) s;
}
c->p1 = p1;
c->pp1 = pp1;
c->sum = sum;
++io;
}
while ( c != ch );
}
else if ( gain != gain_unit )
{
short* const end = io + count;
while ( io < end )
{
int s = (*io * gain) >> gain_bits;
if ( (short) s != s )
s = (s >> 31) ^ 0x7FFF;
*io++ = (short) s;
}
}
}
|