summaryrefslogtreecommitdiff
path: root/apps/metadata/wave.c
diff options
context:
space:
mode:
authorYoshihisa Uchida <uchida@rockbox.org>2010-03-10 10:55:01 +0000
committerYoshihisa Uchida <uchida@rockbox.org>2010-03-10 10:55:01 +0000
commit207a84a3810a0a8916dc4adca7c8b3a9a4bfb929 (patch)
tree4c5938c6483344e6c613604eb19ae4d0835b457d /apps/metadata/wave.c
parent56069476be65da87604d7b006aee7008445b965f (diff)
downloadrockbox-207a84a3810a0a8916dc4adca7c8b3a9a4bfb929.tar.gz
rockbox-207a84a3810a0a8916dc4adca7c8b3a9a4bfb929.zip
unify the wave/wave64 parser.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25106 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/metadata/wave.c')
-rw-r--r--apps/metadata/wave.c363
1 files changed, 176 insertions, 187 deletions
diff --git a/apps/metadata/wave.c b/apps/metadata/wave.c
index c9291cbe54..c6bf4bdf53 100644
--- a/apps/metadata/wave.c
+++ b/apps/metadata/wave.c
@@ -31,6 +31,9 @@
31#include "metadata_parsers.h" 31#include "metadata_parsers.h"
32#include "logf.h" 32#include "logf.h"
33 33
34/* Wave(RIFF)/Wave64 format */
35
36
34# define AV_WL32(p, d) do { \ 37# define AV_WL32(p, d) do { \
35 ((uint8_t*)(p))[0] = (d); \ 38 ((uint8_t*)(p))[0] = (d); \
36 ((uint8_t*)(p))[1] = (d)>>8; \ 39 ((uint8_t*)(p))[1] = (d)>>8; \
@@ -42,14 +45,36 @@
42 ((uint8_t*)(p))[1] = (d)>>8; \ 45 ((uint8_t*)(p))[1] = (d)>>8; \
43 } while(0) 46 } while(0)
44 47
45/* Wave(RIFF)/Wave64 format */ 48enum {
49 RIFF_CHUNK = 0,
50 WAVE_CHUNK,
51 FMT_CHUNK,
52 FACT_CHUNK,
53 DATA_CHUNK,
54 NUM_CHUNKS,
55};
56
57/* Wave chunk names */
58static const unsigned char *wave_chunknames[NUM_CHUNKS] =
59{
60 [RIFF_CHUNK] = "RIFF",
61 [WAVE_CHUNK] = "WAVE",
62 [FMT_CHUNK] = "fmt ",
63 [FACT_CHUNK] = "fact",
64 [DATA_CHUNK] = "data",
65};
46 66
47/* Wave64 GUIDs */ 67/* Wave64 GUIDs */
48#define WAVE64_GUID_RIFF "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00" 68static const unsigned char *wave64_chunknames[NUM_CHUNKS] =
49#define WAVE64_GUID_WAVE "wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a" 69{
50#define WAVE64_GUID_FMT "fmt \xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a" 70 [RIFF_CHUNK] = "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00",
51#define WAVE64_GUID_DATA "data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a" 71 [WAVE_CHUNK] = "wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a",
72 [FMT_CHUNK] = "fmt \xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a",
73 [FACT_CHUNK] = "fact\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",
75};
52 76
77/* support formats */
53enum 78enum
54{ 79{
55 WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */ 80 WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */
@@ -65,21 +90,21 @@ enum
65 IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */ 90 IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */
66 WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */ 91 WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */
67 WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */ 92 WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */
93 WAVE_FORMAT_EXTENSIBLE = 0xFFFE,
68}; 94};
69 95
70struct wave_fmt { 96struct wave_fmt {
71 unsigned int formattag; 97 unsigned int formattag;
72 unsigned long channels; 98 unsigned int channels;
73 unsigned int blockalign; 99 unsigned int blockalign;
74 unsigned long bitspersample; 100 unsigned int bitspersample;
75 unsigned int samplesperblock; 101 unsigned int samplesperblock;
102 uint32_t totalsamples;
76 uint64_t numbytes; 103 uint64_t numbytes;
77}; 104};
78 105
79static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3) 106static void set_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3)
80{ 107{
81 unsigned long totalsamples = 0;
82
83 switch (fmt->formattag) 108 switch (fmt->formattag)
84 { 109 {
85 case WAVE_FORMAT_PCM: 110 case WAVE_FORMAT_PCM:
@@ -88,39 +113,45 @@ static unsigned long get_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3
88 case WAVE_FORMAT_MULAW: 113 case WAVE_FORMAT_MULAW:
89 case IBM_FORMAT_ALAW: 114 case IBM_FORMAT_ALAW:
90 case IBM_FORMAT_MULAW: 115 case IBM_FORMAT_MULAW:
91 totalsamples = 116 if (fmt->bitspersample != 0 && fmt->channels != 0)
92 fmt->numbytes / ((fmt->bitspersample >> 3) * fmt->channels); 117 fmt->totalsamples = fmt->numbytes / ((fmt->bitspersample >> 3) * fmt->channels);
93 break; 118 break;
94 case WAVE_FORMAT_ADPCM: 119 case WAVE_FORMAT_ADPCM:
95 case WAVE_FORMAT_DVI_ADPCM: 120 case WAVE_FORMAT_DVI_ADPCM:
96 case WAVE_FORMAT_XBOX_ADPCM: 121 case WAVE_FORMAT_XBOX_ADPCM:
97 totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; 122 if (fmt->blockalign != 0)
123 fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
98 break; 124 break;
99 case WAVE_FORMAT_YAMAHA_ADPCM: 125 case WAVE_FORMAT_YAMAHA_ADPCM:
100 if (fmt->samplesperblock == 0) 126 if (fmt->blockalign != 0 && fmt->channels != 0)
101 { 127 {
102 if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels) 128 if (fmt->samplesperblock == 0)
103 fmt->samplesperblock = id3->frequency / 30; 129 {
104 else 130 if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels)
105 fmt->samplesperblock = (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;
106 } 136 }
107 totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
108 break; 137 break;
109 case WAVE_FORMAT_DIALOGIC_OKI_ADPCM: 138 case WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
110 totalsamples = fmt->numbytes << 1; 139 fmt->totalsamples = fmt->numbytes << 1;
111 break; 140 break;
112 case WAVE_FORMAT_SWF_ADPCM: 141 case WAVE_FORMAT_SWF_ADPCM:
113 if (fmt->samplesperblock == 0) 142 if (fmt->blockalign != 0 && fmt->bitspersample != 0 && fmt->channels != 0)
114 fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22) 143 {
115 / fmt->bitspersample; 144 if (fmt->samplesperblock == 0)
145 fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22)
146 / fmt->bitspersample;
116 147
117 totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock; 148 fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
149 }
118 break; 150 break;
119 default: 151 default:
120 totalsamples = 0; 152 fmt->totalsamples = 0;
121 break; 153 break;
122 } 154 }
123 return totalsamples;
124} 155}
125 156
126static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt, 157static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt,
@@ -138,33 +169,65 @@ static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *
138 fmt->blockalign = buf[12] | (buf[13] << 8); 169 fmt->blockalign = buf[12] | (buf[13] << 8);
139 /* wBitsPerSample */ 170 /* wBitsPerSample */
140 fmt->bitspersample = buf[14] | (buf[15] << 8); 171 fmt->bitspersample = buf[14] | (buf[15] << 8);
141 if (fmtsize > 19) 172
173 if (fmt->formattag != WAVE_FORMAT_EXTENSIBLE)
142 { 174 {
143 /* wSamplesPerBlock */ 175 if (fmtsize > 19)
144 fmt->samplesperblock = buf[18] | (buf[19] << 8); 176 {
177 /* wSamplesPerBlock */
178 fmt->samplesperblock = buf[18] | (buf[19] << 8);
179 }
180 }
181 else if (fmtsize > 25)
182 {
183 /* wValidBitsPerSample */
184 fmt->bitspersample = buf[18] | (buf[19] << 8);
185 /* SubFormat */
186 fmt->formattag = buf[24] | (buf[25] << 8);
187 }
188
189 /* Check for ATRAC3 stream */
190 if (fmt->formattag == WAVE_FORMAT_ATRAC3)
191 {
192 int jsflag = 0;
193 if(id3->bitrate == 66 || id3->bitrate == 94)
194 jsflag = 1;
195
196 id3->extradata_size = 14;
197 id3->channels = 2;
198 id3->codectype = AFMT_OMA_ATRAC3;
199 /* Store the extradata for the codec */
200 AV_WL16(&id3->id3v2buf[0], 1); // always 1
201 AV_WL32(&id3->id3v2buf[2], id3->frequency);// samples rate
202 AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode
203 AV_WL16(&id3->id3v2buf[8], jsflag); // coding mode
204 AV_WL16(&id3->id3v2buf[10], 1); // always 1
205 AV_WL16(&id3->id3v2buf[12], 0); // always 0
145 } 206 }
146} 207}
147 208
148bool get_wave_metadata(int fd, struct mp3entry* id3) 209bool read_header(int fd, struct mp3entry* id3, const unsigned char **chunknames, bool is_64)
149{ 210{
150 /* Use the trackname part of the id3 structure as a temporary buffer */ 211 /* Use the temporary buffer */
151 unsigned char* buf = (unsigned char *)id3->path; 212 unsigned char* buf = (unsigned char *)id3->path;
213
152 struct wave_fmt fmt; 214 struct wave_fmt fmt;
153 unsigned long totalsamples = 0; 215
154 unsigned long offset = 0; 216 unsigned int namelen = (is_64)? 16 : 4;
155 int read_bytes; 217 unsigned int sizelen = (is_64)? 8 : 4;
156 int i; 218 unsigned int len = namelen + sizelen;
219 uint64_t chunksize;
220 uint64_t offset = len + namelen;
221 int read_data;
157 222
158 memset(&fmt, 0, sizeof(struct wave_fmt)); 223 memset(&fmt, 0, sizeof(struct wave_fmt));
159 224
160 /* get RIFF chunk header */ 225 /* get RIFF chunk header */
161 if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 12) < 12)) 226 lseek(fd, 0, SEEK_SET);
162 { 227 read(fd, buf, offset);
163 return false;
164 }
165 offset += 12;
166 228
167 if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) 229 if ((memcmp(buf, chunknames[RIFF_CHUNK], namelen) != 0) ||
230 (memcmp(buf + len, chunknames[WAVE_CHUNK], namelen) != 0))
168 { 231 {
169 DEBUGF("metadata error: missing riff header.\n"); 232 DEBUGF("metadata error: missing riff header.\n");
170 return false; 233 return false;
@@ -174,180 +237,106 @@ bool get_wave_metadata(int fd, struct mp3entry* id3)
174 while (true) 237 while (true)
175 { 238 {
176 /* get chunk header */ 239 /* get chunk header */
177 if (read(fd, buf, 8) < 8) 240 if (read(fd, buf, len) <= 0)
241 {
242 DEBUGF("metadata error: read error or missing 'data' chunk.\n");
178 return false; 243 return false;
179 offset += 8; 244 }
180
181 /* chunkSize */
182 i = get_long_le(&buf[4]);
183 245
184 if (memcmp(buf, "fmt ", 4) == 0) 246 offset += len;
185 {
186 /* get rest of chunk */
187 if (i < 16)
188 return false;
189 247
190 read_bytes = (i > 19)? 20 : 16; 248 /* get chunk size (when the header is wave64, chunksize includes GUID and data length) */
249 chunksize = (is_64) ? get_uint64_le(buf + namelen) - len :
250 get_long_le(buf + namelen);
191 251
192 if (read(fd, buf, read_bytes) != read_bytes) 252 if (memcmp(buf, chunknames[DATA_CHUNK], namelen) == 0)
193 return false; 253 {
254 DEBUGF("find 'data' chunk\n");
255 fmt.numbytes = chunksize;
256 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
257 id3->first_frame_offset = offset;
258 break;
259 }
194 260
195 offset += read_bytes; 261 /* padded to next chunk */
196 i -= read_bytes; 262 chunksize += ((is_64)? ((1 + ~chunksize) & 0x07) : (chunksize & 1));
263 offset += chunksize;
197 264
198 parse_riff_format(buf, read_bytes, &fmt, id3); 265 read_data = 0;
266 if (memcmp(buf, chunknames[FMT_CHUNK], namelen) == 0)
267 {
268 DEBUGF("find 'fmt ' chunk\n");
199 269
200 /* Check for ATRAC3 stream */ 270 if (chunksize < 16)
201 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
202 { 271 {
203 int jsflag = 0; 272 DEBUGF("metadata error: 'fmt ' chunk is too small: %d\n", (int)chunksize);
204 if(id3->bitrate == 66 || id3->bitrate == 94) 273 return false;
205 jsflag = 1;
206
207 id3->extradata_size = 14;
208 id3->channels = 2;
209 id3->codectype = AFMT_OMA_ATRAC3;
210 /* Store the extradata for the codec */
211 AV_WL16(&id3->id3v2buf[0], 1); // always 1
212 AV_WL32(&id3->id3v2buf[2], id3->frequency); // samples rate
213 AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode
214 AV_WL16(&id3->id3v2buf[8], jsflag); // coding mode
215 AV_WL16(&id3->id3v2buf[10], 1); // always 1
216 AV_WL16(&id3->id3v2buf[12], 0); // always 0
217 } 274 }
275
276 /* get and parse format */
277 read_data = (chunksize > 25)? 26 : chunksize;
278
279 read(fd, buf, read_data);
280 parse_riff_format(buf, read_data, &fmt, id3);
218 } 281 }
219 else if (memcmp(buf, "data", 4) == 0) 282 else if (memcmp(buf, chunknames[FACT_CHUNK], namelen) == 0)
220 {
221 fmt.numbytes = i;
222 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
223 id3->first_frame_offset = offset;
224 break;
225 }
226 else if (memcmp(buf, "fact", 4) == 0)
227 { 283 {
284 DEBUGF("find 'fact' chunk\n");
285
228 /* dwSampleLength */ 286 /* dwSampleLength */
229 if (i >= 4) 287 if (chunksize >= sizelen)
230 { 288 {
231 /* get rest of chunk */ 289 /* get totalsamples */
232 if (read(fd, buf, 4) < 4) 290 read_data = sizelen;
233 return false; 291 read(fd, buf, read_data);
234 offset += 4; 292 fmt.totalsamples = (is_64)? get_uint64_le(buf) : get_long_le(buf);
235 i -= 4;
236 totalsamples = get_long_le(buf);
237 } 293 }
238 } 294 }
239 295
240 /* seek to next chunk (even chunk sizes must be padded) */ 296 lseek(fd, chunksize - read_data, SEEK_CUR);
241 i += (i & 0x01);
242
243 if(lseek(fd, i, SEEK_CUR) < 0)
244 return false;
245 offset += i;
246 } 297 }
247 298
248 if ((fmt.numbytes == 0) || (fmt.channels == 0) || (fmt.blockalign == 0)) 299 if (fmt.totalsamples == 0)
249 { 300 set_totalsamples(&fmt, id3);
250 DEBUGF("metadata error: numbytes, channels, or blockalign is 0.\n");
251 return false;
252 }
253 301
254 if (totalsamples == 0) 302 id3->vbr = false; /* All Wave/Wave64 files are CBR */
255 {
256 totalsamples = get_totalsamples(&fmt, id3);
257 }
258
259 id3->vbr = false; /* All WAV files are CBR */
260 id3->filesize = filesize(fd); 303 id3->filesize = filesize(fd);
261 304
262 /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ 305 /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
263 if(id3->codectype != AFMT_OMA_ATRAC3) 306 if(fmt.formattag != AFMT_OMA_ATRAC3)
264 id3->length = ((int64_t) totalsamples * 1000) / id3->frequency;
265 else
266 id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
267
268 return true;
269}
270
271bool get_wave64_metadata(int fd, struct mp3entry* id3)
272{
273 /* Use the trackname part of the id3 structure as a temporary buffer */
274 unsigned char* buf = (unsigned char *)id3->path;
275 struct wave_fmt fmt;
276 unsigned long totalsamples = 0;
277 int read_bytes;
278 uint64_t i;
279
280 memset(&fmt, 0, sizeof(struct wave_fmt));
281
282 /* get RIFF chunk header */
283 if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 40) < 40))
284 return false;
285
286 if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0)||
287 (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0))
288 {
289 DEBUGF("metadata error: does not wave64 file\n");
290 return false;
291 }
292
293 /* iterate over WAVE chunks until 'data' chunk */
294 while (true)
295 { 307 {
296 /* get chunk header */ 308 if (id3->frequency != 0)
297 if (read(fd, buf, 24) < 24) 309 id3->length = ((int64_t) fmt.totalsamples * 1000) / id3->frequency;
298 return false;
299
300 /* chunkSize (excludes GUID and size length) */
301 i = get_uint64_le(buf + 16) - 24;
302
303 if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0)
304 {
305 DEBUGF("find 'fmt ' chunk\n");
306 if (i < 16)
307 return false;
308
309 read_bytes = (i > 16)? 24 : 16;
310 if ((int)i < read_bytes)
311 i = 0;
312 else
313 i -= read_bytes;
314
315 /* get rest of chunk */
316 if (read(fd, buf, read_bytes) < read_bytes)
317 return false;
318
319 parse_riff_format(buf, read_bytes, &fmt, id3);
320 }
321 else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0)
322 {
323 DEBUGF("find 'data' chunk\n");
324 fmt.numbytes = i;
325 break;
326 }
327
328 /* seek to next chunk (8byte bound) */
329 i += (1 + ~i) & 0x07;
330
331 if(lseek(fd, i, SEEK_CUR) < 0)
332 return false;
333 } 310 }
334 311 else
335 if ((fmt.numbytes == 0) || (fmt.channels == 0) || (fmt.blockalign == 0))
336 { 312 {
337 DEBUGF("metadata error: numbytes, channels, or blockalign is 0\n"); 313 if (id3->bitrate != 0)
338 return false; 314 id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
339 } 315 }
340 316
341 if (totalsamples == 0) 317 /* output header/id3 info (for debug) */
342 { 318 DEBUGF("%s header info ----\n", (is_64)? "wave64" : "wave");
343 totalsamples = get_totalsamples(&fmt, id3); 319 DEBUGF(" format: %04x\n", (int)fmt.formattag);
344 } 320 DEBUGF(" channels: %u\n", fmt.channels);
321 DEBUGF(" blockalign: %u\n", fmt.blockalign);
322 DEBUGF(" bitspersample: %u\n", fmt.bitspersample);
323 DEBUGF(" samplesperblock: %u\n", fmt.samplesperblock);
324 DEBUGF(" totalsamples: %u\n", (unsigned int)fmt.totalsamples);
325 DEBUGF(" numbytes; %u\n", (unsigned int)fmt.numbytes);
326 DEBUGF("id3 info ----\n");
327 DEBUGF(" frquency: %u\n", (unsigned int)id3->frequency);
328 DEBUGF(" bitrate: %d\n", id3->bitrate);
329 DEBUGF(" length: %u\n", (unsigned int)id3->length);
345 330
346 id3->vbr = false; /* All Wave64 files are CBR */ 331 return true;
347 id3->filesize = filesize(fd); 332}
348 333
349 /* Calculate track length [ms] */ 334bool get_wave_metadata(int fd, struct mp3entry* id3)
350 id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; 335{
336 return read_header(fd, id3, (const unsigned char **)&wave_chunknames, false);
337}
351 338
352 return true; 339bool get_wave64_metadata(int fd, struct mp3entry* id3)
340{
341 return read_header(fd, id3, (const unsigned char **)&wave64_chunknames, true);
353} 342}