diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-03-14 05:41:02 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-03-14 05:41:02 +0000 |
commit | 2d1937a158b1259a54c8820194e6f7fb5ff1ab47 (patch) | |
tree | e086f4e50b17b931cc8df520da3339821afc2f56 /apps/metadata/wave.c | |
parent | efeb43b3415f367f110e1b25c9ada1b6478d6325 (diff) | |
download | rockbox-2d1937a158b1259a54c8820194e6f7fb5ff1ab47.tar.gz rockbox-2d1937a158b1259a54c8820194e6f7fb5ff1ab47.zip |
wave metadata parser reduces binsize.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25161 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/metadata/wave.c')
-rw-r--r-- | apps/metadata/wave.c | 117 |
1 files changed, 53 insertions, 64 deletions
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c index 3a54d72439..eeb4f0f343 100644 --- a/apps/metadata/wave.c +++ b/apps/metadata/wave.c | |||
@@ -21,8 +21,6 @@ | |||
21 | ****************************************************************************/ | 21 | ****************************************************************************/ |
22 | #include <stdio.h> | 22 | #include <stdio.h> |
23 | #include <string.h> | 23 | #include <string.h> |
24 | #include <stdlib.h> | ||
25 | #include <ctype.h> | ||
26 | #include <inttypes.h> | 24 | #include <inttypes.h> |
27 | 25 | ||
28 | #include "system.h" | 26 | #include "system.h" |
@@ -51,28 +49,29 @@ enum { | |||
51 | FMT_CHUNK, | 49 | FMT_CHUNK, |
52 | FACT_CHUNK, | 50 | FACT_CHUNK, |
53 | DATA_CHUNK, | 51 | DATA_CHUNK, |
54 | NUM_CHUNKS, | ||
55 | }; | 52 | }; |
56 | 53 | ||
57 | /* Wave chunk names */ | 54 | /* Wave chunk names */ |
58 | static const unsigned char *wave_chunknames[NUM_CHUNKS] = | 55 | #define WAVE_CHUNKNAME_LENGTH 4 |
59 | { | 56 | #define WAVE_CHUNKSIZE_LENGTH 4 |
60 | [RIFF_CHUNK] = "RIFF", | 57 | |
61 | [WAVE_CHUNK] = "WAVE", | 58 | static const unsigned char *wave_chunklist = "RIFF" |
62 | [FMT_CHUNK] = "fmt ", | 59 | "WAVE" |
63 | [FACT_CHUNK] = "fact", | 60 | "fmt " |
64 | [DATA_CHUNK] = "data", | 61 | "fact" |
65 | }; | 62 | "data"; |
66 | 63 | ||
67 | /* Wave64 GUIDs */ | 64 | /* Wave64 GUIDs */ |
68 | static const unsigned char *wave64_chunknames[NUM_CHUNKS] = | 65 | #define WAVE64_CHUNKNAME_LENGTH 16 |
69 | { | 66 | #define WAVE64_CHUNKSIZE_LENGTH 8 |
70 | [RIFF_CHUNK] = "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00", | 67 | |
71 | [WAVE_CHUNK] = "wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a", | 68 | static const unsigned char *wave64_chunklist |
72 | [FMT_CHUNK] = "fmt \xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a", | 69 | = "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00" |
73 | [FACT_CHUNK] = "fact\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a", | 70 | "wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a" |
74 | [DATA_CHUNK] = "data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a", | 71 | "fmt \xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a" |
75 | }; | 72 | "fact\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a" |
73 | "data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"; | ||
74 | |||
76 | 75 | ||
77 | /* support formats */ | 76 | /* support formats */ |
78 | enum | 77 | enum |
@@ -113,45 +112,35 @@ static void set_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3) | |||
113 | case WAVE_FORMAT_MULAW: | 112 | case WAVE_FORMAT_MULAW: |
114 | case IBM_FORMAT_ALAW: | 113 | case IBM_FORMAT_ALAW: |
115 | case IBM_FORMAT_MULAW: | 114 | case IBM_FORMAT_MULAW: |
116 | if (fmt->bitspersample != 0 && fmt->channels != 0) | 115 | fmt->blockalign = fmt->bitspersample * fmt->channels >> 3; |
117 | fmt->totalsamples = fmt->numbytes / ((fmt->bitspersample >> 3) * fmt->channels); | 116 | fmt->samplesperblock = 1; |
118 | break; | ||
119 | case WAVE_FORMAT_ADPCM: | ||
120 | case WAVE_FORMAT_DVI_ADPCM: | ||
121 | case WAVE_FORMAT_XBOX_ADPCM: | ||
122 | if (fmt->blockalign != 0) | ||
123 | fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
124 | break; | 117 | break; |
125 | case WAVE_FORMAT_YAMAHA_ADPCM: | 118 | case WAVE_FORMAT_YAMAHA_ADPCM: |
126 | if (fmt->blockalign != 0 && fmt->channels != 0) | 119 | if (id3->channels != 0) |
127 | { | 120 | { |
128 | if (fmt->samplesperblock == 0) | 121 | fmt->samplesperblock = |
129 | { | 122 | (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels)? |
130 | if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels) | 123 | id3->frequency / 30 : (fmt->blockalign << 1) / fmt->channels; |
131 | fmt->samplesperblock = id3->frequency / 30; | ||
132 | else | ||
133 | fmt->samplesperblock = (fmt->blockalign << 1) / fmt->channels; | ||
134 | } | ||
135 | fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
136 | } | 124 | } |
137 | break; | 125 | break; |
138 | case WAVE_FORMAT_DIALOGIC_OKI_ADPCM: | 126 | case WAVE_FORMAT_DIALOGIC_OKI_ADPCM: |
139 | fmt->totalsamples = fmt->numbytes << 1; | 127 | fmt->blockalign = 1; |
128 | fmt->samplesperblock = 2; | ||
140 | break; | 129 | break; |
141 | case WAVE_FORMAT_SWF_ADPCM: | 130 | case WAVE_FORMAT_SWF_ADPCM: |
142 | if (fmt->blockalign != 0 && fmt->bitspersample != 0 && fmt->channels != 0) | 131 | if (fmt->bitspersample != 0 && id3->channels != 0) |
143 | { | 132 | { |
144 | if (fmt->samplesperblock == 0) | 133 | fmt->samplesperblock |
145 | fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) | 134 | = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) |
146 | / fmt->bitspersample; | 135 | / fmt->bitspersample + 1; |
147 | |||
148 | fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
149 | } | 136 | } |
150 | break; | 137 | break; |
151 | default: | 138 | default: |
152 | fmt->totalsamples = 0; | ||
153 | break; | 139 | break; |
154 | } | 140 | } |
141 | |||
142 | if (fmt->blockalign != 0) | ||
143 | fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; | ||
155 | } | 144 | } |
156 | 145 | ||
157 | static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt, | 146 | static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt, |
@@ -208,15 +197,16 @@ static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt * | |||
208 | } | 197 | } |
209 | } | 198 | } |
210 | 199 | ||
211 | static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chunknames, bool is_64) | 200 | static bool read_header(int fd, struct mp3entry* id3, const unsigned char *chunknames, |
201 | bool is_64) | ||
212 | { | 202 | { |
213 | /* Use the temporary buffer */ | 203 | /* Use the temporary buffer */ |
214 | unsigned char* buf = (unsigned char *)id3->path; | 204 | unsigned char* buf = (unsigned char *)id3->path; |
215 | 205 | ||
216 | struct wave_fmt fmt; | 206 | struct wave_fmt fmt; |
217 | 207 | ||
218 | unsigned int namelen = (is_64)? 16 : 4; | 208 | unsigned int namelen = (is_64)? WAVE64_CHUNKNAME_LENGTH : WAVE_CHUNKNAME_LENGTH; |
219 | unsigned int sizelen = (is_64)? 8 : 4; | 209 | unsigned int sizelen = (is_64)? WAVE64_CHUNKSIZE_LENGTH : WAVE_CHUNKSIZE_LENGTH; |
220 | unsigned int len = namelen + sizelen; | 210 | unsigned int len = namelen + sizelen; |
221 | uint64_t chunksize; | 211 | uint64_t chunksize; |
222 | uint64_t offset = len + namelen; | 212 | uint64_t offset = len + namelen; |
@@ -228,8 +218,8 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun | |||
228 | lseek(fd, 0, SEEK_SET); | 218 | lseek(fd, 0, SEEK_SET); |
229 | read(fd, buf, offset); | 219 | read(fd, buf, offset); |
230 | 220 | ||
231 | if ((memcmp(buf, chunknames[RIFF_CHUNK], namelen) != 0) || | 221 | if ((memcmp(buf, chunknames + RIFF_CHUNK * namelen, namelen) != 0) || |
232 | (memcmp(buf + len, chunknames[WAVE_CHUNK], namelen) != 0)) | 222 | (memcmp(buf + len, chunknames + WAVE_CHUNK * namelen, namelen) != 0)) |
233 | { | 223 | { |
234 | DEBUGF("metadata error: missing riff header.\n"); | 224 | DEBUGF("metadata error: missing riff header.\n"); |
235 | return false; | 225 | return false; |
@@ -251,7 +241,7 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun | |||
251 | chunksize = (is_64) ? get_uint64_le(buf + namelen) - len : | 241 | chunksize = (is_64) ? get_uint64_le(buf + namelen) - len : |
252 | get_long_le(buf + namelen); | 242 | get_long_le(buf + namelen); |
253 | 243 | ||
254 | if (memcmp(buf, chunknames[DATA_CHUNK], namelen) == 0) | 244 | if (memcmp(buf, chunknames + DATA_CHUNK * namelen, namelen) == 0) |
255 | { | 245 | { |
256 | DEBUGF("find 'data' chunk\n"); | 246 | DEBUGF("find 'data' chunk\n"); |
257 | fmt.numbytes = chunksize; | 247 | fmt.numbytes = chunksize; |
@@ -265,7 +255,7 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun | |||
265 | offset += chunksize; | 255 | offset += chunksize; |
266 | 256 | ||
267 | read_data = 0; | 257 | read_data = 0; |
268 | if (memcmp(buf, chunknames[FMT_CHUNK], namelen) == 0) | 258 | if (memcmp(buf, chunknames + FMT_CHUNK * namelen, namelen) == 0) |
269 | { | 259 | { |
270 | DEBUGF("find 'fmt ' chunk\n"); | 260 | DEBUGF("find 'fmt ' chunk\n"); |
271 | 261 | ||
@@ -281,7 +271,7 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun | |||
281 | read(fd, buf, read_data); | 271 | read(fd, buf, read_data); |
282 | parse_riff_format(buf, read_data, &fmt, id3); | 272 | parse_riff_format(buf, read_data, &fmt, id3); |
283 | } | 273 | } |
284 | else if (memcmp(buf, chunknames[FACT_CHUNK], namelen) == 0) | 274 | else if (memcmp(buf, chunknames + FACT_CHUNK * namelen, namelen) == 0) |
285 | { | 275 | { |
286 | DEBUGF("find 'fact' chunk\n"); | 276 | DEBUGF("find 'fact' chunk\n"); |
287 | 277 | ||
@@ -301,20 +291,19 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun | |||
301 | if (fmt.totalsamples == 0) | 291 | if (fmt.totalsamples == 0) |
302 | set_totalsamples(&fmt, id3); | 292 | set_totalsamples(&fmt, id3); |
303 | 293 | ||
294 | if (id3->frequency == 0 || id3->bitrate == 0) | ||
295 | { | ||
296 | DEBUGF("metadata error: frequency or bitrate is 0\n"); | ||
297 | return false; | ||
298 | } | ||
299 | |||
304 | id3->vbr = false; /* All Wave/Wave64 files are CBR */ | 300 | id3->vbr = false; /* All Wave/Wave64 files are CBR */ |
305 | id3->filesize = filesize(fd); | 301 | id3->filesize = filesize(fd); |
306 | 302 | ||
307 | /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ | 303 | /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ |
308 | if(fmt.formattag != WAVE_FORMAT_ATRAC3) | 304 | id3->length = (fmt.formattag != WAVE_FORMAT_ATRAC3)? |
309 | { | 305 | (uint64_t)fmt.totalsamples * 1000 / id3->frequency : |
310 | if (id3->frequency != 0) | 306 | ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate; |
311 | id3->length = ((int64_t) fmt.totalsamples * 1000) / id3->frequency; | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | if (id3->bitrate != 0) | ||
316 | id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate; | ||
317 | } | ||
318 | 307 | ||
319 | /* output header/id3 info (for debug) */ | 308 | /* output header/id3 info (for debug) */ |
320 | DEBUGF("%s header info ----\n", (is_64)? "wave64" : "wave"); | 309 | DEBUGF("%s header info ----\n", (is_64)? "wave64" : "wave"); |
@@ -335,10 +324,10 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun | |||
335 | 324 | ||
336 | bool get_wave_metadata(int fd, struct mp3entry* id3) | 325 | bool get_wave_metadata(int fd, struct mp3entry* id3) |
337 | { | 326 | { |
338 | return read_header(fd, id3, (const unsigned char **)&wave_chunknames, false); | 327 | return read_header(fd, id3, wave_chunklist, false); |
339 | } | 328 | } |
340 | 329 | ||
341 | bool get_wave64_metadata(int fd, struct mp3entry* id3) | 330 | bool get_wave64_metadata(int fd, struct mp3entry* id3) |
342 | { | 331 | { |
343 | return read_header(fd, id3, (const unsigned char **)&wave64_chunknames, true); | 332 | return read_header(fd, id3, wave64_chunklist, true); |
344 | } | 333 | } |