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
main.cpp
- Committer:
- jcobb
- Date:
- 2010-03-21
- Revision:
- 0:5b7b619f59cd
File content as of revision 0:5b7b619f59cd:
#define SAMPLE_RATE 48000 #include "mbed.h" #include "adc.h" //Going to use the Mellen FFT rather than STM, as the STM (port by Igor) won't compile //extern "C" void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin); extern "C" void fftR4(short *y, short *x, int N); //use the LED as a bargraph DigitalOut l1(LED1); DigitalOut l2(LED2); DigitalOut l3(LED3); DigitalOut l4(LED4); //set up a timer for timing FFT's Timer timer; //Set up filesystem so we can write some useful files LocalFileSystem local("local"); FILE *fp; //Set up a global buffer for audio data so interrupt can access it int Counter = 0; int16_t Buffer[5000]; //Initialise ADC to maximum SAMPLE_RATE and cclk divide set to 1 ADC adc(SAMPLE_RATE, 1); //Functions to write 16 bit audio data and 32 bit headers to files in au format (cf sndRecorder Cookbook) void fwrite16(uint16_t v) { uint8_t *b = (uint8_t *)&v; fprintf(fp,"%c%c", b[1], b[0]); } void fwrite32(uint32_t v) { uint8_t *b = (uint8_t *)&v; fprintf(fp,"%c%c%c%c", b[3], b[2], b[1], b[0]); } //Our interrupt handler for audio sampling void sample_ADC(int chan, uint32_t value) { float s; s = adc.read(p20); int16_t b = (s -2048)*16; Buffer[Counter] = b; Counter += 1; /* bar graph */ int g = abs(s-2048); l1 = g > 0.1f*2048; l2 = g > 0.3f*2048; l3 = g > 0.6f*2048; l4 = g > 0.8f*2048; } int main() { //Prepare for burst mode on all ADC pins and set up interrupt handler (using ADC library from Simon Blandford adc.append(sample_ADC); adc.startmode(0,0); adc.burst(1); adc.setup(p20,1); //introduce a delay as initial waveform has bias whilst decoupling cap charges wait(1); //start the interrupt and wait for about 4096 samples adc.interrupt_state(p20,1); wait(0.1); //Finsh up - Unset pin 20 adc.interrupt_state(p20,0); adc.setup(p20,0); int actual_rate = adc.actual_sample_rate(); //for debugging tell the terminal sample rate and how many samples we took printf("Requested max sample rate is %u, actual max sample rate is %u.\n", SAMPLE_RATE, actual_rate); printf("We did %i samples\n",Counter); //write original audio file to filesytem so we can load on PC and see what's there (cf sndRecorder Cookbook) fp = fopen("/local/out.au", "w"); fprintf(fp,".snd"); fwrite32(24); fwrite32(-1); fwrite32(3); fwrite32(48000); fwrite32(1); int writeCount = 0; while(writeCount <=Counter) { fwrite16(Buffer[writeCount]); writeCount+=1; } //Not using the STM FFT, but leave code here for the moment /* //now do a fft of the initial 1024 samples #define N 256 //Number of points uint32_t x[N], y[N]; // input and output arrays int16_t real[N], imag[N]; // real and imaginary arrays memset(real, 0, sizeof(real)); memset(imag, 0, sizeof(imag)); // real[1]=SHRT_MAX; // Fill the input array for (int i=0; i<N; i++) { x[i] = (((uint16_t)(Buffer[i])) | ((uint32_t)(0<<16))); } timer.reset(); timer.start(); cr4_fft_256_stm32(y, x, N); //computes the FFT of the x[N] samples printf("ST32 fft up took %i\n",timer.read_us()); FILE* log = fopen("/local/stm32.txt","w"); for (int i=0; i<N; i++) { fprintf(log, "%d: %d, %d -> %d, %d\n", i, Buffer[i], 0 , int16_t(y[i] & 0xFFFF), int16_t(y[i] >> 16)); } fclose(log); //compute frequencies and magnitudes of result FILE* spectrum = fopen("/local/stm32Spec.txt","w"); for (int i=0; i<N/2; i++) { float real = int16_t(y[i] & 0xFFFF)* int16_t(y[i] & 0xFFFF); float imag = int16_t(y[i] >> 16)* int16_t(y[i] >> 16); fprintf(spectrum, "%d -> %f\n", int(SAMPLE_RATE/N*i),sqrt(imag+real)); } fclose(spectrum); */ //now lets try mellen fft timer.reset(); timer.start(); #define MN 1024 /*Number of points*/ short mx[MN*2]; // input data 16 bit, 4 byte aligned x0r,x0i,x1r,x1i,.... short my[MN*2]; // output data 16 bit,4 byte aligned y0r,y0i,y1r,y1i,.... for (int i=0;i<MN*2;i++) mx[i]=0; for (int i=0;i<MN;i=i+1) { mx[i*2]=Buffer[i];} printf("Mellen set up took %i\n",timer.read_us()); //call functions timer.reset(); timer.start(); fftR4(my, mx, MN); printf("Mellen fft took %i\n",timer.read_us()); FILE* mlog = fopen("/local/mellen.csv","w"); //now write a CSV file to filesytem of frequency vs amplitude for (int i=0; i<MN; i=i+2) { // fprintf(mlog, "%d: %d -> %d\n", i, mx[i], my[i]); fprintf(mlog, "%d,%f\n", int(actual_rate/MN/2*i),sqrt(float( (my[i]*my[i]) +(my[i+1]*my[i+1]) ) ) ); } fclose(mlog); }