1616
1717#include " mozzi_utils.h"
1818#include " meta.h"
19+ #include " IntegerType.h"
1920
2021enum interpolation_types {LINEAR,ALLPASS};
2122
@@ -31,11 +32,14 @@ with the input, do it in your sketch. AudioDelayFeedback uses more processing an
3132than a plain AudioDelay, but allows for more dramatic effects with feedback.
3233@tparam INTERP_TYPE a choice of LINEAR (default) or ALLPASS interpolation. LINEAR is better
3334for sweeping delay times, ALLPASS may be better for reverb-like effects.
35+ @tparam the type of numbers to use for the signal in the delay. The default is int8_t, but int16_t could be useful. Larger types (int32_t) might produce overflows as of v2.0.2.
3436*/
35- template <uint16_t NUM_BUFFER_SAMPLES, int8_t INTERP_TYPE = LINEAR>
37+ template <uint16_t NUM_BUFFER_SAMPLES, int8_t INTERP_TYPE = LINEAR, typename su= int8_t >
3638class AudioDelayFeedback
3739{
3840
41+ typedef typename IntegerType<sizeof (su)+sizeof (su)>::signed_type return_type;
42+
3943public:
4044 /* * Constructor.
4145 */
@@ -68,7 +72,7 @@ class AudioDelayFeedback
6872 @note slower than next(int8_t input, uint16_t delaytime_cells)
6973 */
7074 inline
71- int16_t next (int8_t input)
75+ return_type next (su input)
7276 {
7377 // chooses a different next() function depending on whether the
7478 // the template parameter is LINEAR(default if none provided) or ALLPASS.
@@ -85,18 +89,19 @@ class AudioDelayFeedback
8589 @note Timing: 4us
8690 */
8791 inline
88- int16_t next (int8_t input, uint16_t delaytime_cells)
92+ return_type next (su input, uint16_t delaytime_cells)
8993 {
9094 // setPin13High();
9195 ++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
9296 uint16_t read_pos = (write_pos - delaytime_cells) & (NUM_BUFFER_SAMPLES - 1 );
9397 // < 1us to here
94- int16_t delay_sig = delay_array[read_pos]; // read the delay buffer
98+ return_type delay_sig = delay_array[read_pos]; // read the delay buffer
9599 // with this line, the method takes 18us
96100 // int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)/128),-128),127); // feedback clipped
97101 // this line, the whole method takes 4us... Compiler doesn't optimise pow2 divides. Why?
98- int8_t feedback_sig = (int8_t ) min (max (((delay_sig * _feedback_level)>>7 ),-128 ),127 ); // feedback clipped
99- delay_array[write_pos] = (int16_t ) input + feedback_sig; // write to buffer
102+ // int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)>>7),-128),127); // feedback clipped
103+ su feedback_sig = (su) constrain ( ((delay_sig * _feedback_level)>>7 ), -(1 <<((sizeof (su)<<3 )-1 )), (1 <<((sizeof (su)<<3 )-1 ))-1 );
104+ delay_array[write_pos] = (return_type)input + feedback_sig; // write to buffer
100105 // setPin13Low();
101106 return delay_sig;
102107 }
@@ -110,7 +115,7 @@ class AudioDelayFeedback
110115 value of _delaytime_cells.
111116 */
112117 inline
113- int16_t next (int8_t input, Q16n16 delaytime_cells)
118+ return_type next (su input, Q16n16 delaytime_cells)
114119 {
115120 // setPin13High();
116121 ++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
@@ -119,21 +124,23 @@ class AudioDelayFeedback
119124 uint16_t fraction = (uint16_t ) delaytime_cells; // keeps low word
120125
121126 uint16_t read_pos1 = (write_pos - index) & (NUM_BUFFER_SAMPLES - 1 );
122- int16_t delay_sig1 = delay_array[read_pos1]; // read the delay buffer
127+ return_type delay_sig1 = delay_array[read_pos1]; // read the delay buffer
123128
124129 uint16_t read_pos2 = (write_pos - (index+1 )) & (NUM_BUFFER_SAMPLES - 1 );
125- int16_t delay_sig2 = delay_array[read_pos2]; // read the delay buffer
130+ return_type delay_sig2 = delay_array[read_pos2]; // read the delay buffer
126131
127132
128- int16_t difference = delay_sig2 - delay_sig1;
129- int16_t delay_sig_fraction = (int16_t )((int32_t )((int32_t ) fraction * difference) >> 16 );
133+ return_type difference = delay_sig2 - delay_sig1;
134+ // int16_t delay_sig_fraction = (int16_t)((int32_t)((int32_t) fraction * difference) >> 16);
135+ return_type delay_sig_fraction = (return_type)((typename IntegerType<sizeof (return_type)+sizeof (return_type)>::signed_type)((typename IntegerType<sizeof (return_type)+sizeof (return_type)>::signed_type)fraction * difference) >> 16 );
130136
131- int16_t delay_sig = delay_sig1+delay_sig_fraction;
137+ return_type delay_sig = delay_sig1+delay_sig_fraction;
132138
133139 // int16_t delay_sig = delay_sig1 + ((int32_t)delay_sig2*fraction)>>16;
134140
135- int8_t feedback_sig = (int8_t ) min (max ((((int16_t )(delay_sig * _feedback_level))>>7 ),-128 ),127 ); // feedback clipped
136- delay_array[write_pos] = (int16_t ) input + feedback_sig; // write to buffer
141+ // int8_t feedback_sig = (int8_t) min(max((((int16_t)(delay_sig * _feedback_level))>>7),-128),127); // feedback clipped
142+ su feedback_sig = (su) constrain (((delay_sig * _feedback_level)>>7 ), -(1 <<((sizeof (su)<<3 )-1 )), (1 <<((sizeof (su)<<3 )-1 ))-1 );
143+ delay_array[write_pos] = (return_type) input + feedback_sig; // write to buffer
137144 // setPin13Low();
138145 return delay_sig;
139146 }
@@ -143,7 +150,7 @@ class AudioDelayFeedback
143150 @param input the signal input.
144151 */
145152 inline
146- void write (int8_t input)
153+ void write (su input)
147154 {
148155 ++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
149156 delay_array[write_pos] = input;
@@ -155,7 +162,7 @@ class AudioDelayFeedback
155162 @param input the signal input.
156163 */
157164 inline
158- void writeFeedback (int8_t input)
165+ void writeFeedback (su input)
159166 {
160167 delay_array[write_pos] = input;
161168 }
@@ -167,7 +174,7 @@ class AudioDelayFeedback
167174 @param offset the number of cells behind the ordinary write position where the input will be written.
168175 */
169176 inline
170- void write (int8_t input, uint16_t offset)
177+ void write (su input, uint16_t offset)
171178 {
172179 uint16_t _pos = (write_pos + offset) & (NUM_BUFFER_SAMPLES - 1 );
173180 delay_array[_pos] = input;
@@ -179,7 +186,7 @@ class AudioDelayFeedback
179186 @param delaytime_cells indicates the delay time in terms of cells in the delay buffer.
180187 */
181188 inline
182- int16_t read (Q16n16 delaytime_cells)
189+ return_type read (Q16n16 delaytime_cells)
183190 {
184191 return read (delaytime_cells, Int2Type<INTERP_TYPE>());
185192 }
@@ -189,7 +196,7 @@ class AudioDelayFeedback
189196 It doesn't change the stored internal value of _delaytime_cells or feedback the output to the input.
190197 */
191198 inline
192- int16_t read ()
199+ return_type read ()
193200 {
194201 return read (Int2Type<INTERP_TYPE>());
195202 }
@@ -243,26 +250,29 @@ class AudioDelayFeedback
243250
244251
245252private:
246- int16_t delay_array[NUM_BUFFER_SAMPLES];
253+ return_type delay_array[NUM_BUFFER_SAMPLES];
247254 uint16_t write_pos;
248255 int8_t _feedback_level;
249256 uint16_t _delaytime_cells;
250257 Q15n16 _coeff; // for allpass interpolation
258+ su last_in;
259+ return_type last_out;
251260
252261
253262
254263 /* * Input a value to the delay and retrieve the signal in the delay line at the position delaytime_cells.
255264 @param in_value the signal input.
256265 */
257266 inline
258- int16_t next (int8_t in_value, Int2Type<LINEAR>)
267+ return_type next (su in_value, Int2Type<LINEAR>)
259268 {
260269 ++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
261270 uint16_t read_pos = (write_pos - _delaytime_cells) & (NUM_BUFFER_SAMPLES - 1 );
262271
263- int16_t delay_sig = delay_array[read_pos]; // read the delay buffer
264- int8_t feedback_sig = (int8_t ) min (max (((delay_sig * _feedback_level)/128 ),-128 ),127 ); // feedback clipped
265- delay_array[write_pos] = (int16_t ) in_value + feedback_sig; // write to buffer
272+ return_type delay_sig = delay_array[read_pos]; // read the delay buffer
273+ // int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)/128),-128),127); // feedback clipped
274+ su feedback_sig = (su) constrain (((delay_sig * _feedback_level)>>7 ), -(1 <<((sizeof (su)<<3 )-1 )), (1 <<((sizeof (su)<<3 )-1 ))-1 );
275+ delay_array[write_pos] = (return_type) in_value + feedback_sig; // write to buffer
266276
267277 return delay_sig;
268278 }
@@ -277,7 +287,7 @@ class AudioDelayFeedback
277287 @note Timing: 10us
278288 */
279289 inline
280- int16_t next (int8_t input, Int2Type<ALLPASS>)
290+ return_type next (su input, Int2Type<ALLPASS>)
281291 {
282292 /*
283293 http://www.scandalis.com/Jarrah/Documents/DelayLine.pdf
@@ -290,19 +300,24 @@ class AudioDelayFeedback
290300 = coeff * (in-last_out) + last_in
291301 */
292302 // setPin13High();
303+
304+ /* I think these should **not** be static
293305 static int8_t last_in;
294306 static int16_t last_out;
295-
307+ */
308+
296309 ++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
297310
298311 uint16_t read_pos1 = (write_pos - _delaytime_cells) & (NUM_BUFFER_SAMPLES - 1 );
299- int16_t delay_sig = delay_array[read_pos1]; // read the delay buffer
312+ return_type delay_sig = delay_array[read_pos1]; // read the delay buffer
300313
301- int16_t interp = (int16_t )(_coeff * ((int16_t )input - last_out)>>16 ) + last_in; // Q15n16*Q15n0 + Q15n0 = Q15n16 + Q15n0 = Q15n16
314+ // int16_t interp = (int16_t)(_coeff * ((int16_t)input - last_out)>>16) + last_in; // Q15n16*Q15n0 + Q15n0 = Q15n16 + Q15n0 = Q15n16
315+ return_type interp = (return_type)(_coeff * ((return_type)input - last_out)>>(sizeof (su)<<4 )) + last_in;
302316 delay_sig += interp;
303317
304- int8_t feedback_sig = (int8_t ) min (max (((delay_sig * _feedback_level)>>7 ),-128 ),127 ); // feedback clipped
305- delay_array[write_pos] = (int16_t ) input + feedback_sig; // write to buffer
318+ // int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)>>7),-128),127); // feedback clipped
319+ su feedback_sig = (su) constrain (((delay_sig * _feedback_level)>>7 ), -(1 <<((sizeof (su)<<3 )-1 )), (1 <<((sizeof (su)<<3 )-1 ))-1 );
320+ delay_array[write_pos] = (return_type) input + feedback_sig; // write to buffer
306321
307322 last_in = input;
308323 last_out = delay_sig;
@@ -372,24 +387,25 @@ class AudioDelayFeedback
372387 @param delaytime_cells indicates the delay time in terms of cells in the delay buffer.
373388 */
374389 inline
375- int16_t read (Q16n16 delaytime_cells, Int2Type<LINEAR>)
390+ return_type read (Q16n16 delaytime_cells, Int2Type<LINEAR>)
376391 {
377392 uint16_t index = (Q16n16)delaytime_cells >> 16 ;
378393 uint16_t fraction = (uint16_t ) delaytime_cells; // keeps low word
379394
380395 uint16_t read_pos1 = (write_pos - index) & (NUM_BUFFER_SAMPLES - 1 );
381- int16_t delay_sig1 = delay_array[read_pos1]; // read the delay buffer
396+ return_type delay_sig1 = delay_array[read_pos1]; // read the delay buffer
382397
383398 uint16_t read_pos2 = (write_pos - (index+1 )) & (NUM_BUFFER_SAMPLES - 1 );
384- int16_t delay_sig2 = delay_array[read_pos2]; // read the delay buffer
399+ return_type delay_sig2 = delay_array[read_pos2]; // read the delay buffer
385400
386401 /*
387402 int16_t difference = delay_sig2 - delay_sig1;
388403 int16_t delay_sig_fraction = ((int32_t) fraction * difference) >> 16;
389404
390405 int16_t delay_sig = delay_sig1+delay_sig_fraction;
391406 */
392- int16_t delay_sig = delay_sig1 + ((int32_t )delay_sig2*fraction)>>16 ;
407+ // int16_t delay_sig = delay_sig1 + ((int32_t)delay_sig2*fraction)>>16;
408+ return_type delay_sig = delay_sig1 + ((typename IntegerType<sizeof (return_type)+sizeof (return_type)>::signed_type)delay_sig2*fraction)>>16 ;
393409
394410 return delay_sig;
395411 }
0 commit comments