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