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
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
Generated on Fri Jul 15 2022 10:39:29 by 1.7.2