Dan Allegre / 401_reverb

Dependencies:   mbed

Committer:
dallegre
Date:
Sat Jul 30 21:34:28 2016 +0000
Revision:
7:c84086dce9ac
Parent:
6:df635006ee1c
Child:
8:ef4dca8695d1
got it!  still sounds a bit low fi;

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 7:c84086dce9ac 18 #define SAMPLINGFREQ 44 //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 3:f8bc3ac22ffd 38 left_out_f = 0, right_out_f = 0;
dallegre 7:c84086dce9ac 39 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 40 float audioFeedbackRight,audioFeedbackLeft;
dallegre 0:c12e968e5b60 41
dallegre 0:c12e968e5b60 42 float LPdampingFreq = 11000, HPdampingFreq = 100; //some parameters you might want to adjust.
dallegre 0:c12e968e5b60 43 int LPdampingPoles = 2, HPdampingPoles = 0; //I don't think the highpass is quite working.
dallegre 0:c12e968e5b60 44
dallegre 0:c12e968e5b60 45 OnePoleLp feedbackFilter;
dallegre 0:c12e968e5b60 46 OnePoleLp lengthFilter;
dallegre 7:c84086dce9ac 47 OnePoleLp dampingFilter;
dallegre 1:a4ce08417c60 48 AllPass delayLeft;
dallegre 3:f8bc3ac22ffd 49 AllPass delayLeft2;
dallegre 3:f8bc3ac22ffd 50 AllPass delayLeft3;
dallegre 7:c84086dce9ac 51 AllPass delayLeft4;
dallegre 1:a4ce08417c60 52 AllPass delayRight;
dallegre 2:1b50325e256f 53 AllPass delayRight2;
dallegre 3:f8bc3ac22ffd 54 AllPass delayRight3;
dallegre 7:c84086dce9ac 55 AllPass delayRight4;
dallegre 3:f8bc3ac22ffd 56 gsOsc OscillatorL;
dallegre 3:f8bc3ac22ffd 57 gsOsc OscillatorL2;
dallegre 3:f8bc3ac22ffd 58 gsOsc OscillatorL3;
dallegre 7:c84086dce9ac 59 gsOsc OscillatorL4;
dallegre 3:f8bc3ac22ffd 60 gsOsc OscillatorR;
dallegre 3:f8bc3ac22ffd 61 gsOsc OscillatorR2;
dallegre 3:f8bc3ac22ffd 62 gsOsc OscillatorR3;
dallegre 7:c84086dce9ac 63 gsOsc OscillatorR4;
dallegre 0:c12e968e5b60 64
dallegre 0:c12e968e5b60 65 void I2S_send(void){
dallegre 0:c12e968e5b60 66 cs.write(0); //0 for left output
dallegre 0:c12e968e5b60 67 left_in = spi.write(left_out);
dallegre 0:c12e968e5b60 68 cs.write(1); //1 for right output
dallegre 0:c12e968e5b60 69 right_in = spi.write(right_out);
dallegre 0:c12e968e5b60 70
dallegre 0:c12e968e5b60 71 left_in_f = intToFloat(left_in);
dallegre 0:c12e968e5b60 72
dallegre 0:c12e968e5b60 73 /////////////////////////////////////////dsp part//////////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 74
dallegre 0:c12e968e5b60 75 //process control signals
dallegre 0:c12e968e5b60 76 feedback2 = feedbackFilter.process(feedback);
dallegre 0:c12e968e5b60 77 feedback3 = feedbackFilter.process(feedback2);
dallegre 0:c12e968e5b60 78 //update delay times with every audio sample if you're going to filter them.
dallegre 7:c84086dce9ac 79 damping2 = lengthFilter.process(damping);
dallegre 7:c84086dce9ac 80 damping3 = lengthFilter.process(damping2);
dallegre 7:c84086dce9ac 81 damping3 *= (5000); //make about 10k the max cutoff for damping
dallegre 7:c84086dce9ac 82
dallegre 7:c84086dce9ac 83
dallegre 7:c84086dce9ac 84 dampingFilter.setFc(damping3);
dallegre 0:c12e968e5b60 85
dallegre 2:1b50325e256f 86 //process audio. probably calculate these coefficients elsewhere so you don't do the multiply all the time.
dallegre 2:1b50325e256f 87 //left delay mod
dallegre 7:c84086dce9ac 88 modL = DELAYLEN*.74 + OscillatorL.process(.53,DELAYLEN/66,1);
dallegre 7:c84086dce9ac 89 modL2 = DELAYLEN*.43 + OscillatorL2.process(.03,DELAYLEN/65,1);
dallegre 7:c84086dce9ac 90 modL3 = DELAYLEN*.33 + OscillatorL3.process(.02,DELAYLEN/78,1);
dallegre 7:c84086dce9ac 91 modL3 = DELAYLEN*.37 + OscillatorL3.process(.023,DELAYLEN/78,0);
dallegre 2:1b50325e256f 92 //right delay mod
dallegre 7:c84086dce9ac 93 modR = DELAYLEN*.75 + OscillatorR.process(.51,DELAYLEN/69,0);
dallegre 7:c84086dce9ac 94 modR2 = DELAYLEN*.49 + OscillatorR2.process(.03,DELAYLEN/67,0);
dallegre 7:c84086dce9ac 95 modR3 = DELAYLEN*.33 + OscillatorR3.process(.02,DELAYLEN/78,1);
dallegre 7:c84086dce9ac 96 modR4 = DELAYLEN*.37 + OscillatorR4.process(.023,DELAYLEN/78,1);
dallegre 7:c84086dce9ac 97 if(modL > DELAYLEN*.9)
dallegre 7:c84086dce9ac 98 modL = DELAYLEN*.9;
dallegre 7:c84086dce9ac 99 if(modL < DELAYLEN*.05)
dallegre 7:c84086dce9ac 100 modL = DELAYLEN*.05;
dallegre 7:c84086dce9ac 101 if(modL2 > DELAYLEN*.9)
dallegre 7:c84086dce9ac 102 modL2 = DELAYLEN*.9;
dallegre 7:c84086dce9ac 103 if(modL2 < DELAYLEN*.05)
dallegre 7:c84086dce9ac 104 modL2 = DELAYLEN*.05;
dallegre 7:c84086dce9ac 105 if(modL3 > DELAYLEN*.9)
dallegre 7:c84086dce9ac 106 modL3 = DELAYLEN*.9;
dallegre 7:c84086dce9ac 107 if(modL3 < DELAYLEN*.05)
dallegre 7:c84086dce9ac 108 modL3 = DELAYLEN*.05;
dallegre 7:c84086dce9ac 109 if(modL4 > DELAYLEN*.9)
dallegre 7:c84086dce9ac 110 modL4 = DELAYLEN*.9;
dallegre 7:c84086dce9ac 111 if(modL4 < DELAYLEN*.05)
dallegre 7:c84086dce9ac 112 modL4 = DELAYLEN*.05;
dallegre 7:c84086dce9ac 113 if(modR > DELAYLEN*.9)
dallegre 7:c84086dce9ac 114 modR = DELAYLEN*.9;
dallegre 7:c84086dce9ac 115 if(modR < DELAYLEN*.05)
dallegre 7:c84086dce9ac 116 modR = DELAYLEN*.05;
dallegre 7:c84086dce9ac 117 if(modR2 > DELAYLEN*.9)
dallegre 7:c84086dce9ac 118 modR2 = DELAYLEN*.9;
dallegre 7:c84086dce9ac 119 if(modR2 < DELAYLEN*.05)
dallegre 7:c84086dce9ac 120 modR2 = DELAYLEN*.05;
dallegre 7:c84086dce9ac 121 if(modR3 > DELAYLEN*.9)
dallegre 7:c84086dce9ac 122 modR3 = DELAYLEN*.9;
dallegre 7:c84086dce9ac 123 if(modR3 < DELAYLEN*.05)
dallegre 7:c84086dce9ac 124 modR3 = DELAYLEN*.05;
dallegre 7:c84086dce9ac 125 if(modR4 > DELAYLEN*.9)
dallegre 7:c84086dce9ac 126 modR4 = DELAYLEN*.9;
dallegre 7:c84086dce9ac 127 if(modR4 < DELAYLEN*.05)
dallegre 7:c84086dce9ac 128 modR4 = DELAYLEN*.05;
dallegre 7:c84086dce9ac 129 left_out_2 = delayLeft2.process(satAdd(left_in_f,loopfb),.3,modL);
dallegre 7:c84086dce9ac 130 left_out_3 = delayLeft3.process(left_out_2,.4,modL2);
dallegre 7:c84086dce9ac 131 left_out_4 = delayLeft4.process(left_out_3,.4,modL3);
dallegre 7:c84086dce9ac 132 left_out_f = delayLeft.process(left_out_4,.4,modL4);
dallegre 7:c84086dce9ac 133 right_out_2 = delayRight2.process(satAdd(left_in_f,loopfb2),.3,modR);
dallegre 7:c84086dce9ac 134 right_out_3 = delayRight3.process(right_out_2,.4,modR2);
dallegre 7:c84086dce9ac 135 right_out_4 = delayRight4.process(right_out_3,.4,modR3);
dallegre 7:c84086dce9ac 136 right_out_f = delayRight.process(right_out_4,.4,modR4);
dallegre 7:c84086dce9ac 137 //loopfb = dampingFilter.process(left_out_f);
dallegre 7:c84086dce9ac 138 //loopfb2 = dampingFilter.process(right_out_f);
dallegre 7:c84086dce9ac 139
dallegre 7:c84086dce9ac 140 //loopfb *= feedback3;
dallegre 7:c84086dce9ac 141 //loopfb2 *= feedback3;
dallegre 7:c84086dce9ac 142 loopfb2 = left_out_f*feedback3; //swizzle the feedbacks left to right
dallegre 7:c84086dce9ac 143 loopfb = right_out_f*feedback3;
dallegre 7:c84086dce9ac 144 //loopfb = dampingFilter.process(loopfb);
dallegre 7:c84086dce9ac 145 //loopfb2 = dampingFilter.process(loopfb2);
dallegre 7:c84086dce9ac 146 //left_out_u = satAdd(left_in_f,left_out_f*damping3/200);
dallegre 7:c84086dce9ac 147 //right_out_u = satAdd(left_in_f,right_out_f*damping3/200);
dallegre 6:df635006ee1c 148 left_out_u = left_out_f;
dallegre 6:df635006ee1c 149 right_out_u = right_out_f;
dallegre 0:c12e968e5b60 150
dallegre 0:c12e968e5b60 151 /////////////////////////////////////////end of dsp part/////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 152
dallegre 0:c12e968e5b60 153 left_out = unsignedToSigned(left_out_u);
dallegre 0:c12e968e5b60 154 right_out = unsignedToSigned(right_out_u);
dallegre 0:c12e968e5b60 155
dallegre 0:c12e968e5b60 156 }
dallegre 0:c12e968e5b60 157
dallegre 0:c12e968e5b60 158 void analog_read(void){
dallegre 0:c12e968e5b60 159 //this is the stuff for the feedback amount pot
dallegre 0:c12e968e5b60 160 meas2f = analog_value2.read_u16(); //converts unint16 value to float
dallegre 0:c12e968e5b60 161 feedback = meas2f/4100; //now you have a value between 0 and 1 that will control the feedback amount.
dallegre 7:c84086dce9ac 162 feedback *= feedback;
dallegre 0:c12e968e5b60 163
dallegre 0:c12e968e5b60 164 //this is the stuff for the delay time pot
dallegre 0:c12e968e5b60 165 meas = 4096 - analog_value.read_u16(); //values go from 1 to 4095
dallegre 0:c12e968e5b60 166 //if(abs(meas - measprev) > 5){
dallegre 0:c12e968e5b60 167 measprev = meas;
dallegre 7:c84086dce9ac 168 damping = meas;
dallegre 7:c84086dce9ac 169 damping /= 4200; //this number took some tweaking.
dallegre 7:c84086dce9ac 170 damping *= damping;
dallegre 0:c12e968e5b60 171 //}
dallegre 0:c12e968e5b60 172 }
dallegre 0:c12e968e5b60 173
dallegre 0:c12e968e5b60 174 int main(){
dallegre 0:c12e968e5b60 175
dallegre 0:c12e968e5b60 176 //set up baud rate for 11.2MHz crystal
dallegre 0:c12e968e5b60 177 pc.baud(.7*9600*2);
dallegre 0:c12e968e5b60 178 wait(.1);
dallegre 0:c12e968e5b60 179
dallegre 0:c12e968e5b60 180 //do I2C transfter to initialize codec
dallegre 0:c12e968e5b60 181 codecInit();
dallegre 0:c12e968e5b60 182
dallegre 0:c12e968e5b60 183 //initialize fixed filters
dallegre 0:c12e968e5b60 184 double feedbackCutoff = 10.0/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 185 feedbackFilter.setFc(feedbackCutoff);
dallegre 0:c12e968e5b60 186 double lengthCutoff = 3.0/(SAMPLINGFREQ*1000);
dallegre 0:c12e968e5b60 187 lengthFilter.setFc(lengthCutoff);
dallegre 0:c12e968e5b60 188
dallegre 0:c12e968e5b60 189 //set up I2S
dallegre 0:c12e968e5b60 190 spi.frequency(8e6*2); //8MHz spi. This is fast enough for 88KHz 16 bit sampling.
dallegre 0:c12e968e5b60 191 spi.format(16,0); //16 bit. clock polarity 0, phase 0.
dallegre 0:c12e968e5b60 192 wait(.1);
dallegre 0:c12e968e5b60 193
dallegre 0:c12e968e5b60 194 //audio rate timers. 29 and 44 are not very good. Might want to use an external clock for the Nucleo.
dallegre 0:c12e968e5b60 195 if(SAMPLINGFREQ == 22)
dallegre 0:c12e968e5b60 196 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 197 if(SAMPLINGFREQ == 29)
dallegre 0:c12e968e5b60 198 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 199 if(SAMPLINGFREQ == 44)
dallegre 0:c12e968e5b60 200 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 201 if(SAMPLINGFREQ == 88)
dallegre 0:c12e968e5b60 202 timer.attach(&I2S_send,8e-6); //88KHz sampling. Need to calculate.
dallegre 0:c12e968e5b60 203
dallegre 0:c12e968e5b60 204 //control signal timer
dallegre 0:c12e968e5b60 205 timer2.attach(&analog_read,25e-3);
dallegre 0:c12e968e5b60 206
dallegre 0:c12e968e5b60 207 //go!
dallegre 0:c12e968e5b60 208 while(1){}
dallegre 0:c12e968e5b60 209 }