You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OpenAudio_ArduinoLibrary/AudioFilterConvolution_F32.h

132 lines
4.9 KiB

/**
******************************************************************************
* @file AudioFilterConvolution_F32.h
* @author Giuseppe Callipo - IK8YFW - ik8yfw@libero.it
* @version V1.0.0
* @date 02-05-2021
* @brief F32 Filter Convolution
*
******************************************************************************
******************************************************************************
This software is based on the AudioFilterConvolution routine
Written by Brian Millier on Mar 2017
https://circuitcellar.com/research-design-hub/fancy-filtering-with-the-teensy-3-6/
and modified by Giuseppe Callipo - ik8yfw.
Modifications:
1) Class refactoring, change some methods visibility;
2) Filter coefficients calculation included into class;
3) Change the class for running in both with F32
OpenAudio_ArduinoLibrary for Teensy;
4) Added initFilter method for single anf fast initialization and on
the fly re-inititialization;
5) Optimize it to use as output audio filter on SDR receiver.
Brought to the Teensy F32 OpenAudio_ArduinoLibrary 2 Feb 2022, Bob Larkin
******************************************************************************/
/*Notes from Giuseppe Callipo, IK8YFW:
*** How to use it. ***
Create an audio project based on chipaudette/OpenAudio_ArduinoLibrary
like the Keiths SDR Project, and just add the h and cpp file to your
processing chain as unique output filter:
************************************************************
1) Include the header
#include "AudioFilterConvolution_F32.h" (or OpenAudio_ArduinoLibrary.h)
2) Initialize as F32 block
(the block must be 128 but the sample rate can be changed but must initialized)
const float sample_rate_Hz = 96000.0f; // or 44100.0f or other
const int audio_block_samples = 128;
AudioSettings_F32 audio_settings(sample_rate_Hz, audio_block_samples);
AudioFilterConvolution_F32 FilterConv(audio_settings);
3) Connect before output
AudioConnection_F32 patchCord1(FilterConv,0,Output_i2s,0);
AudioConnection_F32 patchCord2(FilterConv,0,Output_i2s,1);
4) Set the filter value when you need - some examples:
// CW - Centered at 800Hz, ( 40 db x oct ), 2=BPF, width = 1200Hz
FilterConv.initFilter((float32_t)800, 40, 2, 1200.0);
// SSB - Centered at 1500Hz, ( 60 db x oct ), 2=BPF, width = 3000Hz
FilterConv.initFilter((float32_t)1500, 60, 2, 3000.0);
************************************************************** */
/* Additional Notes from Bob
* Measured 128 word update in update() is 248 microseconds (T4.x)
* Comparison with a conventional FIR, from this library, the
* AudioFilterFIRGeneral_F32 showed that a 512 tap FIR gave
* essentially the same response and was slightly faster at
* 225 microseconds per update. Also, note that this form of
* computation uses about 52 kB of memory where the direct FIR
* uses about 10 kB. The responses differ in only minor ways.
* ************************************************************ */
#ifndef AudioFilterConvolution_F32_h_
#define AudioFilterConvolution_F32_h_
#include <AudioStream_F32.h>
#include <arm_math.h>
#include <arm_const_structs.h>
#define MAX_NUMCOEF 513
#define TPI 6.28318530717959f
#define PIH 1.57079632679490f
#define FOURPI 2.0 * TPI
#define SIXPI 3.0 * TPI
class AudioFilterConvolution_F32 :
public AudioStream_F32
{
public:
AudioFilterConvolution_F32(void) : AudioStream_F32(1, inputQueueArray_f32) {
fs = AUDIO_SAMPLE_RATE;
//block_size = AUDIO_BLOCK_SAMPLES;
};
AudioFilterConvolution_F32(const AudioSettings_F32 &settings) : AudioStream_F32(1, inputQueueArray_f32) {
// Performs the first initialize
fs = settings.sample_rate_Hz;
};
boolean begin(int status);
virtual void update(void);
void passThrough(int stat);
void initFilter (float32_t fc, float32_t Astop, int type, float dfc);
private:
#define BUFFER_SIZE 128
float32_t fs;
audio_block_f32_t *inputQueueArray_f32[1];
float32_t *sp_L;
volatile uint8_t state;
int i;
int k;
int l;
int passThru;
int enabled;
float32_t FIR_Coef[MAX_NUMCOEF];
const uint32_t FFT_length = 1024;
float32_t FIR_coef[2048] __attribute__((aligned(4)));
float32_t FIR_filter_mask[2048] __attribute__((aligned(4)));
float32_t buffer[2048] __attribute__((aligned(4)));
float32_t tbuffer[2048]__attribute__((aligned(4)));
float32_t FFT_buffer[2048] __attribute__((aligned(4)));
float32_t iFFT_buffer[2048] __attribute__((aligned(4)));
float32_t float_buffer_L[512]__attribute__((aligned(4)));
float32_t last_sample_buffer_L[512];
void impulse(float32_t *coefs);
float32_t Izero (float32_t x);
float m_sinc(int m, float fc);
void calc_FIR_coeffs (float * coeffs, int numCoeffs, float32_t fc, float32_t Astop, int type, float dfc, float Fsamprate);
};
#endif