diff --git a/AudioDelayFeedback.h b/AudioDelayFeedback.h index 5aac25b28..f34b943b1 100644 --- a/AudioDelayFeedback.h +++ b/AudioDelayFeedback.h @@ -37,6 +37,8 @@ template ::signed_type return_type; + public: /** Constructor. */ @@ -69,7 +71,7 @@ class AudioDelayFeedback @note slower than next(int8_t input, uint16_t delaytime_cells) */ inline - typename IntegerType::signed_type next(su input) + return_type next(su input) { // chooses a different next() function depending on whether the // the template parameter is LINEAR(default if none provided) or ALLPASS. @@ -86,24 +88,24 @@ class AudioDelayFeedback @note Timing: 4us */ inline - typename IntegerType::signed_type next(su input, uint16_t delaytime_cells) + return_type next(su input, uint16_t delaytime_cells) { //setPin13High(); ++write_pos &= (NUM_BUFFER_SAMPLES - 1); uint16_t read_pos = (write_pos - delaytime_cells) & (NUM_BUFFER_SAMPLES - 1); // < 1us to here - IntegerType::signed_type delay_sig = delay_array[read_pos]; // read the delay buffer + return_type delay_sig = delay_array[read_pos]; // read the delay buffer // with this line, the method takes 18us //int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)/128),-128),127); // feedback clipped // this line, the whole method takes 4us... Compiler doesn't optimise pow2 divides. Why? //int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)>>7),-128),127); // feedback clipped - su feedback_sig = (su) constrain( ((delay_sig * feedback_level)>>7), (1<<((sizeof(su)<<3)-1))-1, -(1<<((sizeof(su)<<3)-1))); - delay_array[write_pos] = (IntegerType::signed_type) input + feedback_sig; // write to buffer + su feedback_sig = (su) constrain( ((delay_sig * _feedback_level)>>7), (1<<((sizeof(su)<<3)-1))-1, -(1<<((sizeof(su)<<3)-1))); + delay_array[write_pos] = (return_type) input + feedback_sig; // write to buffer //setPin13Low(); return delay_sig; } - ///////// STOPPED HERE FOR NOW + /** Input a value to the delay, retrieve the signal in the delay line at the interpolated fractional position delaytime_cells, and add feedback from the output to the input. @param input the signal input. @@ -112,7 +114,7 @@ class AudioDelayFeedback value of _delaytime_cells. */ inline - int16_t next(int8_t input, Q16n16 delaytime_cells) + return_type next(su input, Q16n16 delaytime_cells) { //setPin13High(); ++write_pos &= (NUM_BUFFER_SAMPLES - 1); @@ -121,21 +123,23 @@ class AudioDelayFeedback uint16_t fraction = (uint16_t) delaytime_cells; // keeps low word uint16_t read_pos1 = (write_pos - index) & (NUM_BUFFER_SAMPLES - 1); - int16_t delay_sig1 = delay_array[read_pos1]; // read the delay buffer + return_type delay_sig1 = delay_array[read_pos1]; // read the delay buffer uint16_t read_pos2 = (write_pos - (index+1)) & (NUM_BUFFER_SAMPLES - 1); - int16_t delay_sig2 = delay_array[read_pos2]; // read the delay buffer + return_type delay_sig2 = delay_array[read_pos2]; // read the delay buffer - int16_t difference = delay_sig2 - delay_sig1; - int16_t delay_sig_fraction = (int16_t)((int32_t)((int32_t) fraction * difference) >> 16); + return_type difference = delay_sig2 - delay_sig1; + //int16_t delay_sig_fraction = (int16_t)((int32_t)((int32_t) fraction * difference) >> 16); + return_type delay_sig_fraction = (return_type) ((typename IntegerType::signed_type)fraction * difference) >> 16; - int16_t delay_sig = delay_sig1+delay_sig_fraction; + return_type delay_sig = delay_sig1+delay_sig_fraction; //int16_t delay_sig = delay_sig1 + ((int32_t)delay_sig2*fraction)>>16; - int8_t feedback_sig = (int8_t) min(max((((int16_t)(delay_sig * _feedback_level))>>7),-128),127); // feedback clipped - delay_array[write_pos] = (int16_t) input + feedback_sig; // write to buffer + //int8_t feedback_sig = (int8_t) min(max((((int16_t)(delay_sig * _feedback_level))>>7),-128),127); // feedback clipped + su feedback_sig = (su) constrain( ((delay_sig * _feedback_level)>>7), (1<<((sizeof(su)<<3)-1))-1, -(1<<((sizeof(su)<<3)-1))); + delay_array[write_pos] = (return_type) input + feedback_sig; // write to buffer //setPin13Low(); return delay_sig; } @@ -145,7 +149,7 @@ class AudioDelayFeedback @param input the signal input. */ inline - void write(int8_t input) + void write(su input) { ++write_pos &= (NUM_BUFFER_SAMPLES - 1); delay_array[write_pos] = input; @@ -157,7 +161,7 @@ class AudioDelayFeedback @param input the signal input. */ inline - void writeFeedback(int8_t input) + void writeFeedback(su input) { delay_array[write_pos] = input; } @@ -169,7 +173,7 @@ class AudioDelayFeedback @param offset the number of cells behind the ordinary write position where the input will be written. */ inline - void write(int8_t input, uint16_t offset) + void write(su input, uint16_t offset) { uint16_t _pos = (write_pos + offset) & (NUM_BUFFER_SAMPLES - 1); delay_array[_pos] = input; @@ -181,7 +185,7 @@ class AudioDelayFeedback @param delaytime_cells indicates the delay time in terms of cells in the delay buffer. */ inline - int16_t read(Q16n16 delaytime_cells) + return_type read(Q16n16 delaytime_cells) { return read(delaytime_cells, Int2Type()); } @@ -191,7 +195,7 @@ class AudioDelayFeedback It doesn't change the stored internal value of _delaytime_cells or feedback the output to the input. */ inline - int16_t read() + return_type read() { return read(Int2Type()); } @@ -245,11 +249,13 @@ class AudioDelayFeedback private: - int16_t delay_array[NUM_BUFFER_SAMPLES]; + return_type delay_array[NUM_BUFFER_SAMPLES]; uint16_t write_pos; int8_t _feedback_level; uint16_t _delaytime_cells; Q15n16 _coeff; // for allpass interpolation + su last_in; + return_type last_out; @@ -257,14 +263,15 @@ class AudioDelayFeedback @param in_value the signal input. */ inline - int16_t next(int8_t in_value, Int2Type) + return_type next(su in_value, Int2Type) { ++write_pos &= (NUM_BUFFER_SAMPLES - 1); uint16_t read_pos = (write_pos - _delaytime_cells) & (NUM_BUFFER_SAMPLES - 1); - int16_t delay_sig = delay_array[read_pos]; // read the delay buffer - int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)/128),-128),127); // feedback clipped - delay_array[write_pos] = (int16_t) in_value + feedback_sig; // write to buffer + return_type delay_sig = delay_array[read_pos]; // read the delay buffer + //int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)/128),-128),127); // feedback clipped + su feedback_sig = (su) constrain( ((delay_sig * _feedback_level)>>7), (1<<((sizeof(su)<<3)-1))-1, -(1<<((sizeof(su)<<3)-1))); + delay_array[write_pos] = (return_type) in_value + feedback_sig; // write to buffer return delay_sig; } @@ -279,7 +286,7 @@ class AudioDelayFeedback @note Timing: 10us */ inline - int16_t next(int8_t input, Int2Type) + return_type next(su input, Int2Type) { /* http://www.scandalis.com/Jarrah/Documents/DelayLine.pdf @@ -292,19 +299,24 @@ class AudioDelayFeedback = coeff * (in-last_out) + last_in */ //setPin13High(); + + /* I think these should **not** be static static int8_t last_in; static int16_t last_out; - + */ + ++write_pos &= (NUM_BUFFER_SAMPLES - 1); uint16_t read_pos1 = (write_pos - _delaytime_cells) & (NUM_BUFFER_SAMPLES - 1); - int16_t delay_sig = delay_array[read_pos1]; // read the delay buffer + return_type delay_sig = delay_array[read_pos1]; // read the delay buffer - int16_t interp = (int16_t)(_coeff * ((int16_t)input - last_out)>>16) + last_in; // Q15n16*Q15n0 + Q15n0 = Q15n16 + Q15n0 = Q15n16 + //int16_t interp = (int16_t)(_coeff * ((int16_t)input - last_out)>>16) + last_in; // Q15n16*Q15n0 + Q15n0 = Q15n16 + Q15n0 = Q15n16 + return_type interp = (return_type)(_coeff * ((return_type)input - last_out)>>(sizeof(su)<<4)) + last_in; delay_sig += interp; - int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)>>7),-128),127); // feedback clipped - delay_array[write_pos] = (int16_t) input + feedback_sig; // write to buffer + //int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)>>7),-128),127); // feedback clipped + su feedback_sig = (su) constrain( ((delay_sig * _feedback_level)>>7), (1<<((sizeof(su)<<3)-1))-1, -(1<<((sizeof(su)<<3)-1))); + delay_array[write_pos] = (return_type) input + feedback_sig; // write to buffer last_in = input; last_out = delay_sig; @@ -374,16 +386,16 @@ class AudioDelayFeedback @param delaytime_cells indicates the delay time in terms of cells in the delay buffer. */ inline - int16_t read(Q16n16 delaytime_cells, Int2Type) + return_type read(Q16n16 delaytime_cells, Int2Type) { uint16_t index = (Q16n16)delaytime_cells >> 16; uint16_t fraction = (uint16_t) delaytime_cells; // keeps low word uint16_t read_pos1 = (write_pos - index) & (NUM_BUFFER_SAMPLES - 1); - int16_t delay_sig1 = delay_array[read_pos1]; // read the delay buffer + return_type delay_sig1 = delay_array[read_pos1]; // read the delay buffer uint16_t read_pos2 = (write_pos - (index+1)) & (NUM_BUFFER_SAMPLES - 1); - int16_t delay_sig2 = delay_array[read_pos2]; // read the delay buffer + return_type delay_sig2 = delay_array[read_pos2]; // read the delay buffer /* int16_t difference = delay_sig2 - delay_sig1; @@ -391,7 +403,8 @@ class AudioDelayFeedback int16_t delay_sig = delay_sig1+delay_sig_fraction; */ - int16_t delay_sig = delay_sig1 + ((int32_t)delay_sig2*fraction)>>16; + //int16_t delay_sig = delay_sig1 + ((int32_t)delay_sig2*fraction)>>16; + return_type delay_sig = delay_sig1 + ((typename IntegerType::signed_type)delay_sig2*fraction)>>16; return delay_sig; }