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