summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYoshihisa Uchida <uchida@rockbox.org>2010-05-13 12:40:09 +0000
committerYoshihisa Uchida <uchida@rockbox.org>2010-05-13 12:40:09 +0000
commit0f5c6d47d4fdd17260b840024880ba6dd3fdf935 (patch)
tree6d2526a58816aa9f6431a22a8f1a56278a445dfd
parent889b4a8ce838bd4191c736d01d9665c177e6d390 (diff)
downloadrockbox-0f5c6d47d4fdd17260b840024880ba6dd3fdf935.tar.gz
rockbox-0f5c6d47d4fdd17260b840024880ba6dd3fdf935.zip
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
-rw-r--r--apps/SOURCES1
-rw-r--r--apps/codecs/SOURCES1
-rw-r--r--apps/codecs/codecs.make2
-rw-r--r--apps/codecs/libtta/README72
-rw-r--r--apps/codecs/libtta/README.rockbox34
-rw-r--r--apps/codecs/libtta/SOURCES4
-rw-r--r--apps/codecs/libtta/filter.h136
-rw-r--r--apps/codecs/libtta/filter_arm.S203
-rw-r--r--apps/codecs/libtta/libtta.make29
-rw-r--r--apps/codecs/libtta/ttadec.c576
-rw-r--r--apps/codecs/libtta/ttadec.h203
-rw-r--r--apps/codecs/libtta/ttalib.h157
-rw-r--r--apps/codecs/tta.c132
-rw-r--r--apps/filetypes.c1
-rw-r--r--apps/metadata.c11
-rw-r--r--apps/metadata.h1
-rw-r--r--apps/metadata/metadata_parsers.h2
-rw-r--r--apps/metadata/mp3.c2
-rw-r--r--apps/metadata/tta.c123
19 files changed, 1689 insertions, 1 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index ef81f0cfdd..8151c299b9 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -197,6 +197,7 @@ metadata/oma.c
197metadata/smaf.c 197metadata/smaf.c
198metadata/au.c 198metadata/au.c
199metadata/vox.c 199metadata/vox.c
200metadata/tta.c
200#endif 201#endif
201#ifdef HAVE_TAGCACHE 202#ifdef HAVE_TAGCACHE
202tagcache.c 203tagcache.c
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index e2ee53e7ee..160b8aa582 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -32,6 +32,7 @@ smaf.c
32au.c 32au.c
33vox.c 33vox.c
34wav64.c 34wav64.c
35tta.c
35#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 36#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
36/* encoders */ 37/* encoders */
37aiff_enc.c 38aiff_enc.c
diff --git a/apps/codecs/codecs.make b/apps/codecs/codecs.make
index 7a83e5d1da..e671932b41 100644
--- a/apps/codecs/codecs.make
+++ b/apps/codecs/codecs.make
@@ -41,6 +41,7 @@ include $(APPSDIR)/codecs/libcook/libcook.make
41include $(APPSDIR)/codecs/librm/librm.make 41include $(APPSDIR)/codecs/librm/librm.make
42include $(APPSDIR)/codecs/libatrac/libatrac.make 42include $(APPSDIR)/codecs/libatrac/libatrac.make
43include $(APPSDIR)/codecs/libpcm/libpcm.make 43include $(APPSDIR)/codecs/libpcm/libpcm.make
44include $(APPSDIR)/codecs/libtta/libtta.make
44 45
45# compile flags for codecs 46# compile flags for codecs
46CODECFLAGS = $(filter-out -fno-strict-aliasing,$(CFLAGS)) -fstrict-aliasing \ 47CODECFLAGS = $(filter-out -fno-strict-aliasing,$(CFLAGS)) -fstrict-aliasing \
@@ -96,6 +97,7 @@ $(CODECDIR)/smaf.codec : $(CODECDIR)/libpcm.a
96$(CODECDIR)/au.codec : $(CODECDIR)/libpcm.a 97$(CODECDIR)/au.codec : $(CODECDIR)/libpcm.a
97$(CODECDIR)/vox.codec : $(CODECDIR)/libpcm.a 98$(CODECDIR)/vox.codec : $(CODECDIR)/libpcm.a
98$(CODECDIR)/wav64.codec : $(CODECDIR)/libpcm.a 99$(CODECDIR)/wav64.codec : $(CODECDIR)/libpcm.a
100$(CODECDIR)/tta.codec : $(CODECDIR)/libtta.a
99 101
100$(CODECS): $(CODECLIB) # this must be last in codec dependency list 102$(CODECS): $(CODECLIB) # this must be last in codec dependency list
101 103
diff --git a/apps/codecs/libtta/README b/apps/codecs/libtta/README
new file mode 100644
index 0000000000..8b1a1b23c0
--- /dev/null
+++ b/apps/codecs/libtta/README
@@ -0,0 +1,72 @@
1TTA Hardware Players Library
2============================
3
4Version 1.2, (c) 2004 Alexander Djourik. All rights reserved.
5
6* Introduction
7
8This library provides to decode a multichannel 8,16 and 24
9bits TTA audio files. TTA is a lossless audio format. Being
10"lossless" means that no data/quality is lost in the compression
11- when uncompressed, the data will be identical to the original.
12The compression ratios of TTA depend on the type of music file
13being compressed, but the compression size will generally range
14between 30% - 70% of the original.
15
16TTA format supports both of ID3v1/v2 tags. Detailed format
17description is available at http://www.true-audio.com.
18
19The decoder process has a minimal system requirements and does
20not required to create a big additional memory pools. As the
21TTA algorithms has a same system requirements both for decoding
22and for encoding processes - the TTA recorder can be easily
23realized also.
24
25* Changes
26
27 14/04/2004 1.0 Initial release
28 16/04/2004 1.1 Code optimization
29 Code clean-up
30 29/10/2004 1.2 ID3 tags support
31 Code clean-up
32
33* To Do
34
35 - TTA recorder functions.
36
37* Developers
38
39 Alexander Djourik <ald@true-audio.com>
40 Pavel Zhilin <pzh@true-audio.com>
41
42* Copying
43
44Redistribution and use in source and binary forms, with or without
45modification, are permitted provided that the following conditions
46are met:
47
481. Redistributions of source code must retain the above copyright
49 notice, this list of conditions and the following disclaimer.
502. Redistributions in binary form must reproduce the above copyright
51 notice, this list of conditions and the following disclaimer in the
52 documentation and/or other materials provided with the distribution.
533. Neither the name of the True Audio Software nor the names of its
54 contributors may be used to endorse or promote products derived
55 from this software without specific prior written permission.
56
57THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
58"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
59LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
60A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
61OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
62SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
63LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
64DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
65THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
66(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
67OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
68
69* See also
70
71Please visit the TTA homepage at http://tta.sourceforge.net for the
72latest in news and downloads.
diff --git a/apps/codecs/libtta/README.rockbox b/apps/codecs/libtta/README.rockbox
new file mode 100644
index 0000000000..d605986d46
--- /dev/null
+++ b/apps/codecs/libtta/README.rockbox
@@ -0,0 +1,34 @@
1Library: True Audio
2Imported by : Yoshihisa Uchida
3Import date : 2010-03-05
4Baseed by : TTA library version 1.2 for hardware players (ttalib-hwplayer-1.2.tgz)
5 from http://true-audio.com/Free_Downloads
6
7This directory contains a decoder version of True Auido.
8
9LICENSING INFORMATION
10
11True Audio license is described in the README file or each source file (excepts filter_arm.S)
12in this directory.
13
14Limitation
15
16In some players, the decoding speed is not enough ( < 110%).
17(For example, H180: decoding speed < 60%)
18
19IMPORT DETAILS
20
21The .[ch] files from ttalib-hwplayer-1.2.tgz were imported into Rockbox.
22But the following files do not include.
23 Makefile
24 tta.vcproj
25 samples/*
26
27
28When source files import in Rockbox, I changed below.
29
30all files
31 - TAB => 4 spaces.
32 - // style comments changes to /* */ style.
33
34Moreover, I modify to optimize the decoding speed.
diff --git a/apps/codecs/libtta/SOURCES b/apps/codecs/libtta/SOURCES
new file mode 100644
index 0000000000..35f2660dd7
--- /dev/null
+++ b/apps/codecs/libtta/SOURCES
@@ -0,0 +1,4 @@
1ttadec.c
2#ifdef CPU_ARM
3filter_arm.S
4#endif
diff --git a/apps/codecs/libtta/filter.h b/apps/codecs/libtta/filter.h
new file mode 100644
index 0000000000..6eef6dcf42
--- /dev/null
+++ b/apps/codecs/libtta/filter.h
@@ -0,0 +1,136 @@
1/*
2 * filter.h
3 *
4 * Description: TTAv1 filter functions
5 * Developed by: Alexander Djourik <ald@true-audio.com>
6 * Pavel Zhilin <pzh@true-audio.com>
7 *
8 * Copyright (c) 2004 True Audio Software. All rights reserved.
9 *
10 */
11
12/*
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the True Audio Software nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#ifndef FILTER_H
40#define FILTER_H
41
42///////// Filter Settings //////////
43static int flt_set[3] = {10, 9, 10};
44
45#ifdef CPU_ARM
46int hybrid_filter(fltst *fs, int *in); /* implements in filter_arm.S */
47
48#else
49
50static inline void
51memshl (register int *pA) {
52 register int *pB = pA + 16;
53
54 *pA++ = *pB++;
55 *pA++ = *pB++;
56 *pA++ = *pB++;
57 *pA++ = *pB++;
58 *pA++ = *pB++;
59 *pA++ = *pB++;
60 *pA++ = *pB++;
61 *pA = *pB;
62}
63
64static inline void
65hybrid_filter (fltst *fs, int *in) {
66 register int *pA = fs->dl + fs->index;
67 register int *pB = fs->qm;
68 register int *pM = fs->dx + fs->index;
69 register int sum = fs->round;
70
71 if (!fs->error) {
72 sum += *pA++ * *pB++;
73 sum += *pA++ * *pB++;
74 sum += *pA++ * *pB++;
75 sum += *pA++ * *pB++;
76 sum += *pA++ * *pB++;
77 sum += *pA++ * *pB++;
78 sum += *pA++ * *pB++;
79 sum += *pA * *pB;
80 pM += 8;
81 } else if (fs->error < 0) {
82 sum += *pA++ * (*pB++ -= *pM++);
83 sum += *pA++ * (*pB++ -= *pM++);
84 sum += *pA++ * (*pB++ -= *pM++);
85 sum += *pA++ * (*pB++ -= *pM++);
86 sum += *pA++ * (*pB++ -= *pM++);
87 sum += *pA++ * (*pB++ -= *pM++);
88 sum += *pA++ * (*pB++ -= *pM++);
89 sum += *pA * (*pB -= *pM++);
90 } else {
91 sum += *pA++ * (*pB++ += *pM++);
92 sum += *pA++ * (*pB++ += *pM++);
93 sum += *pA++ * (*pB++ += *pM++);
94 sum += *pA++ * (*pB++ += *pM++);
95 sum += *pA++ * (*pB++ += *pM++);
96 sum += *pA++ * (*pB++ += *pM++);
97 sum += *pA++ * (*pB++ += *pM++);
98 sum += *pA * (*pB += *pM++);
99 }
100
101 pB = pA++;
102 fs->error = *in;
103 *in += (sum >> fs->shift);
104 *pA = *in;
105
106 *pM-- = ((*pB-- >> 30) | 1) << 2;
107 *pM-- = ((*pB-- >> 30) | 1) << 1;
108 *pM-- = ((*pB-- >> 30) | 1) << 1;
109 *pM = ((*pB >> 30) | 1);
110
111 *(pA-1) = *(pA-0) - *(pA-1);
112 *(pA-2) = *(pA-1) - *(pA-2);
113 *(pA-3) = *(pA-2) - *(pA-3);
114
115 /*
116 * Rockbox speciffic
117 * in order to make speed up, memshl() is executed at the rate once every 16 times.
118 */
119 if (++fs->index == 16)
120 {
121 memshl (fs->dl);
122 memshl (fs->dx);
123 fs->index = 0;
124 }
125}
126#endif
127
128static inline void
129filter_init (fltst *fs, int shift) {
130 ci->memset (fs, 0, sizeof(fltst));
131 fs->shift = shift;
132 fs->round = 1 << (shift - 1);
133 fs->index = 0;
134}
135
136#endif /* FILTER_H */
diff --git a/apps/codecs/libtta/filter_arm.S b/apps/codecs/libtta/filter_arm.S
new file mode 100644
index 0000000000..37c515d3a9
--- /dev/null
+++ b/apps/codecs/libtta/filter_arm.S
@@ -0,0 +1,203 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Yoshihisa Uchida
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23
24/*
25 * The following are assembler optimised version of
26 * void hybrid_filter(fltst *fs, int *in)
27 */
28
29#ifdef USE_IRAM
30 .section .icode, "ax", %progbits
31#else
32 .text
33#endif
34 .align
35 .global hybrid_filter
36 .type hybrid_filter, %function
37
38hybrid_filter:
39 @ input: r0 = fs, r1 = in
40 stmdb sp!, {r4 - r12, lr}
41
42 @ get fs members
43 @ r2 pA := fs->dl + fs->index
44 @ r3 pM := fs->dx + fs->index
45 @ r4 pB := fs->qm
46 @ r5 fs->index
47 @ r6 fs->error
48 @ lr sum := fs->round
49
50 add r2, r0, #148 @ r2 = fs->dl
51 add r3, r0, #52 @ r3 = fs->dx
52 add r4, r0, #20 @ r4 = fs->qm
53 ldmia r0, {r5, r6, lr} @ r5 = fs->index
54 @ r6 = fs->error
55 @ lr = fs->round
56 mov r5, r5, asl #2
57 add r2, r2, r5 @ r2 = fs->dl + fs->index
58 add r3, r3, r5 @ r3 = fs->dx + fs->index
59
60 cmp r6, #0
61 bne .hf_positive
62
63 @ case fs->error == 0
64
65 add r3, r3, #32
66 ldmia r4!, {r5, r6, r7, r8 }
67 ldmia r2!, {r9, r10, r11, r12}
68 mla lr, r5, r9, lr
69 mla lr, r6, r10, lr
70 mla lr, r7, r11, lr
71 mla lr, r8, r12, lr
72 ldmia r4!, {r5, r6, r7, r8 }
73 b .hf2
74
75.hf_positive:
76 blt .hf_negative
77
78 @ case fs->error > 0
79
80 ldmia r4, {r5, r6, r7, r8 }
81 ldmia r3!, {r9, r10, r11, r12}
82 add r5, r5, r9
83 add r6, r6, r10
84 add r7, r7, r11
85 add r8, r8, r12
86 stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[0], ..., fs->qm[3]
87 ldmia r2!, {r9, r10, r11, r12}
88 mla lr, r5, r9, lr
89 mla lr, r6, r10, lr
90 mla lr, r7, r11, lr
91 mla lr, r8, r12, lr
92 ldmia r4, {r5, r6, r7, r8 }
93 ldmia r3!, {r9, r10, r11, r12}
94 add r5, r5, r9
95 add r6, r6, r10
96 add r7, r7, r11
97 add r8, r8, r12
98 stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[4], ..., fs->qm[7]
99 b .hf2
100
101.hf_negative:
102 @ case fs->error < 0
103
104 ldmia r4, {r5, r6, r7, r8 }
105 ldmia r3!, {r9, r10, r11, r12}
106 sub r5, r5, r9
107 sub r6, r6, r10
108 sub r7, r7, r11
109 sub r8, r8, r12
110 stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[0], ..., fs->qm[3]
111 ldmia r2!, {r9, r10, r11, r12}
112 mla lr, r5, r9, lr
113 mla lr, r6, r10, lr
114 mla lr, r7, r11, lr
115 mla lr, r8, r12, lr
116 ldmia r4, {r5, r6, r7, r8 }
117 ldmia r3!, {r9, r10, r11, r12}
118 sub r5, r5, r9
119 sub r6, r6, r10
120 sub r7, r7, r11
121 sub r8, r8, r12
122 stmia r4!, {r5, r6, r7, r8 } @ update fs->qm[4], ..., fs->qm[7]
123
124.hf2:
125 ldmia r2!, {r9, r10, r11, r12}
126 mla lr, r5, r9, lr
127 mla lr, r6, r10, lr
128 mla lr, r7, r11, lr
129 mla lr, r8, r12, lr
130
131 @ fs->error = *in;
132 @ *in += (sum >> fs->shift)
133 @ *pA = *in
134
135 ldr r5, [r1] @ r5 = *in
136 ldr r6, [r0, #12] @ r6 = fs->shift
137 add lr, r5, lr, asr r6
138 str lr, [r1] @ *in += (sum >> fs->shift)
139
140 @ update fs->index
141
142 ldr r1, [r0] @ r1 = fs->index
143 add r1, r1, #1
144 ands r1, r1, #15 @ set Z flag (after this, CPSR must keep !!)
145 stmia r0, {r1, r5} @ fs->index = (++fs->index & 15)
146 @ fs->error = (original) *in
147
148 @ change *pM, *(pM-1), *(pM-2), *(pM-3)
149 @ r9 = *(pA-4), r5 = *(pM-3)
150 @ r10 = *(pA-3), r6 = *(pM-2)
151 @ r11 = *(pA-2), r7 = *(pM-1)
152 @ r12 = *(pA-1), r8 = *(pM-0)
153 @ lr = *(pA-0)
154
155 mov r4, #1
156 orr r5, r4, r9, asr #30
157 orr r6, r4, r10, asr #30
158 orr r7, r4, r11, asr #30
159 orr r8, r4, r12, asr #30
160 mov r6, r6, lsl #1
161 mov r7, r7, lsl #1
162 mov r8, r8, lsl #2
163
164 @ change *(pA-1), *(pA-2), *(pA-3)
165 sub r12, lr, r12
166 sub r11, r12, r11
167 sub r10, r11, r10
168
169 @ check fs->index is zero
170 beq .hf_memshl
171
172 @ set to the memory: *pA, *(pA-1), *(pA-2), *(pA-3), *pM, *(pM-1), *(pM-2), *(pM-3)
173 stmda r2, {r10, r11, r12, lr}
174 stmda r3, {r5, r6, r7, r8}
175 ldmfd sp!, {r4-r12, pc} @ hybrid_filter end (when fs->index != 0)
176
177.hf_memshl:
178 @ memshl (fs->dl)
179 @ r9 = fs->dl[16 + 3]
180 @ r10 = fs->dl[16 + 4]
181 @ r11 = fs->dl[16 + 5]
182 @ r12 = fs->dl[16 + 6]
183 @ lr = fs->dl[16 + 7]
184
185 add r2, r0, #212 @ r2 = fs->dl + 16
186 ldmia r2, {r1, r3, r4}
187 sub r2, r2, #64 @ r2 = fs->dl
188 stmia r2, {r1, r3, r4, r9 - r12, lr}
189
190 @ memshl (fs->dx)
191 @ r5 = fs->dx[16 + 4]
192 @ r6 = fs->dx[16 + 5]
193 @ r7 = fs->dx[16 + 6]
194 @ r8 = fs->dx[16 + 7]
195
196 add r9, r0, #116 @ r9 = fs->dx + 16
197 ldmia r9, {r1, r2, r3, r4}
198 sub r9, r9, #64 @ r9 = fs->dx
199 stmia r9, {r1 - r8}
200 ldmfd sp!, {r4 - r12, pc} @ hybrid_filter end (when fs->index == 0)
201
202hybrid_filter_end:
203 .size hybrid_filter, hybrid_filter_end - hybrid_filter
diff --git a/apps/codecs/libtta/libtta.make b/apps/codecs/libtta/libtta.make
new file mode 100644
index 0000000000..c0a799ac67
--- /dev/null
+++ b/apps/codecs/libtta/libtta.make
@@ -0,0 +1,29 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10# libtta
11TTALIB := $(CODECDIR)/libtta.a
12TTALIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libtta/SOURCES)
13TTALIB_OBJ := $(call c2obj, $(TTALIB_SRC))
14OTHER_SRC += $(TTALIB_SRC)
15
16$(TTALIB): $(TTALIB_OBJ)
17 $(SILENT)$(shell rm -f $@)
18 $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
19
20TTAFLAGS = $(filter-out -O%,$(CODECFLAGS))
21TTAFLAGS += -O3 -funroll-loops -fomit-frame-pointer
22
23$(CODECDIR)/libtta/%.o: $(ROOTDIR)/apps/codecs/libtta/%.c
24 $(SILENT)mkdir -p $(dir $@)
25 $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) $(TTAFLAGS) -c $< -o $@
26
27$(CODECDIR)/libtta/%.o: $(ROOTDIR)/apps/codecs/libtta/%.S
28 $(SILENT)mkdir -p $(dir $@)
29 $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) $(TTAFLAGS) -c $< -o $@
diff --git a/apps/codecs/libtta/ttadec.c b/apps/codecs/libtta/ttadec.c
new file mode 100644
index 0000000000..027b78a17e
--- /dev/null
+++ b/apps/codecs/libtta/ttadec.c
@@ -0,0 +1,576 @@
1/*
2 * ttadec.c
3 *
4 * Description: TTAv1 decoder library for HW players
5 * Developed by: Alexander Djourik <ald@true-audio.com>
6 * Pavel Zhilin <pzh@true-audio.com>
7 *
8 * Copyright (c) 2004 True Audio Software. All rights reserved.
9 *
10 */
11
12/*
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the True Audio Software nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include "codeclib.h"
40
41#include "ttalib.h"
42#include "ttadec.h"
43#include "filter.h"
44
45/******************* static variables and structures *******************/
46
47static unsigned char isobuffers[ISO_BUFFERS_SIZE + 4] IBSS_ATTR;
48static unsigned char *iso_buffers_end = isobuffers + ISO_BUFFERS_SIZE;
49static unsigned int pcm_buffer_size;
50
51static decoder tta[MAX_NCH]; /* decoder state */
52/* Rockbox speciffic: cache is defined in get_samples() (non static value) */
53/* static int cache[MAX_NCH]; // decoder cache */
54
55tta_info *ttainfo; /* currently playing file info */
56
57static unsigned int fframes; /* number of frames in file */
58static unsigned int framelen; /* the frame length in samples */
59static unsigned int lastlen; /* the length of the last frame in samples */
60static unsigned int data_pos; /* currently playing frame index */
61static unsigned int data_cur; /* the playing position in frame */
62
63static int maxvalue; /* output data max value */
64
65/* Rockbox speciffic: seek_table is static size */
66static unsigned int seek_table[MAX_SEEK_TABLE_SIZE]; /* the playing position table */
67static unsigned int st_state; /* seek table status */
68
69static unsigned int frame_crc32;
70static unsigned int bit_count;
71static unsigned int bit_cache;
72static unsigned char *bitpos;
73
74/* Rockbox speciffic: deletes read_id3_tags(). */
75/* static int read_id3_tags (tta_info *info); */
76
77/********************* rockbox helper functions *************************/
78
79/* emulate stdio functions */
80static int fread(void *ptr, size_t size, size_t nobj)
81{
82 size_t read_size;
83 unsigned char *buffer = ci->request_buffer(&read_size, size * nobj);
84
85 if (read_size > 0)
86 {
87 ci->memcpy(ptr, buffer, read_size);
88 ci->advance_buffer(read_size);
89 }
90 return read_size;
91}
92
93static int fseek(long offset, int origin)
94{
95 switch (origin)
96 {
97 case SEEK_CUR:
98 ci->advance_buffer(offset);
99 break;
100 case SEEK_SET:
101 ci->seek_buffer(offset);
102 break;
103 case SEEK_END:
104 ci->seek_buffer(offset + ci->id3->filesize);
105 break;
106 default:
107 return -1;
108 }
109 return 0;
110}
111
112/************************* crc32 functions *****************************/
113
114#define UPDATE_CRC32(x, crc) crc = \
115 (((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc^x) & 0xFF])
116
117static unsigned int
118crc32 (unsigned char *buffer, unsigned int len) {
119 unsigned int i;
120 unsigned int crc = 0xFFFFFFFF;
121
122 for (i = 0; i < len; i++) UPDATE_CRC32(buffer[i], crc);
123
124 return (crc ^ 0xFFFFFFFF);
125}
126
127/************************* bit operations ******************************/
128
129#define GET_BINARY(value, bits) \
130 while (bit_count < bits) { \
131 if (bitpos == iso_buffers_end) { \
132 if (!fread(isobuffers, 1, ISO_BUFFERS_SIZE)) { \
133 ttainfo->STATE = READ_ERROR; \
134 return -1; \
135 } \
136 bitpos = isobuffers; \
137 } \
138 UPDATE_CRC32(*bitpos, frame_crc32); \
139 bit_cache |= *bitpos << bit_count; \
140 bit_count += 8; \
141 bitpos++; \
142 } \
143 value = bit_cache & bit_mask[bits]; \
144 bit_cache >>= bits; \
145 bit_count -= bits; \
146 bit_cache &= bit_mask[bit_count];
147
148#define GET_UNARY(value) \
149 value = 0; \
150 while (!(bit_cache ^ bit_mask[bit_count])) { \
151 if (bitpos == iso_buffers_end) { \
152 if (!fread(isobuffers, 1, ISO_BUFFERS_SIZE)) { \
153 ttainfo->STATE = READ_ERROR; \
154 return -1; \
155 } \
156 bitpos = isobuffers; \
157 } \
158 value += bit_count; \
159 bit_cache = *bitpos++; \
160 UPDATE_CRC32(bit_cache, frame_crc32); \
161 bit_count = 8; \
162 } \
163 while (bit_cache & 1) { \
164 value++; \
165 bit_cache >>= 1; \
166 bit_count--; \
167 } \
168 bit_cache >>= 1; \
169 bit_count--;
170
171/************************* rice operations ******************************/
172
173static inline int update_rice(int value, adapt *rice, int depth,
174 const unsigned int *shift_table)
175{
176 if (depth > 0)
177 {
178 rice->sum1 += value - (rice->sum1 >> 4);
179 if (rice->k1 > 0 && rice->sum1 < shift_table[rice->k1])
180 rice->k1--;
181 else if (rice->sum1 > shift_table[rice->k1 + 1])
182 rice->k1++;
183 value += *(shift_table + rice->k0 - 4);
184 }
185 rice->sum0 += value - (rice->sum0 >> 4);
186 if (rice->k0 > 0 && rice->sum0 < shift_table[rice->k0])
187 rice->k0--;
188 else if (rice->sum0 > shift_table[rice->k0 + 1])
189 rice->k0++;
190
191 return DEC(value);
192}
193
194/************************* buffer functions ******************************/
195
196static void init_buffer_read(void) {
197 frame_crc32 = 0xFFFFFFFFUL;
198 bit_count = bit_cache = 0;
199 bitpos = iso_buffers_end;
200}
201
202static int done_buffer_read(void) {
203 unsigned int crc32, rbytes;
204
205 frame_crc32 ^= 0xFFFFFFFFUL;
206 rbytes = iso_buffers_end - bitpos;
207
208 if (rbytes < sizeof(int)) {
209 ci->memcpy(isobuffers, bitpos, 4);
210 if (!fread(isobuffers + rbytes, 1, ISO_BUFFERS_SIZE - rbytes))
211 return -1;
212 bitpos = isobuffers;
213 }
214
215 ci->memcpy(&crc32, bitpos, 4);
216 crc32 = ENDSWAP_INT32(crc32);
217 bitpos += sizeof(int);
218
219 if (crc32 != frame_crc32) return -1;
220
221 bit_cache = bit_count = 0;
222 frame_crc32 = 0xFFFFFFFFUL;
223
224 return 0;
225}
226
227/************************* decoder functions ****************************/
228
229const char *get_error_str (int error) {
230 switch (error) {
231 case NO_ERROR: return "No errors found";
232 case OPEN_ERROR: return "Can't open file";
233 case FORMAT_ERROR: return "Not supported file format";
234 case FILE_ERROR: return "File is corrupted";
235 case READ_ERROR: return "Can't read from file";
236 case MEMORY_ERROR: return "Insufficient memory available";
237 default: return "Unknown error code";
238 }
239}
240
241int set_tta_info (tta_info *info)
242{
243 unsigned int checksum;
244 unsigned int datasize;
245 unsigned int origsize;
246 tta_hdr ttahdr;
247
248 /* clear the memory */
249 ci->memset (info, 0, sizeof(tta_info));
250
251 /* skip id3v2 tags */
252 fseek(ci->id3->id3v2len, SEEK_SET);
253
254 /* read TTA header */
255 if (fread (&ttahdr, 1, sizeof (ttahdr)) == 0) {
256 info->STATE = READ_ERROR;
257 return -1;
258 }
259
260 /* check for TTA3 signature */
261 if (ENDSWAP_INT32(ttahdr.TTAid) != TTA1_SIGN) {
262 DEBUGF("ID error: %x\n", ENDSWAP_INT32(ttahdr.TTAid));
263 info->STATE = FORMAT_ERROR;
264 return -1;
265 }
266
267 ttahdr.CRC32 = ENDSWAP_INT32(ttahdr.CRC32);
268 checksum = crc32((unsigned char *) &ttahdr,
269 sizeof(tta_hdr) - sizeof(int));
270 if (checksum != ttahdr.CRC32) {
271 DEBUGF("CRC error: %x != %x\n", ttahdr.CRC32, checksum);
272 info->STATE = FILE_ERROR;
273 return -1;
274 }
275
276 ttahdr.AudioFormat = ENDSWAP_INT16(ttahdr.AudioFormat);
277 ttahdr.NumChannels = ENDSWAP_INT16(ttahdr.NumChannels);
278 ttahdr.BitsPerSample = ENDSWAP_INT16(ttahdr.BitsPerSample);
279 ttahdr.SampleRate = ENDSWAP_INT32(ttahdr.SampleRate);
280 ttahdr.DataLength = ENDSWAP_INT32(ttahdr.DataLength);
281
282 /* check for player supported formats */
283 if (ttahdr.AudioFormat != WAVE_FORMAT_PCM ||
284 ttahdr.NumChannels > MAX_NCH ||
285 ttahdr.BitsPerSample > MAX_BPS ||(
286 ttahdr.SampleRate != 16000 &&
287 ttahdr.SampleRate != 22050 &&
288 ttahdr.SampleRate != 24000 &&
289 ttahdr.SampleRate != 32000 &&
290 ttahdr.SampleRate != 44100 &&
291 ttahdr.SampleRate != 48000 &&
292 ttahdr.SampleRate != 64000 &&
293 ttahdr.SampleRate != 88200 &&
294 ttahdr.SampleRate != 96000)) {
295 info->STATE = FORMAT_ERROR;
296 DEBUGF("illegal audio format: %d channels: %d samplerate: %d\n",
297 ttahdr.AudioFormat, ttahdr.NumChannels, ttahdr.SampleRate);
298 return -1;
299 }
300
301 /* fill the File Info */
302 info->NCH = ttahdr.NumChannels;
303 info->BPS = ttahdr.BitsPerSample;
304 info->BSIZE = (ttahdr.BitsPerSample + 7)/8;
305 info->FORMAT = ttahdr.AudioFormat;
306 info->SAMPLERATE = ttahdr.SampleRate;
307 info->DATALENGTH = ttahdr.DataLength;
308 info->FRAMELEN = (int) MULTIPLY_FRAME_TIME(ttahdr.SampleRate);
309 info->LENGTH = ttahdr.DataLength / ttahdr.SampleRate;
310 info->DATAPOS = ci->id3->id3v2len;
311 info->FILESIZE = ci->id3->filesize;
312
313 datasize = info->FILESIZE - info->DATAPOS;
314 origsize = info->DATALENGTH * info->BSIZE * info->NCH;
315
316 /* info->COMPRESS = (double) datasize / origsize; */
317 info->BITRATE = (int) ((uint64_t) datasize * info->SAMPLERATE * info->NCH * info->BPS
318 / (origsize * 1000LL));
319
320 return 0;
321}
322
323static void rice_init(adapt *rice, unsigned int k0, unsigned int k1) {
324 rice->k0 = k0;
325 rice->k1 = k1;
326 rice->sum0 = shift_16[k0];
327 rice->sum1 = shift_16[k1];
328}
329
330static void decoder_init(decoder *tta, int nch, int byte_size) {
331 int shift = flt_set[byte_size - 1];
332 int i;
333
334 for (i = 0; i < nch; i++) {
335 filter_init(&tta[i].fst, shift);
336 rice_init(&tta[i].rice, 10, 10);
337 tta[i].last = 0;
338 }
339}
340
341static void seek_table_init (unsigned int *seek_table,
342 unsigned int len, unsigned int data_offset) {
343 unsigned int *st, frame_len;
344
345 for (st = seek_table; st < (seek_table + len); st++) {
346 frame_len = ENDSWAP_INT32(*st);
347 *st = data_offset;
348 data_offset += frame_len;
349 }
350}
351
352int set_position (unsigned int pos, enum tta_seek_type type)
353{
354 unsigned int i;
355 unsigned int seek_pos;
356
357 if (type == TTA_SEEK_TIME)
358 {
359 if (pos >= fframes)
360 pos = fframes -1;
361 }
362 else
363 {
364 pos -= ttainfo->DATAPOS;
365 for (i = 1; i < fframes; i++)
366 {
367 if (seek_table[i] > pos)
368 break;
369 }
370 pos = i - 1;
371 }
372 if (!st_state) {
373 ttainfo->STATE = FILE_ERROR;
374 return -1;
375 }
376 seek_pos = ttainfo->DATAPOS + seek_table[data_pos = pos];
377 if (fseek(seek_pos, SEEK_SET) < 0) {
378 ttainfo->STATE = READ_ERROR;
379 return -1;
380 }
381
382 data_cur = 0;
383 framelen = 0;
384
385 /* init bit reader */
386 init_buffer_read();
387 return data_pos * ttainfo->FRAMELEN;
388}
389
390int player_init (tta_info *info) {
391 unsigned int checksum;
392 unsigned int data_offset;
393 unsigned int st_size;
394
395 ttainfo = info;
396
397 framelen = 0;
398 data_pos = 0;
399 data_cur = 0;
400
401 lastlen = ttainfo->DATALENGTH % ttainfo->FRAMELEN;
402 fframes = ttainfo->DATALENGTH / ttainfo->FRAMELEN + (lastlen ? 1 : 0);
403 st_size = (fframes + 1) * sizeof(int);
404
405 /*
406 * Rockbox speciffic
407 * playable tta file is to MAX_SEEK_TABLE_SIZE frames
408 * about 1:08:15 (frequency 44.1 kHz)
409 */
410 if (fframes > MAX_SEEK_TABLE_SIZE)
411 {
412 LOGF("frame is too many: %d > %d", fframes, MAX_SEEK_TABLE_SIZE);
413 return -1;
414 }
415
416 /* read seek table */
417 if (!fread(seek_table, st_size, 1)) {
418 ttainfo->STATE = READ_ERROR;
419 return -1;
420 }
421
422 checksum = crc32((unsigned char *) seek_table, st_size - sizeof(int));
423 st_state = (checksum == ENDSWAP_INT32(seek_table[fframes]));
424 data_offset = sizeof(tta_hdr) + st_size;
425
426 /* init seek table */
427 seek_table_init(seek_table, fframes, data_offset);
428
429 /* init bit reader */
430 init_buffer_read();
431
432 /*
433 * Rockbox speciffic
434 * because pcm data is int32_t, does not multiply ttainfo->BSIZE.
435 */
436 pcm_buffer_size = PCM_BUFFER_LENGTH * ttainfo->NCH;
437 maxvalue = (1UL << ttainfo->BPS) - 1;
438
439 return 0;
440}
441
442/*
443 * Rockbox specffic
444 * because the seek table is static size buffer, player_stop() is nooperation function.
445 */
446void player_stop (void) {
447/*
448 if (seek_table) {
449 free(seek_table);
450 seek_table = NULL;
451 }
452*/
453}
454
455/*
456 * Rockbox speciffic
457 * with the optimization, the decoding logic is modify a little.
458 */
459int get_samples (int32_t *buffer) {
460 unsigned int k, depth, unary, binary;
461 int32_t *p = buffer;
462 decoder *dec = tta;
463 int value, res;
464 int cur_pos = pcm_buffer_size;
465 int pcm_shift_bits = TTA_OUTPUT_DEPTH - ttainfo->BPS;
466 int pr_bits = (ttainfo->BSIZE == 1)? 4 : 5;
467 int cache = 0; /* decoder cache */
468
469 fltst *fst;
470 adapt *rice;
471
472 for (res = 0; --cur_pos >= 0;) {
473 fst = &dec->fst;
474 rice = &dec->rice;
475
476 if (data_cur == framelen) {
477 if (data_pos == fframes) break;
478 if (framelen && done_buffer_read()) {
479 if (set_position(data_pos, TTA_SEEK_TIME) < 0) return -1;
480 if (res) break;
481 }
482
483 if (data_pos == fframes - 1 && lastlen)
484 framelen = lastlen;
485 else framelen = ttainfo->FRAMELEN;
486
487 decoder_init(tta, ttainfo->NCH, ttainfo->BSIZE);
488 data_pos++; data_cur = 0;
489 }
490
491 /* decode Rice unsigned */
492 GET_UNARY(unary);
493
494 switch (unary) {
495 case 0: depth = 0; k = rice->k0; break;
496 default:
497 depth = 1; k = rice->k1;
498 unary--;
499 }
500
501 if (k) {
502 GET_BINARY(binary, k);
503 value = (unary << k) + binary;
504 } else value = unary;
505
506 value = update_rice(value, rice, depth, shift_16);
507
508 /* Rockbox specific: the following logic move to update_rice() */
509#if 0
510 if (depth > 0)
511 {
512 rice->sum1 += value - (rice->sum1 >> 4);
513 if (rice->k1 > 0 && rice->sum1 < shift_16[rice->k1])
514 rice->k1--;
515 else if (rice->sum1 > shift_16[rice->k1 + 1])
516 rice->k1++;
517 value += bit_shift[rice->k0];
518 }
519 rice->sum0 += value - (rice->sum0 >> 4);
520 if (rice->k0 > 0 && rice->sum0 < shift_16[rice->k0])
521 rice->k0--;
522 else if (rice->sum0 > shift_16[rice->k0 + 1])
523 rice->k0++;
524
525 value = DEC(value);
526#endif
527
528 /* decompress stage 1: adaptive hybrid filter */
529 hybrid_filter(fst, &value);
530
531 /* decompress stage 2: fixed order 1 prediction */
532 value += PREDICTOR1(dec->last, pr_bits);
533 dec->last = value;
534
535 /* check for errors */
536 if (abs(value) > maxvalue) {
537 unsigned int tail =
538 pcm_buffer_size / (ttainfo->BSIZE * ttainfo->NCH) - res;
539 ci->memset(buffer, 0, pcm_buffer_size * sizeof(int32_t));
540 data_cur += tail; res += tail;
541 break;
542 }
543
544 /* Rockbox speciffic: Rockbox supports max 2channels */
545 if (ttainfo->NCH == 1)
546 {
547 *p++ = value << pcm_shift_bits;
548 data_cur++;
549 res++;
550 }
551 else
552 {
553 if (dec == tta)
554 {
555 cache = value;
556 dec++;
557 }
558 else
559 {
560 value += cache / 2;
561 cache = value - cache;
562 dec = tta;
563 *p++ = cache << pcm_shift_bits;
564 *p++ = value << pcm_shift_bits;
565 data_cur++;
566 res++;
567 }
568 }
569 }
570
571 return res;
572}
573
574/* Rockbox speciffic: id3 tags functions delete. */
575
576/* eof */
diff --git a/apps/codecs/libtta/ttadec.h b/apps/codecs/libtta/ttadec.h
new file mode 100644
index 0000000000..43affd952b
--- /dev/null
+++ b/apps/codecs/libtta/ttadec.h
@@ -0,0 +1,203 @@
1/*
2 * ttadec.h
3 *
4 * Description: TTAv1 decoder definitions and prototypes
5 * Developed by: Alexander Djourik <ald@true-audio.com>
6 * Pavel Zhilin <pzh@true-audio.com>
7 *
8 * Copyright (c) 2004 True Audio Software. All rights reserved.
9 *
10 */
11
12/*
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the True Audio Software nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#ifndef TTADEC_H_
40#define TTADEC_H_
41
42#define __ATTRIBUTE_PACKED__ __attribute__((packed))
43
44#define TTA1_SIGN 0x31415454
45#define MAX_ORDER 8
46
47#ifndef WAVE_FORMAT_PCM
48#define WAVE_FORMAT_PCM 1
49#endif
50
51typedef unsigned long long uint64;
52
53static const unsigned int crc32_table[256] ICONST_ATTR = {
54 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
55 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
56 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
57 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
58 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
59 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
60 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
61 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
62 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
63 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
64 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
65 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
66 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
67 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
68 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
69 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
70 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
71 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
72 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
73 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
74 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
75 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
76 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
77 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
78 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
79 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
80 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
81 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
82 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
83 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
84 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
85 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
86 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
87 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
88 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
89 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
90 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
91 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
92 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
93 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
94 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
95 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
96 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
97 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
98 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
99 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
100 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
101 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
102 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
103 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
104 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
105 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
106 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
107 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
108 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
109 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
110 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
111 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
112 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
113 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
114 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
115 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
116 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
117 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
118};
119
120static const unsigned int bit_mask[] ICONST_ATTR = {
121 0x00000000, 0x00000001, 0x00000003, 0x00000007,
122 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
123 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
124 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
125 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
126 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
127 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
128 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
129 0xffffffff
130};
131
132static const unsigned int bit_shift[] ICONST_ATTR = {
133 0x00000001, 0x00000002, 0x00000004, 0x00000008,
134 0x00000010, 0x00000020, 0x00000040, 0x00000080,
135 0x00000100, 0x00000200, 0x00000400, 0x00000800,
136 0x00001000, 0x00002000, 0x00004000, 0x00008000,
137 0x00010000, 0x00020000, 0x00040000, 0x00080000,
138 0x00100000, 0x00200000, 0x00400000, 0x00800000,
139 0x01000000, 0x02000000, 0x04000000, 0x08000000,
140 0x10000000, 0x20000000, 0x40000000, 0x80000000,
141 0x80000000, 0x80000000, 0x80000000, 0x80000000,
142 0x80000000, 0x80000000, 0x80000000, 0x80000000
143};
144
145static const unsigned int *shift_16 = bit_shift + 4;
146
147typedef unsigned char byte;
148
149#ifndef ROCKBOX_LITTLE_ENDIAN
150#define ENDSWAP_INT16(x) (((((x)>>8)&0xFF)|(((x)&0xFF)<<8)))
151#define ENDSWAP_INT32(x) (((((x)>>24)&0xFF)|(((x)>>8)&0xFF00)|(((x)&0xFF00)<<8)|(((x)&0xFF)<<24)))
152#define WRITE_BUFFER(x, bsize, out) { \
153 if (bsize > 2) *out++ = (byte)(*x >> 16)); \
154 if (bsize > 1) *out++ = (byte)(*x >> 8); \
155 *out++ = (byte) *x; }
156#else
157#define ENDSWAP_INT16(x) (x)
158#define ENDSWAP_INT32(x) (x)
159#define WRITE_BUFFER(x, bsize, out) { \
160 *out++ = (byte) *x; \
161 if (bsize > 1) *out++ = (byte)(*x >> 8); \
162 if (bsize > 2) *out++ = (byte)(*x >> 16); }
163#endif
164
165#define PREDICTOR1(x, k) ((int)((((uint64)x << k) - x) >> k))
166#define DEC(x) (((x)&1)?(((x)+1)>>1):(-(x)>>1))
167
168typedef struct {
169 unsigned int TTAid;
170 unsigned short AudioFormat;
171 unsigned short NumChannels;
172 unsigned short BitsPerSample;
173 unsigned int SampleRate;
174 unsigned int DataLength;
175 unsigned int CRC32;
176} __ATTRIBUTE_PACKED__ tta_hdr;
177
178typedef struct {
179 unsigned int k0;
180 unsigned int k1;
181 unsigned int sum0;
182 unsigned int sum1;
183} adapt;
184
185typedef struct {
186 int index; /* Rockbox speciffic */
187 int error;
188 int round;
189 int shift;
190 int mutex;
191 int qm[MAX_ORDER];
192 int dx[MAX_ORDER * 3]; /* original: dx[MAX_ORDER + 1] */
193 int dl[MAX_ORDER * 3]; /* original: dx[MAX_ORDER + 1] */
194} fltst;
195
196typedef struct {
197 fltst fst;
198 adapt rice;
199 int last;
200} decoder;
201
202/* Rockbox speciffic: about id3 tags definitions delete. */
203#endif /* TTADEC_H_ */
diff --git a/apps/codecs/libtta/ttalib.h b/apps/codecs/libtta/ttalib.h
new file mode 100644
index 0000000000..861c119cd4
--- /dev/null
+++ b/apps/codecs/libtta/ttalib.h
@@ -0,0 +1,157 @@
1/*
2 * ttalib.h
3 *
4 * Description: TTAv1 player library prototypes
5 * Developed by: Alexander Djourik <ald@true-audio.com>
6 * Pavel Zhilin <pzh@true-audio.com>
7 *
8 * Copyright (c) 2004 True Audio Software. All rights reserved.
9 *
10 */
11
12/*
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. Neither the name of the True Audio Software nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#ifndef TTALIB_H_
40#define TTALIB_H_
41
42#define MAX_BPS 24 /* Max supported Bit resolution */
43#define MAX_NCH 2 /* Max supported number of channels (Rockbox changes: 8 -> 2) */
44
45#ifndef MAXLINE
46#define MAX_LINE 1024
47#endif
48
49/* decoded pcm sample depth (sample 28bit + sign 1bit) */
50#define TTA_OUTPUT_DEPTH 29
51
52/* return codes */
53#define NO_ERROR 0 /* No errors found */
54#define OPEN_ERROR 1 /* Can't open file */
55#define FORMAT_ERROR 2 /* Unknown TTA format version */
56#define PLAYER_ERROR 3 /* Not supported file format */
57#define FILE_ERROR 4 /* File is corrupted */
58#define READ_ERROR 5 /* Can't read from file */
59#define MEMORY_ERROR 6 /* Insufficient memory available */
60
61/* Rockbox speciffic: does not use FRAME_TIME */
62/* #define FRAME_TIME 1.04489795918367346939 */
63#define MULTIPLY_FRAME_TIME(x) (256 * (x) / 245) /* = FRAME_TIME * x */
64#define SEEK_STEP (int)MULTIPLY_FRAME_TIME(1000) /* (FRAME_TIME * 1000) */
65
66#define ISO_BUFFER_LENGTH (1024*32)
67#define ISO_NBUFFERS (8)
68#define ISO_BUFFERS_SIZE (4096) /* (ISO_BUFFER_LENGTH*ISO_NBUFFERS) */
69#define PCM_BUFFER_LENGTH (4608)
70#define MAX_SEEK_TABLE_SIZE (4096)
71
72typedef struct {
73 /* FILE *HANDLE; // file handle (Rockbox does not use) */
74 unsigned int FILESIZE; /* compressed size */
75 unsigned short NCH; /* number of channels */
76 unsigned short BPS; /* bits per sample */
77 unsigned short BSIZE; /* byte size */
78 unsigned short FORMAT; /* audio format */
79 unsigned int SAMPLERATE; /* samplerate (sps) */
80 unsigned int DATALENGTH; /* data length in samples */
81 unsigned int FRAMELEN; /* frame length */
82 unsigned int LENGTH; /* playback time (sec) */
83 unsigned int STATE; /* return code */
84 unsigned int DATAPOS; /* size of ID3v2 header */
85 unsigned int BITRATE; /* average bitrate (kbps) */
86 /* double COMPRESS; // compression ratio (Rockbox does not use) */
87 /* id3_info ID3; // ID3 information (Rockbox does not use) */
88} tta_info;
89
90enum tta_seek_type
91{
92 TTA_SEEK_TIME,
93 TTA_SEEK_POS,
94};
95
96/*********************** Library functions *************************/
97/* Rockbox speciffic: open_tta_file() does not use */
98
99/* Rockbox speciffic: It is used in place of open_tta_file(). */
100int set_tta_info( // FUNCTION: set tta file info structure
101 tta_info *info); // file info structure
102/*
103 * RETURN VALUE
104 * This function returns 0 if success. Otherwise, -1 is returned
105 * and the variable STATE of the currently using info structure
106 * is set to indicate the error.
107 *
108 */
109
110/* Rockbox speciffic: close_tta_file() does not use */
111
112/* Rockbox speciffic: set_position() change arguments and return value. */
113/*
114 * FUNCTION: sets playback position
115 * pos: seek position
116 * seek_time_ms / SEEK_STEP (when type is TTA_SEEK_TIME)
117 * file position (when type is TTA_SEEK_POS)
118 */
119int set_position (
120 unsigned int pos,
121 enum tta_seek_type type);
122
123/*
124 * RETURN VALUE
125 * This function returns the seeked data position (>= 0) if success. Otherwise, -1 is returned
126 * and the variable STATE of the currently using info structure
127 * is set to indicate the error.
128 *
129 */
130
131int player_init ( // FUNCTION: initializes TTA player
132 tta_info *info); // file info structure
133/*
134 * RETURN VALUE
135 * This function returns 0 if success. Otherwise, -1 is returned
136 * and the variable STATE of the currently using info structure
137 * is set to indicate the error.
138 *
139 */
140
141void player_stop (void); // FUNCTION: destroys memory pools
142
143/* Rockbox speciffic: unsigned char -> int32_t */
144int get_samples ( // FUNCTION: decode PCM_BUFFER_LENGTH samples
145 int32_t *buffer); // into the current PCM buffer position
146
147/*
148 * RETURN VALUE
149 * This function returns the number of samples successfully decoded.
150 * Otherwise, -1 is returned and the variable STATE of the currently
151 * using info structure is set to indicate the error.
152 *
153 */
154
155const char *get_error_str (int error); // FUNCTION: get error description
156
157#endif /* TTALIB_H_ */
diff --git a/apps/codecs/tta.c b/apps/codecs/tta.c
new file mode 100644
index 0000000000..541dc2b7ef
--- /dev/null
+++ b/apps/codecs/tta.c
@@ -0,0 +1,132 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Yoshihisa Uchida
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "codeclib.h"
23#include "codecs/libtta/ttalib.h"
24
25CODEC_HEADER
26
27/*
28 * TTA (True Audio) codec:
29 *
30 * References
31 * [1] TRUE AUDIO CODEC SOFTWARE http://true-audio.com/
32 */
33
34static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR;
35
36/* this is the codec entry point */
37enum codec_status codec_main(void)
38{
39 tta_info info;
40 int status = CODEC_OK;
41 unsigned int decodedsamples = 0;
42 int endofstream;
43 int new_pos = 0;
44 int sample_count;
45
46 /* Generic codec initialisation */
47 ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1);
48
49 if (codec_init())
50 {
51 DEBUGF("codec_init() error\n");
52 status = CODEC_ERROR;
53 goto exit;
54 }
55
56next_track:
57 while (!*ci->taginfo_ready && !ci->stop_codec)
58 ci->sleep(1);
59
60 if (set_tta_info(&info) < 0)
61 {
62 status = CODEC_ERROR;
63 goto exit;
64 }
65 if (player_init(&info) < 0)
66 {
67 status = CODEC_ERROR;
68 goto exit;
69 }
70
71 codec_set_replaygain(ci->id3);
72
73 ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
74 if (info.NCH == 2) {
75 ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
76 } else if (info.NCH == 1) {
77 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
78 } else {
79 DEBUGF("CODEC_ERROR: more than 2 channels\n");
80 status = CODEC_ERROR;
81 goto done;
82 }
83
84 /* The main decoder loop */
85 endofstream = 0;
86
87 if (ci->id3->offset > 0)
88 {
89 /* Need to save offset for later use (cleared indirectly by advance_buffer) */
90 new_pos = set_position(ci->id3->offset, TTA_SEEK_POS);
91 if (new_pos >= 0)
92 decodedsamples = new_pos;
93 ci->seek_complete();
94 }
95
96 while (!endofstream)
97 {
98 ci->yield();
99 if (ci->stop_codec || ci->new_track)
100 break;
101
102 if (ci->seek_time)
103 {
104 new_pos = set_position(ci->seek_time / SEEK_STEP, TTA_SEEK_TIME);
105 if (new_pos >= 0)
106 {
107 decodedsamples = new_pos;
108 ci->seek_complete();
109 }
110 }
111
112 sample_count = get_samples(samples);
113 if (sample_count < 0)
114 {
115 status = CODEC_ERROR;
116 break;
117 }
118 ci->pcmbuf_insert(samples, NULL, sample_count);
119 decodedsamples += sample_count;
120 if (decodedsamples >= info.DATALENGTH)
121 endofstream = 1;
122 ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH);
123 }
124 status = CODEC_OK;
125done:
126 player_stop();
127 if (ci->request_next_track())
128 goto next_track;
129
130exit:
131 return status;
132}
diff --git a/apps/filetypes.c b/apps/filetypes.c
index 6548d46fdb..11b9fa0c0f 100644
--- a/apps/filetypes.c
+++ b/apps/filetypes.c
@@ -105,6 +105,7 @@ static const struct filetype inbuilt_filetypes[] = {
105 { "snd", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, 105 { "snd", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
106 { "vox", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, 106 { "vox", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
107 { "w64", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA }, 107 { "w64", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
108 { "tta", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
108#endif 109#endif
109 { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, 110 { "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
110 { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, 111 { "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
diff --git a/apps/metadata.c b/apps/metadata.c
index 97f376035d..076b753958 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -179,6 +179,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
179 /* Wave64 */ 179 /* Wave64 */
180 [AFMT_WAVE64] = 180 [AFMT_WAVE64] =
181 AFMT_ENTRY("WAVE64", "wav64", NULL, "w64\0" ), 181 AFMT_ENTRY("WAVE64", "wav64", NULL, "w64\0" ),
182 /* True Audio */
183 [AFMT_TTA] =
184 AFMT_ENTRY("TTA", "tta", NULL, "tta\0" ),
182#endif 185#endif
183}; 186};
184 187
@@ -494,6 +497,14 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
494 } 497 }
495 break; 498 break;
496 499
500 case AFMT_TTA:
501 if (!get_tta_metadata(fd, id3))
502 {
503 DEBUGF("get_tta_metadata error\n");
504 return false;
505 }
506 break;
507
497#endif /* CONFIG_CODEC == SWCODEC */ 508#endif /* CONFIG_CODEC == SWCODEC */
498 509
499 default: 510 default:
diff --git a/apps/metadata.h b/apps/metadata.h
index aa59eac2dd..6b15f6dead 100644
--- a/apps/metadata.h
+++ b/apps/metadata.h
@@ -83,6 +83,7 @@ enum
83 AFMT_AU, /* Sun Audio file */ 83 AFMT_AU, /* Sun Audio file */
84 AFMT_VOX, /* VOX */ 84 AFMT_VOX, /* VOX */
85 AFMT_WAVE64, /* Wave64 */ 85 AFMT_WAVE64, /* Wave64 */
86 AFMT_TTA, /* True Audio */
86#endif 87#endif
87 88
88 /* add new formats at any index above this line to have a sensible order - 89 /* add new formats at any index above this line to have a sensible order -
diff --git a/apps/metadata/metadata_parsers.h b/apps/metadata/metadata_parsers.h
index 0e813ccb48..7238b71a30 100644
--- a/apps/metadata/metadata_parsers.h
+++ b/apps/metadata/metadata_parsers.h
@@ -22,6 +22,7 @@
22char* id3_get_num_genre(unsigned int genre_num); 22char* id3_get_num_genre(unsigned int genre_num);
23int getid3v2len(int fd); 23int getid3v2len(int fd);
24bool setid3v1title(int fd, struct mp3entry *entry); 24bool setid3v1title(int fd, struct mp3entry *entry);
25void setid3v2title(int fd, struct mp3entry *entry);
25bool get_mp3_metadata(int fd, struct mp3entry* id3, const char *filename); 26bool get_mp3_metadata(int fd, struct mp3entry* id3, const char *filename);
26 27
27bool get_adx_metadata(int fd, struct mp3entry* id3); 28bool get_adx_metadata(int fd, struct mp3entry* id3);
@@ -46,3 +47,4 @@ bool get_smaf_metadata(int fd, struct mp3entry* id3);
46bool get_au_metadata(int fd, struct mp3entry* id3); 47bool get_au_metadata(int fd, struct mp3entry* id3);
47bool get_vox_metadata(int fd, struct mp3entry* id3); 48bool get_vox_metadata(int fd, struct mp3entry* id3);
48bool get_wave64_metadata(int fd, struct mp3entry* id3); 49bool get_wave64_metadata(int fd, struct mp3entry* id3);
50bool get_tta_metadata(int fd, struct mp3entry* id3);
diff --git a/apps/metadata/mp3.c b/apps/metadata/mp3.c
index 49d5c7362e..0f786bd52b 100644
--- a/apps/metadata/mp3.c
+++ b/apps/metadata/mp3.c
@@ -640,7 +640,7 @@ bool setid3v1title(int fd, struct mp3entry *entry)
640 * 640 *
641 * Returns: true if a title was found and created, else false 641 * Returns: true if a title was found and created, else false
642 */ 642 */
643static void setid3v2title(int fd, struct mp3entry *entry) 643void setid3v2title(int fd, struct mp3entry *entry)
644{ 644{
645 int minframesize; 645 int minframesize;
646 int size; 646 int size;
diff --git a/apps/metadata/tta.c b/apps/metadata/tta.c
new file mode 100644
index 0000000000..1d3d95f118
--- /dev/null
+++ b/apps/metadata/tta.c
@@ -0,0 +1,123 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Yoshihisa Uchida
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <inttypes.h>
26
27#include "system.h"
28#include "metadata.h"
29#include "metadata_common.h"
30#include "metadata_parsers.h"
31#include "logf.h"
32
33#define TTA1_SIGN 0x31415454
34
35#define TTA_HEADER_ID 0
36#define TTA_HEADER_AUDIO_FORMAT (TTA_HEADER_ID + sizeof(unsigned int))
37#define TTA_HEADER_NUM_CHANNELS (TTA_HEADER_AUDIO_FORMAT + sizeof(unsigned short))
38#define TTA_HEADER_BITS_PER_SAMPLE (TTA_HEADER_NUM_CHANNELS + sizeof(unsigned short))
39#define TTA_HEADER_SAMPLE_RATE (TTA_HEADER_BITS_PER_SAMPLE + sizeof(unsigned short))
40#define TTA_HEADER_DATA_LENGTH (TTA_HEADER_SAMPLE_RATE + sizeof(unsigned int))
41#define TTA_HEADER_CRC32 (TTA_HEADER_DATA_LENGTH + sizeof(unsigned int))
42#define TTA_HEADER_SIZE (TTA_HEADER_CRC32 + sizeof(unsigned int))
43
44#define TTA_HEADER_GETTER_ID(x) get_long_le(x)
45#define TTA_HEADER_GETTER_AUDIO_FORMAT(x) get_short_le(x)
46#define TTA_HEADER_GETTER_NUM_CHANNELS(x) get_short_le(x)
47#define TTA_HEADER_GETTER_BITS_PER_SAMPLE(x) get_short_le(x)
48#define TTA_HEADER_GETTER_SAMPLE_RATE(x) get_long_le(x)
49#define TTA_HEADER_GETTER_DATA_LENGTH(x) get_long_le(x)
50#define TTA_HEADER_GETTER_CRC32(x) get_long_le(x)
51
52#define GET_HEADER(x, tag) TTA_HEADER_GETTER_ ## tag((x) + TTA_HEADER_ ## tag)
53
54static void read_id3_tags(int fd, struct mp3entry* id3)
55{
56 id3->title = NULL;
57 id3->filesize = filesize(fd);
58 id3->id3v2len = getid3v2len(fd);
59 id3->tracknum = 0;
60 id3->discnum = 0;
61 id3->vbr = false; /* All TTA files are CBR */
62
63 /* first get id3v2 tags. if no id3v2 tags ware found, get id3v1 tags */
64 if (id3->id3v2len)
65 {
66 setid3v2title(fd, id3);
67 id3->first_frame_offset = id3->id3v2len;
68 return;
69 }
70 setid3v1title(fd, id3);
71}
72
73bool get_tta_metadata(int fd, struct mp3entry* id3)
74{
75 unsigned char ttahdr[TTA_HEADER_SIZE];
76 unsigned int datasize;
77 unsigned int origsize;
78 int bps;
79
80 lseek(fd, 0, SEEK_SET);
81
82 /* read id3 tags */
83 read_id3_tags(fd, id3);
84 lseek(fd, id3->id3v2len, SEEK_SET);
85
86 /* read TTA header */
87 if (read(fd, ttahdr, TTA_HEADER_SIZE) < 0)
88 return false;
89
90 /* check for TTA3 signature */
91 if ((GET_HEADER(ttahdr, ID)) != TTA1_SIGN)
92 return false;
93
94 /* skip check CRC */
95
96 id3->channels = (GET_HEADER(ttahdr, NUM_CHANNELS));
97 id3->frequency = (GET_HEADER(ttahdr, SAMPLE_RATE));
98 id3->length = ((GET_HEADER(ttahdr, DATA_LENGTH)) / id3->frequency) * 1000LL;
99 bps = (GET_HEADER(ttahdr, BITS_PER_SAMPLE));
100
101 datasize = id3->filesize - id3->first_frame_offset;
102 origsize = (GET_HEADER(ttahdr, DATA_LENGTH)) * ((bps + 7) / 8) * id3->channels;
103
104 id3->bitrate = (int) ((uint64_t) datasize * id3->frequency * id3->channels * bps
105 / (origsize * 1000LL));
106
107 /* output header info (for debug) */
108 DEBUGF("TTA header info ----\n");
109 DEBUGF("id: %x\n", (unsigned int)(GET_HEADER(ttahdr, ID)));
110 DEBUGF("channels: %d\n", id3->channels);
111 DEBUGF("frequency: %ld\n", id3->frequency);
112 DEBUGF("length: %ld\n", id3->length);
113 DEBUGF("bitrate: %d\n", id3->bitrate);
114 DEBUGF("bits per sample: %d\n", bps);
115 DEBUGF("compressed size: %d\n", datasize);
116 DEBUGF("original size: %d\n", origsize);
117 DEBUGF("id3----\n");
118 DEBUGF("artist: %s\n", id3->artist);
119 DEBUGF("title: %s\n", id3->title);
120 DEBUGF("genre: %s\n", id3->genre_string);
121
122 return true;
123}