blacktronics
Member
Heyo, so after my Teensy 3.2 randomly decided to fling off into outer space without leaving a notice as to why, I figured I'd give the 3.6 a shot.
Particularly intriguing was the speed and the support for CMSIS 4.5. I did what was mentioned in the "Excellent results with Floating Point FFT/IFFT Processing and Teensy 3.6" thread Here and Here
I however, can not get the 4096-point fft working using these new functions, I am probably doing everything wrong because I have no idea what I am doing, I'm trying though.
I simply went and modified analyze_fft1024.cpp and analyze_fft1024, and added #include "analyze_fft4096.h" to Audio.h
The code compiles and uploads without errors, but it just does nothing. Very enjoyable to troubleshoot.
Sketch:
analyze_fft4096.cpp:
analyze_fft4096.h
I am aware there are other methods to implement this, but honestly, the audio library makes using this stuff so exceptionally convenient.
Particularly intriguing was the speed and the support for CMSIS 4.5. I did what was mentioned in the "Excellent results with Floating Point FFT/IFFT Processing and Teensy 3.6" thread Here and Here
I however, can not get the 4096-point fft working using these new functions, I am probably doing everything wrong because I have no idea what I am doing, I'm trying though.
I simply went and modified analyze_fft1024.cpp and analyze_fft1024, and added #include "analyze_fft4096.h" to Audio.h
The code compiles and uploads without errors, but it just does nothing. Very enjoyable to troubleshoot.
Sketch:
Code:
#include <Audio.h>
#include <avr/power.h>
AudioInputAnalog adc1(A2);
AudioAnalyzeFFT4096 fft1;
AudioConnection patchCord2(adc1, fft1);
void setup() {
AudioMemory(16);
Serial.begin(9600);
fft1.averageTogether(8);
}
void loop() {
if (fft1.available()) {
for (uint16_t i = 0; i < 4096; i += 1) {
int32_t n = fft1.read(i);
Serial.print(n);
Serial.print(" ");
}
Serial.println();
}
}
analyze_fft4096.cpp:
Code:
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
*
* Development of this audio library was funded by PJRC.COM, LLC by sales of
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
* open source software by purchasing Teensy or other PJRC products.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice, development funding notice, and this permission
* notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "analyze_fft4096.h"
#include "sqrt_integer.h"
#include "utility/dspinst.h"
// 140312 - PAH - slightly faster copy
static void copy_to_fft_buffer(void *destination, const void *source)
{
const uint32_t *src = (const uint32_t *)source;
uint32_t *dst = (uint32_t *)destination;
for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) {
*dst++ = *src++; // real sample plus a zero for imaginary
}
}
static void apply_window_to_fft_buffer(void *buffer, const void *window)
{
int32_t *buf = (int32_t *)buffer;
const int32_t *win = (int32_t *)window;;
for (int i=0; i < 4096; i++) {
int32_t val = *buf * *win++;
//*buf = signed_saturate_rshift(val, 16, 15);
*buf = val >> 15;
buf += 2;
}
}
void AudioAnalyzeFFT4096::update(void)
{
audio_block_t *block;
block = receiveReadOnly();
if (!block) return;
#if defined(KINETISK)
switch (state) {
case 0:
blocklist[0] = block;
state = 1;
break;
case 1:
blocklist[1] = block;
state = 2;
break;
case 2:
blocklist[2] = block;
state = 3;
break;
case 3:
blocklist[3] = block;
state = 4;
break;
case 4:
blocklist[4] = block;
state = 5;
break;
case 5:
blocklist[5] = block;
state = 6;
break;
case 6:
blocklist[6] = block;
state = 7;
break;
case 7:
blocklist[7] = block;
state = 8;
break;
case 8:
blocklist[8] = block;
state = 9;
break;
case 9:
blocklist[9] = block;
state = 10;
break;
case 10:
blocklist[10] = block;
state = 11;
break;
case 11:
blocklist[11] = block;
state = 12;
break;
case 12:
blocklist[12] = block;
state = 13;
break;
case 13:
blocklist[13] = block;
state = 14;
break;
case 14:
blocklist[14] = block;
state = 15;
break;
case 15:
blocklist[15] = block;
state = 16;
break;
case 16:
blocklist[16] = block;
state = 17;
break;
case 17:
blocklist[17] = block;
state = 18;
break;
case 18:
blocklist[18] = block;
state = 19;
break;
case 19:
blocklist[19] = block;
// TODO: perhaps distribute the work over multiple update() ??
// github pull requsts welcome......
copy_to_fft_buffer(buffer+0x000, blocklist[0]->data);
copy_to_fft_buffer(buffer+0x100, blocklist[1]->data);
copy_to_fft_buffer(buffer+0x200, blocklist[2]->data);
copy_to_fft_buffer(buffer+0x300, blocklist[3]->data);
copy_to_fft_buffer(buffer+0x400, blocklist[4]->data);
copy_to_fft_buffer(buffer+0x500, blocklist[5]->data);
copy_to_fft_buffer(buffer+0x600, blocklist[6]->data);
copy_to_fft_buffer(buffer+0x700, blocklist[7]->data);
copy_to_fft_buffer(buffer+0x800, blocklist[8]->data);
copy_to_fft_buffer(buffer+0x900, blocklist[9]->data);
copy_to_fft_buffer(buffer+0x1000, blocklist[10]->data);
copy_to_fft_buffer(buffer+0x1100, blocklist[11]->data);
copy_to_fft_buffer(buffer+0x1100, blocklist[12]->data);
copy_to_fft_buffer(buffer+0x1200, blocklist[12]->data);
copy_to_fft_buffer(buffer+0x1300, blocklist[13]->data);
copy_to_fft_buffer(buffer+0x1400, blocklist[14]->data);
copy_to_fft_buffer(buffer+0x1500, blocklist[15]->data);
copy_to_fft_buffer(buffer+0x1600, blocklist[16]->data);
copy_to_fft_buffer(buffer+0x1700, blocklist[17]->data);
copy_to_fft_buffer(buffer+0x1800, blocklist[18]->data);
copy_to_fft_buffer(buffer+0x1900, blocklist[19]->data);
if (window) apply_window_to_fft_buffer(buffer, window);
arm_cfft_radix4_q31(&fft_inst, buffer);
// TODO: support averaging multiple copies
for (int i=0; i < 2048; i++) {
uint32_t tmp = *((uint32_t *)buffer + i); // real & imag
uint32_t magsq = multiply_16tx16t_add_16bx16b(tmp, tmp);
output[i] = sqrt_uint32_approx(magsq);
}
outputflag = true;
release(blocklist[0]);
release(blocklist[1]);
release(blocklist[2]);
release(blocklist[3]);
release(blocklist[4]);
release(blocklist[5]);
release(blocklist[6]);
release(blocklist[7]);
release(blocklist[8]);
release(blocklist[9]);
blocklist[0] = blocklist[10];
blocklist[1] = blocklist[11];
blocklist[2] = blocklist[12];
blocklist[3] = blocklist[13];
blocklist[4] = blocklist[14];
blocklist[5] = blocklist[15];
blocklist[6] = blocklist[16];
blocklist[7] = blocklist[17];
blocklist[8] = blocklist[18];
blocklist[9] = blocklist[19];
state = 10;
break;
}
#else
release(block);
#endif
}
Code:
/* Audio Library for Teensy 3.X
* Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com
*
* Development of this audio library was funded by PJRC.COM, LLC by sales of
* Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
* open source software by purchasing Teensy or other PJRC products.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice, development funding notice, and this permission
* notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef analyze_fft4096_h_
#define analyze_fft4096_h_
#include "Arduino.h"
#include "AudioStream.h"
#include "arm_math.h"
// windows.c
extern "C" {
extern const int32_t AudioWindowHanning4096[];
}
class AudioAnalyzeFFT4096 : public AudioStream
{
public:
AudioAnalyzeFFT4096() : AudioStream(1, inputQueueArray),
window(AudioWindowHanning4096), state(0), outputflag(false) {
arm_cfft_radix4_init_q31(&fft_inst, 4096, 0, 1);
}
bool available() {
if (outputflag == true) {
outputflag = false;
return true;
}
return false;
}
float read(unsigned int binNumber) {
if (binNumber > 2047) return 0.0;
return (float)(output[binNumber]) * (1.0 / 16384.0);
}
float read(unsigned int binFirst, unsigned int binLast) {
if (binFirst > binLast) {
unsigned int tmp = binLast;
binLast = binFirst;
binFirst = tmp;
}
if (binFirst > 2047) return 0.0;
if (binLast > 2047) binLast = 2047;
uint32_t sum = 0;
do {
sum += output[binFirst++];
} while (binFirst <= binLast);
return (float)sum * (1.0 / 16384.0);
}
void averageTogether(uint8_t n) {
// not implemented yet (may never be, 86 Hz output rate is ok)
}
void windowFunction(const int32_t *w) {
window = w;
}
virtual void update(void);
uint32_t output[2048] __attribute__ ((aligned (4)));
private:
void init(void);
const int32_t *window;
audio_block_t *blocklist[8];
int32_t buffer[8192] __attribute__ ((aligned (4)));
//uint32_t sum[2048];
//uint8_t count;
uint8_t state;
//uint8_t naverage;
volatile bool outputflag;
audio_block_t *inputQueueArray[1];
arm_cfft_radix4_instance_q31 fft_inst;
};
#endif
I am aware there are other methods to implement this, but honestly, the audio library makes using this stuff so exceptionally convenient.