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