Dan Allegre / 401_reverb

Dependencies:   mbed

Revision:
0:c12e968e5b60
Child:
1:a4ce08417c60
diff -r 000000000000 -r c12e968e5b60 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jun 23 06:22:47 2015 +0000
@@ -0,0 +1,153 @@
+//delay dsp for stm32f401re nucleo board with openmusiclabs audio codec shield.  Need to jumpter the i2c pins from the 
+//top right arduino headers on the nucleo board to the bottom left 2 pins on the codec shield.  Bottom left i2c pins are
+//not mbed enabled on the nucleo boards. 
+//Also need to install a 11.2896MHz crystal on nucleo board and connect the appropriate jumpers as explained in the nucleo
+//user manual.  Two 20pf capacitors are used with the crystal.  The series resistors going from the crystal to the stm32 chip
+//are just shorts.   
+//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
+//blocking cap after the op amp.
+//Note that this is setup for the left input only and drives both outputs.  It is easy to modify the code for stereo effects
+//and both inputs.  
+
+//June 2015..
+//Added interpolation so it acts more like a bbd or tape delay.  It is easy to switch between cosine and linear interpolation.
+//Cubic interpolation might be a possibility if I can figure out how it works.
+//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.
+
+#define DELAYLEN        11500       //24,000 is about as far as you can go in the ram.
+#define SAMPLINGFREQ    22          //roughly the smapling frequency in KHz.  options are 22,29,44,88 for 22khz,29khz,etc..
+
+#include "mbed.h"
+#include "dsp.h" 
+#include "codec.h"
+ 
+SPI spi(SPI_MOSI,SPI_MISO,SPI_SCK);
+Ticker timer;
+Ticker timer2;
+AnalogIn analog_value(A1);          //delay time pot
+AnalogIn analog_value2(A0);         //feedback amount pot
+DigitalOut cs(D10);
+
+int left_out = 0, right_out = 0, left_out_u = 0, right_out_u = 0, left_in = 0, right_in = 0,
+index1 = 0, index2 = (DELAYLEN*0.99), index3 = (DELAYLEN*0.99);
+uint16_t left_in_u = 0, meas = 0, measprev = 0;
+float left_in_f = 0, feedback = 0, feedback2 = 0, feedback3 = 0, offset = 10.0,
+meas2f = 0.5, measf = 0, measf2 = 0, measf3 = 0, left_out_f = 0, right_out_f = 0;
+float audioFeedbackRight,audioFeedbackLeft;
+
+float LPdampingFreq = 11000, HPdampingFreq = 100;  //some parameters you might want to adjust.
+int   LPdampingPoles = 2, HPdampingPoles = 0;       //I don't think the highpass is quite working.
+
+OnePoleLp audioFilter;                          //might use this as a mor thorough DC offset removal tool.  Not yet implemented.
+OnePoleHp audioFilterHP;
+OnePoleLp feedbackFilter;
+OnePoleLp lengthFilter;
+Delay delayLeft;
+Delay delayRight;
+
+void I2S_send(void){
+    cs.write(0);                                //0 for left output
+    left_in = spi.write(left_out);
+    cs.write(1);                                //1 for right output
+    right_in = spi.write(right_out);
+    
+    left_in_f = intToFloat(left_in);
+    
+    /////////////////////////////////////////dsp part//////////////////////////////////////////////////////////////////////
+        
+    //process control signals
+    feedback2 = feedbackFilter.process(feedback);
+    feedback3 = feedbackFilter.process(feedback2);
+    //update delay times with every audio sample if you're going to filter them.
+    measf2 = lengthFilter.process(measf);
+    measf3 = lengthFilter.process(measf2);
+    measf3 *= (DELAYLEN);                       //convert to delay index normalization
+
+    //process audio
+    ///*
+    //*/
+    left_out_f = delayLeft.process(left_in_f,audioFeedbackRight*feedback3,measf3);
+    right_out_f = delayRight.process(left_in_f,audioFeedbackLeft*feedback3,measf3+offset);     //add an offset in just for shits.
+    left_out_u = satAdd(left_in_f,left_out_f);
+    right_out_u = satAdd(left_in_f,right_out_f);
+    
+    //a little damping of the feedback
+    audioFeedbackRight =  audioFilter.process(right_out_f);
+    for(int i = 0; i < LPdampingPoles - 1; i++){
+        audioFeedbackRight =  audioFilter.process(audioFeedbackRight);
+    }
+    for(int i = 0; i < HPdampingPoles; i++){
+        audioFeedbackRight =  audioFilterHP.process(audioFeedbackRight);
+    }
+    audioFeedbackLeft =   audioFilter.process(left_out_f);
+    for(int i = 0; i < LPdampingPoles - 1; i++){    
+        audioFeedbackLeft =   audioFilter.process(audioFeedbackLeft);
+    }
+    for(int i = 0; i < HPdampingPoles; i++){    
+        audioFeedbackLeft =  audioFilterHP.process(audioFeedbackLeft);
+    }
+
+    /////////////////////////////////////////end of dsp part/////////////////////////////////////////////////////////////////
+    
+    left_out = unsignedToSigned(left_out_u);
+    right_out = unsignedToSigned(right_out_u);
+
+}
+
+void analog_read(void){
+    //this is the stuff for the feedback amount pot
+    meas2f = analog_value2.read_u16();          //converts unint16 value to float
+    feedback = meas2f/4100;                     //now you have a value between 0 and 1 that will control the feedback amount.
+    
+    //this is the stuff for the delay time pot
+    meas = 4096 - analog_value.read_u16();      //values go from 1 to 4095
+    //if(abs(meas - measprev) > 5){
+        measprev = meas;
+        measf = meas;
+        measf /= 4200;                              //this number took some tweaking.
+        measf *= measf;
+    //}
+}
+
+int main(){
+    
+    //set up baud rate for 11.2MHz crystal
+    pc.baud(.7*9600*2);
+    wait(.1);
+    
+    //do I2C transfter to initialize codec
+    codecInit();
+    
+    //initialize fixed filters
+    double feedbackCutoff = 10.0/(SAMPLINGFREQ*1000);       //adjust these cutoffs according to taste.
+    feedbackFilter.setFc(feedbackCutoff);
+    double lengthCutoff = 3.0/(SAMPLINGFREQ*1000);
+    lengthFilter.setFc(lengthCutoff);
+    
+    //initialize audio filter
+    double audioCutoff = LPdampingFreq/(SAMPLINGFREQ*1000);       //adjust these cutoffs according to taste.
+    audioFilter.setFc(audioCutoff);
+    audioCutoff = HPdampingFreq/(SAMPLINGFREQ*1000);       //adjust these cutoffs according to taste.
+    audioFilterHP.setFc(audioCutoff);
+
+    //set up I2S
+    spi.frequency(8e6*2);                         //8MHz spi.  This is fast enough for 88KHz 16 bit sampling.
+    spi.format(16,0);                           //16 bit.  clock polarity 0, phase 0.
+    wait(.1);
+    
+    //audio rate timers.   29 and 44 are not very good.  Might want to use an external clock for the Nucleo.  
+    if(SAMPLINGFREQ == 22)
+        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.
+    if(SAMPLINGFREQ == 29)
+        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.
+    if(SAMPLINGFREQ == 44)    
+        timer.attach(&I2S_send,16.0e-6);        //44.1KHz sampling.         almost exactly 32e-6 and then divide by 2.  Doesn't sound right yet.
+    if(SAMPLINGFREQ == 88)
+        timer.attach(&I2S_send,8e-6);       //88KHz sampling.   Need to calculate.
+    
+    //control signal timer
+    timer2.attach(&analog_read,25e-3);
+    
+    //go!
+    while(1){}
+}
\ No newline at end of file