summaryrefslogtreecommitdiff
path: root/apps/metadata/smaf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/metadata/smaf.c')
-rw-r--r--apps/metadata/smaf.c578
1 files changed, 339 insertions, 239 deletions
diff --git a/apps/metadata/smaf.c b/apps/metadata/smaf.c
index 586802b7b5..ca5b690e0b 100644
--- a/apps/metadata/smaf.c
+++ b/apps/metadata/smaf.c
@@ -18,10 +18,7 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include <stdio.h>
22#include <string.h> 21#include <string.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <inttypes.h> 22#include <inttypes.h>
26 23
27#include "system.h" 24#include "system.h"
@@ -31,339 +28,442 @@
31#include "rbunicode.h" 28#include "rbunicode.h"
32#include "logf.h" 29#include "logf.h"
33 30
34static int basebits[4] = { 4, 8, 12, 16 }; 31static const int basebits[4] = { 4, 8, 12, 16 };
35 32
36static int frequency[5] = { 4000, 8000, 11025, 22050, 44100 }; 33static const int frequency[5] = { 4000, 8000, 11025, 22050, 44100 };
37 34
38static int support_codepages[7] = { 35static const int support_codepages[5] = {
39 SJIS, ISO_8859_1, -1, GB_2312, BIG_5, -1, -1, 36#ifdef HAVE_LCD_BITMAP
37 SJIS, ISO_8859_1, -1, GB_2312, BIG_5,
38#else
39 -1, ISO_8859_1, -1, -1, -1,
40#endif
40}; 41};
41 42
42/* extra codepage */ 43/* extra codepage */
43#define UCS_2 (NUM_CODEPAGES + 1) 44#define UCS2 (NUM_CODEPAGES + 1)
44#define UTF_16 (NUM_CODEPAGES + 2)
45 45
46/* support id3 tag */ 46/* support id3 tag */
47#define TAG_TITLE (('S'<<8)|'T') 47#define TAG_TITLE (('S'<<8)|'T')
48#define TAG_ARTIST (('A'<<8)|'N') 48#define TAG_ARTIST (('A'<<8)|'N')
49#define TAG_COMPOSER (('S'<<8)|'W') 49#define TAG_COMPOSER (('S'<<8)|'W')
50 50
51static bool read_datachunk(unsigned char *src, int size, unsigned short tag, 51/* convert functions */
52 int codepage, unsigned char *dst) 52#define CONVERT_SMAF_CHANNELS(c) (((c) >> 7) + 1)
53{
54 int datasize = 0;
55 unsigned char *utf8;
56 53
57 while(size > datasize + 4)
58 {
59 datasize = (src[2] << 8) | src[3];
60 if (tag == ((src[0] << 8) | src[1]))
61 {
62 src += 4;
63 if (codepage < NUM_CODEPAGES)
64 utf8 = iso_decode(src, dst, codepage, datasize);
65 else /* codepage == UTF_16, UCS_2 */
66 utf8 = utf16BEdecode(src, dst, datasize);
67 *utf8 = '\0';
68
69 return true;
70 }
71 src += (datasize + 4);
72 }
73 return false;
74}
75 54
76static bool read_option(unsigned char *src, int size, unsigned short tag, 55static inline int convert_smaf_audio_basebit(unsigned int basebit)
77 int codepage, unsigned char *dst)
78{ 56{
79 int datasize = 0; 57 if (basebit > 3)
80 unsigned char *endsrc = src + size; 58 return 0;
81 unsigned char *utf8; 59 return basebits[basebit];
82
83 while(src < endsrc)
84 {
85 utf8 = src;
86 src += 3;
87 datasize = 0;
88 while (*src != ',' || *(src-1) == '\\')
89 {
90 datasize++;
91 src++;
92 }
93 if (tag == ((utf8[0] << 8) | utf8[1]) && utf8[2] == ':')
94 {
95 utf8 += 3;
96 if (codepage < NUM_CODEPAGES)
97 utf8 = iso_decode(utf8, dst, codepage, datasize);
98 else /* codepage == UTF_16, UCS_2 */
99 utf8 = utf16BEdecode(utf8, dst, datasize);
100 *utf8 = '\0';
101
102 return true;
103 }
104 src++;
105 }
106 return false;
107} 60}
108 61
109static int convert_smaf_audio_frequency(unsigned int freq) 62static inline int convert_smaf_audio_frequency(unsigned int freq)
110{ 63{
111 if (freq > 4) 64 if (freq > 4)
112 return 0; 65 return 0;
113 return frequency[freq]; 66 return frequency[freq];
114} 67}
115 68
116static int convert_smaf_audio_basebit(unsigned int basebit)
117{
118 if (basebit > 4)
119 return 0;
120 return basebits[basebit];
121}
122
123static int convert_smaf_codetype(unsigned int codetype) 69static int convert_smaf_codetype(unsigned int codetype)
124{ 70{
125 if (codetype < 7) 71 if (codetype < 5)
126 return support_codepages[codetype]; 72 return support_codepages[codetype];
127 else if (codetype < 0x20) 73 else if (codetype == 0x20 || codetype == 0x24) /* In Rockbox, UCS2 and UTF-16 are same. */
128 return -1; 74 return UCS2;
129 else if (codetype == 0x20)
130 return UCS_2;
131 else if (codetype == 0x23) 75 else if (codetype == 0x23)
132 return UTF_8; 76 return UTF_8;
133 else if (codetype == 0x24)
134 return UTF_16;
135 else if (codetype == 0xff) 77 else if (codetype == 0xff)
136 return ISO_8859_1; 78 return ISO_8859_1;
137 return -1; 79 return -1;
138} 80}
139 81
140static bool get_smaf_metadata_audio_track(struct mp3entry *id3, 82static void set_length(struct mp3entry *id3, unsigned int ch, unsigned int basebit,
141 unsigned char* buf, unsigned char *endbuf) 83 unsigned int numbytes)
142{ 84{
143 int bitspersample; 85 int bitspersample = convert_smaf_audio_basebit(basebit);
144 int channels; 86
145 int chunksize; 87 if (bitspersample != 0 && id3->frequency != 0)
146 long numbytes;
147 unsigned long totalsamples;
148
149 channels = ((buf[10] & 0x80) >> 7) + 1;
150 bitspersample = convert_smaf_audio_basebit(buf[11] >> 4);
151 if (bitspersample == 0)
152 { 88 {
153 DEBUGF("metada error: smaf unsupport basebit %d\n", buf[11] >> 4); 89 /* Calculate track length [ms] and bitrate [kbit/s] */
154 return false; 90 id3->length = (uint64_t)numbytes * 8000LL
91 / (bitspersample * CONVERT_SMAF_CHANNELS(ch) * id3->frequency);
92 id3->bitrate = bitspersample * id3->frequency / 1000;
155 } 93 }
156 id3->frequency = convert_smaf_audio_frequency(buf[10] & 0x0f);
157 94
158 buf += 14; 95 /* output contents/wave data/id3 info (for debug) */
159 while (buf < endbuf) 96 DEBUGF("contents info ----\n");
160 { 97 DEBUGF(" TITLE: %s\n", (id3->title)? id3->title : "(NULL)");
161 chunksize = get_long_be(buf + 4) + 8; 98 DEBUGF(" ARTIST: %s\n", (id3->artist)? id3->artist : "(NULL)");
162 if (memcmp(buf, "Awa", 3) == 0) 99 DEBUGF(" COMPOSER: %s\n", (id3->composer)? id3->composer : "(NULL)");
163 { 100 DEBUGF("wave data info ----\n");
164 numbytes = get_long_be(buf + 4) - 3; 101 DEBUGF(" channels: %u\n", CONVERT_SMAF_CHANNELS(ch));
165 totalsamples = (numbytes << 3) / (bitspersample * channels); 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);
108}
166 109
167 /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ 110/* contents parse functions */
168 id3->length = ((int64_t)totalsamples * 1000LL) / id3->frequency;
169 111
170 return true; 112/* Note:
171 } 113 * 1) When the codepage is UTF-8 or UCS2, contents data do not start BOM.
172 buf += chunksize; 114 * 2) The byte order of contents data is big endian.
115 */
116
117static void decode2utf8(const unsigned char *src, unsigned char **dst,
118 int srcsize, int *dstsize, int codepage)
119{
120 unsigned char tmpbuf[srcsize * 3 + 1];
121 unsigned char *p;
122 int utf8size;
123
124 if (codepage < NUM_CODEPAGES)
125 p = iso_decode(src, tmpbuf, codepage, srcsize);
126 else /* codepage == UCS2 */
127 p = utf16BEdecode(src, tmpbuf, srcsize);
128
129 *p = '\0';
130
131 strlcpy(*dst, tmpbuf, *dstsize);
132 utf8size = (p - tmpbuf) + 1;
133 if (utf8size > *dstsize)
134 {
135 DEBUGF("metadata warning: data length: %d > contents store buffer size: %d\n",
136 utf8size, *dstsize);
137 utf8size = *dstsize;
173 } 138 }
174 DEBUGF("metada error: smaf does not include pcm audio data\n"); 139 *dst += utf8size;
175 return false; 140 *dstsize -= utf8size;
176} 141}
177 142
178static bool get_smaf_metadata_score_track(struct mp3entry *id3, 143static int read_audio_track_contets(int fd, int codepage, unsigned char **dst,
179 unsigned char* buf, unsigned char *endbuf) 144 int *dstsize)
180{ 145{
181 int bitspersample; 146 /* value length <= 256 bytes */
182 int channels; 147 unsigned char buf[256];
183 int chunksize; 148 unsigned char *p = buf;
184 long numbytes; 149 unsigned char *q = buf;
185 unsigned long totalsamples; 150 int datasize;
186 151
187 /* 152 read(fd, buf, 256);
188 * skip to the next chunk.
189 * MA-2/MA-3/MA-5: padding 16 bytes
190 * MA-7: padding 32 bytes
191 */
192 if (buf[3] < 7)
193 buf += 28;
194 else
195 buf += 44;
196 153
197 while (buf + 10 < endbuf) 154 while (p - buf < 256 && *p != ',')
198 { 155 {
199 chunksize = get_long_be(buf + 4) + 8; 156 /* skip yen mark */
200 if (memcmp(buf, "Mtsp", 4) == 0) 157 if (codepage != UCS2)
201 { 158 {
202 buf += 8; 159 if (*p == '\\')
203 if (memcmp(buf, "Mwa", 3) != 0) 160 p++;
161 }
162 else if (*p == '\0' && *(p+1) == '\\')
163 p += 2;
164
165 if (*p > 0x7f)
166 {
167 if (codepage == UTF_8)
204 { 168 {
205 DEBUGF("metada error: smaf unsupport format: %c%c%c%c\n", 169 while ((*p & MASK) != COMP)
206 buf[0], buf[1], buf[2], buf[3]); 170 *q++ = *p++;
207 return false;
208 } 171 }
209 172#ifdef HAVE_LCD_BITMAP
210 channels = ((buf[8] & 0x80) >> 7) + 1; 173 else if (codepage == SJIS)
211 bitspersample = convert_smaf_audio_basebit(buf[8] & 0x0f);
212 if (bitspersample == 0)
213 { 174 {
214 DEBUGF("metada error: smaf unsupport basebit %d\n", buf[8] & 0x0f); 175 if (*p <= 0xa0 || *p >= 0xe0)
215 return false; 176 *q++ = *p++;
216 } 177 }
178#endif
179 }
217 180
218 numbytes = get_long_be(buf + 4) - 3; 181 *q++ = *p++;
219 totalsamples = numbytes * 8 / (bitspersample * channels); 182 if (codepage == UCS2)
220 183 *q++ = *p++;
221 id3->frequency = (buf[9] << 8) | buf[10]; 184 }
185 datasize = p - buf + 1;
186 lseek(fd, datasize - 256, SEEK_CUR);
222 187
223 /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ 188 if (dst != NULL)
224 id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; 189 decode2utf8(buf, dst, q - buf, dstsize, codepage);
225 190
226 return true; 191 return datasize;
227 }
228 buf += chunksize;
229 }
230 DEBUGF("metada error: smaf does not include pcm audio data\n");
231 return false;
232} 192}
233 193
234bool get_smaf_metadata(int fd, struct mp3entry* id3) 194static void read_score_track_contets(int fd, int codepage, int datasize,
195 unsigned char **dst, int *dstsize)
235{ 196{
236 unsigned char smafbuf[1024]; 197 unsigned char buf[datasize];
237 198
238 /* Use the trackname part of the id3 structure as a temporary buffer */ 199 read(fd, buf, datasize);
239 unsigned char* buf = (unsigned char *)id3->path; 200 decode2utf8(buf, dst, datasize, dstsize, codepage);
240 unsigned char *endbuf = smafbuf + sizeof(smafbuf); 201}
241 int i;
242 int contents_size;
243 int codepage = ISO_8859_1;
244 202
245 id3->title = NULL; 203/* traverse chunk functions */
246 id3->artist = NULL;
247 id3->composer = NULL;
248 204
249 id3->vbr = false; /* All SMAF files are CBR */ 205static unsigned int search_chunk(int fd, const unsigned char *name, int nlen)
250 id3->filesize = filesize(fd); 206{
207 unsigned char buf[8];
208 unsigned int chunksize;
251 209
252 /* get RIFF chunk header */ 210 while (read(fd, buf, 8) > 0)
253 if ((lseek(fd, 0, SEEK_SET) < 0) || (read(fd, buf, 21) < 21))
254 { 211 {
255 return false; 212 chunksize = get_long_be(buf + 4);
256 } 213 if (memcmp(buf, name, nlen) == 0)
214 return chunksize;
257 215
258 if ((memcmp(buf, "MMMD", 4) != 0) || (memcmp(&buf[8], "CNTI", 4) != 0)) 216 lseek(fd, chunksize, SEEK_CUR);
259 {
260 DEBUGF("metada error: does not smaf format\n");
261 return false;
262 } 217 }
218 DEBUGF("metadata error: missing '%s' chunk\n", name);
219 return 0;
220}
221
222static bool parse_smaf_audio_track(int fd, struct mp3entry *id3, unsigned int datasize)
223{
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);
229
230 unsigned int chunksize = datasize;
231 int valsize;
263 232
264 contents_size = get_long_be(buf + 12); 233 int codepage;
265 if (contents_size < 5) 234
235 /* parse contents info */
236 read(fd, tmp, 5);
237 codepage = convert_smaf_codetype(tmp[2]);
238 if (codepage < 0)
266 { 239 {
267 DEBUGF("metada error: CNTI chunk size is small %d\n", contents_size); 240 DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp[2]);
268 return false; 241 return false;
269 } 242 }
270 243
271 contents_size -= 5; 244 datasize -= 5;
272 i = contents_size; 245 while ((id3->title == NULL || id3->artist == NULL || id3->composer == NULL)
273 if (i == 0) 246 && (datasize > 0 && bufsize > 0))
274 { 247 {
275 read(fd, buf, 16); 248 if (read(fd, tmp, 3) <= 0)
276 if (memcmp(buf, "OPDA", 4) != 0)
277 {
278 DEBUGF("metada error: smaf does not include OPDA chunk\n");
279 return false; 249 return false;
280 }
281 contents_size = get_long_be(buf + 4) - 8;
282 250
283 if (memcmp(buf + 8, "Dch", 3) != 0) 251 if (tmp[2] != ':')
284 { 252 {
285 DEBUGF("metada error: smaf does not include Dch chunk\n"); 253 DEBUGF("metadata error: illegal tag: %c%c%c\n", tmp[0], tmp[1], tmp[2]);
286 return false; 254 return false;
287 } 255 }
288 codepage = convert_smaf_codetype(buf[11]); 256 switch ((tmp[0]<<8)|tmp[1])
289 if (codepage < 0)
290 { 257 {
291 DEBUGF("metada error: smaf unsupport codetype: %d\n", buf[11]); 258 case TAG_TITLE:
292 return false; 259 id3->title = buf;
260 valsize = read_audio_track_contets(fd, codepage, &buf, &bufsize);
261 break;
262 case TAG_ARTIST:
263 id3->artist = buf;
264 valsize = read_audio_track_contets(fd, codepage, &buf, &bufsize);
265 break;
266 case TAG_COMPOSER:
267 id3->composer = buf;
268 valsize = read_audio_track_contets(fd, codepage, &buf, &bufsize);
269 break;
270 default:
271 valsize = read_audio_track_contets(fd, codepage, NULL, &bufsize);
272 break;
293 } 273 }
274 datasize -= (valsize + 3);
275 }
294 276
295 i = get_long_be(buf + 12); 277 /* search PCM Audio Track Chunk */
278 lseek(fd, 16 + chunksize, SEEK_SET);
296 279
297 if (i > MAX_PATH) 280 chunksize = search_chunk(fd, "ATR", 3);
298 { 281 if (chunksize == 0)
299 DEBUGF("metada warning: smaf contents size is big %d\n", i); 282 {
300 i = MAX_PATH; 283 DEBUGF("metadata error: missing PCM Audio Track Chunk\n");
301 } 284 return false;
302 if (read(fd, buf, i) < i) 285 }
303 return false; 286
287 /*
288 * get format
289 * tmp
290 * +0: Format Type
291 * +1: Sequence Type
292 * +2: bit 7 0:mono/1:stereo, bit 4-6 format, bit 0-3: frequency
293 * +3: bit 4-7: base bit
294 * +4: TimeBase_D
295 * +5: TimeBase_G
296 *
297 * Note: If PCM Audio Track does not include Sequence Data Chunk,
298 * tmp+6 is the start position of Wave Data Chunk.
299 */
300 read(fd, tmp, 6);
301
302 /* search Wave Data Chunk */
303 chunksize = search_chunk(fd, "Awa", 3);
304 if (chunksize == 0)
305 {
306 DEBUGF("metadata error: missing Wave Data Chunk\n");
307 return false;
308 }
304 309
305 /* title */ 310 /* set track length and bitrate */
306 if (read_datachunk(buf, i, TAG_TITLE, codepage, id3->id3v1buf[0])) 311 id3->frequency = convert_smaf_audio_frequency(tmp[2] & 0x0f);
307 id3->title = id3->id3v1buf[0]; 312 set_length(id3, tmp[2], tmp[3] >> 4, chunksize);
313 return true;
314}
315
316static bool parse_smaf_score_track(int fd, struct mp3entry *id3)
317{
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);
324
325 unsigned int chunksize;
326 unsigned int datasize;
327 int valsize;
328
329 int codepage;
330
331 /* parse Optional Data Chunk */
332 read(fd, tmp, 21);
333 if (memcmp(tmp + 5, "OPDA", 4) != 0)
334 {
335 DEBUGF("metadata error: missing Optional Data Chunk\n");
336 return false;
337 }
308 338
309 /* artist */ 339 /* Optional Data Chunk size */
310 if (read_datachunk(buf, i, TAG_ARTIST, codepage, id3->id3v1buf[1])) 340 chunksize = get_long_be(tmp + 9);
311 id3->artist = id3->id3v1buf[1];
312 341
313 /* composer */ 342 /* parse Data Chunk */
314 if (read_datachunk(buf, i, TAG_COMPOSER, codepage, id3->id3v1buf[2])) 343 if (memcmp(tmp + 13, "Dch", 3) != 0)
315 id3->composer = id3->id3v1buf[2]; 344 {
345 DEBUGF("metadata error: missing Data Chunk\n");
346 return false;
316 } 347 }
317 else 348
349 codepage = convert_smaf_codetype(tmp[16]);
350 if (codepage < 0)
318 { 351 {
319 codepage = convert_smaf_codetype(buf[14]); 352 DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp[16]);
320 if (codepage < 0) 353 return false;
321 { 354 }
322 DEBUGF("metada error: smaf unsupport codetype: %d\n", buf[11]); 355
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))
360 {
361 if (read(fd, tmp, 4) <= 0)
323 return false; 362 return false;
324 }
325 363
326 if (i > MAX_PATH) 364 valsize = (tmp[2] << 8) | tmp[3];
365 datasize -= (valsize + 4);
366 switch ((tmp[0]<<8)|tmp[1])
327 { 367 {
328 DEBUGF("metada warning: smaf contents size is big %d\n", i); 368 case TAG_TITLE:
329 i = MAX_PATH; 369 id3->title = buf;
370 read_score_track_contets(fd, codepage, valsize, &buf, &bufsize);
371 break;
372 case TAG_ARTIST:
373 id3->artist = buf;
374 read_score_track_contets(fd, codepage, valsize, &buf, &bufsize);
375 break;
376 case TAG_COMPOSER:
377 id3->composer = buf;
378 read_score_track_contets(fd, codepage, valsize, &buf, &bufsize);
379 break;
380 default:
381 lseek(fd, valsize, SEEK_CUR);
382 break;
330 } 383 }
331 if (read(fd, buf, i) < i) 384 }
332 return false;
333
334 /* title */
335 if (read_option(buf, i, TAG_TITLE, codepage, id3->id3v1buf[0]))
336 id3->title = id3->id3v1buf[0];
337 385
338 /* artist */ 386 /* search Score Track Chunk */
339 if (read_option(buf, i, TAG_ARTIST, codepage, id3->id3v1buf[1])) 387 lseek(fd, 29 + chunksize, SEEK_SET);
340 id3->artist = id3->id3v1buf[1];
341 388
342 /* composer */ 389 if (search_chunk(fd, "MTR", 3) == 0)
343 if (read_option(buf, i, TAG_COMPOSER, codepage, id3->id3v1buf[2])) 390 {
344 id3->composer = id3->id3v1buf[2]; 391 DEBUGF("metadata error: missing Score Track Chunk\n");
392 return false;
345 } 393 }
346 394
347 if (contents_size > i) 395 /*
348 lseek(fd, contents_size - i, SEEK_CUR); 396 * search next chunk
397 * usually, next chunk ('M***') found within 40 bytes.
398 */
399 chunksize = 40;
400 read(fd, tmp, chunksize);
401
402 tmp[chunksize] = 'M'; /* stopper */
403 while (*p != 'M')
404 p++;
349 405
350 /* assume the SMAF pcm data position is near the start */ 406 chunksize -= (p - tmp);
351 if (read(fd, smafbuf, sizeof(smafbuf)) < (ssize_t)sizeof(smafbuf)) 407 if (chunksize == 0)
408 {
409 DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk");
352 return false; 410 return false;
411 }
353 412
354 buf = smafbuf; 413 /* search Score Track Stream PCM Data Chunk */
355 while (buf + 8 < endbuf) 414 lseek(fd, -chunksize, SEEK_CUR);
415 if (search_chunk(fd, "Mtsp", 4) == 0)
356 { 416 {
357 i = get_long_be(buf + 4) + 8; 417 DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk\n");
418 return false;
419 }
358 420
359 if (memcmp(buf, "ATR", 3) == 0) 421 /*
360 return get_smaf_metadata_audio_track(id3, buf, endbuf); 422 * parse Score Track Stream Wave Data Chunk
361 else if (memcmp(buf, "MTR", 3) == 0) 423 * tmp
362 return get_smaf_metadata_score_track(id3, buf, endbuf); 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)
428 */
429 read(fd, tmp, 11);
430 if (memcmp(tmp, "Mwa", 3) != 0)
431 {
432 DEBUGF("metadata error: missing Score Track Stream Wave Data Chunk\n");
433 return false;
434 }
435
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);
439 return true;
440}
441
442bool get_smaf_metadata(int fd, struct mp3entry* id3)
443{
444 /* temporary buffer */
445 unsigned char *tmp = (unsigned char *)id3->path;
446 unsigned int chunksize;
363 447
364 buf += i; 448 id3->title = NULL;
449 id3->artist = NULL;
450 id3->composer = NULL;
451
452 id3->vbr = false; /* All SMAF files are CBR */
453 id3->filesize = filesize(fd);
454
455 /* check File Chunk and Contents Info Chunk */
456 lseek(fd, 0, SEEK_SET);
457 read(fd, tmp, 16);
458 if ((memcmp(tmp, "MMMD", 4) != 0) || (memcmp(tmp + 8, "CNTI", 4) != 0))
459 {
460 DEBUGF("metadata error: does not smaf format\n");
461 return false;
365 } 462 }
366 463
367 DEBUGF("metada error: smaf does not include track chunk\n"); 464 chunksize = get_long_be(tmp + 12);
368 return false; 465 if (chunksize > 5)
466 return parse_smaf_audio_track(fd, id3, chunksize);
467
468 return parse_smaf_score_track(fd, id3);
369} 469}