Skip to content

Commit 1e4d766

Browse files
authored
Merge pull request #10288 from gamblor21/synthio_fixedpoint_fix
Fix for fixed point overflow in synthio
2 parents a1e2b0b + 5fcf8ae commit 1e4d766

13 files changed

+115112
-115109
lines changed

shared-module/audiofreeverb/Freeverb.c

+7-27
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// Fixed point ideas from - Paul Stoffregen in the Teensy audio library https://github.com/PaulStoffregen/Audio/blob/master/effect_freeverb.cpp
99
//
1010
#include "shared-bindings/audiofreeverb/Freeverb.h"
11+
#include "shared-module/synthio/__init__.h"
1112

1213
#include <stdint.h>
1314
#include "py/runtime.h"
@@ -217,27 +218,6 @@ void common_hal_audiofreeverb_freeverb_stop(audiofreeverb_freeverb_obj_t *self)
217218
return;
218219
}
219220

220-
// cleaner sat16 by http://www.moseleyinstruments.com/
221-
static int16_t sat16(int32_t n, int rshift) {
222-
// we should always round towards 0
223-
// to avoid recirculating round-off noise
224-
//
225-
// a 2s complement positive number is always
226-
// rounded down, so we only need to take
227-
// care of negative numbers
228-
if (n < 0) {
229-
n = n + (~(0xFFFFFFFFUL << rshift));
230-
}
231-
n = n >> rshift;
232-
if (n > 32767) {
233-
return 32767;
234-
}
235-
if (n < -32768) {
236-
return -32768;
237-
}
238-
return n;
239-
}
240-
241221
audioio_get_buffer_result_t audiofreeverb_freeverb_get_buffer(audiofreeverb_freeverb_obj_t *self, bool single_channel_output, uint8_t channel,
242222
uint8_t **buffer, uint32_t *buffer_length) {
243223

@@ -301,35 +281,35 @@ audioio_get_buffer_result_t audiofreeverb_freeverb_get_buffer(audiofreeverb_free
301281
int16_t input, bufout, output;
302282
uint32_t channel_comb_offset = 0, channel_allpass_offset = 0;
303283

304-
input = sat16(sample_word * 8738, 17); // Initial input scaled down so we can add reverb
284+
input = synthio_sat16(sample_word * 8738, 17); // Initial input scaled down so we can add reverb
305285
sum = 0;
306286

307287
// Calculate each of the 8 comb buffers
308288
for (uint32_t j = 0 + channel_comb_offset; j < 8 + channel_comb_offset; j++) {
309289
bufout = self->combbuffers[j][self->combbufferindex[j]];
310290
sum += bufout;
311-
self->combfitlers[j] = sat16(bufout * damp2 + self->combfitlers[j] * damp1, 15);
312-
self->combbuffers[j][self->combbufferindex[j]] = sat16(input + sat16(self->combfitlers[j] * feedback, 15), 0);
291+
self->combfitlers[j] = synthio_sat16(bufout * damp2 + self->combfitlers[j] * damp1, 15);
292+
self->combbuffers[j][self->combbufferindex[j]] = synthio_sat16(input + synthio_sat16(self->combfitlers[j] * feedback, 15), 0);
313293
if (++self->combbufferindex[j] >= self->combbuffersizes[j]) {
314294
self->combbufferindex[j] = 0;
315295
}
316296
}
317297

318-
output = sat16(sum * 31457, 17); // 31457 = 0.24f with shift of 17
298+
output = synthio_sat16(sum * 31457, 17); // 31457 = 0.24f with shift of 17
319299

320300
// Calculate each of the 4 all pass buffers
321301
for (uint32_t j = 0 + channel_allpass_offset; j < 4 + channel_allpass_offset; j++) {
322302
bufout = self->allpassbuffers[j][self->allpassbufferindex[j]];
323303
self->allpassbuffers[j][self->allpassbufferindex[j]] = output + (bufout >> 1); // bufout >> 1 same as bufout*0.5f
324-
output = sat16(bufout - output, 1);
304+
output = synthio_sat16(bufout - output, 1);
325305
if (++self->allpassbufferindex[j] >= self->allpassbuffersizes[j]) {
326306
self->allpassbufferindex[j] = 0;
327307
}
328308
}
329309

330310
word = output * 30; // Add some volume back don't have to saturate as next step will
331311

332-
word = sat16(sample_word * mix_sample, 15) + sat16(word * mix_effect, 15);
312+
word = synthio_sat16(sample_word * mix_sample, 15) + synthio_sat16(word * mix_effect, 15);
333313
word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2));
334314
word_buffer[i] = (int16_t)word;
335315

shared-module/synthio/Biquad.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "shared-bindings/synthio/Biquad.h"
1010
#include "shared-module/synthio/Biquad.h"
1111
#include "shared-module/synthio/block.h"
12+
#include "shared-bindings/synthio/__init__.h"
1213

1314
typedef struct {
1415
mp_float_t s, c;
@@ -212,7 +213,7 @@ void synthio_biquad_filter_samples(mp_obj_t self_in, biquad_filter_state *st, in
212213

213214
for (size_t n = n_samples; n; --n, ++buffer) {
214215
int32_t input = *buffer;
215-
int32_t output = (b0 * input + b1 * x0 + b2 * x1 - a1 * y0 - a2 * y1 + (1 << (BIQUAD_SHIFT - 1))) >> BIQUAD_SHIFT;
216+
int32_t output = synthio_sat16((b0 * input + b1 * x0 + b2 * x1 - a1 * y0 - a2 * y1 + (1 << (BIQUAD_SHIFT - 1))), BIQUAD_SHIFT);
216217

217218
x1 = x0;
218219
x0 = input;

shared-module/synthio/__init__.c

+24-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,26 @@ static const int16_t square_wave[] = {-32768, 32767};
2424
static const uint16_t notes[] = {8372, 8870, 9397, 9956, 10548, 11175, 11840,
2525
12544, 13290, 14080, 14917, 15804}; // 9th octave
2626

27+
// cleaner sat16 by http://www.moseleyinstruments.com/
28+
int16_t synthio_sat16(int32_t n, int rshift) {
29+
// we should always round towards 0
30+
// to avoid recirculating round-off noise
31+
//
32+
// a 2s complement positive number is always
33+
// rounded down, so we only need to take
34+
// care of negative numbers
35+
if (n < 0) {
36+
n = n + (~(0xFFFFFFFFUL << rshift));
37+
}
38+
n = n >> rshift;
39+
if (n > 32767) {
40+
return 32767;
41+
}
42+
if (n < -32768) {
43+
return -32768;
44+
}
45+
return n;
46+
}
2747

2848
static int64_t round_float_to_int64(mp_float_t f) {
2949
return (int64_t)(f + MICROPY_FLOAT_CONST(0.5));
@@ -250,7 +270,7 @@ static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou
250270
accum = accum - lim + offset;
251271
}
252272
int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT;
253-
int16_t wi = (ring_waveform[idx] * out_buffer32[i]) / 32768;
273+
int16_t wi = (ring_waveform[idx] * out_buffer32[i]) / 32768; // consider for synthio_sat16 but had a weird artificat
254274
out_buffer32[i] = wi;
255275
}
256276
synth->ring_accum[chan] = accum;
@@ -272,12 +292,12 @@ static mp_obj_t synthio_synth_get_note_filter(mp_obj_t note_obj) {
272292
static void sum_with_loudness(int32_t *out_buffer32, int32_t *tmp_buffer32, int16_t loudness[2], size_t dur, int synth_chan) {
273293
if (synth_chan == 1) {
274294
for (size_t i = 0; i < dur; i++) {
275-
*out_buffer32++ += (*tmp_buffer32++ *loudness[0]) >> 16;
295+
*out_buffer32++ += synthio_sat16((*tmp_buffer32++ *loudness[0]), 16);
276296
}
277297
} else {
278298
for (size_t i = 0; i < dur; i++) {
279-
*out_buffer32++ += (*tmp_buffer32 * loudness[0]) >> 16;
280-
*out_buffer32++ += (*tmp_buffer32++ *loudness[1]) >> 16;
299+
*out_buffer32++ += synthio_sat16((*tmp_buffer32 * loudness[0]), 16);
300+
*out_buffer32++ += synthio_sat16((*tmp_buffer32++ *loudness[1]), 16);
281301
}
282302
}
283303
}

shared-module/synthio/__init__.h

+2
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,5 @@ int synthio_sweep_in_step(synthio_lfo_state_t *state, uint16_t dur);
9595
extern mp_float_t synthio_global_rate_scale, synthio_global_W_scale;
9696
extern uint8_t synthio_global_tick;
9797
void shared_bindings_synthio_lfo_tick(uint32_t sample_rate, uint16_t num_samples);
98+
99+
int16_t synthio_sat16(int32_t n, int rshift);

0 commit comments

Comments
 (0)