Pages: 1 [2]   Go Down
Author Topic: Fast Fourier Transformation Library? v2.0  (Read 3355 times)
0 Members and 1 Guest are viewing this topic.
the land of sun+snow
Offline Offline
Faraday Member
**
Karma: 159
Posts: 2895
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, since no one volunteered the display I was after, I cobbled one toghether, will print
upto 128 values, and positive-only values, bipolar values, or fullwave-rectified values.

Bar height set = 8 here for compactness, but can be changed inside the display function.
I built a sinewave for display.

Code:
0 49 97 142 180 212 236 251 255 251 236 213 181 142 98 50
0 -49 -97 -141 -180 -212 -236 -250 -255 -251 -236 -213 -181 -142 -98 -50
0 49 97 141 180 212 236 250 255 251 236 213 181 143 99 51
1 -48 -96 -141 -180 -212 -235 -250 -255 -251 -237 -213 -182 -143 -99 -51
        |                               |                       
      |||||                           |||||                     
     |||||||                         |||||||                   
    |||||||||                       |||||||||                   
   |||||||||||                     |||||||||||                 
  |||||||||||||                   |||||||||||||                 
  |||||||||||||                   |||||||||||||                 
 |||||||||||||||                 |||||||||||||||               
----------------------------------------------------------------
                 |||||||||||||||                 |||||||||||||||
                  |||||||||||||                   |||||||||||||
                  |||||||||||||                   |||||||||||||
                   |||||||||||                     ||||||||||| 
                    |||||||||                       |||||||||   
                     |||||||                         |||||||   
                      |||||                           |||||     
                        |                               |       


        |               |               |               |       
      |||||           |||||           |||||           |||||     
     |||||||         |||||||         |||||||         |||||||   
    |||||||||       |||||||||       |||||||||       |||||||||   
   |||||||||||     |||||||||||     |||||||||||     ||||||||||| 
  |||||||||||||   |||||||||||||   |||||||||||||   |||||||||||||
  |||||||||||||   |||||||||||||   |||||||||||||   |||||||||||||
 ||||||||||||||| ||||||||||||||| ||||||||||||||| |||||||||||||||
----------------------------------------------------------------

/*
file: spectrum1
(revised: 03/01/12, orig 03/01/12).

Simple bargraph-type spectrum display.
*********************************************/

#define WAVSZ  64
int wave[WAVSZ];

/********************************************/
void setup()
{
  Serial.begin(57600);
  build_sine(2, wave, WAVSZ);
  display_wave(wave, WAVSZ, -1);
  //
  newline();
  display_wave(wave, WAVSZ, 0);
}

/********************************************/
void loop()
{
}

/*
  freq in #cycles.
**********************************************/
void build_sine(int freq, int ary[], int siz)
{
  for( int i=0; i<siz; i++) {
    if( (i % 16) == 0) newline();
    ary[i] = (int)(256 * sin(freq * (float)i * 6.28 / (float)siz));
    Serial.print( ary[i] );
    spc();
  }
}

/*
  display integer ary[] of siz values.
  - show 64 cells max.
  - posneg = 1, display positive values only.
    posneg = 0, full-wave rectify data.
    posneg = -1, display in bipolar format.
*******************************************************/
void display_wave(int ary[], int siz, int posneg)
{
  #define BARMAX    8   // maximum bar height.
  #define DISPMAX  128  // maximum display size.
  int dat[DISPMAX];
  int i, j, x, max=0;
  int dispsz=DISPMAX;
 
  // set max# display cells.
  if( siz < DISPMAX ) dispsz = siz;
 
  // find maximum, and normalize data.
  for( i=0; i<siz; i++) {
    x = ary[i];
    if( x < 0 ) x = -x;
    if( x > max) max = x;
  }
  // normalize data to +/-BARMAX.
  for( i=0; i<siz; i++) {
    x = ary[i];
    if( (posneg == 0) && (x < 0) ) x = -x;
    dat[i] = (int)( (long)x * (long)BARMAX / max);
  }
  newline();
  // display data >= 0.
  for( j=BARMAX; j > 0; j--) {
    for( i=0; i<dispsz; i++) {
      x = dat[i];
      if( x < j ) spc();
        else vbar();
    }
    newline();
  }
  disp_xaxis(siz);
  newline();
  if( posneg >= 0 ) return;
 
  // display data < 0.
  for( j=0; j > -BARMAX; j--) {
    for( i=0; i<dispsz; i++) {
      x = dat[i];
      if( x < j ) vbar();
        else spc();
    }
    newline();
  }
}

/*
  display horizontal axis.
******************************/
void disp_xaxis(int siz)
{
  for( int i=0; i<siz; i++) Serial.write("-"); 
}

/*
  print utilities: vertical bar, space, newline.
***************************************************/
void vbar()    {  Serial.write('|');  }
void spc()     {  Serial.write(' ');  }
void newline() {  Serial.print("\n"); }
Logged

Global Moderator
Offline Offline
Brattain Member
*****
Karma: 474
Posts: 18696
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That's very cool! Well done. smiley

On the bright side, think of how much you learned by doing it yourself.

And thanks for sharing the code.
Logged

Seattle, WA
Offline Offline
Full Member
***
Karma: 1
Posts: 225
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Nick Gammon, yeah i converted the print to DEC and it works great now. I was getting values over 12 in the monitor, but i think i can manage getting that to work correctly. here is the code:
Code:
/*
FFT for printing 12 values mapped to 12
based on FFT library and code from the Arduino forums
*/

#include <fix_fft.h>

#define AUDIOPIN 5


char im[128], data[128];

char data_avgs[12];

int i = 0, val;



void setup() {
Serial.begin(9600);
}


void loop() {

for (i=0; i < 128; i++){
  val = analogRead(AUDIOPIN);
  data[i] = val;
  im[i] = 0;
}

fix_fft(data,im,7,0);

for (i = 0; i < 64;i++){
data[i] = sqrt(data[i] * data[i] + im[i] * im[i]); // this gets the
//absolute value of the values in the array, so we're only dealing
//with positive numbers
}


// average bars together
 for (i=0; i<12; i++) {
 data_avgs[i] = data[i*5] + data[i*5 + 1] + data[i*5 + 2] + data[i*5 + 3] + data[i*5 + 4]; // average together, for 12 sets of 5
 data_avgs[i] = map(data_avgs[i], 0, 37, 0, 12); // remap values for my application, so 12
 }
// print out the averaged bars
    for (i=0; i<12; i++)
        {
        Serial.print(data_avgs[i], DEC);
        if (i < 11)
            Serial.print(", ");  // Separate values for easy reading
        else
            Serial.println(".");   // End of line
        }
}
You guys are the best, thanks so much. smiley smiley smiley smiley smiley 
Logged

"It's Dr. Evil. I didn't spend six years in Evil Medical School to be called 'mister,' thank you very much."

Seattle, WA
Offline Offline
Full Member
***
Karma: 1
Posts: 225
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

One more quick question, the intensity of the numbers in the moniter changed intensity depending on what volume the music was being played. Is there a simple hardware or software solution for this?? Thanks.
Logged

"It's Dr. Evil. I didn't spend six years in Evil Medical School to be called 'mister,' thank you very much."

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there a simple hardware or software solution for this??
There is a very simple solution. Quit changing the volume.

You could always find the minimum value in the array, and subtract that value from all the other positions. However, if you are trying to make a VU meter, the values are supposed to change as volume does.
Logged

Seattle, WA
Offline Offline
Full Member
***
Karma: 1
Posts: 225
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow. Your wit astounds me. Good solution.
Logged

"It's Dr. Evil. I didn't spend six years in Evil Medical School to be called 'mister,' thank you very much."

Pages: 1 [2]   Go Up
Jump to: