25
25
* THE SOFTWARE.
26
26
*/
27
27
28
- #include "shared-bindings/audiomp3/MP3File .h"
28
+ #include "shared-bindings/audiomp3/MP3Decoder .h"
29
29
30
30
#include <stdint.h>
31
31
#include <string.h>
32
+ #include <math.h>
32
33
33
34
#include "py/mperrno.h"
34
35
#include "py/runtime.h"
35
36
36
- #include "shared-module/audiomp3/MP3File .h"
37
+ #include "shared-module/audiomp3/MP3Decoder .h"
37
38
#include "supervisor/shared/translate.h"
38
39
#include "lib/mp3/src/mp3common.h"
39
40
41
+ #define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t))
42
+
40
43
/** Fill the input buffer if it is less than half full.
41
44
*
42
45
* Returns true if the input buffer contains any useful data,
@@ -143,7 +146,7 @@ STATIC bool mp3file_get_next_frame_info(audiomp3_mp3file_obj_t* self, MP3FrameIn
143
146
do {
144
147
err = MP3GetNextFrameInfo (self -> decoder , fi , READ_PTR (self ));
145
148
if (err == ERR_MP3_NONE ) {
146
- break ;
149
+ break ;
147
150
}
148
151
CONSUME (self , 1 );
149
152
mp3file_find_sync_word (self );
@@ -165,7 +168,6 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
165
168
// than the two 4kB output buffers, except that the alignment allows to
166
169
// never allocate that extra frame buffer.
167
170
168
- self -> file = file ;
169
171
self -> inbuf_length = 2048 ;
170
172
self -> inbuf_offset = self -> inbuf_length ;
171
173
self -> inbuf = m_malloc (self -> inbuf_length , false);
@@ -181,40 +183,56 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
181
183
translate ("Couldn't allocate decoder" ));
182
184
}
183
185
184
- mp3file_find_sync_word (self );
185
- MP3FrameInfo fi ;
186
- if (!mp3file_get_next_frame_info (self , & fi )) {
187
- mp_raise_msg (& mp_type_RuntimeError ,
188
- translate ("Failed to parse MP3 file" ));
189
- }
190
-
191
- self -> sample_rate = fi .samprate ;
192
- self -> channel_count = fi .nChans ;
193
- self -> frame_buffer_size = fi .outputSamps * sizeof (int16_t );
194
-
195
186
if ((intptr_t )buffer & 1 ) {
196
187
buffer += 1 ; buffer_size -= 1 ;
197
188
}
198
- if (buffer_size >= 2 * self -> frame_buffer_size ) {
199
- self -> len = buffer_size / 2 / self -> frame_buffer_size * self -> frame_buffer_size ;
189
+ if (buffer_size >= 2 * MAX_BUFFER_LEN ) {
200
190
self -> buffers [0 ] = (int16_t * )(void * )buffer ;
201
- self -> buffers [1 ] = (int16_t * )(void * )buffer + self -> len ;
191
+ self -> buffers [1 ] = (int16_t * )(void * )( buffer + MAX_BUFFER_LEN ) ;
202
192
} else {
203
- self -> len = 2 * self -> frame_buffer_size ;
204
- self -> buffers [0 ] = m_malloc (self -> len , false);
193
+ self -> buffers [0 ] = m_malloc (MAX_BUFFER_LEN , false);
205
194
if (self -> buffers [0 ] == NULL ) {
206
195
common_hal_audiomp3_mp3file_deinit (self );
207
196
mp_raise_msg (& mp_type_MemoryError ,
208
197
translate ("Couldn't allocate first buffer" ));
209
198
}
210
199
211
- self -> buffers [1 ] = m_malloc (self -> len , false);
200
+ self -> buffers [1 ] = m_malloc (MAX_BUFFER_LEN , false);
212
201
if (self -> buffers [1 ] == NULL ) {
213
202
common_hal_audiomp3_mp3file_deinit (self );
214
203
mp_raise_msg (& mp_type_MemoryError ,
215
204
translate ("Couldn't allocate second buffer" ));
216
205
}
217
206
}
207
+
208
+ common_hal_audiomp3_mp3file_set_file (self , file );
209
+ }
210
+
211
+ void common_hal_audiomp3_mp3file_set_file (audiomp3_mp3file_obj_t * self , pyb_file_obj_t * file ) {
212
+ self -> file = file ;
213
+ f_lseek (& self -> file -> fp , 0 );
214
+ self -> inbuf_offset = self -> inbuf_length ;
215
+ self -> eof = 0 ;
216
+ self -> other_channel = -1 ;
217
+ mp3file_update_inbuf (self );
218
+ mp3file_find_sync_word (self );
219
+ // It **SHOULD** not be necessary to do this; the buffer should be filled
220
+ // with fresh content before it is returned by get_buffer(). The fact that
221
+ // this is necessary to avoid a glitch at the start of playback of a second
222
+ // track using the same decoder object means there's still a bug in
223
+ // get_buffer() that I didn't understand.
224
+ memset (self -> buffers [0 ], 0 , MAX_BUFFER_LEN );
225
+ memset (self -> buffers [1 ], 0 , MAX_BUFFER_LEN );
226
+ MP3FrameInfo fi ;
227
+ if (!mp3file_get_next_frame_info (self , & fi )) {
228
+ mp_raise_msg (& mp_type_RuntimeError ,
229
+ translate ("Failed to parse MP3 file" ));
230
+ }
231
+
232
+ self -> sample_rate = fi .samprate ;
233
+ self -> channel_count = fi .nChans ;
234
+ self -> frame_buffer_size = fi .outputSamps * sizeof (int16_t );
235
+ self -> len = 2 * self -> frame_buffer_size ;
218
236
}
219
237
220
238
void common_hal_audiomp3_mp3file_deinit (audiomp3_mp3file_obj_t * self ) {
@@ -280,7 +298,6 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t*
280
298
channel = 0 ;
281
299
}
282
300
283
- * bufptr = (uint8_t * )(self -> buffers [self -> buffer_index ] + channel );
284
301
* buffer_length = self -> frame_buffer_size ;
285
302
286
303
if (channel == self -> other_channel ) {
@@ -289,11 +306,12 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t*
289
306
return GET_BUFFER_MORE_DATA ;
290
307
}
291
308
292
- self -> other_channel = 1 - channel ;
293
- self -> other_buffer_index = self -> buffer_index ;
294
309
295
310
self -> buffer_index = !self -> buffer_index ;
311
+ self -> other_channel = 1 - channel ;
312
+ self -> other_buffer_index = self -> buffer_index ;
296
313
int16_t * buffer = (int16_t * )(void * )self -> buffers [self -> buffer_index ];
314
+ * bufptr = (uint8_t * )buffer ;
297
315
298
316
mp3file_skip_id3v2 (self );
299
317
if (!mp3file_find_sync_word (self )) {
@@ -322,3 +340,13 @@ void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool si
322
340
* spacing = 1 ;
323
341
}
324
342
}
343
+
344
+ float common_hal_audiomp3_mp3file_get_rms_level (audiomp3_mp3file_obj_t * self ) {
345
+ float sumsq = 0.f ;
346
+ // Assumes no DC component to the audio. Is that a safe assumption?
347
+ int16_t * buffer = (int16_t * )(void * )self -> buffers [self -> buffer_index ];
348
+ for (size_t i = 0 ; i < self -> frame_buffer_size / sizeof (int16_t ); i ++ ) {
349
+ sumsq += (float )buffer [i ] * buffer [i ];
350
+ }
351
+ return sqrtf (sumsq ) / (self -> frame_buffer_size / sizeof (int16_t ));
352
+ }
0 commit comments