diff --git a/alac/codec/ALACBitUtilities.c b/alac/codec/ALACBitUtilities.c new file mode 100644 index 0000000..9414889 --- /dev/null +++ b/alac/codec/ALACBitUtilities.c @@ -0,0 +1,260 @@ +/* + * 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: ALACBitUtilities.c + + $NoKeywords: $ +=============================================================================*/ + +#include +#include "ALACBitUtilities.h" + +// BitBufferInit +// +void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize ) +{ + bits->cur = buffer; + bits->end = bits->cur + byteSize; + bits->bitIndex = 0; + bits->byteSize = byteSize; +} + +// BitBufferRead +// +uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits ) +{ + uint32_t returnBits; + + //Assert( numBits <= 16 ); + + returnBits = ((uint32_t)bits->cur[0] << 16) | ((uint32_t)bits->cur[1] << 8) | ((uint32_t)bits->cur[2]); + returnBits = returnBits << bits->bitIndex; + returnBits &= 0x00FFFFFF; + + bits->bitIndex += numBits; + + returnBits = returnBits >> (24 - numBits); + + bits->cur += (bits->bitIndex >> 3); + bits->bitIndex &= 7; + + //Assert( bits->cur <= bits->end ); + + return returnBits; +} + +// BitBufferReadSmall +// +// Reads up to 8 bits +uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits ) +{ + uint16_t returnBits; + + //Assert( numBits <= 8 ); + + returnBits = (bits->cur[0] << 8) | bits->cur[1]; + returnBits = returnBits << bits->bitIndex; + + bits->bitIndex += numBits; + + returnBits = returnBits >> (16 - numBits); + + bits->cur += (bits->bitIndex >> 3); + bits->bitIndex &= 7; + + //Assert( bits->cur <= bits->end ); + + return (uint8_t)returnBits; +} + +// BitBufferReadOne +// +// Reads one byte +uint8_t BitBufferReadOne( BitBuffer * bits ) +{ + uint8_t returnBits; + + returnBits = (bits->cur[0] >> (7 - bits->bitIndex)) & 1; + + bits->bitIndex++; + + bits->cur += (bits->bitIndex >> 3); + bits->bitIndex &= 7; + + //Assert( bits->cur <= bits->end ); + + return returnBits; +} + +// BitBufferPeek +// +uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits ) +{ + return ((((((uint32_t) bits->cur[0] << 16) | ((uint32_t) bits->cur[1] << 8) | + ((uint32_t) bits->cur[2])) << bits->bitIndex) & 0x00FFFFFF) >> (24 - numBits)); +} + +// BitBufferPeekOne +// +uint32_t BitBufferPeekOne( BitBuffer * bits ) +{ + return ((bits->cur[0] >> (7 - bits->bitIndex)) & 1); +} + +// BitBufferUnpackBERSize +// +uint32_t BitBufferUnpackBERSize( BitBuffer * bits ) +{ + uint32_t size; + uint8_t tmp; + + for ( size = 0, tmp = 0x80u; tmp &= 0x80u; size = (size << 7u) | (tmp & 0x7fu) ) + tmp = (uint8_t) BitBufferReadSmall( bits, 8 ); + + return size; +} + +// BitBufferGetPosition +// +uint32_t BitBufferGetPosition( BitBuffer * bits ) +{ + uint8_t * begin; + + begin = bits->end - bits->byteSize; + + return ((uint32_t)(bits->cur - begin) * 8) + bits->bitIndex; +} + +// BitBufferByteAlign +// +void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros ) +{ + // align bit buffer to next byte boundary, writing zeros if requested + if ( bits->bitIndex == 0 ) + return; + + if ( addZeros ) + BitBufferWrite( bits, 0, 8 - bits->bitIndex ); + else + BitBufferAdvance( bits, 8 - bits->bitIndex ); +} + +// BitBufferAdvance +// +void BitBufferAdvance( BitBuffer * bits, uint32_t numBits ) +{ + if ( numBits ) + { + bits->bitIndex += numBits; + bits->cur += (bits->bitIndex >> 3); + bits->bitIndex &= 7; + } +} + +// BitBufferRewind +// +void BitBufferRewind( BitBuffer * bits, uint32_t numBits ) +{ + uint32_t numBytes; + + if ( numBits == 0 ) + return; + + if ( bits->bitIndex >= numBits ) + { + bits->bitIndex -= numBits; + return; + } + + numBits -= bits->bitIndex; + bits->bitIndex = 0; + + numBytes = numBits / 8; + numBits = numBits % 8; + + bits->cur -= numBytes; + + if ( numBits > 0 ) + { + bits->bitIndex = 8 - numBits; + bits->cur--; + } + + if ( bits->cur < (bits->end - bits->byteSize) ) + { + //DebugCMsg("BitBufferRewind: Rewound too far."); + + bits->cur = (bits->end - bits->byteSize); + bits->bitIndex = 0; + } +} + +// BitBufferWrite +// +void BitBufferWrite( BitBuffer * bits, uint32_t bitValues, uint32_t numBits ) +{ + uint32_t invBitIndex; + + RequireAction( bits != nil, return; ); + RequireActionSilent( numBits > 0, return; ); + + invBitIndex = 8 - bits->bitIndex; + + while ( numBits > 0 ) + { + uint32_t tmp; + uint8_t shift; + uint8_t mask; + uint32_t curNum; + + curNum = MIN( invBitIndex, numBits ); + + tmp = bitValues >> (numBits - curNum); + + shift = (uint8_t)(invBitIndex - curNum); + mask = 0xffu >> (8 - curNum); // must be done in two steps to avoid compiler sequencing ambiguity + mask <<= shift; + + bits->cur[0] = (bits->cur[0] & ~mask) | (((uint8_t) tmp << shift) & mask); + numBits -= curNum; + + // increment to next byte if need be + invBitIndex -= curNum; + if ( invBitIndex == 0 ) + { + invBitIndex = 8; + bits->cur++; + } + } + + bits->bitIndex = 8 - invBitIndex; +} + +void BitBufferReset( BitBuffer * bits ) +//void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize ) +{ + bits->cur = bits->end - bits->byteSize; + bits->bitIndex = 0; +} + +#if PRAGMA_MARK +#pragma mark - +#endif diff --git a/alac/codec/ALACBitUtilities.h b/alac/codec/ALACBitUtilities.h new file mode 100644 index 0000000..97e9ebe --- /dev/null +++ b/alac/codec/ALACBitUtilities.h @@ -0,0 +1,104 @@ +/* + * 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: ALACBitUtilities.h + + $NoKeywords: $ +=============================================================================*/ + +#ifndef __ALACBITUTILITIES_H +#define __ALACBITUTILITIES_H + +#include + +#ifndef MIN +#define MIN(x, y) ( (x)<(y) ?(x) :(y) ) +#endif //MIN +#ifndef MAX +#define MAX(x, y) ( (x)>(y) ?(x): (y) ) +#endif //MAX + +#ifndef nil +#define nil NULL +#endif + +#define RequireAction(condition, action) if (!(condition)) { action } +#define RequireActionSilent(condition, action) if (!(condition)) { action } +#define RequireNoErr(condition, action) if ((condition)) { action } + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + ALAC_noErr = 0 +}; + + +typedef enum +{ + + ID_SCE = 0, /* Single Channel Element */ + ID_CPE = 1, /* Channel Pair Element */ + ID_CCE = 2, /* Coupling Channel Element */ + ID_LFE = 3, /* LFE Channel Element */ + ID_DSE = 4, /* not yet supported */ + ID_PCE = 5, + ID_FIL = 6, + ID_END = 7 +} ELEMENT_TYPE; + +// types +typedef struct BitBuffer +{ + uint8_t * cur; + uint8_t * end; + uint32_t bitIndex; + uint32_t byteSize; + +} BitBuffer; + +/* + BitBuffer routines + - these routines take a fixed size buffer and read/write to it + - bounds checking must be done by the client +*/ +void BitBufferInit( BitBuffer * bits, uint8_t * buffer, uint32_t byteSize ); +uint32_t BitBufferRead( BitBuffer * bits, uint8_t numBits ); // note: cannot read more than 16 bits at a time +uint8_t BitBufferReadSmall( BitBuffer * bits, uint8_t numBits ); +uint8_t BitBufferReadOne( BitBuffer * bits ); +uint32_t BitBufferPeek( BitBuffer * bits, uint8_t numBits ); // note: cannot read more than 16 bits at a time +uint32_t BitBufferPeekOne( BitBuffer * bits ); +uint32_t BitBufferUnpackBERSize( BitBuffer * bits ); +uint32_t BitBufferGetPosition( BitBuffer * bits ); +void BitBufferByteAlign( BitBuffer * bits, int32_t addZeros ); +void BitBufferAdvance( BitBuffer * bits, uint32_t numBits ); +void BitBufferRewind( BitBuffer * bits, uint32_t numBits ); +void BitBufferWrite( BitBuffer * bits, uint32_t value, uint32_t numBits ); +void BitBufferReset( BitBuffer * bits); + + +#ifdef __cplusplus +} +#endif + +#endif /* __BITUTILITIES_H */ diff --git a/alac/codec/ALACDecoder.cpp b/alac/codec/ALACDecoder.cpp new file mode 100644 index 0000000..ce3340d --- /dev/null +++ b/alac/codec/ALACDecoder.cpp @@ -0,0 +1,730 @@ +/* + * 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: ALACDecoder.cpp +*/ + +#include +#include + +#include "ALACDecoder.h" + +#include "dplib.h" +#include "aglib.h" +#include "matrixlib.h" + +#include "ALACBitUtilities.h" +#include "EndianPortable.h" + +// constants/data +const uint32_t kMaxBitDepth = 32; // max allowed bit depth is 32 + + +// prototypes +static void Zero16( int16_t * buffer, uint32_t numItems, uint32_t stride ); +static void Zero24( uint8_t * buffer, uint32_t numItems, uint32_t stride ); +static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride ); + +/* + Constructor +*/ +ALACDecoder::ALACDecoder() : + mMixBufferU( nil ), + mMixBufferV( nil ), + mPredictor( nil ), + mShiftBuffer( nil ) +{ + memset( &mConfig, 0, sizeof(mConfig) ); +} + +/* + Destructor +*/ +ALACDecoder::~ALACDecoder() +{ + // delete the matrix mixing buffers + if ( mMixBufferU ) + { + free(mMixBufferU); + mMixBufferU = NULL; + } + if ( mMixBufferV ) + { + free(mMixBufferV); + mMixBufferV = NULL; + } + + // delete the dynamic predictor's "corrector" buffer + // - note: mShiftBuffer shares memory with this buffer + if ( mPredictor ) + { + free(mPredictor); + mPredictor = NULL; + } +} + +/* + Init() + - initialize the decoder with the given configuration +*/ +int32_t ALACDecoder::Init( void * inMagicCookie, uint32_t inMagicCookieSize ) +{ + int32_t status = ALAC_noErr; + ALACSpecificConfig theConfig; + uint8_t * theActualCookie = (uint8_t *)inMagicCookie; + uint32_t theCookieBytesRemaining = inMagicCookieSize; + + // For historical reasons the decoder needs to be resilient to magic cookies vended by older encoders. + // As specified in the ALACMagicCookieDescription.txt document, there may be additional data encapsulating + // the ALACSpecificConfig. This would consist of format ('frma') and 'alac' atoms which precede the + // ALACSpecificConfig. + // See ALACMagicCookieDescription.txt for additional documentation concerning the 'magic cookie' + + // skip format ('frma') atom if present + if (theActualCookie[4] == 'f' && theActualCookie[5] == 'r' && theActualCookie[6] == 'm' && theActualCookie[7] == 'a') + { + theActualCookie += 12; + theCookieBytesRemaining -= 12; + } + + // skip 'alac' atom header if present + if (theActualCookie[4] == 'a' && theActualCookie[5] == 'l' && theActualCookie[6] == 'a' && theActualCookie[7] == 'c') + { + theActualCookie += 12; + theCookieBytesRemaining -= 12; + } + + // read the ALACSpecificConfig + if (theCookieBytesRemaining >= sizeof(ALACSpecificConfig)) + { + theConfig.frameLength = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->frameLength); + theConfig.compatibleVersion = ((ALACSpecificConfig *)theActualCookie)->compatibleVersion; + theConfig.bitDepth = ((ALACSpecificConfig *)theActualCookie)->bitDepth; + theConfig.pb = ((ALACSpecificConfig *)theActualCookie)->pb; + theConfig.mb = ((ALACSpecificConfig *)theActualCookie)->mb; + theConfig.kb = ((ALACSpecificConfig *)theActualCookie)->kb; + theConfig.numChannels = ((ALACSpecificConfig *)theActualCookie)->numChannels; + theConfig.maxRun = Swap16BtoN(((ALACSpecificConfig *)theActualCookie)->maxRun); + theConfig.maxFrameBytes = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->maxFrameBytes); + theConfig.avgBitRate = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->avgBitRate); + theConfig.sampleRate = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->sampleRate); + + mConfig = theConfig; + + RequireAction( mConfig.compatibleVersion <= kALACVersion, return kALAC_ParamError; ); + + // allocate mix buffers + mMixBufferU = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 ); + mMixBufferV = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 ); + + // allocate dynamic predictor buffer + mPredictor = (int32_t *) calloc( mConfig.frameLength * sizeof(int32_t), 1 ); + + // "shift off" buffer shares memory with predictor buffer + mShiftBuffer = (uint16_t *) mPredictor; + + RequireAction( (mMixBufferU != nil) && (mMixBufferV != nil) && (mPredictor != nil), + status = kALAC_MemFullError; goto Exit; ); + } + else + { + status = kALAC_ParamError; + } + + // skip to Channel Layout Info + // theActualCookie += sizeof(ALACSpecificConfig); + + // Currently, the Channel Layout Info portion of the magic cookie (as defined in the + // ALACMagicCookieDescription.txt document) is unused by the decoder. + +Exit: + return status; +} + +/* + Decode() + - the decoded samples are interleaved into the output buffer in the order they arrive in + the bitstream +*/ +int32_t ALACDecoder::Decode( BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples ) +{ + BitBuffer shiftBits; + uint32_t bits1, bits2; + uint8_t tag; + uint8_t elementInstanceTag; + AGParamRec agParams; + uint32_t channelIndex; + int16_t coefsU[32]; // max possible size is 32 although NUMCOEPAIRS is the current limit + int16_t coefsV[32]; + uint8_t numU, numV; + uint8_t mixBits; + int8_t mixRes; + uint16_t unusedHeader; + uint8_t escapeFlag; + uint32_t chanBits; + uint8_t bytesShifted; + uint32_t shift; + uint8_t modeU, modeV; + uint32_t denShiftU, denShiftV; + uint16_t pbFactorU, pbFactorV; + uint16_t pb; + int16_t * samples; + int16_t * out16; + uint8_t * out20; + uint8_t * out24; + int32_t * out32; + uint8_t headerByte; + uint8_t partialFrame; + uint32_t extraBits; + int32_t val; + uint32_t i, j; + int32_t status; + + RequireAction( (bits != nil) && (sampleBuffer != nil) && (outNumSamples != nil), return kALAC_ParamError; ); + RequireAction( numChannels > 0, return kALAC_ParamError; ); + + mActiveElements = 0; + channelIndex = 0; + + samples = (int16_t *) sampleBuffer; + + status = ALAC_noErr; + *outNumSamples = numSamples; + + while ( status == ALAC_noErr ) + { + // bail if we ran off the end of the buffer + RequireAction( bits->cur < bits->end, status = kALAC_ParamError; goto Exit; ); + + // copy global decode params for this element + pb = mConfig.pb; + + // read element tag + tag = BitBufferReadSmall( bits, 3 ); + switch ( tag ) + { + case ID_SCE: + case ID_LFE: + { + // mono/LFE channel + elementInstanceTag = BitBufferReadSmall( bits, 4 ); + mActiveElements |= (1u << elementInstanceTag); + + // read the 12 unused header bits + unusedHeader = (uint16_t) BitBufferRead( bits, 12 ); + RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; ); + + // read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag + headerByte = (uint8_t) BitBufferRead( bits, 4 ); + + partialFrame = headerByte >> 3; + + bytesShifted = (headerByte >> 1) & 0x3u; + RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; ); + + shift = bytesShifted * 8; + + escapeFlag = headerByte & 0x1; + + chanBits = mConfig.bitDepth - (bytesShifted * 8); + + // check for partial frame to override requested numSamples + if ( partialFrame != 0 ) + { + numSamples = BitBufferRead( bits, 16 ) << 16; + numSamples |= BitBufferRead( bits, 16 ); + } + + if ( escapeFlag == 0 ) + { + // compressed frame, read rest of parameters + mixBits = (uint8_t) BitBufferRead( bits, 8 ); + mixRes = (int8_t) BitBufferRead( bits, 8 ); + //Assert( (mixBits == 0) && (mixRes == 0) ); // no mixing for mono + + headerByte = (uint8_t) BitBufferRead( bits, 8 ); + modeU = headerByte >> 4; + denShiftU = headerByte & 0xfu; + + headerByte = (uint8_t) BitBufferRead( bits, 8 ); + pbFactorU = headerByte >> 5; + numU = headerByte & 0x1fu; + + for ( i = 0; i < numU; i++ ) + coefsU[i] = (int16_t) BitBufferRead( bits, 16 ); + + // if shift active, skip the the shift buffer but remember where it starts + if ( bytesShifted != 0 ) + { + shiftBits = *bits; + BitBufferAdvance( bits, (bytesShifted * 8) * numSamples ); + } + + // decompress + set_ag_params( &agParams, mConfig.mb, (pb * pbFactorU) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun ); + status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits1 ); + RequireNoErr( status, goto Exit; ); + + if ( modeU == 0 ) + { + unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU ); + } + else + { + // the special "numActive == 31" mode can be done in-place + unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 ); + unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU ); + } + } + else + { + //Assert( bytesShifted == 0 ); + + // uncompressed frame, copy data into the mix buffer to use common output code + shift = 32 - chanBits; + if ( chanBits <= 16 ) + { + for ( i = 0; i < numSamples; i++ ) + { + val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits ); + val = (val << shift) >> shift; + mMixBufferU[i] = val; + } + } + else + { + // BitBufferRead() can't read more than 16 bits at a time so break up the reads + extraBits = chanBits - 16; + for ( i = 0; i < numSamples; i++ ) + { + val = (int32_t) BitBufferRead( bits, 16 ); + val = (val << 16) >> shift; + mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t) extraBits ); + } + } + + mixBits = mixRes = 0; + bits1 = chanBits * numSamples; + bytesShifted = 0; + } + + // now read the shifted values into the shift buffer + if ( bytesShifted != 0 ) + { + shift = bytesShifted * 8; + //Assert( shift <= 16 ); + + for ( i = 0; i < numSamples; i++ ) + mShiftBuffer[i] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift ); + } + + // convert 32-bit integers into output buffer + switch ( mConfig.bitDepth ) + { + case 16: + out16 = &((int16_t *)sampleBuffer)[channelIndex]; + for ( i = 0, j = 0; i < numSamples; i++, j += numChannels ) + out16[j] = (int16_t) mMixBufferU[i]; + break; + case 20: + out20 = (uint8_t *)sampleBuffer + (channelIndex * 3); + copyPredictorTo20( mMixBufferU, out20, numChannels, numSamples ); + break; + case 24: + out24 = (uint8_t *)sampleBuffer + (channelIndex * 3); + if ( bytesShifted != 0 ) + copyPredictorTo24Shift( mMixBufferU, mShiftBuffer, out24, numChannels, numSamples, bytesShifted ); + else + copyPredictorTo24( mMixBufferU, out24, numChannels, numSamples ); + break; + case 32: + out32 = &((int32_t *)sampleBuffer)[channelIndex]; + if ( bytesShifted != 0 ) + copyPredictorTo32Shift( mMixBufferU, mShiftBuffer, out32, numChannels, numSamples, bytesShifted ); + else + copyPredictorTo32( mMixBufferU, out32, numChannels, numSamples); + break; + } + + channelIndex += 1; + *outNumSamples = numSamples; + break; + } + + case ID_CPE: + { + // if decoding this pair would take us over the max channels limit, bail + if ( (channelIndex + 2) > numChannels ) + goto NoMoreChannels; + + // stereo channel pair + elementInstanceTag = BitBufferReadSmall( bits, 4 ); + mActiveElements |= (1u << elementInstanceTag); + + // read the 12 unused header bits + unusedHeader = (uint16_t) BitBufferRead( bits, 12 ); + RequireAction( unusedHeader == 0, status = kALAC_ParamError; goto Exit; ); + + // read the 1-bit "partial frame" flag, 2-bit "shift-off" flag & 1-bit "escape" flag + headerByte = (uint8_t) BitBufferRead( bits, 4 ); + + partialFrame = headerByte >> 3; + + bytesShifted = (headerByte >> 1) & 0x3u; + RequireAction( bytesShifted != 3, status = kALAC_ParamError; goto Exit; ); + + shift = bytesShifted * 8; + + escapeFlag = headerByte & 0x1; + + chanBits = mConfig.bitDepth - (bytesShifted * 8) + 1; + + // check for partial frame length to override requested numSamples + if ( partialFrame != 0 ) + { + numSamples = BitBufferRead( bits, 16 ) << 16; + numSamples |= BitBufferRead( bits, 16 ); + } + + if ( escapeFlag == 0 ) + { + // compressed frame, read rest of parameters + mixBits = (uint8_t) BitBufferRead( bits, 8 ); + mixRes = (int8_t) BitBufferRead( bits, 8 ); + + headerByte = (uint8_t) BitBufferRead( bits, 8 ); + modeU = headerByte >> 4; + denShiftU = headerByte & 0xfu; + + headerByte = (uint8_t) BitBufferRead( bits, 8 ); + pbFactorU = headerByte >> 5; + numU = headerByte & 0x1fu; + for ( i = 0; i < numU; i++ ) + coefsU[i] = (int16_t) BitBufferRead( bits, 16 ); + + headerByte = (uint8_t) BitBufferRead( bits, 8 ); + modeV = headerByte >> 4; + denShiftV = headerByte & 0xfu; + + headerByte = (uint8_t) BitBufferRead( bits, 8 ); + pbFactorV = headerByte >> 5; + numV = headerByte & 0x1fu; + for ( i = 0; i < numV; i++ ) + coefsV[i] = (int16_t) BitBufferRead( bits, 16 ); + + // if shift active, skip the interleaved shifted values but remember where they start + if ( bytesShifted != 0 ) + { + shiftBits = *bits; + BitBufferAdvance( bits, (bytesShifted * 8) * 2 * numSamples ); + } + + // decompress and run predictor for "left" channel + set_ag_params( &agParams, mConfig.mb, (pb * pbFactorU) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun ); + status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits1 ); + RequireNoErr( status, goto Exit; ); + + if ( modeU == 0 ) + { + unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU ); + } + else + { + // the special "numActive == 31" mode can be done in-place + unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 ); + unpc_block( mPredictor, mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU ); + } + + // decompress and run predictor for "right" channel + set_ag_params( &agParams, mConfig.mb, (pb * pbFactorV) / 4, mConfig.kb, numSamples, numSamples, mConfig.maxRun ); + status = dyn_decomp( &agParams, bits, mPredictor, numSamples, chanBits, &bits2 ); + RequireNoErr( status, goto Exit; ); + + if ( modeV == 0 ) + { + unpc_block( mPredictor, mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV ); + } + else + { + // the special "numActive == 31" mode can be done in-place + unpc_block( mPredictor, mPredictor, numSamples, nil, 31, chanBits, 0 ); + unpc_block( mPredictor, mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV ); + } + } + else + { + //Assert( bytesShifted == 0 ); + + // uncompressed frame, copy data into the mix buffers to use common output code + chanBits = mConfig.bitDepth; + shift = 32 - chanBits; + if ( chanBits <= 16 ) + { + for ( i = 0; i < numSamples; i++ ) + { + val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits ); + val = (val << shift) >> shift; + mMixBufferU[i] = val; + + val = (int32_t) BitBufferRead( bits, (uint8_t) chanBits ); + val = (val << shift) >> shift; + mMixBufferV[i] = val; + } + } + else + { + // BitBufferRead() can't read more than 16 bits at a time so break up the reads + extraBits = chanBits - 16; + for ( i = 0; i < numSamples; i++ ) + { + val = (int32_t) BitBufferRead( bits, 16 ); + val = (val << 16) >> shift; + mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t)extraBits ); + + val = (int32_t) BitBufferRead( bits, 16 ); + val = (val << 16) >> shift; + mMixBufferV[i] = val | BitBufferRead( bits, (uint8_t)extraBits ); + } + } + + bits1 = chanBits * numSamples; + bits2 = chanBits * numSamples; + mixBits = mixRes = 0; + bytesShifted = 0; + } + + // now read the shifted values into the shift buffer + if ( bytesShifted != 0 ) + { + shift = bytesShifted * 8; + //Assert( shift <= 16 ); + + for ( i = 0; i < (numSamples * 2); i += 2 ) + { + mShiftBuffer[i + 0] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift ); + mShiftBuffer[i + 1] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift ); + } + } + + // un-mix the data and convert to output format + // - note that mixRes = 0 means just interleave so we use that path for uncompressed frames + switch ( mConfig.bitDepth ) + { + case 16: + out16 = &((int16_t *)sampleBuffer)[channelIndex]; + unmix16( mMixBufferU, mMixBufferV, out16, numChannels, numSamples, mixBits, mixRes ); + break; + case 20: + out20 = (uint8_t *)sampleBuffer + (channelIndex * 3); + unmix20( mMixBufferU, mMixBufferV, out20, numChannels, numSamples, mixBits, mixRes ); + break; + case 24: + out24 = (uint8_t *)sampleBuffer + (channelIndex * 3); + unmix24( mMixBufferU, mMixBufferV, out24, numChannels, numSamples, + mixBits, mixRes, mShiftBuffer, bytesShifted ); + break; + case 32: + out32 = &((int32_t *)sampleBuffer)[channelIndex]; + unmix32( mMixBufferU, mMixBufferV, out32, numChannels, numSamples, + mixBits, mixRes, mShiftBuffer, bytesShifted ); + break; + } + + channelIndex += 2; + *outNumSamples = numSamples; + break; + } + + case ID_CCE: + case ID_PCE: + { + // unsupported element, bail + //AssertNoErr( tag ); + status = kALAC_ParamError; + break; + } + + case ID_DSE: + { + // data stream element -- parse but ignore + status = this->DataStreamElement( bits ); + break; + } + + case ID_FIL: + { + // fill element -- parse but ignore + status = this->FillElement( bits ); + break; + } + + case ID_END: + { + // frame end, all done so byte align the frame and check for overruns + BitBufferByteAlign( bits, false ); + //Assert( bits->cur == bits->end ); + goto Exit; + } + } + +#if ! DEBUG + // if we've decoded all of our channels, bail (but not in debug b/c we want to know if we're seeing bad bits) + // - this also protects us if the config does not match the bitstream or crap data bits follow the audio bits + if ( channelIndex >= numChannels ) + break; +#endif + } + +NoMoreChannels: + + // if we get here and haven't decoded all of the requested channels, fill the remaining channels with zeros + for ( ; channelIndex < numChannels; channelIndex++ ) + { + switch ( mConfig.bitDepth ) + { + case 16: + { + int16_t * fill16 = &((int16_t *)sampleBuffer)[channelIndex]; + Zero16( fill16, numSamples, numChannels ); + break; + } + case 24: + { + uint8_t * fill24 = (uint8_t *)sampleBuffer + (channelIndex * 3); + Zero24( fill24, numSamples, numChannels ); + break; + } + case 32: + { + int32_t * fill32 = &((int32_t *)sampleBuffer)[channelIndex]; + Zero32( fill32, numSamples, numChannels ); + break; + } + } + } + +Exit: + return status; +} + +#if PRAGMA_MARK +#pragma mark - +#endif + +/* + FillElement() + - they're just filler so we don't need 'em +*/ +int32_t ALACDecoder::FillElement( BitBuffer * bits ) +{ + int16_t count; + + // 4-bit count or (4-bit + 8-bit count) if 4-bit count == 15 + // - plus this weird -1 thing I still don't fully understand + count = BitBufferReadSmall( bits, 4 ); + if ( count == 15 ) + count += (int16_t) BitBufferReadSmall( bits, 8 ) - 1; + + BitBufferAdvance( bits, count * 8 ); + + RequireAction( bits->cur <= bits->end, return kALAC_ParamError; ); + + return ALAC_noErr; +} + +/* + DataStreamElement() + - we don't care about data stream elements so just skip them +*/ +int32_t ALACDecoder::DataStreamElement( BitBuffer * bits ) +{ + uint8_t element_instance_tag; + int32_t data_byte_align_flag; + uint16_t count; + + // the tag associates this data stream element with a given audio element + element_instance_tag = BitBufferReadSmall( bits, 4 ); + + data_byte_align_flag = BitBufferReadOne( bits ); + + // 8-bit count or (8-bit + 8-bit count) if 8-bit count == 255 + count = BitBufferReadSmall( bits, 8 ); + if ( count == 255 ) + count += BitBufferReadSmall( bits, 8 ); + + // the align flag means the bitstream should be byte-aligned before reading the following data bytes + if ( data_byte_align_flag ) + BitBufferByteAlign( bits, false ); + + // skip the data bytes + BitBufferAdvance( bits, count * 8 ); + + RequireAction( bits->cur <= bits->end, return kALAC_ParamError; ); + + return ALAC_noErr; +} + +/* + ZeroN() + - helper routines to clear out output channel buffers when decoding fewer channels than requested +*/ +static void Zero16( int16_t * buffer, uint32_t numItems, uint32_t stride ) +{ + if ( stride == 1 ) + { + memset( buffer, 0, numItems * sizeof(int16_t) ); + } + else + { + for ( uint32_t index = 0; index < (numItems * stride); index += stride ) + buffer[index] = 0; + } +} + +static void Zero24( uint8_t * buffer, uint32_t numItems, uint32_t stride ) +{ + if ( stride == 1 ) + { + memset( buffer, 0, numItems * 3 ); + } + else + { + for ( uint32_t index = 0; index < (numItems * stride * 3); index += (stride * 3) ) + { + buffer[index + 0] = 0; + buffer[index + 1] = 0; + buffer[index + 2] = 0; + } + } +} + +static void Zero32( int32_t * buffer, uint32_t numItems, uint32_t stride ) +{ + if ( stride == 1 ) + { + memset( buffer, 0, numItems * sizeof(int32_t) ); + } + else + { + for ( uint32_t index = 0; index < (numItems * stride); index += stride ) + buffer[index] = 0; + } +}