Database: find_entry_ram: Avoid dircache use if it's not ready
[kugel-rb.git] / apps / metadata / wave.c
blob93c4d8309c3e3f5420a174016b21e2e86399ce76
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Dave Chapman
11 * Copyright (C) 2010 Yoshihisa Uchida
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
22 #include <stdio.h>
23 #include <string.h>
24 #include <inttypes.h>
26 #include "system.h"
27 #include "metadata.h"
28 #include "metadata_common.h"
29 #include "metadata_parsers.h"
30 #include "rbunicode.h"
31 #include "logf.h"
33 #ifdef DEBUGF
34 #undef DEBUGF
35 #define DEBUGF(...)
36 #endif
38 /* Wave(RIFF)/Wave64 format */
41 # define AV_WL32(p, d) do { \
42 ((uint8_t*)(p))[0] = (d); \
43 ((uint8_t*)(p))[1] = (d)>>8; \
44 ((uint8_t*)(p))[2] = (d)>>16; \
45 ((uint8_t*)(p))[3] = (d)>>24; \
46 } while(0)
47 # define AV_WL16(p, d) do { \
48 ((uint8_t*)(p))[0] = (d); \
49 ((uint8_t*)(p))[1] = (d)>>8; \
50 } while(0)
52 enum {
53 RIFF_CHUNK = 0,
54 WAVE_CHUNK,
55 FMT_CHUNK,
56 FACT_CHUNK,
57 DATA_CHUNK,
58 LIST_CHUNK,
61 /* Wave chunk names */
62 #define WAVE_CHUNKNAME_LENGTH 4
63 #define WAVE_CHUNKSIZE_LENGTH 4
65 static const unsigned char *wave_chunklist = "RIFF"
66 "WAVE"
67 "fmt "
68 "fact"
69 "data"
70 "LIST";
72 /* Wave64 GUIDs */
73 #define WAVE64_CHUNKNAME_LENGTH 16
74 #define WAVE64_CHUNKSIZE_LENGTH 8
76 static const unsigned char *wave64_chunklist
77 = "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00"
78 "wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"
79 "fmt \xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"
80 "fact\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"
81 "data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"
82 "\xbc\x94\x5f\x92\x5a\x52\xd2\x11\x86\xdc\x00\xc0\x4f\x8e\xdb\x8a";
84 /* list/info chunk */
86 struct info_chunk {
87 const unsigned char* tag;
88 size_t offset;
91 /* info chunk names are common wave/wave64 */
92 static const struct info_chunk info_chunks[] = {
93 { "INAM", offsetof(struct mp3entry, title), }, /* title */
94 { "IART", offsetof(struct mp3entry, artist), }, /* artist */
95 { "ISBJ", offsetof(struct mp3entry, albumartist), }, /* albumartist */
96 { "IPRD", offsetof(struct mp3entry, album), }, /* album */
97 { "IWRI", offsetof(struct mp3entry, composer), }, /* composer */
98 { "ICMT", offsetof(struct mp3entry, comment), }, /* comment */
99 { "ISRF", offsetof(struct mp3entry, grouping), }, /* grouping */
100 { "IGNR", offsetof(struct mp3entry, genre_string), }, /* genre */
101 { "ICRD", offsetof(struct mp3entry, year_string), }, /* date */
102 { "IPRT", offsetof(struct mp3entry, track_string), }, /* track/trackcount */
103 { "IFRM", offsetof(struct mp3entry, disc_string), }, /* disc/disccount */
106 #define INFO_CHUNK_COUNT ((int)ARRAYLEN(info_chunks))
108 /* support formats */
109 enum
111 WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM Format */
112 WAVE_FORMAT_ADPCM = 0x0002, /* Microsoft ADPCM Format */
113 WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* IEEE Float */
114 WAVE_FORMAT_ALAW = 0x0006, /* Microsoft ALAW */
115 WAVE_FORMAT_MULAW = 0x0007, /* Microsoft MULAW */
116 WAVE_FORMAT_DVI_ADPCM = 0x0011, /* Intel's DVI ADPCM */
117 WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic OKI ADPCM */
118 WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha ADPCM */
119 WAVE_FORMAT_XBOX_ADPCM = 0x0069, /* XBOX ADPCM */
120 IBM_FORMAT_MULAW = 0x0101, /* same as WAVE_FORMAT_MULAW */
121 IBM_FORMAT_ALAW = 0x0102, /* same as WAVE_FORMAT_ALAW */
122 WAVE_FORMAT_ATRAC3 = 0x0270, /* Atrac3 stream */
123 WAVE_FORMAT_SWF_ADPCM = 0x5346, /* Adobe SWF ADPCM */
124 WAVE_FORMAT_EXTENSIBLE = 0xFFFE,
127 struct wave_fmt {
128 unsigned int formattag;
129 unsigned int channels;
130 unsigned int blockalign;
131 unsigned int bitspersample;
132 unsigned int samplesperblock;
133 uint32_t totalsamples;
134 uint64_t numbytes;
137 static unsigned char *convert_utf8(const unsigned char *src, unsigned char *dst,
138 int size, bool is_64)
140 if (is_64)
142 /* Note: wave64: metadata codepage is UTF-16 only */
143 return utf16LEdecode(src, dst, size);
145 return iso_decode(src, dst, -1, size);
148 static void set_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3)
150 switch (fmt->formattag)
152 case WAVE_FORMAT_PCM:
153 case WAVE_FORMAT_IEEE_FLOAT:
154 case WAVE_FORMAT_ALAW:
155 case WAVE_FORMAT_MULAW:
156 case IBM_FORMAT_ALAW:
157 case IBM_FORMAT_MULAW:
158 fmt->blockalign = fmt->bitspersample * fmt->channels >> 3;
159 fmt->samplesperblock = 1;
160 break;
161 case WAVE_FORMAT_YAMAHA_ADPCM:
162 if (id3->channels != 0)
164 fmt->samplesperblock =
165 (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels)?
166 id3->frequency / 30 : (fmt->blockalign << 1) / fmt->channels;
168 break;
169 case WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
170 fmt->blockalign = 1;
171 fmt->samplesperblock = 2;
172 break;
173 case WAVE_FORMAT_SWF_ADPCM:
174 if (fmt->bitspersample != 0 && id3->channels != 0)
176 fmt->samplesperblock
177 = (((fmt->blockalign << 3) - 2) / fmt->channels - 22)
178 / fmt->bitspersample + 1;
180 break;
181 default:
182 break;
185 if (fmt->blockalign != 0)
186 fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
189 static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt,
190 struct mp3entry* id3)
192 /* wFormatTag */
193 fmt->formattag = buf[0] | (buf[1] << 8);
194 /* wChannels */
195 fmt->channels = buf[2] | (buf[3] << 8);
196 /* dwSamplesPerSec */
197 id3->frequency = get_long_le(&buf[4]);
198 /* dwAvgBytesPerSec */
199 id3->bitrate = (get_long_le(&buf[8]) * 8) / 1000;
200 /* wBlockAlign */
201 fmt->blockalign = buf[12] | (buf[13] << 8);
202 /* wBitsPerSample */
203 fmt->bitspersample = buf[14] | (buf[15] << 8);
205 if (fmt->formattag != WAVE_FORMAT_EXTENSIBLE)
207 if (fmtsize > 19)
209 /* wSamplesPerBlock */
210 fmt->samplesperblock = buf[18] | (buf[19] << 8);
213 else if (fmtsize > 25)
215 /* wValidBitsPerSample */
216 fmt->bitspersample = buf[18] | (buf[19] << 8);
217 /* SubFormat */
218 fmt->formattag = buf[24] | (buf[25] << 8);
221 /* Check for ATRAC3 stream */
222 if (fmt->formattag == WAVE_FORMAT_ATRAC3)
224 int jsflag = 0;
225 if(id3->bitrate == 66 || id3->bitrate == 94)
226 jsflag = 1;
228 id3->extradata_size = 14;
229 id3->channels = 2;
230 id3->codectype = AFMT_OMA_ATRAC3;
231 id3->bytesperframe = fmt->blockalign;
233 /* Store the extradata for the codec */
234 AV_WL16(&id3->id3v2buf[0], 1); // always 1
235 AV_WL32(&id3->id3v2buf[2], id3->frequency);// samples rate
236 AV_WL16(&id3->id3v2buf[6], jsflag); // coding mode
237 AV_WL16(&id3->id3v2buf[8], jsflag); // coding mode
238 AV_WL16(&id3->id3v2buf[10], 1); // always 1
239 AV_WL16(&id3->id3v2buf[12], 0); // always 0
243 static void parse_list_chunk(int fd, struct mp3entry* id3, int chunksize, bool is_64)
245 unsigned char tmpbuf[ID3V2_BUF_SIZE];
246 unsigned char *bp = tmpbuf;
247 unsigned char *endp;
248 unsigned char *data_pos;
249 unsigned char *tag_pos = id3->id3v2buf;
250 int datasize;
251 int infosize;
252 int remain;
253 int i;
255 if (is_64)
256 lseek(fd, 4, SEEK_CUR);
257 else if (read(fd, bp, 4) < 4 || memcmp(bp, "INFO", 4))
258 return;
260 /* decrease skip bytes */
261 chunksize -= 4;
263 infosize = read(fd, bp, (ID3V2_BUF_SIZE > chunksize)? chunksize : ID3V2_BUF_SIZE);
264 if (infosize <= 8)
265 return;
267 endp = bp + infosize;
268 while (bp < endp)
270 datasize = get_long_le(bp + 4);
271 data_pos = bp + 8;
272 remain = ID3V2_BUF_SIZE - (tag_pos - (unsigned char*)id3->id3v2buf);
273 if (remain < 1)
274 break;
276 for (i = 0; i < INFO_CHUNK_COUNT; i++)
278 if (memcmp(bp, info_chunks[i].tag, 4) == 0)
280 *((char **)(((char*)id3) + info_chunks[i].offset)) = tag_pos;
281 tag_pos = convert_utf8(data_pos, tag_pos,
282 (datasize + 1 >= remain )? remain - 1 : datasize,
283 is_64);
284 *tag_pos++ = 0;
285 break;
288 bp = data_pos + datasize + (datasize & 1);
292 static bool read_header(int fd, struct mp3entry* id3, const unsigned char *chunknames,
293 bool is_64)
295 /* Use the temporary buffer */
296 unsigned char* buf = (unsigned char *)id3->path;
298 struct wave_fmt fmt;
300 const unsigned int namelen = (is_64)? WAVE64_CHUNKNAME_LENGTH : WAVE_CHUNKNAME_LENGTH;
301 const unsigned int sizelen = (is_64)? WAVE64_CHUNKSIZE_LENGTH : WAVE_CHUNKSIZE_LENGTH;
302 const unsigned int len = namelen + sizelen;
303 uint64_t chunksize;
304 uint64_t offset = len + namelen;
305 int read_data;
307 memset(&fmt, 0, sizeof(struct wave_fmt));
309 id3->vbr = false; /* All Wave/Wave64 files are CBR */
310 id3->filesize = filesize(fd);
312 /* get RIFF chunk header */
313 lseek(fd, 0, SEEK_SET);
314 read(fd, buf, offset);
316 if ((memcmp(buf, chunknames + RIFF_CHUNK * namelen, namelen) != 0) ||
317 (memcmp(buf + len, chunknames + WAVE_CHUNK * namelen, namelen) != 0))
319 DEBUGF("metadata error: missing riff header.\n");
320 return false;
323 /* iterate over WAVE chunks until 'data' chunk */
324 while (read(fd, buf, len) > 0)
326 offset += len;
328 /* get chunk size (when the header is wave64, chunksize includes GUID and data length) */
329 chunksize = (is_64) ? get_uint64_le(buf + namelen) - len :
330 get_long_le(buf + namelen);
332 read_data = 0;
333 if (memcmp(buf, chunknames + FMT_CHUNK * namelen, namelen) == 0)
335 DEBUGF("find 'fmt ' chunk\n");
337 if (chunksize < 16)
339 DEBUGF("metadata error: 'fmt ' chunk is too small: %d\n", (int)chunksize);
340 return false;
343 /* get and parse format */
344 read_data = (chunksize > 25)? 26 : chunksize;
346 read(fd, buf, read_data);
347 parse_riff_format(buf, read_data, &fmt, id3);
349 else if (memcmp(buf, chunknames + FACT_CHUNK * namelen, namelen) == 0)
351 DEBUGF("find 'fact' chunk\n");
353 /* dwSampleLength */
354 if (chunksize >= sizelen)
356 /* get totalsamples */
357 read_data = sizelen;
358 read(fd, buf, read_data);
359 fmt.totalsamples = (is_64)? get_uint64_le(buf) : get_long_le(buf);
362 else if (memcmp(buf, chunknames + DATA_CHUNK * namelen, namelen) == 0)
364 DEBUGF("find 'data' chunk\n");
365 fmt.numbytes = chunksize;
366 if (fmt.formattag == WAVE_FORMAT_ATRAC3)
367 id3->first_frame_offset = offset;
369 else if (memcmp(buf, chunknames + LIST_CHUNK * namelen, namelen) == 0)
371 DEBUGF("find 'LIST' chunk\n");
372 parse_list_chunk(fd, id3, chunksize, is_64);
373 lseek(fd, offset, SEEK_SET);
376 /* padded to next chunk */
377 chunksize += ((is_64)? ((1 + ~chunksize) & 0x07) : (chunksize & 1));
379 offset += chunksize;
380 if (offset >= id3->filesize)
381 break;
383 lseek(fd, chunksize - read_data, SEEK_CUR);
386 if (fmt.numbytes == 0)
388 DEBUGF("metadata error: read error or missing 'data' chunk.\n");
389 return false;
392 if (fmt.totalsamples == 0)
393 set_totalsamples(&fmt, id3);
395 if (id3->frequency == 0 || id3->bitrate == 0)
397 DEBUGF("metadata error: frequency or bitrate is 0\n");
398 return false;
401 /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
402 id3->length = (fmt.formattag != WAVE_FORMAT_ATRAC3)?
403 (uint64_t)fmt.totalsamples * 1000 / id3->frequency :
404 ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
406 /* output header/id3 info (for debug) */
407 DEBUGF("%s header info ----\n", (is_64)? "wave64" : "wave");
408 DEBUGF(" format: %04x\n", (int)fmt.formattag);
409 DEBUGF(" channels: %u\n", fmt.channels);
410 DEBUGF(" blockalign: %u\n", fmt.blockalign);
411 DEBUGF(" bitspersample: %u\n", fmt.bitspersample);
412 DEBUGF(" samplesperblock: %u\n", fmt.samplesperblock);
413 DEBUGF(" totalsamples: %u\n", (unsigned int)fmt.totalsamples);
414 DEBUGF(" numbytes: %u\n", (unsigned int)fmt.numbytes);
415 DEBUGF("id3 info ----\n");
416 DEBUGF(" frequency: %u\n", (unsigned int)id3->frequency);
417 DEBUGF(" bitrate: %d\n", id3->bitrate);
418 DEBUGF(" length: %u\n", (unsigned int)id3->length);
420 return true;
423 bool get_wave_metadata(int fd, struct mp3entry* id3)
425 return read_header(fd, id3, wave_chunklist, false);
428 bool get_wave64_metadata(int fd, struct mp3entry* id3)
430 return read_header(fd, id3, wave64_chunklist, true);