jamie@1
|
1 /* libxtract feature extraction library
|
jamie@1
|
2 *
|
jamie@1
|
3 * Copyright (C) 2006 Jamie Bullock
|
jamie@1
|
4 *
|
jamie@1
|
5 * This program is free software; you can redistribute it and/or modify
|
jamie@1
|
6 * it under the terms of the GNU General Public License as published by
|
jamie@1
|
7 * the Free Software Foundation; either version 2 of the License, or
|
jamie@1
|
8 * (at your option) any later version.
|
jamie@1
|
9 *
|
jamie@1
|
10 * This program is distributed in the hope that it will be useful,
|
jamie@1
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
jamie@1
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
jamie@1
|
13 * GNU General Public License for more details.
|
jamie@1
|
14 *
|
jamie@1
|
15 * You should have received a copy of the GNU General Public License
|
jamie@1
|
16 * along with this program; if not, write to the Free Software
|
jamie@1
|
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
jamie@1
|
18 * USA.
|
jamie@1
|
19 */
|
jamie@1
|
20
|
jamie@1
|
21 /* init.c: defines functions that extract a feature as a single value from an input vector */
|
jamie@1
|
22
|
jamie@1
|
23 #include "xtract/libxtract.h"
|
jamie@1
|
24 #include <math.h>
|
jamie@26
|
25 #include <stdlib.h>
|
jamie@1
|
26
|
jamie@1
|
27 int xtract_init_mfcc(int N, float nyquist, int style, float freq_max, float freq_min, int freq_bands, float **fft_tables){
|
jamie@1
|
28
|
jamie@1
|
29 int n,i, *fft_peak, M;
|
jamie@1
|
30 float norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val,
|
jamie@1
|
31 freq_bw_mel, *mel_peak, *height_norm, *lin_peak;
|
jamie@1
|
32
|
jamie@1
|
33
|
jamie@1
|
34 mel_peak = height_norm = lin_peak = NULL;
|
jamie@1
|
35 fft_peak = NULL;
|
jamie@1
|
36 norm = 1;
|
jamie@1
|
37
|
jamie@1
|
38 mel_freq_max = 1127 * log(1 + freq_max / 700);
|
jamie@1
|
39 mel_freq_min = 1127 * log(1 + freq_min / 700);
|
jamie@1
|
40 freq_bw_mel = (mel_freq_max - mel_freq_min) / freq_bands;
|
jamie@1
|
41
|
jamie@1
|
42 mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
|
jamie@1
|
43 /* +2 for zeros at start and end */
|
jamie@1
|
44 lin_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
|
jamie@1
|
45 fft_peak = (int *)malloc((freq_bands + 2) * sizeof(int));
|
jamie@1
|
46 height_norm = (float *)malloc(freq_bands * sizeof(float));
|
jamie@1
|
47
|
jamie@1
|
48 if(mel_peak == NULL || height_norm == NULL ||
|
jamie@1
|
49 lin_peak == NULL || fft_peak == NULL)
|
jamie@1
|
50 return MALLOC_FAILED;
|
jamie@1
|
51
|
jamie@1
|
52 M = N >> 1;
|
jamie@1
|
53
|
jamie@1
|
54 mel_peak[0] = mel_freq_min;
|
jamie@1
|
55 lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1);
|
jamie@1
|
56 fft_peak[0] = lin_peak[0] / nyquist * M;
|
jamie@1
|
57
|
jamie@1
|
58
|
jamie@1
|
59 for (n = 1; n <= freq_bands; n++){
|
jamie@1
|
60 /*roll out peak locations - mel, linear and linear on fft window scale */
|
jamie@1
|
61 mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
|
jamie@1
|
62 lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
|
jamie@1
|
63 fft_peak[n] = lin_peak[n] / nyquist * M;
|
jamie@1
|
64 }
|
jamie@1
|
65
|
jamie@1
|
66 for (n = 0; n < freq_bands; n++){
|
jamie@1
|
67 /*roll out normalised gain of each peak*/
|
jamie@1
|
68 if (style == EQUAL_GAIN){
|
jamie@1
|
69 height = 1;
|
jamie@1
|
70 norm_fact = norm;
|
jamie@1
|
71 }
|
jamie@1
|
72 else{
|
jamie@1
|
73 height = 2 / (lin_peak[n + 2] - lin_peak[n]);
|
jamie@1
|
74 norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
|
jamie@1
|
75 }
|
jamie@1
|
76 height_norm[n] = height * norm_fact;
|
jamie@1
|
77 }
|
jamie@1
|
78
|
jamie@1
|
79 i = 0;
|
jamie@1
|
80
|
jamie@1
|
81 for(n = 0; n < freq_bands; n++){
|
jamie@1
|
82 if(n > 0)
|
jamie@1
|
83 /*calculate the rise increment*/
|
jamie@1
|
84 inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
|
jamie@1
|
85 else
|
jamie@1
|
86 inc = height_norm[n] / fft_peak[n];
|
jamie@1
|
87 val = 0;
|
jamie@1
|
88 for(; i <= fft_peak[n]; i++){
|
jamie@1
|
89 /*fill in the 'rise' */
|
jamie@1
|
90 fft_tables[n][i] = val;
|
jamie@1
|
91 val += inc;
|
jamie@1
|
92 }
|
jamie@1
|
93 inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
|
jamie@1
|
94 /*calculate the fall increment */
|
jamie@1
|
95 val = 0;
|
jamie@1
|
96 for(i = fft_peak[n + 1]; i > fft_peak[n]; i--){
|
jamie@1
|
97 /*reverse fill the 'fall' */
|
jamie@1
|
98 fft_tables[n][i] = val;
|
jamie@1
|
99 val += inc;
|
jamie@1
|
100 }
|
jamie@1
|
101 }
|
jamie@1
|
102
|
jamie@1
|
103
|
jamie@1
|
104 free(mel_peak);
|
jamie@1
|
105 free(lin_peak);
|
jamie@1
|
106 free(height_norm);
|
jamie@1
|
107 free(fft_peak);
|
jamie@1
|
108
|
jamie@1
|
109 return SUCCESS;
|
jamie@1
|
110
|
jamie@1
|
111 }
|
jamie@1
|
112
|
jamie@1
|
113 int xtract_init_bark(int N, float nyquist, int *band_limits){
|
jamie@1
|
114
|
jamie@38
|
115 float edges[] = {0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, 20500, 27000}; /* Takes us up to sr = 54kHz (CCRMA: JOS)*/
|
jamie@1
|
116
|
jamie@1
|
117 int M, bands = BARK_BANDS;
|
jamie@1
|
118
|
jamie@1
|
119 M = N >> 1;
|
jamie@1
|
120
|
jamie@1
|
121 while(bands--)
|
jamie@1
|
122 band_limits[bands] = edges[bands] / nyquist * M;
|
jamie@1
|
123 /*FIX shohuld use rounding, but couldn't get it to work */
|
jamie@38
|
124
|
jamie@38
|
125 return SUCCESS;
|
jamie@1
|
126 }
|