shithub: mp3dec

Download patch

ref: 9719597ec6d609e5ea535172bde809be67ce1b5a
parent: 0ae65c429d96f8cae1a959e7b51294ea90aaa427
author: lieff <lieff@users.noreply.github.com>
date: Wed Feb 5 20:45:48 EST 2020

mp3dec_ex: handle padding for mp3dec_ex_read + test decoded length

--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -50,7 +50,7 @@
     mp3dec_t mp3d;
     mp3dec_map_info_t file;
     mp3dec_index_t index;
-    uint64_t offset, samples, detected_samples, start_offset, end_offset;
+    uint64_t offset, samples, detected_samples, cur_sample, start_offset, end_offset;
     mp3dec_frame_info_t info;
     mp3d_sample_t buffer[MINIMP3_MAX_SAMPLES_PER_FRAME];
 #ifndef MINIMP3_NO_STDIO
@@ -274,8 +274,8 @@
                 progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
         }
     } while (frame_bytes);
-    if (detected_samples)
-        info->samples = detected_samples;
+    if (detected_samples && info->samples > detected_samples)
+        info->samples = detected_samples; /* cut padding */
     /* reallocate to normal buffer size */
     if (allocated != info->samples*sizeof(mp3d_sample_t))
         info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));
@@ -419,8 +419,10 @@
     if (MP3D_SEEK_TO_BYTE == dec->seek_method)
     {
         dec->offset = position;
+        dec->cur_sample = 0;
         return 0;
     }
+    dec->cur_sample = position;
     position += dec->start_delay;
     if (0 == position)
     {   /* optimize seek to zero, no index needed */
@@ -499,9 +501,17 @@
     size_t samples_requested = samples;
     mp3dec_frame_info_t frame_info;
     memset(&frame_info, 0, sizeof(frame_info));
+    if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
+        return 0; /* at end of stream */
     if (dec->buffer_consumed < dec->buffer_samples)
     {
         size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
+        if (dec->detected_samples)
+        {   /* count decoded samples to properly cut padding */
+            if (dec->cur_sample + to_copy >= dec->detected_samples)
+                to_copy = dec->detected_samples - dec->cur_sample;
+            dec->cur_sample += to_copy;
+        }
         memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
         buf += to_copy;
         dec->buffer_consumed += to_copy;
@@ -509,6 +519,8 @@
     }
     while (samples)
     {
+        if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
+            break;
         const uint8_t *dec_buf = dec->file.buffer + dec->offset;
         uint64_t buf_size = end_offset - dec->offset;
         if (!buf_size)
@@ -525,6 +537,12 @@
                 dec->to_skip -= skip;
             }
             size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
+            if (dec->detected_samples)
+            {   /* ^ handle padding */
+                if (dec->cur_sample + to_copy >= dec->detected_samples)
+                    to_copy = dec->detected_samples - dec->cur_sample;
+                dec->cur_sample += to_copy;
+            }
             memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
             buf += to_copy;
             dec->buffer_consumed += to_copy;
--- a/minimp3_test.c
+++ b/minimp3_test.c
@@ -121,6 +121,7 @@
         info.samples = dec.samples;
         info.buffer  = malloc(dec.samples*sizeof(int16_t));
         info.hz      = dec.info.hz;
+        info.layer   = dec.info.layer;
         info.channels = dec.info.channels;
         if (position < 0)
         {
@@ -142,6 +143,12 @@
             printf("error: mp3dec_ex_read() readed less than expected\n");
             exit(1);
         }
+        readed = mp3dec_ex_read(&dec, info.buffer, 1);
+        if (readed)
+        {
+            printf("error: mp3dec_ex_read() readed more than expected\n");
+            exit(1);
+        }
         mp3dec_ex_close(&dec);
     } else
     {
@@ -172,7 +179,13 @@
         total_samples += info.samples;
         if (buf_ref)
         {
-            int max_samples = MINIMP3_MIN((size_t)ref_size/2, info.samples);
+            size_t ref_samples = ref_size/2;
+            if (ref_samples != info.samples && (ref_samples + 1152) != info.samples && (ref_samples + 2304) != info.samples && 3 == info.layer)
+            {   /* some standard vectors are for some reason a little shorter */
+                printf("error: reference and produced number of samples do not match (%d/%d)\n", (int)ref_samples, (int)info.samples);
+                exit(1);
+            }
+            int max_samples = MINIMP3_MIN(ref_samples, info.samples);
             for (i = 0; i < max_samples; i++)
             {
                 int MSEtemp = abs((int)buffer[i] - (int)(int16_t)read16le(&buf_ref[i*sizeof(int16_t)]));
@@ -195,7 +208,7 @@
     printf("rate=%d samples=%d max_diff=%d PSNR=%f\n", info.hz, total_samples, maxdiff, psnr);
     if (psnr < 96)
     {
-        printf("PSNR compliance failed\n");
+        printf("error: PSNR compliance failed\n");
         exit(1);
     }
 #endif