An floppy drive audio generator using dsp on live audio
Dependencies: Terminal asyncADC mbed-dsp mbed
main.cpp@1:02553973d9cf, 2017-05-24 (annotated)
- Committer:
- Condo2k4
- Date:
- Wed May 24 11:59:27 2017 +0000
- Revision:
- 1:02553973d9cf
- Parent:
- 0:84c336a81482
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Condo2k4 | 0:84c336a81482 | 1 | //#include "mbed.h" |
Condo2k4 | 0:84c336a81482 | 2 | //#include <algorithm> |
Condo2k4 | 0:84c336a81482 | 3 | //#include "asyncADC.h" |
Condo2k4 | 0:84c336a81482 | 4 | //#include "arm_math.h" |
Condo2k4 | 0:84c336a81482 | 5 | //#include "arm_common_tables.h" |
Condo2k4 | 0:84c336a81482 | 6 | //#include "moppy.h" |
Condo2k4 | 0:84c336a81482 | 7 | //#include "Terminal.h" |
Condo2k4 | 0:84c336a81482 | 8 | // |
Condo2k4 | 0:84c336a81482 | 9 | //#define AUDIO_PIN (A0) |
Condo2k4 | 0:84c336a81482 | 10 | // |
Condo2k4 | 0:84c336a81482 | 11 | //Terminal pc(USBTX, USBRX, 115200); |
Condo2k4 | 0:84c336a81482 | 12 | //DigitalOut process_led(LED3); // Blue |
Condo2k4 | 0:84c336a81482 | 13 | //Timer timer; |
Condo2k4 | 0:84c336a81482 | 14 | // |
Condo2k4 | 0:84c336a81482 | 15 | //#define FFT_SIZE 2048 |
Condo2k4 | 0:84c336a81482 | 16 | //#define SAMPLE_RATE_HZ 10000 // Sample rate in Hertz |
Condo2k4 | 0:84c336a81482 | 17 | //#include "fft.h" |
Condo2k4 | 0:84c336a81482 | 18 | // |
Condo2k4 | 0:84c336a81482 | 19 | //#define BIN_TO_FREQ(bin) ((bin*(long)SAMPLE_RATE_HZ)/FFT_SIZE) |
Condo2k4 | 0:84c336a81482 | 20 | // |
Condo2k4 | 0:84c336a81482 | 21 | // |
Condo2k4 | 0:84c336a81482 | 22 | //#define FREQ_ANALYSER_SCALAR (3) |
Condo2k4 | 0:84c336a81482 | 23 | //#define FREQ_ANALYSER_WIDTH (FFT_SIZE>>(FREQ_ANALYSER_SCALAR+1)) |
Condo2k4 | 0:84c336a81482 | 24 | //#define FREQ_ANALYSER_HEIGHT (10) |
Condo2k4 | 0:84c336a81482 | 25 | // |
Condo2k4 | 0:84c336a81482 | 26 | ////BUFFERS |
Condo2k4 | 0:84c336a81482 | 27 | // |
Condo2k4 | 0:84c336a81482 | 28 | //uint16_t adcBuffer[FFT_SIZE*2]; |
Condo2k4 | 0:84c336a81482 | 29 | //float fftBuffer[FFT_SIZE*2]; |
Condo2k4 | 0:84c336a81482 | 30 | //float magnitudes[FFT_SIZE]; |
Condo2k4 | 0:84c336a81482 | 31 | //char pcBuffer1[FREQ_ANALYSER_WIDTH+3]; |
Condo2k4 | 0:84c336a81482 | 32 | //char pcBuffer2[FREQ_ANALYSER_WIDTH+3]; |
Condo2k4 | 0:84c336a81482 | 33 | // |
Condo2k4 | 0:84c336a81482 | 34 | // |
Condo2k4 | 0:84c336a81482 | 35 | //// INTERRUPTS |
Condo2k4 | 0:84c336a81482 | 36 | // |
Condo2k4 | 0:84c336a81482 | 37 | //volatile int sectionCounter = 0; |
Condo2k4 | 0:84c336a81482 | 38 | //volatile bool sectionFilled = false; |
Condo2k4 | 0:84c336a81482 | 39 | //volatile uint32_t sectionStart, sectionEnd; |
Condo2k4 | 0:84c336a81482 | 40 | // |
Condo2k4 | 0:84c336a81482 | 41 | //void callback(uint32_t start, uint32_t end) { |
Condo2k4 | 0:84c336a81482 | 42 | // sectionFilled = true; |
Condo2k4 | 0:84c336a81482 | 43 | // sectionCounter++; |
Condo2k4 | 0:84c336a81482 | 44 | // sectionStart = start; |
Condo2k4 | 0:84c336a81482 | 45 | // sectionEnd = end; |
Condo2k4 | 0:84c336a81482 | 46 | //} |
Condo2k4 | 0:84c336a81482 | 47 | // |
Condo2k4 | 0:84c336a81482 | 48 | //// UTILS |
Condo2k4 | 0:84c336a81482 | 49 | // |
Condo2k4 | 0:84c336a81482 | 50 | //uint32_t ceilToPowerOf2(uint32_t i) { |
Condo2k4 | 0:84c336a81482 | 51 | // i--; |
Condo2k4 | 0:84c336a81482 | 52 | // i|=(i>>1); |
Condo2k4 | 0:84c336a81482 | 53 | // i|=(i>>2); |
Condo2k4 | 0:84c336a81482 | 54 | // i|=(i>>4); |
Condo2k4 | 0:84c336a81482 | 55 | // i|=(i>>8); |
Condo2k4 | 0:84c336a81482 | 56 | // i|=(i>>16); |
Condo2k4 | 0:84c336a81482 | 57 | // return i+1; |
Condo2k4 | 0:84c336a81482 | 58 | //} |
Condo2k4 | 0:84c336a81482 | 59 | // |
Condo2k4 | 0:84c336a81482 | 60 | //void trySwp(int16_t *indices, float *magnitudes, int a, int b) { |
Condo2k4 | 0:84c336a81482 | 61 | // if(magnitudes[indices[a]]>magnitudes[indices[b]]) { |
Condo2k4 | 0:84c336a81482 | 62 | // int x = indices[a]; |
Condo2k4 | 0:84c336a81482 | 63 | // indices[a] = indices[b]; |
Condo2k4 | 0:84c336a81482 | 64 | // indices[b] = x; |
Condo2k4 | 0:84c336a81482 | 65 | // } |
Condo2k4 | 0:84c336a81482 | 66 | //} |
Condo2k4 | 0:84c336a81482 | 67 | // |
Condo2k4 | 0:84c336a81482 | 68 | //void sort(int16_t *indices, float *magnitudes, int size) { |
Condo2k4 | 0:84c336a81482 | 69 | // indices[0] = 0; |
Condo2k4 | 0:84c336a81482 | 70 | // for(int i=1; i<size; i++) { |
Condo2k4 | 0:84c336a81482 | 71 | // indices[i]=i; |
Condo2k4 | 0:84c336a81482 | 72 | // for(int j=i; j-->0;) { |
Condo2k4 | 0:84c336a81482 | 73 | // trySwp(indices, magnitudes, j, j+1); |
Condo2k4 | 0:84c336a81482 | 74 | // } |
Condo2k4 | 0:84c336a81482 | 75 | // } |
Condo2k4 | 0:84c336a81482 | 76 | //} |
Condo2k4 | 0:84c336a81482 | 77 | // |
Condo2k4 | 0:84c336a81482 | 78 | //bool magComparator(int const & a, int const & b) { |
Condo2k4 | 0:84c336a81482 | 79 | // return magnitudes[a] > magnitudes[b]; |
Condo2k4 | 0:84c336a81482 | 80 | //} |
Condo2k4 | 0:84c336a81482 | 81 | // |
Condo2k4 | 0:84c336a81482 | 82 | //// MAIN |
Condo2k4 | 0:84c336a81482 | 83 | // |
Condo2k4 | 0:84c336a81482 | 84 | //int main() |
Condo2k4 | 0:84c336a81482 | 85 | //{ |
Condo2k4 | 0:84c336a81482 | 86 | // |
Condo2k4 | 0:84c336a81482 | 87 | // pcBuffer1[0] = '|'; |
Condo2k4 | 0:84c336a81482 | 88 | // pcBuffer1[FREQ_ANALYSER_WIDTH+1] = '|'; |
Condo2k4 | 0:84c336a81482 | 89 | // pcBuffer1[FREQ_ANALYSER_WIDTH+2] = 0; |
Condo2k4 | 0:84c336a81482 | 90 | // memset(pcBuffer2+1, '-', FREQ_ANALYSER_WIDTH); |
Condo2k4 | 0:84c336a81482 | 91 | // pcBuffer2[0] = '+'; |
Condo2k4 | 0:84c336a81482 | 92 | // pcBuffer2[FREQ_ANALYSER_WIDTH+1] = '+'; |
Condo2k4 | 0:84c336a81482 | 93 | // pcBuffer2[FREQ_ANALYSER_WIDTH+2] = 0; |
Condo2k4 | 0:84c336a81482 | 94 | // |
Condo2k4 | 0:84c336a81482 | 95 | // process_led = 1; |
Condo2k4 | 0:84c336a81482 | 96 | // |
Condo2k4 | 0:84c336a81482 | 97 | // pc.cls(); |
Condo2k4 | 0:84c336a81482 | 98 | // pc.cursor(false); |
Condo2k4 | 0:84c336a81482 | 99 | // pc.locate(0,0); |
Condo2k4 | 0:84c336a81482 | 100 | // pc.printf("Synchronising Floppy Drives\r\n"); |
Condo2k4 | 0:84c336a81482 | 101 | // |
Condo2k4 | 0:84c336a81482 | 102 | // Moppy moppy(D1, D0, 38400); // tx, rx, baud |
Condo2k4 | 0:84c336a81482 | 103 | // |
Condo2k4 | 0:84c336a81482 | 104 | // pc.printf("Setup Complete\r\n"); |
Condo2k4 | 0:84c336a81482 | 105 | // |
Condo2k4 | 0:84c336a81482 | 106 | // switch(asyncAnalogToCircularBuffer(AUDIO_PIN, adcBuffer, 2*FFT_SIZE, SAMPLE_RATE_HZ, callback)) { |
Condo2k4 | 0:84c336a81482 | 107 | // case E_ASYNC_ADC_ACTIVE: |
Condo2k4 | 0:84c336a81482 | 108 | // error("AsyncADC already in use"); |
Condo2k4 | 0:84c336a81482 | 109 | // case E_DMA_IN_USE: |
Condo2k4 | 0:84c336a81482 | 110 | // error("DMA already in use"); |
Condo2k4 | 0:84c336a81482 | 111 | // case E_INVALID_BUFFER_SIZE: |
Condo2k4 | 0:84c336a81482 | 112 | // error("Invalid destination buffer size"); |
Condo2k4 | 0:84c336a81482 | 113 | // } |
Condo2k4 | 0:84c336a81482 | 114 | // |
Condo2k4 | 0:84c336a81482 | 115 | // int16_t indices[FFT_SIZE*2]; |
Condo2k4 | 0:84c336a81482 | 116 | // |
Condo2k4 | 0:84c336a81482 | 117 | // timer.start(); |
Condo2k4 | 0:84c336a81482 | 118 | // |
Condo2k4 | 0:84c336a81482 | 119 | // pc.locate(0,16); |
Condo2k4 | 0:84c336a81482 | 120 | // pc.printf("%dHz", BIN_TO_FREQ(1)); |
Condo2k4 | 0:84c336a81482 | 121 | // pc.locate(FREQ_ANALYSER_WIDTH-20,16); |
Condo2k4 | 0:84c336a81482 | 122 | // pc.printf("%20dHz", BIN_TO_FREQ(FFT_SIZE/2)); |
Condo2k4 | 0:84c336a81482 | 123 | // |
Condo2k4 | 0:84c336a81482 | 124 | // while(1) { |
Condo2k4 | 0:84c336a81482 | 125 | // if(sectionFilled) { |
Condo2k4 | 0:84c336a81482 | 126 | // process_led = 0; |
Condo2k4 | 0:84c336a81482 | 127 | // |
Condo2k4 | 0:84c336a81482 | 128 | // timer.reset(); |
Condo2k4 | 0:84c336a81482 | 129 | // |
Condo2k4 | 0:84c336a81482 | 130 | // //convert to floating point |
Condo2k4 | 0:84c336a81482 | 131 | // for(int i=sectionStart, j=0; i<=sectionEnd; i++, j+=2) { |
Condo2k4 | 0:84c336a81482 | 132 | // fftBuffer[j] = (float)adcBuffer[i]; |
Condo2k4 | 0:84c336a81482 | 133 | // fftBuffer[j+1] = 0.0f; |
Condo2k4 | 0:84c336a81482 | 134 | // } |
Condo2k4 | 0:84c336a81482 | 135 | // |
Condo2k4 | 0:84c336a81482 | 136 | // // Calculate FFT if a full sample is available. |
Condo2k4 | 0:84c336a81482 | 137 | // // Run FFT on sample data. |
Condo2k4 | 0:84c336a81482 | 138 | // arm_cfft_f32(FFT_BUFFER, fftBuffer, 0, 1); |
Condo2k4 | 0:84c336a81482 | 139 | // // Calculate magnitude of complex numbers output by the FFT. |
Condo2k4 | 0:84c336a81482 | 140 | // arm_cmplx_mag_f32(fftBuffer, magnitudes, FFT_SIZE); |
Condo2k4 | 0:84c336a81482 | 141 | // |
Condo2k4 | 0:84c336a81482 | 142 | // for(int i=1; i<FFT_SIZE; i++) |
Condo2k4 | 0:84c336a81482 | 143 | // indices[i]=i; |
Condo2k4 | 0:84c336a81482 | 144 | // std::sort(indices + 1, indices + (FFT_SIZE/2), magComparator); |
Condo2k4 | 0:84c336a81482 | 145 | // |
Condo2k4 | 0:84c336a81482 | 146 | // //REMEMBER: Ignore Indicies[0]!!!! |
Condo2k4 | 0:84c336a81482 | 147 | // moppy.setFrequency(0, BIN_TO_FREQ(indices[1])); |
Condo2k4 | 0:84c336a81482 | 148 | // moppy.setFrequency(1, BIN_TO_FREQ(indices[2])); |
Condo2k4 | 0:84c336a81482 | 149 | // moppy.setFrequency(2, BIN_TO_FREQ(indices[3])); |
Condo2k4 | 0:84c336a81482 | 150 | // moppy.setFrequency(3, BIN_TO_FREQ(indices[4])); |
Condo2k4 | 0:84c336a81482 | 151 | // moppy.flush(); |
Condo2k4 | 0:84c336a81482 | 152 | // |
Condo2k4 | 0:84c336a81482 | 153 | // pc.locate(0, 4); |
Condo2k4 | 0:84c336a81482 | 154 | // pc.puts(pcBuffer2); |
Condo2k4 | 0:84c336a81482 | 155 | // memset(pcBuffer1+1, ' ', FREQ_ANALYSER_WIDTH); |
Condo2k4 | 0:84c336a81482 | 156 | // float max = magnitudes[indices[1]]; |
Condo2k4 | 0:84c336a81482 | 157 | // if(max<1000000) max = 1000000; |
Condo2k4 | 0:84c336a81482 | 158 | // for(int i=2; i<FFT_SIZE/2; i++) { |
Condo2k4 | 0:84c336a81482 | 159 | // int j = (i>>FREQ_ANALYSER_SCALAR)+1; |
Condo2k4 | 0:84c336a81482 | 160 | // if(magnitudes[i] > magnitudes[j]) |
Condo2k4 | 0:84c336a81482 | 161 | // magnitudes[j] = magnitudes[i]; |
Condo2k4 | 0:84c336a81482 | 162 | // } |
Condo2k4 | 0:84c336a81482 | 163 | // for(int y=0; y<FREQ_ANALYSER_HEIGHT; y++) { |
Condo2k4 | 0:84c336a81482 | 164 | // float thresh = max*(FREQ_ANALYSER_HEIGHT-y)/(FREQ_ANALYSER_HEIGHT+1.0f);//((FREQ_ANALYSER_HEIGHT-1)-y)*max/(FREQ_ANALYSER_HEIGHT+1); |
Condo2k4 | 0:84c336a81482 | 165 | // for(int x=1; x<=FREQ_ANALYSER_WIDTH; x++) |
Condo2k4 | 0:84c336a81482 | 166 | // if(pcBuffer1[x]!='#' && magnitudes[x]>thresh) |
Condo2k4 | 0:84c336a81482 | 167 | // pcBuffer1[x]='#'; |
Condo2k4 | 0:84c336a81482 | 168 | // pc.locate(0, y+5); |
Condo2k4 | 0:84c336a81482 | 169 | // pc.puts(pcBuffer1); |
Condo2k4 | 0:84c336a81482 | 170 | // } |
Condo2k4 | 0:84c336a81482 | 171 | // pc.locate(0, FREQ_ANALYSER_HEIGHT+5); |
Condo2k4 | 0:84c336a81482 | 172 | // pc.puts(pcBuffer2); |
Condo2k4 | 0:84c336a81482 | 173 | // |
Condo2k4 | 0:84c336a81482 | 174 | // |
Condo2k4 | 0:84c336a81482 | 175 | // long process_time = timer.read_us(); |
Condo2k4 | 0:84c336a81482 | 176 | // |
Condo2k4 | 0:84c336a81482 | 177 | // |
Condo2k4 | 0:84c336a81482 | 178 | // long x = (process_time)/(100*FFT_SIZE/SAMPLE_RATE_HZ); |
Condo2k4 | 0:84c336a81482 | 179 | // |
Condo2k4 | 0:84c336a81482 | 180 | // pc.locate(0,2); |
Condo2k4 | 0:84c336a81482 | 181 | // pc.printf("Process Time:%3d.%02dms ~%d.%02d%%", process_time/1000, ((process_time+5)/10)%100, x/100, x%100); |
Condo2k4 | 0:84c336a81482 | 182 | //// pc.printf("\r\n%f", magnitudes[indices[1]]); |
Condo2k4 | 0:84c336a81482 | 183 | // |
Condo2k4 | 0:84c336a81482 | 184 | // process_led = 1; |
Condo2k4 | 0:84c336a81482 | 185 | // |
Condo2k4 | 0:84c336a81482 | 186 | // sectionFilled = false; |
Condo2k4 | 0:84c336a81482 | 187 | // } |
Condo2k4 | 0:84c336a81482 | 188 | // sleep(); |
Condo2k4 | 0:84c336a81482 | 189 | // } |
Condo2k4 | 0:84c336a81482 | 190 | //} |