@@ -38,10 +38,6 @@ void common_hal_audiofilters_phaser_construct(audiofilters_phaser_obj_t *self,
38
38
39
39
self -> last_buf_idx = 1 ; // Which buffer to use first, toggle between 0 and 1
40
40
41
- // This buffer will be used to process samples through the biquad filter
42
- self -> filter_buffer = m_malloc_without_collect (SYNTHIO_MAX_DUR * sizeof (int32_t ));
43
- memset (self -> filter_buffer , 0 , SYNTHIO_MAX_DUR * sizeof (int32_t ));
44
-
45
41
// Initialize other values most effects will need.
46
42
self -> sample = NULL ; // The current playing sample
47
43
self -> sample_remaining_buffer = NULL ; // Pointer to the start of the sample buffer we have not played
@@ -51,7 +47,11 @@ void common_hal_audiofilters_phaser_construct(audiofilters_phaser_obj_t *self,
51
47
52
48
// The below section sets up the effect's starting values.
53
49
54
- self -> nyquist = (mp_float_t ) self -> base .sample_rate / 2 ;
50
+ // Create buffer to hold the last processed word
51
+ self -> word_buffer = m_malloc_without_collect (self -> base .channel_count * sizeof (int32_t ));
52
+ memset (self -> word_buffer , 0 , self -> base .channel_count * sizeof (int32_t ));
53
+
54
+ self -> nyquist = (mp_float_t )self -> base .sample_rate / 2 ;
55
55
56
56
if (feedback == mp_const_none ) {
57
57
feedback = mp_obj_new_float (MICROPY_FLOAT_CONST (0.7 ));
@@ -68,6 +68,8 @@ void common_hal_audiofilters_phaser_deinit(audiofilters_phaser_obj_t *self) {
68
68
audiosample_mark_deinit (& self -> base );
69
69
self -> buffer [0 ] = NULL ;
70
70
self -> buffer [1 ] = NULL ;
71
+ self -> word_buffer = NULL ;
72
+ self -> allpass_buffer = NULL ;
71
73
}
72
74
73
75
mp_obj_t common_hal_audiofilters_phaser_get_frequency (audiofilters_phaser_obj_t * self ) {
@@ -102,8 +104,15 @@ void common_hal_audiofilters_phaser_set_stages(audiofilters_phaser_obj_t *self,
102
104
if (!arg ) {
103
105
arg = 1 ;
104
106
}
105
- // TODO: reallocate filters
107
+
108
+ self -> allpass_buffer = (int32_t * )m_realloc (self -> allpass_buffer ,
109
+ #if MICROPY_MALLOC_USES_ALLOCATED_SIZE
110
+ self -> base .channel_count * self -> stages * sizeof (int32_t ), // Old size
111
+ #endif
112
+ self -> base .channel_count * arg * sizeof (int32_t ));
106
113
self -> stages = arg ;
114
+
115
+ memset (self -> allpass_buffer , 0 , self -> base .channel_count * self -> stages * sizeof (int32_t ));
107
116
}
108
117
109
118
void audiofilters_phaser_reset_buffer (audiofilters_phaser_obj_t * self ,
@@ -112,6 +121,8 @@ void audiofilters_phaser_reset_buffer(audiofilters_phaser_obj_t *self,
112
121
113
122
memset (self -> buffer [0 ], 0 , self -> buffer_len );
114
123
memset (self -> buffer [1 ], 0 , self -> buffer_len );
124
+ memset (self -> word_buffer , 0 , self -> base .channel_count * sizeof (int32_t ));
125
+ memset (self -> allpass_buffer , 0 , self -> base .channel_count * self -> stages * sizeof (int32_t ));
115
126
}
116
127
117
128
bool common_hal_audiofilters_phaser_get_playing (audiofilters_phaser_obj_t * self ) {
@@ -222,7 +233,15 @@ audioio_get_buffer_result_t audiofilters_phaser_get_buffer(audiofilters_phaser_o
222
233
}
223
234
}
224
235
} else {
236
+
237
+ // Update all-pass filter coefficient
238
+ mp_float_t allpasscoef = frequency / self -> nyquist ;
239
+ allpasscoef = (MICROPY_FLOAT_CONST (1.0 ) - allpasscoef ) / (MICROPY_FLOAT_CONST (1.0 ) + allpasscoef );
240
+
225
241
for (uint32_t i = 0 ; i < n ; i ++ ) {
242
+ bool right_channel = (single_channel_output && channel == 1 ) || (!single_channel_output && (i % self -> base .channel_count ) == 1 );
243
+ uint32_t allpass_buffer_offset = self -> stages * right_channel ;
244
+
226
245
int32_t sample_word = 0 ;
227
246
if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
228
247
sample_word = sample_src [i ];
@@ -235,13 +254,21 @@ audioio_get_buffer_result_t audiofilters_phaser_get_buffer(audiofilters_phaser_o
235
254
}
236
255
}
237
256
238
- // TODO: Process sample
239
- int32_t word = 0 ;
257
+ int32_t word = sample_word + self -> word_buffer [right_channel ] * feedback ;
258
+ int32_t allpass_word = 0 ;
259
+
260
+ // Update all-pass filters
261
+ for (uint32_t j = 0 ; j < self -> stages ; j ++ ) {
262
+ allpass_word = word * - allpasscoef + self -> allpass_buffer [j + allpass_buffer_offset ];
263
+ self -> allpass_buffer [j + allpass_buffer_offset ] = allpass_word * allpasscoef + word ;
264
+ word = allpass_word ;
265
+ }
266
+ self -> word_buffer [(bool )allpass_buffer_offset ] = word ;
240
267
241
268
// Add original sample + effect
242
269
word = sample_word + (int32_t )(word * mix );
243
270
word = synthio_mix_down_sample (word , 2 );
244
-
271
+
245
272
if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
246
273
word_buffer [i ] = word ;
247
274
if (!self -> base .samples_signed ) {
0 commit comments