Coder Social home page Coder Social logo

esp32-fft's Introduction

ESP32 FFT

This provides a vanilla radix-2 FFT out-of-place implementation and a test example.

Author

This code was written by Robin Scheibler during rainy days in October 2017.

Example

#include "fft.h"

...

// Create the FFT config structure
fft_config_t *real_fft_plan = fft_init(NFFT, FFT_REAL, FFT_FORWARD, NULL, NULL);

// Fill array with some data
for (k = 0 ; k < fft_analysis->size ; k++)
  real_fft_plan->input[k] = (float)k;

// Execute transformation
fft_execute(real_fft_plan);

// Now do something with the output
printf("DC component : %f\n", real_fft_plan->output[0]);  // DC is at [0]
for (k = 1 ; k < real_fft_plan->size / 2 ; k++)
  printf("%d-th freq : %f+j%f\n", k, real_fft_plan->output[2*k], real_fft_plan->output[2*k+1]);
printf("Middle component : %f\n", real_fft_plan->output[1]);  // N/2 is real and stored at [1]

// Don't forget to clean up at the end to free all the memory that was allocated
fft_destroy(real_fft_plan)

Documentation

  1. Create the FFT configuration by running fft_init.

     fft_config_t *fft_init(int size, fft_type_t type, fft_direction_t direction, float *input, float *output)
    
     Parameters
     ----------
     size : int
         The FFT size (should be a power of two), if not, returns NULL.
     type : fft_type_t
         The type of FFT, FFT_REAL or FFT_COMPLEX
     direction : fft_direction_t
         The direction, FFT_FORWARD or FFT_BACKWARD (inverse transformation)
     input : float *
         A pointer to a buffer of the correct size. If NULL, a buffer is allocated dynamically
     output : float *
         A pointer to a buffer of the correct size. If NULL, a buffer is allocated dynamically.
    
     Returns
     -------
     A pointer to an `fft_config_t` structure that holds pointers to the buffers and
     all the necessary configuration options.
    
  2. Fill data in the input buffer

  3. Call fft_execute to run the FFT

  4. Use the transformed data located in the output buffer

  5. Possibly free up memory by calling fft_destroy on the configuration structure

Note about Inverse Real FFT

When doing an inverse real FFT, the data in the input buffer is destroyed.

Buffer sizes and data organization

  • For FFT_REAL FFTs (forward as well as backward) of size NFFT, the buffer is of size NFFT. Then, the input data is organized as

      Input  : [ x[0], x[1], x[2], ..., x[NFFT-1] ]
      Output : [ X[0], X[NFFT/2], Re(X[1]), Im(X[1]), ..., Re(X[NFFT/2-1]), Im(X[NFFT/2-1]) ]
    
  • For FFT_COMPLEX of size NFFT, the buffer is of size 2 * NFFT as both real and imaginary parts should be saved.

      Input  : [ Re(x[0]), Im(x[0]), ..., Re(x[NFFT-1]), Im(x[NFFT-1]) ]
      Output : [ Re(X[0]), Im(X[0]), ..., Re(X[NFFT-1]), Im(X[NFFT-1]) ]
    

License

This software is released under the MIT license.

Copyright (c) 2017 Robin Scheibler

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 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.

esp32-fft's People

Contributors

fakufaku avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

esp32-fft's Issues

Slightly unexpected results, maybe my mistake?

For some reason if I generate a sine wave at excactly 1000.f Hz and 32kHz sample rate and run it through the real fft, I'll yield a peak frequency of exactly 3000 Hz, which is a bit odd, since it's not just a multiple fundamental, the fundamental has a much lower rms value, all the multiples have a quite low assigned value, and everything else is 0. I wonder why that is, because dumping the exact same sine wave as pcm wav file and running it through e.g. Audacity yields a perfect peak at 1000 with no harmonics. Size of fft doesn't matter, 2 << 8 through 2 << 16 all yield the exact same result.

Interestingly just using 1000.1f will work just fine and be "seen" as around 1000-ish.

Output Array not organized

Hey there,

I've tested out your code and it works very fast and I am confident in the values however, when testing using a function generator i'd increase the frequency ranging from 100Hz->22kHz and the index of the max output does not match to what i'd expect. For example using a 64 sample size and a test range of 1kHz->6kHz, the index would increase consecutively (5, 6, 7, 8 ,9) but for other increasing frequency ranges it would bounce around (21, 38, 18, 50). Shouldn't the indexes be scaled to the range of frequency?

How to use this library

Hi, I'm interested in using this lib on an ESP32. But how do I compile/flash it?
I'm running Windows 7/10 machines and are unable to use linux here at work.
At the moment I only have the ArduinoIDE installed on my working machine. But for sure I can aso our IT to install PlatformIO or anything else if required.

Which framework is it supposed to be used with?
A short info in the readmefile would have been nice - especially for beginners like me ;)

How to make it work without destroying the config each time ?

I am trying to run fft on two input arrays back and forth.

ft_config_t *fft_analysis = fft_init(4096, FFT_REAL, FFT_FORWARD, fft_input0, fft_output);
//Do something
fft_destroy(fft_analysis);
ft_config_t *fft_analysis = fft_init(4096, FFT_REAL, FFT_FORWARD, fft_input1, fft_output);
//Do something
fft_destroy(fft_analysis);

Both arrays are of same size. Is it possible to use it such that I don't have to run fft_init every time and instead just change the input and run fft_execute ? I want to do so because fft_init takes more time than fft_execute. And I am short on CPU time.

Best way to implement Peak Detection ?

Hi Robin! i'm very interested to fork and port it on Arduino, for now i'm running this on ESP-IDF sdk but..
i don't have much experience on FFT but... what you think is the best way to implement a frequency Peak Detection?
Thanks for your help.

ps. i tried on on Arduino environment, i don't understand the reason but the benchmark results are slower than the firmware compiled on C in ESP-IDF

arduino
// Now measure execution time tStart = millis(); digitalWrite(GPIO_OUTPUT, 1); for (k = 0 ; k < REP ; k++) fft_execute(fft_analysis); digitalWrite(GPIO_OUTPUT, 0); printf(" FFT size=%d runtime=%d ms\n", NFFT, (millis() - tStart));

' FFT size=64 runtime=2 ms
iFFT size=64 runtime=3 ms
Transform seems to work!
FFT size=128 runtime=5 ms
iFFT size=128 runtime=6 ms
Transform seems to work!
FFT size=256 runtime=10 ms
iFFT size=256 runtime=12 ms
Transform seems to work!
FFT size=512 runtime=21 ms
iFFT size=512 runtime=27 ms
Transform seems to work!
FFT size=1024 runtime=48 ms
iFFT size=1024 runtime=58 ms
Transform seems to work!
FFT size=2048 runtime=104 ms
iFFT size=2048 runtime=126 ms
Transform seems to work!
FFT size=4096 runtime=225 ms
iFFT size=4096 runtime=269 ms
Transform seems to work!
Real FFT size=64 runtime=1 ms
Real iFFT size=64 runtime=1 ms
Transform seems to work!
Real FFT size=128 runtime=3 ms
Real iFFT size=128 runtime=3 ms
Transform seems to work!
Real FFT size=256 runtime=5 ms
Real iFFT size=256 runtime=7 ms
Transform seems to work!
Real FFT size=512 runtime=12 ms
Real iFFT size=512 runtime=15 ms
Transform seems to work!
Real FFT size=1024 runtime=26 ms
Real iFFT size=1024 runtime=32 ms
Transform seems to work!
Real FFT size=2048 runtime=57 ms
Real iFFT size=2048 runtime=69 ms
Transform seems to work!
Real FFT size=4096 runtime=123 ms
Real iFFT size=4096 runtime=146 ms'

' FFT size=64 runtime=0.018380 ms
iFFT size=64 runtime=0.027940 ms
Transform seems to work!
FFT size=128 runtime=0.041850 ms
iFFT size=128 runtime=0.058130 ms
Transform seems to work!
FFT size=256 runtime=0.095090 ms
iFFT size=256 runtime=0.125000 ms
Transform seems to work!
FFT size=512 runtime=0.211900 ms
iFFT size=512 runtime=0.269020 ms
Transform seems to work!
FFT size=1024 runtime=0.469330 ms
iFFT size=1024 runtime=0.580850 ms
Transform seems to work!
FFT size=2048 runtime=1.028650 ms
iFFT size=2048 runtime=1.249040 ms
Transform seems to work!
FFT size=4096 runtime=2.239450 ms
iFFT size=4096 runtime=2.677460 ms
Transform seems to work!
Real FFT size=64 runtime=0.010620 ms
Real iFFT size=64 runtime=0.016860 ms
Transform seems to work!
Real FFT size=128 runtime=0.024330 ms
Real iFFT size=128 runtime=0.034250 ms
Transform seems to work!
Real FFT size=256 runtime=0.053820 ms
Real iFFT size=256 runtime=0.070890 ms
Transform seems to work!
Real FFT size=512 runtime=0.119000 ms
Real iFFT size=512 runtime=0.150520 ms
Transform seems to work!
Real FFT size=1024 runtime=0.259810 ms
Real iFFT size=1024 runtime=0.320190 ms
Transform seems to work!
Real FFT size=2048 runtime=0.565280 ms
Real iFFT size=2048 runtime=0.683220 ms
Transform seems to work!
Real FFT size=4096 runtime=1.220650 ms
Real iFFT size=4096 runtime=1.453830 ms'

Arduino Millis() does not return milliseconds value?

Arduino IDE, frequency ordering in input and output fields

Hi fakufaku,
I am using your library under arduino IDE and its working without any issues. On the code page of the project, I am missing the ordering of positive and negative frequencies in input and output fields for case of the complex numbers. Can you add it please?

To be precise, I mean: How an amplitude in the input (for IFFT) or output (for FFT) field of the complex numbers is related to its frequency. By trial and error I recognized, that the negative frequencies (for FFT) are ordered from upper index - NFFT-1 downside and positive from index 0 upside. But I am not sure, if component with index NFFT/2 is related to highest positive of lowest negative frequency.

Thanks for explanation.

Real FFT frequency axis to linear

I found your library after implementing one by myself.
You did a great job gathering most of the options into one library for benchmark in ESP32!
I believe you had configured your ESP32 clock at 160Mhz rather than 240Mhz. So real benchmark is a little faster than what you published.

In the other hand I am very interested in the Real FFT. I manage to use it but I don't know how to interpret the X axis of the FFT (Real data points -> FFT -> Frequency domain). When comparing it to traditional it seems like it is in a Log basis. Do you know how to interpret it/ convert it into a linear relationship?

I am currently using the 4096 size for data being sampled at 4096Hz. I know I have a frequency at 1500Hz which is being shown at 1095Hz. How can I get the output frequencies back to its linear approximation?

Thanks!
esp32_fft

Large sample array issue

Hi, I found your code and my ESP32 crashes whenever 'size' in fft_init becomes larger than 4096. I've seen the same problem with Arduinofft. In Arduinofft you need to define two double arrays (real and imag). If the two arrays become too large it will not fit in the ESP32 dram. When using Arduinofft and you define the arrays too large you will see a compiler warning. With your code there's no compiler error but the ESP32 simply crashes.
I need a large sample array because I want to create an class-I audiometer. For this you need to sample with a speed of 48kHz and for a duration of 125ms.
Can you confirm? And if so do you have a solution?

Arduino compatibility

Have you considered making this library 'Arduino compatible'?

I think this mostly just means putting the source code and examples in specific directories, adding a library.properties file and a library.json file. You probably don't have anything in there that is really hardware dependent.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.