| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 | /* * Copyright (c) 2011 Apple Inc. All rights reserved. * * @APPLE_APACHE_LICENSE_HEADER_START@ *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *     http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *  * @APPLE_APACHE_LICENSE_HEADER_END@ *//*	File:		ag_dec.c		Contains:   Adaptive Golomb decode routines.	Copyright:	(c) 2001-2011 Apple, Inc.*/#include "aglib.h"#include "ALACBitUtilities.h"#include "ALACAudioTypes.h"#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#if __GNUC__ && TARGET_OS_MAC	#if __POWERPC__		#include <ppc_intrinsics.h>	#else		#include <libkern/OSByteOrder.h>	#endif#endif#define CODE_TO_LONG_MAXBITS	32#define N_MAX_MEAN_CLAMP		0xffff#define N_MEAN_CLAMP_VAL		0xffff#define REPORT_VAL  40#if __GNUC__#define ALWAYS_INLINE		__attribute__((always_inline))#else#define ALWAYS_INLINE#endif/*	And on the subject of the CodeWarrior x86 compiler and inlining, I reworked a lot of this	to help the compiler out.   In many cases this required manual inlining or a macro.  Sorry	if it is ugly but the performance gains are well worth it.	- WSK 5/19/04*/void set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth){	/* Use		fullwidth = sectorwidth = numOfSamples, for analog 1-dimensional type-short data,		but use		fullwidth = full image width, sectorwidth = sector (patch) width		for such as image (2-dim.) data.	*/	set_ag_params( params, MB0, PB0, KB0, fullwidth, sectorwidth, MAX_RUN_DEFAULT );}void set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun){	params->mb = params->mb0 = m;	params->pb = p;	params->kb = k;	params->wb = (1u<<params->kb)-1;	params->qb = QB-params->pb; 	params->fw = f;	params->sw = s;	params->maxrun = maxrun;}#if PRAGMA_MARK#pragma mark -#endif// note: implementing this with some kind of "count leading zeros" assembly is a big performance winstatic inline int32_t lead( int32_t m ){	long j;	unsigned long c = (1ul << 31);	for(j=0; j < 32; j++)	{		if((c & m) != 0)			break;		c >>= 1;	}	return (j);}#define arithmin(a, b) ((a) < (b) ? (a) : (b))static inline int32_t ALWAYS_INLINE lg3a( int32_t x){    int32_t result;    x += 3;    result = lead(x);    return 31 - result;}static inline uint32_t ALWAYS_INLINE read32bit( uint8_t * buffer ){	// embedded CPUs typically can't read unaligned 32-bit words so just read the bytes	uint32_t		value;		value = ((uint32_t)buffer[0] << 24) | ((uint32_t)buffer[1] << 16) |			 ((uint32_t)buffer[2] << 8) | (uint32_t)buffer[3];	return value;}#if PRAGMA_MARK#pragma mark -#endif#define get_next_fromlong(inlong, suff)		((inlong) >> (32 - (suff)))static inline uint32_t ALWAYS_INLINEgetstreambits( uint8_t *in, int32_t bitoffset, int32_t numbits ){	uint32_t	load1, load2;	uint32_t	byteoffset = bitoffset / 8;	uint32_t	result;		//Assert( numbits <= 32 );	load1 = read32bit( in + byteoffset );	if ( (numbits + (bitoffset & 0x7)) > 32)	{		int32_t load2shift;		result = load1 << (bitoffset & 0x7);		load2 = (uint32_t) in[byteoffset+4];		load2shift = (8-(numbits + (bitoffset & 0x7)-32));		load2 >>= load2shift;		result >>= (32-numbits);		result |= load2;			}	else	{		result = load1 >> (32-numbits-(bitoffset & 7));	}	// a shift of >= "the number of bits in the type of the value being shifted" results in undefined	// behavior so don't try to shift by 32	if ( numbits != (sizeof(result) * 8) )		result &= ~(0xfffffffful << numbits);		return result;}static inline int32_t dyn_get(unsigned char *in, uint32_t *bitPos, uint32_t m, uint32_t k){    uint32_t	tempbits = *bitPos;    uint32_t		result;    uint32_t		pre = 0, v;    uint32_t		streamlong;	streamlong = read32bit( in + (tempbits >> 3) );    streamlong <<= (tempbits & 7);    /* find the number of bits in the prefix */     {        uint32_t	notI = ~streamlong;    	pre = lead( notI);    }    if(pre >= MAX_PREFIX_16)    {        pre = MAX_PREFIX_16;        tempbits += pre;        streamlong <<= pre;        result = get_next_fromlong(streamlong,MAX_DATATYPE_BITS_16);        tempbits += MAX_DATATYPE_BITS_16;    }    else    {        // all of the bits must fit within the long we have loaded        //Assert(pre+1+k <= 32);        tempbits += pre;        tempbits += 1;        streamlong <<= pre+1;        v = get_next_fromlong(streamlong, k);        tempbits += k;            result = pre*m + v-1;        if(v<2) {            result -= (v-1);            tempbits -= 1;        }    }    *bitPos = tempbits;    return result;}static inline int32_t dyn_get_32bit( uint8_t * in, uint32_t * bitPos, int32_t m, int32_t k, int32_t maxbits ){	uint32_t	tempbits = *bitPos;	uint32_t		v;	uint32_t		streamlong;	uint32_t		result;		streamlong = read32bit( in + (tempbits >> 3) );	streamlong <<= (tempbits & 7);	/* find the number of bits in the prefix */ 	{		uint32_t notI = ~streamlong;		result = lead( notI);	}		if(result >= MAX_PREFIX_32)	{		result = getstreambits(in, tempbits+MAX_PREFIX_32, maxbits);		tempbits += MAX_PREFIX_32 + maxbits;	}	else	{				/* all of the bits must fit within the long we have loaded*/		//Assert(k<=14);		//Assert(result<MAX_PREFIX_32);		//Assert(result+1+k <= 32);				tempbits += result;		tempbits += 1;				if (k != 1)		{			streamlong <<= result+1;			v = get_next_fromlong(streamlong, k);			tempbits += k;			tempbits -= 1;			result = result*m;						if(v>=2)			{				result += (v-1);				tempbits += 1;			}		}	}	*bitPos = tempbits;	return result;}int32_t dyn_decomp( AGParamRecPtr params, BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits ){    uint8_t 		*in;    int32_t			*outPtr = pc;    uint32_t 	bitPos, startPos, maxPos;    uint32_t		j, m, k, n, c, mz;    int32_t			del, zmode;    uint32_t 	mb;    uint32_t	pb_local = params->pb;    uint32_t	kb_local = params->kb;    uint32_t	wb_local = params->wb;    int32_t				status;	RequireAction( (bitstream != nil) && (pc != nil) && (outNumBits != nil), return kALAC_ParamError; );	*outNumBits = 0;	in = bitstream->cur;	startPos = bitstream->bitIndex;	maxPos = bitstream->byteSize * 8;	bitPos = startPos;    mb = params->mb0;    zmode = 0;    c = 0;	status = ALAC_noErr;    while (c < numSamples)    {		// bail if we've run off the end of the buffer    	RequireAction( bitPos < maxPos, status = kALAC_ParamError; goto Exit; );        m = (mb)>>QBSHIFT;        k = lg3a(m);        k = arithmin(k, kb_local);        m = (1<<k)-1;        		n = dyn_get_32bit( in, &bitPos, m, k, maxSize );        // least significant bit is sign bit        {        	uint32_t	ndecode = n + zmode;            int32_t		multiplier = (- (ndecode&1));            multiplier |= 1;            del = ((ndecode+1) >> 1) * (multiplier);        }        *outPtr++ = del;        c++;        mb = pb_local*(n+zmode) + mb - ((pb_local*mb)>>QBSHIFT);		// update mean tracking		if (n > N_MAX_MEAN_CLAMP)			mb = N_MEAN_CLAMP_VAL;        zmode = 0;        if (((mb << MMULSHIFT) < QB) && (c < numSamples))        {            zmode = 1;            k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);            mz = ((1<<k)-1) & wb_local;            n = dyn_get(in, &bitPos, mz, k);            RequireAction(c+n <= numSamples, status = kALAC_ParamError; goto Exit; );            for(j=0; j < n; j++)            {                *outPtr++ = 0;                ++c;                                }            if(n >= 65535)            	zmode = 0;            mb = 0;        }    }Exit:	*outNumBits = (bitPos - startPos);	BitBufferAdvance( bitstream, *outNumBits );	RequireAction( bitstream->cur <= bitstream->end, status = kALAC_ParamError; );    return status;}
 |