summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoshihisa Uchida <uchida@rockbox.org>2010-03-14 05:41:02 +0000
committerYoshihisa Uchida <uchida@rockbox.org>2010-03-14 05:41:02 +0000
commit2d1937a158b1259a54c8820194e6f7fb5ff1ab47 (patch)
treee086f4e50b17b931cc8df520da3339821afc2f56
parentefeb43b3415f367f110e1b25c9ada1b6478d6325 (diff)
downloadrockbox-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
-rw-r--r--apps/metadata/wave.c117
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 */
58static 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", 58static 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 */
68static 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", 68static 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 */
78enum 77enum
@@ -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
157static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt, 146static 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
211static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chunknames, bool is_64) 200static 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
336bool get_wave_metadata(int fd, struct mp3entry* id3) 325bool 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
341bool get_wave64_metadata(int fd, struct mp3entry* id3) 330bool 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}