Chris@0
|
1 /*
|
Chris@0
|
2 copyright (C) 2011 I. Irigaray, M. Rocamora
|
Chris@0
|
3
|
Chris@0
|
4 This program is free software: you can redistribute it and/or modify
|
Chris@0
|
5 it under the terms of the GNU General Public License as published by
|
Chris@0
|
6 the Free Software Foundation, either version 3 of the License, or
|
Chris@0
|
7 (at your option) any later version.
|
Chris@0
|
8
|
Chris@0
|
9 This program is distributed in the hope that it will be useful,
|
Chris@0
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Chris@0
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Chris@0
|
12 GNU General Public License for more details.
|
Chris@0
|
13
|
Chris@0
|
14 You should have received a copy of the GNU General Public License
|
Chris@0
|
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
Chris@0
|
16 */
|
Chris@0
|
17
|
Chris@0
|
18 #include "FChTransformF0gram.h"
|
Chris@0
|
19 #include "FChTransformUtils.h"
|
Chris@0
|
20 #include <math.h>
|
Chris@0
|
21 #include <float.h>
|
Chris@0
|
22 //#define DEBUG
|
Chris@0
|
23 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
Chris@0
|
24
|
Chris@0
|
25 FChTransformF0gram::FChTransformF0gram(float inputSampleRate) :
|
Chris@0
|
26 Plugin(inputSampleRate),
|
Chris@0
|
27 m_currentProgram("default"),
|
Chris@0
|
28 m_stepSize(0), // We are using 0 for step and block size to indicate "not yet set".
|
Chris@0
|
29 m_blockSize(0) {
|
Chris@0
|
30
|
Chris@0
|
31 printf("FUNCTION CALL: %s\n", __FUNCTION__);
|
Chris@0
|
32
|
Chris@0
|
33 m_fs = inputSampleRate;
|
Chris@0
|
34 // max frequency of interest (Hz)
|
Chris@0
|
35 m_fmax = 10000.f;
|
Chris@0
|
36 // warping parameters
|
Chris@0
|
37 m_warp_params.nsamps_twarp = 2048;
|
Chris@0
|
38 //m_warp_params.nsamps_twarp = 8;
|
Chris@0
|
39 m_warp_params.alpha_max = 4;
|
Chris@0
|
40 m_warp_params.num_warps = 21;
|
Chris@0
|
41 //m_warp_params.num_warps = 11;
|
Chris@0
|
42 m_warp_params.fact_over_samp = 2;
|
Chris@0
|
43 m_warp_params.alpha_dist = 0;
|
Chris@0
|
44 // f0 parameters
|
Chris@0
|
45 m_f0_params.f0min = 80.0;
|
Chris@0
|
46 m_f0_params.num_octs = 4;
|
Chris@0
|
47 m_f0_params.num_f0s_per_oct = 192;
|
Chris@0
|
48 m_f0_params.num_f0_hyps = 5;
|
Chris@0
|
49 m_f0_params.prefer = true;
|
Chris@0
|
50 m_f0_params.prefer_mean = 60;
|
Chris@0
|
51 m_f0_params.prefer_stdev = 18;
|
Chris@0
|
52 // glogs parameters
|
Chris@0
|
53 m_glogs_params.HP_logS = true;
|
Chris@0
|
54 m_glogs_params.att_subharms = 1;
|
Chris@0
|
55 // display parameters
|
Chris@0
|
56 m_f0gram_mode = true;
|
Chris@0
|
57
|
Chris@0
|
58 m_glogs_params.median_poly_coefs[0] = -0.000000058551680;
|
Chris@0
|
59 m_glogs_params.median_poly_coefs[1] = -0.000006945207775;
|
Chris@0
|
60 m_glogs_params.median_poly_coefs[2] = 0.002357223226588;
|
Chris@0
|
61
|
Chris@0
|
62 m_glogs_params.sigma_poly_coefs[0] = 0.000000092782308;
|
Chris@0
|
63 m_glogs_params.sigma_poly_coefs[1] = 0.000057283574898;
|
Chris@0
|
64 m_glogs_params.sigma_poly_coefs[2] = 0.022199903714288;
|
Chris@0
|
65
|
Chris@0
|
66 // number of fft points (controls zero-padding)
|
Chris@0
|
67 m_nfft = m_warp_params.nsamps_twarp;
|
Chris@0
|
68 // hop in samples
|
Chris@0
|
69 m_hop = m_warp_params.fact_over_samp * 256;
|
Chris@0
|
70
|
Chris@0
|
71 m_num_f0s = 0;
|
Chris@0
|
72
|
Chris@0
|
73 }
|
Chris@0
|
74
|
Chris@0
|
75 FChTransformF0gram::~FChTransformF0gram() {
|
Chris@0
|
76 // remeber to delete everything that deserves to
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 string
|
Chris@0
|
80 FChTransformF0gram::getIdentifier() const {
|
Chris@0
|
81 return "fchtransformf0gram";
|
Chris@0
|
82 }
|
Chris@0
|
83
|
Chris@0
|
84 string
|
Chris@0
|
85 FChTransformF0gram::getName() const {
|
Chris@0
|
86 return "Fan Chirp Transform F0gram";
|
Chris@0
|
87 }
|
Chris@0
|
88
|
Chris@0
|
89 string
|
Chris@0
|
90 FChTransformF0gram::getDescription() const {
|
Chris@0
|
91 // Return something helpful here!
|
Chris@0
|
92 return "This plug-in produces a representation, called F0gram, which exhibits the salience of the fundamental frequency of the sound sources in the audio file. The computation of the F0gram makes use of the Fan Chirp Transform analysis. It is based on the article \"Fan chirp transform for music representation\" P. Cancela, E. Lopez, M. Rocamora, International Conference on Digital Audio Effects, 13th. DAFx-10. Graz, Austria - 6-10 Sep 2010.";
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 string
|
Chris@0
|
96 FChTransformF0gram::getMaker() const {
|
Chris@0
|
97 // Your name here
|
Chris@0
|
98 return "Audio Processing Group \n Universidad de la Republica";
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 int
|
Chris@0
|
102 FChTransformF0gram::getPluginVersion() const {
|
Chris@0
|
103 // Increment this each time you release a version that behaves
|
Chris@0
|
104 // differently from the previous one
|
Chris@0
|
105 //
|
Chris@0
|
106 // 0 - initial version from scratch
|
Chris@0
|
107 return 0;
|
Chris@0
|
108 }
|
Chris@0
|
109
|
Chris@0
|
110 string
|
Chris@0
|
111 FChTransformF0gram::getCopyright() const {
|
Chris@0
|
112 // This function is not ideally named. It does not necessarily
|
Chris@0
|
113 // need to say who made the plugin -- getMaker does that -- but it
|
Chris@0
|
114 // should indicate the terms under which it is distributed. For
|
Chris@0
|
115 // example, "Copyright (year). All Rights Reserved", or "GPL"
|
Chris@0
|
116 return "copyright (C) 2011 GPL - Audio Processing Group, UdelaR";
|
Chris@0
|
117 }
|
Chris@0
|
118
|
Chris@0
|
119 FChTransformF0gram::InputDomain
|
Chris@0
|
120 FChTransformF0gram::getInputDomain() const {
|
Chris@0
|
121 return TimeDomain;
|
Chris@0
|
122 }
|
Chris@0
|
123
|
Chris@0
|
124 size_t FChTransformF0gram::getPreferredBlockSize() const {
|
Chris@0
|
125 return 8192; // 0 means "I can handle any block size"
|
Chris@0
|
126 }
|
Chris@0
|
127
|
Chris@0
|
128 size_t
|
Chris@0
|
129 FChTransformF0gram::getPreferredStepSize() const {
|
Chris@0
|
130 return 256; // 0 means "anything sensible"; in practice this
|
Chris@0
|
131 // means the same as the block size for TimeDomain
|
Chris@0
|
132 // plugins, or half of it for FrequencyDomain plugins
|
Chris@0
|
133 }
|
Chris@0
|
134
|
Chris@0
|
135 size_t
|
Chris@0
|
136 FChTransformF0gram::getMinChannelCount() const {
|
Chris@0
|
137 return 1;
|
Chris@0
|
138 }
|
Chris@0
|
139
|
Chris@0
|
140 size_t
|
Chris@0
|
141 FChTransformF0gram::getMaxChannelCount() const {
|
Chris@0
|
142 return 1;
|
Chris@0
|
143 }
|
Chris@0
|
144
|
Chris@0
|
145 FChTransformF0gram::ParameterList
|
Chris@0
|
146 FChTransformF0gram::getParameterDescriptors() const {
|
Chris@0
|
147 ParameterList list;
|
Chris@0
|
148
|
Chris@0
|
149 // If the plugin has no adjustable parameters, return an empty
|
Chris@0
|
150 // list here (and there's no need to provide implementations of
|
Chris@0
|
151 // getParameter and setParameter in that case either).
|
Chris@0
|
152
|
Chris@0
|
153 // Note that it is your responsibility to make sure the parameters
|
Chris@0
|
154 // start off having their default values (e.g. in the constructor
|
Chris@0
|
155 // above). The host needs to know the default value so it can do
|
Chris@0
|
156 // things like provide a "reset to default" function, but it will
|
Chris@0
|
157 // not explicitly set your parameters to their defaults for you if
|
Chris@0
|
158 // they have not changed in the mean time.
|
Chris@0
|
159
|
Chris@0
|
160 // ============= WARPING PARAMETERS =============
|
Chris@0
|
161
|
Chris@0
|
162 ParameterDescriptor fmax;
|
Chris@0
|
163 fmax.identifier = "fmax";
|
Chris@0
|
164 fmax.name = "Maximum frequency";
|
Chris@0
|
165 fmax.description = "Maximum frequency of interest for the analysis.";
|
Chris@0
|
166 fmax.unit = "Hz";
|
Chris@0
|
167 fmax.minValue = 2000;
|
Chris@0
|
168 fmax.maxValue = 22050;
|
Chris@0
|
169 fmax.defaultValue = 10000;
|
Chris@0
|
170 fmax.isQuantized = true;
|
Chris@0
|
171 fmax.quantizeStep = 1.0;
|
Chris@0
|
172 list.push_back(fmax);
|
Chris@0
|
173
|
Chris@0
|
174 ParameterDescriptor nsamp;
|
Chris@0
|
175 nsamp.identifier = "nsamp";
|
Chris@0
|
176 nsamp.name = "Number of samples";
|
Chris@0
|
177 nsamp.description = "Number of samples of the time warped frame";
|
Chris@0
|
178 nsamp.unit = "samples";
|
Chris@0
|
179 nsamp.minValue = 128;
|
Chris@0
|
180 nsamp.maxValue = 4096;
|
Chris@0
|
181 nsamp.defaultValue = 2048;
|
Chris@0
|
182 nsamp.isQuantized = true;
|
Chris@0
|
183 nsamp.quantizeStep = 1.0;
|
Chris@0
|
184 list.push_back(nsamp);
|
Chris@0
|
185
|
Chris@0
|
186 ParameterDescriptor nfft;
|
Chris@0
|
187 nfft.identifier = "nfft";
|
Chris@0
|
188 nfft.name = "FFT number of points";
|
Chris@0
|
189 nfft.description = "Number of FFT points (controls zero-padding)";
|
Chris@0
|
190 nfft.unit = "samples";
|
Chris@0
|
191 nfft.minValue = 0;
|
Chris@0
|
192 nfft.maxValue = 4;
|
Chris@0
|
193 nfft.defaultValue = 3;
|
Chris@0
|
194 nfft.isQuantized = true;
|
Chris@0
|
195 nfft.quantizeStep = 1.0;
|
Chris@0
|
196 nfft.valueNames.push_back("256");
|
Chris@0
|
197 nfft.valueNames.push_back("512");
|
Chris@0
|
198 nfft.valueNames.push_back("1024");
|
Chris@0
|
199 nfft.valueNames.push_back("2048");
|
Chris@0
|
200 nfft.valueNames.push_back("4096");
|
Chris@0
|
201 nfft.valueNames.push_back("8192");
|
Chris@0
|
202 list.push_back(nfft);
|
Chris@0
|
203
|
Chris@0
|
204 ParameterDescriptor alpha_max;
|
Chris@0
|
205 alpha_max.identifier = "alpha_max";
|
Chris@0
|
206 alpha_max.name = "Maximum alpha value";
|
Chris@0
|
207 alpha_max.description = "Maximum value for the alpha parameter of the transform.";
|
Chris@0
|
208 alpha_max.unit = "Hz/s";
|
Chris@0
|
209 alpha_max.minValue = -10;
|
Chris@0
|
210 alpha_max.maxValue = 10;
|
Chris@0
|
211 alpha_max.defaultValue = 5;
|
Chris@0
|
212 alpha_max.isQuantized = true;
|
Chris@0
|
213 alpha_max.quantizeStep = 1.0;
|
Chris@0
|
214 list.push_back(alpha_max);
|
Chris@0
|
215
|
Chris@0
|
216 ParameterDescriptor num_warps;
|
Chris@0
|
217 num_warps.identifier = "num_warps";
|
Chris@0
|
218 num_warps.name = "Number of warpings";
|
Chris@0
|
219 num_warps.description = "Number of different warpings in the specified range (must be odd).";
|
Chris@0
|
220 num_warps.unit = "";
|
Chris@0
|
221 num_warps.minValue = 1;
|
Chris@0
|
222 num_warps.maxValue = 101;
|
Chris@0
|
223 num_warps.defaultValue = 21;
|
Chris@0
|
224 num_warps.isQuantized = true;
|
Chris@0
|
225 num_warps.quantizeStep = 2.0;
|
Chris@0
|
226 list.push_back(num_warps);
|
Chris@0
|
227
|
Chris@0
|
228 ParameterDescriptor alpha_dist;
|
Chris@0
|
229 alpha_dist.identifier = "alpha_dist";
|
Chris@0
|
230 alpha_dist.name = "alpha distribution";
|
Chris@0
|
231 alpha_dist.description = "Type of distribution of alpha values (linear or log).";
|
Chris@0
|
232 alpha_dist.unit = "";
|
Chris@0
|
233 alpha_dist.minValue = 0;
|
Chris@0
|
234 alpha_dist.maxValue = 1;
|
Chris@0
|
235 alpha_dist.defaultValue = 1;
|
Chris@0
|
236 alpha_dist.isQuantized = true;
|
Chris@0
|
237 alpha_dist.quantizeStep = 1.0;
|
Chris@0
|
238 // lin (0), log (1)
|
Chris@0
|
239 alpha_dist.valueNames.push_back("lin");
|
Chris@0
|
240 alpha_dist.valueNames.push_back("log");
|
Chris@0
|
241 list.push_back(alpha_dist);
|
Chris@0
|
242
|
Chris@0
|
243 // ============= F0-GRAM PARAMETERS =============
|
Chris@0
|
244
|
Chris@0
|
245 ParameterDescriptor f0min;
|
Chris@0
|
246 f0min.identifier = "f0min";
|
Chris@0
|
247 f0min.name = "min f0";
|
Chris@0
|
248 f0min.description = "Minimum fundamental frequency (f0) value.";
|
Chris@0
|
249 f0min.unit = "Hz";
|
Chris@0
|
250 f0min.minValue = 1;
|
Chris@0
|
251 f0min.maxValue = 500;
|
Chris@0
|
252 f0min.defaultValue = 80;
|
Chris@0
|
253 f0min.isQuantized = true;
|
Chris@0
|
254 f0min.quantizeStep = 1.0;
|
Chris@0
|
255 list.push_back(f0min);
|
Chris@0
|
256
|
Chris@0
|
257 ParameterDescriptor num_octs;
|
Chris@0
|
258 num_octs.identifier = "num_octs";
|
Chris@0
|
259 num_octs.name = "number of octaves";
|
Chris@0
|
260 num_octs.description = "Number of octaves for F0gram computation.";
|
Chris@0
|
261 num_octs.unit = "";
|
Chris@0
|
262 num_octs.minValue = 1;
|
Chris@0
|
263 num_octs.maxValue = 10;
|
Chris@0
|
264 num_octs.defaultValue = 4;
|
Chris@0
|
265 num_octs.isQuantized = true;
|
Chris@0
|
266 num_octs.quantizeStep = 1.0;
|
Chris@0
|
267 list.push_back(num_octs);
|
Chris@0
|
268
|
Chris@0
|
269 ParameterDescriptor num_f0_hyps;
|
Chris@0
|
270 num_f0_hyps.identifier = "num_f0_hyps";
|
Chris@0
|
271 num_f0_hyps.name = "number of f0 hypotesis";
|
Chris@0
|
272 num_f0_hyps.description = "Number of f0 hypotesis to extract.";
|
Chris@0
|
273 num_f0_hyps.unit = "";
|
Chris@0
|
274 num_f0_hyps.minValue = 1;
|
Chris@0
|
275 num_f0_hyps.maxValue = 100;
|
Chris@0
|
276 num_f0_hyps.defaultValue = 10;
|
Chris@0
|
277 num_f0_hyps.isQuantized = true;
|
Chris@0
|
278 num_f0_hyps.quantizeStep = 1.0;
|
Chris@0
|
279 list.push_back(num_f0_hyps);
|
Chris@0
|
280
|
Chris@0
|
281 ParameterDescriptor f0s_per_oct;
|
Chris@0
|
282 f0s_per_oct.identifier = "f0s_per_oct";
|
Chris@0
|
283 f0s_per_oct.name = "f0 values per octave";
|
Chris@0
|
284 f0s_per_oct.description = "Number of f0 values per octave.";
|
Chris@0
|
285 f0s_per_oct.unit = "";
|
Chris@0
|
286 f0s_per_oct.minValue = 12;
|
Chris@0
|
287 f0s_per_oct.maxValue = 768;
|
Chris@0
|
288 f0s_per_oct.defaultValue = 192;
|
Chris@0
|
289 f0s_per_oct.isQuantized = true;
|
Chris@0
|
290 f0s_per_oct.quantizeStep = 1.0;
|
Chris@0
|
291 list.push_back(f0s_per_oct);
|
Chris@0
|
292
|
Chris@0
|
293 ParameterDescriptor f0_prefer_fun;
|
Chris@0
|
294 f0_prefer_fun.identifier = "f0_prefer_fun";
|
Chris@0
|
295 f0_prefer_fun.name = "f0 preference function";
|
Chris@0
|
296 f0_prefer_fun.description = "Whether to use a f0 weighting function.";
|
Chris@0
|
297 f0_prefer_fun.unit = "";
|
Chris@0
|
298 f0_prefer_fun.minValue = 0;
|
Chris@0
|
299 f0_prefer_fun.maxValue = 1;
|
Chris@0
|
300 f0_prefer_fun.defaultValue = 1;
|
Chris@0
|
301 f0_prefer_fun.isQuantized = true;
|
Chris@0
|
302 f0_prefer_fun.quantizeStep = 1.0;
|
Chris@0
|
303 list.push_back(f0_prefer_fun);
|
Chris@0
|
304
|
Chris@0
|
305 ParameterDescriptor f0_prefer_mean;
|
Chris@0
|
306 f0_prefer_mean.identifier = "f0_prefer_mean";
|
Chris@0
|
307 f0_prefer_mean.name = "mean f0 preference function";
|
Chris@0
|
308 f0_prefer_mean.description = "Mean value for f0 weighting function (MIDI number).";
|
Chris@0
|
309 f0_prefer_mean.unit = "";
|
Chris@0
|
310 f0_prefer_mean.minValue = 1;
|
Chris@0
|
311 f0_prefer_mean.maxValue = 127;
|
Chris@0
|
312 f0_prefer_mean.defaultValue = 60;
|
Chris@0
|
313 f0_prefer_mean.isQuantized = true;
|
Chris@0
|
314 f0_prefer_mean.quantizeStep = 1.0;
|
Chris@0
|
315 list.push_back(f0_prefer_mean);
|
Chris@0
|
316
|
Chris@0
|
317 ParameterDescriptor f0_prefer_stdev;
|
Chris@0
|
318 f0_prefer_stdev.identifier = "f0_prefer_stdev";
|
Chris@0
|
319 f0_prefer_stdev.name = "stdev of f0 preference function";
|
Chris@0
|
320 f0_prefer_stdev.description = "Stdev for f0 weighting function (MIDI number).";
|
Chris@0
|
321 f0_prefer_stdev.unit = "";
|
Chris@0
|
322 f0_prefer_stdev.minValue = 1;
|
Chris@0
|
323 f0_prefer_stdev.maxValue = 127;
|
Chris@0
|
324 f0_prefer_stdev.defaultValue = 18;
|
Chris@0
|
325 f0_prefer_stdev.isQuantized = true;
|
Chris@0
|
326 f0_prefer_stdev.quantizeStep = 1.0;
|
Chris@0
|
327 list.push_back(f0_prefer_stdev);
|
Chris@0
|
328
|
Chris@0
|
329 ParameterDescriptor f0gram_mode;
|
Chris@0
|
330 f0gram_mode.identifier = "f0gram_mode";
|
Chris@0
|
331 f0gram_mode.name = "display mode of f0gram";
|
Chris@0
|
332 f0gram_mode.description = "Display all bins of the best direction, or the best bin for each direction.";
|
Chris@0
|
333 f0gram_mode.unit = "";
|
Chris@0
|
334 f0gram_mode.minValue = 0;
|
Chris@0
|
335 f0gram_mode.maxValue = 1;
|
Chris@0
|
336 f0gram_mode.defaultValue = 1;
|
Chris@0
|
337 f0gram_mode.isQuantized = true;
|
Chris@0
|
338 f0gram_mode.quantizeStep = 1.0;
|
Chris@0
|
339 list.push_back(f0gram_mode);
|
Chris@0
|
340
|
Chris@0
|
341 return list;
|
Chris@0
|
342 }
|
Chris@0
|
343
|
Chris@0
|
344 float
|
Chris@0
|
345 FChTransformF0gram::getParameter(string identifier) const {
|
Chris@0
|
346
|
Chris@0
|
347 printf("FUNCTION CALL: %s(%s)\n", __FUNCTION__, identifier.c_str());
|
Chris@0
|
348
|
Chris@0
|
349 if (identifier == "fmax") {
|
Chris@0
|
350 return m_fmax;
|
Chris@0
|
351 } else if (identifier == "nsamp") {
|
Chris@0
|
352 return m_warp_params.nsamps_twarp;
|
Chris@0
|
353 } else if (identifier == "alpha_max") {
|
Chris@0
|
354 return m_warp_params.alpha_max;
|
Chris@0
|
355 } else if (identifier == "num_warps") {
|
Chris@0
|
356 return m_warp_params.num_warps;
|
Chris@0
|
357 } else if (identifier == "alpha_dist") {
|
Chris@0
|
358 return m_warp_params.alpha_dist;
|
Chris@0
|
359 } else if (identifier == "nfft") {
|
Chris@0
|
360 return m_nfft;
|
Chris@0
|
361 } else if (identifier == "f0min") {
|
Chris@0
|
362 return m_f0_params.f0min;
|
Chris@0
|
363 } else if (identifier == "num_octs") {
|
Chris@0
|
364 return m_f0_params.num_octs;
|
Chris@0
|
365 } else if (identifier == "f0s_per_oct") {
|
Chris@0
|
366 return m_f0_params.num_f0s_per_oct;
|
Chris@0
|
367 } else if (identifier == "num_f0_hyps") {
|
Chris@0
|
368 return m_f0_params.num_f0_hyps;
|
Chris@0
|
369 } else if (identifier == "f0_prefer_fun") {
|
Chris@0
|
370 return m_f0_params.prefer;
|
Chris@0
|
371 } else if (identifier == "f0_prefer_mean") {
|
Chris@0
|
372 return m_f0_params.prefer_mean;
|
Chris@0
|
373 } else if (identifier == "f0_prefer_stdev") {
|
Chris@0
|
374 return m_f0_params.prefer_stdev;
|
Chris@0
|
375 } else if (identifier == "f0gram_mode") {
|
Chris@0
|
376 return m_f0gram_mode;
|
Chris@0
|
377 } else {
|
Chris@0
|
378 return 0.f;
|
Chris@0
|
379 }
|
Chris@0
|
380
|
Chris@0
|
381 }
|
Chris@0
|
382
|
Chris@0
|
383 void FChTransformF0gram::setParameter(string identifier, float value) {
|
Chris@0
|
384
|
Chris@0
|
385 printf("FUNCTION CALL: %s(%s) = %f.\n", __FUNCTION__, identifier.c_str(), value);
|
Chris@0
|
386
|
Chris@0
|
387 if (identifier == "fmax") {
|
Chris@0
|
388 m_fmax = value;
|
Chris@0
|
389 } else if (identifier == "nsamp") {
|
Chris@0
|
390 m_warp_params.nsamps_twarp = value;
|
Chris@0
|
391 } else if (identifier == "alpha_max") {
|
Chris@0
|
392 m_warp_params.alpha_max = value;
|
Chris@0
|
393 } else if (identifier == "num_warps") {
|
Chris@0
|
394 m_warp_params.num_warps = value;
|
Chris@0
|
395 } else if (identifier == "alpha_dist") {
|
Chris@0
|
396 m_warp_params.alpha_dist = value;
|
Chris@0
|
397 } else if (identifier == "nfft") {
|
Chris@0
|
398 m_nfft = value;
|
Chris@0
|
399 } else if (identifier == "f0min") {
|
Chris@0
|
400 m_f0_params.f0min = value;
|
Chris@0
|
401 } else if (identifier == "num_octs") {
|
Chris@0
|
402 m_f0_params.num_octs = value;
|
Chris@0
|
403 } else if (identifier == "f0s_per_oct") {
|
Chris@0
|
404 m_f0_params.num_f0s_per_oct = value;
|
Chris@0
|
405 } else if (identifier == "num_f0_hyps") {
|
Chris@0
|
406 m_f0_params.num_f0_hyps = value;
|
Chris@0
|
407 } else if (identifier == "f0_prefer_fun") {
|
Chris@0
|
408 m_f0_params.prefer = value;
|
Chris@0
|
409 } else if (identifier == "f0_prefer_mean") {
|
Chris@0
|
410 m_f0_params.prefer_mean = value;
|
Chris@0
|
411 } else if (identifier == "f0_prefer_stdev") {
|
Chris@0
|
412 m_f0_params.prefer_stdev = value;
|
Chris@0
|
413 } else if (identifier == "f0gram_mode") {
|
Chris@0
|
414 m_f0gram_mode = value;
|
Chris@0
|
415 }
|
Chris@0
|
416
|
Chris@0
|
417 }
|
Chris@0
|
418
|
Chris@0
|
419 FChTransformF0gram::ProgramList
|
Chris@0
|
420 FChTransformF0gram::getPrograms() const {
|
Chris@0
|
421 ProgramList list;
|
Chris@0
|
422
|
Chris@0
|
423 list.push_back("default");
|
Chris@0
|
424
|
Chris@0
|
425 return list;
|
Chris@0
|
426 }
|
Chris@0
|
427
|
Chris@0
|
428 string
|
Chris@0
|
429 FChTransformF0gram::getCurrentProgram() const {
|
Chris@0
|
430 return m_currentProgram;
|
Chris@0
|
431 }
|
Chris@0
|
432
|
Chris@0
|
433 void
|
Chris@0
|
434 FChTransformF0gram::selectProgram(string name) {
|
Chris@0
|
435
|
Chris@0
|
436 printf("FUNCTION CALL: %s\n", __FUNCTION__);
|
Chris@0
|
437
|
Chris@0
|
438 m_currentProgram = name;
|
Chris@0
|
439
|
Chris@0
|
440 if (name == "default") {
|
Chris@0
|
441 m_fmax = 10000.f;
|
Chris@0
|
442
|
Chris@0
|
443 m_warp_params.nsamps_twarp = 2048;
|
Chris@0
|
444 m_warp_params.alpha_max = 4;
|
Chris@0
|
445 m_warp_params.num_warps = 21;
|
Chris@0
|
446 m_warp_params.fact_over_samp = 2;
|
Chris@0
|
447 m_warp_params.alpha_dist = 0;
|
Chris@0
|
448
|
Chris@0
|
449 m_f0_params.f0min = 80.0;
|
Chris@0
|
450 m_f0_params.num_octs = 4;
|
Chris@0
|
451 m_f0_params.num_f0s_per_oct = 192;
|
Chris@0
|
452 m_f0_params.num_f0_hyps = 5;
|
Chris@0
|
453 m_f0_params.prefer = true;
|
Chris@0
|
454 m_f0_params.prefer_mean = 60;
|
Chris@0
|
455 m_f0_params.prefer_stdev = 18;
|
Chris@0
|
456
|
Chris@0
|
457 m_glogs_params.HP_logS = true;
|
Chris@0
|
458 m_glogs_params.att_subharms = 1;
|
Chris@0
|
459
|
Chris@0
|
460 m_glogs_params.median_poly_coefs[0] = -0.000000058551680;
|
Chris@0
|
461 m_glogs_params.median_poly_coefs[1] = -0.000006945207775;
|
Chris@0
|
462 m_glogs_params.median_poly_coefs[2] = 0.002357223226588;
|
Chris@0
|
463
|
Chris@0
|
464 m_glogs_params.sigma_poly_coefs[0] = 0.000000092782308;
|
Chris@0
|
465 m_glogs_params.sigma_poly_coefs[1] = 0.000057283574898;
|
Chris@0
|
466 m_glogs_params.sigma_poly_coefs[2] = 0.022199903714288;
|
Chris@0
|
467
|
Chris@0
|
468 m_nfft = m_warp_params.nsamps_twarp;
|
Chris@0
|
469 m_hop = m_warp_params.fact_over_samp * 256;
|
Chris@0
|
470
|
Chris@0
|
471 m_num_f0s = 0;
|
Chris@0
|
472
|
Chris@0
|
473 m_f0gram_mode = 1;
|
Chris@0
|
474
|
Chris@0
|
475 }
|
Chris@0
|
476 }
|
Chris@0
|
477
|
Chris@0
|
478 FChTransformF0gram::OutputList
|
Chris@0
|
479 FChTransformF0gram::getOutputDescriptors() const {
|
Chris@0
|
480
|
Chris@0
|
481 printf("FUNCTION CALL: %s\n", __FUNCTION__);
|
Chris@0
|
482
|
Chris@0
|
483 OutputList list;
|
Chris@0
|
484
|
Chris@0
|
485 // See OutputDescriptor documentation for the possibilities here.
|
Chris@0
|
486 // Every plugin must have at least one output.
|
Chris@0
|
487
|
Chris@0
|
488 /* f0 values of F0gram grid as string values */
|
Chris@0
|
489 vector<string> f0values;
|
Chris@0
|
490 size_t ind = 0;
|
Chris@0
|
491 char f0String[10];
|
Chris@0
|
492 while (ind < m_num_f0s) {
|
Chris@0
|
493 sprintf(f0String, "%4.2f", m_f0s[ind]);
|
Chris@0
|
494 f0values.push_back(f0String);
|
Chris@0
|
495 ind++;
|
Chris@0
|
496 }
|
Chris@0
|
497
|
Chris@0
|
498 /* The F0gram */
|
Chris@0
|
499 OutputDescriptor d;
|
Chris@0
|
500 d.identifier = "f0gram";
|
Chris@0
|
501 d.name = "F0gram: salience of f0s";
|
Chris@0
|
502 d.description = "This representation show the salience of the different f0s in the signal.";
|
Chris@0
|
503 d.unit = "Hertz";
|
Chris@0
|
504 d.hasFixedBinCount = true;
|
Chris@0
|
505 //d.binCount = m_num_f0s;
|
Chris@0
|
506 //d.binCount = m_blockSize/2+1;
|
Chris@0
|
507 //d.binCount = m_warp_params.nsamps_twarp/2+1;
|
Chris@0
|
508 //d.binCount = m_warpings.nsamps_torig;
|
Chris@0
|
509 d.binCount = m_f0_params.num_octs*m_f0_params.num_f0s_per_oct;
|
Chris@0
|
510 d.binNames = f0values;
|
Chris@0
|
511 d.hasKnownExtents = false;
|
Chris@0
|
512 d.isQuantized = false;
|
Chris@0
|
513 d.sampleType = OutputDescriptor::OneSamplePerStep;
|
Chris@0
|
514 d.hasDuration = false;
|
Chris@0
|
515 list.push_back(d);
|
Chris@0
|
516
|
Chris@0
|
517 return list;
|
Chris@0
|
518 }
|
Chris@0
|
519
|
Chris@0
|
520 bool
|
Chris@0
|
521 FChTransformF0gram::initialise(size_t channels, size_t stepSize, size_t blockSize) {
|
Chris@0
|
522 if (channels < getMinChannelCount() ||
|
Chris@0
|
523 channels > getMaxChannelCount()) return false;
|
Chris@0
|
524
|
Chris@0
|
525 printf("FUNCTION CALL: %s\n", __FUNCTION__);
|
Chris@0
|
526
|
Chris@0
|
527 // set blockSize and stepSize (but changed below)
|
Chris@0
|
528 m_blockSize = blockSize;
|
Chris@0
|
529 m_stepSize = stepSize;
|
Chris@0
|
530
|
Chris@0
|
531 // WARNING !!!
|
Chris@0
|
532 // these values in fact are determined by the sampling frequency m_fs
|
Chris@0
|
533 // the parameters used below correspond to default values i.e. m_fs = 44.100 Hz
|
Chris@0
|
534 //m_blockSize = 4 * m_warp_params.nsamps_twarp;
|
Chris@0
|
535 m_stepSize = floor(m_hop / m_warp_params.fact_over_samp);
|
Chris@0
|
536
|
Chris@0
|
537 /* initialise m_warp_params */
|
Chris@0
|
538 // FChTF0gram:warping_design m_warpings = new warping_design;
|
Chris@0
|
539 /* initialise m_f0_params */
|
Chris@0
|
540
|
Chris@0
|
541 /* initialise m_glogs_params */
|
Chris@0
|
542 design_GLogS();
|
Chris@0
|
543
|
Chris@0
|
544 /* design of FChT */
|
Chris@0
|
545 // design_fcht(m_warps, m_accums, m_f0s)
|
Chris@0
|
546 design_FChT();
|
Chris@0
|
547
|
Chris@0
|
548 design_FFT();
|
Chris@0
|
549
|
Chris@0
|
550 design_LPF();
|
Chris@0
|
551
|
Chris@0
|
552 design_time_window();
|
Chris@0
|
553
|
Chris@0
|
554 // Create Hanning window for warped signals
|
Chris@0
|
555 mp_HanningWindow = new double[m_warp_params.nsamps_twarp];
|
Chris@0
|
556 bool normalize = false;
|
Chris@0
|
557 hanning_window(mp_HanningWindow, m_warp_params.nsamps_twarp, normalize);
|
Chris@0
|
558
|
Chris@0
|
559 printf(" End of initialise().\n");
|
Chris@0
|
560 return true;
|
Chris@0
|
561 }
|
Chris@0
|
562
|
Chris@0
|
563 void
|
Chris@0
|
564 FChTransformF0gram::design_GLogS() {
|
Chris@0
|
565 printf(" Running design_GLogS().\n");
|
Chris@0
|
566
|
Chris@0
|
567 // total number & initial quantity of f0s
|
Chris@0
|
568 m_glogs_init_f0s = (size_t)(((double)m_f0_params.num_f0s_per_oct)*log2(5.0))+1;
|
Chris@0
|
569 m_glogs_num_f0s = (m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct + m_glogs_init_f0s;
|
Chris@0
|
570
|
Chris@0
|
571 // Initialize arrays
|
Chris@0
|
572 m_glogs_f0 = new double[m_glogs_num_f0s];
|
Chris@0
|
573 m_glogs = new double[m_glogs_num_f0s*m_warp_params.num_warps];
|
Chris@0
|
574 m_glogs_n = new size_t[m_glogs_num_f0s];
|
Chris@0
|
575 m_glogs_index = new size_t[m_glogs_num_f0s];
|
Chris@0
|
576
|
Chris@0
|
577 // Compute f0 values
|
Chris@0
|
578 m_glogs_harmonic_count = 0;
|
Chris@0
|
579 double factor = (double)(m_warp_params.nsamps_twarp/2)/(double)(m_warp_params.nsamps_twarp/2+1);
|
Chris@0
|
580 for (size_t i = 0; i < m_glogs_num_f0s; i++) {
|
Chris@0
|
581 m_glogs_f0[i] = (m_f0_params.f0min/5.0)*pow(2.0,(double)i/(double)m_f0_params.num_f0s_per_oct);
|
Chris@0
|
582 // for every f0 compute number of partials less or equal than m_fmax.
|
Chris@0
|
583 m_glogs_n[i] = m_fmax*factor/m_glogs_f0[i];
|
Chris@0
|
584 m_glogs_index[i] = m_glogs_harmonic_count;
|
Chris@0
|
585 m_glogs_harmonic_count += m_glogs_n[i];
|
Chris@0
|
586 }
|
Chris@0
|
587
|
Chris@0
|
588 // Initialize arrays for interpolation
|
Chris@0
|
589 m_glogs_posint = new size_t[m_glogs_harmonic_count];
|
Chris@0
|
590 m_glogs_posfrac = new double[m_glogs_harmonic_count];
|
Chris@0
|
591 m_glogs_interp = new double[m_glogs_harmonic_count];
|
Chris@0
|
592
|
Chris@0
|
593 // Compute int & frac of interpolation positions
|
Chris@0
|
594 size_t aux_index = 0;
|
Chris@0
|
595 double aux_pos;
|
Chris@0
|
596 for (size_t i = 0; i < m_glogs_num_f0s; i++) {
|
Chris@0
|
597 for (size_t j = 1; j <= m_glogs_n[i]; j++) {
|
Chris@0
|
598 // indice en el vector de largo t_warp/2+1 donde el ultimo valor corresponde a f=m_fmax
|
Chris@0
|
599 aux_pos = ((double)j*m_glogs_f0[i])*((double)(m_warp_params.nsamps_twarp/2+1))/m_fmax;
|
Chris@0
|
600 m_glogs_posint[aux_index] = (size_t)aux_pos;
|
Chris@0
|
601 m_glogs_posfrac[aux_index] = aux_pos - (double)m_glogs_posint[aux_index];
|
Chris@0
|
602 aux_index++;
|
Chris@0
|
603 }
|
Chris@0
|
604 }
|
Chris@0
|
605
|
Chris@0
|
606 // Third harmonic attenuation
|
Chris@0
|
607 double aux_third_harmonic;
|
Chris@0
|
608 m_glogs_third_harmonic_posint = new size_t[(m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
609 m_glogs_third_harmonic_posfrac = new double[(m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
610 for (size_t i = 0; i < (m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct; i++) {
|
Chris@0
|
611 aux_third_harmonic = (double)i + (double)m_glogs_init_f0s - ((double)m_f0_params.num_f0s_per_oct)*log2(3.0);
|
Chris@0
|
612 //printf(" aux_third_harmonic = %f.\n", aux_third_harmonic);
|
Chris@0
|
613 m_glogs_third_harmonic_posint[i] = (size_t)aux_third_harmonic;
|
Chris@0
|
614 m_glogs_third_harmonic_posfrac[i] = aux_third_harmonic - (double)(m_glogs_third_harmonic_posint[i]);
|
Chris@0
|
615 }
|
Chris@0
|
616 m_glogs_third_harmonic = new double[(m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
617
|
Chris@0
|
618 // Fifth harmonic attenuation
|
Chris@0
|
619 double aux_fifth_harmonic;
|
Chris@0
|
620 m_glogs_fifth_harmonic_posint = new size_t[(m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
621 m_glogs_fifth_harmonic_posfrac = new double[(m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
622 for (size_t i = 0; i < (m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct; i++) {
|
Chris@0
|
623 aux_fifth_harmonic = (double)i + (double)m_glogs_init_f0s - ((double)m_f0_params.num_f0s_per_oct)*log2(5.0);
|
Chris@0
|
624 //printf(" aux_fifth_harmonic = %f.\n", aux_fifth_harmonic);
|
Chris@0
|
625 m_glogs_fifth_harmonic_posint[i] = (size_t)aux_fifth_harmonic;
|
Chris@0
|
626 m_glogs_fifth_harmonic_posfrac[i] = aux_fifth_harmonic - (double)(m_glogs_fifth_harmonic_posint[i]);
|
Chris@0
|
627 }
|
Chris@0
|
628 m_glogs_fifth_harmonic = new double[(m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
629
|
Chris@0
|
630 // Normalization & attenuation windows
|
Chris@0
|
631 m_glogs_f0_preference_weights = new double[m_f0_params.num_octs*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
632 m_glogs_median_correction = new double[m_f0_params.num_octs*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
633 m_glogs_sigma_correction = new double[m_f0_params.num_octs*m_f0_params.num_f0s_per_oct];
|
Chris@0
|
634 m_glogs_hf_smoothing_window = new double[m_warp_params.nsamps_twarp/2+1];
|
Chris@0
|
635 double MIDI_value;
|
Chris@0
|
636 for (size_t i = 0; i < m_f0_params.num_octs*m_f0_params.num_f0s_per_oct; i++) {
|
Chris@0
|
637 MIDI_value = 69.0 + 12.0 * log2(m_glogs_f0[i + m_glogs_init_f0s]/440.0);
|
Chris@0
|
638 m_glogs_f0_preference_weights[i] = 1.0/sqrt(2.0*M_PI*m_f0_params.prefer_stdev*m_f0_params.prefer_stdev)*exp(-(MIDI_value-m_f0_params.prefer_mean)*(MIDI_value-m_f0_params.prefer_mean)/(2.0*m_f0_params.prefer_stdev*m_f0_params.prefer_stdev));
|
Chris@0
|
639 m_glogs_f0_preference_weights[i] = (0.01 + m_glogs_f0_preference_weights[i]) / (1.01);
|
Chris@0
|
640
|
Chris@0
|
641 m_glogs_median_correction[i] = m_glogs_params.median_poly_coefs[0]*(i+1.0)*(i+1.0) + m_glogs_params.median_poly_coefs[1]*(i+1.0) + m_glogs_params.median_poly_coefs[2];
|
Chris@0
|
642 m_glogs_sigma_correction[i] = 1.0 / (m_glogs_params.sigma_poly_coefs[0]*(i+1.0)*(i+1.0) + m_glogs_params.sigma_poly_coefs[1]*(i+1.0) + m_glogs_params.sigma_poly_coefs[2]);
|
Chris@0
|
643 }
|
Chris@0
|
644
|
Chris@0
|
645 double smooth_width = 1000.0; // hertz.
|
Chris@0
|
646 double smooth_aux = (double)(m_warp_params.nsamps_twarp/2+1)*(m_fmax-smooth_width)/m_fmax;
|
Chris@0
|
647 for (size_t i = 0; i < m_warp_params.nsamps_twarp/2+1; i++) {
|
Chris@0
|
648 if (i < smooth_aux) {
|
Chris@0
|
649 m_glogs_hf_smoothing_window[i] = 1.0;
|
Chris@0
|
650 } else {
|
Chris@0
|
651 m_glogs_hf_smoothing_window[i] = ((double)i - (double)m_warp_params.nsamps_twarp/2.0)*(-1.0/((double)(m_warp_params.nsamps_twarp/2+1)-smooth_aux));
|
Chris@0
|
652 }
|
Chris@0
|
653 }
|
Chris@0
|
654
|
Chris@0
|
655 printf(" End of design_GLogS().\n");
|
Chris@0
|
656
|
Chris@0
|
657 }
|
Chris@0
|
658
|
Chris@0
|
659 void
|
Chris@0
|
660 FChTransformF0gram::design_FFT() {
|
Chris@0
|
661 printf(" Running design_FFT().\n");
|
Chris@0
|
662
|
Chris@0
|
663 in = (fftw_complex*) fftw_malloc(sizeof (fftw_complex) * m_nfft);
|
Chris@0
|
664 out = (fftw_complex*) fftw_malloc(sizeof (fftw_complex) * m_nfft);
|
Chris@0
|
665 //TODO verificar que el tipo de datos de in_window es del tipo double, era float.
|
Chris@0
|
666 in_window = (double*) fftw_malloc(sizeof (double) * m_nfft);
|
Chris@0
|
667 planFFT = fftw_plan_dft_1d(m_nfft, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
|
Chris@0
|
668
|
Chris@0
|
669 //TODO hacer diseño del FFT para el filtrado pasabajos.
|
Chris@0
|
670
|
Chris@0
|
671 }
|
Chris@0
|
672
|
Chris@0
|
673 void
|
Chris@0
|
674 FChTransformF0gram::design_FChT() {
|
Chris@0
|
675
|
Chris@0
|
676 printf(" Running design_FChT().\n");
|
Chris@0
|
677 /*
|
Chris@0
|
678 * FILES FOR DEBUGGING
|
Chris@0
|
679 */
|
Chris@0
|
680
|
Chris@0
|
681 //ofstream output("output.txt");
|
Chris@0
|
682
|
Chris@0
|
683
|
Chris@0
|
684 /* ============= WARPING DESIGN ============= */
|
Chris@0
|
685
|
Chris@0
|
686 // sampling frequency after oversampling
|
Chris@0
|
687 m_warpings.fs_orig = m_warp_params.fact_over_samp * m_fs;
|
Chris@0
|
688
|
Chris@0
|
689 // number of samples of the original signal frame
|
Chris@0
|
690 m_warpings.nsamps_torig = 4 * m_warp_params.fact_over_samp * m_warp_params.nsamps_twarp;
|
Chris@0
|
691 // equivalent to: m_warpings.nsamps_torig = m_warp_params.fact_over_samp * m_blockSize;
|
Chris@0
|
692
|
Chris@0
|
693 // time instants of the original signal frame
|
Chris@0
|
694 double t_orig[m_warpings.nsamps_torig];
|
Chris@0
|
695 //float * t_orig = new float [m_warpings.nsamps_torig];
|
Chris@0
|
696 for (size_t ind = 0; ind < m_warpings.nsamps_torig; ind++) {
|
Chris@0
|
697 t_orig[ind] = ((double)(ind + 1) - (double)m_warpings.nsamps_torig / 2.0) / m_warpings.fs_orig;
|
Chris@0
|
698 }
|
Chris@0
|
699
|
Chris@0
|
700 // linear chirps warping definition as relative frequency deviation
|
Chris@0
|
701 //double * freq_relative = new double [m_warpings.nsamps_torig * m_warp_params.num_warps];
|
Chris@0
|
702 //TODO
|
Chris@0
|
703 double *freq_relative = new double [m_warpings.nsamps_torig * m_warp_params.num_warps];
|
Chris@0
|
704 define_warps_linear_chirps(freq_relative, t_orig);
|
Chris@0
|
705
|
Chris@0
|
706 // maximum relative frequency deviation
|
Chris@0
|
707 double freq_relative_max = 0;
|
Chris@0
|
708 for (size_t i = 0; i < m_warpings.nsamps_torig; i++)
|
Chris@0
|
709 for (size_t j = 0; j < m_warp_params.num_warps; j++)
|
Chris@0
|
710 if (freq_relative_max < freq_relative[j * m_warpings.nsamps_torig + i])
|
Chris@0
|
711 freq_relative_max = freq_relative[j * m_warpings.nsamps_torig + i];
|
Chris@0
|
712
|
Chris@0
|
713 // sampling frequency of warped signal to be free of aliasing up to fmax
|
Chris@0
|
714 m_warpings.fs_warp = 2 * m_fmax * freq_relative_max;
|
Chris@0
|
715
|
Chris@0
|
716 // time instants of the warped signal frame
|
Chris@0
|
717 double t_warp[m_warp_params.nsamps_twarp];
|
Chris@0
|
718 for (size_t ind = 0; ind < m_warp_params.nsamps_twarp; ind++) {
|
Chris@0
|
719 t_warp[ind] = ((double)((int)(ind + 1)- (int)m_warp_params.nsamps_twarp / 2)) / (double)m_warpings.fs_warp;
|
Chris@0
|
720 }
|
Chris@0
|
721
|
Chris@0
|
722 // design of warpings for efficient interpolation
|
Chris@0
|
723 design_warps(freq_relative, t_orig, t_warp);
|
Chris@0
|
724
|
Chris@0
|
725
|
Chris@0
|
726 /*
|
Chris@0
|
727 * FILES FOR DEBUGGING
|
Chris@0
|
728 */
|
Chris@0
|
729
|
Chris@0
|
730 /*
|
Chris@0
|
731 output << "chirp_rates" << endl;
|
Chris@0
|
732 for (size_t j = 0; j < m_warp_params.num_warps; j++){
|
Chris@0
|
733 output << m_warpings.chirp_rates[j];
|
Chris@0
|
734 output << " ";
|
Chris@0
|
735 }
|
Chris@0
|
736 output << endl << "freq_relative" << endl;
|
Chris@0
|
737
|
Chris@0
|
738 for (size_t i = 0; i < m_warpings.nsamps_torig; i++){
|
Chris@0
|
739 for (size_t j = 0; j < m_warp_params.num_warps; j++){
|
Chris@0
|
740 output << freq_relative[j * m_warpings.nsamps_torig + i];
|
Chris@0
|
741 output << " ";
|
Chris@0
|
742 }
|
Chris@0
|
743 output << endl;
|
Chris@0
|
744 }
|
Chris@0
|
745
|
Chris@0
|
746 output << endl << "t_orig" << endl;
|
Chris@0
|
747
|
Chris@0
|
748 for (size_t i = 0; i < m_warpings.nsamps_torig; i++){
|
Chris@0
|
749 output << t_orig[i] << endl ;
|
Chris@0
|
750 }
|
Chris@0
|
751 */
|
Chris@0
|
752
|
Chris@0
|
753 delete [] freq_relative;
|
Chris@0
|
754 //output.close();
|
Chris@0
|
755
|
Chris@0
|
756 /* ============= FFTW PLAN DESIGN ============= */
|
Chris@0
|
757 // Initialize 2-d array for warped signals
|
Chris@0
|
758 x_warping = new double[m_warp_params.nsamps_twarp];
|
Chris@0
|
759 m_absFanChirpTransform = (double*)fftw_malloc(sizeof (double) * m_warp_params.num_warps * (m_warp_params.nsamps_twarp/2 + 1));
|
Chris@0
|
760 m_auxFanChirpTransform = (fftw_complex*)fftw_malloc(sizeof ( fftw_complex) * (m_warp_params.nsamps_twarp/2 + 1));
|
Chris@0
|
761 plan_forward_xwarping = fftw_plan_dft_r2c_1d(m_warp_params.nsamps_twarp, x_warping, m_auxFanChirpTransform, FFTW_ESTIMATE);
|
Chris@0
|
762
|
Chris@0
|
763 printf(" End of design_FChT().\n");
|
Chris@0
|
764
|
Chris@0
|
765 }
|
Chris@0
|
766
|
Chris@0
|
767 void
|
Chris@0
|
768 FChTransformF0gram::design_warps(double * freq_relative, double * t_orig, double * t_warp) {
|
Chris@0
|
769 /* the warping is done by interpolating the original signal in time instants
|
Chris@0
|
770 given by the desired frequency deviation, to do this, the interpolation
|
Chris@0
|
771 instants are stored in a structure as an integer index and a fractional value
|
Chris@0
|
772 hypothesis: sampling frequency at the central point equals the original
|
Chris@0
|
773 */
|
Chris@0
|
774 printf(" Running design_warps().\n");
|
Chris@0
|
775
|
Chris@0
|
776 m_warpings.pos_int = new size_t[m_warp_params.num_warps * m_warp_params.nsamps_twarp];
|
Chris@0
|
777 m_warpings.pos_frac = new double[m_warp_params.num_warps * m_warp_params.nsamps_twarp];
|
Chris@0
|
778
|
Chris@0
|
779 // vector of phase values
|
Chris@0
|
780 double *phi = new double[m_warpings.nsamps_torig];
|
Chris@0
|
781 double aux;
|
Chris@0
|
782
|
Chris@0
|
783 // warped positions
|
Chris@0
|
784 double *pos1 = new double[m_warp_params.nsamps_twarp*m_warp_params.num_warps];
|
Chris@0
|
785
|
Chris@0
|
786 for (size_t i = 0; i < m_warp_params.num_warps; i++) {
|
Chris@0
|
787 // vector of phase values
|
Chris@0
|
788 // float * phi;
|
Chris@0
|
789 // integration of relative frequency to obtain phase values
|
Chris@0
|
790 // phi = cumtrapz(t_orig,freq_relative(:,i)');
|
Chris@0
|
791 // centering of phase values to force original frequency in the middle
|
Chris@0
|
792 //phi = phi - phi(end/2);
|
Chris@0
|
793 // interpolation of phase values to obtain warped positions
|
Chris@0
|
794 //pos1(i,:) = interp1(phi,t_orig,t_warp)*fs_orig + length(t_orig)/2;
|
Chris@0
|
795
|
Chris@0
|
796 // integration of relative frequency to obtain phase values
|
Chris@0
|
797 cumtrapz(t_orig, freq_relative + i*(m_warpings.nsamps_torig), m_warpings.nsamps_torig, phi);
|
Chris@0
|
798
|
Chris@0
|
799 // centering of phase values to force original frequency in the middle
|
Chris@0
|
800 aux = phi[m_warpings.nsamps_torig/2];
|
Chris@0
|
801 for (size_t j = 0; j < m_warpings.nsamps_torig; j++) {
|
Chris@0
|
802 phi[j] -= aux;
|
Chris@0
|
803 } //for
|
Chris@0
|
804
|
Chris@0
|
805 // interpolation of phase values to obtain warped positions
|
Chris@0
|
806 interp1(phi, t_orig, m_warpings.nsamps_torig, t_warp, pos1 + i*m_warp_params.nsamps_twarp, m_warp_params.nsamps_twarp);
|
Chris@0
|
807
|
Chris@0
|
808 }
|
Chris@0
|
809
|
Chris@0
|
810 // % previous sample index
|
Chris@0
|
811 // pos1_int = uint32(floor(pos1))';
|
Chris@0
|
812 // % integer corresponding to previous sample index in "c"
|
Chris@0
|
813 // warps.pos1_int = (pos1_int - uint32(1));
|
Chris@0
|
814 // % fractional value that defines the warped position
|
Chris@0
|
815 // warps.pos1_frac = (double(pos1)' - double(pos1_int));
|
Chris@0
|
816
|
Chris@0
|
817 // m_warpings.pos_int = new size_t[m_warp_params.num_warps * m_warp_params.nsamps_twarp];
|
Chris@0
|
818 for (size_t j = 0; j < m_warp_params.nsamps_twarp*m_warp_params.num_warps; j++) {
|
Chris@0
|
819 // previous sample index
|
Chris@0
|
820 pos1[j] = pos1[j]*m_warpings.fs_orig + m_warpings.nsamps_torig/2 + 1;
|
Chris@0
|
821 m_warpings.pos_int[j] = (size_t) pos1[j];
|
Chris@0
|
822 m_warpings.pos_frac[j] = pos1[j] - (double)(m_warpings.pos_int[j]);
|
Chris@0
|
823 } //for
|
Chris@0
|
824
|
Chris@0
|
825 delete [] phi;
|
Chris@0
|
826 delete [] pos1;
|
Chris@0
|
827
|
Chris@0
|
828 printf(" End of design_warps().\n");
|
Chris@0
|
829
|
Chris@0
|
830 }
|
Chris@0
|
831
|
Chris@0
|
832 void
|
Chris@0
|
833 FChTransformF0gram::define_warps_linear_chirps(double * freq_relative, double * t_orig) {
|
Chris@0
|
834 /** define warps as relative frequency deviation from original frequency
|
Chris@0
|
835 t_orig : time vector
|
Chris@0
|
836 freq_relative : relative frequency deviations
|
Chris@0
|
837 */
|
Chris@0
|
838 printf(" Running define_warps_linear_chirps().\n");
|
Chris@0
|
839
|
Chris@0
|
840 if (m_warp_params.alpha_dist == 0) {
|
Chris@0
|
841
|
Chris@0
|
842 // linear alpha values spacing
|
Chris@0
|
843 m_warpings.chirp_rates = new double [m_warp_params.num_warps];
|
Chris@0
|
844 // WARNING m_warp_params.num_warps must be odd
|
Chris@0
|
845 m_warpings.chirp_rates[0] = -m_warp_params.alpha_max;
|
Chris@0
|
846 double increment = (double) m_warp_params.alpha_max / ((m_warp_params.num_warps - 1) / 2);
|
Chris@0
|
847
|
Chris@0
|
848 for (size_t ind = 1; ind < m_warp_params.num_warps; ind++) {
|
Chris@0
|
849 m_warpings.chirp_rates[ind] = m_warpings.chirp_rates[ind - 1] + increment;
|
Chris@0
|
850 }
|
Chris@0
|
851 // force zero value
|
Chris@0
|
852 m_warpings.chirp_rates[(int) ((m_warp_params.num_warps - 1) / 2)] = 0;
|
Chris@0
|
853
|
Chris@0
|
854 } else {
|
Chris@0
|
855 // log alpha values spacing
|
Chris@0
|
856 m_warpings.chirp_rates = new double [m_warp_params.num_warps];
|
Chris@0
|
857
|
Chris@0
|
858 // force zero value
|
Chris@0
|
859 int middle_point = (int) ((m_warp_params.num_warps - 1) / 2);
|
Chris@0
|
860 m_warpings.chirp_rates[middle_point] = 0;
|
Chris@0
|
861
|
Chris@0
|
862 double logMax = log10(m_warp_params.alpha_max + 1);
|
Chris@0
|
863 double increment = logMax / ((m_warp_params.num_warps - 1) / 2.0f);
|
Chris@0
|
864 double exponent = 0;
|
Chris@0
|
865
|
Chris@0
|
866 // fill positive values
|
Chris@0
|
867 int ind_log = middle_point;
|
Chris@0
|
868 for (size_t ind = 0; ind < (m_warp_params.num_warps + 1) / 2; ind++) {
|
Chris@0
|
869 m_warpings.chirp_rates[ind_log] = pow(10, exponent) - 1;
|
Chris@0
|
870 exponent += increment;
|
Chris@0
|
871 ind_log++;
|
Chris@0
|
872 }
|
Chris@0
|
873 // fill negative values
|
Chris@0
|
874 for (size_t ind = 0; ind < (m_warp_params.num_warps - 1) / 2; ind++) {
|
Chris@0
|
875 m_warpings.chirp_rates[ind] = -m_warpings.chirp_rates[m_warp_params.num_warps - 1 - ind];
|
Chris@0
|
876 }
|
Chris@0
|
877 }
|
Chris@0
|
878
|
Chris@0
|
879 // compute relative frequency deviation
|
Chris@0
|
880 for (size_t i = 0; i < m_warpings.nsamps_torig; i++)
|
Chris@0
|
881 for (size_t j = 0; j < m_warp_params.num_warps; j++)
|
Chris@0
|
882 freq_relative[j * m_warpings.nsamps_torig + i] = 1.0 + t_orig[i] * m_warpings.chirp_rates[j];
|
Chris@0
|
883 //freq_relative[i * m_warpings.nsamps_torig + j] = 1.0 + t_orig[i] * m_warpings.chirp_rates[j];
|
Chris@0
|
884 //freq_relative[i][j] = 1.0 + t_orig[i] * m_warpings.chirp_rates[j];
|
Chris@0
|
885
|
Chris@0
|
886 printf(" End of define_warps_linear_chirps().\n");
|
Chris@0
|
887
|
Chris@0
|
888 }
|
Chris@0
|
889
|
Chris@0
|
890 void
|
Chris@0
|
891 FChTransformF0gram::design_LPF() {
|
Chris@0
|
892
|
Chris@0
|
893 printf(" Running design_LPF().\n");
|
Chris@0
|
894 // in = (fftw_complex*) fftw_malloc(sizeof (fftw_complex) * tamanoVentana);
|
Chris@0
|
895 // out = (fftw_complex*) fftw_malloc(sizeof (fftw_complex) * tamanoVentana);
|
Chris@0
|
896 // in_window = (float*) fftw_malloc(sizeof (float) * tamanoVentana);
|
Chris@0
|
897 // p = fftw_plan_dft_1d(tamanoVentana, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
|
Chris@0
|
898 double *lp_LPFWindow_aux = new double[m_blockSize/2+1];
|
Chris@0
|
899 mp_LPFWindow = new double[m_blockSize/2+1];
|
Chris@0
|
900
|
Chris@0
|
901 size_t i_max = (size_t) ((2.0*m_fmax/m_fs) * ( (double)m_blockSize / 2.0 + 1.0 ));
|
Chris@0
|
902 //printf(" i_max = %d.\n", (int)i_max);
|
Chris@0
|
903 for (size_t i = 0; i < m_blockSize/2+1; i++) {
|
Chris@0
|
904 if (i >= i_max) {
|
Chris@0
|
905 lp_LPFWindow_aux[i] = 0.0;
|
Chris@0
|
906 } else {
|
Chris@0
|
907 lp_LPFWindow_aux[i] = 1.0;
|
Chris@0
|
908 }
|
Chris@0
|
909 }
|
Chris@0
|
910 LPF_time = (double*)fftw_malloc(sizeof ( double) * m_warpings.nsamps_torig);
|
Chris@0
|
911 //memset((char*)LPF_time, 0, m_warpings.nsamps_torig * sizeof(double));
|
Chris@0
|
912 // sustituyo el memset por un for:
|
Chris@0
|
913 for (size_t i = 0; i < m_warpings.nsamps_torig; i++) {
|
Chris@0
|
914 LPF_time[i] = 0.0;
|
Chris@0
|
915 }
|
Chris@0
|
916 #ifdef DEBUG
|
Chris@0
|
917 printf(" Corrio primer memset...\n");
|
Chris@0
|
918 #endif
|
Chris@0
|
919 LPF_frequency = (fftw_complex*)fftw_malloc(sizeof ( fftw_complex) * (m_warpings.nsamps_torig/2 + 1)); //tamaño de la fft cuando la entrada es real
|
Chris@0
|
920 //memset((char*)LPF_frequency, 0, sizeof(fftw_complex) * (m_warpings.nsamps_torig/2 + 1));
|
Chris@0
|
921 // sustituyo el memset por un for:
|
Chris@0
|
922 for (size_t i = 0; i < (m_warpings.nsamps_torig/2 + 1); i++) {
|
Chris@0
|
923 LPF_frequency[i][0] = 0.0;
|
Chris@0
|
924 LPF_frequency[i][1] = 0.0;
|
Chris@0
|
925 }
|
Chris@0
|
926 // for (int i=0; i<(m_blockSize/2+1); i++) {
|
Chris@0
|
927 // LPF_frequency[i] = new fftw_complex;
|
Chris@0
|
928 // }
|
Chris@0
|
929 plan_forward_LPF = fftw_plan_dft_r2c_1d(m_blockSize, LPF_time, LPF_frequency, FFTW_ESTIMATE);
|
Chris@0
|
930 plan_backward_LPF = fftw_plan_dft_c2r_1d(m_warpings.nsamps_torig, LPF_frequency, LPF_time, FFTW_ESTIMATE|FFTW_PRESERVE_INPUT);
|
Chris@0
|
931
|
Chris@0
|
932 size_t winWidth = 11;
|
Chris@0
|
933 double *lp_hanningWindow = new double[winWidth];
|
Chris@0
|
934 double accum=0;
|
Chris@0
|
935 for (size_t i = 0; i < winWidth; i++) {
|
Chris@0
|
936 lp_hanningWindow[i]=0.5*(1.0-cos(2*M_PI*(double)(i+1)/((double)winWidth+1.0)));
|
Chris@0
|
937 accum+=lp_hanningWindow[i];
|
Chris@0
|
938
|
Chris@0
|
939 }
|
Chris@0
|
940 for (size_t i = 0; i < winWidth; i++) { //window normalization
|
Chris@0
|
941 lp_hanningWindow[i]=lp_hanningWindow[i]/accum;
|
Chris@0
|
942 //printf(" lp_hanningWindow[%d] = %f.\n",(int)i,lp_hanningWindow[i]);
|
Chris@0
|
943 }
|
Chris@0
|
944 for (size_t i = 0; i < m_blockSize/2+1; i++) {
|
Chris@0
|
945 //if (((i-(winWidth-1)/2)<0)||(i+(winWidth-1))/2>m_blockSize/2-1) {//consideramos winWidth impar, si la ventana sale del arreglo se rellena con el valor origianl
|
Chris@0
|
946 if ( (i > (i_max + (winWidth-1)/2)) || (i <= (i_max - (winWidth-1)/2)) ) {
|
Chris@0
|
947 mp_LPFWindow[i]=lp_LPFWindow_aux[i];
|
Chris@0
|
948 //printf(" entro al if en i=%d.\n",(int)i);
|
Chris@0
|
949 } else {
|
Chris@0
|
950 accum=0;
|
Chris@0
|
951 for (size_t j = -((winWidth-1)/2); j <= (winWidth-1)/2; j++) {
|
Chris@0
|
952 accum+=lp_LPFWindow_aux[i-j]*lp_hanningWindow[j+(winWidth-1)/2];
|
Chris@0
|
953 //printf(" accum = %f.\n",accum);
|
Chris@0
|
954 }
|
Chris@0
|
955 mp_LPFWindow[i]=accum;
|
Chris@0
|
956 }
|
Chris@0
|
957 }
|
Chris@0
|
958
|
Chris@0
|
959 delete[] lp_LPFWindow_aux;
|
Chris@0
|
960 delete[] lp_hanningWindow;
|
Chris@0
|
961
|
Chris@0
|
962 printf(" End of design_LPF().\n");
|
Chris@0
|
963 }
|
Chris@0
|
964
|
Chris@0
|
965 void FChTransformF0gram::apply_LPF() {
|
Chris@0
|
966 fftw_execute(plan_forward_LPF);
|
Chris@0
|
967 for (size_t i = 0; i < m_blockSize/2+1; i++) {
|
Chris@0
|
968 LPF_frequency[i][0]*=mp_LPFWindow[i];
|
Chris@0
|
969 LPF_frequency[i][1]*=mp_LPFWindow[i];
|
Chris@0
|
970 }
|
Chris@0
|
971 fftw_execute(plan_backward_LPF);
|
Chris@0
|
972
|
Chris@0
|
973 // TODO ver si hay que hacer fftshift para corregir la fase respecto al centro del frame.
|
Chris@0
|
974 // nota: además de aplicar el LPF, esta función resamplea la señal original.
|
Chris@0
|
975 }
|
Chris@0
|
976
|
Chris@0
|
977 void FChTransformF0gram::clean_LPF() {
|
Chris@0
|
978 delete[] mp_LPFWindow;
|
Chris@0
|
979
|
Chris@0
|
980 fftw_destroy_plan(plan_forward_LPF);
|
Chris@0
|
981 fftw_destroy_plan(plan_backward_LPF);
|
Chris@0
|
982 fftw_free(LPF_time);
|
Chris@0
|
983 fftw_free(LPF_frequency);
|
Chris@0
|
984 }
|
Chris@0
|
985
|
Chris@0
|
986 void FChTransformF0gram::reset() {
|
Chris@0
|
987
|
Chris@0
|
988 printf("FUNCTION CALL: %s\n", __FUNCTION__);
|
Chris@0
|
989 // Clear buffers, reset stored values, etc
|
Chris@0
|
990
|
Chris@0
|
991 delete [] m_warpings.pos_int;
|
Chris@0
|
992 delete [] m_warpings.pos_frac;
|
Chris@0
|
993
|
Chris@0
|
994 fftw_destroy_plan(planFFT);
|
Chris@0
|
995 fftw_free(in);
|
Chris@0
|
996 fftw_free(out);
|
Chris@0
|
997
|
Chris@0
|
998 clean_LPF();
|
Chris@0
|
999
|
Chris@0
|
1000 delete [] m_timeWindow;
|
Chris@0
|
1001
|
Chris@0
|
1002 delete [] mp_HanningWindow;
|
Chris@0
|
1003
|
Chris@0
|
1004 // Warping
|
Chris@0
|
1005 delete [] x_warping;
|
Chris@0
|
1006 fftw_destroy_plan(plan_forward_xwarping);
|
Chris@0
|
1007 fftw_free(m_absFanChirpTransform);
|
Chris@0
|
1008 fftw_free(m_auxFanChirpTransform);
|
Chris@0
|
1009
|
Chris@0
|
1010 // design_GLogS
|
Chris@0
|
1011 delete [] m_glogs_f0;
|
Chris@0
|
1012 delete [] m_glogs;
|
Chris@0
|
1013 delete [] m_glogs_n;
|
Chris@0
|
1014 delete [] m_glogs_index;
|
Chris@0
|
1015 delete [] m_glogs_posint;
|
Chris@0
|
1016 delete [] m_glogs_posfrac;
|
Chris@0
|
1017 delete [] m_glogs_third_harmonic_posint;
|
Chris@0
|
1018 delete [] m_glogs_third_harmonic_posfrac;
|
Chris@0
|
1019 delete [] m_glogs_third_harmonic;
|
Chris@0
|
1020 delete [] m_glogs_fifth_harmonic_posint;
|
Chris@0
|
1021 delete [] m_glogs_fifth_harmonic_posfrac;
|
Chris@0
|
1022 delete [] m_glogs_fifth_harmonic;
|
Chris@0
|
1023 delete [] m_glogs_f0_preference_weights;
|
Chris@0
|
1024 delete [] m_glogs_median_correction;
|
Chris@0
|
1025 delete [] m_glogs_sigma_correction;
|
Chris@0
|
1026 delete [] m_glogs_hf_smoothing_window;
|
Chris@0
|
1027
|
Chris@0
|
1028 }
|
Chris@0
|
1029
|
Chris@0
|
1030 FChTransformF0gram::FeatureSet
|
Chris@5
|
1031 FChTransformF0gram::process(const float *const *inputBuffers, Vamp::RealTime) {
|
Chris@0
|
1032
|
Chris@0
|
1033 printf("FUNCTION CALL: %s\n", __FUNCTION__);
|
Chris@0
|
1034
|
Chris@0
|
1035 // // Do actual work!
|
Chris@0
|
1036 //
|
Chris@0
|
1037
|
Chris@0
|
1038 /* PSEUDOCÓDIGO:
|
Chris@0
|
1039 - Aplicar FFT al frame entero.
|
Chris@0
|
1040 - Filtro pasabajos en frecuencia.
|
Chris@0
|
1041 - FFT inversa al frame entero.
|
Chris@0
|
1042 -----------------------------------------------------------------------------
|
Chris@0
|
1043 - Para cada warp: *Si es un espectrograma direccional (un solo warp
|
Chris@0
|
1044 => no es para cada warp sino para el elegido)
|
Chris@0
|
1045 - Hacer la interpolación con interp1q.
|
Chris@0
|
1046 - Aplicar la FFT al frame warpeado.
|
Chris@0
|
1047 - (Opcional) GLogS.
|
Chris@0
|
1048 - ...
|
Chris@0
|
1049 */
|
Chris@0
|
1050
|
Chris@0
|
1051 //---------------------------------------------------------------------------
|
Chris@0
|
1052 FeatureSet fs;
|
Chris@0
|
1053
|
Chris@0
|
1054 #ifdef DEBUG
|
Chris@0
|
1055 printf("\n ----- DEBUG INFORMATION ----- \n");
|
Chris@0
|
1056 printf(" m_fs = %f Hz.\n",m_fs);
|
Chris@0
|
1057 printf(" fs_orig = %f Hz.\n",m_warpings.fs_orig);
|
Chris@0
|
1058 printf(" fs_warp = %f Hz.\n",m_warpings.fs_warp);
|
Chris@0
|
1059 printf(" m_nfft = %d.\n",m_nfft);
|
Chris@0
|
1060 printf(" m_blockSize = %d.\n",m_blockSize);
|
Chris@0
|
1061 printf(" m_warpings.nsamps_torig = %d.\n",m_warpings.nsamps_torig);
|
Chris@0
|
1062 printf(" m_warp_params.num_warps = %d.\n",m_warp_params.num_warps);
|
Chris@0
|
1063 printf(" m_glogs_harmonic_count = %d.\n",m_glogs_harmonic_count);
|
Chris@0
|
1064 #endif
|
Chris@0
|
1065
|
Chris@0
|
1066 // size_t n = m_nfft/2 + 1;
|
Chris@0
|
1067 // double *tbuf = in_window;
|
Chris@0
|
1068
|
Chris@0
|
1069 for (size_t i = 0; i < m_blockSize; i++) {
|
Chris@0
|
1070 LPF_time[i] = (double)(inputBuffers[0][i]) * m_timeWindow[i];
|
Chris@0
|
1071 }
|
Chris@0
|
1072
|
Chris@0
|
1073 // #ifdef DEBUG
|
Chris@0
|
1074 // printf(" HASTA ACÁ ANDA!!!\n");
|
Chris@0
|
1075 // cout << flush;
|
Chris@0
|
1076 // #endif
|
Chris@0
|
1077
|
Chris@0
|
1078 apply_LPF();
|
Chris@0
|
1079 // Señal filtrada queda en LPF_time
|
Chris@0
|
1080
|
Chris@0
|
1081 Feature feature;
|
Chris@0
|
1082 feature.hasTimestamp = false;
|
Chris@0
|
1083
|
Chris@0
|
1084
|
Chris@0
|
1085 /* Solo a modo de prueba, voy a poner la salida del filtrado en «in» y
|
Chris@0
|
1086 voy a mostrar la FFT de eso, para ver el efecto del filtrado. */
|
Chris@0
|
1087 // for (size_t i = 0; i < m_nfft; i++) {
|
Chris@0
|
1088 // in[i][0] = tbuf[i];
|
Chris@0
|
1089 // in[i][1] = 0;
|
Chris@0
|
1090 // }
|
Chris@0
|
1091 // fftw_execute(planFFT);
|
Chris@0
|
1092 // double real, imag;
|
Chris@0
|
1093 // for (size_t i=0; i<n; ++i) { // preincremento?? ver version de nacho
|
Chris@0
|
1094 // real = out[i][0];
|
Chris@0
|
1095 // imag = out[i][1];
|
Chris@0
|
1096 // feature.values.push_back(real*real + imag*imag);
|
Chris@0
|
1097 // }
|
Chris@0
|
1098 // fs[0].push_back(feature);
|
Chris@0
|
1099
|
Chris@0
|
1100 // float real;
|
Chris@0
|
1101 // float imag;
|
Chris@0
|
1102 // for (size_t i=0; i<m_blockSize/2+1; i++) {
|
Chris@0
|
1103 // real = (float)(LPF_frequency[i][0]);
|
Chris@0
|
1104 // imag = (float)(LPF_frequency[i][1]);
|
Chris@0
|
1105 // feature.values.push_back(real*real+imag*imag);
|
Chris@0
|
1106 // //feature.values.push_back((float)(mp_LPFWindow[i]));
|
Chris@0
|
1107 // }
|
Chris@0
|
1108
|
Chris@0
|
1109 // ----------------------------------------------------------------------------------------------
|
Chris@0
|
1110 // Hanning window & FFT for all warp directions
|
Chris@0
|
1111
|
Chris@0
|
1112 double max_glogs = -DBL_MAX;
|
Chris@0
|
1113 size_t ind_max_glogs = 0;
|
Chris@0
|
1114
|
Chris@0
|
1115 for (size_t i_warp = 0; i_warp < m_warp_params.num_warps; i_warp++) {
|
Chris@0
|
1116 // Interpolate
|
Chris@0
|
1117 interp1q(LPF_time, (m_warpings.pos_int) + i_warp*m_warp_params.nsamps_twarp, m_warpings.pos_frac + i_warp*m_warp_params.nsamps_twarp, x_warping, m_warp_params.nsamps_twarp);
|
Chris@0
|
1118
|
Chris@0
|
1119 // Apply window
|
Chris@0
|
1120 for (size_t i = 0; i < m_warp_params.nsamps_twarp; i++) {
|
Chris@0
|
1121 x_warping[i] *= mp_HanningWindow[i];
|
Chris@0
|
1122 }
|
Chris@0
|
1123
|
Chris@0
|
1124 // Transform
|
Chris@0
|
1125 fftw_execute(plan_forward_xwarping);
|
Chris@0
|
1126
|
Chris@0
|
1127 // Copy result
|
Chris@0
|
1128 //memcpy(m_absFanChirpTransform + i_warp*(m_warp_params.nsamps_twarp/2+1), m_auxFanChirpTransform, (m_warp_params.nsamps_twarp/2+1)*sizeof(fftw_complex)); asi como esta no funciona
|
Chris@0
|
1129 double *aux_abs_fcht = m_absFanChirpTransform + i_warp*(m_warp_params.nsamps_twarp/2+1);
|
Chris@0
|
1130 for (size_t i = 0; i < (m_warp_params.nsamps_twarp/2+1); i++) {
|
Chris@0
|
1131 aux_abs_fcht[i] = log10(1.0 + 10.0*sqrt(m_auxFanChirpTransform[i][0]*m_auxFanChirpTransform[i][0]+m_auxFanChirpTransform[i][1]*m_auxFanChirpTransform[i][1]));
|
Chris@0
|
1132 // smoothing high frequency values
|
Chris@0
|
1133 //aux_abs_fcht[i] *= m_glogs_hf_smoothing_window[i];
|
Chris@0
|
1134 }
|
Chris@0
|
1135
|
Chris@0
|
1136 // -----------------------------------------------------------------------------------------
|
Chris@0
|
1137 // GLogS
|
Chris@0
|
1138 interp1q(aux_abs_fcht, m_glogs_posint, m_glogs_posfrac, m_glogs_interp, m_glogs_harmonic_count);
|
Chris@0
|
1139 size_t glogs_ind = 0;
|
Chris@0
|
1140 for (size_t i = 0; i < m_glogs_num_f0s; i++) {
|
Chris@0
|
1141 double glogs_accum = 0;
|
Chris@0
|
1142 for (size_t j = 1; j <= m_glogs_n[i]; j++) {
|
Chris@0
|
1143 glogs_accum += m_glogs_interp[glogs_ind++];
|
Chris@0
|
1144 }
|
Chris@0
|
1145 m_glogs[i + i_warp*m_glogs_num_f0s] = glogs_accum/(double)m_glogs_n[i];
|
Chris@0
|
1146 }
|
Chris@0
|
1147 //printf(" glogs_ind = %d.\n",(int)glogs_ind);
|
Chris@0
|
1148
|
Chris@0
|
1149 // Sub/super harmonic correction
|
Chris@0
|
1150 interp1q(m_glogs + i_warp*m_glogs_num_f0s, m_glogs_third_harmonic_posint, m_glogs_third_harmonic_posfrac, m_glogs_third_harmonic, (m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct);
|
Chris@0
|
1151 interp1q(m_glogs + i_warp*m_glogs_num_f0s, m_glogs_fifth_harmonic_posint, m_glogs_fifth_harmonic_posfrac, m_glogs_fifth_harmonic, (m_f0_params.num_octs+1)*m_f0_params.num_f0s_per_oct);
|
Chris@0
|
1152 for (size_t i = m_glogs_num_f0s-1; i >= m_glogs_init_f0s; i--) {
|
Chris@0
|
1153 m_glogs[i + i_warp*m_glogs_num_f0s] -= MAX(MAX(m_glogs[i-m_f0_params.num_f0s_per_oct + i_warp*m_glogs_num_f0s],m_glogs_third_harmonic[i-m_glogs_init_f0s]),m_glogs_fifth_harmonic[i-m_glogs_init_f0s]);
|
Chris@0
|
1154 //m_glogs[i] -= MAX(m_glogs[i-m_f0_params.num_f0s_per_oct],m_glogs_third_harmonic[i-m_glogs_init_f0s]);
|
Chris@0
|
1155 }
|
Chris@0
|
1156 for (size_t i = m_glogs_init_f0s; i < m_glogs_num_f0s-m_f0_params.num_f0s_per_oct; i++) {
|
Chris@0
|
1157 m_glogs[i + i_warp*m_glogs_num_f0s] -= 0.3*m_glogs[i+m_f0_params.num_f0s_per_oct + i_warp*m_glogs_num_f0s];
|
Chris@0
|
1158 // Median, sigma $ weights correction
|
Chris@0
|
1159 m_glogs[i + i_warp*m_glogs_num_f0s] = (m_glogs[i + i_warp*m_glogs_num_f0s]-m_glogs_median_correction[i-m_glogs_init_f0s])*m_glogs_sigma_correction[i-m_glogs_init_f0s]*m_glogs_f0_preference_weights[i-m_glogs_init_f0s];
|
Chris@0
|
1160 }
|
Chris@0
|
1161
|
Chris@0
|
1162 // Look for maximum value to determine best direction
|
Chris@0
|
1163 for (size_t i = m_glogs_init_f0s; i < m_glogs_num_f0s-m_f0_params.num_f0s_per_oct; i++) {
|
Chris@0
|
1164 if (m_glogs[i + i_warp*m_glogs_num_f0s] > max_glogs) {
|
Chris@0
|
1165 max_glogs = m_glogs[i + i_warp*m_glogs_num_f0s];
|
Chris@0
|
1166 ind_max_glogs = i_warp;
|
Chris@0
|
1167 }
|
Chris@0
|
1168 }
|
Chris@0
|
1169 }
|
Chris@0
|
1170
|
Chris@0
|
1171 // ----------------------------------------------------------------------------------------------
|
Chris@0
|
1172
|
Chris@0
|
1173 for (size_t i=m_glogs_init_f0s; i< m_glogs_num_f0s - m_f0_params.num_f0s_per_oct; i++) {
|
Chris@0
|
1174 //for (size_t i=0; i<(m_warp_params.nsamps_twarp/2+1); i++) {
|
Chris@0
|
1175 //feature.values.push_back((float)(m_warpings.pos_int[i])+ (float)(m_warpings.pos_frac[i]));
|
Chris@0
|
1176 //feature.values.push_back((float)(phi[i]*100000.0));
|
Chris@0
|
1177 //feature.values.push_back((float)(t_orig[i]));
|
Chris@0
|
1178 //feature.values.push_back((float)(pos1[i]));
|
Chris@0
|
1179 //feature.values.push_back((float)x_warping[i]);
|
Chris@0
|
1180 //feature.values.push_back(m_absFanChirpTransform[i + ind_max_glogs*(m_warp_params.nsamps_twarp/2+1)]);
|
Chris@0
|
1181 //feature.values.push_back((float)m_glogs[i+(long)ind_max_glogs*(long)m_glogs_num_f0s]);
|
Chris@0
|
1182 switch (m_f0gram_mode) {
|
Chris@0
|
1183 case 1:
|
Chris@0
|
1184 max_glogs = -DBL_MAX;
|
Chris@0
|
1185 for (size_t i_warp = 0; i_warp < m_warp_params.num_warps; i_warp++) {
|
Chris@0
|
1186 if (m_glogs[i + i_warp*m_glogs_num_f0s] > max_glogs) {
|
Chris@0
|
1187 max_glogs = m_glogs[i + i_warp*m_glogs_num_f0s];
|
Chris@0
|
1188 ind_max_glogs = i_warp;
|
Chris@0
|
1189 }
|
Chris@0
|
1190 }
|
Chris@0
|
1191 feature.values.push_back((float)max_glogs);
|
Chris@0
|
1192 break;
|
Chris@0
|
1193 case 0:
|
Chris@0
|
1194 feature.values.push_back((float)m_glogs[i+(size_t)ind_max_glogs*(size_t)m_glogs_num_f0s]);
|
Chris@0
|
1195 break;
|
Chris@0
|
1196 }
|
Chris@0
|
1197 //feature.values.push_back((float)m_glogs_hf_smoothing_window[i]);
|
Chris@0
|
1198 }
|
Chris@0
|
1199
|
Chris@0
|
1200 // ----------------------------------------------------------------------------------------------
|
Chris@0
|
1201
|
Chris@0
|
1202 fs[0].push_back(feature);
|
Chris@0
|
1203
|
Chris@0
|
1204 #ifdef DEBUG
|
Chris@0
|
1205 printf(" ----------------------------- \n");
|
Chris@0
|
1206 #endif
|
Chris@0
|
1207
|
Chris@0
|
1208 return fs;
|
Chris@0
|
1209 //---------------------------------------------------------------------------
|
Chris@0
|
1210
|
Chris@0
|
1211 //return FeatureSet();
|
Chris@0
|
1212 }
|
Chris@0
|
1213
|
Chris@0
|
1214 FChTransformF0gram::FeatureSet
|
Chris@0
|
1215 FChTransformF0gram::getRemainingFeatures() {
|
Chris@0
|
1216
|
Chris@0
|
1217 printf("FUNCTION CALL: %s\n", __FUNCTION__);
|
Chris@0
|
1218
|
Chris@0
|
1219 return FeatureSet();
|
Chris@0
|
1220 }
|
Chris@0
|
1221
|
Chris@0
|
1222 void
|
Chris@0
|
1223 FChTransformF0gram::design_time_window() {
|
Chris@0
|
1224
|
Chris@0
|
1225 printf(" Running design_time_window().\n");
|
Chris@0
|
1226
|
Chris@0
|
1227 size_t transitionWidth = (size_t)m_blockSize/128 + 1;;
|
Chris@0
|
1228 m_timeWindow = new double[m_blockSize];
|
Chris@0
|
1229 double *lp_transitionWindow = new double[transitionWidth];
|
Chris@0
|
1230
|
Chris@0
|
1231 //memset(m_timeWindow, 1.0, m_blockSize);
|
Chris@0
|
1232 for (size_t i = 0; i < m_blockSize; i++) {
|
Chris@0
|
1233 m_timeWindow[i] = 1.0;
|
Chris@0
|
1234 }
|
Chris@0
|
1235
|
Chris@0
|
1236 for (size_t i = 0; i < transitionWidth; i++) {
|
Chris@0
|
1237 lp_transitionWindow[i]=0.5*(1.0-cos(2*M_PI*(double)(i+1)/((double)transitionWidth+1.0)));
|
Chris@0
|
1238 }
|
Chris@0
|
1239
|
Chris@0
|
1240 for (size_t i = 0; i < transitionWidth/2; i++) {
|
Chris@0
|
1241 m_timeWindow[i] = lp_transitionWindow[i];
|
Chris@0
|
1242 m_timeWindow[m_blockSize-1-i] = lp_transitionWindow[transitionWidth-1-i];
|
Chris@0
|
1243 }
|
Chris@0
|
1244
|
Chris@0
|
1245 #ifdef DEBUG
|
Chris@0
|
1246 for (int i = 0; i < m_blockSize; i++) {
|
Chris@0
|
1247 if ((i<transitionWidth)) {
|
Chris@0
|
1248 printf(" m_timeWindow[%d] = %f.\n",i,m_timeWindow[i]);
|
Chris@0
|
1249 }
|
Chris@0
|
1250 }
|
Chris@0
|
1251 #endif
|
Chris@0
|
1252
|
Chris@0
|
1253 delete [] lp_transitionWindow;
|
Chris@0
|
1254
|
Chris@0
|
1255 printf(" End of design_time_window().\n");
|
Chris@0
|
1256 }
|
Chris@0
|
1257
|