From f40bfc9267b13b54e6379dfe7539447662879d24 Mon Sep 17 00:00:00 2001 From: Sean Bartell Date: Sat, 25 Jun 2011 21:32:25 -0400 Subject: Add codecs to librbcodec. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id7f4717d51ed02d67cb9f9cb3c0ada4a81843f97 Reviewed-on: http://gerrit.rockbox.org/137 Reviewed-by: Nils Wallménius Tested-by: Nils Wallménius --- lib/rbcodec/codecs/libtta/README | 72 ++++ lib/rbcodec/codecs/libtta/README.rockbox | 33 ++ lib/rbcodec/codecs/libtta/SOURCES | 7 + lib/rbcodec/codecs/libtta/filter.h | 136 +++++++ lib/rbcodec/codecs/libtta/filter_arm.S | 198 ++++++++++ lib/rbcodec/codecs/libtta/filter_coldfire.S | 164 ++++++++ lib/rbcodec/codecs/libtta/libtta.make | 18 + lib/rbcodec/codecs/libtta/ttadec.c | 582 ++++++++++++++++++++++++++++ lib/rbcodec/codecs/libtta/ttadec.h | 203 ++++++++++ lib/rbcodec/codecs/libtta/ttalib.h | 157 ++++++++ 10 files changed, 1570 insertions(+) create mode 100644 lib/rbcodec/codecs/libtta/README create mode 100644 lib/rbcodec/codecs/libtta/README.rockbox create mode 100644 lib/rbcodec/codecs/libtta/SOURCES create mode 100644 lib/rbcodec/codecs/libtta/filter.h create mode 100644 lib/rbcodec/codecs/libtta/filter_arm.S create mode 100644 lib/rbcodec/codecs/libtta/filter_coldfire.S create mode 100644 lib/rbcodec/codecs/libtta/libtta.make create mode 100644 lib/rbcodec/codecs/libtta/ttadec.c create mode 100644 lib/rbcodec/codecs/libtta/ttadec.h create mode 100644 lib/rbcodec/codecs/libtta/ttalib.h (limited to 'lib/rbcodec/codecs/libtta') diff --git a/lib/rbcodec/codecs/libtta/README b/lib/rbcodec/codecs/libtta/README new file mode 100644 index 0000000000..8b1a1b23c0 --- /dev/null +++ b/lib/rbcodec/codecs/libtta/README @@ -0,0 +1,72 @@ +TTA Hardware Players Library +============================ + +Version 1.2, (c) 2004 Alexander Djourik. All rights reserved. + +* Introduction + +This library provides to decode a multichannel 8,16 and 24 +bits TTA audio files. TTA is a lossless audio format. Being +"lossless" means that no data/quality is lost in the compression +- when uncompressed, the data will be identical to the original. +The compression ratios of TTA depend on the type of music file +being compressed, but the compression size will generally range +between 30% - 70% of the original. + +TTA format supports both of ID3v1/v2 tags. Detailed format +description is available at http://www.true-audio.com. + +The decoder process has a minimal system requirements and does +not required to create a big additional memory pools. As the +TTA algorithms has a same system requirements both for decoding +and for encoding processes - the TTA recorder can be easily +realized also. + +* Changes + + 14/04/2004 1.0 Initial release + 16/04/2004 1.1 Code optimization + Code clean-up + 29/10/2004 1.2 ID3 tags support + Code clean-up + +* To Do + + - TTA recorder functions. + +* Developers + + Alexander Djourik + Pavel Zhilin + +* Copying + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the True Audio Software nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +* See also + +Please visit the TTA homepage at http://tta.sourceforge.net for the +latest in news and downloads. diff --git a/lib/rbcodec/codecs/libtta/README.rockbox b/lib/rbcodec/codecs/libtta/README.rockbox new file mode 100644 index 0000000000..549aa4e097 --- /dev/null +++ b/lib/rbcodec/codecs/libtta/README.rockbox @@ -0,0 +1,33 @@ +Library: True Audio +Imported by : Yoshihisa Uchida +Import date : 2010-03-05 +Baseed by : TTA library version 1.2 for hardware players (ttalib-hwplayer-1.2.tgz) + from http://true-audio.com/Free_Downloads + +This directory contains a decoder version of True Auido. + +LICENSING INFORMATION + +True Audio license is described in the README file or each source file in this directory. + +Limitation + + - Decoding is not real time on some targets. + - Max duration is 4095 seconds (about 1 hours 8 minutes). + +IMPORT DETAILS + +The .[ch] files from ttalib-hwplayer-1.2.tgz were imported into Rockbox. +But the following files do not include. + Makefile + tta.vcproj + samples/* + + +When source files import in Rockbox, I changed below. + +all files + - TAB => 4 spaces. + - // style comments changes to /* */ style. + +Moreover, I modify to optimize the decoding speed. diff --git a/lib/rbcodec/codecs/libtta/SOURCES b/lib/rbcodec/codecs/libtta/SOURCES new file mode 100644 index 0000000000..0a8f1171eb --- /dev/null +++ b/lib/rbcodec/codecs/libtta/SOURCES @@ -0,0 +1,7 @@ +ttadec.c +#ifdef CPU_ARM +filter_arm.S +#endif +#ifdef CPU_COLDFIRE +filter_coldfire.S +#endif diff --git a/lib/rbcodec/codecs/libtta/filter.h b/lib/rbcodec/codecs/libtta/filter.h new file mode 100644 index 0000000000..228757b9a0 --- /dev/null +++ b/lib/rbcodec/codecs/libtta/filter.h @@ -0,0 +1,136 @@ +/* + * filter.h + * + * Description: TTAv1 filter functions + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 2004 True Audio Software. All rights reserved. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the True Audio Software nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FILTER_H +#define FILTER_H + +///////// Filter Settings ////////// +static int flt_set[3] = {10, 9, 10}; + +#if defined(CPU_ARM) || defined(CPU_COLDFIRE) +int hybrid_filter(fltst *fs, int *in); /* implements in filter_arm.S */ + +#else + +static inline void +memshl (register int *pA) { + register int *pB = pA + 16; + + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA++ = *pB++; + *pA = *pB; +} + +static inline void +hybrid_filter (fltst *fs, int *in) { + register int *pA = fs->dl + fs->index; + register int *pB = fs->qm; + register int *pM = fs->dx + fs->index; + register int sum = fs->round; + + if (!fs->error) { + sum += *pA++ * *pB++; + sum += *pA++ * *pB++; + sum += *pA++ * *pB++; + sum += *pA++ * *pB++; + sum += *pA++ * *pB++; + sum += *pA++ * *pB++; + sum += *pA++ * *pB++; + sum += *pA * *pB; + pM += 8; + } else if (fs->error < 0) { + sum += *pA++ * (*pB++ -= *pM++); + sum += *pA++ * (*pB++ -= *pM++); + sum += *pA++ * (*pB++ -= *pM++); + sum += *pA++ * (*pB++ -= *pM++); + sum += *pA++ * (*pB++ -= *pM++); + sum += *pA++ * (*pB++ -= *pM++); + sum += *pA++ * (*pB++ -= *pM++); + sum += *pA * (*pB -= *pM++); + } else { + sum += *pA++ * (*pB++ += *pM++); + sum += *pA++ * (*pB++ += *pM++); + sum += *pA++ * (*pB++ += *pM++); + sum += *pA++ * (*pB++ += *pM++); + sum += *pA++ * (*pB++ += *pM++); + sum += *pA++ * (*pB++ += *pM++); + sum += *pA++ * (*pB++ += *pM++); + sum += *pA * (*pB += *pM++); + } + + pB = pA++; + fs->error = *in; + *in += (sum >> fs->shift); + *pA = *in; + + *pM-- = ((*pB-- >> 30) | 1) << 2; + *pM-- = ((*pB-- >> 30) | 1) << 1; + *pM-- = ((*pB-- >> 30) | 1) << 1; + *pM = ((*pB >> 30) | 1); + + *(pA-1) = *(pA-0) - *(pA-1); + *(pA-2) = *(pA-1) - *(pA-2); + *(pA-3) = *(pA-2) - *(pA-3); + + /* + * Rockbox speciffic + * in order to make speed up, memshl() is executed at the rate once every 16 times. + */ + if (++fs->index == 16) + { + memshl (fs->dl); + memshl (fs->dx); + fs->index = 0; + } +} +#endif + +static inline void +filter_init (fltst *fs, int shift) { + ci->memset (fs, 0, sizeof(fltst)); + fs->shift = shift; + fs->round = 1 << (shift - 1); + fs->index = 0; +} + +#endif /* FILTER_H */ diff --git a/lib/rbcodec/codecs/libtta/filter_arm.S b/lib/rbcodec/codecs/libtta/filter_arm.S new file mode 100644 index 0000000000..f3959b83ca --- /dev/null +++ b/lib/rbcodec/codecs/libtta/filter_arm.S @@ -0,0 +1,198 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "config.h" + +/* + * The following are assembler optimised version of + * void hybrid_filter(fltst *fs, int *in) + */ + +#ifdef USE_IRAM + .section .icode, "ax", %progbits +#else + .text +#endif + .align + .global hybrid_filter + .type hybrid_filter, %function + +hybrid_filter: + @ input: r0 = fs, r1 = in + stmdb sp!, {r4 - r12, lr} + + @ get fs members + @ r2 pA := fs->dl + fs->index + @ r3 pM := fs->dx + fs->index + @ r4 pB := fs->qm + @ r5 fs->index + @ r6 fs->error + @ lr sum := fs->round + + ldmia r0, {r5, r6, lr} @ r5 = fs->index + @ r6 = fs->error + @ lr = fs->round + add r2, r0, #148 @ r2 = fs->dl + add r3, r0, #52 @ r3 = fs->dx + add r4, r0, #20 @ r4 = fs->qm + add r2, r2, r5 @ r2 = (unsigned char*)fs->dl + fs->index + add r3, r3, r5 @ r3 = (unsigned char*)fs->dx + fs->index + + cmp r6, #0 + bmi .hf_negative + bne .hf_positive + + @ case fs->error == 0 + + add r3, r3, #32 + ldmia r4!, {r5, r6, r7, r8 } + ldmia r2!, {r9, r10, r11, r12} + mla lr, r5, r9, lr + mla lr, r6, r10, lr + mla lr, r7, r11, lr + mla lr, r8, r12, lr + ldmia r4!, {r5, r6, r7, r8 } + b .hf2 + +.hf_negative: + @ case fs->error < 0 + + ldmia r4, {r5, r6, r7, r8 } + ldmia r3!, {r9, r10, r11, r12} + sub r5, r5, r9 + sub r6, r6, r10 + sub r7, r7, r11 + sub r8, r8, r12 + stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[0], ..., fs->qm[3] + ldmia r2!, {r9, r10, r11, r12} + mla lr, r5, r9, lr + mla lr, r6, r10, lr + mla lr, r7, r11, lr + mla lr, r8, r12, lr + ldmia r4, {r5, r6, r7, r8 } + ldmia r3!, {r9, r10, r11, r12} + sub r5, r5, r9 + sub r6, r6, r10 + sub r7, r7, r11 + sub r8, r8, r12 + stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[4], ..., fs->qm[7] + b .hf2 + +.hf_positive: + @ case fs->error > 0 + + ldmia r4, {r5, r6, r7, r8 } + ldmia r3!, {r9, r10, r11, r12} + add r5, r5, r9 + add r6, r6, r10 + add r7, r7, r11 + add r8, r8, r12 + stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[0], ..., fs->qm[3] + ldmia r2!, {r9, r10, r11, r12} + mla lr, r5, r9, lr + mla lr, r6, r10, lr + mla lr, r7, r11, lr + mla lr, r8, r12, lr + ldmia r4, {r5, r6, r7, r8 } + ldmia r3!, {r9, r10, r11, r12} + add r5, r5, r9 + add r6, r6, r10 + add r7, r7, r11 + add r8, r8, r12 + stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[4], ..., fs->qm[7] + +.hf2: + ldmia r2!, {r9, r10, r11, r12} + mla lr, r5, r9, lr + mla lr, r6, r10, lr + mla lr, r7, r11, lr + mla lr, r8, r12, lr + + @ fs->error = *in; + @ *in += (sum >> fs->shift) + @ *pA = *in + + ldr r5, [r1] @ r5 = *in + ldr r6, [r0, #12] @ r6 = fs->shift + add lr, r5, lr, asr r6 + str lr, [r1] @ *in += (sum >> fs->shift) + + @ update fs->index + + ldr r1, [r0] @ r1 = fs->index + add r1, r1, #4 + ands r1, r1, #63 @ set Z flag (after this, CPSR must keep !!) + stmia r0, {r1, r5} @ fs->index = (fs->index + 4) & 63 + @ fs->error = (original) *in + + @ change *pM, *(pM-1), *(pM-2), *(pM-3) + @ r9 = *(pA-4), r5 = *(pM-3) + @ r10 = *(pA-3), r6 = *(pM-2) + @ r11 = *(pA-2), r7 = *(pM-1) + @ r12 = *(pA-1), r8 = *(pM-0) + @ lr = *(pA-0) + + mov r4, #1 + orr r5, r4, r9, asr #30 + orr r6, r4, r10, asr #30 + orr r7, r4, r11, asr #30 + orr r8, r4, r12, asr #30 + mov r6, r6, lsl #1 + mov r7, r7, lsl #1 + mov r8, r8, lsl #2 + + @ change *(pA-1), *(pA-2), *(pA-3) + sub r12, lr, r12 + sub r11, r12, r11 + sub r10, r11, r10 + + @ set to the memory: *pA, *(pA-1), *(pA-2), *(pA-3), *pM, *(pM-1), *(pM-2), *(pM-3) + stmneda r2, {r10, r11, r12, lr} + stmneda r3, {r5, r6, r7, r8} + ldmpc cond=ne regs=r4-r12 @ hybrid_filter end (when fs->index != 0) + +.hf_memshl: + @ memshl (fs->dl) + @ r9 = fs->dl[16 + 3] + @ r10 = fs->dl[16 + 4] + @ r11 = fs->dl[16 + 5] + @ r12 = fs->dl[16 + 6] + @ lr = fs->dl[16 + 7] + + add r2, r0, #212 @ r2 = fs->dl + 16 + ldmia r2, {r1, r3, r4} + sub r2, r2, #64 @ r2 = fs->dl + stmia r2, {r1, r3, r4, r9 - r12, lr} + + @ memshl (fs->dx) + @ r5 = fs->dx[16 + 4] + @ r6 = fs->dx[16 + 5] + @ r7 = fs->dx[16 + 6] + @ r8 = fs->dx[16 + 7] + + add r9, r0, #116 @ r9 = fs->dx + 16 + ldmia r9, {r1, r2, r3, r4} + sub r9, r9, #64 @ r9 = fs->dx + stmia r9, {r1 - r8} + ldmpc regs=r4-r12 @ hybrid_filter end (when fs->index == 0) + +hybrid_filter_end: + .size hybrid_filter, hybrid_filter_end - hybrid_filter diff --git a/lib/rbcodec/codecs/libtta/filter_coldfire.S b/lib/rbcodec/codecs/libtta/filter_coldfire.S new file mode 100644 index 0000000000..3950eb52e6 --- /dev/null +++ b/lib/rbcodec/codecs/libtta/filter_coldfire.S @@ -0,0 +1,164 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Nils Wallménius + * + * 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 "config.h" + +/* + * The following is an assembler optimised version of + * void hybrid_filter(fltst *fs, int *in) + */ + +#if defined(USE_IRAM) + .section .icode +#else + .text +#endif + .align 2 + .global hybrid_filter + .type hybrid_filter, @function + +hybrid_filter: + lea.l (-8*4, %sp), %sp + movem.l %d2-%d7/%a2-%a3, (%sp) | save some registers + move.l (8*4+4, %sp), %a0 | a0 = fs + movem.l (%a0), %d4-%d5 | d4 = fs->index, d5 = fs->error + + lea.l (%a0, %d4.l*4), %a2 + lea.l (148, %a2), %a1 | a1 = fs->dl + fs->index (*pA) + lea.l (52, %a2), %a2 | a2 = fs->dx + fs->index (*pM) + + move.l (%a1)+, %a3 | load one value from *pA (needed in every case) + movem.l (20, %a0), %d0-%d3 | load 4 values from *pB + + tst.l %d5 + blt .hf_negative + bgt .hf_positive + + | fs->error == 0 + mac.l %d0, %a3, (%a1)+, %a3, %acc0 + mac.l %d1, %a3, (%a1)+, %a3, %acc0 + mac.l %d2, %a3, (%a1)+, %a3, %acc0 + mac.l %d3, %a3, (%a1)+, %d4, %acc0 + movem.l (4*4+20, %a0), %d0-%d3 | load 4 values from *pB + bra 0f + + .hf_negative: | fs->error < 0 + movem.l (%a2), %d4-%d7 | load 4 values from *pM + sub.l %d4, %d0 + sub.l %d5, %d1 + sub.l %d6, %d2 + sub.l %d7, %d3 + movem.l %d0-%d3, (20, %a0) + mac.l %d0, %a3, (%a1)+, %a3, %acc0 + mac.l %d1, %a3, (%a1)+, %a3, %acc0 + mac.l %d2, %a3, (%a1)+, %a3, %acc0 + mac.l %d3, %a3, (%a1)+, %d4, %acc0 + + movem.l (4*4+20, %a0), %d0-%d3 | load 4 values from *pB + movem.l (4*4, %a2), %d5-%d7/%a3 | load 4 values from *pM + sub.l %d5, %d0 + sub.l %d6, %d1 + sub.l %d7, %d2 + sub.l %a3, %d3 + movem.l %d0-%d3, (4*4+20, %a0) + bra 0f + + .hf_positive: | fs->error > 0 + movem.l (%a2), %d4-%d7 | load 4 values from *pM + add.l %d4, %d0 + add.l %d5, %d1 + add.l %d6, %d2 + add.l %d7, %d3 + movem.l %d0-%d3, (20, %a0) + mac.l %d0, %a3, (%a1)+, %a3, %acc0 + mac.l %d1, %a3, (%a1)+, %a3, %acc0 + mac.l %d2, %a3, (%a1)+, %a3, %acc0 + mac.l %d3, %a3, (%a1)+, %d4, %acc0 + + movem.l (4*4+20, %a0), %d0-%d3 | load 4 values from *pB + movem.l (4*4, %a2), %d5-%d7/%a3 | load 4 values from *pM + add.l %d5, %d0 + add.l %d6, %d1 + add.l %d7, %d2 + add.l %a3, %d3 + movem.l %d0-%d3, (4*4+20, %a0) + + 0: + + mac.l %d0, %d4, (%a1)+, %d5, %acc0 | common macro block + mac.l %d1, %d5, (%a1)+, %d6, %acc0 + mac.l %d2, %d6, (%a1), %d7, %acc0 + mac.l %d3, %d7, %acc0 + + move.l (8*4+8, %sp), %a3 | a3 = in + move.l (%a3), %d3 + move.l %d3, (4, %a0) | fs->error = *in + movclr.l %acc0, %d0 | d0 = sum + movem.l (8, %a0), %d1-%d2 + add.l %d1, %d0 | sum += fs->round + asr.l %d2, %d0 | sum >>= fs->shift + + add.l %d0, %d3 + move.l %d3, (%a3) | *in += (sum >> fs->shift) + + move.l %d3, ( 1*4, %a1) + sub.l %d7, %d3 + move.l %d3, ( 0*4, %a1) + sub.l %d6, %d3 + move.l %d3, (-1*4, %a1) + sub.l %d5, %d3 + move.l %d3, (-2*4, %a1) + + moveq #30,%d0 + asr.l %d0,%d7 + asr.l %d0,%d6 + asr.l %d0,%d5 + asr.l %d0,%d4 + + moveq #1,%d0 + or.l %d0,%d7 + or.l %d0,%d6 + or.l %d0,%d5 + or.l %d0,%d4 + + lsl.l #2,%d7 + lsl.l #1,%d6 + lsl.l #1,%d5 + movem.l %d4-%d7, (8*4-3*4,%a2) | store to *pM + + move.l (%a0), %d0 + addq.l #1, %d0 + cmp.l #16, %d0 | ++fs->index == 16 ? + bne 1f + + movem.l (16*4+148, %a0), %d0-%d7 + movem.l %d0-%d7, (148, %a0) + movem.l (16*4+52, %a0), %d0-%d7 + movem.l %d0-%d7, (52, %a0) + clr.l %d0 | fs->index = 0 + 1: + + move.l %d0, (%a0) + + movem.l (%sp), %d2-%d7/%a2-%a3 | restore stacked regs + lea.l (8*4, %sp), %sp + rts + diff --git a/lib/rbcodec/codecs/libtta/libtta.make b/lib/rbcodec/codecs/libtta/libtta.make new file mode 100644 index 0000000000..3fe3db1989 --- /dev/null +++ b/lib/rbcodec/codecs/libtta/libtta.make @@ -0,0 +1,18 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +# libtta +TTALIB := $(CODECDIR)/libtta.a +TTALIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/libtta/SOURCES) +TTALIB_OBJ := $(call c2obj, $(TTALIB_SRC)) +OTHER_SRC += $(TTALIB_SRC) + +$(TTALIB): $(TTALIB_OBJ) + $(SILENT)$(shell rm -f $@) + $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null diff --git a/lib/rbcodec/codecs/libtta/ttadec.c b/lib/rbcodec/codecs/libtta/ttadec.c new file mode 100644 index 0000000000..06ca431084 --- /dev/null +++ b/lib/rbcodec/codecs/libtta/ttadec.c @@ -0,0 +1,582 @@ +/* + * ttadec.c + * + * Description: TTAv1 decoder library for HW players + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 2004 True Audio Software. All rights reserved. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the True Audio Software nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "codeclib.h" + +#include "ttalib.h" +#include "ttadec.h" +#include "filter.h" + +/******************* static variables and structures *******************/ + +static unsigned char isobuffers[ISO_BUFFERS_SIZE + 4] IBSS_ATTR; +static unsigned char * const iso_buffers_end ICONST_ATTR = isobuffers + ISO_BUFFERS_SIZE; +static unsigned int pcm_buffer_size IBSS_ATTR; + +static decoder tta[MAX_NCH] IBSS_ATTR; /* decoder state */ +/* Rockbox speciffic: cache is defined in get_samples() (non static value) */ +/* static int cache[MAX_NCH]; // decoder cache */ + +static tta_info *ttainfo IBSS_ATTR; /* currently playing file info */ + +static unsigned int fframes IBSS_ATTR; /* number of frames in file */ +static unsigned int framelen IBSS_ATTR; /* the frame length in samples */ +static unsigned int lastlen IBSS_ATTR; /* the length of the last frame in samples */ +static unsigned int data_pos IBSS_ATTR; /* currently playing frame index */ +static unsigned int data_cur IBSS_ATTR; /* the playing position in frame */ + +static int maxvalue IBSS_ATTR; /* output data max value */ + +/* Rockbox speciffic: seek_table is static size */ +static unsigned int seek_table[MAX_SEEK_TABLE_SIZE]; /* the playing position table */ +static unsigned int st_state; /* seek table status */ + +static unsigned int frame_crc32 IBSS_ATTR; +static unsigned int bit_count IBSS_ATTR; +static unsigned int bit_cache IBSS_ATTR; +static unsigned char *bitpos IBSS_ATTR; + +/* Rockbox speciffic: deletes read_id3_tags(). */ +/* static int read_id3_tags (tta_info *info); */ + +/********************* rockbox helper functions *************************/ + +/* emulate stdio functions */ +static size_t tta_fread(void *ptr, size_t size, size_t nobj) +{ + size_t read_size; + unsigned char *buffer = ci->request_buffer(&read_size, size * nobj); + + if (read_size > 0) + { + ci->memcpy(ptr, buffer, read_size); + ci->advance_buffer(read_size); + } + return read_size; +} + +static int tta_fseek(long offset, int origin) +{ + switch (origin) + { + case SEEK_CUR: + ci->advance_buffer(offset); + break; + case SEEK_SET: + ci->seek_buffer(offset); + break; + case SEEK_END: + ci->seek_buffer(offset + ci->id3->filesize); + break; + default: + return -1; + } + return 0; +} + +/************************* crc32 functions *****************************/ + +#define UPDATE_CRC32(x, crc) crc = \ + (((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc^x) & 0xFF]) + +static unsigned int +crc32 (unsigned char *buffer, unsigned int len) { + unsigned int i; + unsigned int crc = 0xFFFFFFFF; + + for (i = 0; i < len; i++) UPDATE_CRC32(buffer[i], crc); + + return (crc ^ 0xFFFFFFFF); +} + +/************************* bit operations ******************************/ + +#define GET_BINARY(value, bits) \ + while (bit_count < bits) { \ + if (bitpos == iso_buffers_end) { \ + if (!tta_fread(isobuffers, 1, ISO_BUFFERS_SIZE)) { \ + ttainfo->STATE = READ_ERROR; \ + return -1; \ + } \ + bitpos = isobuffers; \ + } \ + UPDATE_CRC32(*bitpos, frame_crc32); \ + bit_cache |= *bitpos << bit_count; \ + bit_count += 8; \ + bitpos++; \ + } \ + value = bit_cache & bit_mask[bits]; \ + bit_cache >>= bits; \ + bit_count -= bits; \ + bit_cache &= bit_mask[bit_count]; + +#define GET_UNARY(value) \ + value = 0; \ + while (!(bit_cache ^ bit_mask[bit_count])) { \ + if (bitpos == iso_buffers_end) { \ + if (!tta_fread(isobuffers, 1, ISO_BUFFERS_SIZE)) { \ + ttainfo->STATE = READ_ERROR; \ + return -1; \ + } \ + bitpos = isobuffers; \ + } \ + value += bit_count; \ + bit_cache = *bitpos++; \ + UPDATE_CRC32(bit_cache, frame_crc32); \ + bit_count = 8; \ + } \ + while (bit_cache & 1) { \ + value++; \ + bit_cache >>= 1; \ + bit_count--; \ + } \ + bit_cache >>= 1; \ + bit_count--; + +/************************* rice operations ******************************/ + +static inline int update_rice(int value, adapt *rice, int depth, + const unsigned int *shift_table) +{ + if (depth > 0) + { + rice->sum1 += value - (rice->sum1 >> 4); + if (rice->k1 > 0 && rice->sum1 < shift_table[rice->k1]) + rice->k1--; + else if (rice->sum1 > shift_table[rice->k1 + 1]) + rice->k1++; + value += *(shift_table + rice->k0 - 4); + } + rice->sum0 += value - (rice->sum0 >> 4); + if (rice->k0 > 0 && rice->sum0 < shift_table[rice->k0]) + rice->k0--; + else if (rice->sum0 > shift_table[rice->k0 + 1]) + rice->k0++; + + return DEC(value); +} + +/************************* buffer functions ******************************/ + +static void init_buffer_read(void) { + frame_crc32 = 0xFFFFFFFFUL; + bit_count = bit_cache = 0; + bitpos = iso_buffers_end; +} + +static int done_buffer_read(void) { + unsigned int crc32, rbytes; + + frame_crc32 ^= 0xFFFFFFFFUL; + rbytes = iso_buffers_end - bitpos; + + if (rbytes < sizeof(int)) { + ci->memcpy(isobuffers, bitpos, 4); + if (!tta_fread(isobuffers + rbytes, 1, ISO_BUFFERS_SIZE - rbytes)) + return -1; + bitpos = isobuffers; + } + + ci->memcpy(&crc32, bitpos, 4); + crc32 = ENDSWAP_INT32(crc32); + bitpos += sizeof(int); + + if (crc32 != frame_crc32) return -1; + + bit_cache = bit_count = 0; + frame_crc32 = 0xFFFFFFFFUL; + + return 0; +} + +/************************* decoder functions ****************************/ + +/* rockbox: not used +const char *get_error_str (int error) { + switch (error) { + case NO_ERROR: return "No errors found"; + case OPEN_ERROR: return "Can't open file"; + case FORMAT_ERROR: return "Not supported file format"; + case FILE_ERROR: return "File is corrupted"; + case READ_ERROR: return "Can't read from file"; + case MEMORY_ERROR: return "Insufficient memory available"; + default: return "Unknown error code"; + } +} */ + +int set_tta_info (tta_info *info) +{ + unsigned int checksum; + unsigned int datasize; + unsigned int origsize; + tta_hdr ttahdr; + + /* clear the memory */ + ci->memset (info, 0, sizeof(tta_info)); + + /* skip id3v2 tags */ + tta_fseek(ci->id3->id3v2len, SEEK_SET); + + /* read TTA header */ + if (tta_fread (&ttahdr, 1, sizeof (ttahdr)) == 0) { + info->STATE = READ_ERROR; + return -1; + } + + /* check for TTA3 signature */ + if (ENDSWAP_INT32(ttahdr.TTAid) != TTA1_SIGN) { + DEBUGF("ID error: %x\n", ENDSWAP_INT32(ttahdr.TTAid)); + info->STATE = FORMAT_ERROR; + return -1; + } + + ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32); + checksum = crc32((unsigned char *) &ttahdr, + sizeof(tta_hdr) - sizeof(int)); + if (checksum != ttahdr.CRC32) { + DEBUGF("CRC error: %x != %x\n", ttahdr.CRC32, checksum); + info->STATE = FILE_ERROR; + return -1; + } + + ttahdr.AudioFormat = ENDSWAP_INT16(ttahdr.AudioFormat); + ttahdr.NumChannels = ENDSWAP_INT16(ttahdr.NumChannels); + ttahdr.BitsPerSample = ENDSWAP_INT16(ttahdr.BitsPerSample); + ttahdr.SampleRate = ENDSWAP_INT32(ttahdr.SampleRate); + ttahdr.DataLength = ENDSWAP_INT32(ttahdr.DataLength); + + /* check for player supported formats */ + if (ttahdr.AudioFormat != WAVE_FORMAT_PCM || + ttahdr.NumChannels > MAX_NCH || + ttahdr.BitsPerSample > MAX_BPS ||( + ttahdr.SampleRate != 16000 && + ttahdr.SampleRate != 22050 && + ttahdr.SampleRate != 24000 && + ttahdr.SampleRate != 32000 && + ttahdr.SampleRate != 44100 && + ttahdr.SampleRate != 48000 && + ttahdr.SampleRate != 64000 && + ttahdr.SampleRate != 88200 && + ttahdr.SampleRate != 96000)) { + info->STATE = FORMAT_ERROR; + DEBUGF("illegal audio format: %d channels: %d samplerate: %d\n", + ttahdr.AudioFormat, ttahdr.NumChannels, ttahdr.SampleRate); + return -1; + } + + /* fill the File Info */ + info->NCH = ttahdr.NumChannels; + info->BPS = ttahdr.BitsPerSample; + info->BSIZE = (ttahdr.BitsPerSample + 7)/8; + info->FORMAT = ttahdr.AudioFormat; + info->SAMPLERATE = ttahdr.SampleRate; + info->DATALENGTH = ttahdr.DataLength; + info->FRAMELEN = (int) MULTIPLY_FRAME_TIME(ttahdr.SampleRate); + info->LENGTH = ttahdr.DataLength / ttahdr.SampleRate; + info->DATAPOS = ci->id3->id3v2len; + info->FILESIZE = ci->id3->filesize; + + datasize = info->FILESIZE - info->DATAPOS; + origsize = info->DATALENGTH * info->BSIZE * info->NCH; + + /* info->COMPRESS = (double) datasize / origsize; */ + info->BITRATE = (int) ((uint64_t) datasize * info->SAMPLERATE * info->NCH * info->BPS + / (origsize * 1000LL)); + + return 0; +} + +static void rice_init(adapt *rice, unsigned int k0, unsigned int k1) { + rice->k0 = k0; + rice->k1 = k1; + rice->sum0 = shift_16[k0]; + rice->sum1 = shift_16[k1]; +} + +static void decoder_init(decoder *tta, int nch, int byte_size) { + int shift = flt_set[byte_size - 1]; + int i; + + for (i = 0; i < nch; i++) { + filter_init(&tta[i].fst, shift); + rice_init(&tta[i].rice, 10, 10); + tta[i].last = 0; + } +} + +static void seek_table_init (unsigned int *seek_table, + unsigned int len, unsigned int data_offset) { + unsigned int *st, frame_len; + + for (st = seek_table; st < (seek_table + len); st++) { + frame_len = ENDSWAP_INT32(*st); + *st = data_offset; + data_offset += frame_len; + } +} + +int set_position (unsigned int pos, enum tta_seek_type type) +{ + unsigned int i; + unsigned int seek_pos; + + if (type == TTA_SEEK_TIME) + { + if (pos >= fframes) + pos = fframes -1; + } + else + { + pos -= ttainfo->DATAPOS; + for (i = 1; i < fframes; i++) + { + if (seek_table[i] > pos) + break; + } + pos = i - 1; + } + if (!st_state) { + ttainfo->STATE = FILE_ERROR; + return -1; + } + seek_pos = ttainfo->DATAPOS + seek_table[data_pos = pos]; + if (tta_fseek(seek_pos, SEEK_SET) < 0) { + ttainfo->STATE = READ_ERROR; + return -1; + } + + data_cur = 0; + framelen = 0; + + /* init bit reader */ + init_buffer_read(); + return data_pos * ttainfo->FRAMELEN; +} + +int player_init (tta_info *info) { + unsigned int checksum; + unsigned int data_offset; + unsigned int st_size; + +#ifdef CPU_COLDFIRE + coldfire_set_macsr(0); /* signed integer mode */ +#endif + + ttainfo = info; + + framelen = 0; + data_pos = 0; + data_cur = 0; + + lastlen = ttainfo->DATALENGTH % ttainfo->FRAMELEN; + fframes = ttainfo->DATALENGTH / ttainfo->FRAMELEN + (lastlen ? 1 : 0); + st_size = (fframes + 1) * sizeof(int); + + /* + * Rockbox speciffic + * playable tta file is to MAX_SEEK_TABLE_SIZE frames + * about 1:08:15 (frequency 44.1 kHz) + */ + if (fframes > MAX_SEEK_TABLE_SIZE) + { + LOGF("frame is too many: %d > %d", fframes, MAX_SEEK_TABLE_SIZE); + return -1; + } + + /* read seek table */ + if (!tta_fread(seek_table, st_size, 1)) { + ttainfo->STATE = READ_ERROR; + return -1; + } + + checksum = crc32((unsigned char *) seek_table, st_size - sizeof(int)); + st_state = (checksum == ENDSWAP_INT32(seek_table[fframes])); + data_offset = sizeof(tta_hdr) + st_size; + + /* init seek table */ + seek_table_init(seek_table, fframes, data_offset); + + /* init bit reader */ + init_buffer_read(); + + /* + * Rockbox speciffic + * because pcm data is int32_t, does not multiply ttainfo->BSIZE. + */ + pcm_buffer_size = PCM_BUFFER_LENGTH * ttainfo->NCH; + maxvalue = (1UL << ttainfo->BPS) - 1; + + return 0; +} + +/* + * Rockbox specffic + * because the seek table is static size buffer, player_stop() is nooperation function. + */ +void player_stop (void) { +/* + if (seek_table) { + free(seek_table); + seek_table = NULL; + } +*/ +} + +/* + * Rockbox speciffic + * with the optimization, the decoding logic is modify a little. + */ +int get_samples (int32_t *buffer) { + unsigned int k, depth, unary, binary; + int32_t *p = buffer; + decoder *dec = tta; + int value, res; + int cur_pos = pcm_buffer_size; + int pcm_shift_bits = TTA_OUTPUT_DEPTH - ttainfo->BPS; + int pr_bits = (ttainfo->BSIZE == 1)? 4 : 5; + int cache = 0; /* decoder cache */ + + fltst *fst; + adapt *rice; + + for (res = 0; --cur_pos >= 0;) { + fst = &dec->fst; + rice = &dec->rice; + + if (data_cur == framelen) { + if (data_pos == fframes) break; + if (framelen && done_buffer_read()) { + if (set_position(data_pos, TTA_SEEK_TIME) < 0) return -1; + if (res) break; + } + + if (data_pos == fframes - 1 && lastlen) + framelen = lastlen; + else framelen = ttainfo->FRAMELEN; + + decoder_init(tta, ttainfo->NCH, ttainfo->BSIZE); + data_pos++; data_cur = 0; + } + + /* decode Rice unsigned */ + GET_UNARY(unary); + + switch (unary) { + case 0: depth = 0; k = rice->k0; break; + default: + depth = 1; k = rice->k1; + unary--; + } + + if (k) { + GET_BINARY(binary, k); + value = (unary << k) + binary; + } else value = unary; + + value = update_rice(value, rice, depth, shift_16); + + /* Rockbox specific: the following logic move to update_rice() */ +#if 0 + if (depth > 0) + { + rice->sum1 += value - (rice->sum1 >> 4); + if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1]) + rice->k1--; + else if (rice->sum1 > shift_16[rice->k1 + 1]) + rice->k1++; + value += bit_shift[rice->k0]; + } + rice->sum0 += value - (rice->sum0 >> 4); + if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0]) + rice->k0--; + else if (rice->sum0 > shift_16[rice->k0 + 1]) + rice->k0++; + + value = DEC(value); +#endif + + /* decompress stage 1: adaptive hybrid filter */ + hybrid_filter(fst, &value); + + /* decompress stage 2: fixed order 1 prediction */ + value += PREDICTOR1(dec->last, pr_bits); + dec->last = value; + + /* check for errors */ + if (abs(value) > maxvalue) { + unsigned int tail = + pcm_buffer_size / (ttainfo->BSIZE * ttainfo->NCH) - res; + ci->memset(buffer, 0, pcm_buffer_size * sizeof(int32_t)); + data_cur += tail; res += tail; + break; + } + + /* Rockbox speciffic: Rockbox supports max 2channels */ + if (ttainfo->NCH == 1) + { + *p++ = value << pcm_shift_bits; + data_cur++; + res++; + } + else + { + if (dec == tta) + { + cache = value; + dec++; + } + else + { + value += cache / 2; + cache = value - cache; + dec = tta; + *p++ = cache << pcm_shift_bits; + *p++ = value << pcm_shift_bits; + data_cur++; + res++; + } + } + } + + return res; +} + +/* Rockbox speciffic: id3 tags functions delete. */ + +/* eof */ diff --git a/lib/rbcodec/codecs/libtta/ttadec.h b/lib/rbcodec/codecs/libtta/ttadec.h new file mode 100644 index 0000000000..c185e5c858 --- /dev/null +++ b/lib/rbcodec/codecs/libtta/ttadec.h @@ -0,0 +1,203 @@ +/* + * ttadec.h + * + * Description: TTAv1 decoder definitions and prototypes + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 2004 True Audio Software. All rights reserved. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the True Audio Software nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TTADEC_H_ +#define TTADEC_H_ + +#define __ATTRIBUTE_PACKED__ __attribute__((packed)) + +#define TTA1_SIGN 0x31415454 +#define MAX_ORDER 8 + +#ifndef WAVE_FORMAT_PCM +#define WAVE_FORMAT_PCM 1 +#endif + +typedef unsigned long long uint64; + +static const unsigned int crc32_table[256] ICONST_ATTR = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d +}; + +static const unsigned int bit_mask[] ICONST_ATTR = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + 0xffffffff +}; + +static const unsigned int bit_shift[] ICONST_ATTR = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x80000000, 0x80000000, 0x80000000, 0x80000000, + 0x80000000, 0x80000000, 0x80000000, 0x80000000 +}; + +static const unsigned int * const shift_16 ICONST_ATTR = bit_shift + 4; + +typedef unsigned char byte; + +#ifndef ROCKBOX_LITTLE_ENDIAN +#define ENDSWAP_INT16(x) (((((x)>>8)&0xFF)|(((x)&0xFF)<<8))) +#define ENDSWAP_INT32(x) (((((x)>>24)&0xFF)|(((x)>>8)&0xFF00)|(((x)&0xFF00)<<8)|(((x)&0xFF)<<24))) +#define WRITE_BUFFER(x, bsize, out) { \ + if (bsize > 2) *out++ = (byte)(*x >> 16)); \ + if (bsize > 1) *out++ = (byte)(*x >> 8); \ + *out++ = (byte) *x; } +#else +#define ENDSWAP_INT16(x) (x) +#define ENDSWAP_INT32(x) (x) +#define WRITE_BUFFER(x, bsize, out) { \ + *out++ = (byte) *x; \ + if (bsize > 1) *out++ = (byte)(*x >> 8); \ + if (bsize > 2) *out++ = (byte)(*x >> 16); } +#endif + +#define PREDICTOR1(x, k) ((int)((((uint64)x << k) - x) >> k)) +#define DEC(x) (((x)&1)?(((x)+1)>>1):(-(x)>>1)) + +typedef struct { + unsigned int TTAid; + unsigned short AudioFormat; + unsigned short NumChannels; + unsigned short BitsPerSample; + unsigned int SampleRate; + unsigned int DataLength; + unsigned int CRC32; +} __ATTRIBUTE_PACKED__ tta_hdr; + +typedef struct { + unsigned int k0; + unsigned int k1; + unsigned int sum0; + unsigned int sum1; +} adapt; + +typedef struct { + int index; /* Rockbox speciffic */ + int error; + int round; + int shift; + int mutex; + int qm[MAX_ORDER]; + int dx[MAX_ORDER * 3]; /* original: dx[MAX_ORDER + 1] */ + int dl[MAX_ORDER * 3]; /* original: dx[MAX_ORDER + 1] */ +} fltst; + +typedef struct { + fltst fst; + adapt rice; + int last; +} decoder; + +/* Rockbox speciffic: about id3 tags definitions delete. */ +#endif /* TTADEC_H_ */ diff --git a/lib/rbcodec/codecs/libtta/ttalib.h b/lib/rbcodec/codecs/libtta/ttalib.h new file mode 100644 index 0000000000..45da71813a --- /dev/null +++ b/lib/rbcodec/codecs/libtta/ttalib.h @@ -0,0 +1,157 @@ +/* + * ttalib.h + * + * Description: TTAv1 player library prototypes + * Developed by: Alexander Djourik + * Pavel Zhilin + * + * Copyright (c) 2004 True Audio Software. All rights reserved. + * + */ + +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the True Audio Software nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TTALIB_H_ +#define TTALIB_H_ + +#define MAX_BPS 24 /* Max supported Bit resolution */ +#define MAX_NCH 2 /* Max supported number of channels (Rockbox changes: 8 -> 2) */ + +#ifndef MAXLINE +#define MAX_LINE 1024 +#endif + +/* decoded pcm sample depth (sample 28bit + sign 1bit) */ +#define TTA_OUTPUT_DEPTH 29 + +/* return codes */ +#define NO_ERROR 0 /* No errors found */ +#define OPEN_ERROR 1 /* Can't open file */ +#define FORMAT_ERROR 2 /* Unknown TTA format version */ +#define PLAYER_ERROR 3 /* Not supported file format */ +#define FILE_ERROR 4 /* File is corrupted */ +#define READ_ERROR 5 /* Can't read from file */ +#define MEMORY_ERROR 6 /* Insufficient memory available */ + +/* Rockbox speciffic: does not use FRAME_TIME */ +/* #define FRAME_TIME 1.04489795918367346939 */ +#define MULTIPLY_FRAME_TIME(x) (256 * (x) / 245) /* = FRAME_TIME * x */ +#define SEEK_STEP (int)MULTIPLY_FRAME_TIME(1000) /* (FRAME_TIME * 1000) */ + +#define ISO_BUFFER_LENGTH (1024*32) +#define ISO_NBUFFERS (8) +#define ISO_BUFFERS_SIZE (4096) /* (ISO_BUFFER_LENGTH*ISO_NBUFFERS) */ +#define PCM_BUFFER_LENGTH (4608) +#define MAX_SEEK_TABLE_SIZE (4096) + +typedef struct { + /* FILE *HANDLE; // file handle (Rockbox does not use) */ + unsigned int FILESIZE; /* compressed size */ + unsigned short NCH; /* number of channels */ + unsigned short BPS; /* bits per sample */ + unsigned short BSIZE; /* byte size */ + unsigned short FORMAT; /* audio format */ + unsigned int SAMPLERATE; /* samplerate (sps) */ + unsigned int DATALENGTH; /* data length in samples */ + unsigned int FRAMELEN; /* frame length */ + unsigned int LENGTH; /* playback time (sec) */ + unsigned int STATE; /* return code */ + unsigned int DATAPOS; /* size of ID3v2 header */ + unsigned int BITRATE; /* average bitrate (kbps) */ + /* double COMPRESS; // compression ratio (Rockbox does not use) */ + /* id3_info ID3; // ID3 information (Rockbox does not use) */ +} tta_info; + +enum tta_seek_type +{ + TTA_SEEK_TIME, + TTA_SEEK_POS, +}; + +/*********************** Library functions *************************/ +/* Rockbox speciffic: open_tta_file() does not use */ + +/* Rockbox speciffic: It is used in place of open_tta_file(). */ +int set_tta_info( // FUNCTION: set tta file info structure + tta_info *info); // file info structure +/* + * RETURN VALUE + * This function returns 0 if success. Otherwise, -1 is returned + * and the variable STATE of the currently using info structure + * is set to indicate the error. + * + */ + +/* Rockbox speciffic: close_tta_file() does not use */ + +/* Rockbox speciffic: set_position() change arguments and return value. */ +/* + * FUNCTION: sets playback position + * pos: seek position + * seek_time_ms / SEEK_STEP (when type is TTA_SEEK_TIME) + * file position (when type is TTA_SEEK_POS) + */ +int set_position ( + unsigned int pos, + enum tta_seek_type type); + +/* + * RETURN VALUE + * This function returns the seeked data position (>= 0) if success. Otherwise, -1 is returned + * and the variable STATE of the currently using info structure + * is set to indicate the error. + * + */ + +int player_init ( // FUNCTION: initializes TTA player + tta_info *info); // file info structure +/* + * RETURN VALUE + * This function returns 0 if success. Otherwise, -1 is returned + * and the variable STATE of the currently using info structure + * is set to indicate the error. + * + */ + +void player_stop (void); // FUNCTION: destroys memory pools + +/* Rockbox speciffic: unsigned char -> int32_t */ +int get_samples ( // FUNCTION: decode PCM_BUFFER_LENGTH samples + int32_t *buffer) ICODE_ATTR; // into the current PCM buffer position + +/* + * RETURN VALUE + * This function returns the number of samples successfully decoded. + * Otherwise, -1 is returned and the variable STATE of the currently + * using info structure is set to indicate the error. + * + */ + +const char *get_error_str (int error); // FUNCTION: get error description + +#endif /* TTALIB_H_ */ -- cgit v1.2.3