@@ -31,7 +31,7 @@ void common_hal_audioeffects_echo_construct(audioeffects_echo_obj_t *self, uint3
3131
3232 // calculate buffer size for the set delay
3333 self -> delay_ms = delay_ms ;
34- self -> echo_buffer_len = self -> sample_rate / 1000.0f * self -> delay_ms * sizeof ( uint32_t );
34+ self -> echo_buffer_len = self -> sample_rate / 1000.0f * self -> delay_ms * ( self -> channel_count * ( self -> bits_per_sample / 8 ) );
3535
3636 self -> echo_buffer = m_malloc (self -> echo_buffer_len );
3737 if (self -> echo_buffer == NULL ) {
@@ -44,6 +44,12 @@ void common_hal_audioeffects_echo_construct(audioeffects_echo_obj_t *self, uint3
4444 // write is what we send to the outgoing buffer
4545 self -> echo_buffer_read_pos = self -> buffer_len / sizeof (uint32_t );
4646 self -> echo_buffer_write_pos = 0 ;
47+
48+ self -> sample = NULL ;
49+ self -> sample_remaining_buffer = NULL ;
50+ self -> sample_buffer_length = 0 ;
51+ self -> loop = false;
52+ self -> more_data = false;
4753}
4854
4955bool common_hal_audioeffects_echo_deinited (audioeffects_echo_obj_t * self ) {
@@ -68,7 +74,7 @@ uint32_t common_hal_audioeffects_echo_get_delay_ms(audioeffects_echo_obj_t *self
6874
6975void common_hal_audioeffects_echo_set_delay_ms (audioeffects_echo_obj_t * self , uint32_t delay_ms ) {
7076 self -> delay_ms = delay_ms ;
71- self -> echo_buffer_len = self -> sample_rate / 1000.0f * self -> delay_ms * sizeof ( uint32_t );
77+ self -> echo_buffer_len = self -> sample_rate / 1000.0f * self -> delay_ms * ( self -> channel_count * ( self -> bits_per_sample / 8 ) );
7278
7379 self -> echo_buffer = m_realloc (self -> echo_buffer , self -> echo_buffer_len );
7480 if (self -> echo_buffer == NULL ) {
@@ -118,59 +124,138 @@ bool common_hal_audioeffects_echo_get_playing(audioeffects_echo_obj_t *self) {
118124}
119125
120126void common_hal_audioeffects_echo_play (audioeffects_echo_obj_t * self , mp_obj_t sample , bool loop ) {
121- // check buffer size vs our buffer length
127+ if (audiosample_sample_rate (sample ) != self -> sample_rate ) {
128+ mp_raise_ValueError (MP_ERROR_TEXT ("The sample's sample rate does not match the effect's" ));
129+ }
130+ if (audiosample_channel_count (sample ) != self -> channel_count ) {
131+ mp_raise_ValueError (MP_ERROR_TEXT ("The sample's channel count does not match the effect's" ));
132+ }
133+ if (audiosample_bits_per_sample (sample ) != self -> bits_per_sample ) {
134+ mp_raise_ValueError (MP_ERROR_TEXT ("The sample's bits_per_sample does not match the effect's" ));
135+ }
136+ bool single_buffer ;
137+ bool samples_signed ;
138+ uint32_t max_buffer_length ;
139+ uint8_t spacing ;
140+ audiosample_get_buffer_structure (sample , false, & single_buffer , & samples_signed , & max_buffer_length , & spacing );
141+ if (samples_signed != self -> samples_signed ) {
142+ mp_raise_ValueError (MP_ERROR_TEXT ("The sample's signedness does not match the effect's" ));
143+ }
122144 self -> sample = sample ;
145+ self -> loop = loop ;
146+
147+ audiosample_reset_buffer (self -> sample , false, 0 );
148+ audioio_get_buffer_result_t result = audiosample_get_buffer (self -> sample , false, 0 , (uint8_t * * )& self -> sample_remaining_buffer , & self -> sample_buffer_length );
149+ // Track length in terms of words.
150+ self -> sample_buffer_length /= sizeof (uint32_t );
151+ self -> more_data = result == GET_BUFFER_MORE_DATA ;
152+
123153 return ;
124154}
125155
126156void common_hal_audioeffects_echo_stop (audioeffects_echo_obj_t * self ) {
127157 self -> sample = NULL ;
128- memset (self -> echo_buffer , 0 , self -> echo_buffer_len ); // clear echo
158+ // memset(self->echo_buffer, 0, self->echo_buffer_len); // clear echo
159+ // memset(self->buffer, 0, self->buffer_len);
129160 return ;
130161}
131162
132163audioio_get_buffer_result_t audioeffects_echo_get_buffer (audioeffects_echo_obj_t * self , bool single_channel_output , uint8_t channel ,
133164 uint8_t * * buffer , uint32_t * buffer_length ) {
134165
135- * buffer_length = self -> buffer_len ;
136- * buffer = (uint8_t * )self -> buffer ;
137-
138- if (self -> sample == NULL ) {
139-
140- } else {
141- // Get the sample's buffer
142- uint32_t * sample_buffer ;
143- uint32_t sample_buffer_len ;
144-
145- // audioio_get_buffer_result_t result =
146- audiosample_get_buffer (self -> sample , false, 0 , (uint8_t * * )& sample_buffer , & sample_buffer_len );
147-
148- uint32_t n = MIN (sample_buffer_len / sizeof (uint32_t ), (self -> buffer_len / sizeof (uint32_t )));
149- * buffer_length = n * sizeof (uint32_t );
150-
151- uint32_t echo_buf_len = self -> echo_buffer_len / sizeof (uint32_t );
152-
153- // pass the sample thru to our buffer adding in the echo
154- for (uint32_t i = 0 ; i < n ; i ++ ) {
155- if (self -> echo_buffer_read_pos >= echo_buf_len ) {
156- self -> echo_buffer_read_pos = 0 ;
166+ uint32_t * word_buffer = (uint32_t * )self -> buffer ;
167+ uint32_t length = self -> buffer_len / sizeof (uint32_t );
168+ uint32_t echo_buf_len = self -> echo_buffer_len / sizeof (uint32_t );
169+
170+ while (length != 0 ) {
171+ if (self -> sample_buffer_length == 0 ) {
172+ if (!self -> more_data ) {
173+ if (self -> loop ) {
174+ if (self -> sample ) {
175+ audiosample_reset_buffer (self -> sample , false, 0 );
176+ }
177+ } else {
178+ self -> sample = NULL ;
179+ }
180+ }
181+ if (self -> sample ) {
182+ // Load another buffer
183+ audioio_get_buffer_result_t result = audiosample_get_buffer (self -> sample , false, 0 , (uint8_t * * )& self -> sample_remaining_buffer , & self -> sample_buffer_length );
184+ // Track length in terms of words.
185+ self -> sample_buffer_length /= sizeof (uint32_t );
186+ self -> more_data = result == GET_BUFFER_MORE_DATA ;
157187 }
158-
159- uint32_t echo = self -> echo_buffer [self -> echo_buffer_read_pos ++ ];
160- self -> buffer [i ] = add16signed (mult16signed (echo , self -> decay ), sample_buffer [i ]);
161188 }
162189
163- // copy sample buffer to echo buf to play back later
164- // This now includes our current sound + previous echos
165- for (uint32_t i = 0 ; i < n ; i ++ ) {
166- if (self -> echo_buffer_write_pos >= echo_buf_len ) {
167- self -> echo_buffer_write_pos = 0 ;
190+ // If we have no sample keep the echo echoing
191+ if (self -> sample == NULL ) {
192+ if (MP_LIKELY (self -> bits_per_sample == 16 )) {
193+ if (MP_LIKELY (self -> samples_signed )) {
194+ for (uint32_t i = 0 ; i < length ; i ++ ) {
195+ if (self -> echo_buffer_read_pos >= echo_buf_len ) {
196+ self -> echo_buffer_read_pos = 0 ;
197+ }
198+
199+ uint32_t echo = self -> echo_buffer [self -> echo_buffer_read_pos ++ ];
200+ word_buffer [i ] = mult16signed (echo , self -> decay );
201+
202+ if (self -> echo_buffer_write_pos >= echo_buf_len ) {
203+ self -> echo_buffer_write_pos = 0 ;
204+ }
205+
206+ self -> echo_buffer [self -> echo_buffer_write_pos ++ ] = word_buffer [i ];
207+ }
208+ }
209+ }
210+ length = 0 ;
211+ } else {
212+ uint32_t n = MIN (self -> sample_buffer_length , length );
213+ uint32_t * sample_src = self -> sample_remaining_buffer ;
214+
215+ if (MP_LIKELY (self -> bits_per_sample == 16 )) {
216+ if (MP_LIKELY (self -> samples_signed )) {
217+ for (uint32_t i = 0 ; i < n ; i ++ ) {
218+ uint32_t sample_word = sample_src [i ];
219+ uint32_t echo = self -> echo_buffer [self -> echo_buffer_read_pos ++ ];
220+ word_buffer [i ] = add16signed (mult16signed (echo , self -> decay ), sample_word );
221+ self -> echo_buffer [self -> echo_buffer_write_pos ++ ] = add16signed (sample_word , word_buffer [i ]);
222+
223+ if (self -> echo_buffer_read_pos >= echo_buf_len ) {
224+ self -> echo_buffer_read_pos = 0 ;
225+ }
226+ if (self -> echo_buffer_write_pos >= echo_buf_len ) {
227+ self -> echo_buffer_write_pos = 0 ;
228+ }
229+ }
230+ } else {
231+ // for (uint32_t i = 0; i < n; i++) {
232+ // uint32_t sample_word = sample_src[i];
233+ // sample_word = tosigned16(sample_word);
234+ // word_buffer[i] = add16signed(mult16signed(sample_word, self->decay), word_buffer[i]);
235+ // }
236+ }
237+ } else {
238+ // uint16_t *hword_buffer = (uint16_t *)word_buffer;
239+ // uint16_t *sample_hsrc = (uint16_t *)sample_src;
240+ // for (uint32_t i = 0; i < n * 2; i++) {
241+ // uint32_t sample_word = unpack8(sample_hsrc[i]);
242+ // if (MP_LIKELY(!self->samples_signed)) {
243+ // sample_word = tosigned16(sample_word);
244+ // }
245+ // sample_word = mult16signed(sample_word, self->decay);
246+ // sample_word = add16signed(sample_word, unpack8(hword_buffer[i]));
247+ // hword_buffer[i] = pack8(sample_word);
248+ // }
168249 }
169250
170- self -> echo_buffer [self -> echo_buffer_write_pos ++ ] = add16signed (sample_buffer [i ], self -> buffer [i ]);
251+ length -= n ;
252+ word_buffer += n ;
253+ self -> sample_remaining_buffer += n ;
254+ self -> sample_buffer_length -= n ;
171255 }
172256 }
173-
257+ * buffer = (uint8_t * )self -> buffer ;
258+ * buffer_length = self -> buffer_len ;
174259 return GET_BUFFER_MORE_DATA ;
175260}
176261
@@ -179,11 +264,16 @@ void audioeffects_echo_get_buffer_structure(audioeffects_echo_obj_t *self, bool
179264
180265 if (self -> sample != NULL ) {
181266 audiosample_get_buffer_structure (self -> sample , single_channel_output , single_buffer , samples_signed , max_buffer_length , spacing );
267+ * single_buffer = false;
182268 * max_buffer_length = self -> buffer_len ;
183269 } else {
184- * single_buffer = false ;
270+ * single_buffer = true ;
185271 * samples_signed = true;
186272 * max_buffer_length = self -> buffer_len ;
187- * spacing = 1 ;
273+ if (single_channel_output ) {
274+ * spacing = self -> channel_count ;
275+ } else {
276+ * spacing = 1 ;
277+ }
188278 }
189279}
0 commit comments