/src/libsndfile/src/ALAC/ag_enc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2011 Apple Inc. All rights reserved. |
3 | | * Copyright (C) 2013-2014 Erik de Castro Lopo <erikd@mega-nerd.com> |
4 | | * |
5 | | * @APPLE_APACHE_LICENSE_HEADER_START@ |
6 | | * |
7 | | * Licensed under the Apache License, Version 2.0 (the "License") ; |
8 | | * you may not use this file except in compliance with the License. |
9 | | * You may obtain a copy of the License at |
10 | | * |
11 | | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | | * |
13 | | * Unless required by applicable law or agreed to in writing, software |
14 | | * distributed under the License is distributed on an "AS IS" BASIS, |
15 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | | * See the License for the specific language governing permissions and |
17 | | * limitations under the License. |
18 | | * |
19 | | * @APPLE_APACHE_LICENSE_HEADER_END@ |
20 | | */ |
21 | | |
22 | | /* |
23 | | File: ag_enc.c |
24 | | |
25 | | Contains: Adaptive Golomb encode routines. |
26 | | |
27 | | Copyright: (c) 2001-2011 Apple, Inc. |
28 | | */ |
29 | | |
30 | | #include "config.h" |
31 | | |
32 | | #include "aglib.h" |
33 | | #include "ALACBitUtilities.h" |
34 | | #include "EndianPortable.h" |
35 | | #include "ALACAudioTypes.h" |
36 | | |
37 | | #include <math.h> |
38 | | #include <stdio.h> |
39 | | #include <stdlib.h> |
40 | | #include <string.h> |
41 | | |
42 | | #define CODE_TO_LONG_MAXBITS 32 |
43 | 0 | #define N_MAX_MEAN_CLAMP 0xffff |
44 | 0 | #define N_MEAN_CLAMP_VAL 0xffff |
45 | | #define REPORT_VAL 40 |
46 | | |
47 | | #if __GNUC__ |
48 | | #define ALWAYS_INLINE __attribute__ ((always_inline)) |
49 | | #elif defined _MSC_VER |
50 | | #define ALWAYS_INLINE __forceinline |
51 | | #else |
52 | | #define ALWAYS_INLINE |
53 | | #endif |
54 | | |
55 | | |
56 | | /* And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this |
57 | | to help the compiler out. In many cases this required manual inlining or a macro. Sorry |
58 | | if it is ugly but the performance gains are well worth it. |
59 | | - WSK 5/19/04 |
60 | | */ |
61 | | |
62 | | // note: implementing this with some kind of "count leading zeros" assembly is a big performance win |
63 | | static inline int32_t lead (int32_t m) |
64 | 0 | { |
65 | 0 | long j ; |
66 | 0 | unsigned long c = (1ul << 31) ; |
67 | |
|
68 | 0 | for (j = 0 ; j < 32 ; j++) |
69 | 0 | { |
70 | 0 | if ((c & m) != 0) |
71 | 0 | break ; |
72 | 0 | c >>= 1 ; |
73 | 0 | } |
74 | 0 | return j ; |
75 | 0 | } |
76 | | |
77 | | #define arithmin (a, b) ((a) < (b) ? (a) : (b)) |
78 | | |
79 | | static inline int32_t ALWAYS_INLINE lg3a (int32_t x) |
80 | 0 | { |
81 | 0 | int32_t result ; |
82 | |
|
83 | 0 | x += 3 ; |
84 | 0 | result = lead (x) ; |
85 | |
|
86 | 0 | return 31 - result ; |
87 | 0 | } |
88 | | |
89 | | static inline int32_t ALWAYS_INLINE abs_func (int32_t a) |
90 | 0 | { |
91 | | // note: the CW PPC intrinsic __abs () turns into these instructions so no need to try and use it |
92 | 0 | int32_t isneg = a >> 31 ; |
93 | 0 | int32_t xorval = a ^ isneg ; |
94 | 0 | int32_t result = xorval-isneg ; |
95 | |
|
96 | 0 | return result ; |
97 | 0 | } |
98 | | |
99 | | #if PRAGMA_MARK |
100 | | #pragma mark - |
101 | | #endif |
102 | | |
103 | | static inline int32_t dyn_code (int32_t m, int32_t k, int32_t n, uint32_t *outNumBits) |
104 | 0 | { |
105 | 0 | uint32_t divx, mod, de ; |
106 | 0 | uint32_t numBits ; |
107 | 0 | uint32_t value ; |
108 | | |
109 | | // Assert (n >= 0) ; |
110 | |
|
111 | 0 | divx = n / m ; |
112 | |
|
113 | 0 | if (divx >= MAX_PREFIX_16) |
114 | 0 | { |
115 | 0 | numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16 ; |
116 | 0 | value = (((1 << MAX_PREFIX_16) - 1) << MAX_DATATYPE_BITS_16) + n ; |
117 | 0 | } |
118 | 0 | else |
119 | 0 | { |
120 | 0 | mod = n%m ; |
121 | 0 | de = (mod == 0) ; |
122 | 0 | numBits = divx + k + 1 - de ; |
123 | 0 | value = (((1 << divx) - 1) << (numBits - divx)) + mod + 1 - de ; |
124 | | |
125 | | // if coding this way is bigger than doing escape, then do escape |
126 | 0 | if (numBits > MAX_PREFIX_16 + MAX_DATATYPE_BITS_16) |
127 | 0 | { |
128 | 0 | numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16 ; |
129 | 0 | value = (((1 << MAX_PREFIX_16) - 1) << MAX_DATATYPE_BITS_16) + n ; |
130 | 0 | } |
131 | 0 | } |
132 | |
|
133 | 0 | *outNumBits = numBits ; |
134 | |
|
135 | 0 | return (int32_t) value ; |
136 | 0 | } |
137 | | |
138 | | |
139 | | static inline int32_t dyn_code_32bit (int32_t maxbits, uint32_t m, uint32_t k, uint32_t n, uint32_t *outNumBits, uint32_t *outValue, uint32_t *overflow, uint32_t *overflowbits) |
140 | 0 | { |
141 | 0 | uint32_t divx, mod, de ; |
142 | 0 | uint32_t numBits ; |
143 | 0 | uint32_t value ; |
144 | 0 | int32_t didOverflow = 0 ; |
145 | |
|
146 | 0 | divx = n / m ; |
147 | |
|
148 | 0 | if (divx < MAX_PREFIX_32) |
149 | 0 | { |
150 | 0 | mod = n - (m * divx) ; |
151 | |
|
152 | 0 | de = (mod == 0) ; |
153 | 0 | numBits = divx + k + 1 - de ; |
154 | 0 | value = (((1 << divx) - 1) << (numBits - divx)) + mod + 1 - de ; |
155 | 0 | if (numBits > 25) |
156 | 0 | goto codeasescape ; |
157 | 0 | } |
158 | 0 | else |
159 | 0 | { |
160 | 0 | codeasescape: |
161 | 0 | numBits = MAX_PREFIX_32 ; |
162 | 0 | value = (((1 << MAX_PREFIX_32) - 1)) ; |
163 | 0 | *overflow = n ; |
164 | 0 | *overflowbits = maxbits ; |
165 | 0 | didOverflow = 1 ; |
166 | 0 | } |
167 | | |
168 | 0 | *outNumBits = numBits ; |
169 | 0 | *outValue = value ; |
170 | |
|
171 | 0 | return didOverflow ; |
172 | 0 | } |
173 | | |
174 | | |
175 | | static inline void ALWAYS_INLINE dyn_jam_noDeref (unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value) |
176 | 0 | { |
177 | 0 | uint32_t mask ; |
178 | 0 | uint32_t curr ; |
179 | 0 | uint32_t shift ; |
180 | | |
181 | | //Assert (numBits <= 32) ; |
182 | |
|
183 | 0 | curr = psf_get_be32 (out, bitPos >> 3) ; |
184 | |
|
185 | 0 | shift = 32 - (bitPos & 7) - numBits ; |
186 | |
|
187 | 0 | mask = ~0u >> (32 - numBits) ; // mask must be created in two steps to avoid compiler sequencing ambiguity |
188 | 0 | mask <<= shift ; |
189 | |
|
190 | 0 | value = (value << shift) & mask ; |
191 | 0 | value |= curr & ~mask ; |
192 | |
|
193 | 0 | psf_put_be32 (out, bitPos >> 3, value) ; |
194 | 0 | } |
195 | | |
196 | | |
197 | | static inline void ALWAYS_INLINE dyn_jam_noDeref_large (unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value) |
198 | 0 | { |
199 | 0 | uint32_t w ; |
200 | 0 | uint32_t curr ; |
201 | 0 | uint32_t mask ; |
202 | 0 | int32_t shiftvalue = (32 - (bitPos & 7) - numBits) ; |
203 | | |
204 | | //Assert (numBits <= 32) ; |
205 | |
|
206 | 0 | curr = psf_get_be32 (out, bitPos >> 3) ; |
207 | |
|
208 | 0 | if (shiftvalue < 0) |
209 | 0 | { |
210 | 0 | uint8_t tailbyte ; |
211 | 0 | uint8_t *tailptr ; |
212 | |
|
213 | 0 | w = value >> -shiftvalue ; |
214 | 0 | mask = ~0u >> -shiftvalue ; |
215 | 0 | w |= (curr & ~mask) ; |
216 | |
|
217 | 0 | tailptr = out + (bitPos >> 3) + 4 ; |
218 | 0 | tailbyte = (value << ((8+shiftvalue))) & 0xff ; |
219 | 0 | *tailptr = (uint8_t) tailbyte ; |
220 | 0 | } |
221 | 0 | else |
222 | 0 | { |
223 | 0 | mask = ~0u >> (32 - numBits) ; |
224 | 0 | mask <<= shiftvalue ; // mask must be created in two steps to avoid compiler sequencing ambiguity |
225 | |
|
226 | 0 | w = (value << shiftvalue) & mask ; |
227 | 0 | w |= curr & ~mask ; |
228 | 0 | } |
229 | |
|
230 | 0 | psf_put_be32 (out, bitPos >> 3, w) ; |
231 | 0 | } |
232 | | |
233 | | |
234 | | int32_t dyn_comp (AGParamRecPtr params, int32_t * pc, BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits) |
235 | 0 | { |
236 | 0 | unsigned char * out ; |
237 | 0 | uint32_t bitPos, startPos ; |
238 | 0 | uint32_t m, k, n, c, mz, nz ; |
239 | 0 | uint32_t numBits ; |
240 | 0 | uint32_t value ; |
241 | 0 | int32_t del, zmode ; |
242 | 0 | uint32_t overflow, overflowbits ; |
243 | 0 | int32_t status ; |
244 | | |
245 | | // shadow the variables in params so there's not the dereferencing overhead |
246 | 0 | uint32_t mb, pb, kb, wb ; |
247 | 0 | int32_t rowPos = 0 ; |
248 | 0 | int32_t rowSize = params->sw ; |
249 | 0 | int32_t rowJump = (params->fw) - rowSize ; |
250 | 0 | int32_t * inPtr = pc ; |
251 | |
|
252 | 0 | *outNumBits = 0 ; |
253 | 0 | RequireAction ((bitSize >= 1) && (bitSize <= 32), return kALAC_ParamError ;) ; |
254 | |
|
255 | 0 | out = bitstream->cur ; |
256 | 0 | startPos = bitstream->bitIndex ; |
257 | 0 | bitPos = startPos ; |
258 | |
|
259 | 0 | mb = params->mb = params->mb0 ; |
260 | 0 | pb = params->pb ; |
261 | 0 | kb = params->kb ; |
262 | 0 | wb = params->wb ; |
263 | 0 | zmode = 0 ; |
264 | |
|
265 | 0 | c = 0 ; |
266 | 0 | status = ALAC_noErr ; |
267 | |
|
268 | 0 | while (c < (uint32_t) numSamples) |
269 | 0 | { |
270 | 0 | m = mb >> QBSHIFT ; |
271 | 0 | k = lg3a (m) ; |
272 | 0 | if (k > kb) |
273 | 0 | { |
274 | 0 | k = kb ; |
275 | 0 | } |
276 | 0 | m = (1 << k) - 1 ; |
277 | |
|
278 | 0 | del = *inPtr++ ; |
279 | 0 | rowPos++ ; |
280 | |
|
281 | 0 | n = (abs_func (del) << 1) - ((del >> 31) & 1) - zmode ; |
282 | | //Assert (32-lead (n) <= bitSize) ; |
283 | |
|
284 | 0 | if (dyn_code_32bit (bitSize, m, k, n, &numBits, &value, &overflow, &overflowbits)) |
285 | 0 | { |
286 | 0 | dyn_jam_noDeref (out, bitPos, numBits, value) ; |
287 | 0 | bitPos += numBits ; |
288 | 0 | dyn_jam_noDeref_large (out, bitPos, overflowbits, overflow) ; |
289 | 0 | bitPos += overflowbits ; |
290 | 0 | } |
291 | 0 | else |
292 | 0 | { |
293 | 0 | dyn_jam_noDeref (out, bitPos, numBits, value) ; |
294 | 0 | bitPos += numBits ; |
295 | 0 | } |
296 | |
|
297 | 0 | c++ ; |
298 | 0 | if (rowPos >= rowSize) |
299 | 0 | { |
300 | 0 | rowPos = 0 ; |
301 | 0 | inPtr += rowJump ; |
302 | 0 | } |
303 | |
|
304 | 0 | mb = pb * (n + zmode) + mb - ((pb * mb) >> QBSHIFT) ; |
305 | | |
306 | | // update mean tracking if it's overflowed |
307 | 0 | if (n > N_MAX_MEAN_CLAMP) |
308 | 0 | mb = N_MEAN_CLAMP_VAL ; |
309 | |
|
310 | 0 | zmode = 0 ; |
311 | |
|
312 | 0 | RequireAction (c <= (uint32_t) numSamples, status = kALAC_ParamError ; goto Exit ;) ; |
313 | |
|
314 | 0 | if (((mb << MMULSHIFT) < QB) && (c < (uint32_t) numSamples)) |
315 | 0 | { |
316 | 0 | zmode = 1 ; |
317 | 0 | nz = 0 ; |
318 | |
|
319 | 0 | while (c < (uint32_t) numSamples && *inPtr == 0) |
320 | 0 | { |
321 | | /* Take care of wrap-around globals. */ |
322 | 0 | ++inPtr ; |
323 | 0 | ++nz ; |
324 | 0 | ++c ; |
325 | 0 | if (++rowPos >= rowSize) |
326 | 0 | { |
327 | 0 | rowPos = 0 ; |
328 | 0 | inPtr += rowJump ; |
329 | 0 | } |
330 | |
|
331 | 0 | if (nz >= 65535) |
332 | 0 | { |
333 | 0 | zmode = 0 ; |
334 | 0 | break ; |
335 | 0 | } |
336 | 0 | } |
337 | |
|
338 | 0 | k = lead (mb) - BITOFF + ((mb + MOFF) >> MDENSHIFT) ; |
339 | 0 | mz = ((1 << k) - 1) & wb ; |
340 | |
|
341 | 0 | value = dyn_code (mz, k, nz, &numBits) ; |
342 | 0 | dyn_jam_noDeref (out, bitPos, numBits, value) ; |
343 | 0 | bitPos += numBits ; |
344 | |
|
345 | 0 | mb = 0 ; |
346 | 0 | } |
347 | 0 | } |
348 | | |
349 | 0 | *outNumBits = (bitPos - startPos) ; |
350 | 0 | BitBufferAdvance (bitstream, *outNumBits) ; |
351 | |
|
352 | 0 | Exit: |
353 | 0 | return status ; |
354 | 0 | } |