diff --git a/libao2/firfilter.c b/libao2/firfilter.c index 9a44018a0e..ff4c1d33cd 100644 --- a/libao2/firfilter.c +++ b/libao2/firfilter.c @@ -1,6 +1,8 @@ +#include + static double desired_7kHz_lowpass[] = {1.0, 0.0}; -static double weights_7kHz_lowpass[] = {0.1, 0.1}; +static double weights_7kHz_lowpass[] = {0.2, 2.0}; double *calc_coefficients_7kHz_lowpass(int rate) { @@ -18,16 +20,20 @@ double *calc_coefficients_7kHz_lowpass(int rate) #if 0 -int16_t firfilter(int16_t *buf, int pos, int len, int count, double *coefficients) -{ - double result = 0.0; +static double desired_125Hz_lowpass[] = {1.0, 0.0}; +static double weights_125Hz_lowpass[] = {0.2, 2.0}; + +double *calc_coefficients_125Hz_lowpass(int rate) +{ + double *result = (double *)malloc(256*sizeof(double)); + double bands[4]; + + bands[0] = 0.0; bands[1] = 125.0/rate; + bands[2] = 175.0/rate; bands[3] = 0.5; + + remez(result, 256, 2, bands, + desired_125Hz_lowpass, weights_125Hz_lowpass, BANDPASS); - // Back 32 samples, maybe wrapping in buffer. - pos = (pos+len-count)%len; - // And do the multiply-accumulate - while (count--) { - result += buf[pos++] * *coefficients++; pos %= len; - } return result; } @@ -57,3 +63,59 @@ int16_t firfilter(int16_t *buf, int pos, int len, int count, double *coefficient while (count2--) result += *buf++ * *coefficients++; return result; } + +void dump_filter_coefficients(double *coefficients) +{ + int i; + fprintf(stderr, "pl_surround: Filter coefficients are: \n"); + for (i=0; (i<32); i++) { + fprintf(stderr, " [%2d]: %23.20f\n", i, coefficients[i]); + } +} + +#ifdef TESTING + +#define PI 3.1415926536 + +// For testing purposes, fill a buffer with some sine-wave tone +void sinewave(int16_t *output, int samples, int incr, int freq, double phase, int samplerate) +{ + double radians_per_sample = 2*PI / ((0.0+samplerate) / freq), r; + + //fprintf(stderr, "samples=%d tone freq=%d, samplerate=%d, radians/sample=%f\n", + // samples, freq, samplerate, radians_per_sample); + r = phase; + while (samples--) { + *output = sin(r)*10000; output = &output[incr]; + r += radians_per_sample; + } +} + +// Pass various frequencies through a FIR filter and report amplitudes +void testfilter(double *coefficients, int count, int samplerate) +{ + int16_t wavein[8192]; //, waveout[2048]; + int sample, samples, maxsample, minsample, totsample; + int nyquist=samplerate/2; + int freq, i; + + for (freq=25; freq maxsample) maxsample=sample; + if (sample < minsample) minsample=sample; + totsample += sample; samples++; + } + // Report results + fprintf(stderr, "%5d %5d %5d %5d %f\n", freq, totsample/samples, maxsample, minsample, 10*log((totsample/samples)/6500.0)); + } +} + +#endif diff --git a/libao2/pl_surround.c b/libao2/pl_surround.c index 7ccf6fdb3a..c2872de7a5 100644 --- a/libao2/pl_surround.c +++ b/libao2/pl_surround.c @@ -115,7 +115,8 @@ static int init(){ ao_plugin_data.sz_mult /= 2; // Figure out buffer space (in int16_ts) needed for the 15msec delay - pl_surround.delaybuf_len = (pl_surround.rate * pl_surround.msecs / 1000); + // Extra 31 samples allow for lowpass filter delay (taps-1) + pl_surround.delaybuf_len = (pl_surround.rate * pl_surround.msecs / 1000) + 31; // Allocate delay buffers pl_surround.Ls_delaybuf=(void*)calloc(pl_surround.delaybuf_len,sizeof(int16_t)); pl_surround.Rs_delaybuf=(void*)calloc(pl_surround.delaybuf_len,sizeof(int16_t)); @@ -124,7 +125,8 @@ static int init(){ pl_surround.delaybuf_pos = 0; // Surround filer coefficients pl_surround.filter_coefs_surround = calc_coefficients_7kHz_lowpass(pl_surround.rate); - + //dump_filter_coefficients(pl_surround.filter_coefs_surround); + //testfilter(pl_surround.filter_coefs_surround, 32, pl_surround.rate); return 1; } @@ -164,8 +166,12 @@ static int play(){ // fprintf(stderr, "pl_surround: play %d bytes, %d samples\n", ao_plugin_data.len, samples); samples = ao_plugin_data.len / sizeof(int16_t) / pl_surround.input_channels; - out = pl_surround.databuf; in = (int16_t *)ao_plugin_data.data; + + // Testing - place a 1kHz tone in the front channels in anti-phase + //sinewave(in, samples, pl_surround.input_channels, 1000, 0.0, pl_surround.rate); + //sinewave(&in[1], samples, pl_surround.input_channels, 1000, PI, pl_surround.rate); + for (i=0; i