aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am15
-rw-r--r--src/delta.c49
-rw-r--r--src/init.c124
-rw-r--r--src/libxtract.c87
-rw-r--r--src/scalar.c414
-rw-r--r--src/vector.c228
6 files changed, 917 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..cf4125c
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,15 @@
+
+
+
+SOURCES = libxtract.c scalar.c delta.c init.c
+
+if BUILD_VECTOR
+VECTOR = vector.c
+else
+VECTOR =
+endif
+
+lib_LTLIBRARIES = libxtract.la
+libxtract_la_CFLAGS = -pedantic -ansi -g -O0 -ggdb
+libxtract_la_SOURCES = $(SOURCES) $(VECTOR)
+libxtract_la_LDFLAGS = -shared
diff --git a/src/delta.c b/src/delta.c
new file mode 100644
index 0000000..c947c0a
--- /dev/null
+++ b/src/delta.c
@@ -0,0 +1,49 @@
+/* libxtract feature extraction library
+ *
+ * Copyright (C) 2006 Jamie Bullock
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+/* xtract_delta.c: defines functions that extract a feature as a single value from more than one input vector */
+
+#include "xtract/xtract_delta.h"
+#include "xtract/xtract_macros.h"
+
+int xtract_flux(float *data, int N, void *argv , float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
+int xtract_attack_time(float *data, int N, void *argv , float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
+int xtract_decay_time(float *data, int N, void *argv, float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
+int xtract_delta_feature(float *data, int N, void *argv, float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
diff --git a/src/init.c b/src/init.c
new file mode 100644
index 0000000..5b7bdf2
--- /dev/null
+++ b/src/init.c
@@ -0,0 +1,124 @@
+/* libxtract feature extraction library
+ *
+ * Copyright (C) 2006 Jamie Bullock
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+/* init.c: defines functions that extract a feature as a single value from an input vector */
+
+#include "xtract/libxtract.h"
+#include <math.h>
+#include <string.h>
+
+int xtract_init_mfcc(int N, float nyquist, int style, float freq_max, float freq_min, int freq_bands, float **fft_tables){
+
+ int n,i, *fft_peak, M;
+ float norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val,
+ freq_bw_mel, *mel_peak, *height_norm, *lin_peak;
+
+
+ mel_peak = height_norm = lin_peak = NULL;
+ fft_peak = NULL;
+ norm = 1;
+
+ mel_freq_max = 1127 * log(1 + freq_max / 700);
+ mel_freq_min = 1127 * log(1 + freq_min / 700);
+ freq_bw_mel = (mel_freq_max - mel_freq_min) / freq_bands;
+
+ mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
+ /* +2 for zeros at start and end */
+ lin_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
+ fft_peak = (int *)malloc((freq_bands + 2) * sizeof(int));
+ height_norm = (float *)malloc(freq_bands * sizeof(float));
+
+ if(mel_peak == NULL || height_norm == NULL ||
+ lin_peak == NULL || fft_peak == NULL)
+ return MALLOC_FAILED;
+
+ M = N >> 1;
+
+ mel_peak[0] = mel_freq_min;
+ lin_peak[0] = 700 * (exp(mel_peak[0] / 1127) - 1);
+ fft_peak[0] = lin_peak[0] / nyquist * M;
+
+
+ for (n = 1; n <= freq_bands; n++){
+ /*roll out peak locations - mel, linear and linear on fft window scale */
+ mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
+ lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
+ fft_peak[n] = lin_peak[n] / nyquist * M;
+ }
+
+ for (n = 0; n < freq_bands; n++){
+ /*roll out normalised gain of each peak*/
+ if (style == EQUAL_GAIN){
+ height = 1;
+ norm_fact = norm;
+ }
+ else{
+ height = 2 / (lin_peak[n + 2] - lin_peak[n]);
+ norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
+ }
+ height_norm[n] = height * norm_fact;
+ }
+
+ i = 0;
+
+ for(n = 0; n < freq_bands; n++){
+ if(n > 0)
+ /*calculate the rise increment*/
+ inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
+ else
+ inc = height_norm[n] / fft_peak[n];
+ val = 0;
+ for(; i <= fft_peak[n]; i++){
+ /*fill in the 'rise' */
+ fft_tables[n][i] = val;
+ val += inc;
+ }
+ inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
+ /*calculate the fall increment */
+ val = 0;
+ for(i = fft_peak[n + 1]; i > fft_peak[n]; i--){
+ /*reverse fill the 'fall' */
+ fft_tables[n][i] = val;
+ val += inc;
+ }
+ }
+
+
+ free(mel_peak);
+ free(lin_peak);
+ free(height_norm);
+ free(fft_peak);
+
+ return SUCCESS;
+
+}
+
+int xtract_init_bark(int N, float nyquist, int *band_limits){
+
+ float bark_freq_max, bark_freq_min, freq_bw_bark, temp, 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)*/
+
+ int M, bands = BARK_BANDS;
+
+ M = N >> 1;
+
+ while(bands--)
+ band_limits[bands] = edges[bands] / nyquist * M;
+ /*FIX shohuld use rounding, but couldn't get it to work */
+}
diff --git a/src/libxtract.c b/src/libxtract.c
new file mode 100644
index 0000000..afd2581
--- /dev/null
+++ b/src/libxtract.c
@@ -0,0 +1,87 @@
+/* libxtract feature extraction library
+ *
+ * Copyright (C) 2006 Jamie Bullock
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+/* libxtract - library for feature extraction from 1D vectors
+Copyright (C) 2006 Jamie Bullock
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+
+#include "xtract/libxtract.h"
+
+int(*xtract[])(float *, int, void *, float *) = {
+ /* xtract_scalar.h */
+ xtract_mean,
+ xtract_variance,
+ xtract_standard_deviation,
+ xtract_average_deviation,
+ xtract_skewness,
+ xtract_kurtosis,
+ xtract_irregularity_k,
+ xtract_irregularity_j,
+ xtract_tristimulus_1,
+ xtract_tristimulus_2,
+ xtract_tristimulus_3,
+ xtract_smoothness,
+ xtract_spread,
+ xtract_zcr,
+ xtract_rolloff,
+ xtract_loudness,
+ xtract_flatness,
+ xtract_tonality,
+ xtract_crest,
+ xtract_noisiness,
+ xtract_rms_amplitude,
+ xtract_inharmonicity,
+ xtract_power,
+ xtract_odd_even_ratio,
+ xtract_sharpness,
+ xtract_slope,
+ xtract_f0,
+ xtract_hps,
+ /* xtract_vector.h */
+ xtract_magnitude_spectrum,
+ xtract_autocorrelation,
+ xtract_autocorrelation_fft,
+ xtract_amdf,
+ xtract_asdf,
+ xtract_mfcc,
+ xtract_dct,
+ xtract_bark_coefficients,
+ xtract_peaks,
+ /* xtract_delta.h */
+ xtract_flux,
+ xtract_attack_time,
+ xtract_decay_time,
+ xtract_delta_feature
+};
diff --git a/src/scalar.c b/src/scalar.c
new file mode 100644
index 0000000..a7191ef
--- /dev/null
+++ b/src/scalar.c
@@ -0,0 +1,414 @@
+/* libxtract feature extraction library
+ *
+ * Copyright (C) 2006 Jamie Bullock
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+
+/* xtract_scalar.c: defines functions that extract a feature as a single value from an input vector */
+
+#include "xtract/libxtract.h"
+#include "math.h"
+
+int xtract_mean(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ while(n--)
+ *result += *data++;
+
+ *result /= N;
+}
+
+int xtract_variance(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ while(n--)
+ *result += *data++ - *(float *)argv;
+
+ *result = SQ(*result) / (N - 1);
+}
+
+int xtract_standard_deviation(float *data, int N, void *argv, float *result){
+
+ *result = sqrt(*(float *)argv);
+
+}
+
+int xtract_average_deviation(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ while(n--)
+ *result += fabs(*data++ - *(float *)argv);
+
+ *result /= N;
+
+}
+
+int xtract_skewness(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ while(n--)
+ *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1];
+
+ *result = pow(*result, 3) / N;
+
+}
+
+int xtract_kurtosis(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ while(n--)
+ *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1];
+
+ *result = pow(*result, 4) / N - 3;
+
+}
+
+int xtract_irregularity_k(float *data, int N, void *argv, float *result){
+
+ int n,
+ M = M - 1;
+
+ for(n = 1; n < M; n++)
+ *result += abs(data[n] - (data[n-1] + data[n] + data[n+1]) / 3);
+
+}
+
+int xtract_irregularity_j(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ float num, den;
+
+ while(n--){
+ num += data[n] - data[n+1];
+ den += data[n] * data[n];
+ }
+
+ *result = num / den;
+
+}
+
+int xtract_tristimulus_1(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ float den;
+
+ while(n--)
+ den += data[n];
+
+ *result = data[0] / den;
+
+}
+
+int xtract_tristimulus_2(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ float den;
+
+ while(n--)
+ den += data[n];
+
+ *result = (data[1] + data[2] + data[3]) / den;
+
+}
+
+int xtract_tristimulus_3(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ float den, num;
+
+ while(n--)
+ den += data[n];
+
+ num = den - data[0] + data[1] + data[2] + data[3];
+
+ *result = num / den;
+
+}
+
+int xtract_smoothness(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ if (data[0] <= 0) data[0] = 1;
+ if (data[1] <= 0) data[1] = 1;
+
+ for(n = 2; n < N; n++){
+ if(data[n] <= 0) data[n] = 1;
+ *result += abs(20 * log(data[n-1]) - (20 * log(data[n-2]) +
+ 20 * log(data[n-1]) + 20 * log(data[n])) / 3);
+ }
+}
+
+int xtract_spread(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ float num, den, tmp;
+
+ while(n--){
+ tmp = n - *(float *)argv;
+ num += SQ(tmp) * data[n];
+ den += data[n];
+ }
+
+ *result = sqrt(num / den);
+
+}
+
+int xtract_zcr(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ for(n = 1; n < N; n++)
+ if(data[n] * data[n-1] < 0) (*result)++;
+
+ *result /= N;
+
+}
+
+int xtract_rolloff(float *data, int N, void *argv, float *result){
+
+ int n = N;
+ float pivot, temp;
+
+ while(n--) pivot += data[n];
+
+ pivot *= *(float *)argv;
+
+ for(n = 0; temp < pivot; temp += data[n++]);
+
+ *result = n;
+
+}
+
+int xtract_loudness(float *data, int N, void *argv, float *result){
+
+ int n = BARK_BANDS;
+
+ /*if(n != N) return BAD_VECTOR_SIZE; */
+
+ while(n--)
+ *result += pow(data[n], 0.23);
+}
+
+
+int xtract_flatness(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ float num, den;
+
+ while(n--){
+ if(data[n] !=0){
+ num *= data[n];
+ den += data[n];
+ }
+ }
+
+ num = pow(num, 1 / N);
+ den /= N;
+
+ *result = 10 * log10(num / den);
+
+}
+
+int xtract_tonality(float *data, int N, void *argv, float *result){
+
+ float sfmdb, sfm;
+
+ sfm = *(float *)argv;
+
+ sfmdb = (sfm > 0 ? (10 * log10(sfm)) / -60 : 0);
+
+ *result = MIN(sfmdb, 1);
+
+}
+
+int xtract_crest(float *data, int N, void *argv, float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
+int xtract_noisiness(float *data, int N, void *argv, float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+int xtract_rms_amplitude(float *data, int N, void *argv, float *result){
+
+ int n = N;
+
+ while(n--) *result += SQ(data[n]);
+
+ *result = sqrt(*result / N);
+
+}
+
+int xtract_inharmonicity(float *data, int N, void *argv, float *result){
+
+ int n = N;
+ float num, den,
+ *fund, *freq;
+
+ fund = *(float **)argv;
+ freq = fund+1;
+
+ while(n--){
+ num += abs(freq[n] - n * *fund) * SQ(data[n]);
+ den += SQ(data[n]);
+ }
+
+ *result = (2 * num) / (*fund * den);
+
+}
+
+
+int xtract_power(float *data, int N, void *argv, float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
+int xtract_odd_even_ratio(float *data, int N, void *argv, float *result){
+
+ int n = N >> 1, j, k;
+
+ float num, den;
+
+ while(n--){
+ j = n * 2;
+ k = j - 1;
+ num += data[k];
+ den += data[j];
+ }
+
+ *result = num / den;
+
+}
+
+int xtract_sharpness(float *data, int N, void *argv, float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
+int xtract_slope(float *data, int N, void *argv, float *result){
+
+ NOT_IMPLEMENTED;
+
+}
+
+int xtract_f0(float *data, int N, void *argv, float *result){
+
+/* int n, M = N >> 1;
+ float guess, error, minimum_error = 1000000, f0, freq;
+
+ guess = *(float *)argv;
+
+ for(n = 0; n < M; n++){
+ if(freq = data[n]){
+ error = abs(guess - freq);
+ if(error < minimum_error){
+ f0 = freq;
+ minimum_error = error;
+ }
+ }
+ }
+ *result = f0;*/
+
+
+ float f0 = SR_LIMIT;
+ int n = N;
+
+ while(n--) {
+ if(data[n] > 0)
+ f0 = MIN(f0, data[n]);
+ }
+
+ *result = (f0 == SR_LIMIT ? 0 : f0);
+
+}
+
+int xtract_hps(float *data, int N, void *argv, float *result){
+
+ int n = N, M, m, l, peak_index, position1_lwr;
+ float *coeffs2, *coeffs3, *product, L,
+ largest1_lwr, peak, ratio1;
+
+ coeffs2 = (float *)malloc(N * sizeof(float));
+ coeffs3 = (float *)malloc(N * sizeof(float));
+ product = (float *)malloc(N * sizeof(float));
+
+ while(n--) coeffs2[n] = coeffs3[n] = 1;
+
+ M = N >> 1;
+ L = N / 3;
+
+ while(M--){
+ m = M << 1;
+ coeffs2[M] = (data[m] + data[m+1]) * 0.5f;
+
+ if(M < L){
+ l = M * 3;
+ coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3;
+ }
+ }
+
+ peak_index = peak = 0;
+
+ for(n = 1; n < N; n++){
+ product[n] = data[n] * coeffs2[n] * coeffs3[n];
+ if(product[n] > peak){
+ peak_index = n;
+ peak = product[n];
+ }
+ }
+
+ largest1_lwr = position1_lwr = 0;
+
+ for(n = 0; n < N; n++){
+ if(data[n] > largest1_lwr && n != peak_index){
+ largest1_lwr = data[n];
+ position1_lwr = n;
+ }
+ }
+
+ ratio1 = data[position1_lwr] / data[peak_index];
+
+ if(position1_lwr > peak_index * 0.4 && position1_lwr <
+ peak_index * 0.6 && ratio1 > 0.1)
+ peak_index = position1_lwr;
+
+ *result = 22050 * (float)peak_index / (float)N;
+
+ free(coeffs2);
+ free(coeffs3);
+ free(product);
+
+}
+
diff --git a/src/vector.c b/src/vector.c
new file mode 100644
index 0000000..cb64110
--- /dev/null
+++ b/src/vector.c
@@ -0,0 +1,228 @@
+/* libxtract feature extraction library
+ *
+ * Copyright (C) 2006 Jamie Bullock
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+
+/* xtract_vector.c: defines functions that extract a feature as a single value from an input vector */
+
+#include "xtract/libxtract.h"
+#include <math.h>
+#include <fftw3.h>
+
+int xtract_magnitude_spectrum(float *data, int N, void *argv, float *result){
+
+ float *temp;
+ int n , M = N >> 1;
+ fftwf_plan plan;
+
+ temp = (float *)fftwf_malloc(N * sizeof(float));
+
+ plan = fftwf_plan_r2r_1d(N, data, temp, FFTW_R2HC, FFTW_ESTIMATE);
+
+ fftwf_execute(plan);
+
+ for(n = 1; n < M; n++){
+ result[n] = sqrt(SQ(temp[n]) + SQ(temp[N - n])) / N;
+ result[N-n] = 0.0f;
+ }
+
+ result[0] = fabs(temp[0]) / N;
+ result[M] = fabs(temp[M]) / N;
+
+ fftwf_destroy_plan(plan);
+ fftwf_free(temp);
+
+}
+
+int xtract_autocorrelation(float *data, int N, void *argv, float *result){
+
+ /* Naive time domain implementation */
+
+ int n = N, i;
+
+ float corr;
+
+ while(n--){
+ corr = 0;
+ for(i = 0; i < N - n; i++){
+ corr += data[i] * data[i + n];
+ }
+ result[n] = corr / N;
+ }
+}
+
+int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result){
+
+ float *temp;
+ int n;
+ fftwf_plan plan;
+
+ temp = (float *)fftwf_malloc(N * sizeof(float));
+ plan = fftwf_plan_r2r_1d(N, data, temp, FFTW_HC2R, FFTW_ESTIMATE);
+
+ fftwf_execute(plan);
+
+ for(n = 0; n < N - 1; n++)
+ result[n] = temp[n+1];
+
+ fftwf_destroy_plan(plan);
+ fftwf_free(temp);
+}
+
+int xtract_amdf(float *data, int N, void *argv, float *result){
+
+ int n = N, i;
+
+ float md;
+
+ while(n--){
+ md = 0;
+ for(i = 0; i < N - n; i++){
+ md += abs(data[i] - data[i + n]);
+ }
+ result[n] = md / N;
+ }
+}
+
+int xtract_asdf(float *data, int N, void *argv, float *result){
+
+ int n = N, i;
+
+ float sd;
+
+ while(n--){
+ sd = 0;
+ for(i = 0; i < N - n; i++){
+ sd = 1;
+ sd += SQ(data[i] - data[i + n]);
+ }
+ result[n] = sd / N;
+ }
+}
+
+int xtract_mfcc(float *data, int N, void *argv, float *result){
+
+ xtract_mel_filter *f;
+ int n, filter;
+ fftwf_plan plan;
+
+ f = (xtract_mel_filter *)argv;
+
+ for(filter = 0; filter < f->n_filters; filter++){
+ for(n = 0; n < N; n++){
+ result[filter] += data[n] * f->filters[filter][n];
+ }
+ if(result[filter] < LOG_LIMIT) result[filter] = LOG_LIMIT;
+ result[filter] = log(result[filter]);
+ }
+
+ for(n = filter + 1; n < N; n++) result[n] = 0;
+
+ xtract_dct(result, f->n_filters, NULL, result);
+
+}
+
+int xtract_dct(float *data, int N, void *argv, float *result){
+
+ fftwf_plan plan;
+
+ plan =
+ fftwf_plan_r2r_1d(N, data, result, FFTW_REDFT00, FFTW_ESTIMATE);
+
+ fftwf_execute(plan);
+ fftwf_destroy_plan(plan);
+}
+
+int xtract_bark_coefficients(float *data, int N, void *argv, float *result){
+
+ int *limits, band, n;
+
+ limits = (int *)argv;
+
+ for(band = 0; band < BARK_BANDS; band++){
+ for(n = limits[band]; n < limits[band + 1]; n++)
+ result[band] += data[n];
+ }
+}
+
+int xtract_peaks(float *data, int N, void *argv, float *result){
+
+ float thresh, max, y, y2, y3, p, width, sr;
+ int n = N, M, return_code;
+
+ if(argv != NULL){
+ thresh = ((float *)argv)[0];
+ sr = ((float *)argv)[1];
+ return_code = BAD_ARGV;
+ }
+ else{
+ thresh = 0;
+ sr = 44100;
+ }
+
+ M = N >> 1;
+ width = sr / N;
+
+ y = y2 = y3 = p = max = 0;
+
+ if(thresh < 0 || thresh > 100){
+ thresh = 0;
+ return_code = BAD_ARGV;
+ }
+
+ if(!sr){
+ sr = 44100;
+ return_code = BAD_ARGV;
+ }
+
+ while(n--){
+ max = MAX(max, data[n]);
+ /* ensure we never take log10(0) */
+ /*data[n] = (data[n] < LOG_LIMIT ? LOG_LIMIT : data[n]);*/
+ if ((data[n] * 100000) <= 1)
+ /* We get a more stable peak this way */
+ data[n] = 1;
+
+ }
+
+ thresh *= .01 * max;
+
+ result[0] = 0;
+ result[M] = 0;
+
+ for(n = 1; n < M; n++){
+ if(data[n] >= thresh){
+ if(data[n] > data[n - 1] && data[n] > data[n + 1]){
+ result[n] = width * (n + (p = .5 * (y = 20 * log10(data[n-1]) - (y3 = 20 * log10(data[n+1]))) / (20 * log10(data[n - 1]) - 2 * (y2 = 20 * log10(data[n])) + 20 * log10(data[n + 1]))));
+ result[M + n] = y2 - .25 * (y - y3) * p;
+ }
+ else{
+ result[n] = 0;
+ result[M + n] = 0;
+ }
+ }
+ else{
+ result[n] = 0;
+ result[M + n] = 0;
+ }
+ }
+
+ return (return_code ? return_code : SUCCESS);
+}
+