@@ -38,10 +38,6 @@ void common_hal_audiofilters_phaser_construct(audiofilters_phaser_obj_t *self,
3838
3939 self -> last_buf_idx = 1 ; // Which buffer to use first, toggle between 0 and 1
4040
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-
4541 // Initialize other values most effects will need.
4642 self -> sample = NULL ; // The current playing sample
4743 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,
5147
5248 // The below section sets up the effect's starting values.
5349
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 ;
5555
5656 if (feedback == mp_const_none ) {
5757 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) {
6868 audiosample_mark_deinit (& self -> base );
6969 self -> buffer [0 ] = NULL ;
7070 self -> buffer [1 ] = NULL ;
71+ self -> word_buffer = NULL ;
72+ self -> allpass_buffer = NULL ;
7173}
7274
7375mp_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,
102104 if (!arg ) {
103105 arg = 1 ;
104106 }
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 ));
106113 self -> stages = arg ;
114+
115+ memset (self -> allpass_buffer , 0 , self -> base .channel_count * self -> stages * sizeof (int32_t ));
107116}
108117
109118void audiofilters_phaser_reset_buffer (audiofilters_phaser_obj_t * self ,
@@ -112,6 +121,8 @@ void audiofilters_phaser_reset_buffer(audiofilters_phaser_obj_t *self,
112121
113122 memset (self -> buffer [0 ], 0 , self -> buffer_len );
114123 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 ));
115126}
116127
117128bool 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
222233 }
223234 }
224235 } 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+
225241 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+
226245 int32_t sample_word = 0 ;
227246 if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
228247 sample_word = sample_src [i ];
@@ -235,13 +254,21 @@ audioio_get_buffer_result_t audiofilters_phaser_get_buffer(audiofilters_phaser_o
235254 }
236255 }
237256
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 ;
240267
241268 // Add original sample + effect
242269 word = sample_word + (int32_t )(word * mix );
243270 word = synthio_mix_down_sample (word , 2 );
244-
271+
245272 if (MP_LIKELY (self -> base .bits_per_sample == 16 )) {
246273 word_buffer [i ] = word ;
247274 if (!self -> base .samples_signed ) {
0 commit comments