From 6d00829a8ccef20c0ce7eeecc54cd3bb5f94b3bd Mon Sep 17 00:00:00 2001 From: Jamie Bullock Date: Mon, 2 Oct 2006 14:18:15 +0000 Subject: Initial import --- src/Makefile.am | 15 ++ src/delta.c | 49 +++++++ src/init.c | 124 +++++++++++++++++ src/libxtract.c | 87 ++++++++++++ src/scalar.c | 414 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vector.c | 228 +++++++++++++++++++++++++++++++ 6 files changed, 917 insertions(+) create mode 100644 src/Makefile.am create mode 100644 src/delta.c create mode 100644 src/init.c create mode 100644 src/libxtract.c create mode 100644 src/scalar.c create mode 100644 src/vector.c (limited to 'src') 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 +#include + +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 +#include + +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); +} + -- cgit v1.2.3