The OpenD Programming Language

1 /*
2     https://github.com/lieff/minimp3
3     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.
4     This software is distributed without any warranty.
5     See <http://creativecommons.org/publicdomain/zero/1.0/>.
6 */
7 /**
8   Translated to D by Guillaume Piolat.
9   Stripped down a bit for the needs of audio-formats.
10 */
11 module audioformats.minimp3_ex;
12 
13 import core.stdc.stdlib;
14 import core.stdc.string;
15 
16 import audioformats.minimp3;
17 
18 nothrow:
19 @nogc:
20 
21 enum MP3D_SEEK_TO_BYTE =   0;
22 enum MP3D_SEEK_TO_SAMPLE = 1;
23 
24 enum MINIMP3_PREDECODE_FRAMES = 2; /* frames to pre-decode and skip after seek (to fill internal structures) */
25 /*#define MINIMP3_SEEK_IDX_LINEAR_SEARCH*/ /* define to use linear index search instead of binary search on seek */
26 enum MINIMP3_IO_SIZE = (128*1024); /* io buffer size for streaming functions, must be greater than MINIMP3_BUF_SIZE */
27 enum MINIMP3_BUF_SIZE = (16*1024); /* buffer which can hold minimum 10 consecutive mp3 frames (~16KB) worst case */
28 enum MINIMP3_ENABLE_RING = 0;      /* enable hardware magic ring buffer if available, to make less input buffer memmove(s) in callback IO mode */
29 
30 enum MP3D_E_PARAM     =  -1;
31 enum MP3D_E_MEMORY    =  -2;
32 enum MP3D_E_IOERROR   =  -3;
33 enum MP3D_E_USER      =  -4;  /* can be used to stop processing from callbacks without indicating specific error */
34 enum MP3D_E_DECODE    =  -5;  /* decode error which can't be safely skipped, such as sample rate, layer and channels change */
35 
36 struct mp3dec_file_info_t
37 {
38     mp3d_sample_t *buffer;
39     size_t samples; /* channels included, byte size = samples*sizeof(mp3d_sample_t) */
40     int channels, hz, layer, avg_bitrate_kbps;
41 }
42 
43 struct mp3dec_map_info_t
44 {
45     const(uint8_t) *buffer;
46     size_t size;
47 }
48 
49 struct mp3dec_frame_t
50 {
51     uint64_t sample;
52     uint64_t offset;
53 }
54 
55 struct mp3dec_index_t
56 {
57     mp3dec_frame_t *frames;
58     size_t num_frames, capacity;
59 }
60 
61 alias MP3D_READ_CB = size_t function(void *buf, size_t size, void *user_data);
62 alias MP3D_SEEK_CB = int function(uint64_t position, void *user_data);
63 
64 
65 struct mp3dec_io_t
66 {
67     MP3D_READ_CB read;
68     void *read_data;
69     MP3D_SEEK_CB seek;
70     void *seek_data;
71 }
72 
73 struct mp3dec_ex_t
74 {
75     mp3dec_t mp3d;
76     mp3dec_map_info_t file;
77     mp3dec_io_t *io;
78     mp3dec_index_t index;
79     uint64_t offset, samples, detected_samples, cur_sample, start_offset, end_offset;
80     mp3dec_frame_info_t info;
81     mp3d_sample_t[MINIMP3_MAX_SAMPLES_PER_FRAME] buffer;
82     size_t input_consumed, input_filled;
83     int is_file, seek_method, vbr_tag_found;
84     int free_format_bytes;
85     int buffer_samples, buffer_consumed, to_skip, start_delay;
86     int last_error;
87 }
88 
89 alias MP3D_ITERATE_CB = int function(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);
90 alias MP3D_PROGRESS_CB = int function(void *user_data, size_t file_size, uint64_t offset, mp3dec_frame_info_t *info);
91 
92 
93 void mp3dec_skip_id3v1(const uint8_t *buf, size_t *pbuf_size)
94 {
95     size_t buf_size = *pbuf_size;
96     if (buf_size >= 128 && !memcmp(buf + buf_size - 128, "TAG".ptr, 3))
97     {
98         buf_size -= 128;
99         if (buf_size >= 227 && !memcmp(buf + buf_size - 227, "TAG+".ptr, 4))
100             buf_size -= 227;
101     }
102     if (buf_size > 32 && !memcmp(buf + buf_size - 32, "APETAGEX".ptr, 8))
103     {
104         buf_size -= 32;
105         const uint8_t *tag = buf + buf_size + 8 + 4;
106         uint32_t tag_size = cast(uint32_t)(tag[3] << 24) | (tag[2] << 16) | (tag[1] << 8) | tag[0];
107         if (buf_size >= tag_size)
108             buf_size -= tag_size;
109     }
110     *pbuf_size = buf_size;
111 }
112 
113 enum MINIMP3_ID3_DETECT_SIZE = 10;
114 
115 size_t mp3dec_skip_id3v2(const uint8_t *buf, size_t buf_size)
116 {    
117     if (buf_size >= MINIMP3_ID3_DETECT_SIZE && !memcmp(buf, "ID3".ptr, 3) && !((buf[5] & 15) || (buf[6] & 0x80) || (buf[7] & 0x80) || (buf[8] & 0x80) || (buf[9] & 0x80)))
118     {
119         size_t id3v2size = (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10;
120         if ((buf[5] & 16))
121             id3v2size += 10; /* footer */
122         return id3v2size;
123     }enum MINIMP3_ID3_DETECT_SIZE = 10;
124     return 0;
125 }
126 
127 void mp3dec_skip_id3(const(uint8_t)**pbuf, size_t *pbuf_size)
128 {
129     uint8_t *buf = cast(uint8_t *)(*pbuf);
130     size_t buf_size = *pbuf_size;
131     size_t id3v2size = mp3dec_skip_id3v2(buf, buf_size);
132     if (id3v2size)
133     {
134         if (id3v2size >= buf_size)
135             id3v2size = buf_size;
136         buf      += id3v2size;
137         buf_size -= id3v2size;
138     }
139     mp3dec_skip_id3v1(buf, &buf_size);
140     *pbuf = cast(const uint8_t *)buf;
141     *pbuf_size = buf_size;
142 }
143 
144 static int mp3dec_check_vbrtag(const uint8_t *frame, int frame_size, uint32_t *frames, int *delay, int *padding)
145 {
146     static immutable char[4] g_xing_tag = "Xing";
147     static immutable char[4] g_info_tag = "Info";
148 
149 enum FRAMES_FLAG =    1;
150 enum BYTES_FLAG     = 2;
151 enum TOC_FLAG       = 4;
152 enum VBR_SCALE_FLAG = 8;
153     /* Side info offsets after header:
154     /                Mono  Stereo
155     /  MPEG1          17     32
156     /  MPEG2 & 2.5     9     17*/
157     bs_t[1] bs;
158     L3_gr_info_t[4] gr_info;
159     bs_init(bs.ptr, frame + HDR_SIZE, frame_size - HDR_SIZE);
160     if (HDR_IS_CRC(frame))
161         get_bits(bs.ptr, 16);
162     if (L3_read_side_info(bs.ptr, gr_info.ptr, frame) < 0)
163         return 0; /* side info corrupted */
164 
165     const(uint8_t)*tag = frame + HDR_SIZE + bs[0].pos/8;
166     if (memcmp(g_xing_tag.ptr, tag, 4) && memcmp(g_info_tag.ptr, tag, 4))
167         return 0;
168     int flags = tag[7];
169     if (!((flags & FRAMES_FLAG)))
170         return -1;
171     tag += 8;
172     *frames = cast(uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
173     tag += 4;
174     if (flags & BYTES_FLAG)
175         tag += 4;
176     if (flags & TOC_FLAG)
177         tag += 100;
178     if (flags & VBR_SCALE_FLAG)
179         tag += 4;
180     *delay = *padding = 0;
181     if (*tag)
182     {   /* extension, LAME, Lavc, etc. Should be the same structure. */
183         tag += 21;
184         if (tag - frame + 14 >= frame_size)
185             return 0;
186         *delay   = ((tag[0] << 4) | (tag[1] >> 4)) + (528 + 1);
187         *padding = (((tag[1] & 0xF) << 8) | tag[2]) - (528 + 1);
188     }
189     return 1;
190 }
191 
192 int mp3dec_detect_buf(const uint8_t *buf, size_t buf_size)
193 {
194     return mp3dec_detect_cb(null, cast(uint8_t *)buf, buf_size);
195 }
196 
197 int mp3dec_detect_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size)
198 {
199     if (!buf || cast(size_t)-1 == buf_size || (io && buf_size < MINIMP3_BUF_SIZE))
200         return MP3D_E_PARAM;
201     size_t filled = buf_size;
202     if (io)
203     {
204         if (io.seek(0, io.seek_data))
205             return MP3D_E_IOERROR;
206         filled = io.read(buf, MINIMP3_ID3_DETECT_SIZE, io.read_data);
207         if (filled > MINIMP3_ID3_DETECT_SIZE)
208             return MP3D_E_IOERROR;
209     }
210     if (filled < MINIMP3_ID3_DETECT_SIZE)
211         return MP3D_E_USER; /* too small, can't be mp3/mpa */
212     if (mp3dec_skip_id3v2(buf, filled))
213         return 0; /* id3v2 tag is enough evidence */
214     if (io)
215     {
216         size_t readed = io.read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io.read_data);
217         if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
218             return MP3D_E_IOERROR;
219         filled += readed;
220         if (filled < MINIMP3_BUF_SIZE)
221             mp3dec_skip_id3v1(buf, &filled);
222     } else
223     {
224         mp3dec_skip_id3v1(buf, &filled);
225         if (filled > MINIMP3_BUF_SIZE)
226             filled = MINIMP3_BUF_SIZE;
227     }
228     int free_format_bytes, frame_size;
229     mp3d_find_frame(buf, cast(int)filled, &free_format_bytes, &frame_size);
230     if (frame_size)
231         return 0; /* MAX_FRAME_SYNC_MATCHES consecutive frames found */
232     return MP3D_E_USER;
233 }
234 
235 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)
236 {
237     return mp3dec_load_cb(dec, null, cast(uint8_t *)buf, buf_size, info, progress_cb, user_data);
238 }
239 
240 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)
241 {
242     if (!dec || !buf || !info || cast(size_t)-1 == buf_size || (io && buf_size < MINIMP3_BUF_SIZE))
243         return MP3D_E_PARAM;
244     uint64_t detected_samples = 0;
245     size_t orig_buf_size = buf_size;
246     int to_skip = 0;
247     mp3dec_frame_info_t frame_info;
248     memset(info, 0, (*info).sizeof);
249     memset(&frame_info, 0, (frame_info).sizeof);
250 
251     /* skip id3 */
252     size_t filled = 0, consumed = 0;
253     int eof = 0, ret2 = 0;
254     if (io)
255     {
256         if (io.seek(0, io.seek_data))
257             return MP3D_E_IOERROR;
258         filled = io.read(buf, MINIMP3_ID3_DETECT_SIZE, io.read_data);
259         if (filled > MINIMP3_ID3_DETECT_SIZE)
260             return MP3D_E_IOERROR;
261         if (MINIMP3_ID3_DETECT_SIZE != filled)
262             return 0;
263         size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
264         if (id3v2size)
265         {
266             if (io.seek(id3v2size, io.seek_data))
267                 return MP3D_E_IOERROR;
268             filled = io.read(buf, buf_size, io.read_data);
269             if (filled > buf_size)
270                 return MP3D_E_IOERROR;
271         } else
272         {
273             size_t readed = io.read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io.read_data);
274             if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
275                 return MP3D_E_IOERROR;
276             filled += readed;
277         }
278         if (filled < MINIMP3_BUF_SIZE)
279             mp3dec_skip_id3v1(buf, &filled);
280     } else
281     {
282         mp3dec_skip_id3(cast(const(uint8_t)**)&buf, &buf_size);
283         if (!buf_size)
284             return 0;
285     }
286     /* try to make allocation size assumption by first frame or vbr tag */
287     mp3dec_init(dec);
288     int samples;
289     do
290     {
291         uint32_t frames;
292         int i, delay, padding, free_format_bytes = 0, frame_size = 0;
293         const(uint8_t) *hdr;
294         if (io)
295         {
296             if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
297             {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
298                 memmove(buf, buf + consumed, filled - consumed);
299                 filled -= consumed;
300                 consumed = 0;
301                 size_t readed = io.read(buf + filled, buf_size - filled, io.read_data);
302                 if (readed > (buf_size - filled))
303                     return MP3D_E_IOERROR;
304                 if (readed != (buf_size - filled))
305                     eof = 1;
306                 filled += readed;
307                 if (eof)
308                     mp3dec_skip_id3v1(buf, &filled);
309             }
310             i = mp3d_find_frame(buf + consumed, cast(int)(filled - consumed), &free_format_bytes, &frame_size);
311             consumed += i;
312             hdr = buf + consumed;
313         } else
314         {
315             i = mp3d_find_frame(buf, cast(int)buf_size, &free_format_bytes, &frame_size);
316             buf      += i;
317             buf_size -= i;
318             hdr = buf;
319         }
320         if (i && !frame_size)
321             continue;
322         if (!frame_size)
323             return 0;
324         frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
325         frame_info.hz = hdr_sample_rate_hz(hdr);
326         frame_info.layer = 4 - HDR_GET_LAYER(hdr);
327         frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
328         frame_info.frame_bytes = frame_size;
329         samples = hdr_frame_samples(hdr)*frame_info.channels;
330         if (3 != frame_info.layer)
331             break;
332         int ret = mp3dec_check_vbrtag(hdr, frame_size, &frames, &delay, &padding);
333         if (ret > 0)
334         {
335             padding *= frame_info.channels;
336             to_skip = delay*frame_info.channels;
337             detected_samples = samples*cast(uint64_t)frames;
338             if (detected_samples >= cast(uint64_t)to_skip)
339                 detected_samples -= to_skip;
340             if (padding > 0 && detected_samples >= cast(uint64_t)padding)
341                 detected_samples -= padding;
342             if (!detected_samples)
343                 return 0;
344         }
345         if (ret)
346         {
347             if (io)
348             {
349                 consumed += frame_size;
350             } else
351             {
352                 buf      += frame_size;
353                 buf_size -= frame_size;
354             }
355         }
356         break;
357     } while(1);
358     size_t allocated = MINIMP3_MAX_SAMPLES_PER_FRAME*(mp3d_sample_t.sizeof);
359     if (detected_samples)
360         allocated += detected_samples*(mp3d_sample_t.sizeof);
361     else
362         allocated += (buf_size/frame_info.frame_bytes)*samples*(mp3d_sample_t.sizeof);
363     info.buffer = cast(mp3d_sample_t*) malloc(allocated);
364     if (!info.buffer)
365         return MP3D_E_MEMORY;
366     /* save info */
367     info.channels = frame_info.channels;
368     info.hz       = frame_info.hz;
369     info.layer    = frame_info.layer;
370     /* decode all frames */
371     size_t avg_bitrate_kbps = 0, frames = 0;
372     do
373     {
374         if ((allocated - info.samples*(mp3d_sample_t.sizeof)) < MINIMP3_MAX_SAMPLES_PER_FRAME*(mp3d_sample_t.sizeof))
375         {
376             allocated *= 2;
377             mp3d_sample_t *alloc_buf = cast(mp3d_sample_t*)realloc(info.buffer, allocated);
378             if (!alloc_buf)
379                 return MP3D_E_MEMORY;
380             info.buffer = alloc_buf;
381         }
382         if (io)
383         {
384             if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
385             {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
386                 memmove(buf, buf + consumed, filled - consumed);
387                 filled -= consumed;
388                 consumed = 0;
389                 size_t readed = io.read(buf + filled, buf_size - filled, io.read_data);
390                 if (readed != (buf_size - filled))
391                     eof = 1;
392                 filled += readed;
393                 if (eof)
394                     mp3dec_skip_id3v1(buf, &filled);
395             }
396             samples = mp3dec_decode_frame(dec, buf + consumed, cast(int)(filled - consumed), info.buffer + info.samples, &frame_info);
397             consumed += frame_info.frame_bytes;
398         } else
399         {
400             samples = mp3dec_decode_frame(dec, buf, cast(int)MINIMP3_MIN(buf_size, cast(size_t)int.max), info.buffer + info.samples, &frame_info);
401             buf      += frame_info.frame_bytes;
402             buf_size -= frame_info.frame_bytes;
403         }
404         if (samples)
405         {
406             if (info.hz != frame_info.hz || info.layer != frame_info.layer)
407             {
408                 ret2 = MP3D_E_DECODE;
409                 break;
410             }
411             if (info.channels && info.channels != frame_info.channels)
412             {
413                 ret2 = MP3D_E_DECODE;
414                 break;
415             }
416             samples *= frame_info.channels;
417             if (to_skip)
418             {
419                 size_t skip = MINIMP3_MIN(samples, to_skip);
420                 to_skip -= skip;
421                 samples -= skip;
422                 memmove(info.buffer, info.buffer + skip, samples);
423             }
424             info.samples += samples;
425             avg_bitrate_kbps += frame_info.bitrate_kbps;
426             frames++;
427             if (progress_cb)
428             {
429                 ret2 = progress_cb(user_data, orig_buf_size, (orig_buf_size - buf_size), &frame_info);
430                 if (ret2)
431                     break;
432             }
433         }
434     } while (frame_info.frame_bytes);
435     if (detected_samples && info.samples > detected_samples)
436         info.samples = cast(size_t) detected_samples; /* cut padding */
437     /* reallocate to normal buffer size */
438     if (allocated != info.samples*(mp3d_sample_t.sizeof))
439     {
440         mp3d_sample_t *alloc_buf = cast(mp3d_sample_t*)realloc(info.buffer, info.samples*(mp3d_sample_t.sizeof));
441         if (!alloc_buf && info.samples)
442             return MP3D_E_MEMORY;
443         info.buffer = alloc_buf;
444     }
445     if (frames)
446         info.avg_bitrate_kbps = cast(int)(avg_bitrate_kbps/frames);
447     return ret2;
448 }
449 
450 int mp3dec_iterate_buf(const(uint8_t)*buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
451 {
452     const uint8_t *orig_buf = buf;
453     if (!buf || cast(size_t)-1 == buf_size || !callback)
454         return MP3D_E_PARAM;
455     /* skip id3 */
456     mp3dec_skip_id3(&buf, &buf_size);
457     if (!buf_size)
458         return 0;
459     mp3dec_frame_info_t frame_info;
460     memset(&frame_info, 0, (frame_info.sizeof));
461     do
462     {
463         int free_format_bytes = 0, frame_size = 0, ret;
464         int i = mp3d_find_frame(buf, cast(int)buf_size, &free_format_bytes, &frame_size);
465         buf      += i;
466         buf_size -= i;
467         if (i && !frame_size)
468             continue;
469         if (!frame_size)
470             break;
471         const uint8_t *hdr = buf;
472         frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
473         frame_info.hz = hdr_sample_rate_hz(hdr);
474         frame_info.layer = 4 - HDR_GET_LAYER(hdr);
475         frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
476         frame_info.frame_bytes = frame_size;
477 
478         if (callback)
479         {
480             ret = callback(user_data, hdr, frame_size, free_format_bytes, buf_size, (hdr - orig_buf), &frame_info);
481             if (ret)
482                 return ret;
483         }
484         buf      += frame_size;
485         buf_size -= frame_size;
486     } while (1);
487     return 0;
488 }
489 
490 int mp3dec_iterate_cb(mp3dec_io_t *io, uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
491 {
492     if (!io || !buf || cast(size_t)-1 == buf_size || buf_size < MINIMP3_BUF_SIZE || !callback)
493         return MP3D_E_PARAM;
494     size_t filled = io.read(buf, MINIMP3_ID3_DETECT_SIZE, io.read_data), consumed = 0;
495     uint64_t readed2 = 0;
496     mp3dec_frame_info_t frame_info;
497     int eof = 0;
498     memset(&frame_info, 0, (frame_info.sizeof));
499     if (filled > MINIMP3_ID3_DETECT_SIZE)
500         return MP3D_E_IOERROR;
501     if (MINIMP3_ID3_DETECT_SIZE != filled)
502         return 0;
503     size_t id3v2size = mp3dec_skip_id3v2(buf, filled);
504     if (id3v2size)
505     {
506         if (io.seek(id3v2size, io.seek_data))
507             return MP3D_E_IOERROR;
508         filled = io.read(buf, buf_size, io.read_data);
509         if (filled > buf_size)
510             return MP3D_E_IOERROR;
511         readed2 += id3v2size;
512     } else
513     {
514         size_t readed = io.read(buf + MINIMP3_ID3_DETECT_SIZE, buf_size - MINIMP3_ID3_DETECT_SIZE, io.read_data);
515         if (readed > (buf_size - MINIMP3_ID3_DETECT_SIZE))
516             return MP3D_E_IOERROR;
517         filled += readed;
518     }
519     if (filled < MINIMP3_BUF_SIZE)
520         mp3dec_skip_id3v1(buf, &filled);
521     do
522     {
523         int free_format_bytes = 0, frame_size = 0, ret;
524         int i = mp3d_find_frame(buf + consumed, cast(int)(filled - consumed), &free_format_bytes, &frame_size);
525         if (i && !frame_size)
526         {
527             consumed += i;
528             continue;
529         }
530         if (!frame_size)
531             break;
532         const uint8_t *hdr = buf + consumed + i;
533         frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
534         frame_info.hz = hdr_sample_rate_hz(hdr);
535         frame_info.layer = 4 - HDR_GET_LAYER(hdr);
536         frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
537         frame_info.frame_bytes = frame_size;
538 
539         readed2 += i;
540         if (callback)
541         {
542             ret = callback(user_data, hdr, frame_size, free_format_bytes, filled - consumed, readed2, &frame_info);
543             if (ret)
544                 return ret;
545         }
546         readed2 += frame_size;
547         consumed += i + frame_size;
548         if (!eof && filled - consumed < MINIMP3_BUF_SIZE)
549         {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
550             memmove(buf, buf + consumed, filled - consumed);
551             filled -= consumed;
552             consumed = 0;
553             size_t readed = io.read(buf + filled, buf_size - filled, io.read_data);
554             if (readed > (buf_size - filled))
555                 return MP3D_E_IOERROR;
556             if (readed != (buf_size - filled))
557                 eof = 1;
558             filled += readed;
559             if (eof)
560                 mp3dec_skip_id3v1(buf, &filled);
561         }
562     } while (1);
563     return 0;
564 }
565 
566 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)
567 {
568     mp3dec_frame_t *idx_frame;
569     mp3dec_ex_t *dec = cast(mp3dec_ex_t *)user_data;
570     if (!dec.index.frames && !dec.start_offset)
571     {   /* detect VBR tag and try to avoid full scan */
572         uint32_t frames;
573         int delay, padding;
574         dec.info = *info;
575         dec.start_offset = dec.offset = offset;
576         dec.end_offset   = (offset + buf_size);
577         dec.free_format_bytes = free_format_bytes; /* should not change */
578         if (3 == dec.info.layer)
579         {
580             int ret = mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding);
581             if (ret)
582                 dec.start_offset = dec.offset = offset + frame_size;
583             if (ret > 0)
584             {
585                 padding *= info.channels;
586                 dec.start_delay = dec.to_skip = delay*info.channels;
587                 dec.samples = hdr_frame_samples(frame)*info.channels*cast(uint64_t)frames;
588                 if (dec.samples >= cast(uint64_t)dec.start_delay)
589                     dec.samples -= dec.start_delay;
590                 if (padding > 0 && dec.samples >= cast(uint64_t)padding)
591                     dec.samples -= padding;
592                 dec.detected_samples = dec.samples;
593                 dec.vbr_tag_found = 1;
594                 return MP3D_E_USER;
595             } else if (ret < 0)
596                 return 0;
597         }
598     }
599     if (dec.index.num_frames + 1 > dec.index.capacity)
600     {
601         if (!dec.index.capacity)
602             dec.index.capacity = 4096;
603         else
604             dec.index.capacity *= 2;
605         mp3dec_frame_t *alloc_buf = cast(mp3dec_frame_t *)realloc(cast(void*)dec.index.frames, (mp3dec_frame_t.sizeof)*dec.index.capacity);
606         if (!alloc_buf)
607             return MP3D_E_MEMORY;
608         dec.index.frames = alloc_buf;
609     }
610     idx_frame = &dec.index.frames[dec.index.num_frames++];
611     idx_frame.offset = offset;
612     idx_frame.sample = dec.samples;
613     if (!dec.buffer_samples && dec.index.num_frames < 256)
614     {   /* for some cutted mp3 frames, bit-reservoir not filled and decoding can't be started from first frames */
615         /* try to decode up to 255 first frames till samples starts to decode */
616         dec.buffer_samples = mp3dec_decode_frame(&dec.mp3d, frame, cast(int)MINIMP3_MIN(buf_size, cast(size_t)int.max), dec.buffer.ptr, info);
617         dec.samples += dec.buffer_samples*info.channels;
618     } else
619         dec.samples += hdr_frame_samples(frame)*info.channels;
620     return 0;
621 }
622 
623 int mp3dec_ex_open_buf(mp3dec_ex_t *dec, const uint8_t *buf, size_t buf_size, int seek_method)
624 {
625     if (!dec || !buf || cast(size_t)-1 == buf_size || !(MP3D_SEEK_TO_BYTE == seek_method || MP3D_SEEK_TO_SAMPLE == seek_method))
626         return MP3D_E_PARAM;
627     memset(dec, 0, (*dec).sizeof);
628     dec.file.buffer = buf;
629     dec.file.size   = buf_size;
630     dec.seek_method = seek_method;
631     mp3dec_init(&dec.mp3d);
632     int ret = mp3dec_iterate_buf(dec.file.buffer, dec.file.size, &mp3dec_load_index, dec);
633     if (ret && MP3D_E_USER != ret)
634         return ret;
635     mp3dec_init(&dec.mp3d);
636     dec.buffer_samples = 0;
637     return 0;
638 }
639 
640 size_t mp3dec_idx_binary_search(mp3dec_index_t *idx, uint64_t position)
641 {
642     size_t end = idx.num_frames, start = 0, index = 0;
643     while (start <= end)
644     {
645         size_t mid = (start + end) / 2;
646         if (idx.frames[mid].sample >= position)
647         {   /* move left side. */
648             if (idx.frames[mid].sample == position)
649                 return mid;
650             end = mid - 1;
651         }  else
652         {   /* move to right side */
653             index = mid;
654             start = mid + 1;
655             if (start == idx.num_frames)
656                 break;
657         }
658     }
659     return index;
660 }
661 
662 int mp3dec_ex_seek(mp3dec_ex_t *dec, uint64_t position)
663 {
664     size_t i;
665     if (!dec)
666         return MP3D_E_PARAM;
667     if (MP3D_SEEK_TO_BYTE == dec.seek_method)
668     {
669         if (dec.io)
670         {
671             dec.offset = position;
672         } else
673         {
674             dec.offset = MINIMP3_MIN(position, dec.file.size);
675         }
676         dec.cur_sample = 0;
677         goto do_exit;
678     }
679     dec.cur_sample = position;
680     position += dec.start_delay;
681     if (0 == position)
682     {   /* optimize seek to zero, no index needed */
683 seek_zero:
684         dec.offset  = dec.start_offset;
685         dec.to_skip = 0;
686         goto do_exit;
687     }
688     if (!dec.index.frames && dec.vbr_tag_found)
689     {   /* no index created yet (vbr tag used to calculate track length) */
690         dec.samples = 0;
691         dec.buffer_samples = 0;
692         if (dec.io)
693         {
694             if (dec.io.seek(dec.start_offset, dec.io.seek_data))
695                 return MP3D_E_IOERROR;
696             int ret = mp3dec_iterate_cb(dec.io, cast(uint8_t *)dec.file.buffer, dec.file.size, &mp3dec_load_index, dec);
697             if (ret && MP3D_E_USER != ret)
698                 return ret;
699         } else
700         {
701             int ret = mp3dec_iterate_buf(dec.file.buffer + dec.start_offset, cast(size_t)(dec.file.size - dec.start_offset), &mp3dec_load_index, dec);
702             if (ret && MP3D_E_USER != ret)
703                 return ret;
704         }
705         for (i = 0; i < dec.index.num_frames; i++)
706             dec.index.frames[i].offset += dec.start_offset;
707         dec.samples = dec.detected_samples;
708     }
709     if (!dec.index.frames)
710         goto seek_zero; /* no frames in file - seek to zero */
711     i = mp3dec_idx_binary_search(&dec.index, position);
712     if (i)
713     {
714         int to_fill_bytes = 511;
715         int skip_frames = MINIMP3_PREDECODE_FRAMES;
716         i -= MINIMP3_MIN(i, cast(size_t)skip_frames);
717         if (3 == dec.info.layer)
718         {
719             while (i && to_fill_bytes)
720             {   /* make sure bit-reservoir is filled when we start decoding */
721                 bs_t[1] bs;
722                 L3_gr_info_t[4] gr_info;
723                 int frame_bytes, frame_size;
724                 const(uint8_t) *hdr;
725                 if (dec.io)
726                 {
727                     hdr = dec.file.buffer;
728                     if (dec.io.seek(dec.index.frames[i - 1].offset, dec.io.seek_data))
729                         return MP3D_E_IOERROR;
730                     size_t readed = dec.io.read(cast(uint8_t *)hdr, HDR_SIZE, dec.io.read_data);
731                     if (readed != HDR_SIZE)
732                         return MP3D_E_IOERROR;
733                     frame_size = hdr_frame_bytes(hdr, dec.free_format_bytes) + hdr_padding(hdr);
734                     readed = dec.io.read(cast(uint8_t *)hdr + HDR_SIZE, frame_size - HDR_SIZE, dec.io.read_data);
735                     if (readed != cast(size_t)(frame_size - HDR_SIZE))
736                         return MP3D_E_IOERROR;
737                     bs_init(bs.ptr, hdr + HDR_SIZE, frame_size - HDR_SIZE);
738                 } else
739                 {
740                     hdr = dec.file.buffer + dec.index.frames[i - 1].offset;
741                     frame_size = hdr_frame_bytes(hdr, dec.free_format_bytes) + hdr_padding(hdr);
742                     bs_init(bs.ptr, hdr + HDR_SIZE, frame_size - HDR_SIZE);
743                 }
744                 if (HDR_IS_CRC(hdr))
745                     get_bits(bs.ptr, 16);
746                 i--;
747                 if (L3_read_side_info(bs.ptr, gr_info.ptr, hdr) < 0)
748                     break; /* frame not decodable, we can start from here */
749                 frame_bytes = (bs[0].limit - bs[0].pos)/8;
750                 to_fill_bytes -= MINIMP3_MIN(to_fill_bytes, frame_bytes);
751             }
752         }
753     }
754     dec.offset = dec.index.frames[i].offset;
755     dec.to_skip = cast(int)(position - dec.index.frames[i].sample);
756     while ((i + 1) < dec.index.num_frames && !dec.index.frames[i].sample && !dec.index.frames[i + 1].sample)
757     {   /* skip not decodable first frames */
758         const(uint8_t) *hdr;
759         if (dec.io)
760         {
761             hdr = dec.file.buffer;
762             if (dec.io.seek(dec.index.frames[i].offset, dec.io.seek_data))
763                 return MP3D_E_IOERROR;
764             size_t readed = dec.io.read(cast(uint8_t *)hdr, HDR_SIZE, dec.io.read_data);
765             if (readed != HDR_SIZE)
766                 return MP3D_E_IOERROR;
767         } else
768             hdr = dec.file.buffer + dec.index.frames[i].offset;
769         dec.to_skip += hdr_frame_samples(hdr)*dec.info.channels;
770         i++;
771     }
772 do_exit:
773     if (dec.io)
774     {
775         if (dec.io.seek(dec.offset, dec.io.seek_data))
776             return MP3D_E_IOERROR;
777     }
778     dec.buffer_samples  = 0;
779     dec.buffer_consumed = 0;
780     dec.input_consumed  = 0;
781     dec.input_filled    = 0;
782     dec.last_error      = 0;
783     mp3dec_init(&dec.mp3d);
784     return 0;
785 }
786 
787 size_t mp3dec_ex_read(mp3dec_ex_t *dec, mp3d_sample_t *buf, size_t samples)
788 {
789     if (!dec || !buf)
790         return MP3D_E_PARAM;
791     uint64_t end_offset = dec.end_offset ? dec.end_offset : dec.file.size;
792     size_t samples_requested = samples;
793     int eof = 0;
794     mp3dec_frame_info_t frame_info;
795     memset(&frame_info, 0, (frame_info.sizeof));
796     if (dec.detected_samples && dec.cur_sample >= dec.detected_samples)
797         return 0; /* at end of stream */
798     if (dec.last_error)
799         return 0; /* error eof state, seek can reset it */
800     if (dec.buffer_consumed < dec.buffer_samples)
801     {
802         size_t to_copy = MINIMP3_MIN(cast(size_t)(dec.buffer_samples - dec.buffer_consumed), samples);
803         if (dec.detected_samples)
804         {   /* count decoded samples to properly cut padding */
805             if (dec.cur_sample + to_copy >= dec.detected_samples)
806                 to_copy = cast(size_t)(dec.detected_samples - dec.cur_sample);
807         }
808         dec.cur_sample += to_copy;
809         memcpy(buf, dec.buffer.ptr + dec.buffer_consumed, to_copy*(mp3d_sample_t.sizeof));
810         buf += to_copy;
811         dec.buffer_consumed += to_copy;
812         samples -= to_copy;
813     }
814     while (samples)
815     {
816         if (dec.detected_samples && dec.cur_sample >= dec.detected_samples)
817             break;
818         const(uint8_t) *dec_buf;
819         if (dec.io)
820         {
821             if (!eof && (dec.input_filled - dec.input_consumed) < MINIMP3_BUF_SIZE)
822             {   /* keep minimum 10 consecutive mp3 frames (~16KB) worst case */
823                 memmove(cast(uint8_t*)dec.file.buffer, cast(uint8_t*)dec.file.buffer + dec.input_consumed, dec.input_filled - dec.input_consumed);
824                 dec.input_filled -= dec.input_consumed;
825                 dec.input_consumed = 0;
826                 size_t readed = dec.io.read(cast(uint8_t*)dec.file.buffer + dec.input_filled, dec.file.size - dec.input_filled, dec.io.read_data);
827                 if (readed > (dec.file.size - dec.input_filled))
828                 {
829                     dec.last_error = MP3D_E_IOERROR;
830                     readed = 0;
831                 }
832                 if (readed != (dec.file.size - dec.input_filled))
833                     eof = 1;
834                 dec.input_filled += readed;
835                 if (eof)
836                     mp3dec_skip_id3v1(cast(uint8_t*)dec.file.buffer, &dec.input_filled);
837             }
838             dec_buf = dec.file.buffer + dec.input_consumed;
839             if (!(dec.input_filled - dec.input_consumed))
840                 break;
841             dec.buffer_samples = mp3dec_decode_frame(&dec.mp3d, dec_buf, cast(int)(dec.input_filled - dec.input_consumed), dec.buffer.ptr, &frame_info);
842             dec.input_consumed += frame_info.frame_bytes;
843         } else
844         {
845             dec_buf = dec.file.buffer + dec.offset;
846             uint64_t buf_size = end_offset - dec.offset;
847             if (!buf_size)
848                 break;
849             dec.buffer_samples = mp3dec_decode_frame(&dec.mp3d, dec_buf, cast(int) MINIMP3_MIN(buf_size, cast(uint64_t)int.max), dec.buffer.ptr, &frame_info);
850         }
851         dec.buffer_consumed = 0;
852         if (dec.info.hz != frame_info.hz || dec.info.layer != frame_info.layer
853             || dec.info.channels != frame_info.channels
854             )
855         {
856             dec.last_error = MP3D_E_DECODE;
857             break;
858         }
859         if (dec.buffer_samples)
860         {
861             dec.buffer_samples *= frame_info.channels;
862             if (dec.to_skip)
863             {
864                 size_t skip = MINIMP3_MIN(dec.buffer_samples, dec.to_skip);
865                 dec.buffer_consumed += skip;
866                 dec.to_skip -= skip;
867             }
868             size_t to_copy = MINIMP3_MIN(cast(size_t)(dec.buffer_samples - dec.buffer_consumed), samples);
869             if (dec.detected_samples)
870             {   /* ^ handle padding */
871                 if (dec.cur_sample + to_copy >= dec.detected_samples)
872                     to_copy = cast(size_t)(dec.detected_samples - dec.cur_sample);
873             }
874             dec.cur_sample += to_copy;
875             memcpy(buf, dec.buffer.ptr + dec.buffer_consumed, to_copy*(mp3d_sample_t.sizeof));
876             buf += to_copy;
877             dec.buffer_consumed += to_copy;
878             samples -= to_copy;
879         } else if (dec.to_skip)
880         {   /* In mp3 decoding not always can start decode from any frame because of bit reservoir,
881                count skip samples for such frames */
882             int frame_samples = hdr_frame_samples(dec_buf)*frame_info.channels;
883             dec.to_skip -= MINIMP3_MIN(frame_samples, dec.to_skip);
884         }
885         dec.offset += frame_info.frame_bytes;
886     }
887     return samples_requested - samples;
888 }
889 
890 
891 void mp3dec_close_file(mp3dec_map_info_t *map_info)
892 {
893     if (map_info.buffer)
894         free(cast(void *)map_info.buffer);
895     map_info.buffer = null;
896     map_info.size = 0;
897 }
898 
899 int mp3dec_detect_mapinfo(mp3dec_map_info_t *map_info)
900 {
901     int ret = mp3dec_detect_buf(map_info.buffer, map_info.size);
902     mp3dec_close_file(map_info);
903     return ret;
904 }
905 
906 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)
907 {
908     int ret = mp3dec_load_buf(dec, map_info.buffer, map_info.size, info, progress_cb, user_data);
909     mp3dec_close_file(map_info);
910     return ret;
911 }
912 
913 int mp3dec_iterate_mapinfo(mp3dec_map_info_t *map_info, MP3D_ITERATE_CB callback, void *user_data)
914 {
915     int ret = mp3dec_iterate_buf(map_info.buffer, map_info.size, callback, user_data);
916     mp3dec_close_file(map_info);
917     return ret;
918 }
919 
920 static int mp3dec_ex_open_mapinfo(mp3dec_ex_t *dec, int seek_method)
921 {
922     int ret = mp3dec_ex_open_buf(dec, dec.file.buffer, dec.file.size, seek_method);
923     dec.is_file = 1;
924     if (ret)
925         mp3dec_ex_close(dec);
926     return ret;
927 }
928 
929 int mp3dec_ex_open_cb(mp3dec_ex_t *dec, mp3dec_io_t *io, int seek_method)
930 {
931     if (!dec || !io || !(MP3D_SEEK_TO_BYTE == seek_method || MP3D_SEEK_TO_SAMPLE == seek_method))
932         return MP3D_E_PARAM;
933     memset(dec, 0, (*dec).sizeof);
934     dec.file.size = MINIMP3_IO_SIZE;
935     dec.file.buffer = cast(const uint8_t*)malloc(dec.file.size);
936     if (!dec.file.buffer)
937         return MP3D_E_MEMORY;
938     dec.seek_method = seek_method;
939     dec.io = io;
940     mp3dec_init(&dec.mp3d);
941     if (io.seek(0, io.seek_data))
942         return MP3D_E_IOERROR;
943     int ret = mp3dec_iterate_cb(io, cast(uint8_t *)dec.file.buffer, dec.file.size, &mp3dec_load_index, dec);
944     if (ret && MP3D_E_USER != ret)
945         return ret;
946     if (dec.io.seek(dec.start_offset, dec.io.seek_data))
947         return MP3D_E_IOERROR;
948     mp3dec_init(&dec.mp3d);
949     dec.buffer_samples = 0;
950     return 0;
951 }
952 
953 void mp3dec_ex_close(mp3dec_ex_t *dec)
954 {
955     if (dec.index.frames)
956         free(dec.index.frames);
957     memset(dec, 0, (*dec).sizeof);
958 }
959 
960