1 /*
2   ZynAddSubFX - a software synthesizer
3 
4   FormantFilter.C - formant filters
5   Copyright (C) 2002-2005 Nasca Octavian Paul
6   Author: Nasca Octavian Paul
7 
8   Modified for rakarrack by Josep Andreu
9 
10   This program is free software; you can redistribute it and/or modify
11   it under the terms of version 2 of the GNU General Public License
12   as published by the Free Software Foundation.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License (version 2) for more details.
18 
19   You should have received a copy of the GNU General Public License (version 2)
20   along with this program; if not, write to the Free Software Foundation,
21   Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22 
23 */
24 
25 #include <math.h>
26 #include <stdio.h>
27 #include "FormantFilter.h"
28 
FormantFilter(FilterParams * pars,float * interpbuf)29 FormantFilter::FormantFilter (FilterParams * pars, float* interpbuf)
30 {
31     numformants = pars->Pnumformants;
32     for (unsigned int i = 0; i < numformants; i++)
33         formant[i] = new AnalogFilter (4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages, pars->fSAMPLE_RATE, interpbuf);
34     cleanup ();
35     inbuffer = new float[pars->intermediate_bufsize];
36     tmpbuf = new float[pars->intermediate_bufsize];
37 
38     for (int j = 0; j < FF_MAX_VOWELS; j++)
39         for (unsigned int i = 0; i < numformants; i++) {
40             formantpar[j][i].freq =
41                 pars->getformantfreq (pars->Pvowels[j].formants[i].freq);
42             formantpar[j][i].amp =
43                 pars->getformantamp (pars->Pvowels[j].formants[i].amp);
44             formantpar[j][i].q =
45                 pars->getformantq (pars->Pvowels[j].formants[i].q);
46         };
47     for (int i = 0; i < FF_MAX_FORMANTS; i++)
48         oldformantamp[i] = 1.0;
49     for (unsigned int i = 0; i < numformants; i++) {
50         currentformants[i].freq = 1000.0f;
51         currentformants[i].amp = 1.0f;
52         currentformants[i].q = 2.0f;
53     };
54 
55     formantslowness = powf (1.0f - ((float)pars->Pformantslowness / 128.0f), 3.0f);
56 
57     sequencesize = pars->Psequencesize;
58     if (sequencesize == 0)
59         sequencesize = 1;
60     for (unsigned int k = 0; k < sequencesize; k++)
61         sequence[k].nvowel = pars->Psequence[k].nvowel;
62 
63     vowelclearness = powf (10.0f, ((float)pars->Pvowelclearness - 32.0f) / 48.0f);
64 
65     sequencestretch = powf (0.1f, ((float)pars->Psequencestretch - 32.0f) / 48.0f);
66     if (pars->Psequencereversed)
67         sequencestretch *= -1.0f;
68 
69     outgain = dB2rap (pars->getgain ());
70 
71     oldinput = -1.0f;
72     Qfactor = 1.0f;
73     oldQfactor = Qfactor;
74     firsttime = 1;
75 };
76 
~FormantFilter()77 FormantFilter::~FormantFilter ()
78 {
79     for (unsigned int i = 0; i < numformants; i++)
80         delete (formant[i]);
81     delete (inbuffer);
82     delete (tmpbuf);
83 };
84 
85 
86 
87 
88 void
cleanup()89 FormantFilter::cleanup ()
90 {
91     for (unsigned int i = 0; i < numformants; i++)
92         formant[i]->cleanup ();
93 };
94 
95 void
setpos(float input)96 FormantFilter::setpos (float input)
97 {
98     int p1, p2;
99 
100     if (firsttime != 0)
101         slowinput = input;
102     else
103         slowinput = slowinput * (1.0f - formantslowness) + input * formantslowness;
104 
105     if ((fabsf (oldinput - input) < 0.001)
106             && (fabsf (slowinput - input) < 0.001)
107             && (fabsf (Qfactor - oldQfactor) < 0.001)) {
108 //      oldinput=input; daca setez asta, o sa faca probleme la schimbari foarte lente
109         firsttime = 0;
110         return;
111     } else
112         oldinput = input;
113 
114 
115     float pos = fmodf (input * sequencestretch, 1.0f);
116     if (pos < 0.0)
117         pos += 1.0f;
118 
119     F2I (pos * (float)sequencesize, p2);
120     p1 = p2 - 1;
121     if (p1 < 0)
122         p1 += sequencesize;
123 
124     pos = fmodf (pos * (float)sequencesize, 1.0f);
125     if (pos < 0.0)
126         pos = 0.0f;
127     else if (pos > 1.0)
128         pos = 1.0f;
129     pos =
130         (atanf ((pos * 2.0f - 1.0f) * vowelclearness) / atanf (vowelclearness) +
131          1.0f) * 0.5f;
132 
133     p1 = sequence[p1].nvowel;
134     p2 = sequence[p2].nvowel;
135 
136     if (firsttime != 0) {
137         for (unsigned int i = 0; i < numformants; i++) {
138             currentformants[i].freq =
139                 formantpar[p1][i].freq * (1.0f - pos) +
140                 formantpar[p2][i].freq * pos;
141             currentformants[i].amp =
142                 formantpar[p1][i].amp * (1.0f - pos) + formantpar[p2][i].amp * pos;
143             currentformants[i].q =
144                 formantpar[p1][i].q * (1.0f - pos) + formantpar[p2][i].q * pos;
145             formant[i]->setfreq_and_q (currentformants[i].freq,
146                                        currentformants[i].q * Qfactor);
147             oldformantamp[i] = currentformants[i].amp;
148         };
149         firsttime = 0;
150     } else {
151         for (unsigned int i = 0; i < numformants; i++) {
152             currentformants[i].freq =
153                 currentformants[i].freq * (1.0f - formantslowness) +
154                 (formantpar[p1][i].freq * (1.0f - pos) +
155                  formantpar[p2][i].freq * pos) * formantslowness;
156 
157             currentformants[i].amp =
158                 currentformants[i].amp * (1.0f - formantslowness) +
159                 (formantpar[p1][i].amp * (1.0f - pos) +
160                  formantpar[p2][i].amp * pos) * formantslowness;
161 
162             currentformants[i].q =
163                 currentformants[i].q * (1.0f - formantslowness) +
164                 (formantpar[p1][i].q * (1.0f - pos) +
165                  formantpar[p2][i].q * pos) * formantslowness;
166 
167             formant[i]->setfreq_and_q (currentformants[i].freq,
168                                        currentformants[i].q * Qfactor);
169         };
170     };
171 
172     oldQfactor = Qfactor;
173 };
174 
175 void
setfreq(float frequency)176 FormantFilter::setfreq (float frequency)
177 {
178     setpos (frequency);
179 };
180 
181 void
setq(float q_)182 FormantFilter::setq (float q_)
183 {
184     Qfactor = q_;
185     for (unsigned int i = 0; i < numformants; i++)
186         formant[i]->setq (Qfactor * currentformants[i].q);
187 };
188 
189 void
setfreq_and_q(float frequency,float q_)190 FormantFilter::setfreq_and_q (float frequency, float q_)
191 {
192     Qfactor = q_;
193     setpos (frequency);
194 };
195 
196 
197 void
filterout(float * smp,uint32_t period)198 FormantFilter::filterout (float * smp, uint32_t period)
199 {
200     unsigned int i, j;
201     for (i = 0; i < period; i++) {
202         inbuffer[i] = smp[i];
203         smp[i] = 0.0;
204     };
205 
206     for (j = 0; j < numformants; j++) {
207         for (i = 0; i < period; i++)
208             tmpbuf[i] = inbuffer[i] * outgain;
209         formant[j]->filterout (tmpbuf, period);
210 
211         if (ABOVE_AMPLITUDE_THRESHOLD
212                 (oldformantamp[j], currentformants[j].amp))
213             for (i = 0; i < period; i++)
214                 smp[i] +=
215                     tmpbuf[i] * INTERPOLATE_AMPLITUDE (oldformantamp[j],
216                                                        currentformants[j].amp, i,
217                                                        period);
218         else
219             for (i = 0; i < period; i++)
220                 smp[i] += tmpbuf[i] * currentformants[j].amp;
221         oldformantamp[j] = currentformants[j].amp;
222     };
223 };
224