2 ZynAddSubFX - a software synthesizer
4 FilterParams.cpp - Parameters for filter
5 Copyright (C) 2002-2005 Nasca Octavian Paul
6 Copyright (C) 2017 Mark McCurry
7 Author: Nasca Octavian Paul
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
16 #include "FilterParams.h"
17 #include "../Misc/Util.h"
18 #include "../Misc/Time.h"
19 #include "../DSP/AnalogFilter.h"
20 #include "../DSP/SVFilter.h"
25 #include <rtosc/rtosc.h>
26 #include <rtosc/ports.h>
27 #include <rtosc/port-sugar.h>
28 using namespace rtosc
;
32 // g++ 4.8 needs this variable saved separately, otherwise it segfaults
33 constexpr int sizeof_pvowels
= sizeof(FilterParams::Pvowels
);
35 #define rObject FilterParams::Pvowels_t::formants_t
37 static const rtosc::Ports subsubports
= {
38 rParamZyn(freq
, rShort("f.freq"), "Formant frequency"),
39 rParamZyn(amp
, rShort("f.str"), rDefault(127), "Strength of formant"),
40 rParamZyn(q
, rShort("f.q"), rDefault(64),
41 "The formant's quality factor, also known as "
42 "resonance bandwidth or Q for short"),
46 static const rtosc::Ports subports
= {
47 {"Pformants#" STRINGIFY(FF_MAX_FORMANTS
) "/", NULL
, &subsubports
,
48 [](const char *msg
, RtData
&d
) {
50 while(*mm
&& !isdigit(*mm
)) ++mm
;
51 unsigned idx
= atoi(mm
);
54 FilterParams::Pvowels_t
*obj
= (FilterParams::Pvowels_t
*) d
.obj
;
55 d
.obj
= (void*) &obj
->formants
[idx
];
56 subsubports
.dispatch(msg
, d
);
60 #define rObject FilterParams
62 #define rChangeCb do { obj->changed = true; if ( obj->time) { \
63 obj->last_update_timestamp = obj->time->time(); } } while(false)
64 const rtosc::Ports
FilterParams::ports
= {
68 rOption(loc
, rProp(internal
),
69 rOptions(ad_global_filter
, ad_voice_filter
, sub_filter
, in_effect
),
70 "location of the filter"),
71 rOption(Pcategory
, rShort("class"),
72 rOptions(analog
, formant
, st
.var
.), rDefault(analog
),
74 rOption(Ptype
, rShort("type"),
75 rOptions(LP1
, HP1
, LP2
, HP2
, BP
, notch
, peak
, l
.shelf
, h
.shelf
),
76 rDefault(LP2
), "Filter Type"),
77 rParamI(Pstages
, rShort("stages"),
78 rLinear(0,5), rDefault(0), "Filter Stages"),
79 rParamF(baseq
, rShort("q"), rUnit(none
), rLog(0.1, 1000),
81 rPreset(ad_global_filter
, 0x1.1592acp
+0),
82 rPreset(ad_voice_filter
, 0x1.e2f3ap
+1),
83 rPreset(sub_filter
, 0x1.1592acp
+0),
84 rPreset(in_effect
, 0x1.384298p
+2),
85 "Quality Factor (resonance/bandwidth)"),
86 rParamF(basefreq
, rShort("cutoff"),
87 rUnit(Hz
), rLog(31.25, 32000),
89 rPreset(ad_global_filter
, 32000),
90 rPreset(ad_voice_filter
, 32000),
91 rPreset(sub_filter
, 32000),
92 rPreset(in_effect
, 0x1.f3fffcp
+9),
93 "Base cutoff frequency"),
94 rParamF(freqtracking
, rShort("f.track"), rUnit(%),
95 rLinear(-100, 100), rDefault(0.0f
),
96 "Frequency Tracking amount"),
97 rParamF(gain
, rShort("gain"), rUnit(dB
),
98 rLinear(-30, 30), rDefault(0.0f
),
100 rParamI(Pnumformants
, rShort("formants"),
101 rLinear(1,12), rDefault(3),
102 "Number of formants to be used"),
103 rParamZyn(Pformantslowness
, rShort("slew"),
104 rDefault(64), "Rate that formants change"),
105 rParamZyn(Pvowelclearness
, rShort("clarity"), rDefault(64),
106 "How much each vowel is smudged with the next in sequence. A high clarity will avoid smudging."),
107 rParamZyn(Pcenterfreq
, rShort("cutoff"), rDefault(64),
108 "Center Freq (formant)"),
109 rParamZyn(Poctavesfreq
, rShort("octaves"), rDefault(64),
110 "Number of octaves for formant"),
112 rParamI(Psequencesize
, rShort("seq.size"),
113 rLinear(0, FF_MAX_SEQUENCE
), rDefault(3), "Length of vowel sequence"),
114 rParamZyn(Psequencestretch
, rShort("seq.str"),
115 rDefault(40), "How modulators stretch the sequence"),
116 rToggle(Psequencereversed
, rShort("reverse"),
117 rDefault(false), "If the modulator input is inverted"),
119 {"vowel_seq#" STRINGIFY(FF_MAX_SEQUENCE
) "::i", rShort("vowel") rDoc("Vowel number of this sequence position"), NULL
,
120 [](const char *msg
, RtData
&d
){
121 FilterParams
*obj
= (FilterParams
*) d
.obj
;
122 const char *mm
= msg
;
123 while(*mm
&& !isdigit(*mm
)) ++mm
;
124 unsigned idx
= atoi(mm
);
125 if(rtosc_narguments(msg
)) {
126 obj
->Psequence
[idx
].nvowel
= rtosc_argument(msg
, 0).i
;
127 d
.broadcast(d
.loc
, "i", obj
->Psequence
[idx
].nvowel
);
129 d
.reply(d
.loc
, "i", obj
->Psequence
[idx
].nvowel
);
131 {"type-svf::i", rProp(parameter
) rShort("type")
132 rOptions(low
, high
, band
, notch
)
133 rDoc("Filter Type"), 0, rOptionCb(Ptype
)},
136 {"Pvowels:", rDoc("Get Formant Vowels"), NULL
,
137 [](const char *, RtData
&d
) {
138 FilterParams
*obj
= (FilterParams
*) d
.obj
;
139 d
.reply(d
.loc
, "b", sizeof_pvowels
, obj
->Pvowels
);
142 rEnabledCondition(is_formant_filter
, obj
->Pcategory
== 1),
143 {"Pvowels#" STRINGIFY(FF_MAX_VOWELS
) "/",
144 rEnabledByCondition(is_formant_filter
),
146 [](const char *msg
, RtData
&d
) {
147 const char *mm
= msg
;
148 while(*mm
&& !isdigit(*mm
)) ++mm
;
149 unsigned idx
= atoi(mm
);
152 FilterParams
*obj
= (FilterParams
*) d
.obj
;
153 d
.obj
= (void*)&obj
->Pvowels
[idx
];
154 subports
.dispatch(msg
, d
);
156 if(rtosc_narguments(msg
))
159 {"centerfreq:", rDoc("Get the center frequency of the formant's graph"),
160 NULL
, [](const char *, RtData
&d
) {
161 FilterParams
*obj
= (FilterParams
*) d
.obj
;
162 d
.reply(d
.loc
, "f", obj
->getcenterfreq());
165 rDoc("Get the number of octave that the formant functions applies to"),
166 NULL
, [](const char *, RtData
&d
) {
167 FilterParams
*obj
= (FilterParams
*) d
.obj
;
168 d
.reply(d
.loc
, "f", obj
->getoctavesfreq());
171 rDoc("Q value for UI Response Graphs"),
172 NULL
, [](const char *, RtData
&d
) {
173 FilterParams
*obj
= (FilterParams
*) d
.obj
;
174 d
.reply(d
.loc
, "f", obj
->getq());
177 rDoc("Get a frequency response"),
178 NULL
, [](const char *, RtData
&d
) {
179 FilterParams
*obj
= (FilterParams
*) d
.obj
;
180 if(obj
->Pcategory
== 0) {
182 float gain
= dB2rap(obj
->getgain());
183 if(obj
->Ptype
!= 6 && obj
->Ptype
!= 7 && obj
->Ptype
!= 8)
185 auto cf
= AnalogFilter::computeCoeff(obj
->Ptype
,
186 Filter::getrealfreq(obj
->getfreq()),
187 obj
->getq(), obj
->Pstages
,
190 d
.reply(d
.loc
, "fffffff",
192 cf
.c
[0], cf
.c
[1], cf
.c
[2],
193 0.0, cf
.d
[1], cf
.d
[2]);
194 } else if(order
== 1) {
195 d
.reply(d
.loc
, "fffff",
200 } else if(obj
->Pcategory
== 2) {
201 float gain
= dB2rap(obj
->getgain());
202 auto cf
= SVFilter::computeResponse(obj
->Ptype
,
203 Filter::getrealfreq(obj
->getfreq()),
204 obj
->getq(), obj
->Pstages
,
206 d
.reply(d
.loc
, "fffffff",
208 cf
.b
[0], cf
.b
[1], cf
.b
[2],
209 0.0, -cf
.a
[1], -cf
.a
[2]);
212 // "", NULL, [](){}},"/freq"
213 //{"Pvowels#" FF_MAX_VOWELS "/formants#" FF_MAX_FORMANTS "/amp",
214 // "", NULL, [](){}},
215 //{"Pvowels#" FF_MAX_VOWELS "/formants#" FF_MAX_FORMANTS "/q",
216 // "", NULL, [](){}},
219 // struct formants_t {
220 // unsigned char freq, amp, q; //frequency,amplitude,Q
221 // } formants[FF_MAX_FORMANTS];
222 //} Pvowels[FF_MAX_VOWELS];
224 rDoc("Get info for formant graph"),
225 NULL
, [](const char *, RtData
&d
) {
226 FilterParams
*obj
= (FilterParams
*) d
.obj
;
228 rtosc_arg_t args
[2+3*FF_MAX_FORMANTS
*FF_MAX_VOWELS
];
229 char type
[2+3*FF_MAX_FORMANTS
*FF_MAX_VOWELS
+ 1] = {};
234 args
[0].i
= FF_MAX_VOWELS
;
235 args
[1].i
= FF_MAX_FORMANTS
;
238 for(int i
=0; i
<FF_MAX_VOWELS
; ++i
) {
239 auto &val
= obj
->Pvowels
[i
];
240 for(int j
=0; j
<FF_MAX_FORMANTS
; ++j
) {
241 auto &f
= val
.formants
[j
];
242 //each formant is 3 arguments
243 //each vowel is FF_MAX_FORMANTS * length of formants long
244 auto *a
= args
+ i
*FF_MAX_FORMANTS
*3 + j
*3 + 2;
245 auto *t
= type
+ i
*FF_MAX_FORMANTS
*3 + j
*3 + 2;
246 a
[0].f
= obj
->getformantfreq(f
.freq
);
247 a
[1].f
= obj
->getformantamp(f
.amp
);
248 a
[2].f
= obj
->getformantq(f
.q
);
249 //printf("<%d,%d,%d,%d,%d,%f,%f,%f>\n", i, j, f.freq, f.amp, f.q, a[0].f, a[1].f, a[2].f);
250 t
[0] = t
[1] = t
[2] = 'f';
253 d
.replyArray(d
.loc
, type
, args
);
256 //Old 0..127 parameter mappings
257 {"Pfreq::i", rLinear(0, 127) rShort("cutoff") rProp(deprecated
) rDoc("Center Freq"), 0,
258 [](const char *msg
, RtData
&d
) {
259 FilterParams
*obj
= (FilterParams
*)d
.obj
;
260 if(rtosc_narguments(msg
)) {
261 int Pfreq
= rtosc_argument(msg
, 0).i
;
262 obj
->basefreq
= (Pfreq
/ 64.0f
- 1.0f
) * 5.0f
;
263 obj
->basefreq
= powf(2.0f
, obj
->basefreq
+ 9.96578428f
);
265 d
.broadcast(d
.loc
, "i", Pfreq
);
267 float tmp
= obj
->basefreq
;
268 tmp
= log2f(tmp
) - 9.96578428f
;
269 tmp
= (tmp
/ 5.0 + 1.0) * 64.0f
;
270 int Pfreq
= roundf(tmp
);
271 d
.reply(d
.loc
, "i", Pfreq
);
274 {"Pfreqtrack::i", rLinear(0, 127) rShort("f.track") rProp(deprecated
) rDoc("Frequency Tracking amount"), 0,
275 [](const char *msg
, RtData
&d
) {
276 FilterParams
*obj
= (FilterParams
*)d
.obj
;
277 if(rtosc_narguments(msg
)) {
278 int Pfreqtracking
= rtosc_argument(msg
, 0).i
;
279 obj
->freqtracking
= 100 * (Pfreqtracking
- 64.0f
) / (64.0f
);
281 d
.broadcast(d
.loc
, "i", Pfreqtracking
);
283 int Pfreqtracking
= obj
->freqtracking
/100.0*64.0 + 64.0;
284 d
.reply(d
.loc
, "i", Pfreqtracking
);
287 {"Pgain::i", rLinear(0, 127) rShort("gain") rProp(deprecated
) rDoc("Output Gain"), 0,
288 [](const char *msg
, RtData
&d
) {
289 FilterParams
*obj
= (FilterParams
*)d
.obj
;
290 if(rtosc_narguments(msg
)) {
291 int Pgain
= rtosc_argument(msg
, 0).i
;
292 obj
->gain
= (Pgain
/ 64.0f
- 1.0f
) * 30.0f
; //-30..30dB
294 d
.broadcast(d
.loc
, "i", Pgain
);
296 int Pgain
= roundf((obj
->gain
/30.0f
+ 1.0f
) * 64.0f
);
297 d
.reply(d
.loc
, "i", Pgain
);
300 {"Pq::i", rLinear(0,127) rShort("q") rProp(deprecated
)
301 rDoc("Quality Factor (resonance/bandwidth)"), 0,
302 [](const char *msg
, RtData
&d
) {
303 FilterParams
*obj
= (FilterParams
*)d
.obj
;
304 if(rtosc_narguments(msg
)) {
305 int Pq
= rtosc_argument(msg
, 0).i
;
306 obj
->baseq
= expf(powf((float) Pq
/ 127.0f
, 2) * logf(1000.0f
)) - 0.9f
;
308 d
.broadcast(d
.loc
, "i", Pq
);
310 int Pq
= roundf(127.0f
* sqrtf(logf(0.9f
+ obj
->baseq
)/logf(1000.0f
)));
311 d
.reply(d
.loc
, "i", Pq
);
320 void FilterParams::setup()
322 setpresettype("Pfilter");
328 FilterParams::FilterParams(const AbsTime
*time_
)
329 :FilterParams(in_effect
, time_
)
333 FilterParams::FilterParams(unsigned char Ptype_
,
334 unsigned char Pfreq_
,
336 consumer_location_t loc
,
337 const AbsTime
*time_
):
338 loc(loc
), time(time_
), last_update_timestamp(0),
339 Dtype(Ptype_
), Dfreq(Pfreq_
), Dq(Pq_
)
344 FilterParams::FilterParams(consumer_location_t loc
,
345 const AbsTime
*time_
):
346 loc(loc
), time(time_
), last_update_timestamp(0)
349 [&](unsigned char Ptype_
, unsigned char Pfreq_
, unsigned char Pq_
)
358 case ad_global_filter
: init(2, 127, 40); break;
359 case ad_voice_filter
: init(2, 127, 60); break;
360 case sub_filter
: init(2, 127, 40); break;
361 case in_effect
: init(0, 64, 64); break;
362 default: throw std::logic_error("Invalid filter consumer location");
368 FilterParams::~FilterParams()
372 void FilterParams::defaults()
379 basefreq
= (Pfreq
/ 64.0f
- 1.0f
) * 5.0f
;
380 basefreq
= powf(2.0f
, basefreq
+ 9.96578428f
);
381 baseq
= expf(powf((float) Pq
/ 127.0f
, 2) * logf(1000.0f
)) - 0.9f
;
389 Pformantslowness
= 64;
390 for(int j
= 0; j
< FF_MAX_VOWELS
; ++j
)
395 for(int i
= 0; i
< FF_MAX_SEQUENCE
; ++i
)
396 Psequence
[i
].nvowel
= i
% FF_MAX_VOWELS
;
398 Psequencestretch
= 40;
399 Psequencereversed
= 0;
400 Pcenterfreq
= 64; //1 kHz
402 Pvowelclearness
= 64;
405 void FilterParams::defaults(int n
)
409 for(int i
= 0; i
< FF_MAX_FORMANTS
; ++i
) {
410 Pvowels
[j
].formants
[i
].freq
= (int)(RND
* 127.0f
); //some random freqs
411 Pvowels
[j
].formants
[i
].q
= 64;
412 Pvowels
[j
].formants
[i
].amp
= 127;
418 * Get the parameters from other FilterParams
420 // WARNING! Function unused since 2004, see declaration in header
421 void FilterParams::getfromFilterParams(const FilterParams
*pars
)
432 Pstages
= pars
->Pstages
;
433 freqtracking
= pars
->freqtracking
;
435 Pcategory
= pars
->Pcategory
;
437 Pnumformants
= pars
->Pnumformants
;
438 Pformantslowness
= pars
->Pformantslowness
;
439 for(int j
= 0; j
< FF_MAX_VOWELS
; ++j
)
440 for(int i
= 0; i
< FF_MAX_FORMANTS
; ++i
) {
441 Pvowels
[j
].formants
[i
].freq
= pars
->Pvowels
[j
].formants
[i
].freq
;
442 Pvowels
[j
].formants
[i
].q
= pars
->Pvowels
[j
].formants
[i
].q
;
443 Pvowels
[j
].formants
[i
].amp
= pars
->Pvowels
[j
].formants
[i
].amp
;
446 Psequencesize
= pars
->Psequencesize
;
447 for(int i
= 0; i
< FF_MAX_SEQUENCE
; ++i
)
448 Psequence
[i
].nvowel
= pars
->Psequence
[i
].nvowel
;
450 Psequencestretch
= pars
->Psequencestretch
;
451 Psequencereversed
= pars
->Psequencereversed
;
452 Pcenterfreq
= pars
->Pcenterfreq
;
453 Poctavesfreq
= pars
->Poctavesfreq
;
454 Pvowelclearness
= pars
->Pvowelclearness
;
461 float FilterParams::getfreq() const
463 return log2(basefreq
) - log2f(1000.0f
);
466 float FilterParams::getq() const
470 float FilterParams::getfreqtracking(float notefreq
) const
472 return log2f(notefreq
/ 440.0f
) * (freqtracking
/ 100.0f
);
475 float FilterParams::getgain() const
481 * Get the center frequency of the formant's graph
483 float FilterParams::getcenterfreq() const
485 return 10000.0f
* powf(10, -(1.0f
- Pcenterfreq
/ 127.0f
) * 2.0f
);
489 * Get the number of octave that the formant functions applies to
491 float FilterParams::getoctavesfreq() const
493 return 0.25f
+ 10.0f
* Poctavesfreq
/ 127.0f
;
497 * Get the frequency from x, where x is [0..1]
499 float FilterParams::getfreqx(float x
) const
503 float octf
= powf(2.0f
, getoctavesfreq());
504 return getcenterfreq() / sqrt(octf
) * powf(octf
, x
);
508 * Get the x coordinate from frequency (used by the UI)
510 float FilterParams::getfreqpos(float freq
) const
512 return (logf(freq
) - logf(getfreqx(0.0f
))) / logf(2.0f
) / getoctavesfreq();
516 * Transforms a parameter to the real value
518 float FilterParams::getformantfreq(unsigned char freq
) const
520 return getfreqx(freq
/ 127.0f
);
523 float FilterParams::getformantamp(unsigned char amp
) const
525 return powf(0.1f
, (1.0f
- amp
/ 127.0f
) * 4.0f
);
528 float FilterParams::getformantq(unsigned char q
) const
531 return powf(25.0f
, (q
- 32.0f
) / 64.0f
);
536 void FilterParams::add2XMLsection(XMLwrapper
& xml
, int n
)
539 for(int nformant
= 0; nformant
< FF_MAX_FORMANTS
; ++nformant
) {
540 xml
.beginbranch("FORMANT", nformant
);
541 xml
.addpar("freq", Pvowels
[nvowel
].formants
[nformant
].freq
);
542 xml
.addpar("amp", Pvowels
[nvowel
].formants
[nformant
].amp
);
543 xml
.addpar("q", Pvowels
[nvowel
].formants
[nformant
].q
);
548 void FilterParams::add2XML(XMLwrapper
& xml
)
551 xml
.addpar("category", Pcategory
);
552 xml
.addpar("type", Ptype
);
553 xml
.addparreal("basefreq", basefreq
);
554 xml
.addparreal("baseq", baseq
);
555 xml
.addpar("stages", Pstages
);
556 xml
.addparreal("freq_tracking", freqtracking
);
557 xml
.addparreal("gain", gain
);
559 //formant filter parameters
560 if((Pcategory
== 1) || (!xml
.minimal
)) {
561 xml
.beginbranch("FORMANT_FILTER");
562 xml
.addpar("num_formants", Pnumformants
);
563 xml
.addpar("formant_slowness", Pformantslowness
);
564 xml
.addpar("vowel_clearness", Pvowelclearness
);
565 xml
.addpar("center_freq", Pcenterfreq
);
566 xml
.addpar("octaves_freq", Poctavesfreq
);
567 for(int nvowel
= 0; nvowel
< FF_MAX_VOWELS
; ++nvowel
) {
568 xml
.beginbranch("VOWEL", nvowel
);
569 add2XMLsection(xml
, nvowel
);
572 xml
.addpar("sequence_size", Psequencesize
);
573 xml
.addpar("sequence_stretch", Psequencestretch
);
574 xml
.addparbool("sequence_reversed", Psequencereversed
);
575 for(int nseq
= 0; nseq
< FF_MAX_SEQUENCE
; ++nseq
) {
576 xml
.beginbranch("SEQUENCE_POS", nseq
);
577 xml
.addpar("vowel_id", Psequence
[nseq
].nvowel
);
585 void FilterParams::getfromXMLsection(XMLwrapper
& xml
, int n
)
588 for(int nformant
= 0; nformant
< FF_MAX_FORMANTS
; ++nformant
) {
589 if(xml
.enterbranch("FORMANT", nformant
) == 0)
591 Pvowels
[nvowel
].formants
[nformant
].freq
= xml
.getpar127(
594 ].formants
[nformant
].freq
);
595 Pvowels
[nvowel
].formants
[nformant
].amp
= xml
.getpar127(
598 ].formants
[nformant
].amp
);
599 Pvowels
[nvowel
].formants
[nformant
].q
=
600 xml
.getpar127("q", Pvowels
[nvowel
].formants
[nformant
].q
);
605 void FilterParams::getfromXML(XMLwrapper
& xml
)
607 const bool upgrade_3_0_2
= (xml
.fileversion() < version_type(3,0,2)) && (xml
.getparreal("basefreq", -1) < 0);
610 Pcategory
= xml
.getpar127("category", Pcategory
);
611 Ptype
= xml
.getpar127("type", Ptype
);
612 Pstages
= xml
.getpar127("stages", Pstages
);
614 int Pfreq
= xml
.getpar127("freq", 0);
615 basefreq
= (Pfreq
/ 64.0f
- 1.0f
) * 5.0f
;
616 basefreq
= powf(2.0f
, basefreq
+ 9.96578428f
);
617 int Pq
= xml
.getpar127("q", 0);
618 baseq
= expf(powf((float) Pq
/ 127.0f
, 2) * logf(1000.0f
)) - 0.9f
;
619 int Pgain
= xml
.getpar127("gain", 0);
620 gain
= (Pgain
/ 64.0f
- 1.0f
) * 30.0f
; //-30..30dB
621 int Pfreqtracking
= xml
.getpar127("freq_track", 0);
622 freqtracking
= 100 * (Pfreqtracking
- 64.0f
) / (64.0f
);
624 basefreq
= xml
.getparreal("basefreq", 1000);
625 baseq
= xml
.getparreal("baseq", 10);
626 gain
= xml
.getparreal("gain", 0);
627 freqtracking
= xml
.getparreal("freq_tracking", 0);
630 //formant filter parameters
631 if(xml
.enterbranch("FORMANT_FILTER")) {
632 Pnumformants
= xml
.getpar127("num_formants", Pnumformants
);
633 Pformantslowness
= xml
.getpar127("formant_slowness", Pformantslowness
);
634 Pvowelclearness
= xml
.getpar127("vowel_clearness", Pvowelclearness
);
635 Pcenterfreq
= xml
.getpar127("center_freq", Pcenterfreq
);
636 Poctavesfreq
= xml
.getpar127("octaves_freq", Poctavesfreq
);
638 for(int nvowel
= 0; nvowel
< FF_MAX_VOWELS
; ++nvowel
) {
639 if(xml
.enterbranch("VOWEL", nvowel
) == 0)
641 getfromXMLsection(xml
, nvowel
);
644 Psequencesize
= xml
.getpar127("sequence_size", Psequencesize
);
645 Psequencestretch
= xml
.getpar127("sequence_stretch", Psequencestretch
);
646 Psequencereversed
= xml
.getparbool("sequence_reversed",
648 for(int nseq
= 0; nseq
< FF_MAX_SEQUENCE
; ++nseq
) {
649 if(xml
.enterbranch("SEQUENCE_POS", nseq
) == 0)
651 Psequence
[nseq
].nvowel
= xml
.getpar("vowel_id",
652 Psequence
[nseq
].nvowel
,
661 #define COPY(y) this->y = x.y
662 void FilterParams::paste(FilterParams
&x
)
673 COPY(Pformantslowness
);
674 COPY(Pvowelclearness
);
678 for(int i
=0; i
<FF_MAX_VOWELS
; ++i
) {
679 for(int j
=0; j
<FF_MAX_FORMANTS
; ++j
) {
680 auto &a
= this->Pvowels
[i
].formants
[j
];
681 auto &b
= x
.Pvowels
[i
].formants
[j
];
690 COPY(Psequencestretch
);
691 COPY(Psequencereversed
);
692 for(int i
=0; i
<FF_MAX_SEQUENCE
; ++i
)
693 this->Psequence
[i
] = x
.Psequence
[i
];
698 last_update_timestamp
= time
->time();
703 void FilterParams::pasteArray(FilterParams
&x
, int nvowel
)
705 for(int nformant
= 0; nformant
< FF_MAX_FORMANTS
; ++nformant
) {
706 auto &self
= Pvowels
[nvowel
].formants
[nformant
];
707 auto &update
= x
.Pvowels
[nvowel
].formants
[nformant
];
708 self
.freq
= update
.freq
;
709 self
.amp
= update
.amp
;
714 last_update_timestamp
= time
->time();