2 ZynAddSubFX - a software synthesizer
4 FormantFilter.C - formant filters
5 Copyright (C) 2002-2005 Nasca Octavian Paul
6 Author: Nasca Octavian Paul
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of version 2 of the GNU General Public License
10 as published by the Free Software Foundation.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License (version 2) for more details.
17 You should have received a copy of the GNU General Public License (version 2)
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "filter_base.h"
28 #include "analog_filter.h"
29 #include "filter_parameters.h"
30 #include "formant_filter.h"
32 void FormantFilter::init(float sample_rate
, FilterParams
*pars
)
36 m_numformants
= pars
->Pnumformants
;
38 for (i
= 0 ; i
< m_numformants
; i
++)
40 m_formants
[i
].init(sample_rate
, ZYN_FILTER_ANALOG_TYPE_BPF2
, 1000.0, 10.0, pars
->m_additional_stages
, 0.0);
45 for (j
= 0 ; j
< FF_MAX_VOWELS
; j
++)
47 for (i
= 0 ; i
< m_numformants
; i
++)
49 m_formantpar
[j
][i
].frequency
= pars
->getformantfreq(pars
->Pvowels
[j
].formants
[i
].freq
);
50 m_formantpar
[j
][i
].amplitude
= pars
->getformantamp(pars
->Pvowels
[j
].formants
[i
].amp
);
51 m_formantpar
[j
][i
].q_factor
= pars
->getformantq(pars
->Pvowels
[j
].formants
[i
].q
);
55 for (i
= 0 ; i
< FF_MAX_FORMANTS
; i
++)
57 m_oldformantamp
[i
] = 1.0;
60 for (i
= 0 ; i
< m_numformants
; i
++)
62 m_currentformants
[i
].frequency
= 1000.0;
63 m_currentformants
[i
].amplitude
= 1.0;
64 m_currentformants
[i
].q_factor
= 2.0;
67 m_formantslowness
= pow(1.0 - pars
->Pformantslowness
/ 128.0, 3.0);
69 m_sequencesize
= pars
->Psequencesize
;
70 if (m_sequencesize
== 0)
75 for (i
= 0 ; i
< m_sequencesize
; i
++)
77 m_sequence
[i
].nvowel
= pars
->Psequence
[i
].nvowel
;
80 m_vowelclearness
= pow(10.0, (pars
->Pvowelclearness
- 32.0) / 48.0);
82 m_sequencestretch
= pow(0.1, (pars
->Psequencestretch
- 32.0) / 48.0);
83 if (pars
->Psequencereversed
)
85 m_sequencestretch
*= -1.0;
88 m_outgain
= dB2rap(pars
->m_gain
);
93 m_oldQfactor
= m_Qfactor
;
98 void FormantFilter::cleanup()
102 for (i
= 0 ; i
< m_numformants
; i
++)
104 m_formants
[i
].cleanup();
108 void FormantFilter::setpos(float input
)
115 if (m_firsttime
!= 0)
121 m_slowinput
= m_slowinput
* (1.0 - m_formantslowness
) + input
* m_formantslowness
;
124 if ((fabs(m_oldinput
- input
) < 0.001) &&
125 (fabs(m_slowinput
- input
) < 0.001) &&
126 (fabs(m_Qfactor
- m_oldQfactor
) < 0.001))
128 // m_oldinput = input; // daca setez asta, o sa faca probleme la schimbari foarte lente
137 pos
= fmod(input
* m_sequencestretch
, 1.0);
143 F2I(pos
* m_sequencesize
, p2
);
147 p1
+= m_sequencesize
;
150 pos
= fmod(pos
* m_sequencesize
, 1.0);
159 pos
= (atan((pos
* 2.0 - 1.0) * m_vowelclearness
) / atan(m_vowelclearness
) + 1.0) * 0.5;
161 p1
= m_sequence
[p1
].nvowel
;
162 p2
= m_sequence
[p2
].nvowel
;
164 if (m_firsttime
!= 0)
166 for (i
= 0 ; i
< m_numformants
; i
++)
168 m_currentformants
[i
].frequency
= m_formantpar
[p1
][i
].frequency
* (1.0 - pos
) + m_formantpar
[p2
][i
].frequency
*pos
;
169 m_currentformants
[i
].amplitude
= m_formantpar
[p1
][i
].amplitude
* (1.0 - pos
) + m_formantpar
[p2
][i
].amplitude
*pos
;
170 m_currentformants
[i
].q_factor
= m_formantpar
[p1
][i
].q_factor
*(1.0 - pos
) + m_formantpar
[p2
][i
].q_factor
* pos
;
171 m_formants
[i
].setfreq_and_q(m_currentformants
[i
].frequency
, m_currentformants
[i
].q_factor
* m_Qfactor
);
172 m_oldformantamp
[i
] = m_currentformants
[i
].amplitude
;
179 for (i
= 0 ; i
< m_numformants
; i
++)
181 m_currentformants
[i
].frequency
= m_currentformants
[i
].frequency
* (1.0 - m_formantslowness
)
182 + (m_formantpar
[p1
][i
].frequency
* (1.0 - pos
) + m_formantpar
[p2
][i
].frequency
* pos
) * m_formantslowness
;
184 m_currentformants
[i
].amplitude
= m_currentformants
[i
].amplitude
* (1.0 - m_formantslowness
)
185 + (m_formantpar
[p1
][i
].amplitude
* (1.0 - pos
) + m_formantpar
[p2
][i
].amplitude
* pos
) * m_formantslowness
;
187 m_currentformants
[i
].q_factor
= m_currentformants
[i
].q_factor
* (1.0 - m_formantslowness
)
188 + (m_formantpar
[p1
][i
].q_factor
* (1.0 - pos
) + m_formantpar
[p2
][i
].q_factor
* pos
) * m_formantslowness
;
190 m_formants
[i
].setfreq_and_q(m_currentformants
[i
].frequency
, m_currentformants
[i
].q_factor
* m_Qfactor
);
194 m_oldQfactor
= m_Qfactor
;
197 void FormantFilter::setfreq(float frequency
)
202 void FormantFilter::setq(float q_
)
208 for (i
= 0 ; i
< m_numformants
; i
++)
210 m_formants
[i
].setq(m_Qfactor
* m_currentformants
[i
].q_factor
);
214 void FormantFilter::setfreq_and_q(float frequency
, float q_
)
220 void FormantFilter::filterout(float *smp
)
225 for (i
= 0 ; i
< SOUND_BUFFER_SIZE
; i
++)
227 m_inbuffer
[i
] = smp
[i
];
231 for (j
= 0 ; j
< m_numformants
; j
++)
233 for (i
= 0 ; i
< SOUND_BUFFER_SIZE
; i
++)
235 m_tmpbuf
[i
] = m_inbuffer
[i
] * m_outgain
;
238 m_formants
[j
].filterout(m_tmpbuf
);
240 if (ABOVE_AMPLITUDE_THRESHOLD(m_oldformantamp
[j
], m_currentformants
[j
].amplitude
))
242 for (i
= 0 ; i
< SOUND_BUFFER_SIZE
; i
++)
244 smp
[i
] += m_tmpbuf
[i
] * INTERPOLATE_AMPLITUDE(m_oldformantamp
[j
], m_currentformants
[j
].amplitude
, i
, SOUND_BUFFER_SIZE
);
249 for (i
= 0 ; i
< SOUND_BUFFER_SIZE
; i
++)
251 smp
[i
] += m_tmpbuf
[i
] * m_currentformants
[j
].amplitude
;
255 m_oldformantamp
[j
] = m_currentformants
[j
].amplitude
;