diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-05-13 12:40:09 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-05-13 12:40:09 +0000 |
commit | 0f5c6d47d4fdd17260b840024880ba6dd3fdf935 (patch) | |
tree | 6d2526a58816aa9f6431a22a8f1a56278a445dfd /apps | |
parent | 889b4a8ce838bd4191c736d01d9665c177e6d390 (diff) | |
download | rockbox-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
Diffstat (limited to 'apps')
-rw-r--r-- | apps/SOURCES | 1 | ||||
-rw-r--r-- | apps/codecs/SOURCES | 1 | ||||
-rw-r--r-- | apps/codecs/codecs.make | 2 | ||||
-rw-r--r-- | apps/codecs/libtta/README | 72 | ||||
-rw-r--r-- | apps/codecs/libtta/README.rockbox | 34 | ||||
-rw-r--r-- | apps/codecs/libtta/SOURCES | 4 | ||||
-rw-r--r-- | apps/codecs/libtta/filter.h | 136 | ||||
-rw-r--r-- | apps/codecs/libtta/filter_arm.S | 203 | ||||
-rw-r--r-- | apps/codecs/libtta/libtta.make | 29 | ||||
-rw-r--r-- | apps/codecs/libtta/ttadec.c | 576 | ||||
-rw-r--r-- | apps/codecs/libtta/ttadec.h | 203 | ||||
-rw-r--r-- | apps/codecs/libtta/ttalib.h | 157 | ||||
-rw-r--r-- | apps/codecs/tta.c | 132 | ||||
-rw-r--r-- | apps/filetypes.c | 1 | ||||
-rw-r--r-- | apps/metadata.c | 11 | ||||
-rw-r--r-- | apps/metadata.h | 1 | ||||
-rw-r--r-- | apps/metadata/metadata_parsers.h | 2 | ||||
-rw-r--r-- | apps/metadata/mp3.c | 2 | ||||
-rw-r--r-- | apps/metadata/tta.c | 123 |
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 | |||
197 | metadata/smaf.c | 197 | metadata/smaf.c |
198 | metadata/au.c | 198 | metadata/au.c |
199 | metadata/vox.c | 199 | metadata/vox.c |
200 | metadata/tta.c | ||
200 | #endif | 201 | #endif |
201 | #ifdef HAVE_TAGCACHE | 202 | #ifdef HAVE_TAGCACHE |
202 | tagcache.c | 203 | tagcache.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 | |||
32 | au.c | 32 | au.c |
33 | vox.c | 33 | vox.c |
34 | wav64.c | 34 | wav64.c |
35 | tta.c | ||
35 | #if defined(HAVE_RECORDING) && !defined(SIMULATOR) | 36 | #if defined(HAVE_RECORDING) && !defined(SIMULATOR) |
36 | /* encoders */ | 37 | /* encoders */ |
37 | aiff_enc.c | 38 | aiff_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 | |||
41 | include $(APPSDIR)/codecs/librm/librm.make | 41 | include $(APPSDIR)/codecs/librm/librm.make |
42 | include $(APPSDIR)/codecs/libatrac/libatrac.make | 42 | include $(APPSDIR)/codecs/libatrac/libatrac.make |
43 | include $(APPSDIR)/codecs/libpcm/libpcm.make | 43 | include $(APPSDIR)/codecs/libpcm/libpcm.make |
44 | include $(APPSDIR)/codecs/libtta/libtta.make | ||
44 | 45 | ||
45 | # compile flags for codecs | 46 | # compile flags for codecs |
46 | CODECFLAGS = $(filter-out -fno-strict-aliasing,$(CFLAGS)) -fstrict-aliasing \ | 47 | CODECFLAGS = $(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 @@ | |||
1 | TTA Hardware Players Library | ||
2 | ============================ | ||
3 | |||
4 | Version 1.2, (c) 2004 Alexander Djourik. All rights reserved. | ||
5 | |||
6 | * Introduction | ||
7 | |||
8 | This library provides to decode a multichannel 8,16 and 24 | ||
9 | bits 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. | ||
12 | The compression ratios of TTA depend on the type of music file | ||
13 | being compressed, but the compression size will generally range | ||
14 | between 30% - 70% of the original. | ||
15 | |||
16 | TTA format supports both of ID3v1/v2 tags. Detailed format | ||
17 | description is available at http://www.true-audio.com. | ||
18 | |||
19 | The decoder process has a minimal system requirements and does | ||
20 | not required to create a big additional memory pools. As the | ||
21 | TTA algorithms has a same system requirements both for decoding | ||
22 | and for encoding processes - the TTA recorder can be easily | ||
23 | realized 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 | |||
44 | Redistribution and use in source and binary forms, with or without | ||
45 | modification, are permitted provided that the following conditions | ||
46 | are met: | ||
47 | |||
48 | 1. Redistributions of source code must retain the above copyright | ||
49 | notice, this list of conditions and the following disclaimer. | ||
50 | 2. 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. | ||
53 | 3. 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 | |||
57 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
58 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
59 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
60 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
61 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
62 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
63 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
64 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
65 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
66 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
67 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
68 | |||
69 | * See also | ||
70 | |||
71 | Please visit the TTA homepage at http://tta.sourceforge.net for the | ||
72 | latest 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 @@ | |||
1 | Library: True Audio | ||
2 | Imported by : Yoshihisa Uchida | ||
3 | Import date : 2010-03-05 | ||
4 | Baseed by : TTA library version 1.2 for hardware players (ttalib-hwplayer-1.2.tgz) | ||
5 | from http://true-audio.com/Free_Downloads | ||
6 | |||
7 | This directory contains a decoder version of True Auido. | ||
8 | |||
9 | LICENSING INFORMATION | ||
10 | |||
11 | True Audio license is described in the README file or each source file (excepts filter_arm.S) | ||
12 | in this directory. | ||
13 | |||
14 | Limitation | ||
15 | |||
16 | In some players, the decoding speed is not enough ( < 110%). | ||
17 | (For example, H180: decoding speed < 60%) | ||
18 | |||
19 | IMPORT DETAILS | ||
20 | |||
21 | The .[ch] files from ttalib-hwplayer-1.2.tgz were imported into Rockbox. | ||
22 | But the following files do not include. | ||
23 | Makefile | ||
24 | tta.vcproj | ||
25 | samples/* | ||
26 | |||
27 | |||
28 | When source files import in Rockbox, I changed below. | ||
29 | |||
30 | all files | ||
31 | - TAB => 4 spaces. | ||
32 | - // style comments changes to /* */ style. | ||
33 | |||
34 | Moreover, 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 @@ | |||
1 | ttadec.c | ||
2 | #ifdef CPU_ARM | ||
3 | filter_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 ////////// | ||
43 | static int flt_set[3] = {10, 9, 10}; | ||
44 | |||
45 | #ifdef CPU_ARM | ||
46 | int hybrid_filter(fltst *fs, int *in); /* implements in filter_arm.S */ | ||
47 | |||
48 | #else | ||
49 | |||
50 | static inline void | ||
51 | memshl (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 | |||
64 | static inline void | ||
65 | hybrid_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 | |||
128 | static inline void | ||
129 | filter_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 | |||
38 | hybrid_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 | |||
202 | hybrid_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 | ||
11 | TTALIB := $(CODECDIR)/libtta.a | ||
12 | TTALIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libtta/SOURCES) | ||
13 | TTALIB_OBJ := $(call c2obj, $(TTALIB_SRC)) | ||
14 | OTHER_SRC += $(TTALIB_SRC) | ||
15 | |||
16 | $(TTALIB): $(TTALIB_OBJ) | ||
17 | $(SILENT)$(shell rm -f $@) | ||
18 | $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null | ||
19 | |||
20 | TTAFLAGS = $(filter-out -O%,$(CODECFLAGS)) | ||
21 | TTAFLAGS += -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 | |||
47 | static unsigned char isobuffers[ISO_BUFFERS_SIZE + 4] IBSS_ATTR; | ||
48 | static unsigned char *iso_buffers_end = isobuffers + ISO_BUFFERS_SIZE; | ||
49 | static unsigned int pcm_buffer_size; | ||
50 | |||
51 | static 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 | |||
55 | tta_info *ttainfo; /* currently playing file info */ | ||
56 | |||
57 | static unsigned int fframes; /* number of frames in file */ | ||
58 | static unsigned int framelen; /* the frame length in samples */ | ||
59 | static unsigned int lastlen; /* the length of the last frame in samples */ | ||
60 | static unsigned int data_pos; /* currently playing frame index */ | ||
61 | static unsigned int data_cur; /* the playing position in frame */ | ||
62 | |||
63 | static int maxvalue; /* output data max value */ | ||
64 | |||
65 | /* Rockbox speciffic: seek_table is static size */ | ||
66 | static unsigned int seek_table[MAX_SEEK_TABLE_SIZE]; /* the playing position table */ | ||
67 | static unsigned int st_state; /* seek table status */ | ||
68 | |||
69 | static unsigned int frame_crc32; | ||
70 | static unsigned int bit_count; | ||
71 | static unsigned int bit_cache; | ||
72 | static 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 */ | ||
80 | static 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 | |||
93 | static 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 | |||
117 | static unsigned int | ||
118 | crc32 (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 | |||
173 | static 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 | |||
196 | static void init_buffer_read(void) { | ||
197 | frame_crc32 = 0xFFFFFFFFUL; | ||
198 | bit_count = bit_cache = 0; | ||
199 | bitpos = iso_buffers_end; | ||
200 | } | ||
201 | |||
202 | static 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 | |||
229 | const 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 | |||
241 | int 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 | |||
323 | static 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 | |||
330 | static 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 | |||
341 | static 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 | |||
352 | int 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 | |||
390 | int 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 | */ | ||
446 | void 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 | */ | ||
459 | int 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 | |||
51 | typedef unsigned long long uint64; | ||
52 | |||
53 | static 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 | |||
120 | static 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 | |||
132 | static 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 | |||
145 | static const unsigned int *shift_16 = bit_shift + 4; | ||
146 | |||
147 | typedef 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 | |||
168 | typedef 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 | |||
178 | typedef struct { | ||
179 | unsigned int k0; | ||
180 | unsigned int k1; | ||
181 | unsigned int sum0; | ||
182 | unsigned int sum1; | ||
183 | } adapt; | ||
184 | |||
185 | typedef 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 | |||
196 | typedef 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 | |||
72 | typedef 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 | |||
90 | enum 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(). */ | ||
100 | int 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 | */ | ||
119 | int 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 | |||
131 | int 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 | |||
141 | void player_stop (void); // FUNCTION: destroys memory pools | ||
142 | |||
143 | /* Rockbox speciffic: unsigned char -> int32_t */ | ||
144 | int 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 | |||
155 | const 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 | |||
25 | CODEC_HEADER | ||
26 | |||
27 | /* | ||
28 | * TTA (True Audio) codec: | ||
29 | * | ||
30 | * References | ||
31 | * [1] TRUE AUDIO CODEC SOFTWARE http://true-audio.com/ | ||
32 | */ | ||
33 | |||
34 | static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR; | ||
35 | |||
36 | /* this is the codec entry point */ | ||
37 | enum 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 | |||
56 | next_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; | ||
125 | done: | ||
126 | player_stop(); | ||
127 | if (ci->request_next_track()) | ||
128 | goto next_track; | ||
129 | |||
130 | exit: | ||
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 @@ | |||
22 | char* id3_get_num_genre(unsigned int genre_num); | 22 | char* id3_get_num_genre(unsigned int genre_num); |
23 | int getid3v2len(int fd); | 23 | int getid3v2len(int fd); |
24 | bool setid3v1title(int fd, struct mp3entry *entry); | 24 | bool setid3v1title(int fd, struct mp3entry *entry); |
25 | void setid3v2title(int fd, struct mp3entry *entry); | ||
25 | bool get_mp3_metadata(int fd, struct mp3entry* id3, const char *filename); | 26 | bool get_mp3_metadata(int fd, struct mp3entry* id3, const char *filename); |
26 | 27 | ||
27 | bool get_adx_metadata(int fd, struct mp3entry* id3); | 28 | bool get_adx_metadata(int fd, struct mp3entry* id3); |
@@ -46,3 +47,4 @@ bool get_smaf_metadata(int fd, struct mp3entry* id3); | |||
46 | bool get_au_metadata(int fd, struct mp3entry* id3); | 47 | bool get_au_metadata(int fd, struct mp3entry* id3); |
47 | bool get_vox_metadata(int fd, struct mp3entry* id3); | 48 | bool get_vox_metadata(int fd, struct mp3entry* id3); |
48 | bool get_wave64_metadata(int fd, struct mp3entry* id3); | 49 | bool get_wave64_metadata(int fd, struct mp3entry* id3); |
50 | bool 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 | */ |
643 | static void setid3v2title(int fd, struct mp3entry *entry) | 643 | void 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 | |||
54 | static 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 | |||
73 | bool 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 | } | ||