1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Yoshihisa Uchida
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "string-extra.h"
26 #include "metadata_common.h"
27 #include "metadata_parsers.h"
28 #include "rbunicode.h"
31 static const int basebits
[4] = { 4, 8, 12, 16 };
33 static const int frequency
[5] = { 4000, 8000, 11025, 22050, 44100 };
35 static const int support_codepages
[5] = {
36 #ifdef HAVE_LCD_BITMAP
37 SJIS
, ISO_8859_1
, -1, GB_2312
, BIG_5
,
39 -1, ISO_8859_1
, -1, -1, -1,
44 #define UCS2 (NUM_CODEPAGES + 1)
47 #define TAG_TITLE (('S'<<8)|'T')
48 #define TAG_ARTIST (('A'<<8)|'N')
49 #define TAG_COMPOSER (('S'<<8)|'W')
51 /* convert functions */
52 #define CONVERT_SMAF_CHANNELS(c) (((c) >> 7) + 1)
55 static inline int convert_smaf_audio_basebit(unsigned int basebit
)
59 return basebits
[basebit
];
62 static inline int convert_smaf_audio_frequency(unsigned int freq
)
66 return frequency
[freq
];
69 static int convert_smaf_codetype(unsigned int codetype
)
72 return support_codepages
[codetype
];
73 else if (codetype
== 0x20 || codetype
== 0x24) /* In Rockbox, UCS2 and UTF-16 are same. */
75 else if (codetype
== 0x23)
77 else if (codetype
== 0xff)
82 static void set_length(struct mp3entry
*id3
, unsigned int ch
, unsigned int basebit
,
83 unsigned int numbytes
)
85 int bitspersample
= convert_smaf_audio_basebit(basebit
);
87 if (bitspersample
!= 0 && id3
->frequency
!= 0)
89 /* Calculate track length [ms] and bitrate [kbit/s] */
90 id3
->length
= (uint64_t)numbytes
* 8000LL
91 / (bitspersample
* CONVERT_SMAF_CHANNELS(ch
) * id3
->frequency
);
92 id3
->bitrate
= bitspersample
* id3
->frequency
/ 1000;
95 /* output contents/wave data/id3 info (for debug) */
96 DEBUGF("contents info ----\n");
97 DEBUGF(" TITLE: %s\n", (id3
->title
)? id3
->title
: "(NULL)");
98 DEBUGF(" ARTIST: %s\n", (id3
->artist
)? id3
->artist
: "(NULL)");
99 DEBUGF(" COMPOSER: %s\n", (id3
->composer
)? id3
->composer
: "(NULL)");
100 DEBUGF("wave data info ----\n");
101 DEBUGF(" channels: %u\n", CONVERT_SMAF_CHANNELS(ch
));
102 DEBUGF(" bitspersample: %d\n", bitspersample
);
103 DEBUGF(" numbytes; %u\n", numbytes
);
104 DEBUGF("id3 info ----\n");
105 DEBUGF(" frquency: %u\n", (unsigned int)id3
->frequency
);
106 DEBUGF(" bitrate: %d\n", id3
->bitrate
);
107 DEBUGF(" length: %u\n", (unsigned int)id3
->length
);
110 /* contents parse functions */
113 * 1) When the codepage is UTF-8 or UCS2, contents data do not start BOM.
114 * 2) The byte order of contents data is big endian.
117 static void decode2utf8(const unsigned char *src
, unsigned char **dst
,
118 int srcsize
, int *dstsize
, int codepage
)
120 unsigned char tmpbuf
[srcsize
* 3 + 1];
124 if (codepage
< NUM_CODEPAGES
)
125 p
= iso_decode(src
, tmpbuf
, codepage
, srcsize
);
126 else /* codepage == UCS2 */
127 p
= utf16BEdecode(src
, tmpbuf
, srcsize
);
131 strlcpy(*dst
, tmpbuf
, *dstsize
);
132 utf8size
= (p
- tmpbuf
) + 1;
133 if (utf8size
> *dstsize
)
135 DEBUGF("metadata warning: data length: %d > contents store buffer size: %d\n",
140 *dstsize
-= utf8size
;
143 static int read_audio_track_contets(int fd
, int codepage
, unsigned char **dst
,
146 /* value length <= 256 bytes */
147 unsigned char buf
[256];
148 unsigned char *p
= buf
;
149 unsigned char *q
= buf
;
154 while (p
- buf
< 256 && *p
!= ',')
157 if (codepage
!= UCS2
)
162 else if (*p
== '\0' && *(p
+1) == '\\')
167 if (codepage
== UTF_8
)
169 while ((*p
& MASK
) != COMP
)
172 #ifdef HAVE_LCD_BITMAP
173 else if (codepage
== SJIS
)
175 if (*p
<= 0xa0 || *p
>= 0xe0)
182 if (codepage
== UCS2
)
185 datasize
= p
- buf
+ 1;
186 lseek(fd
, datasize
- 256, SEEK_CUR
);
189 decode2utf8(buf
, dst
, q
- buf
, dstsize
, codepage
);
194 static void read_score_track_contets(int fd
, int codepage
, int datasize
,
195 unsigned char **dst
, int *dstsize
)
197 unsigned char buf
[datasize
];
199 read(fd
, buf
, datasize
);
200 decode2utf8(buf
, dst
, datasize
, dstsize
, codepage
);
203 /* traverse chunk functions */
205 static unsigned int search_chunk(int fd
, const unsigned char *name
, int nlen
)
207 unsigned char buf
[8];
208 unsigned int chunksize
;
210 while (read(fd
, buf
, 8) > 0)
212 chunksize
= get_long_be(buf
+ 4);
213 if (memcmp(buf
, name
, nlen
) == 0)
216 lseek(fd
, chunksize
, SEEK_CUR
);
218 DEBUGF("metadata error: missing '%s' chunk\n", name
);
222 static bool parse_smaf_audio_track(int fd
, struct mp3entry
*id3
, unsigned int datasize
)
224 /* temporary buffer */
225 unsigned char *tmp
= (unsigned char*)id3
->path
;
226 /* contents stored buffer */
227 unsigned char *buf
= id3
->id3v2buf
;
228 int bufsize
= sizeof(id3
->id3v2buf
);
230 unsigned int chunksize
= datasize
;
235 /* parse contents info */
237 codepage
= convert_smaf_codetype(tmp
[2]);
240 DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp
[2]);
245 while ((id3
->title
== NULL
|| id3
->artist
== NULL
|| id3
->composer
== NULL
)
246 && (datasize
> 0 && bufsize
> 0))
248 if (read(fd
, tmp
, 3) <= 0)
253 DEBUGF("metadata error: illegal tag: %c%c%c\n", tmp
[0], tmp
[1], tmp
[2]);
256 switch ((tmp
[0]<<8)|tmp
[1])
260 valsize
= read_audio_track_contets(fd
, codepage
, &buf
, &bufsize
);
264 valsize
= read_audio_track_contets(fd
, codepage
, &buf
, &bufsize
);
268 valsize
= read_audio_track_contets(fd
, codepage
, &buf
, &bufsize
);
271 valsize
= read_audio_track_contets(fd
, codepage
, NULL
, &bufsize
);
274 datasize
-= (valsize
+ 3);
277 /* search PCM Audio Track Chunk */
278 lseek(fd
, 16 + chunksize
, SEEK_SET
);
280 chunksize
= search_chunk(fd
, "ATR", 3);
283 DEBUGF("metadata error: missing PCM Audio Track Chunk\n");
292 * +2: bit 7 0:mono/1:stereo, bit 4-6 format, bit 0-3: frequency
293 * +3: bit 4-7: base bit
297 * Note: If PCM Audio Track does not include Sequence Data Chunk,
298 * tmp+6 is the start position of Wave Data Chunk.
302 /* search Wave Data Chunk */
303 chunksize
= search_chunk(fd
, "Awa", 3);
306 DEBUGF("metadata error: missing Wave Data Chunk\n");
310 /* set track length and bitrate */
311 id3
->frequency
= convert_smaf_audio_frequency(tmp
[2] & 0x0f);
312 set_length(id3
, tmp
[2], tmp
[3] >> 4, chunksize
);
316 static bool parse_smaf_score_track(int fd
, struct mp3entry
*id3
)
318 /* temporary buffer */
319 unsigned char *tmp
= (unsigned char*)id3
->path
;
320 unsigned char *p
= tmp
;
321 /* contents stored buffer */
322 unsigned char *buf
= id3
->id3v2buf
;
323 int bufsize
= sizeof(id3
->id3v2buf
);
325 unsigned int chunksize
;
326 unsigned int datasize
;
331 /* parse Optional Data Chunk */
333 if (memcmp(tmp
+ 5, "OPDA", 4) != 0)
335 DEBUGF("metadata error: missing Optional Data Chunk\n");
339 /* Optional Data Chunk size */
340 chunksize
= get_long_be(tmp
+ 9);
342 /* parse Data Chunk */
343 if (memcmp(tmp
+ 13, "Dch", 3) != 0)
345 DEBUGF("metadata error: missing Data Chunk\n");
349 codepage
= convert_smaf_codetype(tmp
[16]);
352 DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp
[16]);
356 /* Data Chunk size */
357 datasize
= get_long_be(tmp
+ 17);
358 while ((id3
->title
== NULL
|| id3
->artist
== NULL
|| id3
->composer
== NULL
)
359 && (datasize
> 0 && bufsize
> 0))
361 if (read(fd
, tmp
, 4) <= 0)
364 valsize
= (tmp
[2] << 8) | tmp
[3];
365 datasize
-= (valsize
+ 4);
366 switch ((tmp
[0]<<8)|tmp
[1])
370 read_score_track_contets(fd
, codepage
, valsize
, &buf
, &bufsize
);
374 read_score_track_contets(fd
, codepage
, valsize
, &buf
, &bufsize
);
378 read_score_track_contets(fd
, codepage
, valsize
, &buf
, &bufsize
);
381 lseek(fd
, valsize
, SEEK_CUR
);
386 /* search Score Track Chunk */
387 lseek(fd
, 29 + chunksize
, SEEK_SET
);
389 if (search_chunk(fd
, "MTR", 3) == 0)
391 DEBUGF("metadata error: missing Score Track Chunk\n");
397 * usually, next chunk ('M***') found within 40 bytes.
400 read(fd
, tmp
, chunksize
);
402 tmp
[chunksize
] = 'M'; /* stopper */
406 chunksize
-= (p
- tmp
);
409 DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk");
413 /* search Score Track Stream PCM Data Chunk */
414 lseek(fd
, -chunksize
, SEEK_CUR
);
415 if (search_chunk(fd
, "Mtsp", 4) == 0)
417 DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk\n");
422 * parse Score Track Stream Wave Data Chunk
424 * +4-7: chunk size (WaveType(3bytes) + wave data count)
425 * +8: bit 7 0:mono/1:stereo, bit 4-6 format, bit 0-3: base bit
426 * +9: frequency (MSB)
427 * +10: frequency (LSB)
430 if (memcmp(tmp
, "Mwa", 3) != 0)
432 DEBUGF("metadata error: missing Score Track Stream Wave Data Chunk\n");
436 /* set track length and bitrate */
437 id3
->frequency
= (tmp
[9] << 8) | tmp
[10];
438 set_length(id3
, tmp
[8], tmp
[8] & 0x0f, get_long_be(tmp
+ 4) - 3);
442 bool get_smaf_metadata(int fd
, struct mp3entry
* id3
)
444 /* temporary buffer */
445 unsigned char *tmp
= (unsigned char *)id3
->path
;
446 unsigned int chunksize
;
450 id3
->composer
= NULL
;
452 id3
->vbr
= false; /* All SMAF files are CBR */
453 id3
->filesize
= filesize(fd
);
455 /* check File Chunk and Contents Info Chunk */
456 lseek(fd
, 0, SEEK_SET
);
458 if ((memcmp(tmp
, "MMMD", 4) != 0) || (memcmp(tmp
+ 8, "CNTI", 4) != 0))
460 DEBUGF("metadata error: does not smaf format\n");
464 chunksize
= get_long_be(tmp
+ 12);
466 return parse_smaf_audio_track(fd
, id3
, chunksize
);
468 return parse_smaf_score_track(fd
, id3
);