1 /*
2 ZynAddSubFX - a software synthesizer
3
4 FilterParams.C - Parameters for filter
5 Copyright (C) 2002-2005 Nasca Octavian Paul
6 Author: Nasca Octavian Paul
7
8
9 Modified for rakarrack by Josep Andreu
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of version 2 of the GNU General Public License
13 as published by the Free Software Foundation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License (version 2) for more details.
19
20 You should have received a copy of the GNU General Public License (version 2)
21 along with this program; if not, write to the Free Software Foundation,
22 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
24 */
25
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include "FilterParams.h"
30
FilterParams(unsigned char Ptype_,unsigned char Pfreq_,unsigned char Pq_,double sample_rate,uint32_t ibufsz)31 FilterParams::FilterParams (unsigned char Ptype_, unsigned char Pfreq_,
32 unsigned char Pq_, double sample_rate, uint32_t ibufsz)
33 {
34
35 // setpresettype("Pfilter");
36 Dtype = Ptype_;
37 Dfreq = Pfreq_;
38 Dq = Pq_;
39 SAMPLE_RATE = sample_rate;
40 fSAMPLE_RATE = sample_rate;
41 intermediate_bufsize = ibufsz;
42
43 changed = false;
44 defaults ();
45 };
46
~FilterParams()47 FilterParams::~FilterParams ()
48 {
49 };
50
51
52 void
defaults()53 FilterParams::defaults ()
54 {
55 Ptype = Dtype;
56 Pfreq = Dfreq;
57 Pq = Dq;
58
59 Pstages = 0;
60 Pfreqtrack = 64;
61 Pgain = 64;
62 Pcategory = 0;
63
64 Pnumformants = 3;
65 Pformantslowness = 64;
66 for (int j = 0; j < FF_MAX_VOWELS; j++) {
67 defaults (j);
68 };
69
70 Psequencesize = 3;
71 for (int i = 0; i < FF_MAX_SEQUENCE; i++)
72 Psequence[i].nvowel = (unsigned char) i % FF_MAX_VOWELS;
73
74 Psequencestretch = 40;
75 Psequencereversed = 0;
76 Pcenterfreq = 64; //1 kHz
77 Poctavesfreq = 64;
78 Pvowelclearness = 64;
79 };
80
81 void
defaults(int n)82 FilterParams::defaults (int n)
83 {
84 int j = n;
85 for (int i = 0; i < FF_MAX_FORMANTS; i++) {
86 Pvowels[j].formants[i].freq = (unsigned char) (RND*127.0); //some random freqs
87 Pvowels[j].formants[i].q = 64;
88 Pvowels[j].formants[i].amp = 127;
89 };
90 };
91
92
93 /*
94 * Get the parameters from other FilterParams
95 */
96
97 void
getfromFilterParams(FilterParams * pars)98 FilterParams::getfromFilterParams (FilterParams * pars)
99 {
100 defaults ();
101
102 if (pars == NULL)
103 return;
104
105 Ptype = pars->Ptype;
106 Pfreq = pars->Pfreq;
107 Pq = pars->Pq;
108
109 Pstages = pars->Pstages;
110 Pfreqtrack = pars->Pfreqtrack;
111 Pgain = pars->Pgain;
112 Pcategory = pars->Pcategory;
113
114 Pnumformants = pars->Pnumformants;
115 Pformantslowness = pars->Pformantslowness;
116 for (int j = 0; j < FF_MAX_VOWELS; j++) {
117 for (int i = 0; i < FF_MAX_FORMANTS; i++) {
118 Pvowels[j].formants[i].freq = pars->Pvowels[j].formants[i].freq;
119 Pvowels[j].formants[i].q = pars->Pvowels[j].formants[i].q;
120 Pvowels[j].formants[i].amp = pars->Pvowels[j].formants[i].amp;
121 };
122 };
123
124 Psequencesize = pars->Psequencesize;
125 for (int i = 0; i < FF_MAX_SEQUENCE; i++)
126 Psequence[i].nvowel = pars->Psequence[i].nvowel;
127
128 Psequencestretch = pars->Psequencestretch;
129 Psequencereversed = pars->Psequencereversed;
130 Pcenterfreq = pars->Pcenterfreq;
131 Poctavesfreq = pars->Poctavesfreq;
132 Pvowelclearness = pars->Pvowelclearness;
133 };
134
135
136 /*
137 * Parameter control
138 */
getfreq()139 float FilterParams::getfreq ()
140 {
141 return (((float)Pfreq / 64.0f - 1.0f) * 5.0f);
142 };
143
getq()144 float FilterParams::getq ()
145 {
146 return (expf (powf ((float) Pq / 127.0f, 2) * logf (1000.0f)) - 0.9f);
147 };
148
getfreqtracking(float notefreq)149 float FilterParams::getfreqtracking (float notefreq)
150 {
151 return (logf (notefreq / 440.0f) * ((float)Pfreqtrack - 64.0f) / (64.0f * LOG_2));
152 };
153
getgain()154 float FilterParams::getgain ()
155 {
156 return (((float)Pgain / 64.0f - 1.0f) * 30.0f); //-30..30dB
157 };
158
159 /*
160 * Get the center frequency of the formant's graph
161 */
getcenterfreq()162 float FilterParams::getcenterfreq ()
163 {
164 return (10000.0f * powf (10.0f, -(1.0f - (float)Pcenterfreq / 127.0f) * 2.0f));
165 };
166
167 /*
168 * Get the number of octave that the formant functions applies to
169 */
getoctavesfreq()170 float FilterParams::getoctavesfreq ()
171 {
172 return (0.25f + 10.0f * (float)Poctavesfreq / 127.0f);
173 };
174
175 /*
176 * Get the frequency from x, where x is [0..1]
177 */
getfreqx(float x)178 float FilterParams::getfreqx (float x)
179 {
180 if (x > 1.0)
181 x = 1.0f;
182 float
183 octf = powf (2.0f, getoctavesfreq ());
184 return (getcenterfreq () / sqrtf (octf) * powf (octf, x));
185 };
186
187 /*
188 * Get the x coordinate from frequency (used by the UI)
189 */
getfreqpos(float freq)190 float FilterParams::getfreqpos (float freq)
191 {
192 return ((logf (freq) -
193 logf (getfreqx (0.0))) / logf (2.0f) / getoctavesfreq ());
194 };
195
196
197 /*
198 * Get the freq. response of the formant filter
199 */
200 void
formantfilterH(int nvowel,int nfreqs,float * freqs)201 FilterParams::formantfilterH (int nvowel, int nfreqs, float * freqs)
202 {
203 float c[3], d[3];
204 float filter_freq, filter_q, filter_amp;
205 float omega, sn, cs, alpha;
206
207 for (int i = 0; i < nfreqs; i++)
208 freqs[i] = 0.0;
209
210 //for each formant...
211 for (int nformant = 0; nformant < Pnumformants; nformant++) {
212 //compute formant parameters(frequency,amplitude,etc.)
213 filter_freq = getformantfreq (Pvowels[nvowel].formants[nformant].freq);
214 filter_q = getformantq (Pvowels[nvowel].formants[nformant].q) * getq ();
215 if (Pstages > 0)
216 filter_q =
217 (filter_q > 1.0 ? powf (filter_q, 1.0f / ((float)Pstages + 1)) : filter_q);
218
219 filter_amp = getformantamp (Pvowels[nvowel].formants[nformant].amp);
220
221
222 if (filter_freq <= (SAMPLE_RATE / 2 - 100.0)) {
223 omega = 2.0f * PI * filter_freq / fSAMPLE_RATE;
224 sn = sinf (omega);
225 cs = cosf (omega);
226 alpha = sn / (2.0f * filter_q);
227 float tmp = 1.0f + alpha;
228 c[0] = alpha / tmp * sqrtf (filter_q + 1.0f);
229 c[1] = 0;
230 c[2] = -alpha / tmp * sqrtf (filter_q + 1.0f);
231 d[1] = -2.0f * cs / tmp * (-1.0f);
232 d[2] = (1.0f - alpha) / tmp * (-1.0f);
233 } else
234 continue;
235
236
237 for (int i = 0; i < nfreqs; i++) {
238 float freq = getfreqx ((float)i / (float) nfreqs);
239 if (freq > SAMPLE_RATE / 2) {
240 for (int tmp = i; tmp < nfreqs; tmp++)
241 freqs[tmp] = 0.0;
242 break;
243 };
244 float fr = freq / fSAMPLE_RATE * PI * 2.0f;
245 float x = c[0], y = 0.0f;
246 for (int n = 1; n < 3; n++) {
247 x += cosf ((float)n * fr) * c[n];
248 y -= sinf ((float)n * fr) * c[n];
249 };
250 float h = x * x + y * y;
251 x = 1.0f;
252 y = 0.0;
253 for (int n = 1; n < 3; n++) {
254 x -= cosf ((float)n * fr) * d[n];
255 y += sinf ((float)n * fr) * d[n];
256 };
257 h = h / (x * x + y * y);
258
259 freqs[i] += powf (h, ((float)Pstages + 1.0f) / 2.0f) * filter_amp;
260 };
261 };
262 for (int i = 0; i < nfreqs; i++) {
263 if (freqs[i] > 0.000000001f)
264 freqs[i] = rap2dB (freqs[i]) + getgain ();
265 else
266 freqs[i] = -90.0f;
267 };
268
269 };
270
271 /*
272 * Transforms a parameter to the real value
273 */
getformantfreq(unsigned char freq)274 float FilterParams::getformantfreq (unsigned char freq)
275 {
276 float
277 result = getfreqx ((float)freq / 127.0f);
278 return (result);
279 };
280
getformantamp(unsigned char amp)281 float FilterParams::getformantamp (unsigned char amp)
282 {
283 float
284 result = powf (0.1f, (1.0f - (float)amp / 127.0f) * 4.0f);
285 return (result);
286 };
287
getformantq(unsigned char q)288 float FilterParams::getformantq (unsigned char q)
289 {
290 //temp
291 float
292 result = powf (25.0f, ((float)q - 32.0f) / 64.0f);
293 return (result);
294 };
295