9
9
#include "py/runtime.h"
10
10
#include <math.h>
11
11
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 ,
13
13
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 ) {
15
15
16
16
// Basic settings every effect and audio sample has
17
17
// 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,
53
53
self -> more_data = false; // Is there still more data to read from the sample or did we finish
54
54
55
55
// 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
+ }
56
110
}
57
111
58
112
bool 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) {
70
124
self -> buffer [1 ] = NULL ;
71
125
}
72
126
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
+
73
172
void audiodelays_reverb_reset_buffer (audiodelays_reverb_obj_t * self ,
74
173
bool single_channel_output ,
75
174
uint8_t channel ) {
@@ -106,6 +205,27 @@ void common_hal_audiodelays_reverb_stop(audiodelays_reverb_obj_t *self) {
106
205
return ;
107
206
}
108
207
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
+
109
229
audioio_get_buffer_result_t audiodelays_reverb_get_buffer (audiodelays_reverb_obj_t * self , bool single_channel_output , uint8_t channel ,
110
230
uint8_t * * buffer , uint32_t * buffer_length ) {
111
231
@@ -150,6 +270,12 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
150
270
151
271
// get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required
152
272
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 );
153
279
154
280
// If we have no sample keep the reverb reverbing
155
281
if (self -> sample == NULL ) {
@@ -164,10 +290,38 @@ audioio_get_buffer_result_t audiodelays_reverb_get_buffer(audiodelays_reverb_obj
164
290
165
291
for (uint32_t i = 0 ; i < n ; i ++ ) {
166
292
int32_t sample_word = sample_src [i ];
167
-
168
293
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
170
311
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 ));
171
325
word_buffer [i ] = (int16_t )word ;
172
326
}
173
327
0 commit comments