LMMS
Loading...
Searching...
No Matches
FormantFilterGraph.cpp
Go to the documentation of this file.
1/*
2 ZynAddSubFX - a software synthesizer
3
4 FormantFilterGraph.cpp - OSC Formant Filter Graph View
5 Copyright (C) 2016 Mark McCurry
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11*/
12#include "FormantFilterGraph.H"
13#include <cmath>
14#include <cstdio>
15#include <cstdlib>
16
17FormantFilterGraph::FormantFilterGraph(int x,int y, int w, int h, const char *label)
18:Fl_Box(x,y,w,h,label), Fl_Osc_Widget(this)
19{
20 memset(Pvowels, 0, sizeof(Pvowels));
21 Pnumformants = 0;
22 Pstages = 0;
23 Pgain = 0;
24 Pcenterfreq = 0;
25 Pq = 0;
26 Poctavesfreq = 0;
30}
31
32void FormantFilterGraph::init(int *nvowel_,int *nformant_)
33{
34 nvowel=nvowel_;
35 nformant=nformant_;
36 graphpoints=new float [w()];
37
38 oscRegister("Pvowels");
39 oscRegister("Pnumformants");
40 oscRegister("Pstages");
41 oscRegister("Pcenterfreq");
42 oscRegister("Poctavesfreq");
43 oscRegister("Pgain");
44 oscRegister("Pq");
45}
46
47void FormantFilterGraph::OSC_value(int x, const char *loc)
48{
49 if(strstr(loc, "Pnumformants"))
51 else if(strstr(loc, "Pstages"))
52 Pstages = x;
53 else if(strstr(loc, "Pcenterfreq"))
54 Pcenterfreq = x;
55 else if(strstr(loc, "Pgain"))
56 Pgain = x;
57 else if(strstr(loc, "Pq"))
58 Pq = x;
59 else if(strstr(loc, "Poctavesfreq"))
61
62 redraw();
63}
64void FormantFilterGraph::OSC_value(unsigned x, void *v)
65{
66 assert(x = sizeof(Pvowels));
67 memcpy(&Pvowels[0], v, x);
68 redraw();
69}
70
72{
73 const float freqx=getfreqpos(freq);
74 switch(type){
75 case 0:fl_line_style(FL_SOLID);break;
76 case 1:fl_line_style(FL_DOT);break;
77 case 2:fl_line_style(FL_DASH);break;
78 };
79
80
81 if ((freqx>0.0)&&(freqx<1.0))
82 fl_line(x()+(int) (freqx*w()),y(),
83 x()+(int) (freqx*w()),y()+h());
84}
85
87{
88 oscWrite("Pvowels");
89 oscWrite("Pnumformants");
90 oscWrite("Pstages");
91 oscWrite("Pcenterfreq");
92 oscWrite("Poctavesfreq");
93 oscWrite("Pgain");
94 oscWrite("Pq");
95}
96
97void FormantFilterGraph::rebase(std::string new_base)
98{
99 osc->renameLink(loc+"Pvowels", new_base+"Pvowels", this);
100 osc->renameLink(loc+"Pnumformants", new_base+"Pnumformants", this);
101 osc->renameLink(loc+"Pstages", new_base+"Pstages", this);
102 osc->renameLink(loc+"Pcenterfreq", new_base+"Pcenterfreq", this);
103 osc->renameLink(loc+"Poctavesfreq", new_base+"Poctavesfreq", this);
104 osc->renameLink(loc+"Pgain", new_base+"Pgain", this);
105 osc->renameLink(loc+"Pq", new_base+"Pq", this);
106 loc = new_base;
107 update();
108}
109
110//TODO A good portion of this is copy/pasta from EnvelopUI's widget
111// REFACTOR!
113{
114 const int maxdB=30;
115 const int ox=x(),oy=y(),lx=w(),ly=h();
116
117 fl_color(FL_BLACK);
118 fl_rectf(ox,oy,lx,ly);
119
120
121 //draw the lines
122 fl_color(FL_GRAY);
123
124 fl_line_style(FL_SOLID);
125 //fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2);
126
127 const float freqx = getfreqpos(1000.0);
128 if ((freqx>0.0)&&(freqx<1.0))
129 fl_line(ox+(int) (freqx*lx),oy,
130 ox+(int) (freqx*lx),oy+ly);
131
132 for(int i=1;i<10;i++){
133 if(i==1){
134 draw_freq_line(i*100.0,0);
135 draw_freq_line(i*1000.0,0);
136 }else
137 if (i==5){
138 draw_freq_line(i*100.0,2);
139 draw_freq_line(i*1000.0,2);
140 }else{
141 draw_freq_line(i*100.0,1);
142 draw_freq_line(i*1000.0,1);
143 };
144 };
145
146 draw_freq_line(10000.0,0);
147 draw_freq_line(20000.0,1);
148
149 fl_line_style(FL_DOT);
150 int GY=10;if (ly<GY*3) GY=-1;
151 for (int i=1;i<GY;i++){
152 int tmp=(int)(ly/(float)GY*i);
153 fl_line(ox+2,oy+tmp,ox+lx-2,oy+tmp);
154 };
155
156 fl_color(FL_YELLOW);
157 fl_font(FL_HELVETICA,10);
158 if (*nformant < Pnumformants){
160
161 //show some information (like current formant frequency,amplitude)
162 char tmpstr[20];
163
164 snprintf(tmpstr,20,"%.2f kHz",getformantfreq(Pvowels[*nvowel].formants[*nformant].freq)*0.001);
165 fl_draw(tmpstr,ox+1,oy+1,40,12,FL_ALIGN_LEFT,NULL,0);
166
167 snprintf(tmpstr,20,"%d dB",(int)( rap2dB(1e-9 +
169 + getgain()));
170 fl_draw(tmpstr,ox+1,oy+15,40,12,FL_ALIGN_LEFT,NULL,0);
171
172 };
173
174 //draw the data
175
176 fl_color(FL_RED);
177 fl_line_style(FL_SOLID);
178
180
181 fl_line_style( FL_SOLID, 2 );
182 fl_begin_line();
183 int oiy=(int) ((graphpoints[0]/maxdB+1.0)*ly/2.0);
184 for(int i=1;i<lx;i++){
185 double iy= ((graphpoints[i]/maxdB+1.0)*ly/2.0);
186 if ((iy>=0)&&(oiy>=0)&&(iy<ly)&&(oiy<lx))
187 fl_vertex(ox+i,oy+ly-iy);
188 oiy=iy;
189 };
190 fl_end_line();
191 fl_line_style(FL_SOLID,0);
192}
193
198
199/*
200 * Parameter control
201 */
203{
204 return (Pgain / 64.0f - 1.0f) * 30.0f; //-30..30dB
205}
206
208{
209 return expf(powf((float) Pq / 127.0f, 2) * logf(1000.0f)) - 0.9f;
210}
211
212/*
213 * Get the center frequency of the formant's graph
214 */
216{
217 return 10000.0f * powf(10, -(1.0f - Pcenterfreq / 127.0f) * 2.0f);
218}
219
220/*
221 * Get the number of octave that the formant functions applies to
222 */
224{
225 return 0.25f + 10.0f * Poctavesfreq / 127.0f;
226}
227
228/*
229 * Get the frequency from x, where x is [0..1]
230 */
232{
233 if(x > 1.0f)
234 x = 1.0f;
235 float octf = powf(2.0f, getoctavesfreq());
236 return getcenterfreq() / sqrt(octf) * powf(octf, x);
237}
238
239/*
240 * Get the x coordinate from frequency (used by the UI)
241 */
243{
244 return (logf(freq) - logf(getfreqx(0.0f))) / logf(2.0f) / getoctavesfreq();
245}
246
247
248/*
249 * Get the freq. response of the formant filter
250 */
251void FormantFilterGraph::formantfilterH(int nvowel, int nfreqs, float *freqs)
252{
253 float c[3], d[3];
254
255 for(int i = 0; i < nfreqs; ++i)
256 freqs[i] = 0.0f;
257
258 //for each formant...
259 for(int nformant = 0; nformant < Pnumformants; ++nformant) {
260 //compute formant parameters(frequency,amplitude,etc.)
261 const float filter_freq = getformantfreq(Pvowels[nvowel].formants[nformant].freq);
262 float filter_q = getformantq(Pvowels[nvowel].formants[nformant].q) * getq();
263 if(Pstages > 0)
264 filter_q = (filter_q > 1.0f ? powf(filter_q, 1.0f / (Pstages + 1)) : filter_q);
265
266 const float filter_amp = getformantamp(Pvowels[nvowel].formants[nformant].amp);
267
268 //printf("NFORMANT %d\n", nformant);
269 //printf("CHARACTERISTICS: FREQ %f Q %f AMP %f\n", filter_freq, filter_q, filter_amp);
270 const float SampleRate = 48000.0f;
271
272
273 if(filter_freq <= (SampleRate / 2 - 100.0f)) {
274 const float omega = 2 * PI * filter_freq / SampleRate;
275 const float sn = sinf(omega);
276 const float cs = cosf(omega);
277 const float alpha = sn / (2 * filter_q);
278 const float tmp = 1 + alpha;
279 c[0] = alpha / tmp *sqrt(filter_q + 1);
280 c[1] = 0;
281 c[2] = -alpha / tmp *sqrt(filter_q + 1);
282 d[1] = -2 * cs / tmp * (-1);
283 d[2] = (1 - alpha) / tmp * (-1);
284 }
285 else
286 continue;
287
288
289 for(int i = 0; i < nfreqs; ++i) {
290 const float freq = getfreqx(i / (float) nfreqs);
291
292 //Discard frequencies above nyquist rate
293 if(freq > SampleRate / 2) {
294 for(int tmp = i; tmp < nfreqs; ++tmp)
295 freqs[tmp] = 0.0f;
296 break;
297 }
298
299 //Convert to normalized frequency
300 const float fr = freq / SampleRate * PI * 2.0f;
301
302 //Evaluate Complex domain ratio
303 float x = c[0], y = 0.0f;
304 for(int n = 1; n < 3; ++n) {
305 x += cosf(n * fr) * c[n];
306 y -= sinf(n * fr) * c[n];
307 }
308 float h = x * x + y * y;
309 x = 1.0f;
310 y = 0.0f;
311 for(int n = 1; n < 3; ++n) {
312 x -= cosf(n * fr) * d[n];
313 y += sinf(n * fr) * d[n];
314 }
315 h = h / (x * x + y * y);
316
317 freqs[i] += powf(h, (Pstages + 1.0f) / 2.0f) * filter_amp;
318 }
319 }
320
321 //Convert to logarithmic data ignoring points that are too small
322 for(int i = 0; i < nfreqs; ++i) {
323 if(freqs[i] > 0.000000001f)
324 freqs[i] = rap2dB(freqs[i]) + getgain();
325 else
326 freqs[i] = -90.0f;
327 }
328}
329
330/*
331 * Transforms a parameter to the real value
332 */
334{
335 return getfreqx(freq / 127.0f);
336}
337
339{
340 return powf(0.1f, (1.0f - amp / 127.0f) * 4.0f);
341}
342
344{
345 return powf(25.0f, (q - 32.0f) / 64.0f);
346}
#define rap2dB(rap)
Definition globals.h:222
#define NULL
Definition CarlaBridgeFormat.cpp:30
assert(0)
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
Fl_Osc_Interface * osc
Definition Fl_Osc_Widget.H:65
Fl_Osc_Widget(void)
Definition Fl_Osc_Widget.cpp:16
std::string loc
Definition Fl_Osc_Widget.H:62
void oscRegister(const char *path)
Definition Fl_Osc_Widget.cpp:91
void oscWrite(std::string path, const char *args,...)
Definition Fl_Osc_Widget.cpp:60
float getformantq(unsigned char q)
Definition FormantFilterGraph.cpp:343
struct FormantFilterGraph::@276341235027263032236322135165367072076106133072::@224335247260230213341307012271020267236073031375 formants[FF_MAX_FORMANTS]
float getoctavesfreq(void)
Definition FormantFilterGraph.cpp:223
void formantfilterH(int, int, float *)
Definition FormantFilterGraph.cpp:251
int Pgain
Definition FormantFilterGraph.H:58
void draw_freq_line(float freq, int type)
Definition FormantFilterGraph.cpp:71
void rebase(std::string new_base) override
Definition FormantFilterGraph.cpp:97
unsigned char freq
Definition FormantFilterGraph.H:51
unsigned char amp
Definition FormantFilterGraph.H:51
int Pq
Definition FormantFilterGraph.H:60
int * nvowel
Definition FormantFilterGraph.H:46
float getq(void)
Definition FormantFilterGraph.cpp:207
virtual ~FormantFilterGraph(void)
Definition FormantFilterGraph.cpp:194
float * graphpoints
Definition FormantFilterGraph.H:47
unsigned char q
Definition FormantFilterGraph.H:51
float getformantfreq(unsigned char)
Definition FormantFilterGraph.cpp:333
float getfreqx(float)
Definition FormantFilterGraph.cpp:231
void update(void)
Definition FormantFilterGraph.cpp:86
int * nformant
Definition FormantFilterGraph.H:46
FormantFilterGraph(int x, int y, int w, int h, const char *label=0)
Definition FormantFilterGraph.cpp:17
int Pcenterfreq
Definition FormantFilterGraph.H:57
struct FormantFilterGraph::@276341235027263032236322135165367072076106133072 Pvowels[FF_MAX_VOWELS]
void OSC_value(int x, const char *) override
Definition FormantFilterGraph.cpp:47
int Pnumformants
Definition FormantFilterGraph.H:55
float getgain(void)
Definition FormantFilterGraph.cpp:202
int Poctavesfreq
Definition FormantFilterGraph.H:61
float getformantamp(unsigned char)
Definition FormantFilterGraph.cpp:338
void draw()
Definition FormantFilterGraph.cpp:112
float getcenterfreq(void)
Definition FormantFilterGraph.cpp:215
void init(int *nvowel_, int *nformant_)
Definition FormantFilterGraph.cpp:32
float getfreqpos(float)
Definition FormantFilterGraph.cpp:242
int Pstages
Definition FormantFilterGraph.H:56
* e
Definition inflate.c:1404
UINT_D64 w
Definition inflate.c:942
int y
Definition inflate.c:1588
unsigned v[N_MAX]
Definition inflate.c:1584
unsigned d
Definition inflate.c:940
int lx[BMAX+1]
Definition inflate.c:1578
register unsigned i
Definition inflate.c:1575
unsigned x[BMAX+1]
Definition inflate.c:1586
#define PI
Definition eel_mdct.h:18
int n
Definition crypt.c:458
return c
Definition crypt.c:175
memcpy(hh, h, RAND_HEAD_LEN)
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
typedef int(UZ_EXP MsgFn)()