summaryrefslogtreecommitdiffstats
path: root/apps/metadata/smaf.c
diff options
context:
space:
mode:
authorSean Bartell <wingedtachikoma@gmail.com>2011-06-24 01:25:21 -0400
committerNils Wallménius <nils@rockbox.org>2012-03-18 12:00:39 +0100
commitb5716df4cb2837bbbc42195cf1aefcf03e21d6a6 (patch)
tree130cd712e2e00893b6df9959a375a8d9523a1aca /apps/metadata/smaf.c
parent24bd9d5393dbe39a5c6194877bc00ede669b1d5d (diff)
downloadrockbox-b5716df4cb2837bbbc42195cf1aefcf03e21d6a6.tar.gz
rockbox-b5716df4cb2837bbbc42195cf1aefcf03e21d6a6.zip
Build librbcodec with DSP and metadata.
All associated files are moved to /lib/rbcodec. Change-Id: I572ddd2b8a996aae1e98c081d06b1ed356dce222
Diffstat (limited to 'apps/metadata/smaf.c')
-rw-r--r--apps/metadata/smaf.c470
1 files changed, 0 insertions, 470 deletions
diff --git a/apps/metadata/smaf.c b/apps/metadata/smaf.c
deleted file mode 100644
index 1b745d3fa1..0000000000
--- a/apps/metadata/smaf.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2010 Yoshihisa Uchida
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#include <inttypes.h>
-#include <stdio.h>
-
-#include "string-extra.h"
-#include "system.h"
-#include "metadata.h"
-#include "metadata_common.h"
-#include "metadata_parsers.h"
-#include "rbunicode.h"
-#include "logf.h"
-
-static const int basebits[4] = { 4, 8, 12, 16 };
-
-static const int frequency[5] = { 4000, 8000, 11025, 22050, 44100 };
-
-static const int support_codepages[5] = {
-#ifdef HAVE_LCD_BITMAP
- SJIS, ISO_8859_1, -1, GB_2312, BIG_5,
-#else
- -1, ISO_8859_1, -1, -1, -1,
-#endif
-};
-
-/* extra codepage */
-#define UCS2 (NUM_CODEPAGES + 1)
-
-/* support id3 tag */
-#define TAG_TITLE (('S'<<8)|'T')
-#define TAG_ARTIST (('A'<<8)|'N')
-#define TAG_COMPOSER (('S'<<8)|'W')
-
-/* convert functions */
-#define CONVERT_SMAF_CHANNELS(c) (((c) >> 7) + 1)
-
-
-static inline int convert_smaf_audio_basebit(unsigned int basebit)
-{
- if (basebit > 3)
- return 0;
- return basebits[basebit];
-}
-
-static inline int convert_smaf_audio_frequency(unsigned int freq)
-{
- if (freq > 4)
- return 0;
- return frequency[freq];
-}
-
-static int convert_smaf_codetype(unsigned int codetype)
-{
- if (codetype < 5)
- return support_codepages[codetype];
- else if (codetype == 0x20 || codetype == 0x24) /* In Rockbox, UCS2 and UTF-16 are same. */
- return UCS2;
- else if (codetype == 0x23)
- return UTF_8;
- else if (codetype == 0xff)
- return ISO_8859_1;
- return -1;
-}
-
-static void set_length(struct mp3entry *id3, unsigned int ch, unsigned int basebit,
- unsigned int numbytes)
-{
- int bitspersample = convert_smaf_audio_basebit(basebit);
-
- if (bitspersample != 0 && id3->frequency != 0)
- {
- /* Calculate track length [ms] and bitrate [kbit/s] */
- id3->length = (uint64_t)numbytes * 8000LL
- / (bitspersample * CONVERT_SMAF_CHANNELS(ch) * id3->frequency);
- id3->bitrate = bitspersample * id3->frequency / 1000;
- }
-
- /* output contents/wave data/id3 info (for debug) */
- DEBUGF("contents info ----\n");
- DEBUGF(" TITLE: %s\n", (id3->title)? id3->title : "(NULL)");
- DEBUGF(" ARTIST: %s\n", (id3->artist)? id3->artist : "(NULL)");
- DEBUGF(" COMPOSER: %s\n", (id3->composer)? id3->composer : "(NULL)");
- DEBUGF("wave data info ----\n");
- DEBUGF(" channels: %u\n", CONVERT_SMAF_CHANNELS(ch));
- DEBUGF(" bitspersample: %d\n", bitspersample);
- DEBUGF(" numbytes; %u\n", numbytes);
- DEBUGF("id3 info ----\n");
- DEBUGF(" frquency: %u\n", (unsigned int)id3->frequency);
- DEBUGF(" bitrate: %d\n", id3->bitrate);
- DEBUGF(" length: %u\n", (unsigned int)id3->length);
-}
-
-/* contents parse functions */
-
-/* Note:
- * 1) When the codepage is UTF-8 or UCS2, contents data do not start BOM.
- * 2) The byte order of contents data is big endian.
- */
-
-static void decode2utf8(const unsigned char *src, unsigned char **dst,
- int srcsize, int *dstsize, int codepage)
-{
- unsigned char tmpbuf[srcsize * 3 + 1];
- unsigned char *p;
- int utf8size;
-
- if (codepage < NUM_CODEPAGES)
- p = iso_decode(src, tmpbuf, codepage, srcsize);
- else /* codepage == UCS2 */
- p = utf16BEdecode(src, tmpbuf, srcsize);
-
- *p = '\0';
-
- strlcpy(*dst, tmpbuf, *dstsize);
- utf8size = (p - tmpbuf) + 1;
- if (utf8size > *dstsize)
- {
- DEBUGF("metadata warning: data length: %d > contents store buffer size: %d\n",
- utf8size, *dstsize);
- utf8size = *dstsize;
- }
- *dst += utf8size;
- *dstsize -= utf8size;
-}
-
-static int read_audio_track_contets(int fd, int codepage, unsigned char **dst,
- int *dstsize)
-{
- /* value length <= 256 bytes */
- unsigned char buf[256];
- unsigned char *p = buf;
- unsigned char *q = buf;
- int datasize;
-
- read(fd, buf, 256);
-
- while (p - buf < 256 && *p != ',')
- {
- /* skip yen mark */
- if (codepage != UCS2)
- {
- if (*p == '\\')
- p++;
- }
- else if (*p == '\0' && *(p+1) == '\\')
- p += 2;
-
- if (*p > 0x7f)
- {
- if (codepage == UTF_8)
- {
- while ((*p & MASK) != COMP)
- *q++ = *p++;
- }
-#ifdef HAVE_LCD_BITMAP
- else if (codepage == SJIS)
- {
- if (*p <= 0xa0 || *p >= 0xe0)
- *q++ = *p++;
- }
-#endif
- }
-
- *q++ = *p++;
- if (codepage == UCS2)
- *q++ = *p++;
- }
- datasize = p - buf + 1;
- lseek(fd, datasize - 256, SEEK_CUR);
-
- if (dst != NULL)
- decode2utf8(buf, dst, q - buf, dstsize, codepage);
-
- return datasize;
-}
-
-static void read_score_track_contets(int fd, int codepage, int datasize,
- unsigned char **dst, int *dstsize)
-{
- unsigned char buf[datasize];
-
- read(fd, buf, datasize);
- decode2utf8(buf, dst, datasize, dstsize, codepage);
-}
-
-/* traverse chunk functions */
-
-static unsigned int search_chunk(int fd, const unsigned char *name, int nlen)
-{
- unsigned char buf[8];
- unsigned int chunksize;
-
- while (read(fd, buf, 8) > 0)
- {
- chunksize = get_long_be(buf + 4);
- if (memcmp(buf, name, nlen) == 0)
- return chunksize;
-
- lseek(fd, chunksize, SEEK_CUR);
- }
- DEBUGF("metadata error: missing '%s' chunk\n", name);
- return 0;
-}
-
-static bool parse_smaf_audio_track(int fd, struct mp3entry *id3, unsigned int datasize)
-{
- /* temporary buffer */
- unsigned char *tmp = (unsigned char*)id3->path;
- /* contents stored buffer */
- unsigned char *buf = id3->id3v2buf;
- int bufsize = sizeof(id3->id3v2buf);
-
- unsigned int chunksize = datasize;
- int valsize;
-
- int codepage;
-
- /* parse contents info */
- read(fd, tmp, 5);
- codepage = convert_smaf_codetype(tmp[2]);
- if (codepage < 0)
- {
- DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp[2]);
- return false;
- }
-
- datasize -= 5;
- while ((id3->title == NULL || id3->artist == NULL || id3->composer == NULL)
- && (datasize > 0 && bufsize > 0))
- {
- if (read(fd, tmp, 3) <= 0)
- return false;
-
- if (tmp[2] != ':')
- {
- DEBUGF("metadata error: illegal tag: %c%c%c\n", tmp[0], tmp[1], tmp[2]);
- return false;
- }
- switch ((tmp[0]<<8)|tmp[1])
- {
- case TAG_TITLE:
- id3->title = buf;
- valsize = read_audio_track_contets(fd, codepage, &buf, &bufsize);
- break;
- case TAG_ARTIST:
- id3->artist = buf;
- valsize = read_audio_track_contets(fd, codepage, &buf, &bufsize);
- break;
- case TAG_COMPOSER:
- id3->composer = buf;
- valsize = read_audio_track_contets(fd, codepage, &buf, &bufsize);
- break;
- default:
- valsize = read_audio_track_contets(fd, codepage, NULL, &bufsize);
- break;
- }
- datasize -= (valsize + 3);
- }
-
- /* search PCM Audio Track Chunk */
- lseek(fd, 16 + chunksize, SEEK_SET);
-
- chunksize = search_chunk(fd, "ATR", 3);
- if (chunksize == 0)
- {
- DEBUGF("metadata error: missing PCM Audio Track Chunk\n");
- return false;
- }
-
- /*
- * get format
- * tmp
- * +0: Format Type
- * +1: Sequence Type
- * +2: bit 7 0:mono/1:stereo, bit 4-6 format, bit 0-3: frequency
- * +3: bit 4-7: base bit
- * +4: TimeBase_D
- * +5: TimeBase_G
- *
- * Note: If PCM Audio Track does not include Sequence Data Chunk,
- * tmp+6 is the start position of Wave Data Chunk.
- */
- read(fd, tmp, 6);
-
- /* search Wave Data Chunk */
- chunksize = search_chunk(fd, "Awa", 3);
- if (chunksize == 0)
- {
- DEBUGF("metadata error: missing Wave Data Chunk\n");
- return false;
- }
-
- /* set track length and bitrate */
- id3->frequency = convert_smaf_audio_frequency(tmp[2] & 0x0f);
- set_length(id3, tmp[2], tmp[3] >> 4, chunksize);
- return true;
-}
-
-static bool parse_smaf_score_track(int fd, struct mp3entry *id3)
-{
- /* temporary buffer */
- unsigned char *tmp = (unsigned char*)id3->path;
- unsigned char *p = tmp;
- /* contents stored buffer */
- unsigned char *buf = id3->id3v2buf;
- int bufsize = sizeof(id3->id3v2buf);
-
- unsigned int chunksize;
- unsigned int datasize;
- int valsize;
-
- int codepage;
-
- /* parse Optional Data Chunk */
- read(fd, tmp, 21);
- if (memcmp(tmp + 5, "OPDA", 4) != 0)
- {
- DEBUGF("metadata error: missing Optional Data Chunk\n");
- return false;
- }
-
- /* Optional Data Chunk size */
- chunksize = get_long_be(tmp + 9);
-
- /* parse Data Chunk */
- if (memcmp(tmp + 13, "Dch", 3) != 0)
- {
- DEBUGF("metadata error: missing Data Chunk\n");
- return false;
- }
-
- codepage = convert_smaf_codetype(tmp[16]);
- if (codepage < 0)
- {
- DEBUGF("metadata error: smaf unsupport codetype: %d\n", tmp[16]);
- return false;
- }
-
- /* Data Chunk size */
- datasize = get_long_be(tmp + 17);
- while ((id3->title == NULL || id3->artist == NULL || id3->composer == NULL)
- && (datasize > 0 && bufsize > 0))
- {
- if (read(fd, tmp, 4) <= 0)
- return false;
-
- valsize = (tmp[2] << 8) | tmp[3];
- datasize -= (valsize + 4);
- switch ((tmp[0]<<8)|tmp[1])
- {
- case TAG_TITLE:
- id3->title = buf;
- read_score_track_contets(fd, codepage, valsize, &buf, &bufsize);
- break;
- case TAG_ARTIST:
- id3->artist = buf;
- read_score_track_contets(fd, codepage, valsize, &buf, &bufsize);
- break;
- case TAG_COMPOSER:
- id3->composer = buf;
- read_score_track_contets(fd, codepage, valsize, &buf, &bufsize);
- break;
- default:
- lseek(fd, valsize, SEEK_CUR);
- break;
- }
- }
-
- /* search Score Track Chunk */
- lseek(fd, 29 + chunksize, SEEK_SET);
-
- if (search_chunk(fd, "MTR", 3) == 0)
- {
- DEBUGF("metadata error: missing Score Track Chunk\n");
- return false;
- }
-
- /*
- * search next chunk
- * usually, next chunk ('M***') found within 40 bytes.
- */
- chunksize = 40;
- read(fd, tmp, chunksize);
-
- tmp[chunksize] = 'M'; /* stopper */
- while (*p != 'M')
- p++;
-
- chunksize -= (p - tmp);
- if (chunksize == 0)
- {
- DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk");
- return false;
- }
-
- /* search Score Track Stream PCM Data Chunk */
- lseek(fd, -chunksize, SEEK_CUR);
- if (search_chunk(fd, "Mtsp", 4) == 0)
- {
- DEBUGF("metadata error: missing Score Track Stream PCM Data Chunk\n");
- return false;
- }
-
- /*
- * parse Score Track Stream Wave Data Chunk
- * tmp
- * +4-7: chunk size (WaveType(3bytes) + wave data count)
- * +8: bit 7 0:mono/1:stereo, bit 4-6 format, bit 0-3: base bit
- * +9: frequency (MSB)
- * +10: frequency (LSB)
- */
- read(fd, tmp, 11);
- if (memcmp(tmp, "Mwa", 3) != 0)
- {
- DEBUGF("metadata error: missing Score Track Stream Wave Data Chunk\n");
- return false;
- }
-
- /* set track length and bitrate */
- id3->frequency = (tmp[9] << 8) | tmp[10];
- set_length(id3, tmp[8], tmp[8] & 0x0f, get_long_be(tmp + 4) - 3);
- return true;
-}
-
-bool get_smaf_metadata(int fd, struct mp3entry* id3)
-{
- /* temporary buffer */
- unsigned char *tmp = (unsigned char *)id3->path;
- unsigned int chunksize;
-
- id3->title = NULL;
- id3->artist = NULL;
- id3->composer = NULL;
-
- id3->vbr = false; /* All SMAF files are CBR */
- id3->filesize = filesize(fd);
-
- /* check File Chunk and Contents Info Chunk */
- lseek(fd, 0, SEEK_SET);
- read(fd, tmp, 16);
- if ((memcmp(tmp, "MMMD", 4) != 0) || (memcmp(tmp + 8, "CNTI", 4) != 0))
- {
- DEBUGF("metadata error: does not smaf format\n");
- return false;
- }
-
- chunksize = get_long_be(tmp + 12);
- if (chunksize > 5)
- return parse_smaf_audio_track(fd, id3, chunksize);
-
- return parse_smaf_score_track(fd, id3);
-}