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