diff options
author | Dave Chapman <dave@dchapman.com> | 2007-06-05 16:58:29 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2007-06-05 16:58:29 +0000 |
commit | 520274219a0745384cb9bc6df4d7ee7905090f5d (patch) | |
tree | 8d6f4536b6758d00e72a2a9457f892ce28a591bd /apps/codecs/demac/libdemac/predictor.c | |
parent | 887b31c01aebb46c0fcc6910241a4a64d9e7991e (diff) | |
download | rockbox-520274219a0745384cb9bc6df4d7ee7905090f5d.tar.gz rockbox-520274219a0745384cb9bc6df4d7ee7905090f5d.zip |
Initial commit of Monkey's Audio (.ape/.mac) support. Note that Monkey's is an extremely CPU-intensive codec, and that the decoding speed is directly related to the compression level (-c1000, -c2000, -c3000, -c4000 or -c5000) used when encoding the file. Current performance is: -c1000 to -c3000 are realtime on a Gigabeat, -c1000 is realtime on Coldfire targets (H100, H300 and Cowon), and nothing is realtime on PortalPlayer targets (iPods, H10, Sansa). Hopefully this can be improved. More information at FS #7256.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13562 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/demac/libdemac/predictor.c')
-rw-r--r-- | apps/codecs/demac/libdemac/predictor.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/apps/codecs/demac/libdemac/predictor.c b/apps/codecs/demac/libdemac/predictor.c new file mode 100644 index 0000000000..ef72fedfbd --- /dev/null +++ b/apps/codecs/demac/libdemac/predictor.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | |||
3 | libdemac - A Monkey's Audio decoder | ||
4 | |||
5 | $Id:$ | ||
6 | |||
7 | Copyright (C) Dave Chapman 2007 | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA | ||
22 | |||
23 | */ | ||
24 | |||
25 | #include <inttypes.h> | ||
26 | #include <string.h> | ||
27 | |||
28 | #include "parser.h" | ||
29 | #include "predictor.h" | ||
30 | |||
31 | #include "vector_math32.h" | ||
32 | |||
33 | /* Return 0 if x is zero, -1 if x is positive, 1 if x is negative */ | ||
34 | #define SIGN(x) (x) ? (((x) > 0) ? -1 : 1) : 0 | ||
35 | |||
36 | static const int32_t initial_coeffs[4] = { | ||
37 | 360, 317, -109, 98 | ||
38 | }; | ||
39 | |||
40 | static void init_predictor(struct predictor_t* p) | ||
41 | { | ||
42 | /* Zero the history buffers */ | ||
43 | memset(p->historybuffer, 0, (PREDICTOR_ORDER*4) * sizeof(int32_t)); | ||
44 | p->delayA = p->historybuffer + PREDICTOR_ORDER*4; | ||
45 | p->delayB = p->historybuffer + PREDICTOR_ORDER*3; | ||
46 | p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2; | ||
47 | p->adaptcoeffsB = p->historybuffer + PREDICTOR_ORDER; | ||
48 | |||
49 | /* Initialise and zero the co-efficients */ | ||
50 | memcpy(p->coeffsA, initial_coeffs, sizeof(initial_coeffs)); | ||
51 | memset(p->coeffsB, 0, sizeof(p->coeffsB)); | ||
52 | |||
53 | p->filterA = 0; | ||
54 | p->filterB = 0; | ||
55 | |||
56 | p->lastA = 0; | ||
57 | } | ||
58 | |||
59 | static int do_predictor_decode(struct predictor_t* p, int32_t A, int32_t B) | ||
60 | { | ||
61 | int32_t predictionA, predictionB, currentA; | ||
62 | |||
63 | p->delayA[0] = p->lastA; | ||
64 | p->delayA[-1] = p->delayA[0] - p->delayA[-1]; | ||
65 | |||
66 | predictionA = scalarproduct4_rev32(p->coeffsA,p->delayA); | ||
67 | |||
68 | /* Apply a scaled first-order filter compression */ | ||
69 | p->delayB[0] = B - ((p->filterB * 31) >> 5); | ||
70 | p->filterB = B; | ||
71 | |||
72 | p->delayB[-1] = p->delayB[0] - p->delayB[-1]; | ||
73 | |||
74 | predictionB = scalarproduct5_rev32(p->coeffsB,p->delayB); | ||
75 | |||
76 | currentA = A + ((predictionA + (predictionB >> 1)) >> 10); | ||
77 | |||
78 | p->adaptcoeffsA[0] = SIGN(p->delayA[0]); | ||
79 | p->adaptcoeffsA[-1] = SIGN(p->delayA[-1]); | ||
80 | |||
81 | p->adaptcoeffsB[0] = SIGN(p->delayB[0]); | ||
82 | p->adaptcoeffsB[-1] = SIGN(p->delayB[-1]); | ||
83 | |||
84 | if (A > 0) | ||
85 | { | ||
86 | vector_sub4_rev32(p->coeffsA, p->adaptcoeffsA); | ||
87 | vector_sub5_rev32(p->coeffsB, p->adaptcoeffsB); | ||
88 | } | ||
89 | else if (A < 0) | ||
90 | { | ||
91 | vector_add4_rev32(p->coeffsA, p->adaptcoeffsA); | ||
92 | vector_add5_rev32(p->coeffsB, p->adaptcoeffsB); | ||
93 | } | ||
94 | |||
95 | p->delayA++; | ||
96 | p->delayB++; | ||
97 | p->adaptcoeffsA++; | ||
98 | p->adaptcoeffsB++; | ||
99 | |||
100 | /* Have we filled the history buffer? */ | ||
101 | if (p->delayA == p->historybuffer + HISTORY_SIZE + (PREDICTOR_ORDER*4)) { | ||
102 | memmove(p->historybuffer, p->delayA - (PREDICTOR_ORDER*4), | ||
103 | (PREDICTOR_ORDER*4) * sizeof(int32_t)); | ||
104 | p->delayA = p->historybuffer + PREDICTOR_ORDER*4; | ||
105 | p->delayB = p->historybuffer + PREDICTOR_ORDER*3; | ||
106 | p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2; | ||
107 | p->adaptcoeffsB = p->historybuffer + PREDICTOR_ORDER; | ||
108 | } | ||
109 | |||
110 | p->lastA = currentA; | ||
111 | p->filterA = currentA + ((p->filterA * 31) >> 5); | ||
112 | |||
113 | return p->filterA; | ||
114 | } | ||
115 | |||
116 | static int32_t X; | ||
117 | |||
118 | void init_predictor_decoder(struct ape_ctx_t* ape_ctx) | ||
119 | { | ||
120 | X = 0; | ||
121 | |||
122 | init_predictor(&ape_ctx->predictorY); | ||
123 | init_predictor(&ape_ctx->predictorX); | ||
124 | } | ||
125 | |||
126 | int predictor_decode_stereo(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int32_t* decoded1, int count) ICODE_ATTR; | ||
127 | int predictor_decode_stereo(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int32_t* decoded1, int count) | ||
128 | { | ||
129 | while (count--) | ||
130 | { | ||
131 | *decoded0 = do_predictor_decode(&ape_ctx->predictorY, *decoded0, X); | ||
132 | X = do_predictor_decode(&ape_ctx->predictorX, *decoded1, *(decoded0)++); | ||
133 | *(decoded1++) = X; | ||
134 | } | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | int predictor_decode_mono(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int count) | ||
140 | { | ||
141 | struct predictor_t* p = &ape_ctx->predictorY; | ||
142 | int32_t predictionA, currentA, A; | ||
143 | |||
144 | currentA = p->lastA; | ||
145 | |||
146 | while (count--) | ||
147 | { | ||
148 | A = *decoded0; | ||
149 | |||
150 | p->delayA[0] = currentA; | ||
151 | p->delayA[-1] = p->delayA[0] - p->delayA[-1]; | ||
152 | |||
153 | predictionA = (p->delayA[0] * p->coeffsA[0]) + | ||
154 | (p->delayA[-1] * p->coeffsA[1]) + | ||
155 | (p->delayA[-2] * p->coeffsA[2]) + | ||
156 | (p->delayA[-3] * p->coeffsA[3]); | ||
157 | |||
158 | currentA = A + (predictionA >> 10); | ||
159 | |||
160 | p->adaptcoeffsA[0] = SIGN(p->delayA[0]); | ||
161 | p->adaptcoeffsA[-1] = SIGN(p->delayA[-1]); | ||
162 | |||
163 | if (A > 0) | ||
164 | { | ||
165 | p->coeffsA[0] -= p->adaptcoeffsA[0]; | ||
166 | p->coeffsA[1] -= p->adaptcoeffsA[-1]; | ||
167 | p->coeffsA[2] -= p->adaptcoeffsA[-2]; | ||
168 | p->coeffsA[3] -= p->adaptcoeffsA[-3]; | ||
169 | } | ||
170 | else if (A < 0) | ||
171 | { | ||
172 | p->coeffsA[0] += p->adaptcoeffsA[0]; | ||
173 | p->coeffsA[1] += p->adaptcoeffsA[-1]; | ||
174 | p->coeffsA[2] += p->adaptcoeffsA[-2]; | ||
175 | p->coeffsA[3] += p->adaptcoeffsA[-3]; | ||
176 | } | ||
177 | |||
178 | p->delayA++; | ||
179 | p->adaptcoeffsA++; | ||
180 | |||
181 | /* Have we filled the history buffer? */ | ||
182 | if (p->delayA == p->historybuffer + HISTORY_SIZE + (PREDICTOR_ORDER*4)) { | ||
183 | memmove(p->historybuffer, p->delayA - (PREDICTOR_ORDER*4), | ||
184 | (PREDICTOR_ORDER*4) * sizeof(int32_t)); | ||
185 | p->delayA = p->historybuffer + PREDICTOR_ORDER*4; | ||
186 | p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2; | ||
187 | } | ||
188 | |||
189 | p->filterA = currentA + ((p->filterA * 31) >> 5); | ||
190 | *(decoded0++) = p->filterA; | ||
191 | } | ||
192 | |||
193 | p->lastA = currentA; | ||
194 | |||
195 | return 0; | ||
196 | } | ||