From 22abf2df0236edcebd39481396e11b2d854cebfd Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Wed, 4 Dec 2024 13:51:18 -0600 Subject: [PATCH] MP3Decoder: clear out DSP data when opening a new stream The new test verifies that the first part of an MP3 decodes as expected even when the "open" method is used. Closes: #9705 --- shared-module/audiomp3/MP3Decoder.c | 12 +++++++++++ tests/circuitpython/issue9705.py | 30 ++++++++++++++++++++++++++++ tests/circuitpython/issue9705.py.exp | 16 +++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/circuitpython/issue9705.py create mode 100644 tests/circuitpython/issue9705.py.exp diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c index b135af758693..3d20ce43a846 100644 --- a/shared-module/audiomp3/MP3Decoder.c +++ b/shared-module/audiomp3/MP3Decoder.c @@ -20,6 +20,7 @@ #include "shared-module/audiomp3/MP3Decoder.h" #include "supervisor/background_callback.h" #include "lib/mp3/src/mp3common.h" +#include "lib/mp3/src/coder.h" #define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t)) @@ -360,6 +361,17 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t // get_buffer() that I didn't understand. memset(self->pcm_buffer[0], 0, MAX_BUFFER_LEN); memset(self->pcm_buffer[1], 0, MAX_BUFFER_LEN); + + /* important to do this - DSP primitives assume a bunch of state variables are 0 on first use */ + struct _MP3DecInfo *decoder = self->decoder; + memset(decoder->FrameHeaderPS, 0, sizeof(FrameHeader)); + memset(decoder->SideInfoPS, 0, sizeof(SideInfo)); + memset(decoder->ScaleFactorInfoPS, 0, sizeof(ScaleFactorInfo)); + memset(decoder->HuffmanInfoPS, 0, sizeof(HuffmanInfo)); + memset(decoder->DequantInfoPS, 0, sizeof(DequantInfo)); + memset(decoder->IMDCTInfoPS, 0, sizeof(IMDCTInfo)); + memset(decoder->SubbandInfoPS, 0, sizeof(SubbandInfo)); + MP3FrameInfo fi; bool result = mp3file_get_next_frame_info(self, &fi, true); background_callback_allow(); diff --git a/tests/circuitpython/issue9705.py b/tests/circuitpython/issue9705.py new file mode 100644 index 000000000000..90ebdc937553 --- /dev/null +++ b/tests/circuitpython/issue9705.py @@ -0,0 +1,30 @@ +import audiomp3, audiocore +import ulab.numpy as np + +TEST_FILE = __file__.rsplit("/", 1)[0] + "/../circuitpython-manual/audiocore/jeplayer-splash-44100-stereo.mp3" + +def normalized_rms_ulab(values): + values = np.frombuffer(values, dtype=np.int16) + # this function works with ndarrays only + minbuf = np.mean(values) + values = values - minbuf + samples_sum = np.sum(values * values) + return (samples_sum / len(values))**.5 + +def print_frame_loudness(decoder, n): + for i in range(n): + result, buf = audiocore.get_buffer(decoder) + print(f"{i} {result} {normalized_rms_ulab(buf):5.0f}") + print() + +# First frames +decoder = audiomp3.MP3Decoder(TEST_FILE) +print_frame_loudness(decoder, 8) + +# First frames (fresh decoder) +decoder = audiomp3.MP3Decoder(TEST_FILE) +print_frame_loudness(decoder, 2) + +# First frames (reopen) +decoder.open(TEST_FILE) +print_frame_loudness(decoder, 3) diff --git a/tests/circuitpython/issue9705.py.exp b/tests/circuitpython/issue9705.py.exp new file mode 100644 index 000000000000..944fb65c8103 --- /dev/null +++ b/tests/circuitpython/issue9705.py.exp @@ -0,0 +1,16 @@ +0 1 0 +1 1 4730 +2 1 27914 +3 1 28737 +4 1 29251 +5 1 29219 +6 1 28672 +7 1 28213 + +0 1 0 +1 1 4730 + +0 1 0 +1 1 4730 +2 1 27914 +