Simplified version of FFT code - drives on-board LED as a "Colour Organ".
Dependencies: FastAnalogIn NVIC_set_all_priorities mbed-dsp mbed
Fork of KL25Z_FFT_Demo_tony by
Diff: main.cpp
- Revision:
- 1:7421267b0777
- Parent:
- 0:b8c9dffbbe7e
- Child:
- 2:177596541c8d
--- a/main.cpp Tue Jun 17 14:03:36 2014 +0000 +++ b/main.cpp Tue Nov 15 22:16:24 2016 +0000 @@ -9,10 +9,11 @@ #include "arm_math.h" #include "arm_const_structs.h" #include "FastAnalogIn.h" +#include <string> +FastAnalogIn Audio(PTC2); Serial pc(USBTX, USBRX); -FastAnalogIn Audio(PTC2); //#define RGBW_ext // Disable this line when you want to use the KL25Z on-board RGB LED. @@ -44,20 +45,12 @@ // Max allowed SAMPLE_RATE_HZ is 40000 // Max allowed FFT_SIZE is 64 //////////////////////////////////////////////////////////////////////////////// - -int SLOWDOWN = 4; // Create an optical delay in spectrumLoop - useful when only one RGB led is used. - // Only active when nonzero. // A value >= 1000 and <= 1000 + PIXEL_COUNT fixes the output to a single frequency // window = a single color. -int SAMPLE_RATE_HZ = 20000; // Sample rate of the audio in hertz. -float SPECTRUM_MIN_DB = 20.0; // Audio intensity (in decibels) that maps to low LED brightness. -float SPECTRUM_MAX_DB = 80.0; // Audio intensity (in decibels) that maps to high LED brightness. -int LEDS_ENABLED = 1; // Control if the LED's should display the spectrum or not. 1 is true, 0 is false. +int SAMPLE_RATE_HZ = 1000; // Sample rate of the audio in hertz. + // Useful for turning the LED display on and off with commands from the serial port. -const int FFT_SIZE = 64; // Size of the FFT. -const int PIXEL_COUNT = 3; // Number of pixels (RGB LED). You should be able to increase this without - // any other changes to the program. -const int MAX_CHARS = 65; // Max size of the input command buffer +const int FFT_SIZE = 256; // Size of the FFT. //////////////////////////////////////////////////////////////////////////////// // INTERNAL STATE @@ -68,43 +61,11 @@ float samples[FFT_SIZE*2]; float magnitudes[FFT_SIZE]; int sampleCounter = 0; -char commandBuffer[MAX_CHARS]; -float frequencyWindow[PIXEL_COUNT+1]; -float hues[PIXEL_COUNT]; -bool commandRecv = 0; -//////////////////////////////////////////////////////////////////////////////// -// UTILITY FUNCTIONS -//////////////////////////////////////////////////////////////////////////////// -void rxisr() { - char c = pc.getc(); - // Add any characters that aren't the end of a command (semicolon) to the input buffer. - if (c != ';') { - c = toupper(c); - strncat(commandBuffer, &c, 1); - } else { - // Parse the command because an end of command token was encountered. - commandRecv = 1; - } -} +int arrayPosition; +int maxFrequencyValue; -// Compute the average magnitude of a target frequency window vs. all other frequencies. -void windowMean(float* magnitudes, int lowBin, int highBin, float* windowMean, float* otherMean) -{ - *windowMean = 0; - *otherMean = 0; - // Notice the first magnitude bin is skipped because it represents the - // average power of the signal. - for (int i = 1; i < FFT_SIZE/2; ++i) { - if (i >= lowBin && i <= highBin) { - *windowMean += magnitudes[i]; - } else { - *otherMean += magnitudes[i]; - } - } - *windowMean /= (highBin - lowBin) + 1; - *otherMean /= (FFT_SIZE / 2 - (highBin - lowBin)); -} +int FFTFrequency; // Convert a frequency to the appropriate FFT bin it will fall within. int frequencyToBin(float frequency) @@ -114,78 +75,6 @@ } -//////////////////////////////////////////////////////////////////////////////// -// SPECTRUM DISPLAY FUNCTIONS -/////////////////////////////////////////////////////////////////////////////// - -void spectrumSetup() -{ - // Set the frequency window values by evenly dividing the possible frequency - // spectrum across the number of neo pixels. - float windowSize = (SAMPLE_RATE_HZ / 2.0) / float(PIXEL_COUNT); - for (int i = 0; i < PIXEL_COUNT+1; ++i) { - frequencyWindow[i] = i*windowSize; - } - -} - -void spectrumLoop() -{ - // Update each LED based on the intensity of the audio - // in the associated frequency window. - static int SLrpt = 0, SLpixcnt = 0; - int SLpixend = 0; - float intensity, otherMean; - if(SLOWDOWN != 0) - { - if(SLOWDOWN >= 1000) - { - if(SLOWDOWN <= (1000 + PIXEL_COUNT-1)) - { - SLpixcnt = SLOWDOWN - 1000; - SLrpt = 0; - SLpixend = SLpixcnt + 1; - } - else - SLOWDOWN = 0; - } - else - { - SLrpt++; - if (SLrpt >= SLOWDOWN) - { - SLrpt = 0; - SLpixcnt = SLpixcnt < PIXEL_COUNT-1 ? ++SLpixcnt : 0; - } - SLpixend = SLpixcnt + 1; - } - } - else - { - SLpixcnt = 0; - SLrpt = 0; - SLpixend = PIXEL_COUNT; - } - for (int i = SLpixcnt; i < SLpixend; ++i) { - windowMean(magnitudes, - frequencyToBin(frequencyWindow[i]), - frequencyToBin(frequencyWindow[i+1]), - &intensity, - &otherMean); - // Convert intensity to decibels. - intensity = 20.0*log10(intensity); - // Scale the intensity and clamp between 0 and 1.0. - intensity -= SPECTRUM_MIN_DB; - intensity = intensity < 0.0 ? 0.0 : intensity; - intensity /= (SPECTRUM_MAX_DB-SPECTRUM_MIN_DB); - intensity = intensity > 1.0 ? 1.0 : intensity; - hues[i]=intensity; - } - rled=1.0-hues[0] ; // onboard LED is common anode so inversion needed - gled=1.0-hues[1]; - bled=1.0-hues[2]; -} - //////////////////////////////////////////////////////////////////////////////// // SAMPLING FUNCTIONS @@ -217,90 +106,33 @@ return sampleCounter >= FFT_SIZE*2; } - //////////////////////////////////////////////////////////////////////////////// -// COMMAND PARSING FUNCTIONS -// These functions allow parsing simple commands input on the serial port. -// Commands allow reading and writing variables that control the device. -// -// All commands must end with a semicolon character. -// -// Example commands are: -// GET SAMPLE_RATE_HZ; -// - Get the sample rate of the device. -// SET SAMPLE_RATE_HZ 400; -// - Set the sample rate of the device to 400 hertz. -// +// FREQUENCY //////////////////////////////////////////////////////////////////////////////// -void parseCommand(char* command) + +void set_ArrayPosition() { - if (strcmp(command, "GET MAGNITUDES") == 0) { - for (int i = 0; i < FFT_SIZE; ++i) { - printf("%f\r\n", magnitudes[i]); - } - } else if (strcmp(command, "GET SAMPLES") == 0) { - for (int i = 0; i < FFT_SIZE*2; i+=2) { - printf("%f\r\n", samples[i]); - } - } else if (strcmp(command, "GET FFT_SIZE") == 0) { - printf("%d\r\n", FFT_SIZE); - } else if (strcmp(command, "GET SAMPLE_RATE_HZ") == 0) { - printf("%d\r\n", SAMPLE_RATE_HZ); - } else if (strstr(command, "SET SAMPLE_RATE_HZ") != NULL) { - SAMPLE_RATE_HZ = (typeof(SAMPLE_RATE_HZ)) atof(command+(sizeof("SET SAMPLE_RATE_HZ")-1)); - } else if (strcmp(command, "GET LEDS_ENABLED") == 0) { - printf("%d\r\n", LEDS_ENABLED); - } else if (strstr(command, "SET LEDS_ENABLED") != NULL) { - LEDS_ENABLED = (typeof(LEDS_ENABLED)) atof(command+(sizeof("SET LEDS_ENABLED")-1)); - } else if (strcmp(command, "GET SPECTRUM_MIN_DB") == 0) { - printf("%f\r\n", SPECTRUM_MIN_DB); - } else if (strstr(command, "SET SPECTRUM_MIN_DB") != NULL) { - SPECTRUM_MIN_DB = (typeof(SPECTRUM_MIN_DB)) atof(command+(sizeof("SET SPECTRUM_MIN_DB")-1)); - } else if (strcmp(command, "GET SPECTRUM_MAX_DB") == 0) { - printf("%f\r\n", SPECTRUM_MAX_DB); - } else if (strstr(command, "SET SPECTRUM_MAX_DB") != NULL) { - SPECTRUM_MAX_DB = (typeof(SPECTRUM_MAX_DB)) atof(command+(sizeof("SET SPECTRUM_MAX_DB")-1)); - } else if (strcmp(command, "GET SLOWDOWN") == 0) { - printf("%d\r\n", SLOWDOWN); - } else if (strstr(command, "SET SLOWDOWN") != NULL) { - SLOWDOWN = (typeof(SLOWDOWN)) atoi(command+(sizeof("SET SLOWDOWN")-1)); - } - - // Update spectrum display values if sample rate was changed. - if (strstr(command, "SET SAMPLE_RATE_HZ ") != NULL) { - spectrumSetup(); - } else if (strcmp(command, "GET HUES") == 0) { - for (int i = 0; i < PIXEL_COUNT; ++i) { - printf("%f\r\n", hues[i]); - } - } + float maxValue = 0.0; - - // Turn off the LEDs if the state changed. - if (LEDS_ENABLED == 0) { - } -} - -void parserLoop() -{ - // Process any incoming characters from the serial port - while (pc.readable()) { - char c = pc.getc(); - // (doesnt work!) printf("%c",c); // echo characters typed - // Add any characters that aren't the end of a command (semicolon) to the input buffer. - if (c != ';') { - c = toupper(c); - strncat(commandBuffer, &c, 1); - } else { - // Parse the command because an end of command token was encountered. - parseCommand(commandBuffer); - // Clear the input buffer - memset(commandBuffer, 0, sizeof(commandBuffer)); + for(int counter=0; counter < FFT_SIZE; counter++) + { + if(magnitudes[counter] > maxValue){ + maxValue = magnitudes[counter]; + arrayPosition = counter+1; } } } +int get_FFTFrequency() +{ + maxFrequencyValue = SAMPLE_RATE_HZ/2; + + set_ArrayPosition(); + + return (maxFrequencyValue*arrayPosition)/FFT_SIZE; + +} //////////////////////////////////////////////////////////////////////////////// // MAIN FUNCTION //////////////////////////////////////////////////////////////////////////////// @@ -309,15 +141,6 @@ { NVIC_set_all_irq_priorities(1); NVIC_SetPriority(UART0_IRQn, 0); - // Set up serial port. - pc.baud (38400); - pc.attach(&rxisr); - - // Clear the input command buffer - memset(commandBuffer, 0, sizeof(commandBuffer)); - - // Initialize spectrum display - spectrumSetup(); // Begin sampling audio samplingBegin(); @@ -354,31 +177,23 @@ break; } - while(1) { + while(true) { // Calculate FFT if a full sample is available. if (samplingIsDone()) { // Run FFT on sample data. arm_cfft_f32(S, samples, 0, 1); // Calculate magnitude of complex numbers output by the FFT. arm_cmplx_mag_f32(samples, magnitudes, FFT_SIZE); - - if (LEDS_ENABLED == 1) { - spectrumLoop(); - } - + //Obtaining the value of the frequency + FFTFrequency = get_FFTFrequency(); + + for(int i=0; + pc.printf("Frequency is: ", FFTFrequency); + pc.printf("\r\n ["); + // Restart audio sampling. samplingBegin(); - printf("this will make it work "); - } - - // Parse any pending commands. - if(commandRecv) { -// pc.attach(NULL); - parseCommand(commandBuffer); - commandRecv = 0; - // Clear the input buffer - memset(commandBuffer, 0, sizeof(commandBuffer)); -// pc.attach(&rxisr); - } + } } + }