|
3 | 3 | // SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus
|
4 | 4 | //
|
5 | 5 | // SPDX-License-Identifier: MIT
|
| 6 | +// |
| 7 | +// Based on FreeVerb - https://github.com/sinshu/freeverb/tree/main |
| 8 | +// Fixed point ideas from - Paul Stoffregen in the Teensy audio library https://github.com/PaulStoffregen/Audio/blob/master/effect_freeverb.cpp |
| 9 | +// |
6 | 10 | #include "shared-bindings/audiodelays/Reverb.h"
|
7 | 11 |
|
8 | 12 | #include <stdint.h>
|
@@ -278,69 +282,62 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
|
278 | 282 | mp_float_t roomsize = synthio_block_slot_get_limited(&self->roomsize, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0));
|
279 | 283 | int16_t feedback = audiodelays_reverb_get_roomsize_fixedpoint(roomsize);
|
280 | 284 |
|
281 |
| - // If we have no sample keep the reverb reverbing |
282 |
| - if (self->sample == NULL) { |
283 |
| - // Since we have no sample we can just iterate over the our entire remaining buffer and finish |
284 |
| - for (uint32_t i = 0; i < n; i++) { |
285 |
| - int16_t word = 0; |
286 |
| - word_buffer[i] = word; |
| 285 | + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; |
| 286 | + |
| 287 | + for (uint32_t i = 0; i < n; i++) { |
| 288 | + int32_t sample_word = 0; |
| 289 | + if (self->sample != NULL) { |
| 290 | + sample_word = sample_src[i]; |
287 | 291 | }
|
288 |
| - } else { |
289 |
| - // we have a sample to play |
290 |
| - int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; |
291 |
| - |
292 |
| - for (uint32_t i = 0; i < n; i++) { |
293 |
| - int32_t sample_word = sample_src[i]; |
294 |
| - |
295 |
| - int32_t word, sum; |
296 |
| - int16_t input, bufout, output; |
297 |
| - uint32_t channel_comb_offset = 0, channel_allpass_offset = 0; |
298 |
| - |
299 |
| - input = sat16(sample_word * 8738, 17); |
300 |
| - sum = 0; |
301 |
| - |
302 |
| - for (uint32_t j = 0 + channel_comb_offset; j < 8 + channel_comb_offset; j++) { |
303 |
| - bufout = self->combbuffers[j][self->combbufferindex[j]]; |
304 |
| - sum += bufout; |
305 |
| - self->combfitlers[j] = sat16(bufout * damp2 + self->combfitlers[j] * damp1, 15); |
306 |
| - self->combbuffers[j][self->combbufferindex[j]] = sat16(input + sat16(self->combfitlers[j] * feedback, 15), 0); |
307 |
| - if (++self->combbufferindex[j] >= self->combbuffersizes[j]) { |
308 |
| - self->combbufferindex[j] = 0; |
309 |
| - } |
310 |
| - } |
311 | 292 |
|
312 |
| - output = sat16(sum * 31457, 17); // 31457 = 0.96f |
| 293 | + int32_t word, sum; |
| 294 | + int16_t input, bufout, output; |
| 295 | + uint32_t channel_comb_offset = 0, channel_allpass_offset = 0; |
313 | 296 |
|
314 |
| - for (uint32_t j = 0 + channel_allpass_offset; j < 4 + channel_allpass_offset; j++) { |
315 |
| - bufout = self->allpassbuffers[j][self->allpassbufferindex[j]]; |
316 |
| - self->allpassbuffers[j][self->allpassbufferindex[j]] = output + (bufout >> 1); // bufout >> 1 same as bufout*0.5f |
317 |
| - output = sat16(bufout - output, 1); |
318 |
| - if (++self->allpassbufferindex[j] >= self->allpassbuffersizes[j]) { |
319 |
| - self->allpassbufferindex[j] = 0; |
320 |
| - } |
321 |
| - } |
| 297 | + input = sat16(sample_word * 8738, 17); |
| 298 | + sum = 0; |
322 | 299 |
|
323 |
| - word = output * 30; |
| 300 | + for (uint32_t j = 0 + channel_comb_offset; j < 8 + channel_comb_offset; j++) { |
| 301 | + bufout = self->combbuffers[j][self->combbufferindex[j]]; |
| 302 | + sum += bufout; |
| 303 | + self->combfitlers[j] = sat16(bufout * damp2 + self->combfitlers[j] * damp1, 15); |
| 304 | + self->combbuffers[j][self->combbufferindex[j]] = sat16(input + sat16(self->combfitlers[j] * feedback, 15), 0); |
| 305 | + if (++self->combbufferindex[j] >= self->combbuffersizes[j]) { |
| 306 | + self->combbufferindex[j] = 0; |
| 307 | + } |
| 308 | + } |
324 | 309 |
|
325 |
| - word = (sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix); |
326 |
| - word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); |
327 |
| - word_buffer[i] = (int16_t)word; |
| 310 | + output = sat16(sum * 31457, 17); // 31457 = 0.96f |
328 | 311 |
|
329 |
| - if ((self->base.channel_count == 2) && (channel_comb_offset == 0)) { |
330 |
| - channel_comb_offset = 8; |
331 |
| - channel_allpass_offset = 4; |
332 |
| - } else { |
333 |
| - channel_comb_offset = 0; |
334 |
| - channel_allpass_offset = 0; |
| 312 | + for (uint32_t j = 0 + channel_allpass_offset; j < 4 + channel_allpass_offset; j++) { |
| 313 | + bufout = self->allpassbuffers[j][self->allpassbufferindex[j]]; |
| 314 | + self->allpassbuffers[j][self->allpassbufferindex[j]] = output + (bufout >> 1); // bufout >> 1 same as bufout*0.5f |
| 315 | + output = sat16(bufout - output, 1); |
| 316 | + if (++self->allpassbufferindex[j] >= self->allpassbuffersizes[j]) { |
| 317 | + self->allpassbufferindex[j] = 0; |
335 | 318 | }
|
336 | 319 | }
|
337 | 320 |
|
338 |
| - // Update the remaining length and the buffer positions based on how much we wrote into our buffer |
339 |
| - length -= n; |
340 |
| - word_buffer += n; |
341 |
| - self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); |
342 |
| - self->sample_buffer_length -= n; |
| 321 | + word = output * 30; |
| 322 | + |
| 323 | + word = (sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix); |
| 324 | + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); |
| 325 | + word_buffer[i] = (int16_t)word; |
| 326 | + |
| 327 | + if ((self->base.channel_count == 2) && (channel_comb_offset == 0)) { |
| 328 | + channel_comb_offset = 8; |
| 329 | + channel_allpass_offset = 4; |
| 330 | + } else { |
| 331 | + channel_comb_offset = 0; |
| 332 | + channel_allpass_offset = 0; |
| 333 | + } |
343 | 334 | }
|
| 335 | + |
| 336 | + // Update the remaining length and the buffer positions based on how much we wrote into our buffer |
| 337 | + length -= n; |
| 338 | + word_buffer += n; |
| 339 | + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); |
| 340 | + self->sample_buffer_length -= n; |
344 | 341 | }
|
345 | 342 |
|
346 | 343 | // Finally pass our buffer and length to the calling audio function
|
|
0 commit comments