1 /* SpiralSynth
2 * Copyleft (C) 2000 David Griffiths <dave@pawfal.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #include "Filter.h"
20
21 static const float MAX_RES = 10;
22 static const float MIN_RES = 1;
23 static const float MAX_CUTOFF = 3000;
24 static const float MIN_CUTOFF = 500;
25
Filter()26 Filter::Filter() :
27 fs(SpiralInfo::SAMPLERATE), // Sampling frequency
28 fc(500), // Filter cutoff
29 Q(1), // Resonance
30 k(1.0), // Set overall filter gain
31 m_RevCutoffMod(false),
32 m_RevResonanceMod(false),
33 m_FilterBypass(false),
34 m_CutoffModBuf(NULL),
35 m_ResonanceModBuf(NULL)
36 {
37 SetupCoeffs();
38
39
40 iir = new FILTER[SpiralInfo::POLY];
41
42 for (int n=0; n<SpiralInfo::POLY; n++)
43 {
44 iir[n].length = FILTER_SECTIONS;
45 iir[n].coef = (float *) calloc(4 * iir[n].length + 1 , sizeof(float));
46
47 if (!iir[n].coef)
48 {
49 printf("Unable to allocate coef array, exiting\n");
50 exit(1);
51 }
52 }
53 }
54
~Filter()55 Filter::~Filter()
56 {
57 delete[] iir;
58 }
59
SetupCoeffs()60 void Filter::SetupCoeffs()
61 {
62 ProtoCoef[0].a0 = 1.0;
63 ProtoCoef[0].a1 = 0;
64 ProtoCoef[0].a2 = 0;
65 ProtoCoef[0].b0 = 1.0;
66 ProtoCoef[0].b1 = 0.765367;
67 ProtoCoef[0].b2 = 1.0;
68
69 ProtoCoef[1].a0 = 1.0;
70 ProtoCoef[1].a1 = 0;
71 ProtoCoef[1].a2 = 0;
72 ProtoCoef[1].b0 = 1.0;
73 ProtoCoef[1].b1 = 1.847759;
74 ProtoCoef[1].b2 = 1.0;
75 }
76
GetOutput(int V,short * data)77 void Filter::GetOutput(int V, short *data)
78 {
79 float Cutoff;
80 float Resonance;
81
82 if (m_FilterBypass) return;
83
84 for (int n=0; n<SpiralInfo::BUFSIZE; n++)
85 {
86 coef = iir[V].coef + 1; /* Skip k, or gain */
87 k=0.25;
88
89 Cutoff = fc;
90 Resonance = Q;
91
92 if (m_CutoffModBuf)
93 {
94 if (!m_RevCutoffMod) Cutoff+=(m_CutoffModBuf[n]*SpiralInfo::VALUECONV)*5000;
95 else Cutoff+=(1.0f-(m_CutoffModBuf[n]*SpiralInfo::VALUECONV))*5000;
96 }
97
98 if (m_ResonanceModBuf)
99 {
100 if (!m_RevResonanceMod) Resonance+=(m_ResonanceModBuf[n]*SpiralInfo::VALUECONV)*10;
101 else Resonance+=(1.0f-(m_ResonanceModBuf[n]*SpiralInfo::VALUECONV))*10;
102 }
103
104 Cutoff/=2;
105
106 if (Resonance>MAX_RES) Resonance=MAX_RES;
107 if (Cutoff>MAX_CUTOFF) Cutoff=MAX_CUTOFF;
108 if (Resonance<MIN_RES) Resonance=MIN_RES;
109 if (Cutoff<MIN_CUTOFF) Cutoff=MIN_CUTOFF;
110
111 if (n%SpiralInfo::FILTERGRAN==0)
112 {
113 for (nInd = 0; nInd < iir[V].length; nInd++)
114 {
115 a2 = ProtoCoef[nInd].a2;
116
117 a0 = ProtoCoef[nInd].a0;
118 a1 = ProtoCoef[nInd].a1;
119
120 b0 = ProtoCoef[nInd].b0;
121 b1 = ProtoCoef[nInd].b1 / Resonance;
122 b2 = ProtoCoef[nInd].b2;
123 szxform(&a0, &a1, &a2, &b0, &b1, &b2, Cutoff*(Cutoff/1000.0f), fs, &k, coef);
124 coef += 4;
125 }
126
127 iir[V].coef[0] = k;
128 }
129
130 long temp=(long)(iir_filter((float)(data[n]/0.5f),&iir[V]));
131 if (temp>SpiralInfo::MAXSAMPLE) temp=SpiralInfo::MAXSAMPLE;
132 if (temp<-SpiralInfo::MAXSAMPLE) temp=-SpiralInfo::MAXSAMPLE;
133
134 data[n]=static_cast<short>(temp);
135 }
136
137 }
138
ModulateCutoff(short * data)139 void Filter::ModulateCutoff(short *data)
140 {
141 m_CutoffModBuf=data;
142 }
143
ModulateResonance(short * data)144 void Filter::ModulateResonance(short *data)
145 {
146 m_ResonanceModBuf=data;
147 }
148
Reset()149 void Filter::Reset()
150 {
151 SetupCoeffs();
152
153 /*for (int n=0; n<FILTER_SECTIONS+1; n++)
154 {
155 iir.coef[n]=0;
156 iir.history[n]=0;
157 }*/
158 }
159
Randomise()160 void Filter::Randomise()
161 {
162 Q=RandFloat(1.0f,10.0f);
163 fc=RandFloat(10.0f,10000.0f);
164 m_RevCutoffMod=(RandFloat()>0.5f);
165 m_RevResonanceMod=(RandFloat()>0.5f);
166 }
167
168 istream &operator>>(istream &s, Filter &o)
169 {
170 s>>o.fc>>o.Q>>o.m_RevCutoffMod>>o.m_RevResonanceMod;
171 return s;
172 }
173
174 ostream &operator<<(ostream &s, Filter &o)
175 {
176 s<<o.fc<<" "<<o.Q<<" "<<o.m_RevCutoffMod<<" "<<o.m_RevResonanceMod<<" ";
177 return s;
178 }
179
180