Skip to content

Commit c1cba1c

Browse files
committed
Merge branch 'master' of github.com:sensorium/Mozzi
2 parents 78238df + 0ca34ef commit c1cba1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+7500
-7067
lines changed

AudioDelay.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class AudioDelay
6363

6464
// why does delay jump if I read it before writing?
6565
delay_array[_write_pos] = in_value; // write to buffer
66-
int8_t delay_sig = delay_array[read_pos] ; // read the delay buffer
66+
T delay_sig = delay_array[read_pos] ; // read the delay buffer
6767

6868
return (T)delay_sig;
6969
}

AudioDelayFeedback.h

Lines changed: 50 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "mozzi_utils.h"
1818
#include "meta.h"
19+
#include "IntegerType.h"
1920

2021
enum interpolation_types {LINEAR,ALLPASS};
2122

@@ -31,11 +32,14 @@ with the input, do it in your sketch. AudioDelayFeedback uses more processing an
3132
than 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
3334
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.
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>
3638
class AudioDelayFeedback
3739
{
3840

41+
typedef typename IntegerType<sizeof(su)+sizeof(su)>::signed_type return_type;
42+
3943
public:
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

245252
private:
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
}

MetaOscil.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "Oscil.h"
2222
#include "mozzi_fixmath.h"
23+
#include <FixMath.h>
2324

2425

2526
/**
@@ -172,6 +173,19 @@ template<uint16_t NUM_TABLE_CELLS, uint16_t UPDATE_RATE, byte N_OSCIL>
172173
setFreq((int) frequency, false);
173174
current_osc->setFreq(frequency);
174175
}
176+
177+
178+
/** Set the MetaOsc frequency with a UFix<NI,NF> fixed-point number format. This falls back to using UFix<16,16> internally and is provided as a fallout for other UFix types..
179+
@param frequency to play the wave table.
180+
*/
181+
template <int8_t NI, int8_t NF, uint64_t RANGE>
182+
inline
183+
void setFreq(UFix<NI,NF,RANGE> frequency)
184+
{
185+
setFreq(frequency.asInt(), false);
186+
current_osc->setFreq(frequency);
187+
}
188+
175189

176190

177191
/** Set the MetaOsc frequency with a Q24n8 fixed-point number format.
@@ -182,6 +196,7 @@ template<uint16_t NUM_TABLE_CELLS, uint16_t UPDATE_RATE, byte N_OSCIL>
182196
setFreq((int) (frequency>>8), false);
183197
current_osc->setFreq_Q24n8(frequency);
184198
}
199+
185200

186201

187202
/** Set the MetaOsc frequency with a Q16n16 fixed-point number format.

examples/09.Delays/AudioDelay/AudioDelay.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ void updateControl(){
4747
}
4848

4949
AudioOutput updateAudio(){
50-
char asig = aDel.next(aTriangle.next(), del_samps);
50+
int8_t asig = aDel.next(aTriangle.next(), del_samps);
5151
return MonoOutput::from8Bit(asig);
5252
}

examples/09.Delays/AudioDelayFeedback/AudioDelayFeedback.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ void updateControl(){
5858

5959

6060
AudioOutput updateAudio(){
61-
char asig = aTriangle.next(); // get this so it can be used twice without calling next() again
61+
int8_t asig = aTriangle.next(); // get this so it can be used twice without calling next() again
6262
//return asig/8 + aDel.next(asig, (uint16_t) del_samps); // mix some straight signal with the delayed signal
6363
//return aDel.next(aTriangle.next(), (uint16_t) del_samps); // instead of the previous 2 lines for only the delayed signal
6464
return MonoOutput::fromAlmostNBit(9, (asig >> 3) + aDel.next(asig, deltime)); // mix some straight signal with the delayed signal

examples/09.Delays/AudioDelayFeedbackAllpass/AudioDelayFeedbackAllpass.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void updateControl(){
6262
// set random delay parameters
6363
float del_cells = (float)rand(65535u)/256;
6464
aDel.setDelayTimeCells(del_cells); // Allpass interpolation for fractional delay time
65-
char fb = rand(-50,50);
65+
int8_t fb = rand(-50,50);
6666
aDel.setFeedbackLevel(fb);
6767
kDelay.start(duration+500);
6868
}

examples/09.Delays/AudioDelayFeedbackX2/AudioDelayFeedbackX2.ino

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,21 @@ void setup(){
5555

5656

5757
void updateControl(){
58-
// delay time range from 0 to 127 samples, @ 16384 samps per sec = 0 to 7 milliseconds
59-
del_samps1 = 64+kDelSamps1.next();
58+
// delay time range from 1 to 128 samples, @ 16384 samps per sec = 0 to 7 milliseconds
59+
del_samps1 = 65+(kDelSamps1.next()>>1);
6060

6161
// delay time range from 1 to 33 samples, @ 16384 samps per sec = 0 to 2 milliseconds
6262
del_samps2 = 17+kDelSamps2.next()/8;
6363
}
6464

6565

6666
AudioOutput updateAudio(){
67-
char asig1 = aTriangle1.next(); // get this so it can be used twice without calling next() again
68-
int aflange1 = (asig1>>3) + aDel1.next(asig1, del_samps1); // mix some straignt signal with the delayed signal
67+
int8_t asig1 = aTriangle1.next(); // get this so it can be used twice without calling next() again
68+
int16_t aflange1 = (asig1>>3) + aDel1.next(asig1, del_samps1); // mix some straignt signal with the delayed signal
6969

70-
char asig2 = aTriangle2.next(); // get this so it can be used twice without calling next() again
71-
int aflange2 = (asig2>>3) + aDel2.next(asig2, del_samps2); // mix some straignt signal with the delayed signal
72-
return MonoOutput::fromAlmostNBit(10, aflange1 + aflange2);
70+
int8_t asig2 = aTriangle2.next(); // get this so it can be used twice without calling next() again
71+
int16_t aflange2 = (asig2>>3) + aDel2.next(asig2, del_samps2); // mix some straignt signal with the delayed signal
72+
return MonoOutput::fromAlmostNBit(10, aflange1 + aflange2).clip();
7373
}
7474

7575

examples/09.Delays/AudioDelayFeedback_HIFI/AudioDelayFeedback_HIFI.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ void updateControl(){
8383

8484

8585
AudioOutput updateAudio(){
86-
char asig = aTriangle.next(); // get this so it can be used twice without calling next() again
86+
int8_t asig = aTriangle.next(); // get this so it can be used twice without calling next() again
8787
//return asig/8 + aDel.next(asig, del_samps); // mix some straight signal with the delayed signal
8888
//return aDel.next(aTriangle.next(), del_samps); // instead of the previous 2 lines for only the delayed signal
8989
return MonoOutput::fromAlmostNBit(13, asig + (aDel.next(asig, del_samps_fractional)<<4)); // mix some straight signal with the delayed signal

0 commit comments

Comments
 (0)