diff --git a/AudioFilterConvolution_F32.cpp b/AudioFilterConvolution_F32.cpp index 6052903..f3fcc6b 100644 --- a/AudioFilterConvolution_F32.cpp +++ b/AudioFilterConvolution_F32.cpp @@ -24,6 +24,7 @@ 6) Optimize the time execution *******************************************************************/ // Revised for OpenAudio_Arduino Teensy F32 library, 8 Feb 2022 + // Revised 18 January to work for Teensy 3.5 and T3.6. Bob L #include "AudioFilterConvolution_F32.h" @@ -48,11 +49,15 @@ void AudioFilterConvolution_F32::impulse(float32_t *FIR_coef) { FIR_filter_mask[i] = 0.0; } - arm_cfft_f32( &arm_cfft_sR_f32_len1024, FIR_filter_mask, 0, 1); +// T3.5 or T3.6 +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + arm_cfft_radix4_f32(&fft_instFwd, FIR_filter_mask); +#elif defined(__IMXRT1062__) + arm_cfft_f32(&arm_cfft_sR_f32_len1024, FIR_filter_mask, 0, 1); // T4.x +#endif // for 1st time thru, zero out the last sample buffer to 0 - arm_fill_f32(0, last_sample_buffer_L, 128*4); - + arm_fill_f32(0, last_sample_buffer_L, 128*4); state = 0; enabled = 1; //enable audio stream again } @@ -69,7 +74,11 @@ void AudioFilterConvolution_F32::update(void) case 0: if (passThru ==0) { arm_cmplx_mult_cmplx_f32(FFT_buffer, FIR_filter_mask, iFFT_buffer, FFT_length); // complex multiplication in Freq domain = convolution in time domain - arm_cfft_f32(&arm_cfft_sR_f32_len1024, iFFT_buffer, 1, 1); // perform complex inverse FFT +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + arm_cfft_radix4_f32(&fft_instRev, iFFT_buffer); +#elif defined(__IMXRT1062__) + arm_cfft_f32(&arm_cfft_sR_f32_len1024, iFFT_buffer, 1, 1); +#endif k = 0; l = 1024; for (int i = 0; i < 512; i++) { @@ -135,7 +144,11 @@ void AudioFilterConvolution_F32::update(void) FFT_buffer[k++] = buffer[i]; // imag } // calculations are performed in-place in FFT routines - arm_cfft_f32(&arm_cfft_sR_f32_len1024, FFT_buffer, 0, 1);// perform complex FFT +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + arm_cfft_radix4_f32(&fft_instFwd, FFT_buffer); +#elif defined(__IMXRT1062__) + arm_cfft_f32(&arm_cfft_sR_f32_len1024, FFT_buffer, 0, 1); // perform complex FFT +#endif } //end if passTHru break; } @@ -264,3 +277,4 @@ void AudioFilterConvolution_F32::initFilter ( float32_t fc, float32_t Astop, int enabled = 0; // set to zero to disable audio processing until impulse has been loaded impulse(FIR_Coef); // generates Filter Mask and enables the audio stream } + diff --git a/AudioFilterConvolution_F32.h b/AudioFilterConvolution_F32.h index 7eb58c8..35eac65 100644 --- a/AudioFilterConvolution_F32.h +++ b/AudioFilterConvolution_F32.h @@ -96,7 +96,7 @@ * use of this class. * * Removed #defines that were not needed. Thanks K7MDL. Bob 6 Mar 2022 - * Added needed part of arm_const_structs.h. Thanks Paul Bob 16 Jan 2023 + * Separated Teensy 3 and 4 parts. Thanks Paul Bob 16 Jan 2023 * * ************************************************************ */ @@ -104,11 +104,12 @@ #define AudioFilterConvolution_F32_h_ #include -#include +#include "arm_math.h" #include "arm_common_tables.h" -// #include not available for teensy3, so here is needed line -extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024; +#if defined(__IMXRT1062__) +#include "arm_const_structs.h" +#endif #define MAX_NUMCOEF 513 @@ -124,13 +125,30 @@ class AudioFilterConvolution_F32 : public AudioStream_F32 { public: - AudioFilterConvolution_F32(void) : AudioStream_F32(1, inputQueueArray_F32) { + AudioFilterConvolution_F32(void) : + AudioStream_F32(1, inputQueueArray_F32) + { fs = AUDIO_SAMPLE_RATE; - //block_size = 128; // Always + //block_size = 128; // Always + // INFO: __MK20DX128__ T_LC; __MKL26Z64__ T3.0; __MK20DX256__ T3.1 and T3.2 + // __MK64FX512__) T3.5; __MK66FX1M0__ T3.6; __IMXRT1062__ T4.0 and T4.1 +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + arm_cfft_radix4_init_f32(&fft_instFwd, 1024, 0, 1); + arm_cfft_radix4_init_f32(&fft_instRev, 1024, 1, 1); + // arm CMSIS library has predefined structures of type arm_cfft_instance_f32 + // arm_cfft_sR_f32_len1024 is one of the structures +#endif }; - AudioFilterConvolution_F32(const AudioSettings_F32 &settings) : AudioStream_F32(1, inputQueueArray_F32) { + + AudioFilterConvolution_F32(const AudioSettings_F32 &settings) : + AudioStream_F32(1, inputQueueArray_F32) + { // Performs the first initialize fs = settings.sample_rate_Hz; +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + arm_cfft_radix4_init_f32(&fft_instFwd, 1024, 0, 1); + arm_cfft_radix4_init_f32(&fft_instRev, 1024, 1, 1); +#endif }; virtual void update(void); @@ -140,8 +158,6 @@ public: int type, float32_t dfc); float32_t* getCoeffPtr(void) {return &FIR_Coef[0];} -//#define Alternate filter init - private: float32_t fs; audio_block_f32_t *inputQueueArray_F32[1]; @@ -161,13 +177,20 @@ private: float32_t iFFT_buffer[2048] __attribute__((aligned(4))); float32_t last_sample_buffer_L[512]; void impulse(float32_t *coefs); - + int aaa = 0; float32_t Izero (float32_t x); float32_t m_sinc(int m, float32_t fc); void calc_FIR_coeffs (float32_t * coeffs, int numCoeffs, float32_t fc, float32_t Astop, int type, float32_t dfc, float32_t Fsamprate); - }; +#if defined(__MK64FX512__) || defined(__MK66FX1M0__) + arm_cfft_radix4_instance_f32 fft_instFwd, fft_instRev; + // #elif defined(__IMXRT1062__) + // arm_cfft_instance_f32 arm_cfft_sR_f32_len1024 is built into cmsis +#endif +}; + +// end of read only once #endif diff --git a/examples/TestConvolutinalFilter/TestConvolutinalFilter.ino b/examples/TestConvolutinalFilter/TestConvolutinalFilter.ino index ff97a83..cae3ef7 100644 --- a/examples/TestConvolutinalFilter/TestConvolutinalFilter.ino +++ b/examples/TestConvolutinalFilter/TestConvolutinalFilter.ino @@ -58,7 +58,7 @@ void setup(void) { //convFilt1.initFilter(800.0f, 40.0f, BANDPASS, 1200.0f); // IK8YFW SSB - Centered at 1500Hz, 60 db SL, 2=BPF, width = 3000Hz - //convFilt1.initFilter(1500.0f, 60.0f, BANDPASS, 3000.0f); + convFilt1.initFilter(1500.0f, 60.0f, BANDPASS, 3000.0f); // Band Reject filter, Centered at 6000Hz, 50 db SL, 3=BRF, width = 2000Hz //convFilt1.initFilter(6000.0f, 60.0f, BANDREJECT, 2000.0f); @@ -86,13 +86,12 @@ void setup(void) { */ // Alternatively, the passthrough case: - convFilt1.passThrough(1); - convFilt1.initFilter(); + //convFilt1.passThrough(1); // Design for direct FIR. This sets frequency response. // Bin for 4kHz at 44.117kHz sample rate and 400 coeff's is (4000/44117) * (512/2) = 23.2 -// for(int ii=0; ii<47; ii++) attenFIR[ii] = 0.0f; -// for(int ii=47; ii<256; ii++) attenFIR[ii] = -150.0f; + // for(int ii=0; ii<47; ii++) attenFIR[ii] = 0.0f; + // for(int ii=47; ii<256; ii++) attenFIR[ii] = -150.0f; // FIRGeneralNew(float *adb, uint16_t nFIR, float *cf32f, float kdb, float *pStateArray); // filterFIRgeneral1.FIRGeneralNew(attenFIR, 512, coeffFIR, 60.0, stateFIR);