Read an audio signal from the ADC, write it out to a file on the filestytem and perform a 1024 point FFT, writing frequency data to a csv file

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 
00002 #define SAMPLE_RATE   48000
00003 
00004 #include "mbed.h"
00005 #include "adc.h"
00006 
00007 //Going to use the Mellen FFT rather than STM, as the STM (port by Igor) won't compile
00008 //extern "C" void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);
00009 extern "C" void fftR4(short *y, short *x, int N);
00010 
00011 //use the LED as a bargraph
00012 DigitalOut l1(LED1);
00013 DigitalOut l2(LED2);
00014 DigitalOut l3(LED3);
00015 DigitalOut l4(LED4);
00016 
00017 //set up a timer for timing FFT's
00018 Timer timer;
00019 
00020 //Set up filesystem so we can write some useful files
00021 
00022 LocalFileSystem local("local");              
00023 FILE *fp;
00024 
00025 //Set up a global buffer for audio data so interrupt can access it
00026 int Counter = 0;
00027 int16_t Buffer[5000];
00028 
00029 //Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1
00030 ADC adc(SAMPLE_RATE, 1);
00031 
00032 //Functions to write 16 bit audio data and 32 bit headers to files in au format (cf sndRecorder Cookbook)
00033 void fwrite16(uint16_t v)
00034 {
00035     uint8_t *b = (uint8_t *)&v;
00036     
00037     fprintf(fp,"%c%c", b[1], b[0]);
00038 }
00039 void fwrite32(uint32_t v)
00040 {
00041     uint8_t *b = (uint8_t *)&v;
00042     
00043     fprintf(fp,"%c%c%c%c", b[3], b[2], b[1], b[0]);
00044 }
00045 
00046 //Our interrupt handler for audio sampling
00047 void sample_ADC(int chan, uint32_t value) {
00048     
00049    float s;
00050    s = adc.read(p20); 
00051    int16_t b = (s -2048)*16;
00052    Buffer[Counter] = b;
00053    Counter += 1;
00054     /* bar graph */
00055     int g = abs(s-2048);
00056     l1 = g > 0.1f*2048;
00057     l2 = g > 0.3f*2048;
00058     l3 = g > 0.6f*2048;
00059     l4 = g > 0.8f*2048;
00060 }
00061 
00062 int main() {
00063 
00064     //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford
00065     adc.append(sample_ADC);
00066     adc.startmode(0,0);
00067     adc.burst(1);
00068     adc.setup(p20,1);
00069     
00070     //introduce a delay as initial waveform has bias whilst decoupling cap charges
00071     wait(1);
00072     
00073     //start the interrupt and wait for about 4096 samples
00074     adc.interrupt_state(p20,1);
00075     wait(0.1);
00076     
00077         //Finsh up - Unset pin 20
00078         adc.interrupt_state(p20,0);
00079         adc.setup(p20,0);
00080         int actual_rate = adc.actual_sample_rate();
00081         
00082         //for debugging tell the terminal sample rate and how many samples we took
00083         printf("Requested max sample rate is %u, actual max sample rate is %u.\n",
00084         SAMPLE_RATE, actual_rate);
00085         printf("We did %i samples\n",Counter);
00086         
00087         //write original audio file to filesytem  so we can load on PC and see what's there (cf sndRecorder Cookbook)
00088         fp = fopen("/local/out.au", "w");
00089         fprintf(fp,".snd");
00090         fwrite32(24);
00091         fwrite32(-1);    
00092         fwrite32(3);     
00093         fwrite32(48000);      
00094         fwrite32(1);     
00095         int writeCount = 0;
00096         while(writeCount <=Counter) {
00097         fwrite16(Buffer[writeCount]);
00098         writeCount+=1;
00099         }
00100         
00101         //Not using the STM FFT, but leave code here for the moment
00102         
00103         /*
00104         //now do a fft of the initial 1024 samples
00105         #define N 256 //Number of points
00106         uint32_t x[N], y[N]; // input and output arrays 
00107         int16_t real[N], imag[N]; // real and imaginary arrays 
00108         memset(real, 0, sizeof(real));
00109         memset(imag, 0, sizeof(imag));
00110        // real[1]=SHRT_MAX;
00111         // Fill the input array 
00112         for (int i=0; i<N; i++)
00113         {
00114             x[i] = (((uint16_t)(Buffer[i])) | ((uint32_t)(0<<16)));
00115         }
00116         timer.reset();
00117         timer.start();
00118         cr4_fft_256_stm32(y, x, N); //computes the FFT of the x[N] samples
00119         printf("ST32 fft up took %i\n",timer.read_us());
00120         FILE* log = fopen("/local/stm32.txt","w");
00121         for (int i=0; i<N; i++)
00122         {
00123             fprintf(log, "%d: %d, %d -> %d, %d\n", i, Buffer[i], 0 , int16_t(y[i] & 0xFFFF), int16_t(y[i] >> 16));
00124         }
00125         fclose(log);    
00126         
00127         //compute frequencies and magnitudes of result
00128         FILE* spectrum = fopen("/local/stm32Spec.txt","w");
00129         for (int i=0; i<N/2; i++)
00130         {
00131             float real =  int16_t(y[i] & 0xFFFF)* int16_t(y[i] & 0xFFFF);
00132             float imag =  int16_t(y[i] >> 16)* int16_t(y[i] >> 16);
00133             fprintf(spectrum, "%d -> %f\n", int(SAMPLE_RATE/N*i),sqrt(imag+real));
00134         }
00135         fclose(spectrum); 
00136         */
00137 
00138         //now lets try mellen fft
00139         timer.reset();
00140         timer.start();
00141         #define MN 1024 /*Number of points*/
00142         short mx[MN*2]; // input data 16 bit, 4 byte aligned  x0r,x0i,x1r,x1i,....
00143         short my[MN*2]; // output data 16 bit,4 byte aligned  y0r,y0i,y1r,y1i,....
00144         for (int i=0;i<MN*2;i++) mx[i]=0;
00145         for (int i=0;i<MN;i=i+1)
00146             { mx[i*2]=Buffer[i];}
00147         printf("Mellen set up took %i\n",timer.read_us());
00148         //call functions
00149         timer.reset();
00150         timer.start();
00151         fftR4(my, mx, MN);
00152         printf("Mellen fft took %i\n",timer.read_us());
00153         FILE* mlog = fopen("/local/mellen.csv","w");
00154         
00155         //now write a CSV file to filesytem of frequency vs amplitude
00156         for (int i=0; i<MN; i=i+2)
00157         {
00158           //  fprintf(mlog, "%d: %d -> %d\n", i, mx[i], my[i]);
00159             fprintf(mlog, "%d,%f\n", int(actual_rate/MN/2*i),sqrt(float(   (my[i]*my[i])  +(my[i+1]*my[i+1])     ) )   );
00160         }
00161         fclose(mlog);    
00162   
00163         
00164 }
00165         
00166       
00167       
00168             
00169