rockbox/apps/metadata/tta.c
Yoshihisa Uchida 0f5c6d47d4 add True Audio (TTA) codec
decoding speed iPod video ~153%
But in some players, the decoding speed is not enough.
(e.g., H180 52.4% (thanks amiconn), H300 55.09% (thanks n1s))

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25994 a1c6a512-1295-4272-9138-f99709370657
2010-05-13 12:40:09 +00:00

123 lines
4.5 KiB
C

/***************************************************************************
* __________ __ ___.
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <inttypes.h>
#include "system.h"
#include "metadata.h"
#include "metadata_common.h"
#include "metadata_parsers.h"
#include "logf.h"
#define TTA1_SIGN 0x31415454
#define TTA_HEADER_ID 0
#define TTA_HEADER_AUDIO_FORMAT (TTA_HEADER_ID + sizeof(unsigned int))
#define TTA_HEADER_NUM_CHANNELS (TTA_HEADER_AUDIO_FORMAT + sizeof(unsigned short))
#define TTA_HEADER_BITS_PER_SAMPLE (TTA_HEADER_NUM_CHANNELS + sizeof(unsigned short))
#define TTA_HEADER_SAMPLE_RATE (TTA_HEADER_BITS_PER_SAMPLE + sizeof(unsigned short))
#define TTA_HEADER_DATA_LENGTH (TTA_HEADER_SAMPLE_RATE + sizeof(unsigned int))
#define TTA_HEADER_CRC32 (TTA_HEADER_DATA_LENGTH + sizeof(unsigned int))
#define TTA_HEADER_SIZE (TTA_HEADER_CRC32 + sizeof(unsigned int))
#define TTA_HEADER_GETTER_ID(x) get_long_le(x)
#define TTA_HEADER_GETTER_AUDIO_FORMAT(x) get_short_le(x)
#define TTA_HEADER_GETTER_NUM_CHANNELS(x) get_short_le(x)
#define TTA_HEADER_GETTER_BITS_PER_SAMPLE(x) get_short_le(x)
#define TTA_HEADER_GETTER_SAMPLE_RATE(x) get_long_le(x)
#define TTA_HEADER_GETTER_DATA_LENGTH(x) get_long_le(x)
#define TTA_HEADER_GETTER_CRC32(x) get_long_le(x)
#define GET_HEADER(x, tag) TTA_HEADER_GETTER_ ## tag((x) + TTA_HEADER_ ## tag)
static void read_id3_tags(int fd, struct mp3entry* id3)
{
id3->title = NULL;
id3->filesize = filesize(fd);
id3->id3v2len = getid3v2len(fd);
id3->tracknum = 0;
id3->discnum = 0;
id3->vbr = false; /* All TTA files are CBR */
/* first get id3v2 tags. if no id3v2 tags ware found, get id3v1 tags */
if (id3->id3v2len)
{
setid3v2title(fd, id3);
id3->first_frame_offset = id3->id3v2len;
return;
}
setid3v1title(fd, id3);
}
bool get_tta_metadata(int fd, struct mp3entry* id3)
{
unsigned char ttahdr[TTA_HEADER_SIZE];
unsigned int datasize;
unsigned int origsize;
int bps;
lseek(fd, 0, SEEK_SET);
/* read id3 tags */
read_id3_tags(fd, id3);
lseek(fd, id3->id3v2len, SEEK_SET);
/* read TTA header */
if (read(fd, ttahdr, TTA_HEADER_SIZE) < 0)
return false;
/* check for TTA3 signature */
if ((GET_HEADER(ttahdr, ID)) != TTA1_SIGN)
return false;
/* skip check CRC */
id3->channels = (GET_HEADER(ttahdr, NUM_CHANNELS));
id3->frequency = (GET_HEADER(ttahdr, SAMPLE_RATE));
id3->length = ((GET_HEADER(ttahdr, DATA_LENGTH)) / id3->frequency) * 1000LL;
bps = (GET_HEADER(ttahdr, BITS_PER_SAMPLE));
datasize = id3->filesize - id3->first_frame_offset;
origsize = (GET_HEADER(ttahdr, DATA_LENGTH)) * ((bps + 7) / 8) * id3->channels;
id3->bitrate = (int) ((uint64_t) datasize * id3->frequency * id3->channels * bps
/ (origsize * 1000LL));
/* output header info (for debug) */
DEBUGF("TTA header info ----\n");
DEBUGF("id: %x\n", (unsigned int)(GET_HEADER(ttahdr, ID)));
DEBUGF("channels: %d\n", id3->channels);
DEBUGF("frequency: %ld\n", id3->frequency);
DEBUGF("length: %ld\n", id3->length);
DEBUGF("bitrate: %d\n", id3->bitrate);
DEBUGF("bits per sample: %d\n", bps);
DEBUGF("compressed size: %d\n", datasize);
DEBUGF("original size: %d\n", origsize);
DEBUGF("id3----\n");
DEBUGF("artist: %s\n", id3->artist);
DEBUGF("title: %s\n", id3->title);
DEBUGF("genre: %s\n", id3->genre_string);
return true;
}