Audio Spectrum analyzer FFT / Disco lys (Læst 2703x)

Offline Jakobsen

  • Højpas filter
  • *****
  • Indlæg: 302
  • Antal brugbare Indlæg: 45
    • Vis profil
Audio Spectrum analyzer FFT / Disco lys
« Dato: Maj 18, 2017, 19:20:57 »
Hej

Jeg roder lidt med at lave noget styring af en programmerbar RGB led strip baseret på HL1606 .
Jeg benytter Arduino UNO.
Jeg kan sagten styre LED som jeg gerne vil med forskellige effekter (løb, blink mm)

Men nu kommer det lidt mere kompliceret, at styre det til musik,
Jeg har en electret mikrofon og en op-amp LM324 (single supply 5V) hvor jeg har laver en Virtuel GND på 2,5V, så jeg kan få et fint analog signal som er offset omkring 2,5v for at gøre Analog indgangen glad på Arduinoen.

I softwaren bruger jeg så #include "arduinoFFT.h"

Først havde jeg tænkt at ville prøve at lave noget "Beat Detect" som kunne finde rytmen i music, efter at have søgt og læst en masse ser det ud til at være mere kompliceret end "bare lige"

Nu har jeg så lavet en mere simpel løsning hvor jeg tænder LED hvis der er over et bestemt niveau på en given frekvens.

Umiddelbar virker det så meget at det blinker til musik, desuden hvis jeg tilslutter en tone generator og sweeper fra f. eks 100Hz til 2Khz så tænder led også ca som forventet, men det virker ikke helt overbevisende.

Så jeg leder efter nogle ideer til at gøre det bedre.

Kode:
#define CHANNEL A0
const uint16_t samples = 128; //This value MUST ALWAYS be a power of 2
double samplingFrequency = 8000;
unsigned int delayTime = 0;
double vReal[samples];
double vImag[samples];

i setup
Kode:
  analogReference(DEFAULT);
   if(samplingFrequency<=1000)
    delayTime = 1000/samplingFrequency;
  else
    delayTime = 1000000/samplingFrequency;
  // nothing to do!
}

i loop kalder jeg Spectrum konstant
Kode:
/**********************************************/
// FFT!
void Spectrum() {

for(uint16_t i =0;i<samples;i++)
  {
   vReal[i]=0;
   vImag[i]=0;
  }
    for(uint16_t i =0;i<samples;i++)
  {
    vReal[i] = double(analogRead(CHANNEL));
    if(samplingFrequency<=1000)
      delay(delayTime);
    else
      delayMicroseconds(delayTime);
  }
  FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);  /* Weigh data */
  FFT.Compute(vReal, vImag, samples, FFT_FORWARD); /* Compute FFT */
  FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */
//  double one_freq = ((5 * 1.0 * samplingFrequency) / samples);v

//    double x = FFT.MajorPeak(vReal, samples, samplingFrequency);
//  Serial.println(x, 6);


       int bass0 = vReal[4]  > 300*2;
       int bass1 = vReal[8]  > 300*2;
       int bass2 = vReal[12]  > 300*2;
       int bass3 = vReal[16]  > 300*2;
       int bass4 = vReal[20]  > 300*2;
       int bass5 = vReal[24]  > 300*2;
       int bass6 = vReal[32]  > 300*2;
       int bass7 = vReal[48]  > 300*2;
       int bass8 = vReal[56]  > 300*2;
       int bass9 = vReal[64]  > 300*2;


 
  if (bass0) { strip.setLEDcolor(0, R);} else { strip.setLEDcolor(0, BLACK);}
  if (bass1) { strip.setLEDcolor(1, R);} else { strip.setLEDcolor(1, BLACK);}
  if (bass2) { strip.setLEDcolor(2, R);} else { strip.setLEDcolor(2, BLACK);}
  if (bass3) { strip.setLEDcolor(3, G);} else { strip.setLEDcolor(3, BLACK);}
  if (bass4) { strip.setLEDcolor(4, G);} else { strip.setLEDcolor(4, BLACK);}
  if (bass5) { strip.setLEDcolor(5, G);} else { strip.setLEDcolor(5, BLACK);}
  if (bass6) { strip.setLEDcolor(6, G);} else { strip.setLEDcolor(6, BLACK);}
  if (bass7) { strip.setLEDcolor(7, B);} else { strip.setLEDcolor(7, BLACK);}
  if (bass8) { strip.setLEDcolor(8, B);} else { strip.setLEDcolor(8, BLACK);}
  if (bass9) { strip.setLEDcolor(9, B);} else { strip.setLEDcolor(9, BLACK);}

strip.writeStrip(); 

}

Er dette den rigtige måde at bruge FFT på?

  FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);  /* Weigh data */
  FFT.Compute(vReal, vImag, samples, FFT_FORWARD); /* Compute FFT */
  FFT.ComplexToMagnitude(vReal, vImag, samples); /* Compute magnitudes */


Ideer modtages  :)