History

Rough high-level API implementation

lieff committed 8 years ago

Commit cba86cd1 parent ee2a6841 file · +210 −10Browse files

Unified · Split

minimp3_ex.h+210−10
@@ -6,16 +6,16 @@ · 5 unmodified lines
66 This software is distributed without any warranty.
77 See <http://creativecommons.org/publicdomain/zero/1.0/>.
88 */
9−#include <minimp3.h>
9+#include "minimp3.h"
1010
1111 typedef struct
1212 {
13− short *buffer;
13+ int16_t *buffer;
1414 size_t samples;
1515 int channels, hz, layer, avg_bitrate_kbps;
1616 } mp3dec_file_info_t;
1717
18−typedef int (*MP3D_ITERATE_CB)(mp3dec_t *dec, void *user, const void *frame, int frame_size, mp3dec_frame_info_t *info);
18+typedef int (*MP3D_ITERATE_CB)(void *user_data, const uint8_t *frame, int frame_size, size_t offset, mp3dec_frame_info_t *info);
1919
2020 #ifdef __cplusplus
2121 extern "C" {
@@ -23,10 +23,10 @@ extern "C" { · 1 unmodified line
2323
2424 /* decode whole file/buffer block */
2525 int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info);
26−int mp3dec_load_buf(mp3dec_t *dec, const void *buf, size_t buf_size, mp3dec_file_info_t *info);
26+void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info);
2727 /* iterate through frames with optional decoding */
28−int mp3dec_iterate(mp3dec_t *dec, const char *file_name, MP3D_ITERATE_CB *cb, void *user);
29−int mp3dec_iterate_buf(mp3dec_t *dec, const void *buf, size_t buf_size, MP3D_ITERATE_CB *cb, void *user);
28+int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data);
29+void mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
3030
3131 #ifdef __cplusplus
3232 }
@@ -35,23 +35,223 @@ int mp3dec_iterate_buf(mp3dec_t *dec, const void *buf, size_t buf_size, MP3D_ITE · 2 unmodified lines
3535
3636 #ifdef MINIMP3_EXT_IMPLEMENTATION
3737
38−int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info)
38+#if defined(__linux__) || defined(__FreeBSD__)
39+#include <errno.h>
40+#include <sys/mman.h>
41+#include <sys/types.h>
42+#include <sys/stat.h>
43+#include <unistd.h>
44+#include <fcntl.h>
45+#if !defined(MAP_POPULATE) && defined(__linux__)
46+#define MAP_POPULATE 0x08000
47+#elif !defined(MAP_POPULATE)
48+#define MAP_POPULATE 0
49+#endif
50+
51+typedef struct
52+{
53+ uint8_t *buffer;
54+ size_t size;
55+ int file;
56+} mp3dec_map_info_t;
57+
58+static void mp3dec_close_file(mp3dec_map_info_t *map_info)
59+{
60+ if (map_info->buffer && MAP_FAILED != map_info->buffer)
61+ munmap(map_info->buffer, map_info->size);
62+ if (map_info->file)
63+ close(map_info->file);
64+ map_info->buffer = 0;
65+ map_info->file = 0;
66+}
67+
68+static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
69+{
70+ struct stat st;
71+ memset(map_info, 0, sizeof(*map_info));
72+retry_open:
73+ map_info->file = open(file_name, O_RDONLY);
74+ if (map_info->file < 0 && (errno == EAGAIN || errno == EINTR))
75+ goto retry_open;
76+ if (map_info->file < 0 || fstat(map_info->file, &st) < 0)
77+ {
78+ mp3dec_close_file(map_info);
79+ return -1;
80+ }
81+
82+ map_info->size = st.st_size;
83+retry_mmap:
84+ map_info->buffer = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, map_info->file, 0);
85+ if (MAP_FAILED == map_info->buffer && (errno == EAGAIN || errno == EINTR))
86+ goto retry_mmap;
87+ if (MAP_FAILED == map_info->buffer)
88+ {
89+ mp3dec_close_file(map_info);
90+ return -1;
91+ }
92+ return 0;
93+}
94+/*#elif defined(_WIN32)*/
95+#else
96+#include <stdio.h>
97+typedef struct
3998 {
99+ uint8_t *buffer;
100+ FILE *file;
101+ size_t size;
102+} mp3dec_map_info_t;
103+
104+static void mp3dec_close_file(mp3dec_map_info_t *map_info)
105+{
106+ if (map_info->buffer)
107+ free(map_info->buffer);
108+ if (map_info->file)
109+ fclose(map_info->file);
110+ map_info->buffer = 0;
111+ map_info->file = 0;
112+}
113+
114+static int mp3dec_open_file(const char *file_name, mp3dec_map_info_t *map_info)
115+{
116+ memset(map_info, 0, sizeof(*map_info));
117+ map_info->file = fopen(file_name, "rb");
118+ if (!map_info->file)
119+ return -1;
120+
121+ if (fseek(map_info->file, 0, SEEK_END))
122+ goto error;
123+ long size = ftell(map_info->file);
124+ if (size < 0)
125+ goto error;
126+ map_info->size = (size_t)size;
127+ if (fseek(map_info->file, 0, SEEK_SET))
128+ goto error;
129+ map_info->buffer = (uint8_t *)malloc(map_info->size);
130+ if (!map_info->buffer)
131+ goto error;
132+ if (fread(map_info->buffer, 1, map_info->size, map_info->file) != map_info->size)
133+ goto error;
40134 return 0;
135+error:
136+ mp3dec_close_file(map_info);
137+ return -1;
41138 }
139+#endif
42140
43−int mp3dec_load_buf(mp3dec_t *dec, const void *buf, size_t buf_size, mp3dec_file_info_t *info)
141+static size_t mp3dec_skip_id3v2(const uint8_t *buf, size_t buf_size)
44142 {
143+ if (buf_size > 10 && !strncmp((char *)buf, "ID3", 3))
144+ {
145+ return (((buf[6] & 0x7f) << 21) | ((buf[7] & 0x7f) << 14) |
146+ ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f)) + 10;
147+ }
45148 return 0;
46149 }
47150
48−int mp3dec_iterate(mp3dec_t *dec, const char *file_name, MP3D_ITERATE_CB *cb)
151+void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info)
49152 {
153+ short pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];
154+ mp3dec_frame_info_t frame_info;
155+ memset(info, 0, sizeof(*info));
156+ memset(&frame_info, 0, sizeof(frame_info));
157+ /* skip id3v2 */
158+ size_t id3v2size = mp3dec_skip_id3v2(buf, buf_size);
159+ if (id3v2size > buf_size)
160+ return;
161+ buf += id3v2size;
162+ buf_size -= id3v2size;
163+ /* try to make allocation size assumption by first frame */
164+ mp3dec_init(dec);
165+ int samples;
166+ do
167+ {
168+ samples = mp3dec_decode_frame(dec, buf, buf_size, pcm, &frame_info);
169+ buf += frame_info.frame_bytes;
170+ buf_size -= frame_info.frame_bytes;
171+ if (samples)
172+ break;
173+ } while (frame_info.frame_bytes);
174+ if (!samples)
175+ return;
176+ size_t samples_bytes = samples*frame_info.channels*2;
177+ size_t allocated = (buf_size/frame_info.frame_bytes)*samples_bytes + MINIMP3_MAX_SAMPLES_PER_FRAME*2;
178+ info->buffer = malloc(allocated);
179+ memcpy(info->buffer, pcm, samples_bytes);
180+ /* save info */
181+ info->channels = frame_info.channels;
182+ info->hz = frame_info.hz;
183+ info->layer = frame_info.layer;
184+ size_t avg_bitrate_kbps = frame_info.bitrate_kbps;
185+ size_t frames = 1;
186+ /* decode rest frames */
187+ do
188+ {
189+ if ((allocated - samples_bytes) < MINIMP3_MAX_SAMPLES_PER_FRAME*2)
190+ {
191+ allocated *= 2;
192+ info->buffer = realloc(info->buffer, allocated);
193+ }
194+ samples = mp3dec_decode_frame(dec, buf, buf_size, (int16_t*)((int8_t *)info->buffer + samples_bytes), &frame_info);
195+ if (samples)
196+ {
197+ info->samples += samples;
198+ avg_bitrate_kbps += frame_info.bitrate_kbps;
199+ samples_bytes += samples*frame_info.channels*2;
200+ }
201+ buf += frame_info.frame_bytes;
202+ buf_size -= frame_info.frame_bytes;
203+ } while (frame_info.frame_bytes);
204+ /* reallocate to normal buffer size */
205+ if (allocated != samples_bytes)
206+ info->buffer = realloc(info->buffer, samples_bytes);
207+ info->avg_bitrate_kbps = avg_bitrate_kbps/frames;
208+}
209+
210+int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info)
211+{
212+ int ret;
213+ mp3dec_map_info_t map_info;
214+ if ((ret = mp3dec_open_file(file_name, &map_info)))
215+ return ret;
216+ mp3dec_load_buf(dec, map_info.buffer, map_info.size, info);
217+ mp3dec_close_file(&map_info);
50218 return 0;
51219 }
52220
53−int mp3dec_iterate_buf(mp3dec_t *dec, const void *buf, size_t buf_size, MP3D_ITERATE_CB *cb)
221+void mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
222+{
223+ mp3dec_frame_info_t frame_info;
224+ memset(&frame_info, 0, sizeof(frame_info));
225+ /* skip id3v2 */
226+ size_t id3v2size = mp3dec_skip_id3v2(buf, buf_size);
227+ if (id3v2size > buf_size)
228+ return;
229+ buf += id3v2size;
230+ buf_size -= id3v2size;
231+ do
232+ {
233+ int free_format_bytes = 0, frame_size = 0;
234+ int i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
235+ buf += i;
236+ buf_size -= i;
237+ if (i && !frame_size)
238+ continue;
239+ if (!frame_size)
240+ break;
241+ callback(user_data, buf + i, frame_size, i, &frame_info);
242+ buf += frame_size;
243+ buf_size -= frame_size;
244+ } while (1);
245+}
246+
247+int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data)
54248 {
249+ int ret;
250+ mp3dec_map_info_t map_info;
251+ if ((ret = mp3dec_open_file(file_name, &map_info)))
252+ return ret;
253+ mp3dec_iterate_buf(map_info.buffer, map_info.size, callback, user_data);
254+ mp3dec_close_file(&map_info);
55255 return 0;
56256 }
57257

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t