Dan Allegre / 401_reverb

Dependencies:   mbed

Committer:
dallegre
Date:
Sat Jul 30 02:21:09 2016 +0000
Revision:
1:a4ce08417c60
Parent:
0:c12e968e5b60
Child:
2:1b50325e256f
made it into an allpass delay program

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 0:c12e968e5b60 17 #define DELAYLEN 11500 //24,000 is about as far as you can go in the ram.
dallegre 0:c12e968e5b60 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 0:c12e968e5b60 24
dallegre 0:c12e968e5b60 25 SPI spi(SPI_MOSI,SPI_MISO,SPI_SCK);
dallegre 0:c12e968e5b60 26 Ticker timer;
dallegre 0:c12e968e5b60 27 Ticker timer2;
dallegre 0:c12e968e5b60 28 AnalogIn analog_value(A1); //delay time pot
dallegre 0:c12e968e5b60 29 AnalogIn analog_value2(A0); //feedback amount pot
dallegre 0:c12e968e5b60 30 DigitalOut cs(D10);
dallegre 0:c12e968e5b60 31
dallegre 0:c12e968e5b60 32 int left_out = 0, right_out = 0, left_out_u = 0, right_out_u = 0, left_in = 0, right_in = 0,
dallegre 0:c12e968e5b60 33 index1 = 0, index2 = (DELAYLEN*0.99), index3 = (DELAYLEN*0.99);
dallegre 0:c12e968e5b60 34 uint16_t left_in_u = 0, meas = 0, measprev = 0;
dallegre 0:c12e968e5b60 35 float left_in_f = 0, feedback = 0, feedback2 = 0, feedback3 = 0, offset = 10.0,
dallegre 0:c12e968e5b60 36 meas2f = 0.5, measf = 0, measf2 = 0, measf3 = 0, left_out_f = 0, right_out_f = 0;
dallegre 0:c12e968e5b60 37 float audioFeedbackRight,audioFeedbackLeft;
dallegre 0:c12e968e5b60 38
dallegre 0:c12e968e5b60 39 float LPdampingFreq = 11000, HPdampingFreq = 100; //some parameters you might want to adjust.
dallegre 0:c12e968e5b60 40 int LPdampingPoles = 2, HPdampingPoles = 0; //I don't think the highpass is quite working.
dallegre 0:c12e968e5b60 41
dallegre 0:c12e968e5b60 42 OnePoleLp audioFilter; //might use this as a mor thorough DC offset removal tool. Not yet implemented.
dallegre 0:c12e968e5b60 43 OnePoleHp audioFilterHP;
dallegre 0:c12e968e5b60 44 OnePoleLp feedbackFilter;
dallegre 0:c12e968e5b60 45 OnePoleLp lengthFilter;
dallegre 1:a4ce08417c60 46 AllPass delayLeft;
dallegre 1:a4ce08417c60 47 AllPass delayRight;
dallegre 0:c12e968e5b60 48
dallegre 0:c12e968e5b60 49 void I2S_send(void){
dallegre 0:c12e968e5b60 50 cs.write(0); //0 for left output
dallegre 0:c12e968e5b60 51 left_in = spi.write(left_out);
dallegre 0:c12e968e5b60 52 cs.write(1); //1 for right output
dallegre 0:c12e968e5b60 53 right_in = spi.write(right_out);
dallegre 0:c12e968e5b60 54
dallegre 0:c12e968e5b60 55 left_in_f = intToFloat(left_in);
dallegre 0:c12e968e5b60 56
dallegre 0:c12e968e5b60 57 /////////////////////////////////////////dsp part//////////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 58
dallegre 0:c12e968e5b60 59 //process control signals
dallegre 0:c12e968e5b60 60 feedback2 = feedbackFilter.process(feedback);
dallegre 0:c12e968e5b60 61 feedback3 = feedbackFilter.process(feedback2);
dallegre 0:c12e968e5b60 62 //update delay times with every audio sample if you're going to filter them.
dallegre 0:c12e968e5b60 63 measf2 = lengthFilter.process(measf);
dallegre 0:c12e968e5b60 64 measf3 = lengthFilter.process(measf2);
dallegre 0:c12e968e5b60 65 measf3 *= (DELAYLEN); //convert to delay index normalization
dallegre 0:c12e968e5b60 66
dallegre 0:c12e968e5b60 67 //process audio
dallegre 1:a4ce08417c60 68 left_out_f = delayLeft.process(left_in_f,feedback3,measf3);
dallegre 1:a4ce08417c60 69 right_out_f = delayRight.process(left_in_f,feedback3,measf3+offset); //add an offset in just for shits.
dallegre 0:c12e968e5b60 70 left_out_u = satAdd(left_in_f,left_out_f);
dallegre 0:c12e968e5b60 71 right_out_u = satAdd(left_in_f,right_out_f);
dallegre 0:c12e968e5b60 72
dallegre 0:c12e968e5b60 73 /////////////////////////////////////////end of dsp part/////////////////////////////////////////////////////////////////
dallegre 0:c12e968e5b60 74
dallegre 0:c12e968e5b60 75 left_out = unsignedToSigned(left_out_u);
dallegre 0:c12e968e5b60 76 right_out = unsignedToSigned(right_out_u);
dallegre 0:c12e968e5b60 77
dallegre 0:c12e968e5b60 78 }
dallegre 0:c12e968e5b60 79
dallegre 0:c12e968e5b60 80 void analog_read(void){
dallegre 0:c12e968e5b60 81 //this is the stuff for the feedback amount pot
dallegre 0:c12e968e5b60 82 meas2f = analog_value2.read_u16(); //converts unint16 value to float
dallegre 0:c12e968e5b60 83 feedback = meas2f/4100; //now you have a value between 0 and 1 that will control the feedback amount.
dallegre 0:c12e968e5b60 84
dallegre 0:c12e968e5b60 85 //this is the stuff for the delay time pot
dallegre 0:c12e968e5b60 86 meas = 4096 - analog_value.read_u16(); //values go from 1 to 4095
dallegre 0:c12e968e5b60 87 //if(abs(meas - measprev) > 5){
dallegre 0:c12e968e5b60 88 measprev = meas;
dallegre 0:c12e968e5b60 89 measf = meas;
dallegre 0:c12e968e5b60 90 measf /= 4200; //this number took some tweaking.
dallegre 0:c12e968e5b60 91 measf *= measf;
dallegre 0:c12e968e5b60 92 //}
dallegre 0:c12e968e5b60 93 }
dallegre 0:c12e968e5b60 94
dallegre 0:c12e968e5b60 95 int main(){
dallegre 0:c12e968e5b60 96
dallegre 0:c12e968e5b60 97 //set up baud rate for 11.2MHz crystal
dallegre 0:c12e968e5b60 98 pc.baud(.7*9600*2);
dallegre 0:c12e968e5b60 99 wait(.1);
dallegre 0:c12e968e5b60 100
dallegre 0:c12e968e5b60 101 //do I2C transfter to initialize codec
dallegre 0:c12e968e5b60 102 codecInit();
dallegre 0:c12e968e5b60 103
dallegre 0:c12e968e5b60 104 //initialize fixed filters
dallegre 0:c12e968e5b60 105 double feedbackCutoff = 10.0/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 106 feedbackFilter.setFc(feedbackCutoff);
dallegre 0:c12e968e5b60 107 double lengthCutoff = 3.0/(SAMPLINGFREQ*1000);
dallegre 0:c12e968e5b60 108 lengthFilter.setFc(lengthCutoff);
dallegre 0:c12e968e5b60 109
dallegre 0:c12e968e5b60 110 //initialize audio filter
dallegre 0:c12e968e5b60 111 double audioCutoff = LPdampingFreq/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 112 audioFilter.setFc(audioCutoff);
dallegre 0:c12e968e5b60 113 audioCutoff = HPdampingFreq/(SAMPLINGFREQ*1000); //adjust these cutoffs according to taste.
dallegre 0:c12e968e5b60 114 audioFilterHP.setFc(audioCutoff);
dallegre 0:c12e968e5b60 115
dallegre 0:c12e968e5b60 116 //set up I2S
dallegre 0:c12e968e5b60 117 spi.frequency(8e6*2); //8MHz spi. This is fast enough for 88KHz 16 bit sampling.
dallegre 0:c12e968e5b60 118 spi.format(16,0); //16 bit. clock polarity 0, phase 0.
dallegre 0:c12e968e5b60 119 wait(.1);
dallegre 0:c12e968e5b60 120
dallegre 0:c12e968e5b60 121 //audio rate timers. 29 and 44 are not very good. Might want to use an external clock for the Nucleo.
dallegre 0:c12e968e5b60 122 if(SAMPLINGFREQ == 22)
dallegre 0:c12e968e5b60 123 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 124 if(SAMPLINGFREQ == 29)
dallegre 0:c12e968e5b60 125 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 126 if(SAMPLINGFREQ == 44)
dallegre 0:c12e968e5b60 127 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 128 if(SAMPLINGFREQ == 88)
dallegre 0:c12e968e5b60 129 timer.attach(&I2S_send,8e-6); //88KHz sampling. Need to calculate.
dallegre 0:c12e968e5b60 130
dallegre 0:c12e968e5b60 131 //control signal timer
dallegre 0:c12e968e5b60 132 timer2.attach(&analog_read,25e-3);
dallegre 0:c12e968e5b60 133
dallegre 0:c12e968e5b60 134 //go!
dallegre 0:c12e968e5b60 135 while(1){}
dallegre 0:c12e968e5b60 136 }