99#include "py/runtime.h"
1010#include <math.h>
1111
12- void common_hal_audiodelays_reverb_construct (audiodelays_reverb_obj_t * self ,
12+ void common_hal_audiodelays_reverb_construct (audiodelays_reverb_obj_t * self , mp_obj_t roomsize , mp_obj_t damp , mp_obj_t mix ,
1313 uint32_t buffer_size , uint8_t bits_per_sample ,
14- bool samples_signed , uint8_t channel_count , uint32_t sample_rate , bool freq_shift ) {
14+ bool samples_signed , uint8_t channel_count , uint32_t sample_rate ) {
1515
1616 // Basic settings every effect and audio sample has
1717 // These are the effects values, not the source sample(s)
@@ -53,6 +53,60 @@ void common_hal_audiodelays_reverb_construct(audiodelays_reverb_obj_t *self,
5353 self -> more_data = false; // Is there still more data to read from the sample or did we finish
5454
5555 // The below section sets up the reverb effect's starting values. For a different effect this section will change
56+ if (roomsize == MP_OBJ_NULL ) {
57+ roomsize = mp_obj_new_float (MICROPY_FLOAT_CONST (0.5 ));
58+ }
59+ synthio_block_assign_slot (roomsize , & self -> roomsize , MP_QSTR_roomsize );
60+ common_hal_audiodelays_reverb_set_roomsize (self , roomsize );
61+
62+ if (damp == MP_OBJ_NULL ) {
63+ damp = mp_obj_new_float (MICROPY_FLOAT_CONST (0.5 ));
64+ }
65+ synthio_block_assign_slot (damp , & self -> damp , MP_QSTR_damp );
66+ common_hal_audiodelays_reverb_set_damp (self , damp );
67+
68+ if (mix == MP_OBJ_NULL ) {
69+ mix = mp_obj_new_float (MICROPY_FLOAT_CONST (0.5 ));
70+ }
71+ synthio_block_assign_slot (mix , & self -> mix , MP_QSTR_mix );
72+ common_hal_audiodelays_reverb_set_mix (self , mix );
73+
74+ // Set up the comb filters
75+ self -> combbuffersizes [0 ] = 1116 ;
76+ self -> combbuffersizes [1 ] = 1188 ;
77+ self -> combbuffersizes [2 ] = 1277 ;
78+ self -> combbuffersizes [3 ] = 1356 ;
79+ self -> combbuffersizes [4 ] = 1422 ;
80+ self -> combbuffersizes [5 ] = 1491 ;
81+ self -> combbuffersizes [6 ] = 1557 ;
82+ self -> combbuffersizes [7 ] = 1617 ;
83+ for (uint32_t i = 0 ; i < 8 ; i ++ ) {
84+ self -> combbuffers [i ] = m_malloc (self -> combbuffersizes [i ] * sizeof (uint16_t ));
85+ if (self -> combbuffers [i ] == NULL ) {
86+ common_hal_audiodelays_reverb_deinit (self );
87+ m_malloc_fail (self -> combbuffersizes [i ]);
88+ }
89+ memset (self -> combbuffers [i ], 0 , self -> combbuffersizes [i ]);
90+
91+ self -> combbufferindex [i ] = 0 ;
92+ self -> combfitlers [i ] = 0 ;
93+ }
94+
95+ // Set up the allpass filters
96+ self -> allpassbuffersizes [0 ] = 556 ;
97+ self -> allpassbuffersizes [1 ] = 441 ;
98+ self -> allpassbuffersizes [2 ] = 341 ;
99+ self -> allpassbuffersizes [3 ] = 225 ;
100+ for (uint32_t i = 0 ; i < 4 ; i ++ ) {
101+ self -> allpassbuffers [i ] = m_malloc (self -> allpassbuffersizes [i ] * sizeof (uint16_t ));
102+ if (self -> allpassbuffers [i ] == NULL ) {
103+ common_hal_audiodelays_reverb_deinit (self );
104+ m_malloc_fail (self -> allpassbuffersizes [i ]);
105+ }
106+ memset (self -> allpassbuffers [i ], 0 , self -> allpassbuffersizes [i ]);
107+
108+ self -> allpassbufferindex [i ] = 0 ;
109+ }
56110}
57111
58112bool common_hal_audiodelays_reverb_deinited (audiodelays_reverb_obj_t * self ) {
@@ -70,6 +124,51 @@ void common_hal_audiodelays_reverb_deinit(audiodelays_reverb_obj_t *self) {
70124 self -> buffer [1 ] = NULL ;
71125}
72126
127+ mp_obj_t common_hal_audiodelays_reverb_get_roomsize (audiodelays_reverb_obj_t * self ) {
128+ return self -> roomsize .obj ;
129+ }
130+
131+ void common_hal_audiodelays_reverb_set_roomsize (audiodelays_reverb_obj_t * self , mp_obj_t roomsize_obj ) {
132+ synthio_block_assign_slot (roomsize_obj , & self -> roomsize , MP_QSTR_roomsize );
133+ }
134+
135+ int16_t audiodelays_reverb_get_roomsize_fixedpoint (mp_float_t n ) {
136+ if (n > 1.0f ) {
137+ n = 1.0f ;
138+ } else if (n < 0.0f ) {
139+ n = 0.0f ;
140+ }
141+
142+ return (int16_t )(n * 9175.04f ) + 22937 ; // 9175.04 = 0.28f in fixed point 22937 = 0.7f
143+ }
144+
145+ mp_obj_t common_hal_audiodelays_reverb_get_damp (audiodelays_reverb_obj_t * self ) {
146+ return self -> damp .obj ;
147+ }
148+
149+ void common_hal_audiodelays_reverb_set_damp (audiodelays_reverb_obj_t * self , mp_obj_t damp ) {
150+ synthio_block_assign_slot (damp , & self -> damp , MP_QSTR_damp );
151+ }
152+
153+ void audiodelays_reverb_get_damp_fixedpoint (mp_float_t n , int16_t * damp1 , int16_t * damp2 ) {
154+ if (n > 1.0f ) {
155+ n = 1.0f ;
156+ } else if (n < 0.0f ) {
157+ n = 0.0f ;
158+ }
159+
160+ * damp1 = (int16_t )(n * 13107.2f ); // 13107.2 = 0.4f scaling factor
161+ * damp2 = (int16_t )(32768 - * damp1 ); // inverse of x1 damp2 = 1.0 - damp1
162+ }
163+
164+ mp_obj_t common_hal_audiodelays_reverb_get_mix (audiodelays_reverb_obj_t * self ) {
165+ return self -> mix .obj ;
166+ }
167+
168+ void common_hal_audiodelays_reverb_set_mix (audiodelays_reverb_obj_t * self , mp_obj_t mix ) {
169+ synthio_block_assign_slot (mix , & self -> mix , MP_QSTR_mix );
170+ }
171+
73172void audiodelays_reverb_reset_buffer (audiodelays_reverb_obj_t * self ,
74173 bool single_channel_output ,
75174 uint8_t channel ) {
@@ -106,6 +205,27 @@ void common_hal_audiodelays_reverb_stop(audiodelays_reverb_obj_t *self) {
106205 return ;
107206}
108207
208+ // cleaner sat16 by http://www.moseleyinstruments.com/
209+ static int16_t sat16 (int32_t n , int rshift ) {
210+ // we should always round towards 0
211+ // to avoid recirculating round-off noise
212+ //
213+ // a 2s complement positive number is always
214+ // rounded down, so we only need to take
215+ // care of negative numbers
216+ if (n < 0 ) {
217+ n = n + (~(0xFFFFFFFFUL << rshift ));
218+ }
219+ n = n >> rshift ;
220+ if (n > 32767 ) {
221+ return 32767 ;
222+ }
223+ if (n < -32768 ) {
224+ return -32768 ;
225+ }
226+ return n ;
227+ }
228+
109229audioio_get_buffer_result_t audiodelays_reverb_get_buffer (audiodelays_reverb_obj_t * self , bool single_channel_output , uint8_t channel ,
110230 uint8_t * * buffer , uint32_t * buffer_length ) {
111231
@@ -150,6 +270,12 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
150270
151271 // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
152272 shared_bindings_synthio_lfo_tick (self -> base .sample_rate , n / self -> base .channel_count );
273+ mp_float_t damp = synthio_block_slot_get_limited (& self -> damp , MICROPY_FLOAT_CONST (0.0 ), MICROPY_FLOAT_CONST (1.0 ));
274+ int16_t damp1 , damp2 ;
275+ audiodelays_reverb_get_damp_fixedpoint (damp , & damp1 , & damp2 );
276+
277+ mp_float_t roomsize = synthio_block_slot_get_limited (& self -> roomsize , MICROPY_FLOAT_CONST (0.0 ), MICROPY_FLOAT_CONST (1.0 ));
278+ int16_t feedback = audiodelays_reverb_get_roomsize_fixedpoint (roomsize );
153279
154280 // If we have no sample keep the reverb reverbing
155281 if (self -> sample == NULL ) {
@@ -164,10 +290,38 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
164290
165291 for (uint32_t i = 0 ; i < n ; i ++ ) {
166292 int32_t sample_word = sample_src [i ];
167-
168293 int32_t word ;
169- word = synthio_mix_down_sample (sample_word , SYNTHIO_MIX_DOWN_SCALE (2 ));
294+ int16_t input , bufout , output ;
295+ int32_t sum ;
296+
297+ input = sat16 (sample_word * 8738 , 17 );
298+ sum = 0 ;
299+
300+ for (uint32_t j = 0 ; j < 8 ; 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+ }
309+
310+ output = sat16 (sum * 31457 , 17 ); // 31457 = 0.96f
170311
312+ for (uint32_t j = 0 ; j < 4 ; 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 ;
318+ }
319+ }
320+
321+ word = sat16 (output * 30 , 0 );
322+
323+
324+ word = synthio_mix_down_sample (sample_word , SYNTHIO_MIX_DOWN_SCALE (2 ));
171325 word_buffer [i ] = (int16_t )word ;
172326 }
173327
0 commit comments