16
16
17
17
#include " mozzi_utils.h"
18
18
#include " meta.h"
19
+ #include " IntegerType.h"
19
20
20
21
enum interpolation_types {LINEAR,ALLPASS};
21
22
@@ -31,11 +32,14 @@ with the input, do it in your sketch. AudioDelayFeedback uses more processing an
31
32
than a plain AudioDelay, but allows for more dramatic effects with feedback.
32
33
@tparam INTERP_TYPE a choice of LINEAR (default) or ALLPASS interpolation. LINEAR is better
33
34
for 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.
34
36
*/
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 >
36
38
class AudioDelayFeedback
37
39
{
38
40
41
+ typedef typename IntegerType<sizeof (su)+sizeof (su)>::signed_type return_type;
42
+
39
43
public:
40
44
/* * Constructor.
41
45
*/
@@ -68,7 +72,7 @@ class AudioDelayFeedback
68
72
@note slower than next(int8_t input, uint16_t delaytime_cells)
69
73
*/
70
74
inline
71
- int16_t next (int8_t input)
75
+ return_type next (su input)
72
76
{
73
77
// chooses a different next() function depending on whether the
74
78
// the template parameter is LINEAR(default if none provided) or ALLPASS.
@@ -85,18 +89,19 @@ class AudioDelayFeedback
85
89
@note Timing: 4us
86
90
*/
87
91
inline
88
- int16_t next (int8_t input, uint16_t delaytime_cells)
92
+ return_type next (su input, uint16_t delaytime_cells)
89
93
{
90
94
// setPin13High();
91
95
++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
92
96
uint16_t read_pos = (write_pos - delaytime_cells) & (NUM_BUFFER_SAMPLES - 1 );
93
97
// < 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
95
99
// with this line, the method takes 18us
96
100
// int8_t feedback_sig = (int8_t) min(max(((delay_sig * _feedback_level)/128),-128),127); // feedback clipped
97
101
// 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
100
105
// setPin13Low();
101
106
return delay_sig;
102
107
}
@@ -110,7 +115,7 @@ class AudioDelayFeedback
110
115
value of _delaytime_cells.
111
116
*/
112
117
inline
113
- int16_t next (int8_t input, Q16n16 delaytime_cells)
118
+ return_type next (su input, Q16n16 delaytime_cells)
114
119
{
115
120
// setPin13High();
116
121
++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
@@ -119,21 +124,23 @@ class AudioDelayFeedback
119
124
uint16_t fraction = (uint16_t ) delaytime_cells; // keeps low word
120
125
121
126
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
123
128
124
129
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
126
131
127
132
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 );
130
136
131
- int16_t delay_sig = delay_sig1+delay_sig_fraction;
137
+ return_type delay_sig = delay_sig1+delay_sig_fraction;
132
138
133
139
// int16_t delay_sig = delay_sig1 + ((int32_t)delay_sig2*fraction)>>16;
134
140
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
137
144
// setPin13Low();
138
145
return delay_sig;
139
146
}
@@ -143,7 +150,7 @@ class AudioDelayFeedback
143
150
@param input the signal input.
144
151
*/
145
152
inline
146
- void write (int8_t input)
153
+ void write (su input)
147
154
{
148
155
++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
149
156
delay_array[write_pos] = input;
@@ -155,7 +162,7 @@ class AudioDelayFeedback
155
162
@param input the signal input.
156
163
*/
157
164
inline
158
- void writeFeedback (int8_t input)
165
+ void writeFeedback (su input)
159
166
{
160
167
delay_array[write_pos] = input;
161
168
}
@@ -167,7 +174,7 @@ class AudioDelayFeedback
167
174
@param offset the number of cells behind the ordinary write position where the input will be written.
168
175
*/
169
176
inline
170
- void write (int8_t input, uint16_t offset)
177
+ void write (su input, uint16_t offset)
171
178
{
172
179
uint16_t _pos = (write_pos + offset) & (NUM_BUFFER_SAMPLES - 1 );
173
180
delay_array[_pos] = input;
@@ -179,7 +186,7 @@ class AudioDelayFeedback
179
186
@param delaytime_cells indicates the delay time in terms of cells in the delay buffer.
180
187
*/
181
188
inline
182
- int16_t read (Q16n16 delaytime_cells)
189
+ return_type read (Q16n16 delaytime_cells)
183
190
{
184
191
return read (delaytime_cells, Int2Type<INTERP_TYPE>());
185
192
}
@@ -189,7 +196,7 @@ class AudioDelayFeedback
189
196
It doesn't change the stored internal value of _delaytime_cells or feedback the output to the input.
190
197
*/
191
198
inline
192
- int16_t read ()
199
+ return_type read ()
193
200
{
194
201
return read (Int2Type<INTERP_TYPE>());
195
202
}
@@ -243,26 +250,29 @@ class AudioDelayFeedback
243
250
244
251
245
252
private:
246
- int16_t delay_array[NUM_BUFFER_SAMPLES];
253
+ return_type delay_array[NUM_BUFFER_SAMPLES];
247
254
uint16_t write_pos;
248
255
int8_t _feedback_level;
249
256
uint16_t _delaytime_cells;
250
257
Q15n16 _coeff; // for allpass interpolation
258
+ su last_in;
259
+ return_type last_out;
251
260
252
261
253
262
254
263
/* * Input a value to the delay and retrieve the signal in the delay line at the position delaytime_cells.
255
264
@param in_value the signal input.
256
265
*/
257
266
inline
258
- int16_t next (int8_t in_value, Int2Type<LINEAR>)
267
+ return_type next (su in_value, Int2Type<LINEAR>)
259
268
{
260
269
++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
261
270
uint16_t read_pos = (write_pos - _delaytime_cells) & (NUM_BUFFER_SAMPLES - 1 );
262
271
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
266
276
267
277
return delay_sig;
268
278
}
@@ -277,7 +287,7 @@ class AudioDelayFeedback
277
287
@note Timing: 10us
278
288
*/
279
289
inline
280
- int16_t next (int8_t input, Int2Type<ALLPASS>)
290
+ return_type next (su input, Int2Type<ALLPASS>)
281
291
{
282
292
/*
283
293
http://www.scandalis.com/Jarrah/Documents/DelayLine.pdf
@@ -290,19 +300,24 @@ class AudioDelayFeedback
290
300
= coeff * (in-last_out) + last_in
291
301
*/
292
302
// setPin13High();
303
+
304
+ /* I think these should **not** be static
293
305
static int8_t last_in;
294
306
static int16_t last_out;
295
-
307
+ */
308
+
296
309
++write_pos &= (NUM_BUFFER_SAMPLES - 1 );
297
310
298
311
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
300
313
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;
302
316
delay_sig += interp;
303
317
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
306
321
307
322
last_in = input;
308
323
last_out = delay_sig;
@@ -372,24 +387,25 @@ class AudioDelayFeedback
372
387
@param delaytime_cells indicates the delay time in terms of cells in the delay buffer.
373
388
*/
374
389
inline
375
- int16_t read (Q16n16 delaytime_cells, Int2Type<LINEAR>)
390
+ return_type read (Q16n16 delaytime_cells, Int2Type<LINEAR>)
376
391
{
377
392
uint16_t index = (Q16n16)delaytime_cells >> 16 ;
378
393
uint16_t fraction = (uint16_t ) delaytime_cells; // keeps low word
379
394
380
395
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
382
397
383
398
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
385
400
386
401
/*
387
402
int16_t difference = delay_sig2 - delay_sig1;
388
403
int16_t delay_sig_fraction = ((int32_t) fraction * difference) >> 16;
389
404
390
405
int16_t delay_sig = delay_sig1+delay_sig_fraction;
391
406
*/
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 ;
393
409
394
410
return delay_sig;
395
411
}
0 commit comments