shithub: mp3dec

Download patch

ref: 081e457b5a3a85275c9d0e7f867bbee68c0baed6
parent: e0c78630f834bc19b7ecc16638ebfcbfdad70299
author: Matthias Geier <Matthias.Geier@gmail.com>
date: Sat Aug 15 07:41:58 EDT 2020

minimp3_ex: add mp3dec_ex_read_frame() function

--- a/minimp3_ex.h
+++ b/minimp3_ex.h
@@ -101,6 +101,7 @@
 int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int flags);
 void mp3dec_ex_close(mp3dec_ex_t *dec);
 int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position);
+size_t mp3dec_ex_read_frame(mp3dec_ex_t *dec, mp3d_sample_t **buf, size_t max_samples);
 size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples);
 #ifndef MINIMP3_NO_STDIO
 /* stdio versions of file detect, load, iterate and stream */
@@ -843,7 +844,7 @@
     return 0;
 }
 
-size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples)
+size_t mp3dec_ex_read_frame(mp3dec_ex_t *dec, mp3d_sample_t **buf, size_t max_samples)
 {
     if (!dec || !buf)
     {
@@ -851,8 +852,8 @@
             dec->last_error = MP3D_E_PARAM;
         return 0;
     }
+    *buf = NULL;
     uint64_t end_offset = dec->end_offset ? dec->end_offset : dec->file.size;
-    size_t samples_requested = samples;
     int eof = 0;
     mp3dec_frame_info_t frame_info;
     memset(&frame_info, 0, sizeof(frame_info));
@@ -860,24 +861,8 @@
         return 0; /* at end of stream */
     if (dec->last_error)
         return 0; /* error eof state, seek can reset it */
-    if (dec->buffer_consumed < dec->buffer_samples)
+    while (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;
-        samples -= to_copy;
-    }
-    while (samples)
-    {
-        if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
-            break;
         const uint8_t *dec_buf;
         if (dec->io)
         {
@@ -900,7 +885,7 @@
             }
             dec_buf = dec->file.buffer + dec->input_consumed;
             if (!(dec->input_filled - dec->input_consumed))
-                break;
+                return 0;
             dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, dec->input_filled - dec->input_consumed, dec->buffer, &frame_info);
             dec->input_consumed += frame_info.frame_bytes;
         } else
@@ -908,7 +893,7 @@
             dec_buf = dec->file.buffer + dec->offset;
             uint64_t buf_size = end_offset - dec->offset;
             if (!buf_size)
-                break;
+                return 0;
             dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, MINIMP3_MIN(buf_size, (uint64_t)INT_MAX), dec->buffer, &frame_info);
         }
         dec->buffer_consumed = 0;
@@ -919,7 +904,7 @@
             )
         {
             dec->last_error = MP3D_E_DECODE;
-            break;
+            return 0;
         }
         if (dec->buffer_samples)
         {
@@ -930,17 +915,6 @@
                 dec->buffer_consumed += skip;
                 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;
-            samples -= to_copy;
         } else if (dec->to_skip)
         {   /* In mp3 decoding not always can start decode from any frame because of bit reservoir,
                count skip samples for such frames */
@@ -948,6 +922,39 @@
             dec->to_skip -= MINIMP3_MIN(frame_samples, dec->to_skip);
         }
         dec->offset += frame_info.frame_bytes;
+    }
+    size_t out_samples = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), max_samples);
+    if (dec->detected_samples)
+    {   /* count decoded samples to properly cut padding */
+        if (dec->cur_sample + out_samples >= dec->detected_samples)
+            out_samples = dec->detected_samples - dec->cur_sample;
+    }
+    dec->cur_sample += out_samples;
+    *buf = dec->buffer + dec->buffer_consumed;
+    dec->buffer_consumed += out_samples;
+    return out_samples;
+}
+
+size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples)
+{
+    if (!dec || !buf)
+    {
+        if (dec)
+            dec->last_error = MP3D_E_PARAM;
+        return 0;
+    }
+    size_t samples_requested = samples;
+    while (samples)
+    {
+        mp3d_sample_t *buf_frame = NULL;
+        size_t read_samples = mp3dec_ex_read_frame(dec, &buf_frame, samples);
+        if (!read_samples)
+        {
+            break;
+        }
+        memcpy(buf, buf_frame, read_samples * sizeof(mp3d_sample_t));
+        buf += read_samples;
+        samples -= read_samples;
     }
     return samples_requested - samples;
 }