@@ -31,7 +31,7 @@ void common_hal_audioeffects_echo_construct(audioeffects_echo_obj_t *self, uint3
31
31
32
32
// calculate buffer size for the set delay
33
33
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 ) );
35
35
36
36
self -> echo_buffer = m_malloc (self -> echo_buffer_len );
37
37
if (self -> echo_buffer == NULL ) {
@@ -44,6 +44,12 @@ void common_hal_audioeffects_echo_construct(audioeffects_echo_obj_t *self, uint3
44
44
// write is what we send to the outgoing buffer
45
45
self -> echo_buffer_read_pos = self -> buffer_len / sizeof (uint32_t );
46
46
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;
47
53
}
48
54
49
55
bool 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
68
74
69
75
void common_hal_audioeffects_echo_set_delay_ms (audioeffects_echo_obj_t * self , uint32_t delay_ms ) {
70
76
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 ) );
72
78
73
79
self -> echo_buffer = m_realloc (self -> echo_buffer , self -> echo_buffer_len );
74
80
if (self -> echo_buffer == NULL ) {
@@ -118,59 +124,138 @@ bool common_hal_audioeffects_echo_get_playing(audioeffects_echo_obj_t *self) {
118
124
}
119
125
120
126
void 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
+ }
122
144
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
+
123
153
return ;
124
154
}
125
155
126
156
void common_hal_audioeffects_echo_stop (audioeffects_echo_obj_t * self ) {
127
157
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);
129
160
return ;
130
161
}
131
162
132
163
audioio_get_buffer_result_t audioeffects_echo_get_buffer (audioeffects_echo_obj_t * self , bool single_channel_output , uint8_t channel ,
133
164
uint8_t * * buffer , uint32_t * buffer_length ) {
134
165
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 ;
157
187
}
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 ]);
161
188
}
162
189
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
+ // }
168
249
}
169
250
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 ;
171
255
}
172
256
}
173
-
257
+ * buffer = (uint8_t * )self -> buffer ;
258
+ * buffer_length = self -> buffer_len ;
174
259
return GET_BUFFER_MORE_DATA ;
175
260
}
176
261
@@ -179,11 +264,16 @@ void audioeffects_echo_get_buffer_structure(audioeffects_echo_obj_t *self, bool
179
264
180
265
if (self -> sample != NULL ) {
181
266
audiosample_get_buffer_structure (self -> sample , single_channel_output , single_buffer , samples_signed , max_buffer_length , spacing );
267
+ * single_buffer = false;
182
268
* max_buffer_length = self -> buffer_len ;
183
269
} else {
184
- * single_buffer = false ;
270
+ * single_buffer = true ;
185
271
* samples_signed = true;
186
272
* 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
+ }
188
278
}
189
279
}
0 commit comments