Dan Allegre / 401_reverb

Dependencies:   mbed

Committer:
dallegre
Date:
Sat Jul 30 20:02:42 2016 +0000
Revision:
6:df635006ee1c
Parent:
5:265c9540466a
Child:
7:c84086dce9ac
pretty good sounding..

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 2:1b50325e256f 17 #define DELAYLEN 3900 //24,000 is about as far as you can go in the ram.
dallegre 6:df635006ee1c 18 #define SAMPLINGFREQ 29 //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 3:f8bc3ac22ffd 37 meas2f = 0.5, measf = 0, measf2 = 0, measf3 = 0, measf3L = 0, measf3L2 = 0, measf3L3 = 0, measf3R = 0, measf3R2 = 0, measf3R3 = 0,
dallegre 3:f8bc3ac22ffd 38 left_out_f = 0, right_out_f = 0;
dallegre 3:f8bc3ac22ffd 39 float left_out_2 = 0, right_out_2 = 0, left_out_3 = 0, right_out_3 = 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 audioFilter; //might use this as a mor thorough DC offset removal tool. Not yet implemented.
dallegre 0:c12e968e5b60 46 OnePoleHp audioFilterHP;
dallegre 0:c12e968e5b60 47 OnePoleLp feedbackFilter;
dallegre 0:c12e968e5b60 48 OnePoleLp lengthFilter;
dallegre 1:a4ce08417c60 49 AllPass delayLeft;
dallegre 3:f8bc3ac22ffd 50 AllPass delayLeft2;
dallegre 3:f8bc3ac22ffd 51 AllPass delayLeft3;
dallegre 1:a4ce08417c60 52 AllPass delayRight;
dallegre 2:1b50325e256f 53 AllPass delayRight2;
dallegre 3:f8bc3ac22ffd 54 AllPass delayRight3;
dallegre 3:f8bc3ac22ffd 55 gsOsc OscillatorL;
dallegre 3:f8bc3ac22ffd 56 gsOsc OscillatorL2;
dallegre 3:f8bc3ac22ffd 57 gsOsc OscillatorL3;
dallegre 3:f8bc3ac22ffd 58 gsOsc OscillatorR;
dallegre 3:f8bc3ac22ffd 59 gsOsc OscillatorR2;
dallegre 3:f8bc3ac22ffd 60 gsOsc OscillatorR3;
dallegre 0:c12e968e5b60 61
dallegre 0:c12e968e5b60 62 void I2S_send(void){
dallegre 0:c12e968e5b60 63 cs.write(0); //0 for left output
dallegre 0:c12e968e5b60 64 left_in = spi.write(left_out);
dallegre 0:c12e968e5b60 65 cs.write(1); //1 for right output
dallegre 0:c12e968e5b60 66 right_in = spi.write(right_out);
dallegre 0:c12e968e5b60 67
dallegre 0:c12e968e5b60 68 left_in_f = intToFloat(left_in);
dallegre 0:c12e968e5b60 69
dallegre 0:c12e968e5b60 70 /////////////////////////////////////////dsp part//////////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 71
dallegre 0:c12e968e5b60 72 //process control signals
dallegre 0:c12e968e5b60 73 feedback2 = feedbackFilter.process(feedback);
dallegre 0:c12e968e5b60 74 feedback3 = feedbackFilter.process(feedback2);
dallegre 0:c12e968e5b60 75 //update delay times with every audio sample if you're going to filter them.
dallegre 0:c12e968e5b60 76 measf2 = lengthFilter.process(measf);
dallegre 0:c12e968e5b60 77 measf3 = lengthFilter.process(measf2);
dallegre 0:c12e968e5b60 78 measf3 *= (DELAYLEN); //convert to delay index normalization
dallegre 0:c12e968e5b60 79
dallegre 2:1b50325e256f 80 //process audio. probably calculate these coefficients elsewhere so you don't do the multiply all the time.
dallegre 2:1b50325e256f 81 //left delay mod
dallegre 6:df635006ee1c 82 measf3L = DELAYLEN*.74 + OscillatorL.process(.23,DELAYLEN/76,1);
dallegre 6:df635006ee1c 83 measf3L2 = DELAYLEN*.43 + OscillatorL2.process(.05,DELAYLEN/75,1);
dallegre 6:df635006ee1c 84 measf3L3 = DELAYLEN*.23 + OscillatorL3.process(.03,DELAYLEN/78,1);
dallegre 2:1b50325e256f 85 //right delay mod
dallegre 6:df635006ee1c 86 measf3R = DELAYLEN*.75 + OscillatorR.process(.21,DELAYLEN/79,0);
dallegre 6:df635006ee1c 87 measf3R2 = DELAYLEN*.49 + OscillatorR2.process(.05,DELAYLEN/77,0);
dallegre 6:df635006ee1c 88 measf3R3 = DELAYLEN*.23 + OscillatorR3.process(.02,DELAYLEN/78,1);
dallegre 3:f8bc3ac22ffd 89 if(measf3L > DELAYLEN*.9)
dallegre 3:f8bc3ac22ffd 90 measf3L = DELAYLEN*.9;
dallegre 3:f8bc3ac22ffd 91 if(measf3L < DELAYLEN*.05)
dallegre 3:f8bc3ac22ffd 92 measf3L = DELAYLEN*.05;
dallegre 3:f8bc3ac22ffd 93 if(measf3L2 > DELAYLEN*.9)
dallegre 3:f8bc3ac22ffd 94 measf3L2 = DELAYLEN*.9;
dallegre 3:f8bc3ac22ffd 95 if(measf3L2 < DELAYLEN*.05)
dallegre 3:f8bc3ac22ffd 96 measf3L2 = DELAYLEN*.05;
dallegre 3:f8bc3ac22ffd 97 if(measf3L3 > DELAYLEN*.9)
dallegre 3:f8bc3ac22ffd 98 measf3L3 = DELAYLEN*.9;
dallegre 3:f8bc3ac22ffd 99 if(measf3L3 < DELAYLEN*.05)
dallegre 3:f8bc3ac22ffd 100 measf3L3 = DELAYLEN*.05;
dallegre 3:f8bc3ac22ffd 101 if(measf3R > DELAYLEN*.9)
dallegre 3:f8bc3ac22ffd 102 measf3R = DELAYLEN*.9;
dallegre 3:f8bc3ac22ffd 103 if(measf3R < DELAYLEN*.05)
dallegre 3:f8bc3ac22ffd 104 measf3R = DELAYLEN*.05;
dallegre 3:f8bc3ac22ffd 105 if(measf3R2 > DELAYLEN*.9)
dallegre 3:f8bc3ac22ffd 106 measf3R2 = DELAYLEN*.9;
dallegre 3:f8bc3ac22ffd 107 if(measf3R2 < DELAYLEN*.05)
dallegre 3:f8bc3ac22ffd 108 measf3R2 = DELAYLEN*.05;
dallegre 3:f8bc3ac22ffd 109 if(measf3R3 > DELAYLEN*.9)
dallegre 3:f8bc3ac22ffd 110 measf3R3 = DELAYLEN*.9;
dallegre 3:f8bc3ac22ffd 111 if(measf3R3 < DELAYLEN*.05)
dallegre 3:f8bc3ac22ffd 112 measf3R3 = DELAYLEN*.05;
dallegre 4:efa5e07fd268 113 left_out_2 = delayLeft2.process(satSubtract(left_in_f,loopfb),.3,measf3L);
dallegre 4:efa5e07fd268 114 left_out_3 = delayLeft3.process(left_out_2,.4,measf3L2);
dallegre 5:265c9540466a 115 left_out_f = delayLeft.process(left_out_3,.4,measf3L3);
dallegre 4:efa5e07fd268 116 right_out_2 = delayRight2.process(satSubtract(left_in_f,loopfb2),.3,measf3R);
dallegre 4:efa5e07fd268 117 right_out_3 = delayRight3.process(right_out_2,.4,measf3R2);
dallegre 5:265c9540466a 118 right_out_f = delayRight.process(right_out_3,.4,measf3R3);
dallegre 3:f8bc3ac22ffd 119 loopfb = left_out_f*feedback3;
dallegre 3:f8bc3ac22ffd 120 loopfb2 = right_out_f*feedback3;
dallegre 6:df635006ee1c 121 //left_out_u = satAdd(left_in_f,left_out_f*measf3/200);
dallegre 6:df635006ee1c 122 //right_out_u = satAdd(left_in_f,right_out_f*measf3/200);
dallegre 6:df635006ee1c 123 left_out_u = left_out_f;
dallegre 6:df635006ee1c 124 right_out_u = right_out_f;
dallegre 0:c12e968e5b60 125
dallegre 0:c12e968e5b60 126 /////////////////////////////////////////end of dsp part/////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 127
dallegre 0:c12e968e5b60 128 left_out = unsignedToSigned(left_out_u);
dallegre 0:c12e968e5b60 129 right_out = unsignedToSigned(right_out_u);
dallegre 0:c12e968e5b60 130
dallegre 0:c12e968e5b60 131 }
dallegre 0:c12e968e5b60 132
dallegre 0:c12e968e5b60 133 void analog_read(void){
dallegre 0:c12e968e5b60 134 //this is the stuff for the feedback amount pot
dallegre 0:c12e968e5b60 135 meas2f = analog_value2.read_u16(); //converts unint16 value to float
dallegre 0:c12e968e5b60 136 feedback = meas2f/4100; //now you have a value between 0 and 1 that will control the feedback amount.
dallegre 0:c12e968e5b60 137
dallegre 0:c12e968e5b60 138 //this is the stuff for the delay time pot
dallegre 0:c12e968e5b60 139 meas = 4096 - analog_value.read_u16(); //values go from 1 to 4095
dallegre 0:c12e968e5b60 140 //if(abs(meas - measprev) > 5){
dallegre 0:c12e968e5b60 141 measprev = meas;
dallegre 0:c12e968e5b60 142 measf = meas;
dallegre 0:c12e968e5b60 143 measf /= 4200; //this number took some tweaking.
dallegre 0:c12e968e5b60 144 measf *= measf;
dallegre 0:c12e968e5b60 145 //}
dallegre 0:c12e968e5b60 146 }
dallegre 0:c12e968e5b60 147
dallegre 0:c12e968e5b60 148 int main(){
dallegre 0:c12e968e5b60 149
dallegre 0:c12e968e5b60 150 //set up baud rate for 11.2MHz crystal
dallegre 0:c12e968e5b60 151 pc.baud(.7*9600*2);
dallegre 0:c12e968e5b60 152 wait(.1);
dallegre 0:c12e968e5b60 153
dallegre 0:c12e968e5b60 154 //do I2C transfter to initialize codec
dallegre 0:c12e968e5b60 155 codecInit();
dallegre 0:c12e968e5b60 156
dallegre 0:c12e968e5b60 157 //initialize fixed filters
dallegre 0:c12e968e5b60 158 double feedbackCutoff = 10.0/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 159 feedbackFilter.setFc(feedbackCutoff);
dallegre 0:c12e968e5b60 160 double lengthCutoff = 3.0/(SAMPLINGFREQ*1000);
dallegre 0:c12e968e5b60 161 lengthFilter.setFc(lengthCutoff);
dallegre 0:c12e968e5b60 162
dallegre 0:c12e968e5b60 163 //initialize audio filter
dallegre 0:c12e968e5b60 164 double audioCutoff = LPdampingFreq/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 165 audioFilter.setFc(audioCutoff);
dallegre 0:c12e968e5b60 166 audioCutoff = HPdampingFreq/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 167 audioFilterHP.setFc(audioCutoff);
dallegre 0:c12e968e5b60 168
dallegre 0:c12e968e5b60 169 //set up I2S
dallegre 0:c12e968e5b60 170 spi.frequency(8e6*2); //8MHz spi. This is fast enough for 88KHz 16 bit sampling.
dallegre 0:c12e968e5b60 171 spi.format(16,0); //16 bit. clock polarity 0, phase 0.
dallegre 0:c12e968e5b60 172 wait(.1);
dallegre 0:c12e968e5b60 173
dallegre 0:c12e968e5b60 174 //audio rate timers. 29 and 44 are not very good. Might want to use an external clock for the Nucleo.
dallegre 0:c12e968e5b60 175 if(SAMPLINGFREQ == 22)
dallegre 0:c12e968e5b60 176 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 177 if(SAMPLINGFREQ == 29)
dallegre 0:c12e968e5b60 178 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 179 if(SAMPLINGFREQ == 44)
dallegre 0:c12e968e5b60 180 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 181 if(SAMPLINGFREQ == 88)
dallegre 0:c12e968e5b60 182 timer.attach(&I2S_send,8e-6); //88KHz sampling. Need to calculate.
dallegre 0:c12e968e5b60 183
dallegre 0:c12e968e5b60 184 //control signal timer
dallegre 0:c12e968e5b60 185 timer2.attach(&analog_read,25e-3);
dallegre 0:c12e968e5b60 186
dallegre 0:c12e968e5b60 187 //go!
dallegre 0:c12e968e5b60 188 while(1){}
dallegre 0:c12e968e5b60 189 }