Open mrSilkie opened 1 year ago
I should have spent a little more time investigating before putting this post up. Reducing the change in frequency to 0.001 i have been able to hear the filter working somewhat correctly as i go from f=0.5 and up.
It starts off with okay values (still a lot of distortion)
[filter-dsp] change f 0.69699: 0.69799
[filter-dsp] Coefficients 0: 12.48261
[filter-dsp] Coefficients 1: 24.96522
[filter-dsp] Coefficients 2: 12.48261
[filter-dsp] Coefficients 3: 12.13230
[filter-dsp] Coefficients 4: 36.79814
And as it increases, the values become greater and greater creating a decimation effect
[filter-dsp] change f 0.72899: 0.72999
[filter-dsp] Coefficients 0: 71.31686
[filter-dsp] Coefficients 1: 142.63373
[filter-dsp] Coefficients 2: 71.31686
[filter-dsp] Coefficients 3: 31.77969
[filter-dsp] Coefficients 4: 252.48778
These values continue to climb before i start seeing nan values.
Hi @mrSilkie ,
Thank you for the feedback. Yes, the frequency is from 0 up to 0.5, where 1 is a sample frequency. The values above 0.5 I this are not correct. The LPF and HPF filters are very sensitive to the qFactor.
I've planed to release the demo application this week with LyraT board and processing audio. There will be just playing samples with volume/bass/treble. You are right, first the samples from codec should be converted from int16 to float, and then back from float to int16. We will implement biquad filter for the stereo samples soon (next few weeks).
Thank you, Dmitry
I got it working, I wasn't converting the int buffer to a float and back correctly.
Now that I've got it working all I can say is that it sounds like trash. A lot of digital distortion. It's getting tricky to debug the Lyra-T as SD card and Aux in both interfere with JTAG. I'll probably have to code in a file or oscillator to atleast have some test data for verification.
I have been using my button to sweep Q's and filter frequencies. Is the Q in log 10? so values 0.001 and 100 are both valid in some sense? Anyway, here is my code so far.
void int16_to_float_stereo(int16_t* input, float* output, int size, bool mode){
switch (mode) {
case true:
for (int i = 0; i < size;i ++)
{
output[i] = input[(2*i)+1] / (float)INT16_MAX;
}
break;
default:
for (int i = 0; i < size; i++)
{
output[i] = input[2*i] / (float)INT16_MAX;
}
break;
}
}
void float_to_int16_stereo(float* input, int16_t* output, int size, bool mode){
switch (mode) {
case true:
for (int i = 1; i < size; i++) {
output[i] = (int16_t)(input[(2*i)+1] * INT16_MAX);
}
break;
default:
for (int i = 0; i < size; i++) {
output[i] = (int16_t)(input[2*i] * INT16_MAX);
}
}
}
// Function shows result of IIR filter
void IIRfilter(int16_t* input, int16_t* output, float freq, float qFactor, bool show, uint8_t channelMode)
{
esp_err_t ret = ESP_OK;
static float last_freq = -1.0;
static float coeffs_lpf[5];
static float filter_History_L[2] = {0};
static float filter_History_R[2] = {0};
float FloatDspBuf_IN[I2S_READLEN] = {0};
float FloatDspBuf_OUT[I2S_READLEN] = {0};
// INT TO FLOAT
switch (channelMode)
{
case LEFT:
int16_to_float_stereo(input, FloatDspBuf_IN, I2S_READLEN, 0);
break;
case RIGHT:
int16_to_float_stereo(input, FloatDspBuf_IN, I2S_READLEN, 1);
break;
default:
// no mono right now
memcpy(output, input, I2S_READLEN);
return;
}
// PRE DSP
if (channelMode != LEFT && freq != last_freq)
{
printf("[filter-dsp] New F:%2.5f . . . Current Q: %2.3f\r\n", freq, qFactor);
last_freq = freq;
// Calculate iir filter coefficients
ret = dsps_biquad_gen_hpf_f32(coeffs_lpf, (freq), qFactor);
// printf all of the coefficients
printf("[filter-dsp] Coefficients %1.5f\t%1.5f\t%1.5f\t%1.5f\t%1.5f\r\n",
coeffs_lpf[0],coeffs_lpf[1],coeffs_lpf[2],coeffs_lpf[3],coeffs_lpf[4]);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Operation error = %i", ret);
return;
}
}
// DSP
switch (channelMode)
{
case LEFT:
ret = dsps_biquad_f32_ansi(FloatDspBuf_IN, FloatDspBuf_OUT, I2S_READLEN_HALF, coeffs_lpf, filter_History_L);
break;
case RIGHT:
ret = dsps_biquad_f32_ansi(FloatDspBuf_IN, FloatDspBuf_OUT, I2S_READLEN_HALF, coeffs_lpf, filter_History_R);
break;
default:
break;
}
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Operation error = %i", ret);
return;
}
// POST DSP
// FLOAT TO INT
switch (channelMode)
{
case LEFT:
float_to_int16_stereo(FloatDspBuf_OUT, output, I2S_READLEN_HALF, 0);
break;
case RIGHT:
float_to_int16_stereo(FloatDspBuf_OUT, output, I2S_READLEN_HALF, 1);
break;
default:
memcpy(output, input, I2S_READLEN);
break;
}
// 0 out memory
}
I'm working on this project for my Uni DSP course. I have the option of doing it in matlab or python, but we all know ESP32 + audio input / output is far more fun!
I am finding that the code is pretty undocumented. There should be different dsps_biquad_f32 functions for different types of filters but I will assume that it is correct for the coefficients generated (they are a function pair after all). Since I am working with a DAC and ADC, I have to convert int to float before processing, this is another consideration. Another consideration is that the ADC/DAC buffers are populated using [L,R,L,R,L,R] so i have my IIR function that takes the odd values of the ADC buffer, and creates a half length array that is then processed before converting the float array back into ints in the odd n positions of the DAC buffer. It operated again for the opposing channel. Since I have made some modifications and this is a 'practical application' of this project, I think there is a lot of value in this post for future readers.
The function that performs the IIR maths on the float array is
I modified show_iir into the following that is now stereo compatible.
My main loop
Looking at the code, I assume that the coefficient generator is working from values 0-1, with 1 being the cutoff frequency equal to that of the sampling frequency. If so, does that mean only values 0 to 0.5 are valid since we are sampling at twice the maximum frequency?
I have found that I have no effect regardless of LPF or HPF coefficients being desired, the audio is silent up till the 60-70s where coefficient 4 starts to increase and continues to increase. I go from silence, to crackling, to a very loud and distorted output. True for both LPF and HPF.
My next plan of attack is to figure out what coefficients to use and hard code them in just so I can validate the IRR math funtion because I am not sure if it is my stereo->mono->float and float->int process is the problem, or if there are implementation problems within my code. Has anybody else had some success and is able to provide a bit more information on how to use this library?