xref: /third_party/libsnd/src/ALAC/ag_dec.c (revision b815c7f3)
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:		ag_dec.c
23
24	Contains:   Adaptive Golomb decode routines.
25
26	Copyright:	(c) 2001-2011 Apple, Inc.
27*/
28
29#include <math.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "aglib.h"
35#include "ALACBitUtilities.h"
36#include "ALACAudioTypes.h"
37
38#define CODE_TO_LONG_MAXBITS	32
39#define N_MAX_MEAN_CLAMP		0xffff
40#define N_MEAN_CLAMP_VAL		0xffff
41#define REPORT_VAL				40
42
43#if __GNUC__
44#define ALWAYS_INLINE		__attribute__ ((always_inline))
45#elif defined _MSC_VER
46#define ALWAYS_INLINE		__forceinline
47#else
48#define ALWAYS_INLINE
49#endif
50
51/*	And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this
52	to help the compiler out.   In many cases this required manual inlining or a macro.  Sorry
53	if it is ugly but the performance gains are well worth it.
54	- WSK 5/19/04
55*/
56
57void set_standard_ag_params (AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth)
58{
59	/* Use
60		fullwidth = sectorwidth = numOfSamples, for analog 1-dimensional type-short data,
61		but use
62		fullwidth = full image width, sectorwidth = sector (patch) width
63		for such as image (2-dim.) data.
64	*/
65	set_ag_params (params, MB0, PB0, KB0, fullwidth, sectorwidth, MAX_RUN_DEFAULT) ;
66}
67
68void set_ag_params (AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun)
69{
70	params->mb = params->mb0 = m ;
71	params->pb = p ;
72	params->kb = k ;
73	params->wb = (1u << params->kb) - 1 ;
74	params->qb = QB-params->pb ;
75	params->fw = f ;
76	params->sw = s ;
77	params->maxrun = maxrun ;
78}
79
80#if PRAGMA_MARK
81#pragma mark -
82#endif
83
84
85// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
86static inline int32_t lead (int32_t m)
87{
88	long j ;
89	unsigned long c = (1ul << 31) ;
90
91	for (j = 0 ; j < 32 ; j++)
92	{
93		if ((c & m) != 0)
94			break ;
95		c >>= 1 ;
96	}
97	return j ;
98}
99
100#define arithmin(a, b) ((a) < (b) ? (a) : (b))
101
102static inline int32_t ALWAYS_INLINE lg3a (int32_t x)
103{
104	int32_t result ;
105
106	x += 3 ;
107	result = lead (x) ;
108
109	return 31 - result ;
110}
111
112static inline uint32_t ALWAYS_INLINE read32bit (uint8_t * buffer)
113{
114	// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes
115	uint32_t		value ;
116
117	value = ((uint32_t) buffer [0] << 24) | ((uint32_t) buffer [1] << 16) |
118				((uint32_t) buffer [2] << 8) | (uint32_t) buffer [3] ;
119	return value ;
120
121}
122
123#if PRAGMA_MARK
124#pragma mark -
125#endif
126
127#define get_next_fromlong(inlong, suff)		((inlong) >> (32 - (suff)))
128
129
130static inline uint32_t ALWAYS_INLINE
131getstreambits (uint8_t *in, int32_t bitoffset, int32_t numbits)
132{
133	uint32_t	load1, load2 ;
134	uint32_t	byteoffset = bitoffset / 8 ;
135	uint32_t	result ;
136
137	//Assert (numbits <= 32) ;
138
139	load1 = read32bit (in + byteoffset) ;
140
141	if ((numbits + (bitoffset & 0x7)) > 32)
142	{
143		int32_t load2shift ;
144
145		result = load1 << (bitoffset & 0x7) ;
146		load2 = (uint32_t) in [byteoffset + 4] ;
147		load2shift = (8 - (numbits + (bitoffset & 0x7) - 32)) ;
148		load2 >>= load2shift ;
149		result >>= (32 - numbits) ;
150		result |= load2 ;
151	}
152	else
153	{
154		result = load1 >> (32 - numbits - (bitoffset & 7)) ;
155	}
156
157	// a shift of >= "the number of bits in the type of the value being shifted" results in undefined
158	// behavior so don't try to shift by 32
159	if (numbits != (sizeof (result) * 8))
160		result &= ~ (0xfffffffful << numbits) ;
161
162	return result ;
163}
164
165
166static inline int32_t dyn_get (unsigned char *in, uint32_t *bitPos, uint32_t m, uint32_t k)
167{
168	uint32_t	tempbits = *bitPos ;
169	uint32_t		result ;
170	uint32_t		pre = 0, v ;
171	uint32_t		streamlong ;
172
173	streamlong = read32bit (in + (tempbits >> 3)) ;
174	streamlong <<= (tempbits & 7) ;
175
176	/* find the number of bits in the prefix */
177	{
178		uint32_t	notI = ~streamlong ;
179		pre = lead (notI) ;
180	}
181
182	if (pre >= MAX_PREFIX_16)
183	{
184		pre = MAX_PREFIX_16 ;
185		tempbits += pre ;
186		streamlong <<= pre ;
187		result = get_next_fromlong (streamlong, MAX_DATATYPE_BITS_16) ;
188		tempbits += MAX_DATATYPE_BITS_16 ;
189
190	}
191	else
192	{
193		// all of the bits must fit within the long we have loaded
194		//Assert (pre+1+k <= 32) ;
195
196		tempbits += pre ;
197		tempbits += 1 ;
198		streamlong <<= pre + 1 ;
199		v = get_next_fromlong (streamlong, k) ;
200		tempbits += k ;
201
202		result = pre*m + v-1 ;
203
204		if (v < 2)
205		{
206			result -= (v-1) ;
207			tempbits -= 1 ;
208		}
209	}
210
211	*bitPos = tempbits ;
212	return result ;
213}
214
215
216static inline int32_t dyn_get_32bit (uint8_t * in, uint32_t * bitPos, int32_t m, int32_t k, int32_t maxbits)
217{
218	uint32_t	tempbits = *bitPos ;
219	uint32_t		v ;
220	uint32_t		streamlong ;
221	uint32_t		result ;
222
223	streamlong = read32bit (in + (tempbits >> 3)) ;
224	streamlong <<= (tempbits & 7) ;
225
226	/* find the number of bits in the prefix */
227	{
228		uint32_t notI = ~streamlong ;
229		result = lead (notI) ;
230	}
231
232	if (result >= MAX_PREFIX_32)
233	{
234		result = getstreambits (in, tempbits+MAX_PREFIX_32, maxbits) ;
235		tempbits += MAX_PREFIX_32 + maxbits ;
236	}
237	else
238	{
239		/* all of the bits must fit within the long we have loaded*/
240		//Assert (k<=14) ;
241		//Assert (result<MAX_PREFIX_32) ;
242		//Assert (result+1+k <= 32) ;
243
244		tempbits += result ;
245		tempbits += 1 ;
246
247		if (k != 1)
248		{
249			streamlong <<= result + 1 ;
250			v = get_next_fromlong (streamlong, k) ;
251			tempbits += k ;
252			tempbits -= 1 ;
253			result = result*m ;
254
255			if (v >= 2)
256			{
257				result += (v-1) ;
258				tempbits += 1 ;
259			}
260		}
261	}
262
263	*bitPos = tempbits ;
264
265	return result ;
266}
267
268int32_t dyn_decomp (AGParamRecPtr params, BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits)
269{
270	uint8_t 		*in ;
271	int32_t			*outPtr = pc ;
272	uint32_t 	bitPos, startPos, maxPos ;
273	uint32_t		j, m, k, n, c, mz ;
274	int32_t			del, zmode ;
275	uint32_t 	mb ;
276	uint32_t	pb_local = params->pb ;
277	uint32_t	kb_local = params->kb ;
278	uint32_t	wb_local = params->wb ;
279	int32_t				status ;
280
281	RequireAction ((bitstream != NULL) && (pc != NULL) && (outNumBits != NULL), return kALAC_ParamError ;) ;
282	*outNumBits = 0 ;
283
284	in = bitstream->cur ;
285	startPos = bitstream->bitIndex ;
286	maxPos = bitstream->byteSize * 8 ;
287	bitPos = startPos ;
288
289	mb = params->mb0 ;
290	zmode = 0 ;
291
292	c = 0 ;
293	status = ALAC_noErr ;
294
295	while (c < (uint32_t) numSamples)
296	{
297		// bail if we've run off the end of the buffer
298		RequireAction (bitPos < maxPos, status = kALAC_ParamError ; goto Exit ;) ;
299
300		m = (mb) >> QBSHIFT ;
301		k = lg3a (m) ;
302
303		k = arithmin (k, kb_local) ;
304		m = (1 << k) - 1 ;
305
306		n = dyn_get_32bit (in, &bitPos, m, k, maxSize) ;
307
308		// least significant bit is sign bit
309		{
310			uint32_t	ndecode = n + zmode ;
311			int32_t		multiplier = - (int) (ndecode & 1) ;
312
313			multiplier |= 1 ;
314			del = ((ndecode+1) >> 1) * (multiplier) ;
315		}
316
317		*outPtr++ = del ;
318
319		c++ ;
320
321		mb = pb_local * (n + zmode) + mb - ((pb_local * mb) >> QBSHIFT) ;
322
323		// update mean tracking
324		if (n > N_MAX_MEAN_CLAMP)
325			mb = N_MEAN_CLAMP_VAL ;
326
327		zmode = 0 ;
328
329		if (((mb << MMULSHIFT) < QB) && (c < (uint32_t) numSamples))
330		{
331			zmode = 1 ;
332			k = lead (mb) - BITOFF + ((mb + MOFF) >> MDENSHIFT) ;
333			mz = ((1 << k) - 1) & wb_local ;
334
335			n = dyn_get (in, &bitPos, mz, k) ;
336
337			RequireAction (c+n <= (uint32_t) numSamples, status = kALAC_ParamError ; goto Exit ;) ;
338
339			for (j = 0 ; j < n ; j++)
340			{
341				*outPtr++ = 0 ;
342				++c ;
343			}
344
345			if (n >= 65535)
346				zmode = 0 ;
347
348			mb = 0 ;
349		}
350	}
351
352Exit:
353	*outNumBits = (bitPos - startPos) ;
354	BitBufferAdvance (bitstream, *outNumBits) ;
355	RequireAction (bitstream->cur <= bitstream->end, status = kALAC_ParamError ;) ;
356
357	return status ;
358}
359