it appears a one-character typo in the cmake_minimum_required line prevents it from compiling under CMake 4.0. in order to fix that, I had to take this thing out of submodules... it is recommended to do this after you pull; git submodule deinit extern/libsndfile
653 lines
20 KiB
C
653 lines
20 KiB
C
/*
|
|
* Copyright (c) 2011 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2012-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
|
|
*
|
|
* @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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
|
|
#include "alac_codec.h"
|
|
|
|
#include "dplib.h"
|
|
#include "aglib.h"
|
|
#include "matrixlib.h"
|
|
#include "shift.h"
|
|
|
|
#include "ALACBitUtilities.h"
|
|
#include "EndianPortable.h"
|
|
|
|
typedef enum
|
|
{ false = 0,
|
|
true = 1
|
|
} bool ;
|
|
|
|
// constants/data
|
|
const uint32_t kMaxBitDepth = 32 ; // max allowed bit depth is 32
|
|
|
|
|
|
// prototypes
|
|
static int32_t alac_fill_element (struct BitBuffer * bits) ;
|
|
static int32_t alac_data_stream_element (struct BitBuffer * bits) ;
|
|
|
|
static void Zero32 (int32_t * buffer, uint32_t numItems, uint32_t stride) ;
|
|
|
|
|
|
/*
|
|
Init ()
|
|
- initialize the decoder with the given configuration
|
|
*/
|
|
int32_t
|
|
alac_decoder_init (ALAC_DECODER *p, 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 = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, frameLength)) ;
|
|
|
|
if (theConfig.frameLength > ALAC_FRAME_LENGTH)
|
|
return fALAC_FrameLengthError ;
|
|
|
|
theConfig.compatibleVersion = theActualCookie [offsetof (ALACSpecificConfig, compatibleVersion)] ;
|
|
theConfig.bitDepth = theActualCookie [offsetof (ALACSpecificConfig, bitDepth)] ;
|
|
theConfig.pb = theActualCookie [offsetof (ALACSpecificConfig, pb)] ;
|
|
theConfig.mb = theActualCookie [offsetof (ALACSpecificConfig, mb)] ;
|
|
theConfig.kb = theActualCookie [offsetof (ALACSpecificConfig, kb)] ;
|
|
theConfig.numChannels = theActualCookie [offsetof (ALACSpecificConfig, numChannels)] ;
|
|
theConfig.maxRun = psf_get_be16 (theActualCookie, offsetof (ALACSpecificConfig, maxRun)) ;
|
|
theConfig.maxFrameBytes = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, maxFrameBytes)) ;
|
|
theConfig.avgBitRate = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, avgBitRate)) ;
|
|
theConfig.sampleRate = psf_get_be32 (theActualCookie, offsetof (ALACSpecificConfig, sampleRate)) ;
|
|
|
|
p->mConfig = theConfig ;
|
|
p->mNumChannels = theConfig.numChannels ;
|
|
|
|
RequireAction (p->mConfig.compatibleVersion <= kALACVersion, return kALAC_IncompatibleVersion ;) ;
|
|
RequireAction ((p->mConfig.bitDepth >= 8 && p->mConfig.bitDepth <= 32), return kALAC_BadBitWidth ;) ;
|
|
RequireAction ((p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->u.mPredictor != NULL),
|
|
status = kALAC_MemFullError ; goto Exit ;) ;
|
|
}
|
|
else
|
|
{
|
|
status = kALAC_BadSpecificConfigSize ;
|
|
}
|
|
|
|
// 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
|
|
alac_decode (ALAC_DECODER *p, struct BitBuffer * bits, int32_t * sampleBuffer, uint32_t numSamples, 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 ;
|
|
int32_t * out32 ;
|
|
uint8_t headerByte ;
|
|
uint8_t partialFrame ;
|
|
uint32_t extraBits ;
|
|
int32_t val ;
|
|
uint32_t i, j ;
|
|
int32_t status ;
|
|
uint32_t numChannels = p->mNumChannels ;
|
|
|
|
RequireAction ((bits != NULL) && (sampleBuffer != NULL) && (outNumSamples != NULL), return kALAC_ParamError ;) ;
|
|
RequireAction (p->mNumChannels > 0, return kALAC_ZeroChannelCount ;) ;
|
|
|
|
p->mActiveElements = 0 ;
|
|
channelIndex = 0 ;
|
|
|
|
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 = p->mConfig.pb ;
|
|
|
|
// read element tag
|
|
tag = BitBufferReadSmall (bits, 3) ;
|
|
switch (tag)
|
|
{
|
|
case ID_SCE:
|
|
case ID_LFE:
|
|
{
|
|
// mono/LFE channel
|
|
elementInstanceTag = BitBufferReadSmall (bits, 4) ;
|
|
p->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 = p->mConfig.bitDepth - (bytesShifted * 8) ;
|
|
|
|
// check for partial frame to override requested numSamples
|
|
if (partialFrame != 0)
|
|
{
|
|
numSamples = BitBufferRead (bits, 16) << 16 ;
|
|
numSamples |= BitBufferRead (bits, 16) ;
|
|
|
|
RequireAction (numSamples < kALACDefaultFramesPerPacket, return kALAC_NumSamplesTooBig ;) ;
|
|
}
|
|
|
|
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 shift buffer but remember where it starts
|
|
if (bytesShifted != 0)
|
|
{
|
|
shiftBits = *bits ;
|
|
BitBufferAdvance (bits, (bytesShifted * 8) * numSamples) ;
|
|
}
|
|
|
|
// decompress
|
|
set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ;
|
|
status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ;
|
|
RequireNoErr (status, goto Exit ;) ;
|
|
|
|
if (modeU == 0)
|
|
{
|
|
unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
|
}
|
|
else
|
|
{
|
|
// the special "numActive == 31" mode can be done in-place
|
|
unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
|
unpc_block (p->u.mPredictor, p->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 ;
|
|
p->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 = arith_shift_left (val, 16) >> shift ;
|
|
p->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++)
|
|
p->u.mShiftBuffer [i] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
|
}
|
|
|
|
// convert 32-bit integers into output buffer
|
|
switch (p->mConfig.bitDepth)
|
|
{
|
|
case 16:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
for (i = 0, j = 0 ; i < numSamples ; i++, j += numChannels)
|
|
out32 [j] = arith_shift_left (p->mMixBufferU [i], 16) ;
|
|
break ;
|
|
case 20:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
copyPredictorTo20 (p->mMixBufferU, out32, numChannels, numSamples) ;
|
|
break ;
|
|
case 24:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
if (bytesShifted != 0)
|
|
copyPredictorTo24Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
|
|
else
|
|
copyPredictorTo24 (p->mMixBufferU, out32, numChannels, numSamples) ;
|
|
break ;
|
|
case 32:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
if (bytesShifted != 0)
|
|
copyPredictorTo32Shift (p->mMixBufferU, p->u.mShiftBuffer, out32, numChannels, numSamples, bytesShifted) ;
|
|
else
|
|
copyPredictorTo32 (p->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) ;
|
|
p->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 = p->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) ;
|
|
|
|
RequireAction (numSamples < kALACDefaultFramesPerPacket, return kALAC_NumSamplesTooBig ;) ;
|
|
}
|
|
|
|
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, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ;
|
|
status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits1) ;
|
|
RequireNoErr (status, goto Exit ;) ;
|
|
|
|
if (modeU == 0)
|
|
{
|
|
unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
|
}
|
|
else
|
|
{
|
|
// the special "numActive == 31" mode can be done in-place
|
|
unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
|
unpc_block (p->u.mPredictor, p->mMixBufferU, numSamples, &coefsU [0], numU, chanBits, denShiftU) ;
|
|
}
|
|
|
|
// decompress and run predictor for "right" channel
|
|
set_ag_params (&agParams, p->mConfig.mb, (pb * pbFactorV) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun) ;
|
|
status = dyn_decomp (&agParams, bits, p->u.mPredictor, numSamples, chanBits, &bits2) ;
|
|
RequireNoErr (status, goto Exit ;) ;
|
|
|
|
if (modeV == 0)
|
|
{
|
|
unpc_block (p->u.mPredictor, p->mMixBufferV, numSamples, &coefsV [0], numV, chanBits, denShiftV) ;
|
|
}
|
|
else
|
|
{
|
|
// the special "numActive == 31" mode can be done in-place
|
|
unpc_block (p->u.mPredictor, p->u.mPredictor, numSamples, NULL, 31, chanBits, 0) ;
|
|
unpc_block (p->u.mPredictor, p->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 = p->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 ;
|
|
p->mMixBufferU [i] = val ;
|
|
|
|
val = (int32_t) BitBufferRead (bits, (uint8_t) chanBits) ;
|
|
val = (val << shift) >> shift ;
|
|
p->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 = (((uint32_t) val) << 16) >> shift ;
|
|
p->mMixBufferU [i] = val | BitBufferRead (bits, (uint8_t) extraBits) ;
|
|
|
|
val = (int32_t) BitBufferRead (bits, 16) ;
|
|
val = ((uint32_t) val) >> shift ;
|
|
p->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)
|
|
{
|
|
p->u.mShiftBuffer [i + 0] = (uint16_t) BitBufferRead (&shiftBits, (uint8_t) shift) ;
|
|
p->u.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 (p->mConfig.bitDepth)
|
|
{
|
|
case 16:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
unmix16 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, mixBits, mixRes) ;
|
|
break ;
|
|
case 20:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
unmix20 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples, mixBits, mixRes) ;
|
|
break ;
|
|
case 24:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
unmix24 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
|
|
mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ;
|
|
break ;
|
|
case 32:
|
|
out32 = sampleBuffer + channelIndex ;
|
|
unmix32 (p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
|
|
mixBits, mixRes, p->u.mShiftBuffer, bytesShifted) ;
|
|
break ;
|
|
}
|
|
|
|
channelIndex += 2 ;
|
|
*outNumSamples = numSamples ;
|
|
break ;
|
|
}
|
|
|
|
case ID_CCE:
|
|
case ID_PCE:
|
|
{
|
|
// unsupported element, bail
|
|
//AssertNoErr (tag) ;
|
|
status = kALAC_UnsupportedElement ;
|
|
break ;
|
|
}
|
|
|
|
case ID_DSE:
|
|
{
|
|
// data stream element -- parse but ignore
|
|
status = alac_data_stream_element (bits) ;
|
|
break ;
|
|
}
|
|
|
|
case ID_FIL:
|
|
{
|
|
// fill element -- parse but ignore
|
|
status = alac_fill_element (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 1 // ! 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++)
|
|
{
|
|
int32_t * fill32 = sampleBuffer + channelIndex ;
|
|
Zero32 (fill32, numSamples, numChannels) ;
|
|
}
|
|
|
|
Exit:
|
|
return status ;
|
|
}
|
|
|
|
#if PRAGMA_MARK
|
|
#pragma mark -
|
|
#endif
|
|
|
|
/*
|
|
FillElement ()
|
|
- they're just filler so we don't need 'em
|
|
*/
|
|
static int32_t
|
|
alac_fill_element (struct 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
|
|
*/
|
|
static int32_t
|
|
alac_data_stream_element (struct BitBuffer * bits)
|
|
{
|
|
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 Zero32 (int32_t * buffer, uint32_t numItems, uint32_t stride)
|
|
{
|
|
if (stride == 1)
|
|
{
|
|
memset (buffer, 0, numItems * sizeof (int32_t)) ;
|
|
}
|
|
else
|
|
{
|
|
for (uint32_t indx = 0 ; indx < (numItems * stride) ; indx += stride)
|
|
buffer [indx] = 0 ;
|
|
}
|
|
}
|