1 #ifndef MINIMP3_EXT_H
2 #define MINIMP3_EXT_H
3 /*
4     https://github.com/lieff/minimp3
5     To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide.
6     This software is distributed without any warranty.
7     See <http://creativecommons.org/publicdomain/zero/1.0/>.
8 */
9 #include "minimp3.h"
10 
11 #define MP3D_SEEK_TO_BYTE   0
12 #define MP3D_SEEK_TO_SAMPLE 1
13 
14 #define MINIMP3_PREDECODE_FRAMES 2 /* frames to pre-decode and skip after seek (to fill internal structures) */
15 /*#define MINIMP3_SEEK_IDX_LINEAR_SEARCH*/ /* define to use linear index search instead of binary search on seek */
16 #define MINIMP3_IO_SIZE (128*1024) /* io buffer size for streaming functions, must be greater than MINIMP3_BUF_SIZE */
17 #define MINIMP3_BUF_SIZE (16*1024) /* buffer which can hold minimum 10 consecutive mp3 frames (~16KB) worst case */
18 #define MINIMP3_ENABLE_RING 0      /* enable hardware magic ring buffer if available, to make less input buffer memmove(s) in callback IO mode */
19 
20 #define MP3D_E_PARAM   -1
21 #define MP3D_E_MEMORY  -2
22 #define MP3D_E_IOERROR -3
23 #define MP3D_E_USER    -4  /* can be used to stop processing from callbacks without indicating specific error */
24 #define MP3D_E_DECODE  -5  /* decode error which can't be safely skipped, such as sample rate, layer and channels change */
25 
26 typedef struct
27 {
28     mp3d_sample_t *buffer;
29     size_t samples; /* channels included, byte size = samples*sizeof(mp3d_sample_t) */
30     int channels, hz, layer, avg_bitrate_kbps;
31 } mp3dec_file_info_t;
32 
33 typedef struct
34 {
35     const uint8_t *buffer;
36     size_t size;
37 } mp3dec_map_info_t;
38 
39 typedef struct
40 {
41     uint64_t sample;
42     uint64_t offset;
43 } mp3dec_frame_t;
44 
45 typedef struct
46 {
47     mp3dec_frame_t *frames;
48     size_t num_frames, capacity;
49 } mp3dec_index_t;
50 
51 typedef size_t (*MP3D_READ_CB)(void *buf, size_t size, void *user_data);
52 typedef int (*MP3D_SEEK_CB)(uint64_t position, void *user_data);
53 
54 typedef struct
55 {
56     MP3D_READ_CB read;
57     void *read_data;
58     MP3D_SEEK_CB seek;
59     void *seek_data;
60 } mp3dec_io_t;
61 
62 typedef struct
63 {
64     mp3dec_t mp3d;
65     mp3dec_map_info_t file;
66     mp3dec_io_t *io;
67     mp3dec_index_t index;
68     uint64_t offset, samples, detected_samples, cur_sample, start_offset, end_offset;
69     mp3dec_frame_info_t info;
70     mp3d_sample_t buffer[MINIMP3_MAX_SAMPLES_PER_FRAME];
71     size_t input_consumed, input_filled;
72     int is_file, seek_method, vbr_tag_found;
73     int free_format_bytes;
74     int buffer_samples, buffer_consumed, to_skip, start_delay;
75     int last_error;
76 } mp3dec_ex_t;
77 
78 typedef int (*MP3D_ITERATE_CB)(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, uint64_t offset, mp3dec_frame_info_t *info);
79 typedef int (*MP3D_PROGRESS_CB)(void *user_data, size_t file_size, uint64_t offset, mp3dec_frame_info_t *info);
80 
81 #ifdef __cplusplus
82 extern "C" {
83 #endif
84 
85 /* decode whole buffer block */
86 int mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
87 int mp3dec_load_cb(mp3dec_t *dec, mp3dec_io_t *io, uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
88 /* iterate through frames */
89 int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
90 int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
91 /* streaming decoder with seeking capability */
92 int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method);
93 int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int seek_method);
94 void mp3dec_ex_close(mp3dec_ex_t *dec);
95 int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position);
96 size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples);
97 #ifndef MINIMP3_NO_STDIO
98 /* stdio versions of file load, iterate and stream */
99 int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
100 int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data);
101 int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int seek_method);
102 #ifdef _WIN32
103 int mp3dec_load_w(mp3dec_t *dec, const wchar_t *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data);
104 int mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data);
105 int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int seek_method);
106 #endif
107 #endif
108 
109 #ifdef __cplusplus
110 }
111 #endif
112 #endif /*MINIMP3_EXT_H*/
113 
114 #ifdef MINIMP3_IMPLEMENTATION
115 #include <limits.h>
116 
mp3dec_skip_id3v1(const uint8_t * buf,size_t * pbuf_size)117 static void mp3dec_skip_id3v1(const uint8_t *buf, size_t *pbuf_size)
118 {
119     size_t buf_size = *pbuf_size;
120 #ifndef MINIMP3_NOSKIP_ID3V1
121     if (buf_size > 128 && !memcmp(buf + buf_size - 128, "TAG", 3))
122     {
123         buf_size -= 128;
124         if (buf_size > 227 && !memcmp(buf + buf_size - 227, "TAG+", 4))
125             buf_size -= 227;
126     }
127 #endif
128 #ifndef MINIMP3_NOSKIP_APEV2
129     if (buf_size > 32 && !memcmp(buf + buf_size - 32, "APETAGEX", 8))
130     {
131         buf_size -= 32;
132     }
133 #endif
134     *pbuf_size = buf_size;
135 }
136 
mp3dec_skip_id3v2(const uint8_t * buf,size_t buf_size)137 static size_t mp3dec_skip_id3v2(const uint8_t *buf, size_t buf_size)
138 {
139 #define MINIMP3_ID3_DETECT_SIZE 10
140 #ifndef MINIMP3_NOSKIP_ID3V2
141     if (buf_size >= MINIMP3_ID3_DETECT_SIZE && !memcmp(buf, "ID3", 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) || (buf[8] & 0x80) || (buf[9] & 0x80)))
142     {
143         size_t id3v2size = (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10;
144         if ((buf[5] & 16))
145             id3v2size += 10; /* footer */
146         return id3v2size;
147     }
148 #endif
149     return 0;
150 }
151 
mp3dec_skip_id3(const uint8_t ** pbuf,size_t * pbuf_size)152 static void mp3dec_skip_id3(const uint8_t **pbuf, size_t *pbuf_size)
153 {
154     uint8_t *buf = (uint8_t *)(*pbuf);
155     size_t buf_size = *pbuf_size;
156     size_t id3v2size = mp3dec_skip_id3v2(buf, buf_size);
157     if (id3v2size)
158     {
159         if (id3v2size >= buf_size)
160             id3v2size = buf_size;
161         buf      += id3v2size;
162         buf_size -= id3v2size;
163     }
164     mp3dec_skip_id3v1(buf, &buf_size);
165     *pbuf = (const uint8_t *)buf;
166     *pbuf_size = buf_size;
167 }
168 
mp3dec_check_vbrtag(const uint8_t * frame,int frame_size,uint32_t * frames,int * delay,int * padding)169 static int mp3dec_check_vbrtag(const uint8_t *frame, int frame_size, uint32_t *frames, int *delay, int *padding)
170 {
171     static const char g_xing_tag[4] = { 'X', 'i', 'n', 'g' };
172     static const char g_info_tag[4] = { 'I', 'n', 'f', 'o' };
173 #define FRAMES_FLAG     1
174 #define BYTES_FLAG      2
175 #define TOC_FLAG        4
176 #define VBR_SCALE_FLAG  8
177     /* Side info offsets after header:
178     /                Mono  Stereo
179     /  MPEG1          17     32
180     /  MPEG2 & 2.5     9     17*/
181     bs_t bs[1];
182     L3_gr_info_t gr_info[4];
183     bs_init(bs, frame + HDR_SIZE, frame_size - HDR_SIZE);
184     if (HDR_IS_CRC(frame))
185         get_bits(bs, 16);
186     if (L3_read_side_info(bs, gr_info, frame) < 0)
187         return 0; /* side info corrupted */
188 
189     const uint8_t *tag = frame + HDR_SIZE + bs->pos/8;
190     if (memcmp(g_xing_tag, tag, 4) && memcmp(g_info_tag, tag, 4))
191         return 0;
192     int flags = tag[7];
193     if (!((flags & FRAMES_FLAG)))
194         return 0;
195     tag += 8;
196     *frames = (uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
197     tag += 4;
198     if (flags & BYTES_FLAG)
199         tag += 4;
200     if (flags & TOC_FLAG)
201         tag += 100;
202     if (flags & VBR_SCALE_FLAG)
203         tag += 4;
204     *delay = *padding = 0;
205     if (*tag)
206     {   /* extension, LAME, Lavc, etc. Should be the same structure. */
207         tag += 21;
208         if (tag - frame + 14 >= frame_size)
209             return 0;
210         *delay   = ((tag[0] << 4) | (tag[1] >> 4)) + (528 + 1);
211         *padding = (((tag[1] & 0xF) << 8) | tag[2]) - (528 + 1);
212     }
213     return 1;
214 }
215 
mp3dec_load_buf(mp3dec_t * dec,const uint8_t * buf,size_t buf_size,mp3dec_file_info_t * info,MP3D_PROGRESS_CB progress_cb,void * user_data)216 int mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
217 {
218     return mp3dec_load_cb(dec, 0, (uint8_t *)buf, buf_size, info, progress_cb, user_data);
219 }
220 
mp3dec_load_cb(mp3dec_t * dec,mp3dec_io_t * io,uint8_t * buf,size_t buf_size,mp3dec_file_info_t * info,MP3D_PROGRESS_CB progress_cb,void * user_data)221 int mp3dec_load_cb(mp3dec_t *dec, mp3dec_io_t *io, uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
222 {
223     uint64_t detected_samples = 0;
224     size_t orig_buf_size = buf_size;
225     int to_skip = 0;
226     mp3dec_frame_info_t frame_info;
227     memset(info, 0, sizeof(*info));
228     memset(&frame_info, 0, sizeof(frame_info));
229     if (!dec || !buf || !info || (size_t)-1 == buf_size)
230         return MP3D_E_PARAM;
231 
232     /* skip id3 */
233     size_t filled = 0, consumed = 0;
234     int eof = 0, ret = 0;
235     if (io)
236     {
237         if (io->seek(0, io->seek_data))
238             return MP3D_E_IOERROR;
239         filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data);
240         if (filled > MINIMP3_ID3_DETECT_SIZE)
241             return MP3D_E_IOERROR;
242         if (MINIMP3_ID3_DETECT_SIZE != filled)
243             return 0;
244         size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
245         if (id3v2size)
246         {
247             if (io->seek(id3v2size, io->seek_data))
248                 return MP3D_E_IOERROR;
249             filled = io->read(buf, buf_size, io->read_data);
250             if (filled > buf_size)
251                 return MP3D_E_IOERROR;
252         } else
253         {
254             size_t readed = io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
255             if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
256                 return MP3D_E_IOERROR;
257             filled += readed;
258         }
259         if (filled < MINIMP3_BUF_SIZE)
260             mp3dec_skip_id3v1(buf, &filled);
261     } else
262     {
263         mp3dec_skip_id3((const uint8_t **)&buf, &buf_size);
264         if (!buf_size)
265             return 0;
266     }
267     /* try to make allocation size assumption by first frame or vbr tag */
268     mp3dec_init(dec);
269     int samples;
270     do
271     {
272         uint32_t frames;
273         int i, delay, padding, free_format_bytes = 0, frame_size = 0;
274         const uint8_t *hdr;
275         if (io)
276         {
277             if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
278             {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
279                 memmove(buf, buf + consumed, filled - consumed);
280                 filled -= consumed;
281                 consumed = 0;
282                 size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
283                 if (readed > (buf_size - filled))
284                     return MP3D_E_IOERROR;
285                 if (readed != (buf_size - filled))
286                     eof = 1;
287                 filled += readed;
288                 if (eof)
289                     mp3dec_skip_id3v1(buf, &filled);
290             }
291             i = mp3d_find_frame(buf + consumed, filled - consumed, &free_format_bytes, &frame_size);
292             consumed += i;
293             hdr = buf + consumed;
294         } else
295         {
296             i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
297             buf      += i;
298             buf_size -= i;
299             hdr = buf;
300         }
301         if (i && !frame_size)
302             continue;
303         if (!frame_size)
304             return 0;
305         frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
306         frame_info.hz = hdr_sample_rate_hz(hdr);
307         frame_info.layer = 4 - HDR_GET_LAYER(hdr);
308         frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
309         frame_info.frame_bytes = frame_size;
310         samples = hdr_frame_samples(hdr)*frame_info.channels;
311         if (mp3dec_check_vbrtag(hdr, frame_size, &frames, &delay, &padding))
312         {
313             padding *= frame_info.channels;
314             to_skip = delay*frame_info.channels;
315             detected_samples = samples*(uint64_t)frames;
316             if (detected_samples >= (uint64_t)to_skip)
317                 detected_samples -= to_skip;
318             if (padding > 0 && detected_samples >= (uint64_t)padding)
319                 detected_samples -= padding;
320             if (!detected_samples)
321                 return 0;
322             if (io)
323             {
324                 consumed += frame_size;
325             } else
326             {
327                 buf      += frame_size;
328                 buf_size -= frame_size;
329             }
330         }
331         break;
332     } while(1);
333     size_t allocated = MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t);
334     if (detected_samples)
335         allocated += detected_samples*sizeof(mp3d_sample_t);
336     else
337         allocated += (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t);
338     info->buffer = (mp3d_sample_t*)malloc(allocated);
339     if (!info->buffer)
340         return MP3D_E_MEMORY;
341     /* save info */
342     info->channels = frame_info.channels;
343     info->hz       = frame_info.hz;
344     info->layer    = frame_info.layer;
345     /* decode all frames */
346     size_t avg_bitrate_kbps = 0, frames = 0;
347     do
348     {
349         if ((allocated - info->samples*sizeof(mp3d_sample_t)) < MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t))
350         {
351             allocated *= 2;
352             info->buffer = (mp3d_sample_t*)realloc(info->buffer, allocated);
353         }
354         if (io)
355         {
356             if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
357             {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
358                 memmove(buf, buf + consumed, filled - consumed);
359                 filled -= consumed;
360                 consumed = 0;
361                 size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
362                 if (readed != (buf_size - filled))
363                     eof = 1;
364                 filled += readed;
365                 if (eof)
366                     mp3dec_skip_id3v1(buf, &filled);
367             }
368             samples = mp3dec_decode_frame(dec, buf + consumed, filled - consumed, info->buffer + info->samples, &frame_info);
369             consumed += frame_info.frame_bytes;
370         } else
371         {
372             samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), info->buffer + info->samples, &frame_info);
373             buf      += frame_info.frame_bytes;
374             buf_size -= frame_info.frame_bytes;
375         }
376         if (samples)
377         {
378             if (info->hz != frame_info.hz || info->layer != frame_info.layer)
379             {
380                 ret = MP3D_E_DECODE;
381                 break;
382             }
383             if (info->channels && info->channels != frame_info.channels)
384             {
385 #ifdef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
386                 info->channels = 0; /* mark file with mono-stereo transition */
387 #else
388                 ret = MP3D_E_DECODE;
389                 break;
390 #endif
391             }
392             samples *= frame_info.channels;
393             if (to_skip)
394             {
395                 size_t skip = MINIMP3_MIN(samples, to_skip);
396                 to_skip -= skip;
397                 samples -= skip;
398                 memmove(info->buffer, info->buffer + skip, samples);
399             }
400             info->samples += samples;
401             avg_bitrate_kbps += frame_info.bitrate_kbps;
402             frames++;
403             if (progress_cb)
404             {
405                 ret = progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
406                 if (ret)
407                     break;
408             }
409         }
410     } while (frame_info.frame_bytes);
411     if (detected_samples && info->samples > detected_samples)
412         info->samples = detected_samples; /* cut padding */
413     /* reallocate to normal buffer size */
414     if (allocated != info->samples*sizeof(mp3d_sample_t))
415         info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));
416     if (frames)
417         info->avg_bitrate_kbps = avg_bitrate_kbps/frames;
418     return ret;
419 }
420 
mp3dec_iterate_buf(const uint8_t * buf,size_t buf_size,MP3D_ITERATE_CB callback,void * user_data)421 int mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
422 {
423     const uint8_t *orig_buf = buf;
424     if (!buf || (size_t)-1 == buf_size)
425         return MP3D_E_PARAM;
426     /* skip id3 */
427     mp3dec_skip_id3(&buf, &buf_size);
428     if (!buf_size)
429         return 0;
430     mp3dec_frame_info_t frame_info;
431     memset(&frame_info, 0, sizeof(frame_info));
432     do
433     {
434         int free_format_bytes = 0, frame_size = 0, ret;
435         int i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
436         buf      += i;
437         buf_size -= i;
438         if (i && !frame_size)
439             continue;
440         if (!frame_size)
441             break;
442         const uint8_t *hdr = buf;
443         frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
444         frame_info.hz = hdr_sample_rate_hz(hdr);
445         frame_info.layer = 4 - HDR_GET_LAYER(hdr);
446         frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
447         frame_info.frame_bytes = frame_size;
448 
449         if (callback)
450         {
451             if ((ret = callback(user_data, hdr, frame_size, free_format_bytes, buf_size, hdr - orig_buf, &frame_info)))
452                 return ret;
453         }
454         buf      += frame_size;
455         buf_size -= frame_size;
456     } while (1);
457     return 0;
458 }
459 
mp3dec_iterate_cb(mp3dec_io_t * io,uint8_t * buf,size_t buf_size,MP3D_ITERATE_CB callback,void * user_data)460 int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
461 {
462     if (!io || !buf || (size_t)-1 == buf_size || buf_size < MINIMP3_BUF_SIZE)
463         return MP3D_E_PARAM;
464     size_t filled = io->read(buf, MINIMP3_ID3_DETECT_SIZE, io->read_data), consumed = 0;
465     uint64_t readed = 0;
466     mp3dec_frame_info_t frame_info;
467     int eof = 0;
468     memset(&frame_info, 0, sizeof(frame_info));
469     if (filled > MINIMP3_ID3_DETECT_SIZE)
470         return MP3D_E_IOERROR;
471     if (MINIMP3_ID3_DETECT_SIZE != filled)
472         return 0;
473     size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
474     if (id3v2size)
475     {
476         if (io->seek(id3v2size, io->seek_data))
477             return MP3D_E_IOERROR;
478         filled = io->read(buf, buf_size, io->read_data);
479         if (filled > buf_size)
480             return MP3D_E_IOERROR;
481         readed += id3v2size;
482     } else
483     {
484         size_t readed = io->read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io->read_data);
485         if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
486             return MP3D_E_IOERROR;
487         filled += readed;
488     }
489     if (filled < MINIMP3_BUF_SIZE)
490         mp3dec_skip_id3v1(buf, &filled);
491     do
492     {
493         int free_format_bytes = 0, frame_size = 0, ret;
494         int i = mp3d_find_frame(buf + consumed, filled - consumed, &free_format_bytes, &frame_size);
495         if (i && !frame_size)
496         {
497             consumed += i;
498             continue;
499         }
500         if (!frame_size)
501             break;
502         const uint8_t *hdr = buf + consumed + i;
503         frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
504         frame_info.hz = hdr_sample_rate_hz(hdr);
505         frame_info.layer = 4 - HDR_GET_LAYER(hdr);
506         frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
507         frame_info.frame_bytes = frame_size;
508 
509         readed += i;
510         if (callback)
511         {
512             if ((ret = callback(user_data, hdr, frame_size, free_format_bytes, filled - consumed, readed, &frame_info)))
513                 return ret;
514         }
515         readed += frame_size;
516         consumed += i + frame_size;
517         if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
518         {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
519             memmove(buf, buf + consumed, filled - consumed);
520             filled -= consumed;
521             consumed = 0;
522             size_t readed = io->read(buf + filled, buf_size - filled, io->read_data);
523             if (readed > (buf_size - filled))
524                 return MP3D_E_IOERROR;
525             if (readed != (buf_size - filled))
526                 eof = 1;
527             filled += readed;
528             if (eof)
529                 mp3dec_skip_id3v1(buf, &filled);
530         }
531     } while (1);
532     return 0;
533 }
534 
mp3dec_load_index(void * user_data,const uint8_t * frame,int frame_size,int free_format_bytes,size_t buf_size,uint64_t offset,mp3dec_frame_info_t * info)535 static int mp3dec_load_index(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, uint64_t offset, mp3dec_frame_info_t *info)
536 {
537     mp3dec_frame_t *idx_frame;
538     mp3dec_ex_t *dec = (mp3dec_ex_t *)user_data;
539     if (!dec->index.frames && !dec->vbr_tag_found)
540     {   /* detect VBR tag and try to avoid full scan */
541         uint32_t frames;
542         int delay, padding;
543         dec->info = *info;
544         dec->start_offset = dec->offset = offset;
545         dec->end_offset   = offset + buf_size;
546         dec->free_format_bytes = free_format_bytes; /* should not change */
547         if (mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding))
548         {
549             padding *= info->channels;
550             dec->start_delay = dec->to_skip = delay*info->channels;
551             dec->samples = hdr_frame_samples(frame)*info->channels*(uint64_t)frames;
552             if (dec->samples >= (uint64_t)dec->start_delay)
553                 dec->samples -= dec->start_delay;
554             if (padding > 0 && dec->samples >= (uint64_t)padding)
555                 dec->samples -= padding;
556             dec->detected_samples = dec->samples;
557             dec->start_offset = dec->offset = offset + frame_size;
558             dec->vbr_tag_found = 1;
559             return MP3D_E_USER;
560         }
561     }
562     if (dec->index.num_frames + 1 > dec->index.capacity)
563     {
564         if (!dec->index.capacity)
565             dec->index.capacity = 4096;
566         else
567             dec->index.capacity *= 2;
568         dec->index.frames = (mp3dec_frame_t *)realloc((void*)dec->index.frames, sizeof(mp3dec_frame_t)*dec->index.capacity);
569         if (!dec->index.frames)
570             return MP3D_E_MEMORY;
571     }
572     idx_frame = &dec->index.frames[dec->index.num_frames++];
573     idx_frame->offset = offset;
574     idx_frame->sample = dec->samples;
575     if (!dec->buffer_samples && dec->index.num_frames < 256)
576     {   /* for some cutted mp3 frames, bit-reservoir not filled and decoding can't be started from first frames */
577         /* try to decode up to 255 first frames till samples starts to decode */
578         dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, frame, MINIMP3_MIN(buf_size, (size_t)INT_MAX), dec->buffer, info);
579         dec->samples += dec->buffer_samples*info->channels;
580     } else
581         dec->samples += hdr_frame_samples(frame)*info->channels;
582     return 0;
583 }
584 
mp3dec_ex_open_buf(mp3dec_ex_t * dec,const uint8_t * buf,size_t buf_size,int seek_method)585 int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method)
586 {
587     if (!dec || !buf || (size_t)-1 == buf_size)
588         return MP3D_E_PARAM;
589     memset(dec, 0, sizeof(*dec));
590     dec->file.buffer = buf;
591     dec->file.size   = buf_size;
592     dec->seek_method = seek_method;
593     mp3dec_init(&dec->mp3d);
594     if (MP3D_SEEK_TO_SAMPLE == dec->seek_method)
595     {
596         int ret = mp3dec_iterate_buf(dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
597         if (ret && MP3D_E_USER != ret)
598             return ret;
599         mp3dec_init(&dec->mp3d);
600         dec->buffer_samples = 0;
601     }
602     return 0;
603 }
604 
605 #ifndef MINIMP3_SEEK_IDX_LINEAR_SEARCH
mp3dec_idx_binary_search(mp3dec_index_t * idx,uint64_t position)606 static size_t mp3dec_idx_binary_search(mp3dec_index_t *idx, uint64_t position)
607 {
608     size_t end = idx->num_frames, start = 0, index = 0;
609     while (start <= end)
610     {
611         size_t mid = (start + end) / 2;
612         if (idx->frames[mid].sample >= position)
613         {   /* move left side. */
614             if (idx->frames[mid].sample == position)
615                 return mid;
616             end = mid - 1;
617         }  else
618         {   /* move to right side */
619             index = mid;
620             start = mid + 1;
621             if (start == idx->num_frames)
622                 break;
623         }
624     }
625     return index;
626 }
627 #endif
628 
mp3dec_ex_seek(mp3dec_ex_t * dec,uint64_t position)629 int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position)
630 {
631     size_t i;
632     if (!dec)
633         return MP3D_E_PARAM;
634     if (MP3D_SEEK_TO_BYTE == dec->seek_method)
635     {
636         if (dec->io)
637         {
638             if (dec->io->seek(position, dec->io->seek_data))
639                 return MP3D_E_IOERROR;
640         } else
641         {
642             dec->offset = MINIMP3_MIN(position, dec->file.size);
643         }
644         dec->cur_sample = 0;
645         goto do_exit;
646     }
647     dec->cur_sample = position;
648     position += dec->start_delay;
649     if (0 == position)
650     {   /* optimize seek to zero, no index needed */
651 seek_zero:
652         dec->offset  = dec->start_offset;
653         dec->to_skip = 0;
654         goto do_exit;
655     }
656     if (!dec->index.frames && dec->vbr_tag_found)
657     {   /* no index created yet (vbr tag used to calculate track length) */
658         dec->samples = 0;
659         dec->buffer_samples = 0;
660         if (dec->io)
661         {
662             if (dec->io->seek(dec->start_offset, dec->io->seek_data))
663                 return MP3D_E_IOERROR;
664             int ret = mp3dec_iterate_cb(dec->io, (uint8_t *)dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
665             if (ret && MP3D_E_USER != ret)
666                 return ret;
667         } else
668         {
669             int ret = mp3dec_iterate_buf(dec->file.buffer + dec->start_offset, dec->file.size - dec->start_offset, mp3dec_load_index, dec);
670             if (ret && MP3D_E_USER != ret)
671                 return ret;
672         }
673         for (i = 0; i < dec->index.num_frames; i++)
674             dec->index.frames[i].offset += dec->start_offset;
675         dec->samples = dec->detected_samples;
676     }
677     if (!dec->index.frames)
678         goto seek_zero; /* no frames in file - seek to zero */
679 #ifdef MINIMP3_SEEK_IDX_LINEAR_SEARCH
680     for (i = 0; i < dec->index.num_frames; i++)
681     {
682         if (dec->index.frames[i].sample >= position)
683             break;
684     }
685 #else
686     i = mp3dec_idx_binary_search(&dec->index, position);
687 #endif
688     if (i)
689     {
690         int to_fill_bytes = 511;
691         int skip_frames = MINIMP3_PREDECODE_FRAMES
692 #ifdef MINIMP3_SEEK_IDX_LINEAR_SEARCH
693          + ((dec->index.frames[i].sample == position) ? 0 : 1)
694 #endif
695         ;
696         i -= MINIMP3_MIN(i, (size_t)skip_frames);
697         if (3 == dec->info.layer)
698         {
699             while (i && to_fill_bytes)
700             {   /* make sure bit-reservoir is filled when we start decoding */
701                 bs_t bs[1];
702                 L3_gr_info_t gr_info[4];
703                 int frame_bytes, frame_size;
704                 const uint8_t *hdr;
705                 if (dec->io)
706                 {
707                     hdr = dec->file.buffer;
708                     if (dec->io->seek(dec->index.frames[i - 1].offset, dec->io->seek_data))
709                         return MP3D_E_IOERROR;
710                     size_t readed = dec->io->read((uint8_t *)hdr, HDR_SIZE, dec->io->read_data);
711                     if (readed != HDR_SIZE)
712                         return MP3D_E_IOERROR;
713                     frame_size = hdr_frame_bytes(hdr, dec->free_format_bytes) + hdr_padding(hdr);
714                     readed = dec->io->read((uint8_t *)hdr + HDR_SIZE, frame_size - HDR_SIZE, dec->io->read_data);
715                     if (readed != (size_t)(frame_size - HDR_SIZE))
716                         return MP3D_E_IOERROR;
717                     bs_init(bs, hdr + HDR_SIZE, frame_size - HDR_SIZE);
718                 } else
719                 {
720                     hdr = dec->file.buffer + dec->index.frames[i - 1].offset;
721                     frame_size = hdr_frame_bytes(hdr, dec->free_format_bytes) + hdr_padding(hdr);
722                     bs_init(bs, hdr + HDR_SIZE, frame_size - HDR_SIZE);
723                 }
724                 if (HDR_IS_CRC(hdr))
725                     get_bits(bs, 16);
726                 i--;
727                 if (L3_read_side_info(bs, gr_info, hdr) < 0)
728                     break; /* frame not decodable, we can start from here */
729                 frame_bytes = (bs->limit - bs->pos)/8;
730                 to_fill_bytes -= MINIMP3_MIN(to_fill_bytes, frame_bytes);
731             }
732         }
733     }
734     dec->offset = dec->index.frames[i].offset;
735     dec->to_skip = position - dec->index.frames[i].sample;
736     while ((i + 1) < dec->index.num_frames && !dec->index.frames[i].sample && !dec->index.frames[i + 1].sample)
737     {   /* skip not decodable first frames */
738         const uint8_t *hdr = dec->file.buffer + dec->index.frames[i].offset;
739         dec->to_skip += hdr_frame_samples(hdr)*dec->info.channels;
740         i++;
741     }
742 do_exit:
743     if (dec->io)
744     {
745         if (dec->io->seek(dec->offset, dec->io->seek_data))
746             return MP3D_E_IOERROR;
747     }
748     dec->buffer_samples  = 0;
749     dec->buffer_consumed = 0;
750     dec->input_consumed  = 0;
751     dec->input_filled    = 0;
752     dec->last_error      = 0;
753     mp3dec_init(&dec->mp3d);
754     return 0;
755 }
756 
mp3dec_ex_read(mp3dec_ex_t * dec,mp3d_sample_t * buf,size_t samples)757 size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples)
758 {
759     if (!dec || !buf)
760         return MP3D_E_PARAM;
761     uint64_t end_offset = dec->end_offset ? dec->end_offset : dec->file.size;
762     size_t samples_requested = samples;
763     int eof = 0;
764     mp3dec_frame_info_t frame_info;
765     memset(&frame_info, 0, sizeof(frame_info));
766     if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
767         return 0; /* at end of stream */
768     if (dec->last_error)
769         return 0; /* error eof state, seek can reset it */
770     if (dec->buffer_consumed < dec->buffer_samples)
771     {
772         size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
773         if (dec->detected_samples)
774         {   /* count decoded samples to properly cut padding */
775             if (dec->cur_sample + to_copy >= dec->detected_samples)
776                 to_copy = dec->detected_samples - dec->cur_sample;
777         }
778         dec->cur_sample += to_copy;
779         memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
780         buf += to_copy;
781         dec->buffer_consumed += to_copy;
782         samples -= to_copy;
783     }
784     while (samples)
785     {
786         if (dec->detected_samples && dec->cur_sample >= dec->detected_samples)
787             break;
788         const uint8_t *dec_buf;
789         if (dec->io)
790         {
791             if (!eof && (dec->input_filled - dec->input_consumed) < MINIMP3_BUF_SIZE)
792             {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
793                 memmove((uint8_t*)dec->file.buffer, (uint8_t*)dec->file.buffer + dec->input_consumed, dec->input_filled - dec->input_consumed);
794                 dec->input_filled -= dec->input_consumed;
795                 dec->input_consumed = 0;
796                 size_t readed = dec->io->read((uint8_t*)dec->file.buffer + dec->input_filled, dec->file.size - dec->input_filled, dec->io->read_data);
797                 if (readed > (dec->file.size - dec->input_filled))
798                     dec->last_error = MP3D_E_IOERROR;
799                 if (readed != (dec->file.size - dec->input_filled))
800                     eof = 1;
801                 dec->input_filled += readed;
802                 if (eof)
803                     mp3dec_skip_id3v1((uint8_t*)dec->file.buffer, &dec->input_filled);
804             }
805             dec_buf = dec->file.buffer + dec->input_consumed;
806             if (!(dec->input_filled - dec->input_consumed))
807                 break;
808             dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, dec->input_filled - dec->input_consumed, dec->buffer, &frame_info);
809             dec->input_consumed += frame_info.frame_bytes;
810         } else
811         {
812             dec_buf = dec->file.buffer + dec->offset;
813             uint64_t buf_size = end_offset - dec->offset;
814             if (!buf_size)
815                 break;
816             dec->buffer_samples = mp3dec_decode_frame(&dec->mp3d, dec_buf, MINIMP3_MIN(buf_size, (uint64_t)INT_MAX), dec->buffer, &frame_info);
817         }
818         dec->buffer_consumed = 0;
819         if (dec->info.hz != frame_info.hz || dec->info.layer != frame_info.layer
820 #ifndef MINIMP3_ALLOW_MONO_STEREO_TRANSITION
821             || dec->info.channels != frame_info.channels
822 #endif
823             )
824         {
825             dec->last_error = MP3D_E_DECODE;
826             break;
827         }
828         if (dec->buffer_samples)
829         {
830             dec->buffer_samples *= frame_info.channels;
831             if (dec->to_skip)
832             {
833                 size_t skip = MINIMP3_MIN(dec->buffer_samples, dec->to_skip);
834                 dec->buffer_consumed += skip;
835                 dec->to_skip -= skip;
836             }
837             size_t to_copy = MINIMP3_MIN((size_t)(dec->buffer_samples - dec->buffer_consumed), samples);
838             if (dec->detected_samples)
839             {   /* ^ handle padding */
840                 if (dec->cur_sample + to_copy >= dec->detected_samples)
841                     to_copy = dec->detected_samples - dec->cur_sample;
842             }
843             dec->cur_sample += to_copy;
844             memcpy(buf, dec->buffer + dec->buffer_consumed, to_copy*sizeof(mp3d_sample_t));
845             buf += to_copy;
846             dec->buffer_consumed += to_copy;
847             samples -= to_copy;
848         } else if (dec->to_skip)
849         {   /* In mp3 decoding not always can start decode from any frame because of bit reservoir,
850                count skip samples for such frames */
851             int frame_samples = hdr_frame_samples(dec_buf)*frame_info.channels;
852             dec->to_skip -= MINIMP3_MIN(frame_samples, dec->to_skip);
853         }
854         dec->offset += frame_info.frame_bytes;
855     }
856     return samples_requested - samples;
857 }
858 
859 #ifndef MINIMP3_NO_STDIO
860 
861 #if defined(__linux__) || defined(__FreeBSD__)
862 #include <errno.h>
863 #include <sys/mman.h>
864 #include <sys/types.h>
865 #include <sys/stat.h>
866 #include <unistd.h>
867 #include <fcntl.h>
868 #if !defined(_GNU_SOURCE)
869 #include <sys/ipc.h>
870 #include <sys/shm.h>
871 #endif
872 #if !defined(MAP_POPULATE) && defined(__linux__)
873 #define MAP_POPULATE 0x08000
874 #elif !defined(MAP_POPULATE)
875 #define MAP_POPULATE 0
876 #endif
877 
mp3dec_close_file(mp3dec_map_info_t * map_info)878 static void mp3dec_close_file(mp3dec_map_info_t *map_info)
879 {
880     if (map_info->buffer && MAP_FAILED != map_info->buffer)
881         munmap((void *)map_info->buffer, map_info->size);
882     map_info->buffer = 0;
883     map_info->size   = 0;
884 }
885 
mp3dec_open_file(const char * file_name,mp3dec_map_info_t * map_info)886 static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
887 {
888     if (!file_name)
889         return MP3D_E_PARAM;
890     int file;
891     struct stat st;
892     memset(map_info, 0, sizeof(*map_info));
893 retry_open:
894     file = open(file_name, O_RDONLY);
895     if (file < 0 && (errno == EAGAIN || errno == EINTR))
896         goto retry_open;
897     if (file < 0 || fstat(file, &st) < 0)
898     {
899         close(file);
900         return MP3D_E_IOERROR;
901     }
902 
903     map_info->size = st.st_size;
904 retry_mmap:
905     map_info->buffer = (const uint8_t *)mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, file, 0);
906     if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
907         goto retry_mmap;
908     close(file);
909     if (MAP_FAILED == map_info->buffer)
910         return MP3D_E_IOERROR;
911     return 0;
912 }
913 
914 #if MINIMP3_ENABLE_RING && defined(__linux__) && defined(_GNU_SOURCE)
915 #define MINIMP3_HAVE_RING
mp3dec_close_ring(mp3dec_map_info_t * map_info)916 static void mp3dec_close_ring(mp3dec_map_info_t *map_info)
917 {
918 #if defined(__linux__) && defined(_GNU_SOURCE)
919     if (map_info->buffer && MAP_FAILED != map_info->buffer)
920         munmap((void *)map_info->buffer, map_info->size*2);
921 #else
922     if (map_info->buffer)
923     {
924         shmdt(map_info->buffer);
925         shmdt(map_info->buffer + map_info->size);
926     }
927 #endif
928     map_info->buffer = 0;
929     map_info->size   = 0;
930 }
931 
mp3dec_open_ring(mp3dec_map_info_t * map_info,size_t size)932 static int mp3dec_open_ring(mp3dec_map_info_t *map_info, size_t size)
933 {
934     int memfd, page_size;
935 #if defined(__linux__) && defined(_GNU_SOURCE)
936     void *buffer;
937     int res;
938 #endif
939     memset(map_info, 0, sizeof(*map_info));
940 
941 #ifdef _SC_PAGESIZE
942     page_size = sysconf(_SC_PAGESIZE);
943 #else
944     page_size = getpagesize();
945 #endif
946     map_info->size = (size + page_size - 1)/page_size*page_size;
947 
948 #if defined(__linux__) && defined(_GNU_SOURCE)
949     memfd = memfd_create("mp3_ring", 0);
950     if (memfd < 0)
951         return MP3D_E_MEMORY;
952 
953 retry_ftruncate:
954     res = ftruncate(memfd, map_info->size);
955     if (res && (errno == EAGAIN || errno == EINTR))
956         goto retry_ftruncate;
957     if (res)
958         goto error;
959 
960 retry_mmap:
961     map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
962     if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
963         goto retry_mmap;
964     if (MAP_FAILED == map_info->buffer || !map_info->buffer)
965         goto error;
966 retry_mmap2:
967     buffer = mmap((void *)map_info->buffer, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
968     if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
969         goto retry_mmap2;
970     if (MAP_FAILED == map_info->buffer || buffer != (void *)map_info->buffer)
971         goto error;
972 retry_mmap3:
973     buffer = mmap((void *)map_info->buffer + map_info->size, map_info->size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, memfd, 0);
974     if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
975         goto retry_mmap3;
976     if (MAP_FAILED == map_info->buffer || buffer != (void *)(map_info->buffer + map_info->size))
977         goto error;
978 
979     close(memfd);
980     return 0;
981 error:
982     close(memfd);
983     mp3dec_close_ring(map_info);
984     return MP3D_E_MEMORY;
985 #else
986     memfd = shmget(IPC_PRIVATE, map_info->size, IPC_CREAT | 0700);
987     if (memfd < 0)
988         return MP3D_E_MEMORY;
989 retry_mmap:
990     map_info->buffer = (const uint8_t *)mmap(NULL, map_info->size*2, PROT_NONE, MAP_PRIVATE, -1, 0);
991     if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
992         goto retry_mmap;
993     if (MAP_FAILED == map_info->buffer)
994         goto error;
995     if (map_info->buffer != shmat(memfd, map_info->buffer, 0))
996         goto error;
997     if ((map_info->buffer + map_info->size) != shmat(memfd, map_info->buffer + map_info->size, 0))
998         goto error;
999     if (shmctl(memfd, IPC_RMID, NULL) < 0)
1000         return MP3D_E_MEMORY;
1001     return 0;
1002 error:
1003     shmctl(memfd, IPC_RMID, NULL);
1004     mp3dec_close_ring(map_info);
1005     return MP3D_E_MEMORY;
1006 #endif
1007 }
1008 #endif /*MINIMP3_ENABLE_RING*/
1009 #elif defined(_WIN32)
1010 #include <windows.h>
1011 
mp3dec_close_file(mp3dec_map_info_t * map_info)1012 static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1013 {
1014     if (map_info->buffer)
1015         UnmapViewOfFile(map_info->buffer);
1016     map_info->buffer = 0;
1017     map_info->size   = 0;
1018 }
1019 
mp3dec_open_file_h(HANDLE file,mp3dec_map_info_t * map_info)1020 static int mp3dec_open_file_h(HANDLE file, mp3dec_map_info_t *map_info)
1021 {
1022     memset(map_info, 0, sizeof(*map_info));
1023 
1024     HANDLE mapping = NULL;
1025     LARGE_INTEGER s;
1026     s.LowPart = GetFileSize(file, (DWORD*)&s.HighPart);
1027     if (s.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR)
1028         goto error;
1029     map_info->size = s.QuadPart;
1030 
1031     mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
1032     if (!mapping)
1033         goto error;
1034     map_info->buffer = (const uint8_t*)MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, s.QuadPart);
1035     CloseHandle(mapping);
1036     if (!map_info->buffer)
1037         goto error;
1038 
1039     CloseHandle(file);
1040     return 0;
1041 error:
1042     mp3dec_close_file(map_info);
1043     CloseHandle(file);
1044     return MP3D_E_IOERROR;
1045 }
1046 
mp3dec_open_file(const char * file_name,mp3dec_map_info_t * map_info)1047 static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1048 {
1049     if (!file_name)
1050         return MP3D_E_PARAM;
1051     HANDLE file = CreateFileA(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
1052     if (INVALID_HANDLE_VALUE == file)
1053         return MP3D_E_IOERROR;
1054     return mp3dec_open_file_h(file, map_info);
1055 }
1056 
mp3dec_open_file_w(const wchar_t * file_name,mp3dec_map_info_t * map_info)1057 static int mp3dec_open_file_w(const wchar_t *file_name, mp3dec_map_info_t *map_info)
1058 {
1059     if (!file_name)
1060         return MP3D_E_PARAM;
1061     HANDLE file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
1062     if (INVALID_HANDLE_VALUE == file)
1063         return MP3D_E_IOERROR;
1064     return mp3dec_open_file_h(file, map_info);
1065 }
1066 #else
1067 #include <stdio.h>
1068 
mp3dec_close_file(mp3dec_map_info_t * map_info)1069 static void mp3dec_close_file(mp3dec_map_info_t *map_info)
1070 {
1071     if (map_info->buffer)
1072         free((void *)map_info->buffer);
1073     map_info->buffer = 0;
1074     map_info->size = 0;
1075 }
1076 
mp3dec_open_file(const char * file_name,mp3dec_map_info_t * map_info)1077 static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
1078 {
1079     if (!file_name)
1080         return MP3D_E_PARAM;
1081     memset(map_info, 0, sizeof(*map_info));
1082     FILE *file = fopen(file_name, "rb");
1083     if (!file)
1084         return MP3D_E_IOERROR;
1085     int res = MP3D_E_IOERROR;
1086     long size = -1;
1087     if (fseek(file, 0, SEEK_END))
1088         goto error;
1089     size = ftell(file);
1090     if (size < 0)
1091         goto error;
1092     map_info->size = (size_t)size;
1093     if (fseek(file, 0, SEEK_SET))
1094         goto error;
1095     map_info->buffer = (uint8_t *)malloc(map_info->size);
1096     if (!map_info->buffer)
1097     {
1098         res = MP3D_E_MEMORY;
1099         goto error;
1100     }
1101     if (fread((void *)map_info->buffer, 1, map_info->size, file) != map_info->size)
1102         goto error;
1103     fclose(file);
1104     return 0;
1105 error:
1106     mp3dec_close_file(map_info);
1107     fclose(file);
1108     return res;
1109 }
1110 #endif
1111 
mp3dec_load_mapinfo(mp3dec_t * dec,mp3dec_map_info_t * map_info,mp3dec_file_info_t * info,MP3D_PROGRESS_CB progress_cb,void * user_data)1112 static int mp3dec_load_mapinfo(mp3dec_t *dec, mp3dec_map_info_t *map_info, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1113 {
1114     int ret = mp3dec_load_buf(dec, map_info->buffer, map_info->size, info, progress_cb, user_data);
1115     mp3dec_close_file(map_info);
1116     return ret;
1117 }
1118 
mp3dec_iterate_mapinfo(mp3dec_map_info_t * map_info,MP3D_ITERATE_CB callback,void * user_data)1119 static int mp3dec_iterate_mapinfo(mp3dec_map_info_t *map_info, MP3D_ITERATE_CB callback, void *user_data)
1120 {
1121     int ret = mp3dec_iterate_buf(map_info->buffer, map_info->size, callback, user_data);
1122     mp3dec_close_file(map_info);
1123     return ret;
1124 }
1125 
mp3dec_ex_open_mapinfo(mp3dec_ex_t * dec,int seek_method)1126 static int mp3dec_ex_open_mapinfo(mp3dec_ex_t *dec, int seek_method)
1127 {
1128     int ret = mp3dec_ex_open_buf(dec, dec->file.buffer, dec->file.size, seek_method);
1129     dec->is_file = 1;
1130     if (ret)
1131         mp3dec_ex_close(dec);
1132     return ret;
1133 }
1134 
mp3dec_load(mp3dec_t * dec,const char * file_name,mp3dec_file_info_t * info,MP3D_PROGRESS_CB progress_cb,void * user_data)1135 int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1136 {
1137     int ret;
1138     mp3dec_map_info_t map_info;
1139     if ((ret = mp3dec_open_file(file_name, &map_info)))
1140         return ret;
1141     return mp3dec_load_mapinfo(dec, &map_info, info, progress_cb, user_data);
1142 }
1143 
mp3dec_iterate(const char * file_name,MP3D_ITERATE_CB callback,void * user_data)1144 int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data)
1145 {
1146     int ret;
1147     mp3dec_map_info_t map_info;
1148     if ((ret = mp3dec_open_file(file_name, &map_info)))
1149         return ret;
1150     return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
1151 }
1152 
mp3dec_ex_open(mp3dec_ex_t * dec,const char * file_name,int seek_method)1153 int mp3dec_ex_open(mp3dec_ex_t *dec, const char *file_name, int seek_method)
1154 {
1155     int ret;
1156     if ((ret = mp3dec_open_file(file_name, &dec->file)))
1157         return ret;
1158     return mp3dec_ex_open_mapinfo(dec, seek_method);
1159 }
1160 
mp3dec_ex_open_cb(mp3dec_ex_t * dec,mp3dec_io_t * io,int seek_method)1161 int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int seek_method)
1162 {
1163     if (!dec || !io)
1164         return MP3D_E_PARAM;
1165     memset(dec, 0, sizeof(*dec));
1166 #ifdef MINIMP3_HAVE_RING
1167     int ret;
1168     if (ret = mp3dec_open_ring(&dec->file, MINIMP3_IO_SIZE))
1169         return ret;
1170 #else
1171     dec->file.size = MINIMP3_IO_SIZE;
1172     dec->file.buffer = (const uint8_t*)malloc(dec->file.size);
1173     if (!dec->file.buffer)
1174         return MP3D_E_MEMORY;
1175 #endif
1176     dec->seek_method = seek_method;
1177     dec->io = io;
1178     mp3dec_init(&dec->mp3d);
1179     if (MP3D_SEEK_TO_SAMPLE == dec->seek_method)
1180     {
1181         if (io->seek(0, io->seek_data))
1182             return MP3D_E_IOERROR;
1183         int ret = mp3dec_iterate_cb(io, (uint8_t *)dec->file.buffer, dec->file.size, mp3dec_load_index, dec);
1184         if (ret && MP3D_E_USER != ret)
1185             return ret;
1186         if (dec->io->seek(dec->start_offset, dec->io->seek_data))
1187             return MP3D_E_IOERROR;
1188         mp3dec_init(&dec->mp3d);
1189         dec->buffer_samples = 0;
1190     }
1191     return 0;
1192 }
1193 
mp3dec_ex_close(mp3dec_ex_t * dec)1194 void mp3dec_ex_close(mp3dec_ex_t *dec)
1195 {
1196 #ifdef MINIMP3_HAVE_RING
1197     if (dec->io)
1198         mp3dec_close_ring(&dec->file);
1199 #else
1200     if (dec->io && dec->file.buffer)
1201         free((void*)dec->file.buffer);
1202 #endif
1203     if (dec->is_file)
1204         mp3dec_close_file(&dec->file);
1205     if (dec->index.frames)
1206         free(dec->index.frames);
1207     memset(dec, 0, sizeof(*dec));
1208 }
1209 
1210 #ifdef _WIN32
mp3dec_load_w(mp3dec_t * dec,const wchar_t * file_name,mp3dec_file_info_t * info,MP3D_PROGRESS_CB progress_cb,void * user_data)1211 int mp3dec_load_w(mp3dec_t *dec, const wchar_t *file_name, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
1212 {
1213     int ret;
1214     mp3dec_map_info_t map_info;
1215     if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1216         return ret;
1217     return mp3dec_load_mapinfo(dec, &map_info,info, progress_cb, user_data);
1218 }
1219 
mp3dec_iterate_w(const wchar_t * file_name,MP3D_ITERATE_CB callback,void * user_data)1220 size_t mp3dec_iterate_w(const wchar_t *file_name, MP3D_ITERATE_CB callback, void *user_data)
1221 {
1222     int ret;
1223     mp3dec_map_info_t map_info;
1224     if ((ret = mp3dec_open_file_w(file_name, &map_info)))
1225         return ret;
1226     return mp3dec_iterate_mapinfo(&map_info, callback, user_data);
1227 }
1228 
mp3dec_ex_open_w(mp3dec_ex_t * dec,const wchar_t * file_name,int seek_method)1229 int mp3dec_ex_open_w(mp3dec_ex_t *dec, const wchar_t *file_name, int seek_method)
1230 {
1231     int ret;
1232     if ((ret = mp3dec_open_file_w(file_name, &dec->file)))
1233         return ret;
1234     return mp3dec_ex_open_mapinfo(dec, seek_method);
1235 }
1236 #endif
1237 #else /* MINIMP3_NO_STDIO */
mp3dec_ex_close(mp3dec_ex_t * dec)1238 void mp3dec_ex_close(mp3dec_ex_t *dec)
1239 {
1240     if (dec->index.frames)
1241         free(dec->index.frames);
1242     memset(dec, 0, sizeof(*dec));
1243 }
1244 #endif
1245 
1246 #endif /*MINIMP3_IMPLEMENTATION*/
1247