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
6 This software is distributed without any warranty.6 This software is distributed without any warranty.
7 See <http://creativecommons.org/publicdomain/zero/1.0/>.7 See <http://creativecommons.org/publicdomain/zero/1.0/>.
8*/8*/
9#include <minimp3.h>9#include "minimp3.h"
10 10
11typedef struct11typedef struct
12{12{
13 short *buffer;13 int16_t *buffer;
14 size_t samples;14 size_t samples;
15 int channels, hz, layer, avg_bitrate_kbps;15 int channels, hz, layer, avg_bitrate_kbps;
16} mp3dec_file_info_t;16} mp3dec_file_info_t;
17 17
18typedef int (*MP3D_ITERATE_CB)(mp3dec_t *dec, void *user, const void *frame, int frame_size, mp3dec_frame_info_t *info);18typedef int (*MP3D_ITERATE_CB)(void *user_data, const uint8_t *frame, int frame_size, size_t offset, mp3dec_frame_info_t *info);
19 19
20#ifdef __cplusplus20#ifdef __cplusplus
21extern "C" {21extern "C" {
@@ -23,10 +23,10 @@ extern "C" { · 1 unmodified line
23 23
24/* decode whole file/buffer block */24/* decode whole file/buffer block */
25int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info);25int mp3dec_load(mp3dec_t *dec, const char *file_name, mp3dec_file_info_t *info);
26int mp3dec_load_buf(mp3dec_t *dec, const void *buf, size_t buf_size, mp3dec_file_info_t *info);26void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info);
27/* iterate through frames with optional decoding */27/* iterate through frames with optional decoding */
28int mp3dec_iterate(mp3dec_t *dec, const char *file_name, MP3D_ITERATE_CB *cb, void *user);28int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data);
29int mp3dec_iterate_buf(mp3dec_t *dec, const void *buf, size_t buf_size, MP3D_ITERATE_CB *cb, void *user);29void mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data);
30 30
31#ifdef __cplusplus31#ifdef __cplusplus
32}32}
@@ -35,23 +35,223 @@ int mp3dec_iterate_buf(mp3dec_t *dec, const void *buf, size_t buf_size, MP3D_ITE · 2 unmodified lines
35 35
36#ifdef MINIMP3_EXT_IMPLEMENTATION36#ifdef MINIMP3_EXT_IMPLEMENTATION
37 37
38int 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
51typedef struct
52{
53 uint8_t *buffer;
54 size_t size;
55 int file;
56} mp3dec_map_info_t;
57
58static 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
68static 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));
72retry_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;
83retry_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>
97typedef struct
39{98{
99 uint8_t *buffer;
100 FILE *file;
101 size_t size;
102} mp3dec_map_info_t;
103
104static 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
114static 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;
40 return 0;134 return 0;
135error:
136 mp3dec_close_file(map_info);
137 return -1;
41}138}
139#endif
42 140
43int mp3dec_load_buf(mp3dec_t *dec, const void *buf, size_t buf_size, mp3dec_file_info_t *info)141static size_t mp3dec_skip_id3v2(const uint8_t *buf, size_t buf_size)
44{142{
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 }
45 return 0;148 return 0;
46}149}
47 150
48int mp3dec_iterate(mp3dec_t *dec, const char *file_name, MP3D_ITERATE_CB *cb)151void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info)
49{152{
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
210int 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);
50 return 0;218 return 0;
51}219}
52 220
53int mp3dec_iterate_buf(mp3dec_t *dec, const void *buf, size_t buf_size, MP3D_ITERATE_CB *cb)221void 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
247int mp3dec_iterate(const char *file_name, MP3D_ITERATE_CB callback, void *user_data)
54{248{
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);
55 return 0;255 return 0;
56}256}
57 257

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