Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 24 of 24

Thread: FFT on Teesy 4?

  1. #1

    FFT on Teesy 4?

    Is it possible to do an FFT on the Teensy 4? I was reading that the audio library wiring doesn't work to connect ADC(A0) to the fft1024_1.

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    Yes, it should. Not sure what was at hand when reading about the issues and how it affects desired use?

  3. #3
    Click image for larger version. 

Name:	Capture.PNG 
Views:	93 
Size:	19.4 KB 
ID:	19853

    I get this when I try to compile this:
    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    // GUItool: begin automatically generated code
    AudioInputAnalog         adc1;           //xy=193,57
    AudioAnalyzeFFT1024      fft1024_1;      //xy=461,75
    AudioConnection          patchCord1(adc1, fft1024_1);
    // GUItool: end automatically generated code
    
    void setup(){
      
    }
    
    void loop(){
      
    }
    I'm not using the audio board. Am I doing something wrong?

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    Perhaps look at the Audio Tutorial FFT examples on the PJRC site. It seems that is missing some things.

  5. #5
    I just watched the relevant portion of the audio tutorial again, and scoured the prjc site for more info on the FFT direct from the ADC, and I don't see anything wrong with my code. The error makes it look like something can't be found in the .h file.

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    Put an Audio board Rev D onto a T_4.0 - and seeing streaming FFT data going by on USB display.

    Using :: ...\hardware\teensy\avr\libraries\Audio\examples\T utorial\Part_3_02_Fourier_Transform\Part_3_02_Four ier_Transform.ino

    That isn't feeding from ADC data - but FFT on T_4.0 works - in this sample using the PJRC audio board as the auto driver for output. The Tutorial focuses on the Audio board - not sure if that is in use - assumed not as it is not in the posted code?
    Info on ADC usage is showing examples: pjrc.com/teensy/gui/?info=AudioInputAnalog
    Code:
    Examples
    File > Examples > Audio > HardwareTesting > PassThroughMono 
    File > Examples > Audio > Analysis > PeakMeterMono 
    File > Examples > Audio > Analysis > DialTone_7segment 
    File > Examples > OctoWS2811 > SpectrumAnalyzer 
    Notes
    analogRead() must not be used, because AudioInputAnalog is regularly accessing the ADC hardware. If both access the hardware at the same moment, analogRead() can end up waiting forever, which effectively crashes your program. 
    A different pin may be used, but adding it as an parameter to the AudioInputAnalog object definition. 
    For example, to use pin A3: 
    AudioInputAnalog adc1(A3);
    > that shows 'AudioInputAnalog adc1(A3);' differs from the above where no pin is given - so "Audio input needs to connect to pin 16 (A2). The signal range is 0 to 1.2V." - according to that GUI Tool text.

    A provided example close to post #3 looks to be :: ...\hardware\teensy\avr\libraries\Audio\examples\A nalysis\PeakMeterMono\PeakMeterMono.ino
    > Perhaps seeing that work with these notes will help as it does not use the PJRC Audio Board. After seeing the 'Peak' work it should easily evolve into FFT usage from one of the other examples.

    And as indicated in the following there is no "AudioMemory( ## )" from :: ...\hardware\teensy\avr\libraries\Audio\examples\A nalysis\SpectrumAnalyzerBasic\SpectrumAnalyzerBasic.ino
    Code:
    void setup() {
      // Audio requires memory to work.
      AudioMemory(12);
    To run the above sketch "Part_3_02_Fourier_Transform.ino" these lines needed to be added - a SD card on the audio board with PJRC file "SDTEST1.WAV" present:
    Code:
    #include <Audio.h>
    #include <Wire.h>
    #include <SPI.h>
    #include <SD.h>
    #include <SerialFlash.h>
    
    
    ///////////////////////////////////
    // copy the Design Tool code here
    ///////////////////////////////////
    // GUItool: begin automatically generated code
    AudioPlaySdWav           playSdWav1;     //xy=90,44
    AudioPlayMemory          playMem1;       //xy=94,113
    AudioSynthWaveform       waveform1;      //xy=104,170
    AudioMixer4              mixer1;         //xy=290,91
    AudioAnalyzeFFT1024      fft1024_1;      //xy=461,132
    AudioOutputI2S           i2s1;           //xy=465,58
    AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
    AudioConnection          patchCord2(playSdWav1, 1, mixer1, 1);
    AudioConnection          patchCord3(playMem1, 0, mixer1, 2);
    AudioConnection          patchCord4(waveform1, 0, mixer1, 3);
    AudioConnection          patchCord5(mixer1, 0, i2s1, 0);
    AudioConnection          patchCord6(mixer1, 0, i2s1, 1);
    AudioConnection          patchCord7(mixer1, fft1024_1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=352,195
    // GUItool: end automatically generated code

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    Quote Originally Posted by pwd847 View Post
    I just watched the relevant portion of the audio tutorial again, and scoured the prjc site for more info on the FFT direct from the ADC, and I don't see anything wrong with my code. The error makes it look like something can't be found in the .h file.
    No error details were provided. Cut and paste of text from the console would show what that was.

    Perhaps it is the error showing here compiling the suggested : ...\hardware\teensy\avr\libraries\Audio\examples\A nalysis\PeakMeterMono\PeakMeterMono.ino

    Just posted a question about that on the TD 1.52 B3 thread - as that may in fact be not yet supported - but FFT's are working.

  8. #8
    Senior Member
    Join Date
    Jul 2014
    Posts
    3,059
    Quote Originally Posted by defragster View Post
    No error details were provided. Cut and paste of text from the console would show what that was.
    See Capture.PNG in #3

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    Quote Originally Posted by WMXZ View Post
    See Capture.PNG in #3
    Indeed it is there once clicked … I thought that was an audio wave form of some sort ( scope or LA ) proving it wasn't working somehow since the code has no loop() there would be no SerMon output.

    Anyhow the answer is - indeed T_4.0 lacks ADC1 support at this time:
    Quote Originally Posted by Frank B View Post
    No, there were several threads absolut this... as with PWM,
    this is still a missing part in the T4 Audiolib.
    I would help with this, or add it, if I knew a way to clock it with 44.100kHz

  10. #10
    Well I have about 24 hours to code my own FFT then. Hmmm...

  11. #11
    Any updates on this thread? Is FFT really not working on teensy 4.0 + the audio board?

  12. #12
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    FFT was working on T_4 - what wasn't working was getting the data from :: AudioInputAnalog adc1;

    That it seems was fixed to work in the TD 1.52 B4 release today. Please try and update.

    Teensyduino-1-52-Beta-4

  13. #13
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,731
    "fixed" might be a strong word to use. "experimental" or "alpha" is probably better.

    ADC input does work now, but still has many caveats. Among them, it requires another input or output because it does not yet cause the audio library to update.

  14. #14
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    Well the COMPILE error was fixed … and provided the link to notes about the need for RunTime caveats …

  15. #15
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,731
    Here is a program which will run on Teensy 4.0 using 1.52-beta4 and gives you FFT of an audio signal on analog pin A2.

    Code:
    #include <Audio.h>
    
    // GUItool: begin automatically generated code
    AudioInputAnalog         adc1;           //xy=197,73
    AudioAnalyzeFFT1024      fft1024_1;      //xy=361,47
    AudioOutputI2S           i2s1;           //xy=378,99
    AudioConnection          patchCord1(adc1, 0, i2s1, 0);
    AudioConnection          patchCord2(adc1, 0, i2s1, 1);
    AudioConnection          patchCord3(adc1, fft1024_1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=265,161
    // GUItool: end automatically generated code
    
    void setup() {
      AudioMemory(30);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
      while (!Serial) ; // wait for Arduino Serial Monitor
      Serial.println("FFT test");
    }
    
    void loop() {
      if (fft1024_1.available()) {
        for (int i=0; i < 20; i++) {  // print the first 20 bins
          Serial.print(fft1024_1.read(i), 3);
          Serial.print(" ");
        }
        Serial.println();
      }
    }
    This will work without the audio shield present, but I2S output (or any other I/O object that causes the library to update) is currently required. Future versions will remove this requirement. Please understand this ADC audio code is very new and still has many minor issues. But at least you can see we're making progress towards ADC input for audio.

    One of those many minor issues is the level. A full scale waveform on the ADC pin does not yet map to a full scale signal coming into the audio library. Removal of DC offset also isn't working well yet.

  16. #16
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,421
    Quote Originally Posted by PaulStoffregen View Post
    Here is a program which will run on Teensy 4.0 using 1.52-beta4 and gives you FFT of an audio signal on analog pin A2.

    Code:
    #include <Audio.h>
    
    // GUItool: begin automatically generated code
    AudioInputAnalog         adc1;           //xy=197,73
    AudioAnalyzeFFT1024      fft1024_1;      //xy=361,47
    AudioOutputI2S           i2s1;           //xy=378,99
    AudioConnection          patchCord1(adc1, 0, i2s1, 0);
    AudioConnection          patchCord2(adc1, 0, i2s1, 1);
    AudioConnection          patchCord3(adc1, fft1024_1);
    AudioControlSGTL5000     sgtl5000_1;     //xy=265,161
    // GUItool: end automatically generated code
    
    void setup() {
      AudioMemory(30);
      sgtl5000_1.enable();
      sgtl5000_1.volume(0.5);
      while (!Serial) ; // wait for Arduino Serial Monitor
      Serial.println("FFT test");
    }
    
    void loop() {
      if (fft1024_1.available()) {
        for (int i=0; i < 20; i++) {  // print the first 20 bins
          Serial.print(fft1024_1.read(i), 3);
          Serial.print(" ");
        }
        Serial.println();
      }
    }
    This will work without the audio shield present, but I2S output (or any other I/O object that causes the library to update) is currently required. Future versions will remove this requirement. Please understand this ADC audio code is very new and still has many minor issues. But at least you can see we're making progress towards ADC input for audio.

    One of those many minor issues is the level. A full scale waveform on the ADC pin does not yet map to a full scale signal coming into the audio library. Removal of DC offset also isn't working well yet.
    Paul - this code works on T_4.0 and 4.1 - but as noted elsewhere FAILS on T_3.6 [ using IDE 1.8.12 and TD 1.52 B4 ]::
    Code:
    "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SD\\fat_t3.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SD\\file_t3.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SD\\init_t3.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SD\\utility\\NXP_SDHC.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SD\\utility\\Sd2Card.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SD\\utility\\SdFile.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SD\\utility\\SdVolume.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SerialFlash\\SerialFlashChip.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\SerialFlash\\SerialFlashDirectory.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\Wire\\Wire.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\Wire\\WireIMXRT.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\Wire\\WireKinetis.cpp.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino\\libraries\\Wire\\utility\\twi.c.o" "T:\\TEMP\\arduino_build_AnalogFFT.ino/core\\core.a" "-LT:\\TEMP\\arduino_build_AnalogFFT.ino" -larm_cortexM4lf_math -lm
    T:\TEMP\arduino_build_AnalogFFT.ino\sketch\AnalogFFT.ino.cpp.o: In function `AudioInputAnalog::AudioInputAnalog(unsigned char)':
    T:\arduino-1.8.12\hardware\teensy\avr\libraries\Audio/input_adc.h:38: undefined reference to `AudioInputAnalog::init(unsigned char)'
    T:\TEMP\arduino_build_AnalogFFT.ino\sketch\AnalogFFT.ino.cpp.o: In function `AudioStream::AudioStream(unsigned char, audio_block_struct**)':
    T:\arduino-1.8.12\hardware\teensy\avr\cores\teensy3/AudioStream.h:138: undefined reference to `vtable for AudioInputAnalog'
    collect2.exe: error: ld returned 1 exit status

  17. #17
    Junior Member
    Join Date
    Feb 2021
    Posts
    9
    Quote Originally Posted by defragster View Post

    "Audio input needs to connect to pin 16 (A2). The signal range is 0 to 1.2V." - according to that GUI Tool text.


    To run the above sketch "Part_3_02_Fourier_Transform.ino" these lines needed to be added - a SD card on the audio board with PJRC file "SDTEST1.WAV" present

    Hello dear defragster / dear forum members,


    I have a few questions regarding the FFT Example:

    Above you said that audio input needs to be connected to pin 16...so does that mean that if I'm connecting a device like e.g. a little Synthesizer to pin 16 the serial monitor / plotter will show me the spectrum of that signal?

    Why do i need the file "SDTEST1.WAV" on my SD card? In the "Part_3_02_Fourier_Transform" example there is a sample of a guitar "AudioSampleGuitar.cpp / .h"... I thought the Fourier analysis was taken from that sample rather than the .WAV file? Or am I seeing the spectrum of "SDTEST1.WAV" right now?

    So are different data types possible then? What I mean: Can I only get the FFT of an wav2sketch sampled .WAV signal? Or also as an analog signal like a synth coming into pin16? Or could I directly send an .WAV into the code without converting it before? What format(s) is / are needed for the FFT?

    Furthermore: Does somebody know on how to find the highest peak in the resulting spectrum? So e.g. if I'm playing an A (440Hz) on my piano, the fundamental of f = 440 Hz should be the loudest in that signal - but how loud is it? Everything coming from the "Part_3_02_Fourier_Transform" - Code is very numerical, I can't really translate those values / LED-pictures to an actual dB-value...any ideas how to transform the values coming out of that "Part_3_02_Fourier_Transform" - Code into some more audio-relatable data like decibel?

    Thanks a lot for this thread and your help guys


    With kind regards,
    Mala

  18. #18
    Senior Member
    Join Date
    Jul 2020
    Posts
    667
    Quote Originally Posted by mala96 View Post
    Hello dear defragster / dear forum members,


    I have a few questions regarding the FFT Example:

    Above you said that audio input needs to be connected to pin 16...so does that mean that if I'm connecting a device like e.g. a little Synthesizer to pin 16 the serial monitor / plotter will show me the spectrum of that signal?
    So long as the signal is in the correct voltage range, 0..Vcc (otherwise you'll risk frying the chip - the suggested interface circuit in the
    docs for adc input doesn't seem to feature any protection alas - at the very least its wise to use series resistor and schottky clamps if
    the voltage source is from an external piece of equipment)

    So are different data types possible then? What I mean: Can I only get the FFT of an wav2sketch sampled .WAV signal? Or also as an analog signal like a synth coming into pin16? Or could I directly send an .WAV into the code without converting it before? What format(s) is / are needed for the FFT?
    Any signal you can get into the audio lib system can be processed however you like with any object. Internally its 44.1kSPS and 16 bit signed
    throughout.

    Furthermore: Does somebody know on how to find the highest peak in the resulting spectrum? So e.g. if I'm playing an A (440Hz) on my piano, the fundamental of f = 440 Hz should be the loudest in that signal - but how loud is it? Everything coming from the "Part_3_02_Fourier_Transform" - Code is very numerical, I can't really translate those values / LED-pictures to an actual dB-value...any ideas how to transform the values coming out of that "Part_3_02_Fourier_Transform" - Code into some more audio-relatable data like decibel?
    That's up to your coding I think - scan the fft bins and find the greatest... BTW its not necessarily true that the fundamental has the
    highest amplitude in a musical note, though often the case. To pick the dominant tone there are much better algorithms than picking
    the highest peak in the FFT, for instance cepstrum analysis is used for speech decoding as its more reliable. For this sort of task
    I'd recommend looking around for existing libraries and projects.
    Thanks a lot for this thread and your help guys


    With kind regards,
    Mala

  19. #19
    Junior Member
    Join Date
    Feb 2021
    Posts
    9
    Quote Originally Posted by MarkT View Post
    So long as the signal is in the correct voltage range, 0..Vcc (otherwise you'll risk frying the chip - the suggested interface circuit in the
    docs for adc input doesn't seem to feature any protection alas - at the very least its wise to use series resistor and schottky clamps if
    the voltage source is from an external piece of equipment)
    Thanks for the advice, i will try that out! Did you ever connect a microphone to one of your teensys / audio boards? Would be interested if you got any tips for a good little MIC and what to bear in mind when connecting it

    Quote Originally Posted by MarkT View Post
    That's up to your coding I think - scan the fft bins and find the greatest... BTW its not necessarily true that the fundamental has the
    highest amplitude in a musical note, though often the case. To pick the dominant tone there are much better algorithms than picking
    the highest peak in the FFT, for instance cepstrum analysis is used for speech decoding as its more reliable. For this sort of task
    I'd recommend looking around for existing libraries and projects.
    Since you've posted in the thread i've started last week (https://forum.pjrc.com/threads/66288...ation-with-FFT) I can tell you why I'm interested in the FFT algorithm:
    I've analyzed the spectrum of my voice inside a DAW. It has a nearly constant fundamental and a very unique overtone series. I actually do not need THE lowest frequency of the signal, it just has to be one of the lowest overtones f. Then I would search for 2f, 3f, 4f and so on. If I could measure the values / loudness of the different frequencies I could actually create my own "voice fingerprint" with that. Taking a second recording I could then evaluate if the person talking into the microphone creates a different spectrum or not.

    To realize this approach I'll need to have access to the different peaks of the spectrum and that's the current issue I'm trying to solve.

    I've never heard of Cepstrum Analysis, thanks for sharing that with me! I googled it and researched a bit on how the transformation works and it is a really powerful tool if you want to evaluate the periodicity of a signal. However I wouldn't see a benefit in using this transformation in my case, since I think the DFT/FFT approach would be way easier to program.

    Thanks for reading this and thanks for any advice / help!


    With kind regards,
    Mala

  20. #20
    Senior Member
    Join Date
    Jul 2020
    Posts
    667
    Voice spectra contain both the signature of the harmonics, related to the waveform from the vocal chords,
    and the filtering envelope imposed by the throat/mouth cavity, which doesn't change in frequency with the
    note, but can change in character with mouth/tongue/soft-palette position (vowel sounds are principally due to this part).

  21. #21
    Junior Member
    Join Date
    Feb 2021
    Posts
    9
    Quote Originally Posted by MarkT View Post
    filtering envelope imposed by the throat/mouth cavity, which doesn't change in frequency with the
    note, but can change in character with mouth/tongue/soft-palette position (vowel sounds are principally due to this part).
    Yes exactly, there isn't really one unique recording of your voice which will always sound the same - there will be filtering-effects due to different recording sessions. I thought of something like a "frequency tolerance" for this issue. Something like this:

    If (f0_new >= f0_old + 5 || f0_new <= f0_old - 5)
    return 0; // Authentification failed

    I know it all looks a bit improvised at this point. But i don't think one wouldn't be able to realize an algorithm like that. But first of all I need to get concrete values for the frequencies and their levels. That's why i was asking here in this thread on how to translate the FFT1024 values.

    (I also would still be interested why you'd need the "SDTEST1.WAV" for this example code? Is the spectrum I'm seeing taken of "AudioSampleGuitar" or of "SDTEST1.WAV"?)

    With kind regards, Mala

  22. #22
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,543
    You need to install the three buttons to use the complete example code. By default it uses SDTEST1.WAV as the audio input to the FFT. Each of the three buttons selects a different input.
    Code:
    // Left button starts playing a new song
    .
    .
    // Middle button plays Guitar sample
    .
    .
    // Right button plays a pure sine wave tone

    and BTW.
    This:
    Code:
    If (f0_new >= f0_old + 5 || f0_new <= f0_old - 5)
    would always be true. It should be this:
    Code:
    if (f0_new >= f0_old + 5 && f0_new <= f0_old - 5)
    Pete

  23. #23
    Junior Member
    Join Date
    Feb 2021
    Posts
    9
    Quote Originally Posted by el_supremo View Post
    You need to install the three buttons to use the complete example code. By default it uses SDTEST1.WAV as the audio input to the FFT. Each of the three buttons selects a different input.
    Thanks a lot Pete, I'll try to install the buttons and analyze the FFTs of the other Signals!

    Quote Originally Posted by el_supremo View Post
    and BTW.
    This:
    Code:
    If (f0_new >= f0_old + 5 || f0_new <= f0_old - 5)
    would always be true. It should be this:
    Code:
    if (f0_new >= f0_old + 5 && f0_new <= f0_old - 5)
    Pete
    I'm not sure about that, because with && the value f0_new would need to be 5Hz higher than f0_old and 5 Hz lower than f0_old at the same time which would then always be false I think?


    Code:
    If (f0_new >= f0_old + 5 || f0_new <= f0_old - 5)

    Assuming f0_old is 200 Hz, then with this or conjunction f0_new would need to be between 195 Hz and 205 Hz (if I'm not overseeing something)

    Thanks for your help guys!


    With kind regards,
    Mala

  24. #24
    Senior Member
    Join Date
    Nov 2012
    Posts
    1,543
    I'm not sure about that
    You're absolutely right. I misread it. Sorry.

    If you just want to see the spectrum of the guitar sample, There's a variable that is set to 0, 1 or 2 when you push the buttons. It is initially zero. If you initialize it to 1, you'll get the guitar spectrum without needing any extra hardware - although the buttons could just be jumper wires and you ground one of them.

    Pete

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •