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@43
|
27 int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq_max, int freq_bands, float **fft_tables){
|
jamie@1
|
28
|
jamie@39
|
29 int n, i, k, *fft_peak, M, next_peak;
|
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 mel_peak = height_norm = lin_peak = NULL;
|
jamie@1
|
34 fft_peak = NULL;
|
jamie@1
|
35 norm = 1;
|
jamie@1
|
36
|
jamie@1
|
37 mel_freq_max = 1127 * log(1 + freq_max / 700);
|
jamie@1
|
38 mel_freq_min = 1127 * log(1 + freq_min / 700);
|
jamie@1
|
39 freq_bw_mel = (mel_freq_max - mel_freq_min) / freq_bands;
|
jamie@1
|
40
|
jamie@1
|
41 mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
|
jamie@1
|
42 /* +2 for zeros at start and end */
|
jamie@1
|
43 lin_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
|
jamie@1
|
44 fft_peak = (int *)malloc((freq_bands + 2) * sizeof(int));
|
jamie@1
|
45 height_norm = (float *)malloc(freq_bands * sizeof(float));
|
jamie@1
|
46
|
jamie@1
|
47 if(mel_peak == NULL || height_norm == NULL ||
|
jamie@1
|
48 lin_peak == NULL || fft_peak == NULL)
|
jamie@1
|
49 return MALLOC_FAILED;
|
jamie@39
|
50
|
jamie@1
|
51 M = N >> 1;
|
jamie@1
|
52
|
jamie@1
|
53 mel_peak[0] = mel_freq_min;
|
jamie@1
|
54 lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1);
|
jamie@1
|
55 fft_peak[0] = lin_peak[0] / nyquist * M;
|
jamie@1
|
56
|
jamie@1
|
57
|
jamie@1
|
58 for (n = 1; n <= freq_bands; n++){
|
jamie@1
|
59 /*roll out peak locations - mel, linear and linear on fft window scale */
|
jamie@1
|
60 mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
|
jamie@1
|
61 lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
|
jamie@1
|
62 fft_peak[n] = lin_peak[n] / nyquist * M;
|
jamie@1
|
63 }
|
jamie@1
|
64
|
jamie@1
|
65 for (n = 0; n < freq_bands; n++){
|
jamie@1
|
66 /*roll out normalised gain of each peak*/
|
jamie@1
|
67 if (style == EQUAL_GAIN){
|
jamie@1
|
68 height = 1;
|
jamie@1
|
69 norm_fact = norm;
|
jamie@1
|
70 }
|
jamie@1
|
71 else{
|
jamie@1
|
72 height = 2 / (lin_peak[n + 2] - lin_peak[n]);
|
jamie@1
|
73 norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
|
jamie@1
|
74 }
|
jamie@1
|
75 height_norm[n] = height * norm_fact;
|
jamie@1
|
76 }
|
jamie@1
|
77
|
jamie@1
|
78 i = 0;
|
jamie@1
|
79
|
jamie@1
|
80 for(n = 0; n < freq_bands; n++){
|
jamie@39
|
81
|
jamie@39
|
82 /*calculate the rise increment*/
|
jamie@1
|
83 if(n > 0)
|
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@39
|
88
|
jamie@39
|
89 /*zero the start of the array*/
|
jamie@39
|
90 for(k = 0; k < i; k++)
|
jamie@39
|
91 fft_tables[n][k] = 0.f;
|
jamie@39
|
92
|
jamie@39
|
93 /*fill in the rise */
|
jamie@1
|
94 for(; i <= fft_peak[n]; i++){
|
jamie@1
|
95 fft_tables[n][i] = val;
|
jamie@1
|
96 val += inc;
|
jamie@1
|
97 }
|
jamie@39
|
98
|
jamie@39
|
99 /*calculate the fall increment */
|
jamie@1
|
100 inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
|
jamie@39
|
101
|
jamie@1
|
102 val = 0;
|
jamie@39
|
103 next_peak = fft_peak[n + 1];
|
jamie@39
|
104
|
jamie@39
|
105 /*reverse fill the 'fall' */
|
jamie@39
|
106 for(i = next_peak; i > fft_peak[n]; i--){
|
jamie@1
|
107 fft_tables[n][i] = val;
|
jamie@1
|
108 val += inc;
|
jamie@1
|
109 }
|
jamie@39
|
110
|
jamie@39
|
111 /*zero the rest of the array*/
|
jamie@39
|
112 for(k = next_peak + 1; k < N; k++)
|
jamie@39
|
113 fft_tables[n][k] = 0.f;
|
jamie@1
|
114 }
|
jamie@1
|
115
|
jamie@1
|
116 free(mel_peak);
|
jamie@1
|
117 free(lin_peak);
|
jamie@1
|
118 free(height_norm);
|
jamie@1
|
119 free(fft_peak);
|
jamie@1
|
120
|
jamie@1
|
121 return SUCCESS;
|
jamie@1
|
122
|
jamie@1
|
123 }
|
jamie@1
|
124
|
jamie@1
|
125 int xtract_init_bark(int N, float nyquist, int *band_limits){
|
jamie@1
|
126
|
jamie@38
|
127 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
|
128
|
jamie@1
|
129 int M, bands = BARK_BANDS;
|
jamie@1
|
130
|
jamie@1
|
131 M = N >> 1;
|
jamie@1
|
132
|
jamie@1
|
133 while(bands--)
|
jamie@1
|
134 band_limits[bands] = edges[bands] / nyquist * M;
|
jamie@1
|
135 /*FIX shohuld use rounding, but couldn't get it to work */
|
jamie@38
|
136
|
jamie@38
|
137 return SUCCESS;
|
jamie@1
|
138 }
|