2525 * THE SOFTWARE.
2626 */
2727
28- #include "shared-bindings/audiomp3/MP3File .h"
28+ #include "shared-bindings/audiomp3/MP3Decoder .h"
2929
3030#include <stdint.h>
3131#include <string.h>
32+ #include <math.h>
3233
3334#include "py/mperrno.h"
3435#include "py/runtime.h"
3536
36- #include "shared-module/audiomp3/MP3File .h"
37+ #include "shared-module/audiomp3/MP3Decoder .h"
3738#include "supervisor/shared/translate.h"
3839#include "lib/mp3/src/mp3common.h"
3940
41+ #define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t))
42+
4043/** Fill the input buffer if it is less than half full.
4144 *
4245 * 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
143146 do {
144147 err = MP3GetNextFrameInfo (self -> decoder , fi , READ_PTR (self ));
145148 if (err == ERR_MP3_NONE ) {
146- break ;
149+ break ;
147150 }
148151 CONSUME (self , 1 );
149152 mp3file_find_sync_word (self );
@@ -165,7 +168,6 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
165168 // than the two 4kB output buffers, except that the alignment allows to
166169 // never allocate that extra frame buffer.
167170
168- self -> file = file ;
169171 self -> inbuf_length = 2048 ;
170172 self -> inbuf_offset = self -> inbuf_length ;
171173 self -> inbuf = m_malloc (self -> inbuf_length , false);
@@ -181,40 +183,56 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t* self,
181183 translate ("Couldn't allocate decoder" ));
182184 }
183185
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-
195186 if ((intptr_t )buffer & 1 ) {
196187 buffer += 1 ; buffer_size -= 1 ;
197188 }
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 ) {
200190 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 ) ;
202192 } 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);
205194 if (self -> buffers [0 ] == NULL ) {
206195 common_hal_audiomp3_mp3file_deinit (self );
207196 mp_raise_msg (& mp_type_MemoryError ,
208197 translate ("Couldn't allocate first buffer" ));
209198 }
210199
211- self -> buffers [1 ] = m_malloc (self -> len , false);
200+ self -> buffers [1 ] = m_malloc (MAX_BUFFER_LEN , false);
212201 if (self -> buffers [1 ] == NULL ) {
213202 common_hal_audiomp3_mp3file_deinit (self );
214203 mp_raise_msg (& mp_type_MemoryError ,
215204 translate ("Couldn't allocate second buffer" ));
216205 }
217206 }
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 ;
218236}
219237
220238void 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*
280298 channel = 0 ;
281299 }
282300
283- * bufptr = (uint8_t * )(self -> buffers [self -> buffer_index ] + channel );
284301 * buffer_length = self -> frame_buffer_size ;
285302
286303 if (channel == self -> other_channel ) {
@@ -289,11 +306,12 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t*
289306 return GET_BUFFER_MORE_DATA ;
290307 }
291308
292- self -> other_channel = 1 - channel ;
293- self -> other_buffer_index = self -> buffer_index ;
294309
295310 self -> buffer_index = !self -> buffer_index ;
311+ self -> other_channel = 1 - channel ;
312+ self -> other_buffer_index = self -> buffer_index ;
296313 int16_t * buffer = (int16_t * )(void * )self -> buffers [self -> buffer_index ];
314+ * bufptr = (uint8_t * )buffer ;
297315
298316 mp3file_skip_id3v2 (self );
299317 if (!mp3file_find_sync_word (self )) {
@@ -322,3 +340,13 @@ void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t* self, bool si
322340 * spacing = 1 ;
323341 }
324342}
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