jamie@1: /* libxtract feature extraction library jamie@1: * jamie@1: * Copyright (C) 2006 Jamie Bullock jamie@1: * jamie@1: * This program is free software; you can redistribute it and/or modify jamie@1: * it under the terms of the GNU General Public License as published by jamie@1: * the Free Software Foundation; either version 2 of the License, or jamie@1: * (at your option) any later version. jamie@1: * jamie@1: * This program is distributed in the hope that it will be useful, jamie@1: * but WITHOUT ANY WARRANTY; without even the implied warranty of jamie@1: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jamie@1: * GNU General Public License for more details. jamie@1: * jamie@1: * You should have received a copy of the GNU General Public License jamie@1: * along with this program; if not, write to the Free Software jamie@1: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, jamie@1: * USA. jamie@1: */ jamie@1: jamie@1: jamie@1: /* xtract_scalar.c: defines functions that extract a feature as a single value from an input vector */ jamie@1: jamie@1: #include "xtract/libxtract.h" jamie@1: #include "math.h" jamie@5: #include jamie@1: jamie@1: int xtract_mean(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: while(n--) jamie@1: *result += *data++; jamie@1: jamie@1: *result /= N; jamie@1: } jamie@1: jamie@1: int xtract_variance(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: while(n--) jamie@1: *result += *data++ - *(float *)argv; jamie@1: jamie@1: *result = SQ(*result) / (N - 1); jamie@1: } jamie@1: jamie@1: int xtract_standard_deviation(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: *result = sqrt(*(float *)argv); jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_average_deviation(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: while(n--) jamie@1: *result += fabs(*data++ - *(float *)argv); jamie@1: jamie@1: *result /= N; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_skewness(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: while(n--) jamie@1: *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1]; jamie@1: jamie@1: *result = pow(*result, 3) / N; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_kurtosis(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: while(n--) jamie@1: *result += (*data++ - ((float *)argv)[0]) / ((float *)argv)[1]; jamie@1: jamie@1: *result = pow(*result, 4) / N - 3; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_irregularity_k(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n, jamie@1: M = M - 1; jamie@1: jamie@1: for(n = 1; n < M; n++) jamie@1: *result += abs(data[n] - (data[n-1] + data[n] + data[n+1]) / 3); jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_irregularity_j(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: float num, den; jamie@1: jamie@1: while(n--){ jamie@1: num += data[n] - data[n+1]; jamie@1: den += data[n] * data[n]; jamie@1: } jamie@1: jamie@1: *result = num / den; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_tristimulus_1(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: float den; jamie@1: jamie@1: while(n--) jamie@1: den += data[n]; jamie@1: jamie@1: *result = data[0] / den; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_tristimulus_2(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: float den; jamie@1: jamie@1: while(n--) jamie@1: den += data[n]; jamie@1: jamie@1: *result = (data[1] + data[2] + data[3]) / den; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_tristimulus_3(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: float den, num; jamie@1: jamie@1: while(n--) jamie@1: den += data[n]; jamie@1: jamie@1: num = den - data[0] + data[1] + data[2] + data[3]; jamie@1: jamie@1: *result = num / den; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_smoothness(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: if (data[0] <= 0) data[0] = 1; jamie@1: if (data[1] <= 0) data[1] = 1; jamie@1: jamie@1: for(n = 2; n < N; n++){ jamie@1: if(data[n] <= 0) data[n] = 1; jamie@1: *result += abs(20 * log(data[n-1]) - (20 * log(data[n-2]) + jamie@1: 20 * log(data[n-1]) + 20 * log(data[n])) / 3); jamie@1: } jamie@1: } jamie@1: jamie@1: int xtract_spread(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: float num, den, tmp; jamie@1: jamie@1: while(n--){ jamie@1: tmp = n - *(float *)argv; jamie@1: num += SQ(tmp) * data[n]; jamie@1: den += data[n]; jamie@1: } jamie@1: jamie@1: *result = sqrt(num / den); jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_zcr(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: for(n = 1; n < N; n++) jamie@1: if(data[n] * data[n-1] < 0) (*result)++; jamie@1: jamie@1: *result /= N; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_rolloff(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: float pivot, temp; jamie@1: jamie@1: while(n--) pivot += data[n]; jamie@1: jamie@1: pivot *= *(float *)argv; jamie@1: jamie@1: for(n = 0; temp < pivot; temp += data[n++]); jamie@1: jamie@1: *result = n; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_loudness(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = BARK_BANDS; jamie@1: jamie@1: /*if(n != N) return BAD_VECTOR_SIZE; */ jamie@1: jamie@1: while(n--) jamie@1: *result += pow(data[n], 0.23); jamie@1: } jamie@1: jamie@1: jamie@1: int xtract_flatness(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: float num, den; jamie@1: jamie@1: while(n--){ jamie@1: if(data[n] !=0){ jamie@1: num *= data[n]; jamie@1: den += data[n]; jamie@1: } jamie@1: } jamie@1: jamie@1: num = pow(num, 1 / N); jamie@1: den /= N; jamie@1: jamie@1: *result = 10 * log10(num / den); jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_tonality(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: float sfmdb, sfm; jamie@1: jamie@1: sfm = *(float *)argv; jamie@1: jamie@1: sfmdb = (sfm > 0 ? (10 * log10(sfm)) / -60 : 0); jamie@1: jamie@1: *result = MIN(sfmdb, 1); jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_crest(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: NOT_IMPLEMENTED; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_noisiness(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: NOT_IMPLEMENTED; jamie@1: jamie@1: } jamie@2: jamie@1: int xtract_rms_amplitude(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: jamie@1: while(n--) *result += SQ(data[n]); jamie@1: jamie@1: *result = sqrt(*result / N); jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_inharmonicity(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N; jamie@1: float num, den, jamie@1: *fund, *freq; jamie@1: jamie@1: fund = *(float **)argv; jamie@1: freq = fund+1; jamie@1: jamie@1: while(n--){ jamie@1: num += abs(freq[n] - n * *fund) * SQ(data[n]); jamie@1: den += SQ(data[n]); jamie@1: } jamie@1: jamie@1: *result = (2 * num) / (*fund * den); jamie@1: jamie@1: } jamie@1: jamie@1: jamie@1: int xtract_power(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: NOT_IMPLEMENTED; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_odd_even_ratio(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N >> 1, j, k; jamie@1: jamie@1: float num, den; jamie@1: jamie@1: while(n--){ jamie@1: j = n * 2; jamie@1: k = j - 1; jamie@1: num += data[k]; jamie@1: den += data[j]; jamie@1: } jamie@1: jamie@1: *result = num / den; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_sharpness(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: NOT_IMPLEMENTED; jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_slope(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: NOT_IMPLEMENTED; jamie@1: jamie@1: } jamie@1: jamie@5: int xtract_lowest_match(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: /* int n, M = N >> 1; jamie@1: float guess, error, minimum_error = 1000000, f0, freq; jamie@1: jamie@1: guess = *(float *)argv; jamie@1: jamie@1: for(n = 0; n < M; n++){ jamie@1: if(freq = data[n]){ jamie@1: error = abs(guess - freq); jamie@1: if(error < minimum_error){ jamie@1: f0 = freq; jamie@1: minimum_error = error; jamie@1: } jamie@1: } jamie@1: } jamie@1: *result = f0;*/ jamie@1: jamie@1: jamie@1: float f0 = SR_LIMIT; jamie@1: int n = N; jamie@1: jamie@1: while(n--) { jamie@1: if(data[n] > 0) jamie@1: f0 = MIN(f0, data[n]); jamie@1: } jamie@1: jamie@1: *result = (f0 == SR_LIMIT ? 0 : f0); jamie@1: jamie@1: } jamie@1: jamie@1: int xtract_hps(float *data, int N, void *argv, float *result){ jamie@1: jamie@1: int n = N, M, m, l, peak_index, position1_lwr; jamie@1: float *coeffs2, *coeffs3, *product, L, jamie@1: largest1_lwr, peak, ratio1; jamie@1: jamie@1: coeffs2 = (float *)malloc(N * sizeof(float)); jamie@1: coeffs3 = (float *)malloc(N * sizeof(float)); jamie@1: product = (float *)malloc(N * sizeof(float)); jamie@1: jamie@1: while(n--) coeffs2[n] = coeffs3[n] = 1; jamie@1: jamie@1: M = N >> 1; jamie@1: L = N / 3; jamie@1: jamie@1: while(M--){ jamie@1: m = M << 1; jamie@1: coeffs2[M] = (data[m] + data[m+1]) * 0.5f; jamie@1: jamie@1: if(M < L){ jamie@1: l = M * 3; jamie@1: coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3; jamie@1: } jamie@1: } jamie@1: jamie@1: peak_index = peak = 0; jamie@1: jamie@1: for(n = 1; n < N; n++){ jamie@1: product[n] = data[n] * coeffs2[n] * coeffs3[n]; jamie@1: if(product[n] > peak){ jamie@1: peak_index = n; jamie@1: peak = product[n]; jamie@1: } jamie@1: } jamie@1: jamie@1: largest1_lwr = position1_lwr = 0; jamie@1: jamie@1: for(n = 0; n < N; n++){ jamie@1: if(data[n] > largest1_lwr && n != peak_index){ jamie@1: largest1_lwr = data[n]; jamie@1: position1_lwr = n; jamie@1: } jamie@1: } jamie@1: jamie@1: ratio1 = data[position1_lwr] / data[peak_index]; jamie@1: jamie@1: if(position1_lwr > peak_index * 0.4 && position1_lwr < jamie@1: peak_index * 0.6 && ratio1 > 0.1) jamie@1: peak_index = position1_lwr; jamie@1: jamie@1: *result = 22050 * (float)peak_index / (float)N; jamie@1: jamie@1: free(coeffs2); jamie@1: free(coeffs3); jamie@1: free(product); jamie@1: jamie@1: } jamie@5: jamie@5: jamie@5: int xtract_f0(float *data, int N, void *argv, float *result){ jamie@5: jamie@5: NOT_IMPLEMENTED; jamie@5: jamie@5: }