Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
dsp.h@1:a4ce08417c60, 2016-07-30 (annotated)
- Committer:
- dallegre
- Date:
- Sat Jul 30 02:21:09 2016 +0000
- Revision:
- 1:a4ce08417c60
- Parent:
- 0:c12e968e5b60
made it into an allpass delay program
Who changed what in which revision?
| User | Revision | Line number | New 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 | index1 = 0; |
| dallegre | 0:c12e968e5b60 | 105 | index2 = DELAYLEN*.99; |
| dallegre | 0:c12e968e5b60 | 106 | for(int i = 0; i <= DELAYLEN; i++){ |
| dallegre | 0:c12e968e5b60 | 107 | buffer[i] = 0; |
| dallegre | 0:c12e968e5b60 | 108 | } |
| dallegre | 0:c12e968e5b60 | 109 | }; |
| dallegre | 0:c12e968e5b60 | 110 | void setLength(float length); |
| dallegre | 0:c12e968e5b60 | 111 | float process(float in, float fbin, float length); |
| dallegre | 0:c12e968e5b60 | 112 | protected: |
| dallegre | 0:c12e968e5b60 | 113 | float buffer[DELAYLEN]; |
| dallegre | 0:c12e968e5b60 | 114 | int index1, index2, intlength; |
| dallegre | 0:c12e968e5b60 | 115 | float fraclength, out; |
| dallegre | 0:c12e968e5b60 | 116 | }; |
| dallegre | 0:c12e968e5b60 | 117 | inline float Delay::process(float in, float fbin, float length){ |
| dallegre | 0:c12e968e5b60 | 118 | //update index values |
| dallegre | 0:c12e968e5b60 | 119 | index1++; |
| dallegre | 0:c12e968e5b60 | 120 | index2++; |
| dallegre | 0:c12e968e5b60 | 121 | if(index1 >= (DELAYLEN)) |
| dallegre | 0:c12e968e5b60 | 122 | index1 = 0; |
| dallegre | 0:c12e968e5b60 | 123 | if(index2 >= (DELAYLEN)) |
| dallegre | 0:c12e968e5b60 | 124 | index2 = 0; |
| dallegre | 0:c12e968e5b60 | 125 | |
| dallegre | 0:c12e968e5b60 | 126 | //separate length into integer and fractional parts for interpolation |
| dallegre | 0:c12e968e5b60 | 127 | intlength = length; |
| dallegre | 0:c12e968e5b60 | 128 | fraclength = length - intlength; |
| dallegre | 0:c12e968e5b60 | 129 | |
| dallegre | 0:c12e968e5b60 | 130 | //update indices based on delay length |
| dallegre | 0:c12e968e5b60 | 131 | index2 = index1 + intlength; |
| dallegre | 0:c12e968e5b60 | 132 | if(index2 >= DELAYLEN) |
| dallegre | 0:c12e968e5b60 | 133 | index2 = index1 + intlength - DELAYLEN; |
| dallegre | 0:c12e968e5b60 | 134 | |
| dallegre | 0:c12e968e5b60 | 135 | //write to delay buffer |
| dallegre | 1:a4ce08417c60 | 136 | buffer[index1] = satAdd(in,fbin); |
| dallegre | 0:c12e968e5b60 | 137 | |
| dallegre | 0:c12e968e5b60 | 138 | //read the delays out of the delay array. do some crazy interpolation stuff. |
| dallegre | 0:c12e968e5b60 | 139 | if(index2+1 < DELAYLEN){ |
| dallegre | 0:c12e968e5b60 | 140 | out = linterp(buffer[index2],buffer[index2+1],fraclength); //worry about the converion from float to uint outside of this. |
| dallegre | 0:c12e968e5b60 | 141 | }else{ |
| dallegre | 0:c12e968e5b60 | 142 | out = buffer[index2]; //probably just want to take the output of the delay and not the dry. |
| dallegre | 0:c12e968e5b60 | 143 | } |
| dallegre | 0:c12e968e5b60 | 144 | return out; |
| dallegre | 1:a4ce08417c60 | 145 | } |