Dan Allegre / 401_reverb

Dependencies:   mbed

Committer:
dallegre
Date:
Mon Oct 08 16:11:21 2018 +0000
Revision:
9:f42863126573
Parent:
8:ef4dca8695d1
Publishing.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dallegre 0:c12e968e5b60 1 //delay dsp for stm32f401re nucleo board with openmusiclabs audio codec shield. Need to jumpter the i2c pins from the
dallegre 0:c12e968e5b60 2 //top right arduino headers on the nucleo board to the bottom left 2 pins on the codec shield. Bottom left i2c pins are
dallegre 0:c12e968e5b60 3 //not mbed enabled on the nucleo boards.
dallegre 0:c12e968e5b60 4 //Also need to install a 11.2896MHz crystal on nucleo board and connect the appropriate jumpers as explained in the nucleo
dallegre 0:c12e968e5b60 5 //user manual. Two 20pf capacitors are used with the crystal. The series resistors going from the crystal to the stm32 chip
dallegre 0:c12e968e5b60 6 //are just shorts.
dallegre 0:c12e968e5b60 7 //Preceed audio path with a 1/47 voltage divider and follow with a 47X inverting op amp to bring up to eurorack levels. Use DC
dallegre 0:c12e968e5b60 8 //blocking cap after the op amp.
dallegre 0:c12e968e5b60 9 //Note that this is setup for the left input only and drives both outputs. It is easy to modify the code for stereo effects
dallegre 0:c12e968e5b60 10 //and both inputs.
dallegre 0:c12e968e5b60 11
dallegre 0:c12e968e5b60 12 //June 2015..
dallegre 0:c12e968e5b60 13 //Added interpolation so it acts more like a bbd or tape delay. It is easy to switch between cosine and linear interpolation.
dallegre 0:c12e968e5b60 14 //Cubic interpolation might be a possibility if I can figure out how it works.
dallegre 0:c12e968e5b60 15 //Added a nice lowpass filter class. Might want to put the delay in a class like this for reverb work. Need to make an oscillator next.
dallegre 0:c12e968e5b60 16
dallegre 7:c84086dce9ac 17 #define DELAYLEN 2900 //24,000 is about as far as you can go in the ram.
dallegre 8:ef4dca8695d1 18 #define SAMPLINGFREQ 22 //roughly the smapling frequency in KHz. options are 22,29,44,88 for 22khz,29khz,etc..
dallegre 0:c12e968e5b60 19
dallegre 0:c12e968e5b60 20 #include "mbed.h"
dallegre 1:a4ce08417c60 21 #include "dsp.h"
dallegre 1:a4ce08417c60 22 #include "allpass.h"
dallegre 0:c12e968e5b60 23 #include "codec.h"
dallegre 2:1b50325e256f 24 #include "osc.h"
dallegre 0:c12e968e5b60 25
dallegre 0:c12e968e5b60 26 SPI spi(SPI_MOSI,SPI_MISO,SPI_SCK);
dallegre 0:c12e968e5b60 27 Ticker timer;
dallegre 0:c12e968e5b60 28 Ticker timer2;
dallegre 0:c12e968e5b60 29 AnalogIn analog_value(A1); //delay time pot
dallegre 0:c12e968e5b60 30 AnalogIn analog_value2(A0); //feedback amount pot
dallegre 0:c12e968e5b60 31 DigitalOut cs(D10);
dallegre 0:c12e968e5b60 32
dallegre 0:c12e968e5b60 33 int left_out = 0, right_out = 0, left_out_u = 0, right_out_u = 0, left_in = 0, right_in = 0,
dallegre 0:c12e968e5b60 34 index1 = 0, index2 = (DELAYLEN*0.99), index3 = (DELAYLEN*0.99);
dallegre 0:c12e968e5b60 35 uint16_t left_in_u = 0, meas = 0, measprev = 0;
dallegre 0:c12e968e5b60 36 float left_in_f = 0, feedback = 0, feedback2 = 0, feedback3 = 0, offset = 10.0,
dallegre 7:c84086dce9ac 37 meas2f = 0.5, damping = 0, damping2 = 0, damping3 = 0, modL = 0, modL2 = 0, modL3 = 0, modL4, modR = 0, modR2 = 0, modR3 = 0, modR4,
dallegre 8:ef4dca8695d1 38 modLos = 0, modL2os = 0, modL3os = 0, modL4os = 0, modRos = 0, modR2os = 0, modR3os = 0, modR4os = 0,
dallegre 8:ef4dca8695d1 39 upperLim, lowerLim,
dallegre 3:f8bc3ac22ffd 40 left_out_f = 0, right_out_f = 0;
dallegre 7:c84086dce9ac 41 float left_out_2 = 0, right_out_2 = 0, left_out_3 = 0, right_out_3 = 0, left_out_4 = 0, right_out_4 = 0, loopfb = 0, loopfb2 = 0;
dallegre 0:c12e968e5b60 42 float audioFeedbackRight,audioFeedbackLeft;
dallegre 0:c12e968e5b60 43
dallegre 0:c12e968e5b60 44 float LPdampingFreq = 11000, HPdampingFreq = 100; //some parameters you might want to adjust.
dallegre 0:c12e968e5b60 45 int LPdampingPoles = 2, HPdampingPoles = 0; //I don't think the highpass is quite working.
dallegre 0:c12e968e5b60 46
dallegre 0:c12e968e5b60 47 OnePoleLp feedbackFilter;
dallegre 0:c12e968e5b60 48 OnePoleLp lengthFilter;
dallegre 7:c84086dce9ac 49 OnePoleLp dampingFilter;
dallegre 1:a4ce08417c60 50 AllPass delayLeft;
dallegre 3:f8bc3ac22ffd 51 AllPass delayLeft2;
dallegre 3:f8bc3ac22ffd 52 AllPass delayLeft3;
dallegre 7:c84086dce9ac 53 AllPass delayLeft4;
dallegre 1:a4ce08417c60 54 AllPass delayRight;
dallegre 2:1b50325e256f 55 AllPass delayRight2;
dallegre 3:f8bc3ac22ffd 56 AllPass delayRight3;
dallegre 7:c84086dce9ac 57 AllPass delayRight4;
dallegre 3:f8bc3ac22ffd 58 gsOsc OscillatorL;
dallegre 3:f8bc3ac22ffd 59 gsOsc OscillatorL2;
dallegre 3:f8bc3ac22ffd 60 gsOsc OscillatorL3;
dallegre 7:c84086dce9ac 61 gsOsc OscillatorL4;
dallegre 3:f8bc3ac22ffd 62 gsOsc OscillatorR;
dallegre 3:f8bc3ac22ffd 63 gsOsc OscillatorR2;
dallegre 3:f8bc3ac22ffd 64 gsOsc OscillatorR3;
dallegre 7:c84086dce9ac 65 gsOsc OscillatorR4;
dallegre 0:c12e968e5b60 66
dallegre 0:c12e968e5b60 67 void I2S_send(void){
dallegre 0:c12e968e5b60 68 cs.write(0); //0 for left output
dallegre 0:c12e968e5b60 69 left_in = spi.write(left_out);
dallegre 0:c12e968e5b60 70 cs.write(1); //1 for right output
dallegre 0:c12e968e5b60 71 right_in = spi.write(right_out);
dallegre 0:c12e968e5b60 72
dallegre 0:c12e968e5b60 73 left_in_f = intToFloat(left_in);
dallegre 0:c12e968e5b60 74
dallegre 0:c12e968e5b60 75 /////////////////////////////////////////dsp part//////////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 76
dallegre 8:ef4dca8695d1 77 ///*
dallegre 0:c12e968e5b60 78 //process control signals
dallegre 0:c12e968e5b60 79 feedback2 = feedbackFilter.process(feedback);
dallegre 8:ef4dca8695d1 80 //maybe move this to the dac sampling interrupt. seems like there was a reason it's here though.
dallegre 8:ef4dca8695d1 81 //damping2 = lengthFilter.process(damping);
dallegre 8:ef4dca8695d1 82 //damping3 = lengthFilter.process(damping2);
dallegre 8:ef4dca8695d1 83 //damping3 *= (5000); //make about 10k the max cutoff for damping
dallegre 8:ef4dca8695d1 84
dallegre 8:ef4dca8695d1 85 //dampingFilter.setFc(damping3/(SAMPLINGFREQ*1000));
dallegre 0:c12e968e5b60 86
dallegre 2:1b50325e256f 87 //process audio. probably calculate these coefficients elsewhere so you don't do the multiply all the time.
dallegre 2:1b50325e256f 88 //left delay mod
dallegre 8:ef4dca8695d1 89 modL = modLos + OscillatorL.process(1);
dallegre 8:ef4dca8695d1 90 modL2 = modL2os + OscillatorL2.process(1);
dallegre 8:ef4dca8695d1 91 modL3 = modL3os + OscillatorL3.process(1);
dallegre 8:ef4dca8695d1 92 modL4 = modL4os + OscillatorL3.process(0);
dallegre 2:1b50325e256f 93 //right delay mod
dallegre 8:ef4dca8695d1 94 modR = modRos + OscillatorR.process(0);
dallegre 8:ef4dca8695d1 95 modR2 = modR2os + OscillatorR2.process(0);
dallegre 8:ef4dca8695d1 96 modR3 = modR3os + OscillatorR3.process(1);
dallegre 8:ef4dca8695d1 97 modR4 = modR4os + OscillatorR4.process(1);
dallegre 8:ef4dca8695d1 98
dallegre 8:ef4dca8695d1 99 if(modL > upperLim)
dallegre 8:ef4dca8695d1 100 modL = upperLim;
dallegre 8:ef4dca8695d1 101 if(modL < lowerLim)
dallegre 8:ef4dca8695d1 102 modL = lowerLim;
dallegre 8:ef4dca8695d1 103 if(modL2 > upperLim)
dallegre 8:ef4dca8695d1 104 modL2 = upperLim;
dallegre 8:ef4dca8695d1 105 if(modL2 < lowerLim)
dallegre 8:ef4dca8695d1 106 modL2 = lowerLim;
dallegre 8:ef4dca8695d1 107 if(modL3 > upperLim)
dallegre 8:ef4dca8695d1 108 modL3 = upperLim;
dallegre 8:ef4dca8695d1 109 if(modL3 < lowerLim)
dallegre 8:ef4dca8695d1 110 modL3 = lowerLim;
dallegre 8:ef4dca8695d1 111 if(modL4 > upperLim)
dallegre 8:ef4dca8695d1 112 modL4 = upperLim;
dallegre 8:ef4dca8695d1 113 if(modL4 < lowerLim)
dallegre 8:ef4dca8695d1 114 modL4 = lowerLim;
dallegre 8:ef4dca8695d1 115 if(modR > upperLim)
dallegre 8:ef4dca8695d1 116 modR = upperLim;
dallegre 8:ef4dca8695d1 117 if(modR < lowerLim)
dallegre 8:ef4dca8695d1 118 modR = lowerLim;
dallegre 8:ef4dca8695d1 119 if(modR2 > upperLim)
dallegre 8:ef4dca8695d1 120 modR2 = upperLim;
dallegre 8:ef4dca8695d1 121 if(modR2 < lowerLim)
dallegre 8:ef4dca8695d1 122 modR2 = lowerLim;
dallegre 8:ef4dca8695d1 123 if(modR3 > upperLim)
dallegre 8:ef4dca8695d1 124 modR3 = upperLim;
dallegre 8:ef4dca8695d1 125 if(modR3 < lowerLim)
dallegre 8:ef4dca8695d1 126 modR3 = lowerLim;
dallegre 8:ef4dca8695d1 127 if(modR4 > upperLim)
dallegre 8:ef4dca8695d1 128 modR4 = upperLim;
dallegre 8:ef4dca8695d1 129 if(modR4 < lowerLim)
dallegre 8:ef4dca8695d1 130 modR4 = lowerLim;
dallegre 8:ef4dca8695d1 131
dallegre 7:c84086dce9ac 132 left_out_2 = delayLeft2.process(satAdd(left_in_f,loopfb),.3,modL);
dallegre 7:c84086dce9ac 133 left_out_3 = delayLeft3.process(left_out_2,.4,modL2);
dallegre 7:c84086dce9ac 134 left_out_4 = delayLeft4.process(left_out_3,.4,modL3);
dallegre 7:c84086dce9ac 135 left_out_f = delayLeft.process(left_out_4,.4,modL4);
dallegre 7:c84086dce9ac 136 right_out_2 = delayRight2.process(satAdd(left_in_f,loopfb2),.3,modR);
dallegre 7:c84086dce9ac 137 right_out_3 = delayRight3.process(right_out_2,.4,modR2);
dallegre 7:c84086dce9ac 138 right_out_4 = delayRight4.process(right_out_3,.4,modR3);
dallegre 7:c84086dce9ac 139 right_out_f = delayRight.process(right_out_4,.4,modR4);
dallegre 7:c84086dce9ac 140
dallegre 8:ef4dca8695d1 141 loopfb2 = left_out_f*feedback2; //swizzle the feedbacks left to right
dallegre 8:ef4dca8695d1 142 loopfb = right_out_f*feedback2;
dallegre 8:ef4dca8695d1 143
dallegre 8:ef4dca8695d1 144 //apply damping
dallegre 7:c84086dce9ac 145 //loopfb = dampingFilter.process(loopfb);
dallegre 7:c84086dce9ac 146 //loopfb2 = dampingFilter.process(loopfb2);
dallegre 8:ef4dca8695d1 147 //*/
dallegre 8:ef4dca8695d1 148 //left_out_f = left_in_f;
dallegre 8:ef4dca8695d1 149 //right_out_f = left_in_f;
dallegre 8:ef4dca8695d1 150
dallegre 6:df635006ee1c 151 left_out_u = left_out_f;
dallegre 6:df635006ee1c 152 right_out_u = right_out_f;
dallegre 0:c12e968e5b60 153
dallegre 0:c12e968e5b60 154 /////////////////////////////////////////end of dsp part/////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 155
dallegre 0:c12e968e5b60 156 left_out = unsignedToSigned(left_out_u);
dallegre 0:c12e968e5b60 157 right_out = unsignedToSigned(right_out_u);
dallegre 0:c12e968e5b60 158
dallegre 0:c12e968e5b60 159 }
dallegre 0:c12e968e5b60 160
dallegre 0:c12e968e5b60 161 void analog_read(void){
dallegre 0:c12e968e5b60 162 //this is the stuff for the feedback amount pot
dallegre 0:c12e968e5b60 163 meas2f = analog_value2.read_u16(); //converts unint16 value to float
dallegre 0:c12e968e5b60 164 feedback = meas2f/4100; //now you have a value between 0 and 1 that will control the feedback amount.
dallegre 7:c84086dce9ac 165 feedback *= feedback;
dallegre 0:c12e968e5b60 166
dallegre 0:c12e968e5b60 167 //this is the stuff for the delay time pot
dallegre 0:c12e968e5b60 168 meas = 4096 - analog_value.read_u16(); //values go from 1 to 4095
dallegre 0:c12e968e5b60 169 //if(abs(meas - measprev) > 5){
dallegre 0:c12e968e5b60 170 measprev = meas;
dallegre 7:c84086dce9ac 171 damping = meas;
dallegre 7:c84086dce9ac 172 damping /= 4200; //this number took some tweaking.
dallegre 7:c84086dce9ac 173 damping *= damping;
dallegre 0:c12e968e5b60 174 //}
dallegre 0:c12e968e5b60 175 }
dallegre 0:c12e968e5b60 176
dallegre 0:c12e968e5b60 177 int main(){
dallegre 0:c12e968e5b60 178
dallegre 0:c12e968e5b60 179 //set up baud rate for 11.2MHz crystal
dallegre 0:c12e968e5b60 180 pc.baud(.7*9600*2);
dallegre 0:c12e968e5b60 181 wait(.1);
dallegre 0:c12e968e5b60 182
dallegre 0:c12e968e5b60 183 //do I2C transfter to initialize codec
dallegre 0:c12e968e5b60 184 codecInit();
dallegre 0:c12e968e5b60 185
dallegre 0:c12e968e5b60 186 //initialize fixed filters
dallegre 0:c12e968e5b60 187 double feedbackCutoff = 10.0/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 188 feedbackFilter.setFc(feedbackCutoff);
dallegre 0:c12e968e5b60 189 double lengthCutoff = 3.0/(SAMPLINGFREQ*1000);
dallegre 0:c12e968e5b60 190 lengthFilter.setFc(lengthCutoff);
dallegre 8:ef4dca8695d1 191
dallegre 8:ef4dca8695d1 192 //initize oscillators and mod offsets
dallegre 8:ef4dca8695d1 193 modLos = DELAYLEN*.74;
dallegre 8:ef4dca8695d1 194 modL2os = DELAYLEN*.43;
dallegre 8:ef4dca8695d1 195 modL3os = DELAYLEN*.33;
dallegre 8:ef4dca8695d1 196 modL4os = DELAYLEN*.37;
dallegre 8:ef4dca8695d1 197 OscillatorL.setF(.53,DELAYLEN/66);
dallegre 8:ef4dca8695d1 198 OscillatorL2.setF(.03,DELAYLEN/65);
dallegre 8:ef4dca8695d1 199 OscillatorL3.setF(.02,DELAYLEN/78);
dallegre 8:ef4dca8695d1 200 OscillatorL4.setF(.023,DELAYLEN/78);
dallegre 8:ef4dca8695d1 201 //right delay mod
dallegre 8:ef4dca8695d1 202 modRos = DELAYLEN*.75;
dallegre 8:ef4dca8695d1 203 modR2os = DELAYLEN*.49;
dallegre 8:ef4dca8695d1 204 modR3os = DELAYLEN*.33;
dallegre 8:ef4dca8695d1 205 modR4os = DELAYLEN*.37;
dallegre 8:ef4dca8695d1 206 OscillatorR.setF(.51,DELAYLEN/69);
dallegre 8:ef4dca8695d1 207 OscillatorR2.setF(.03,DELAYLEN/67);
dallegre 8:ef4dca8695d1 208 OscillatorR3.setF(.02,DELAYLEN/78);
dallegre 8:ef4dca8695d1 209 OscillatorR4.setF(.023,DELAYLEN/78);
dallegre 8:ef4dca8695d1 210 upperLim = .9*DELAYLEN;
dallegre 8:ef4dca8695d1 211 lowerLim = .05*DELAYLEN;
dallegre 0:c12e968e5b60 212
dallegre 0:c12e968e5b60 213 //set up I2S
dallegre 9:f42863126573 214 spi.frequency(4e6*2); //8MHz spi. This is fast enough for 88KHz 16 bit sampling.
dallegre 0:c12e968e5b60 215 spi.format(16,0); //16 bit. clock polarity 0, phase 0.
dallegre 0:c12e968e5b60 216 wait(.1);
dallegre 0:c12e968e5b60 217
dallegre 0:c12e968e5b60 218 //audio rate timers. 29 and 44 are not very good. Might want to use an external clock for the Nucleo.
dallegre 0:c12e968e5b60 219 if(SAMPLINGFREQ == 22)
dallegre 0:c12e968e5b60 220 timer.attach(&I2S_send,32e-6); //22KHz sampling. 12.2008MHz/512 = 21.876KHz. 1/(21.876KHz(8/11.2008)) = 64e-6 Sec and / by 2 because the codec divides by to before sending the osc out.
dallegre 0:c12e968e5b60 221 if(SAMPLINGFREQ == 29)
dallegre 0:c12e968e5b60 222 timer.attach(&I2S_send,24e-6); //29.168KHz sampling. 11.2008MHz/384 = 19.168KHz. 1/(29.168KHz(8/11.2008)) = 48.0012e-6 Sec and / by 2 because the codec divides by to before sending the osc out.
dallegre 0:c12e968e5b60 223 if(SAMPLINGFREQ == 44)
dallegre 0:c12e968e5b60 224 timer.attach(&I2S_send,16.0e-6); //44.1KHz sampling. almost exactly 32e-6 and then divide by 2. Doesn't sound right yet.
dallegre 0:c12e968e5b60 225 if(SAMPLINGFREQ == 88)
dallegre 0:c12e968e5b60 226 timer.attach(&I2S_send,8e-6); //88KHz sampling. Need to calculate.
dallegre 0:c12e968e5b60 227
dallegre 0:c12e968e5b60 228 //control signal timer
dallegre 9:f42863126573 229 timer2.attach(&analog_read,50e-3);
dallegre 0:c12e968e5b60 230
dallegre 0:c12e968e5b60 231 //go!
dallegre 0:c12e968e5b60 232 while(1){}
dallegre 0:c12e968e5b60 233 }