Dan Allegre / 401_reverb

Dependencies:   mbed

Committer:
dallegre
Date:
Tue Jun 23 06:22:47 2015 +0000
Revision:
0:c12e968e5b60
Child:
1:a4ce08417c60
working audio delay with large array as sram buffer.  doesn't work with mbed library revision 89 or later.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dallegre 0:c12e968e5b60 1 //Header including the saturating math functions. Also includes signed to unsigned and unsigned to signed integer conversion
dallegre 0:c12e968e5b60 2 //functions.
dallegre 0:c12e968e5b60 3
dallegre 0:c12e968e5b60 4 #define MIN -15000.0f //so you don't get negative vlaues because the stuff is in unsigned format
dallegre 0:c12e968e5b60 5 #define MAX 15000.0f //limit at maximum 16 bit value so it doesn't wrap around
dallegre 0:c12e968e5b60 6
dallegre 0:c12e968e5b60 7 //saturation addition
dallegre 0:c12e968e5b60 8 float satSubtract(float x, float y){ //x - y
dallegre 0:c12e968e5b60 9 if(x < (MIN + y)) //if((x - y) < MIN), add y to both sides to yields if(x < (MIN + y))
dallegre 0:c12e968e5b60 10 return MIN;
dallegre 0:c12e968e5b60 11 if(-y > (MAX - x)) //if((x - y) > MAX), subtract x from both sides to yield if(-y > (MAX - x))
dallegre 0:c12e968e5b60 12 return MAX;
dallegre 0:c12e968e5b60 13 return (x - y); //if it's not limiting then just return x - y
dallegre 0:c12e968e5b60 14 }
dallegre 0:c12e968e5b60 15
dallegre 0:c12e968e5b60 16 //saturation subtraction
dallegre 0:c12e968e5b60 17 float satAdd(float x, float y){ //x + y
dallegre 0:c12e968e5b60 18 if(x < (MIN - y)) //if((x + y) < MIN)
dallegre 0:c12e968e5b60 19 return MIN;
dallegre 0:c12e968e5b60 20 if(x > (MAX - y)) //if((x + y) > MAX)
dallegre 0:c12e968e5b60 21 return MAX;
dallegre 0:c12e968e5b60 22 return (x + y); //if it's not limiting then just return x + y
dallegre 0:c12e968e5b60 23 }
dallegre 0:c12e968e5b60 24
dallegre 0:c12e968e5b60 25 //signed to unsigned integer conversion
dallegre 0:c12e968e5b60 26 float intToFloat(int input){
dallegre 0:c12e968e5b60 27 uint16_t output = 0;
dallegre 0:c12e968e5b60 28 float output_f = 0;
dallegre 0:c12e968e5b60 29 if(0x8000 && input){
dallegre 0:c12e968e5b60 30 output = input - 0x8000; //then it's a negative number
dallegre 0:c12e968e5b60 31 }else{
dallegre 0:c12e968e5b60 32 output = input + 0x8000; //then it's a postive number
dallegre 0:c12e968e5b60 33 }
dallegre 0:c12e968e5b60 34 output_f = output/2.0;
dallegre 0:c12e968e5b60 35 output_f -= 32768.0/2.0; //remove DC offsset from signed to unsigned conversion.
dallegre 0:c12e968e5b60 36 output_f *= float(2.0); //amplify a little.
dallegre 0:c12e968e5b60 37 return output_f;
dallegre 0:c12e968e5b60 38 }
dallegre 0:c12e968e5b60 39
dallegre 0:c12e968e5b60 40 //unsigned to signed integer conversion
dallegre 0:c12e968e5b60 41 int unsignedToSigned(int input){
dallegre 0:c12e968e5b60 42 int output = 0;
dallegre 0:c12e968e5b60 43 if(input >= 0x8000) //then convert it to a positive signed numbber
dallegre 0:c12e968e5b60 44 output = ((input >> 1) & 0x7FFF);
dallegre 0:c12e968e5b60 45 if(input < 0x8000)
dallegre 0:c12e968e5b60 46 output = input + 0x8000;
dallegre 0:c12e968e5b60 47 return output + 32768/2;
dallegre 0:c12e968e5b60 48 }
dallegre 0:c12e968e5b60 49
dallegre 0:c12e968e5b60 50 //these ideas taken from paulbourke.net/miscellaneous/interpolation/
dallegre 0:c12e968e5b60 51 //linear
dallegre 0:c12e968e5b60 52 float linterp(float y1, float y2, float frac){
dallegre 0:c12e968e5b60 53 return(y1*(1-frac) + y2*frac);
dallegre 0:c12e968e5b60 54 }
dallegre 0:c12e968e5b60 55 //cosine
dallegre 0:c12e968e5b60 56 float cosinterp(float y1, float y2, float frac){
dallegre 0:c12e968e5b60 57 float frac2;
dallegre 0:c12e968e5b60 58 frac2 = (1 - cos(frac*float(3.14159)))/2;
dallegre 0:c12e968e5b60 59 return(y1*(1-frac2) + y2*frac2);
dallegre 0:c12e968e5b60 60 }
dallegre 0:c12e968e5b60 61
dallegre 0:c12e968e5b60 62 //1 pole lowpass filter from ear level engineering's website
dallegre 0:c12e968e5b60 63 #include <math.h>
dallegre 0:c12e968e5b60 64 class OnePoleLp {
dallegre 0:c12e968e5b60 65 public:
dallegre 0:c12e968e5b60 66 OnePoleLp() {a0 = 1.0; b1 = 0.0; z1 = 0.0;};
dallegre 0:c12e968e5b60 67 OnePoleLp(float Fc) {z1 = 0.0; setFc(Fc);};
dallegre 0:c12e968e5b60 68 //~OnePole();
dallegre 0:c12e968e5b60 69 void setFc(float Fc);
dallegre 0:c12e968e5b60 70 float process(float in);
dallegre 0:c12e968e5b60 71 protected:
dallegre 0:c12e968e5b60 72 float a0, b1, z1;
dallegre 0:c12e968e5b60 73 };
dallegre 0:c12e968e5b60 74 inline void OnePoleLp::setFc(float Fc) {
dallegre 0:c12e968e5b60 75 b1 = exp(-2.0 * 3.14159 * Fc);
dallegre 0:c12e968e5b60 76 a0 = float(1.0) - b1;
dallegre 0:c12e968e5b60 77 }
dallegre 0:c12e968e5b60 78 inline float OnePoleLp::process(float in) {
dallegre 0:c12e968e5b60 79 return z1 = in * a0 + z1 * b1;
dallegre 0:c12e968e5b60 80 }
dallegre 0:c12e968e5b60 81 //1 pole highpass filter
dallegre 0:c12e968e5b60 82 class OnePoleHp {
dallegre 0:c12e968e5b60 83 public:
dallegre 0:c12e968e5b60 84 OnePoleHp() {a0 = 1.0; b1 = 0.0; z1 = 0.0;};
dallegre 0:c12e968e5b60 85 OnePoleHp(float Fc) {z1 = 0.0; setFc(Fc);};
dallegre 0:c12e968e5b60 86 //~OnePole();
dallegre 0:c12e968e5b60 87 void setFc(float Fc);
dallegre 0:c12e968e5b60 88 float process(float in);
dallegre 0:c12e968e5b60 89 protected:
dallegre 0:c12e968e5b60 90 float a0, b1, z1;
dallegre 0:c12e968e5b60 91 };
dallegre 0:c12e968e5b60 92 inline void OnePoleHp::setFc(float Fc) {
dallegre 0:c12e968e5b60 93 b1 = -exp(-2.0 * 3.14159 * (float(0.5) - Fc));
dallegre 0:c12e968e5b60 94 a0 = float(1.0) + b1;
dallegre 0:c12e968e5b60 95 }
dallegre 0:c12e968e5b60 96 inline float OnePoleHp::process(float in) {
dallegre 0:c12e968e5b60 97 return z1 = in * a0 + z1 * b1;
dallegre 0:c12e968e5b60 98 }
dallegre 0:c12e968e5b60 99
dallegre 0:c12e968e5b60 100 //make a delay class
dallegre 0:c12e968e5b60 101 class Delay {
dallegre 0:c12e968e5b60 102 public:
dallegre 0:c12e968e5b60 103 Delay() {
dallegre 0:c12e968e5b60 104 //buffer[DELAYLEN] = {0};
dallegre 0:c12e968e5b60 105 index1 = 0;
dallegre 0:c12e968e5b60 106 index2 = DELAYLEN*.99;
dallegre 0:c12e968e5b60 107 for(int i = 0; i <= DELAYLEN; i++){
dallegre 0:c12e968e5b60 108 buffer[i] = 0;
dallegre 0:c12e968e5b60 109 }
dallegre 0:c12e968e5b60 110 };
dallegre 0:c12e968e5b60 111 //~Delay();
dallegre 0:c12e968e5b60 112 void setLength(float length);
dallegre 0:c12e968e5b60 113 float process(float in, float fbin, float length);
dallegre 0:c12e968e5b60 114 protected:
dallegre 0:c12e968e5b60 115 float buffer[DELAYLEN];
dallegre 0:c12e968e5b60 116 int index1, index2, intlength;
dallegre 0:c12e968e5b60 117 float fraclength, out;
dallegre 0:c12e968e5b60 118 };
dallegre 0:c12e968e5b60 119 inline float Delay::process(float in, float fbin, float length){
dallegre 0:c12e968e5b60 120
dallegre 0:c12e968e5b60 121 //update index values
dallegre 0:c12e968e5b60 122 index1++;
dallegre 0:c12e968e5b60 123 index2++;
dallegre 0:c12e968e5b60 124 if(index1 >= (DELAYLEN))
dallegre 0:c12e968e5b60 125 index1 = 0;
dallegre 0:c12e968e5b60 126 if(index2 >= (DELAYLEN))
dallegre 0:c12e968e5b60 127 index2 = 0;
dallegre 0:c12e968e5b60 128
dallegre 0:c12e968e5b60 129 //separate length into integer and fractional parts for interpolation
dallegre 0:c12e968e5b60 130 intlength = length;
dallegre 0:c12e968e5b60 131 fraclength = length - intlength;
dallegre 0:c12e968e5b60 132
dallegre 0:c12e968e5b60 133 //update indices based on delay length
dallegre 0:c12e968e5b60 134 index2 = index1 + intlength;
dallegre 0:c12e968e5b60 135 if(index2 >= DELAYLEN)
dallegre 0:c12e968e5b60 136 index2 = index1 + intlength - DELAYLEN;
dallegre 0:c12e968e5b60 137
dallegre 0:c12e968e5b60 138 //write to delay buffer
dallegre 0:c12e968e5b60 139 buffer[index1] = satSubtract(in,fbin);
dallegre 0:c12e968e5b60 140
dallegre 0:c12e968e5b60 141 //read the delays out of the delay array. do some crazy interpolation stuff.
dallegre 0:c12e968e5b60 142 if(index2+1 < DELAYLEN){
dallegre 0:c12e968e5b60 143 out = linterp(buffer[index2],buffer[index2+1],fraclength); //worry about the converion from float to uint outside of this.
dallegre 0:c12e968e5b60 144 }else{
dallegre 0:c12e968e5b60 145 out = buffer[index2]; //probably just want to take the output of the delay and not the dry.
dallegre 0:c12e968e5b60 146 }
dallegre 0:c12e968e5b60 147 return out;
dallegre 0:c12e968e5b60 148 }