soundeditor/atsa/other-utils.c

179 lines
4.0 KiB
C

/* other-utils.c
* atsa: ATS analysis implementation
* Oscar Pablo Di Liscia / Pete Moss / Juan Pampin
*/
#include "atsa.h"
#include <math.h>
#include <stdlib.h>
/* private function prototypes */
void fft_bit_reversal(double* rl, double* im, int n);
/* make_window
* ===========
* makes an analysis window, returns a pointer to it.
* win_type: window type, available types are:
* BLACKMAN, BLACKMAN HARRIS, HANNING and VON HANN
* win_size: window size
*/
double *make_window(int win_type, int win_size)
{
double *buffer;
int i;
double arg = TWOPI / (double)(win_size - 1);
buffer = (double *)malloc(win_size*sizeof(double));
for(i=0; i < win_size; i++) {
switch (win_type) {
case BLACKMAN: //Blackman (3 term)
buffer[i]= 0.42 - 0.5*cos(arg*i) + 0.08*cos(arg*i*2.);
break;
case BLACKMAN_H: //Blackman-Harris (4 term)
buffer[i]= 0.35875 - 0.48829*cos(arg*i) + 0.14128*cos(arg*i*2.) - 0.01168*cos(arg*i*3.);
break;
case HANNING: //Hanning
buffer[i]= 0.54 - 0.46*cos(arg*i);
break;
case VONHANN: //Von Hann ("hanning")
buffer[i]= 0.5 - 0.5*cos(arg*i);
break;
}
}
return(buffer);
}
/* window_norm
* ===========
* computes the norm of a window
* returns the norm value
* win: pointer to a window
* size: window size
*/
double window_norm(double *win, int size)
{
double acc=0.0;
int i;
for(i=0 ; i<size ; i++){
acc += win[i];
}
return(2.0 / acc);
}
/* push_peak
* =========
* pushes a peak into an array of peaks
* re-allocating memory and updating its size
* returns a pointer to the array of peaks.
* new_peak: pointer to new peak to push into the array
* peaks_list: list of peaks
* peaks_size: pointer to the current size of the array.
*/
ATS_PEAK *push_peak(ATS_PEAK *new_peak, ATS_PEAK *peaks_list, int *peaks_size)
{
peaks_list = (ATS_PEAK *)realloc(peaks_list, sizeof(ATS_PEAK) * ++*peaks_size);
peaks_list[*peaks_size-1] = *new_peak;
return(peaks_list);
}
/* peak_frq_inc
* ============
* function used by qsort to sort an array of peaks
* in increasing frequency order.
*/
int peak_frq_inc(void const *a, void const *b)
{
const ATS_PEAK *pa = (ATS_PEAK *)a;
const ATS_PEAK *pb = (ATS_PEAK *)b;
return (pa->frq < pb->frq ? -1 : (pa->frq > pb->frq ? 1 : 0));
}
/* peak_smr_dec
* ============
* function used by qsort to sort an array of peaks
* in decreasing SMR order.
*/
int peak_smr_dec(void const *a, void const *b)
{
const ATS_PEAK *pa = (ATS_PEAK *)a;
const ATS_PEAK *pb = (ATS_PEAK *)b;
return (pb->smr < pa->smr ? -1 : (pb->smr > pa->smr ? 1 : 0));
}
/* fft
* ===
* standard fft based on simplfft by Joerg Arndt.
* rl: pointer to real part data
* im: pointer to imaginary part data
* n: size of data
* is: 1=forward trasnform -1=backward transform
*/
void fft(double *rl, double *im, int n, int is)
{
int m, j, mh, ldm, lg, i, i2, j2, imh;
double ur, ui, u, vr, vi, angle, c, s;
imh = (int)(log(n + 1) / log(2.0));
fft_bit_reversal(rl, im, n);
m = 2;
ldm = 1;
mh = n >> 1;
angle = (M_PI * is);
for (lg = 0; lg < imh; lg++)
{
c = cos(angle);
s = sin(angle);
ur = 1.0;
ui = 0.0;
for (i2 = 0; i2 < ldm; i2++)
{
i = i2;
j = i2 + ldm;
for (j2 = 0; j2 < mh; j2++)
{
vr = ur * rl[j] - ui * im[j];
vi = ur * im[j] + ui * rl[j];
rl[j] = rl[i] - vr;
im[j] = im[i] - vi;
rl[i] += vr;
im[i] += vi;
i += m;
j += m;
}
u = ur;
ur = (ur * c) - (ui * s);
ui = (ui * c) + (u * s);
}
mh >>= 1;
ldm = m;
angle *= 0.5;
m <<= 1;
}
}
/* bit reversal */
void fft_bit_reversal(double* rl, double* im, int n)
{
int i, m, j;
double vr, vi;
j = 0;
for (i = 0; i < n; i++) {
if (j > i) {
vr = rl[j];
vi = im[j];
rl[j] = rl[i];
im[j] = im[i];
rl[i] = vr;
im[i] = vi;
}
m = n >> 1;
while ((m >= 2) && (j >= m)) {
j -= m;
m = m >> 1;
}
j += m;
}
}