cannam@125
|
1 /*
|
cannam@125
|
2 * Copyright (c) 2011 Apple Inc. All rights reserved.
|
cannam@125
|
3 *
|
cannam@125
|
4 * @APPLE_APACHE_LICENSE_HEADER_START@
|
cannam@125
|
5 *
|
cannam@125
|
6 * Licensed under the Apache License, Version 2.0 (the "License") ;
|
cannam@125
|
7 * you may not use this file except in compliance with the License.
|
cannam@125
|
8 * You may obtain a copy of the License at
|
cannam@125
|
9 *
|
cannam@125
|
10 * http://www.apache.org/licenses/LICENSE-2.0
|
cannam@125
|
11 *
|
cannam@125
|
12 * Unless required by applicable law or agreed to in writing, software
|
cannam@125
|
13 * distributed under the License is distributed on an "AS IS" BASIS,
|
cannam@125
|
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
cannam@125
|
15 * See the License for the specific language governing permissions and
|
cannam@125
|
16 * limitations under the License.
|
cannam@125
|
17 *
|
cannam@125
|
18 * @APPLE_APACHE_LICENSE_HEADER_END@
|
cannam@125
|
19 */
|
cannam@125
|
20
|
cannam@125
|
21 /*
|
cannam@125
|
22 File: dp_dec.c
|
cannam@125
|
23
|
cannam@125
|
24 Contains: Dynamic Predictor decode routines
|
cannam@125
|
25
|
cannam@125
|
26 Copyright: (c) 2001-2011 Apple, Inc.
|
cannam@125
|
27 */
|
cannam@125
|
28
|
cannam@125
|
29
|
cannam@125
|
30 #include <string.h>
|
cannam@125
|
31
|
cannam@125
|
32 #include "dplib.h"
|
cannam@125
|
33 #include "shift.h"
|
cannam@125
|
34
|
cannam@125
|
35 #if __GNUC__
|
cannam@125
|
36 #define ALWAYS_INLINE __attribute__ ((always_inline))
|
cannam@125
|
37 #else
|
cannam@125
|
38 #define ALWAYS_INLINE
|
cannam@125
|
39 #endif
|
cannam@125
|
40
|
cannam@125
|
41 #define LOOP_ALIGN
|
cannam@125
|
42
|
cannam@125
|
43 static inline int32_t ALWAYS_INLINE
|
cannam@125
|
44 sign_of_int (int32_t i)
|
cannam@125
|
45 {
|
cannam@125
|
46 int32_t negishift ;
|
cannam@125
|
47
|
cannam@125
|
48 negishift = ((uint32_t) - i) >> 31 ;
|
cannam@125
|
49 return negishift | (i >> 31) ;
|
cannam@125
|
50 }
|
cannam@125
|
51
|
cannam@125
|
52 void
|
cannam@125
|
53 unpc_block (const int32_t * pc1, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift)
|
cannam@125
|
54 {
|
cannam@125
|
55 register int16_t a0, a1, a2, a3 ;
|
cannam@125
|
56 register int32_t b0, b1, b2, b3 ;
|
cannam@125
|
57 int32_t j, k, lim ;
|
cannam@125
|
58 int32_t sum1, sg, sgn, top, dd ;
|
cannam@125
|
59 int32_t * pout ;
|
cannam@125
|
60 int32_t del, del0 ;
|
cannam@125
|
61 uint32_t chanshift = 32 - chanbits ;
|
cannam@125
|
62 int32_t denhalf = 1 << (denshift - 1) ;
|
cannam@125
|
63
|
cannam@125
|
64 out [0] = pc1 [0] ;
|
cannam@125
|
65 if (numactive == 0)
|
cannam@125
|
66 {
|
cannam@125
|
67 // just copy if numactive == 0 (but don't bother if in/out pointers the same)
|
cannam@125
|
68 if ((num > 1) && (pc1 != out))
|
cannam@125
|
69 memcpy (&out [1], &pc1 [1], (num - 1) * sizeof (int32_t)) ;
|
cannam@125
|
70 return ;
|
cannam@125
|
71 }
|
cannam@125
|
72 if (numactive == 31)
|
cannam@125
|
73 {
|
cannam@125
|
74 // short-circuit if numactive == 31
|
cannam@125
|
75 int32_t prev ;
|
cannam@125
|
76
|
cannam@125
|
77 /* this code is written such that the in/out buffers can be the same
|
cannam@125
|
78 to conserve buffer space on embedded devices like the iPod
|
cannam@125
|
79
|
cannam@125
|
80 (original code)
|
cannam@125
|
81 for (j = 1 ; j < num ; j++)
|
cannam@125
|
82 del = pc1 [j] + out [j-1] ;
|
cannam@125
|
83 out [j] = (del << chanshift) >> chanshift ;
|
cannam@125
|
84 */
|
cannam@125
|
85 prev = out [0] ;
|
cannam@125
|
86 for (j = 1 ; j < num ; j++)
|
cannam@125
|
87 {
|
cannam@125
|
88 del = pc1 [j] + prev ;
|
cannam@125
|
89 prev = (del << chanshift) >> chanshift ;
|
cannam@125
|
90 out [j] = prev ;
|
cannam@125
|
91 }
|
cannam@125
|
92 return ;
|
cannam@125
|
93 }
|
cannam@125
|
94
|
cannam@125
|
95 for (j = 1 ; j <= numactive ; j++)
|
cannam@125
|
96 {
|
cannam@125
|
97 del = pc1 [j] + out [j-1] ;
|
cannam@125
|
98 out [j] = arith_shift_left (del, chanshift) >> chanshift ;
|
cannam@125
|
99 }
|
cannam@125
|
100
|
cannam@125
|
101 lim = numactive + 1 ;
|
cannam@125
|
102
|
cannam@125
|
103 if (numactive == 4)
|
cannam@125
|
104 {
|
cannam@125
|
105 // optimization for numactive == 4
|
cannam@125
|
106 register int16_t ia0, ia1, ia2, ia3 ;
|
cannam@125
|
107 register int32_t ib0, ib1, ib2, ib3 ;
|
cannam@125
|
108
|
cannam@125
|
109 ia0 = coefs [0] ;
|
cannam@125
|
110 ia1 = coefs [1] ;
|
cannam@125
|
111 ia2 = coefs [2] ;
|
cannam@125
|
112 ia3 = coefs [3] ;
|
cannam@125
|
113
|
cannam@125
|
114 for (j = lim ; j < num ; j++)
|
cannam@125
|
115 {
|
cannam@125
|
116 LOOP_ALIGN
|
cannam@125
|
117
|
cannam@125
|
118 top = out [j - lim] ;
|
cannam@125
|
119 pout = out + j - 1 ;
|
cannam@125
|
120
|
cannam@125
|
121 ib0 = top - pout [0] ;
|
cannam@125
|
122 ib1 = top - pout [-1] ;
|
cannam@125
|
123 ib2 = top - pout [-2] ;
|
cannam@125
|
124 ib3 = top - pout [-3] ;
|
cannam@125
|
125
|
cannam@125
|
126 sum1 = (denhalf - ia0 * ib0 - ia1 * ib1 - ia2 * ib2 - ia3 * ib3) >> denshift ;
|
cannam@125
|
127
|
cannam@125
|
128 del = pc1 [j] ;
|
cannam@125
|
129 del0 = del ;
|
cannam@125
|
130 sg = sign_of_int (del) ;
|
cannam@125
|
131 del += top + sum1 ;
|
cannam@125
|
132
|
cannam@125
|
133 out [j] = arith_shift_left (del, chanshift) >> chanshift ;
|
cannam@125
|
134
|
cannam@125
|
135 if (sg > 0)
|
cannam@125
|
136 {
|
cannam@125
|
137 sgn = sign_of_int (ib3) ;
|
cannam@125
|
138 ia3 -= sgn ;
|
cannam@125
|
139 del0 -= (4 - 3) * ((sgn * ib3) >> denshift) ;
|
cannam@125
|
140 if (del0 <= 0)
|
cannam@125
|
141 continue ;
|
cannam@125
|
142
|
cannam@125
|
143 sgn = sign_of_int (ib2) ;
|
cannam@125
|
144 ia2 -= sgn ;
|
cannam@125
|
145 del0 -= (4 - 2) * ((sgn * ib2) >> denshift) ;
|
cannam@125
|
146 if (del0 <= 0)
|
cannam@125
|
147 continue ;
|
cannam@125
|
148
|
cannam@125
|
149 sgn = sign_of_int (ib1) ;
|
cannam@125
|
150 ia1 -= sgn ;
|
cannam@125
|
151 del0 -= (4 - 1) * ((sgn * ib1) >> denshift) ;
|
cannam@125
|
152 if (del0 <= 0)
|
cannam@125
|
153 continue ;
|
cannam@125
|
154
|
cannam@125
|
155 ia0 -= sign_of_int (ib0) ;
|
cannam@125
|
156 }
|
cannam@125
|
157 else if (sg < 0)
|
cannam@125
|
158 {
|
cannam@125
|
159 // note: to avoid unnecessary negations, we flip the value of "sgn"
|
cannam@125
|
160 sgn = -sign_of_int (ib3) ;
|
cannam@125
|
161 ia3 -= sgn ;
|
cannam@125
|
162 del0 -= (4 - 3) * ((sgn * ib3) >> denshift) ;
|
cannam@125
|
163 if (del0 >= 0)
|
cannam@125
|
164 continue ;
|
cannam@125
|
165
|
cannam@125
|
166 sgn = -sign_of_int (ib2) ;
|
cannam@125
|
167 ia2 -= sgn ;
|
cannam@125
|
168 del0 -= (4 - 2) * ((sgn * ib2) >> denshift) ;
|
cannam@125
|
169 if (del0 >= 0)
|
cannam@125
|
170 continue ;
|
cannam@125
|
171
|
cannam@125
|
172 sgn = -sign_of_int (ib1) ;
|
cannam@125
|
173 ia1 -= sgn ;
|
cannam@125
|
174 del0 -= (4 - 1) * ((sgn * ib1) >> denshift) ;
|
cannam@125
|
175 if (del0 >= 0)
|
cannam@125
|
176 continue ;
|
cannam@125
|
177
|
cannam@125
|
178 ia0 += sign_of_int (ib0) ;
|
cannam@125
|
179 }
|
cannam@125
|
180 }
|
cannam@125
|
181
|
cannam@125
|
182 coefs [0] = ia0 ;
|
cannam@125
|
183 coefs [1] = ia1 ;
|
cannam@125
|
184 coefs [2] = ia2 ;
|
cannam@125
|
185 coefs [3] = ia3 ;
|
cannam@125
|
186 }
|
cannam@125
|
187 else if (numactive == 8)
|
cannam@125
|
188 {
|
cannam@125
|
189 register int16_t a4, a5, a6, a7 ;
|
cannam@125
|
190 register int32_t b4, b5, b6, b7 ;
|
cannam@125
|
191
|
cannam@125
|
192 // optimization for numactive == 8
|
cannam@125
|
193 a0 = coefs [0] ;
|
cannam@125
|
194 a1 = coefs [1] ;
|
cannam@125
|
195 a2 = coefs [2] ;
|
cannam@125
|
196 a3 = coefs [3] ;
|
cannam@125
|
197 a4 = coefs [4] ;
|
cannam@125
|
198 a5 = coefs [5] ;
|
cannam@125
|
199 a6 = coefs [6] ;
|
cannam@125
|
200 a7 = coefs [7] ;
|
cannam@125
|
201
|
cannam@125
|
202 for (j = lim ; j < num ; j++)
|
cannam@125
|
203 {
|
cannam@125
|
204 LOOP_ALIGN
|
cannam@125
|
205
|
cannam@125
|
206 top = out [j - lim] ;
|
cannam@125
|
207 pout = out + j - 1 ;
|
cannam@125
|
208
|
cannam@125
|
209 b0 = top - (*pout--) ;
|
cannam@125
|
210 b1 = top - (*pout--) ;
|
cannam@125
|
211 b2 = top - (*pout--) ;
|
cannam@125
|
212 b3 = top - (*pout--) ;
|
cannam@125
|
213 b4 = top - (*pout--) ;
|
cannam@125
|
214 b5 = top - (*pout--) ;
|
cannam@125
|
215 b6 = top - (*pout--) ;
|
cannam@125
|
216 b7 = top - (*pout) ;
|
cannam@125
|
217 pout += 8 ;
|
cannam@125
|
218
|
cannam@125
|
219 sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
|
cannam@125
|
220 - a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift ;
|
cannam@125
|
221
|
cannam@125
|
222 del = pc1 [j] ;
|
cannam@125
|
223 del0 = del ;
|
cannam@125
|
224 sg = sign_of_int (del) ;
|
cannam@125
|
225 del += top + sum1 ;
|
cannam@125
|
226
|
cannam@125
|
227 out [j] = arith_shift_left (del, chanshift) >> chanshift ;
|
cannam@125
|
228
|
cannam@125
|
229 if (sg > 0)
|
cannam@125
|
230 {
|
cannam@125
|
231 sgn = sign_of_int (b7) ;
|
cannam@125
|
232 a7 -= sgn ;
|
cannam@125
|
233 del0 -= 1 * ((sgn * b7) >> denshift) ;
|
cannam@125
|
234 if (del0 <= 0)
|
cannam@125
|
235 continue ;
|
cannam@125
|
236
|
cannam@125
|
237 sgn = sign_of_int (b6) ;
|
cannam@125
|
238 a6 -= sgn ;
|
cannam@125
|
239 del0 -= 2 * ((sgn * b6) >> denshift) ;
|
cannam@125
|
240 if (del0 <= 0)
|
cannam@125
|
241 continue ;
|
cannam@125
|
242
|
cannam@125
|
243 sgn = sign_of_int (b5) ;
|
cannam@125
|
244 a5 -= sgn ;
|
cannam@125
|
245 del0 -= 3 * ((sgn * b5) >> denshift) ;
|
cannam@125
|
246 if (del0 <= 0)
|
cannam@125
|
247 continue ;
|
cannam@125
|
248
|
cannam@125
|
249 sgn = sign_of_int (b4) ;
|
cannam@125
|
250 a4 -= sgn ;
|
cannam@125
|
251 del0 -= 4 * ((sgn * b4) >> denshift) ;
|
cannam@125
|
252 if (del0 <= 0)
|
cannam@125
|
253 continue ;
|
cannam@125
|
254
|
cannam@125
|
255 sgn = sign_of_int (b3) ;
|
cannam@125
|
256 a3 -= sgn ;
|
cannam@125
|
257 del0 -= 5 * ((sgn * b3) >> denshift) ;
|
cannam@125
|
258 if (del0 <= 0)
|
cannam@125
|
259 continue ;
|
cannam@125
|
260
|
cannam@125
|
261 sgn = sign_of_int (b2) ;
|
cannam@125
|
262 a2 -= sgn ;
|
cannam@125
|
263 del0 -= 6 * ((sgn * b2) >> denshift) ;
|
cannam@125
|
264 if (del0 <= 0)
|
cannam@125
|
265 continue ;
|
cannam@125
|
266
|
cannam@125
|
267 sgn = sign_of_int (b1) ;
|
cannam@125
|
268 a1 -= sgn ;
|
cannam@125
|
269 del0 -= 7 * ((sgn * b1) >> denshift) ;
|
cannam@125
|
270 if (del0 <= 0)
|
cannam@125
|
271 continue ;
|
cannam@125
|
272
|
cannam@125
|
273 a0 -= sign_of_int (b0) ;
|
cannam@125
|
274 }
|
cannam@125
|
275 else if (sg < 0)
|
cannam@125
|
276 {
|
cannam@125
|
277 // note: to avoid unnecessary negations, we flip the value of "sgn"
|
cannam@125
|
278 sgn = -sign_of_int (b7) ;
|
cannam@125
|
279 a7 -= sgn ;
|
cannam@125
|
280 del0 -= 1 * ((sgn * b7) >> denshift) ;
|
cannam@125
|
281 if (del0 >= 0)
|
cannam@125
|
282 continue ;
|
cannam@125
|
283
|
cannam@125
|
284 sgn = -sign_of_int (b6) ;
|
cannam@125
|
285 a6 -= sgn ;
|
cannam@125
|
286 del0 -= 2 * ((sgn * b6) >> denshift) ;
|
cannam@125
|
287 if (del0 >= 0)
|
cannam@125
|
288 continue ;
|
cannam@125
|
289
|
cannam@125
|
290 sgn = -sign_of_int (b5) ;
|
cannam@125
|
291 a5 -= sgn ;
|
cannam@125
|
292 del0 -= 3 * ((sgn * b5) >> denshift) ;
|
cannam@125
|
293 if (del0 >= 0)
|
cannam@125
|
294 continue ;
|
cannam@125
|
295
|
cannam@125
|
296 sgn = -sign_of_int (b4) ;
|
cannam@125
|
297 a4 -= sgn ;
|
cannam@125
|
298 del0 -= 4 * ((sgn * b4) >> denshift) ;
|
cannam@125
|
299 if (del0 >= 0)
|
cannam@125
|
300 continue ;
|
cannam@125
|
301
|
cannam@125
|
302 sgn = -sign_of_int (b3) ;
|
cannam@125
|
303 a3 -= sgn ;
|
cannam@125
|
304 del0 -= 5 * ((sgn * b3) >> denshift) ;
|
cannam@125
|
305 if (del0 >= 0)
|
cannam@125
|
306 continue ;
|
cannam@125
|
307
|
cannam@125
|
308 sgn = -sign_of_int (b2) ;
|
cannam@125
|
309 a2 -= sgn ;
|
cannam@125
|
310 del0 -= 6 * ((sgn * b2) >> denshift) ;
|
cannam@125
|
311 if (del0 >= 0)
|
cannam@125
|
312 continue ;
|
cannam@125
|
313
|
cannam@125
|
314 sgn = -sign_of_int (b1) ;
|
cannam@125
|
315 a1 -= sgn ;
|
cannam@125
|
316 del0 -= 7 * ((sgn * b1) >> denshift) ;
|
cannam@125
|
317 if (del0 >= 0)
|
cannam@125
|
318 continue ;
|
cannam@125
|
319
|
cannam@125
|
320 a0 += sign_of_int (b0) ;
|
cannam@125
|
321 }
|
cannam@125
|
322 }
|
cannam@125
|
323
|
cannam@125
|
324 coefs [0] = a0 ;
|
cannam@125
|
325 coefs [1] = a1 ;
|
cannam@125
|
326 coefs [2] = a2 ;
|
cannam@125
|
327 coefs [3] = a3 ;
|
cannam@125
|
328 coefs [4] = a4 ;
|
cannam@125
|
329 coefs [5] = a5 ;
|
cannam@125
|
330 coefs [6] = a6 ;
|
cannam@125
|
331 coefs [7] = a7 ;
|
cannam@125
|
332 }
|
cannam@125
|
333 else
|
cannam@125
|
334 {
|
cannam@125
|
335 // general case
|
cannam@125
|
336 for (j = lim ; j < num ; j++)
|
cannam@125
|
337 {
|
cannam@125
|
338 LOOP_ALIGN
|
cannam@125
|
339
|
cannam@125
|
340 sum1 = 0 ;
|
cannam@125
|
341 pout = out + j - 1 ;
|
cannam@125
|
342 top = out [j-lim] ;
|
cannam@125
|
343
|
cannam@125
|
344 for (k = 0 ; k < numactive ; k++)
|
cannam@125
|
345 sum1 += coefs [k] * (pout [-k] - top) ;
|
cannam@125
|
346
|
cannam@125
|
347 del = pc1 [j] ;
|
cannam@125
|
348 del0 = del ;
|
cannam@125
|
349 sg = sign_of_int (del) ;
|
cannam@125
|
350 del += top + ((sum1 + denhalf) >> denshift) ;
|
cannam@125
|
351 out [j] = (del << chanshift) >> chanshift ;
|
cannam@125
|
352
|
cannam@125
|
353 if (sg > 0)
|
cannam@125
|
354 {
|
cannam@125
|
355 for (k = (numactive - 1) ; k >= 0 ; k--)
|
cannam@125
|
356 {
|
cannam@125
|
357 dd = top - pout [-k] ;
|
cannam@125
|
358 sgn = sign_of_int (dd) ;
|
cannam@125
|
359 coefs [k] -= sgn ;
|
cannam@125
|
360 del0 -= (numactive - k) * ((sgn * dd) >> denshift) ;
|
cannam@125
|
361 if (del0 <= 0)
|
cannam@125
|
362 break ;
|
cannam@125
|
363 }
|
cannam@125
|
364 }
|
cannam@125
|
365 else if (sg < 0)
|
cannam@125
|
366 {
|
cannam@125
|
367 for (k = (numactive - 1) ; k >= 0 ; k--)
|
cannam@125
|
368 {
|
cannam@125
|
369 dd = top - pout [-k] ;
|
cannam@125
|
370 sgn = sign_of_int (dd) ;
|
cannam@125
|
371 coefs [k] += sgn ;
|
cannam@125
|
372 del0 -= (numactive - k) * ((-sgn * dd) >> denshift) ;
|
cannam@125
|
373 if (del0 >= 0)
|
cannam@125
|
374 break ;
|
cannam@125
|
375 }
|
cannam@125
|
376 }
|
cannam@125
|
377 }
|
cannam@125
|
378 }
|
cannam@125
|
379 }
|