src/ALAC/* : Big code dump of code for Apple's ALAC file format.

This commit is contained in:
Erik de Castro Lopo 2012-03-03 23:00:07 +11:00
parent cf5a13e84a
commit 297cb9c3bd
24 changed files with 5864 additions and 0 deletions

View File

@ -1,3 +1,12 @@
2012-02-03 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* src/ALAC/*
Big code dump of code for Apple's ALAC file format. This copyyright to this
code is owned by Apple who have released it under an Apache style license.
A few modifications were made to allow this to be integrated into libsndfile
but unfortunately the history of those changes were lost because they were
developed in a Bzr tree and during that time libsndfile moved to Git.
2012-02-02 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
* src/aiff.c src/wav.c

3
README
View File

@ -20,6 +20,9 @@ Bormann. Their original code can be found at :
The src/G72x directory contains code written and released by Sun Microsystems
under a suitably free license.
The src/ALAC directory contains code written and released by Apple Inc and
released under the Apache license.
LINUX
-----

200
src/ALAC/ALACAudioTypes.h Normal file
View File

@ -0,0 +1,200 @@
/*
* 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: ALACAudioTypes.h
*/
#ifndef ALACAUDIOTYPES_H
#define ALACAUDIOTYPES_H
/* Force these Mac OS specific things to zero. */
#define PRAGMA_STRUCT_ALIGN 0
#define PRAGMA_STRUCT_PACKPUSH 0
#define PRAGMA_STRUCT_PACK 0
#define PRAGMA_ONCE 0
#define PRAGMA_MARK 0
#if PRAGMA_ONCE
#pragma once
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include "sfendian.h"
#if CPU_IS_BIG_ENDIAN == 1
#define TARGET_RT_BIG_ENDIAN 1
#else
#define TARGET_RT_BIG_ENDIAN 0
#endif
#define kChannelAtomSize 12
enum
{
kALAC_UnimplementedError = -4,
kALAC_FileNotFoundError = -43,
kALAC_ParamError = -50,
kALAC_MemFullError = -108,
fALAC_FrameLengthError = -666,
};
enum
{
kALACFormatAppleLossless = MAKE_MARKER ('a', 'l', 'a', 'c'),
kALACFormatLinearPCM = MAKE_MARKER ('l', 'p', 'c', 'm')
};
enum
{
kALACMaxChannels = 8,
kALACMaxEscapeHeaderBytes = 8,
kALACMaxSearches = 16,
kALACMaxCoefs = 16,
kALACDefaultFramesPerPacket = 4096
};
typedef uint32_t ALACChannelLayoutTag;
enum
{
kALACFormatFlagIsFloat = (1 << 0), // 0x1
kALACFormatFlagIsBigEndian = (1 << 1), // 0x2
kALACFormatFlagIsSignedInteger = (1 << 2), // 0x4
kALACFormatFlagIsPacked = (1 << 3), // 0x8
kALACFormatFlagIsAlignedHigh = (1 << 4), // 0x10
};
enum
{
#if TARGET_RT_BIG_ENDIAN
kALACFormatFlagsNativeEndian = kALACFormatFlagIsBigEndian
#else
kALACFormatFlagsNativeEndian = 0
#endif
};
// this is required to be an IEEE 64bit float
typedef double alac_float64_t;
// These are the Channel Layout Tags used in the Channel Layout Info portion of the ALAC magic cookie
enum
{
kALACChannelLayoutTag_Mono = (100<<16) | 1, // C
kALACChannelLayoutTag_Stereo = (101<<16) | 2, // L R
kALACChannelLayoutTag_MPEG_3_0_B = (113<<16) | 3, // C L R
kALACChannelLayoutTag_MPEG_4_0_B = (116<<16) | 4, // C L R Cs
kALACChannelLayoutTag_MPEG_5_0_D = (120<<16) | 5, // C L R Ls Rs
kALACChannelLayoutTag_MPEG_5_1_D = (124<<16) | 6, // C L R Ls Rs LFE
kALACChannelLayoutTag_AAC_6_1 = (142<<16) | 7, // C L R Ls Rs Cs LFE
kALACChannelLayoutTag_MPEG_7_1_B = (127<<16) | 8 // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// ALAC currently only utilizes these channels layouts. There is a one for one correspondance between a
// given number of channels and one of these layout tags
static const ALACChannelLayoutTag ALACChannelLayoutTags[kALACMaxChannels] =
{
kALACChannelLayoutTag_Mono, // C
kALACChannelLayoutTag_Stereo, // L R
kALACChannelLayoutTag_MPEG_3_0_B, // C L R
kALACChannelLayoutTag_MPEG_4_0_B, // C L R Cs
kALACChannelLayoutTag_MPEG_5_0_D, // C L R Ls Rs
kALACChannelLayoutTag_MPEG_5_1_D, // C L R Ls Rs LFE
kALACChannelLayoutTag_AAC_6_1, // C L R Ls Rs Cs LFE
kALACChannelLayoutTag_MPEG_7_1_B // C Lc Rc L R Ls Rs LFE (doc: IS-13818-7 MPEG2-AAC)
};
// AudioChannelLayout from CoreAudioTypes.h. We never need the AudioChannelDescription so we remove it
struct ALACAudioChannelLayout
{
ALACChannelLayoutTag mChannelLayoutTag;
uint32_t mChannelBitmap;
uint32_t mNumberChannelDescriptions;
};
typedef struct ALACAudioChannelLayout ALACAudioChannelLayout;
struct AudioFormatDescription
{
alac_float64_t mSampleRate;
uint32_t mFormatID;
uint32_t mFormatFlags;
uint32_t mBytesPerPacket;
uint32_t mFramesPerPacket;
uint32_t mBytesPerFrame;
uint32_t mChannelsPerFrame;
uint32_t mBitsPerChannel;
uint32_t mReserved;
};
typedef struct AudioFormatDescription AudioFormatDescription;
/* Lossless Definitions */
enum
{
kALACCodecFormat = MAKE_MARKER ('a', 'l', 'a', 'c'),
kALACVersion = 0,
kALACCompatibleVersion = kALACVersion,
kALACDefaultFrameSize = 4096
};
// note: this struct is wrapped in an 'alac' atom in the sample description extension area
// note: in QT movies, it will be further wrapped in a 'wave' atom surrounded by 'frma' and 'term' atoms
typedef struct ALACSpecificConfig
{
uint32_t frameLength;
uint8_t compatibleVersion;
uint8_t bitDepth; // max 32
uint8_t pb; // 0 <= pb <= 255
uint8_t mb;
uint8_t kb;
uint8_t numChannels;
uint16_t maxRun;
uint32_t maxFrameBytes;
uint32_t avgBitRate;
uint32_t sampleRate;
} ALACSpecificConfig;
// The AudioChannelLayout atom type is not exposed yet so define it here
enum
{
AudioChannelLayoutAID = MAKE_MARKER ('c', 'h', 'a', 'n')
};
#if PRAGMA_STRUCT_ALIGN
#pragma options align=reset
#elif PRAGMA_STRUCT_PACKPUSH
#pragma pack(pop)
#elif PRAGMA_STRUCT_PACK
#pragma pack()
#endif
#ifdef __cplusplus
}
#endif
#endif /* ALACAUDIOTYPES_H */

262
src/ALAC/ALACBitUtilities.c Normal file
View File

@ -0,0 +1,262 @@
/*
* 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 <stdio.h>
#include "ALACBitUtilities.h"
#define PRAGMA_MARK 0
// 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 != NULL, 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

View File

@ -0,0 +1,91 @@
/*
* 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 <stdint.h>
#ifndef MIN
#define MIN(x, y) ( (x)<(y) ?(x) :(y) )
#endif //MIN
#ifndef MAX
#define MAX(x, y) ( (x)>(y) ?(x): (y) )
#endif //MAX
#define RequireAction(condition, action) if (!(condition)) { action }
#define RequireActionSilent(condition, action) if (!(condition)) { action }
#define RequireNoErr(condition, action) if ((condition)) { action }
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);
#endif /* __BITUTILITIES_H */

61
src/ALAC/ALACDecoder.h Normal file
View File

@ -0,0 +1,61 @@
/*
* 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.h
*/
#ifndef _ALACDECODER_H
#define _ALACDECODER_H
#include <stdint.h>
#include "ALACAudioTypes.h"
struct BitBuffer;
class ALACDecoder
{
public:
ALACDecoder();
~ALACDecoder();
int32_t Init( void * inMagicCookie, uint32_t inMagicCookieSize );
int32_t Decode( struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples );
public:
// decoding parameters (public for use in the analyzer)
ALACSpecificConfig mConfig;
protected:
int32_t FillElement( struct BitBuffer * bits );
int32_t DataStreamElement( struct BitBuffer * bits );
uint16_t mActiveElements;
// decoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictor;
uint16_t * mShiftBuffer; // note: this points to mPredictor's memory but different
// variable for clarity and type difference
};
#endif /* _ALACDECODER_H */

92
src/ALAC/ALACEncoder.h Normal file
View File

@ -0,0 +1,92 @@
/*
* 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: ALACEncoder.h
*/
#pragma once
#include <stdint.h>
#include "ALACAudioTypes.h"
struct BitBuffer;
class ALACEncoder
{
public:
ALACEncoder();
virtual ~ALACEncoder();
virtual int32_t Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat,
unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes);
virtual int32_t Finish( );
void SetFastMode( bool fast ) { mFastMode = fast; };
// this must be called *before* InitializeEncoder()
void SetFrameSize( uint32_t frameSize ) { mFrameSize = frameSize; };
void GetConfig( ALACSpecificConfig & config );
uint32_t GetMagicCookieSize(uint32_t inNumChannels);
void GetMagicCookie( void * config, uint32_t * ioSize );
virtual int32_t InitializeEncoder(AudioFormatDescription theOutputFormat);
protected:
virtual void GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output );
int32_t EncodeStereo( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoFast( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoEscape( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t numSamples );
int32_t EncodeMono( struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
// ALAC encoder parameters
int16_t mBitDepth;
bool mFastMode;
// encoding state
int16_t mLastMixRes[kALACMaxChannels];
// encoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictorU;
int32_t * mPredictorV;
uint16_t * mShiftBufferUV;
uint8_t * mWorkBuffer;
// per-channel coefficients buffers
int16_t mCoefsU[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
int16_t mCoefsV[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
// encoding statistics
uint32_t mTotalBytesGenerated;
uint32_t mAvgBitRate;
uint32_t mMaxFrameBytes;
uint32_t mFrameSize;
uint32_t mMaxOutputBytes;
uint32_t mNumChannels;
uint32_t mOutputSampleRate;
};

175
src/ALAC/EndianPortable.c Normal file
View File

@ -0,0 +1,175 @@
/*
* 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@
*/
//
// EndianPortable.c
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#include <stdio.h>
#include "EndianPortable.h"
#define BSWAP16(x) (((x << 8) | ((x >> 8) & 0x00ff)))
#define BSWAP32(x) (((x << 24) | ((x << 8) & 0x00ff0000) | ((x >> 8) & 0x0000ff00) | ((x >> 24) & 0x000000ff)))
#define BSWAP64(x) ((((int64_t)x << 56) | (((int64_t)x << 40) & 0x00ff000000000000LL) | \
(((int64_t)x << 24) & 0x0000ff0000000000LL) | (((int64_t)x << 8) & 0x000000ff00000000LL) | \
(((int64_t)x >> 8) & 0x00000000ff000000LL) | (((int64_t)x >> 24) & 0x0000000000ff0000LL) | \
(((int64_t)x >> 40) & 0x000000000000ff00LL) | (((int64_t)x >> 56) & 0x00000000000000ffLL)))
#if defined(__i386__)
#define TARGET_RT_LITTLE_ENDIAN 1
#elif defined(__x86_64__)
#define TARGET_RT_LITTLE_ENDIAN 1
#elif defined (TARGET_OS_WIN32)
#define TARGET_RT_LITTLE_ENDIAN 1
#endif
uint16_t Swap16NtoB(uint16_t inUInt16)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP16(inUInt16);
#else
return inUInt16;
#endif
}
uint16_t Swap16BtoN(uint16_t inUInt16)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP16(inUInt16);
#else
return inUInt16;
#endif
}
uint32_t Swap32NtoB(uint32_t inUInt32)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP32(inUInt32);
#else
return inUInt32;
#endif
}
uint32_t Swap32BtoN(uint32_t inUInt32)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP32(inUInt32);
#else
return inUInt32;
#endif
}
uint64_t Swap64BtoN(uint64_t inUInt64)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP64(inUInt64);
#else
return inUInt64;
#endif
}
uint64_t Swap64NtoB(uint64_t inUInt64)
{
#if TARGET_RT_LITTLE_ENDIAN
return BSWAP64(inUInt64);
#else
return inUInt64;
#endif
}
float SwapFloat32BtoN(float in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
float f;
int32_t i;
} x;
x.f = in;
x.i = BSWAP32(x.i);
return x.f;
#else
return in;
#endif
}
float SwapFloat32NtoB(float in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
float f;
int32_t i;
} x;
x.f = in;
x.i = BSWAP32(x.i);
return x.f;
#else
return in;
#endif
}
double SwapFloat64BtoN(double in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
double f;
int64_t i;
} x;
x.f = in;
x.i = BSWAP64(x.i);
return x.f;
#else
return in;
#endif
}
double SwapFloat64NtoB(double in)
{
#if TARGET_RT_LITTLE_ENDIAN
union {
double f;
int64_t i;
} x;
x.f = in;
x.i = BSWAP64(x.i);
return x.f;
#else
return in;
#endif
}
void Swap16(uint16_t * inUInt16)
{
*inUInt16 = BSWAP16(*inUInt16);
}
void Swap24(uint8_t * inUInt24)
{
uint8_t tempVal = inUInt24[0];
inUInt24[0] = inUInt24[2];
inUInt24[2] = tempVal;
}
void Swap32(uint32_t * inUInt32)
{
*inUInt32 = BSWAP32(*inUInt32);
}

59
src/ALAC/EndianPortable.h Normal file
View File

@ -0,0 +1,59 @@
/*
* 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@
*/
//
// EndianPortable.h
//
// Copyright 2011 Apple Inc. All rights reserved.
//
#ifndef _EndianPortable_h
#define _EndianPortable_h
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
uint16_t Swap16NtoB(uint16_t inUInt16);
uint16_t Swap16BtoN(uint16_t inUInt16);
uint32_t Swap32NtoB(uint32_t inUInt32);
uint32_t Swap32BtoN(uint32_t inUInt32);
uint64_t Swap64BtoN(uint64_t inUInt64);
uint64_t Swap64NtoB(uint64_t inUInt64);
float SwapFloat32BtoN(float in);
float SwapFloat32NtoB(float in);
double SwapFloat64BtoN(double in);
double SwapFloat64NtoB(double in);
void Swap16(uint16_t * inUInt16);
void Swap24(uint8_t * inUInt24);
void Swap32(uint32_t * inUInt32);
#ifdef __cplusplus
}
#endif
#endif

170
src/ALAC/LICENSE Normal file
View File

@ -0,0 +1,170 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the
copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other
entities that control, are controlled by, or are under common control
with that entity. For the purposes of this definition, "control" means
(i) the power, direct or indirect, to cause the direction or management
of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii)
beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source,
and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but not
limited to compiled object code, generated documentation, and
conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object
form, made available under the License, as indicated by a copyright
notice that is included in or attached to the work (an example is
provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original
version of the Work and any modifications or additions to that Work or
Derivative Works thereof, that is intentionally submitted to Licensor
for inclusion in the Work by the copyright owner or by an individual
or Legal Entity authorized to submit on behalf of the copyright owner.
For the purposes of this definition, "submitted" means any form of
electronic, verbal, or written communication sent to the Licensor
or its representatives, including but not limited to communication
on electronic mailing lists, source code control systems, and issue
tracking systems that are managed by, or on behalf of, the Licensor
for the purpose of discussing and improving the Work, but excluding
communication that is conspicuously marked or otherwise designated in
writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions
of this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of, publicly
display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except
as stated in this section) patent license to make, have made, use,
offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such
Contributor that are necessarily infringed by their Contribution(s)
alone or by combination of their Contribution(s) with the Work to which
such Contribution(s) was submitted. If You institute patent litigation
against any entity (including a cross-claim or counterclaim in a
lawsuit) alleging that the Work or a Contribution incorporated within
the Work constitutes direct or contributory patent infringement, then
any patent licenses granted to You under this License for that Work
shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You meet the
following conditions:
You must give any other recipients of the Work or Derivative Works a
copy of this License; and
You must cause any modified files to carry prominent notices stating
that You changed the files; and
You must retain, in the Source form of any Derivative Works that You
distribute, all copyright, patent, trademark, and attribution notices
from the Source form of the Work, excluding those notices that do not
pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution,
then any Derivative Works that You distribute must include a readable
copy of the attribution notices contained within such NOTICE file,
excluding those notices that do not pertain to any part of the
Derivative Works, in at least one of the following places: within a
NOTICE text file distributed as part of the Derivative Works; within
the Source form or documentation, if provided along with the Derivative
Works; or, within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents of the
NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative
Works that You distribute, alongside or as an addendum to the NOTICE
text from the Work, provided that such additional attribution notices
cannot be construed as modifying the License. You may add Your own
copyright statement to Your modifications and may provide additional
or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as
a whole, provided Your use, reproduction, and distribution of the Work
otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work by
You to the Licensor shall be under the terms and conditions of this
License, without any additional terms or conditions. Notwithstanding
the above, nothing herein shall supersede or modify the terms of any
separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed
to in writing, Licensor provides the Work (and each Contributor
provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied, including, without
limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your
exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise, unless
required by applicable law (such as deliberate and grossly negligent
acts) or agreed to in writing, shall any Contributor be liable to You
for damages, including any direct, indirect, special, incidental, or
consequential damages of any character arising as a result of this
License or out of the use or inability to use the Work (including but
not limited to damages for loss of goodwill, work stoppage, computer
failure or malfunction, or any and all other commercial damages or
losses), even if such Contributor has been advised of the possibility of
such damages.
9. Accepting Warranty or Additional Liability. While redistributing the
Work or Derivative Works thereof, You may choose to offer, and charge a
fee for, acceptance of support, warranty, indemnity, or other liability
obligations and/or rights consistent with this License. However, in
accepting such obligations, You may act only on Your own behalf and
on Your sole responsibility, not on behalf of any other Contributor,
and only if You agree to indemnify, defend, and hold each Contributor
harmless for any liability incurred by, or claims asserted against, such
Contributor by reason of your accepting any such warranty or additional
liability.

355
src/ALAC/ag_dec.c Normal file
View File

@ -0,0 +1,355 @@
/*
* 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>
#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 win
static 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_INLINE
getstreambits( 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 != NULL) && (pc != NULL) && (outNumBits != NULL), 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 < (uint32_t) 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 < (uint32_t) 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 <= (uint32_t) 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;
}

363
src/ALAC/ag_enc.c Normal file
View File

@ -0,0 +1,363 @@
/*
* 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_enc.c
Contains: Adaptive Golomb encode routines.
Copyright: (c) 2001-2011 Apple, Inc.
*/
#include "aglib.h"
#include "ALACBitUtilities.h"
#include "EndianPortable.h"
#include "ALACAudioTypes.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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
*/
// note: implementing this with some kind of "count leading zeros" assembly is a big performance win
static 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 int32_t ALWAYS_INLINE abs_func( int32_t a )
{
// note: the CW PPC intrinsic __abs() turns into these instructions so no need to try and use it
int32_t isneg = a >> 31;
int32_t xorval = a ^ isneg;
int32_t result = xorval-isneg;
return 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
static inline int32_t dyn_code(int32_t m, int32_t k, int32_t n, uint32_t *outNumBits)
{
uint32_t divx, mod, de;
uint32_t numBits;
uint32_t value;
//Assert( n >= 0 );
divx = n/m;
if(divx >= MAX_PREFIX_16)
{
numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;
}
else
{
mod = n%m;
de = (mod == 0);
numBits = divx + k + 1 - de;
value = (((1<<divx)-1)<<(numBits-divx)) + mod + 1 - de;
// if coding this way is bigger than doing escape, then do escape
if (numBits > MAX_PREFIX_16 + MAX_DATATYPE_BITS_16)
{
numBits = MAX_PREFIX_16 + MAX_DATATYPE_BITS_16;
value = (((1<<MAX_PREFIX_16)-1)<<MAX_DATATYPE_BITS_16) + n;
}
}
*outNumBits = numBits;
return (int32_t) value;
}
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)
{
uint32_t divx, mod, de;
uint32_t numBits;
uint32_t value;
int32_t didOverflow = 0;
divx = n/m;
if (divx < MAX_PREFIX_32)
{
mod = n - (m * divx);
de = (mod == 0);
numBits = divx + k + 1 - de;
value = (((1<<divx)-1)<<(numBits-divx)) + mod + 1 - de;
if (numBits > 25)
goto codeasescape;
}
else
{
codeasescape:
numBits = MAX_PREFIX_32;
value = (((1<<MAX_PREFIX_32)-1));
*overflow = n;
*overflowbits = maxbits;
didOverflow = 1;
}
*outNumBits = numBits;
*outValue = value;
return didOverflow;
}
static inline void ALWAYS_INLINE dyn_jam_noDeref(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
{
uint32_t *i = (uint32_t *)(out + (bitPos >> 3));
uint32_t mask;
uint32_t curr;
uint32_t shift;
//Assert( numBits <= 32 );
curr = *i;
curr = Swap32NtoB( curr );
shift = 32 - (bitPos & 7) - numBits;
mask = ~0u >> (32 - numBits); // mask must be created in two steps to avoid compiler sequencing ambiguity
mask <<= shift;
value = (value << shift) & mask;
value |= curr & ~mask;
*i = Swap32BtoN( value );
}
static inline void ALWAYS_INLINE dyn_jam_noDeref_large(unsigned char *out, uint32_t bitPos, uint32_t numBits, uint32_t value)
{
uint32_t * i = (uint32_t *)(out + (bitPos>>3));
uint32_t w;
uint32_t curr;
uint32_t mask;
int32_t shiftvalue = (32 - (bitPos&7) - numBits);
//Assert(numBits <= 32);
curr = *i;
curr = Swap32NtoB( curr );
if (shiftvalue < 0)
{
uint8_t tailbyte;
uint8_t *tailptr;
w = value >> -shiftvalue;
mask = ~0u >> -shiftvalue;
w |= (curr & ~mask);
tailptr = ((uint8_t *)i) + 4;
tailbyte = (value << ((8+shiftvalue))) & 0xff;
*tailptr = (uint8_t)tailbyte;
}
else
{
mask = ~0u >> (32 - numBits);
mask <<= shiftvalue; // mask must be created in two steps to avoid compiler sequencing ambiguity
w = (value << shiftvalue) & mask;
w |= curr & ~mask;
}
*i = Swap32BtoN( w );
}
int32_t dyn_comp( AGParamRecPtr params, int32_t * pc, BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits )
{
unsigned char * out;
uint32_t bitPos, startPos;
uint32_t m, k, n, c, mz, nz;
uint32_t numBits;
uint32_t value;
int32_t del, zmode;
uint32_t overflow, overflowbits;
int32_t status;
// shadow the variables in params so there's not the dereferencing overhead
uint32_t mb, pb, kb, wb;
int32_t rowPos = 0;
int32_t rowSize = params->sw;
int32_t rowJump = (params->fw) - rowSize;
int32_t * inPtr = pc;
*outNumBits = 0;
RequireAction( (bitSize >= 1) && (bitSize <= 32), return kALAC_ParamError; );
out = bitstream->cur;
startPos = bitstream->bitIndex;
bitPos = startPos;
mb = params->mb = params->mb0;
pb = params->pb;
kb = params->kb;
wb = params->wb;
zmode = 0;
c=0;
status = ALAC_noErr;
while (c < (uint32_t) numSamples)
{
m = mb >> QBSHIFT;
k = lg3a(m);
if ( k > kb)
{
k = kb;
}
m = (1<<k)-1;
del = *inPtr++;
rowPos++;
n = (abs_func(del) << 1) - ((del >> 31) & 1) - zmode;
//Assert( 32-lead(n) <= bitSize );
if ( dyn_code_32bit(bitSize, m, k, n, &numBits, &value, &overflow, &overflowbits) )
{
dyn_jam_noDeref(out, bitPos, numBits, value);
bitPos += numBits;
dyn_jam_noDeref_large(out, bitPos, overflowbits, overflow);
bitPos += overflowbits;
}
else
{
dyn_jam_noDeref(out, bitPos, numBits, value);
bitPos += numBits;
}
c++;
if ( rowPos >= rowSize)
{
rowPos = 0;
inPtr += rowJump;
}
mb = pb * (n + zmode) + mb - ((pb *mb)>>QBSHIFT);
// update mean tracking if it's overflowed
if (n > N_MAX_MEAN_CLAMP)
mb = N_MEAN_CLAMP_VAL;
zmode = 0;
RequireAction(c <= (uint32_t) numSamples, status = kALAC_ParamError; goto Exit; );
if (((mb << MMULSHIFT) < QB) && (c < (uint32_t) numSamples))
{
zmode = 1;
nz = 0;
while(c<(uint32_t) numSamples && *inPtr == 0)
{
/* Take care of wrap-around globals. */
++inPtr;
++nz;
++c;
if ( ++rowPos >= rowSize)
{
rowPos = 0;
inPtr += rowJump;
}
if(nz >= 65535)
{
zmode = 0;
break;
}
}
k = lead(mb) - BITOFF+((mb+MOFF)>>MDENSHIFT);
mz = ((1<<k)-1) & wb;
value = dyn_code(mz, k, nz, &numBits);
dyn_jam_noDeref(out, bitPos, numBits, value);
bitPos += numBits;
mb = 0;
}
}
*outNumBits = (bitPos - startPos);
BitBufferAdvance( bitstream, *outNumBits );
Exit:
return status;
}

81
src/ALAC/aglib.h Normal file
View File

@ -0,0 +1,81 @@
/*
* 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: aglib.h
Copyright: (C) 2001-2011 Apple, Inc.
*/
#ifndef AGLIB_H
#define AGLIB_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define QBSHIFT 9
#define QB (1<<QBSHIFT)
#define PB0 40
#define MB0 10
#define KB0 14
#define MAX_RUN_DEFAULT 255
#define MMULSHIFT 2
#define MDENSHIFT (QBSHIFT - MMULSHIFT - 1)
#define MOFF ((1<<(MDENSHIFT-2)))
#define BITOFF 24
/* Max. prefix of 1's. */
#define MAX_PREFIX_16 9
#define MAX_PREFIX_TOLONG_16 15
#define MAX_PREFIX_32 9
/* Max. bits in 16-bit data type */
#define MAX_DATATYPE_BITS_16 16
typedef struct AGParamRec
{
uint32_t mb, mb0, pb, kb, wb, qb;
uint32_t fw, sw;
uint32_t maxrun;
// fw = 1, sw = 1;
} AGParamRec, *AGParamRecPtr;
struct BitBuffer;
void set_standard_ag_params(AGParamRecPtr params, uint32_t fullwidth, uint32_t sectorwidth);
void set_ag_params(AGParamRecPtr params, uint32_t m, uint32_t p, uint32_t k, uint32_t f, uint32_t s, uint32_t maxrun);
int32_t dyn_comp(AGParamRecPtr params, int32_t * pc, struct BitBuffer * bitstream, int32_t numSamples, int32_t bitSize, uint32_t * outNumBits);
int32_t dyn_decomp(AGParamRecPtr params, struct BitBuffer * bitstream, int32_t * pc, int32_t numSamples, int32_t maxSize, uint32_t * outNumBits);
#ifdef __cplusplus
}
#endif
#endif //#ifndef AGLIB_H

102
src/ALAC/alac_codec.h Normal file
View File

@ -0,0 +1,102 @@
/*
* 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: alac_codec.h
*/
#ifndef ALAC_CODEC_H
#define ALAC_CODEC_H
#include <stdint.h>
#include "ALACAudioTypes.h"
#define ALAC_FRAME_LENGTH 4096
struct BitBuffer;
typedef struct alac_decoder_s
{
// decoding parameters (public for use in the analyzer)
ALACSpecificConfig mConfig;
uint16_t mActiveElements;
// decoding buffers
int32_t mMixBufferU [ALAC_FRAME_LENGTH];
int32_t mMixBufferV [ALAC_FRAME_LENGTH];
union
{
int32_t mPredictor [ALAC_FRAME_LENGTH];
uint16_t mShiftBuffer [ALAC_FRAME_LENGTH];
} ;
} ALAC_DECODER ;
typedef struct alac_encoder_s
{
// ALAC encoder parameters
int16_t mBitDepth;
// encoding state
int16_t mLastMixRes [kALACMaxChannels];
int32_t mFastMode;
// encoding buffers
int32_t mMixBufferU [ALAC_FRAME_LENGTH] ;
int32_t mMixBufferV [ALAC_FRAME_LENGTH] ;
int32_t mPredictorU [ALAC_FRAME_LENGTH] ;
int32_t mPredictorV [ALAC_FRAME_LENGTH] ;
uint16_t mShiftBufferUV [2 * ALAC_FRAME_LENGTH] ;
uint8_t mWorkBuffer [4 * ALAC_FRAME_LENGTH];
// per-channel coefficients buffers
int16_t mCoefsU [kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
int16_t mCoefsV [kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
// encoding statistics
uint32_t mTotalBytesGenerated;
uint32_t mAvgBitRate;
uint32_t mMaxFrameBytes;
uint32_t mFrameSize;
uint32_t mMaxOutputBytes;
uint32_t mNumChannels;
uint32_t mOutputSampleRate;
} ALAC_ENCODER ;
int32_t alac_decoder_init (ALAC_DECODER *p, void * inMagicCookie, uint32_t inMagicCookieSize) ;
int32_t alac_encoder_init (ALAC_ENCODER *p, uint32_t samplerate, uint32_t channels, uint32_t format_flags, uint32_t frameSize) ;
int32_t alac_decode (ALAC_DECODER *, struct BitBuffer * bits, uint8_t * sampleBuffer,
uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples) ;
int32_t alac_encode (ALAC_ENCODER *p, uint32_t numChannels, uint32_t bytesPerPacket,
unsigned char * theReadBuffer, unsigned char * theWriteBuffer,
int32_t * ioNumBytes) ;
void alac_set_fastmode(ALAC_ENCODER * p, int32_t fast) ;
uint32_t alac_get_magic_cookie_size(uint32_t inNumChannels) ;
void alac_get_magic_cookie(ALAC_ENCODER *p, void * config, uint32_t * ioSize) ;
void alac_get_source_format(ALAC_ENCODER *p, const AudioFormatDescription * source, AudioFormatDescription * output) ;
#endif

696
src/ALAC/alac_decoder.c Normal file
View File

@ -0,0 +1,696 @@
/*
* 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 <stdlib.h>
#include <string.h>
#include "alac_codec.h"
#include "dplib.h"
#include "aglib.h"
#include "matrixlib.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 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 );
/*
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 = Swap32BtoN(((ALACSpecificConfig *)theActualCookie)->frameLength);
if (theConfig.frameLength > ALAC_FRAME_LENGTH)
return fALAC_FrameLengthError ;
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);
p->mConfig = theConfig;
RequireAction( p->mConfig.compatibleVersion <= kALACVersion, return kALAC_ParamError; );
RequireAction( (p->mMixBufferU != NULL) && (p->mMixBufferV != NULL) && (p->mPredictor != NULL),
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
alac_decode (ALAC_DECODER *p, struct 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 * 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 != NULL) && (sampleBuffer != NULL) && (outNumSamples != NULL), return kALAC_ParamError; );
RequireAction( numChannels > 0, return kALAC_ParamError; );
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 );
}
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, p->mConfig.mb, (pb * pbFactorU) / 4, p->mConfig.kb, numSamples, numSamples, p->mConfig.maxRun );
status = dyn_decomp( &agParams, bits, p->mPredictor, numSamples, chanBits, &bits1 );
RequireNoErr( status, goto Exit; );
if ( modeU == 0 )
{
unpc_block( p->mPredictor, p->mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
}
else
{
// the special "numActive == 31" mode can be done in-place
unpc_block( p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0 );
unpc_block( p->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 = (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->mShiftBuffer[i] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
}
// convert 32-bit integers into output buffer
switch ( p->mConfig.bitDepth )
{
case 16:
out16 = &((int16_t *)sampleBuffer)[channelIndex];
for ( i = 0, j = 0; i < numSamples; i++, j += numChannels )
out16[j] = (int16_t) p->mMixBufferU[i];
break;
case 20:
out20 = (uint8_t *)sampleBuffer + (channelIndex * 3);
copyPredictorTo20( p->mMixBufferU, out20, numChannels, numSamples );
break;
case 24:
out24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
if ( bytesShifted != 0 )
copyPredictorTo24Shift( p->mMixBufferU, p->mShiftBuffer, out24, numChannels, numSamples, bytesShifted );
else
copyPredictorTo24( p->mMixBufferU, out24, numChannels, numSamples );
break;
case 32:
out32 = &((int32_t *)sampleBuffer)[channelIndex];
if ( bytesShifted != 0 )
copyPredictorTo32Shift( p->mMixBufferU, p->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 );
}
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->mPredictor, numSamples, chanBits, &bits1 );
RequireNoErr( status, goto Exit; );
if ( modeU == 0 )
{
unpc_block( p->mPredictor, p->mMixBufferU, numSamples, &coefsU[0], numU, chanBits, denShiftU );
}
else
{
// the special "numActive == 31" mode can be done in-place
unpc_block( p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0 );
unpc_block( p->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->mPredictor, numSamples, chanBits, &bits2 );
RequireNoErr( status, goto Exit; );
if ( modeV == 0 )
{
unpc_block( p->mPredictor, p->mMixBufferV, numSamples, &coefsV[0], numV, chanBits, denShiftV );
}
else
{
// the special "numActive == 31" mode can be done in-place
unpc_block( p->mPredictor, p->mPredictor, numSamples, NULL, 31, chanBits, 0 );
unpc_block( p->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 = (val << 16) >> shift;
p->mMixBufferU[i] = val | BitBufferRead( bits, (uint8_t)extraBits );
val = (int32_t) BitBufferRead( bits, 16 );
val = (val << 16) >> 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->mShiftBuffer[i + 0] = (uint16_t) BitBufferRead( &shiftBits, (uint8_t) shift );
p->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:
out16 = &((int16_t *)sampleBuffer)[channelIndex];
unmix16( p->mMixBufferU, p->mMixBufferV, out16, numChannels, numSamples, mixBits, mixRes );
break;
case 20:
out20 = (uint8_t *)sampleBuffer + (channelIndex * 3);
unmix20( p->mMixBufferU, p->mMixBufferV, out20, numChannels, numSamples, mixBits, mixRes );
break;
case 24:
out24 = (uint8_t *)sampleBuffer + (channelIndex * 3);
unmix24( p->mMixBufferU, p->mMixBufferV, out24, numChannels, numSamples,
mixBits, mixRes, p->mShiftBuffer, bytesShifted );
break;
case 32:
out32 = &((int32_t *)sampleBuffer)[channelIndex];
unmix32( p->mMixBufferU, p->mMixBufferV, out32, numChannels, numSamples,
mixBits, mixRes, p->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 = 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 0 // ! 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 ( p->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
*/
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 Zero16( int16_t * buffer, uint32_t numItems, uint32_t stride )
{
if ( stride == 1 )
{
memset( buffer, 0, numItems * sizeof(int16_t) );
}
else
{
for ( uint32_t indx = 0; indx < (numItems * stride); indx += stride )
buffer[indx] = 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 indx = 0; indx < (numItems * stride * 3); indx += (stride * 3) )
{
buffer[indx + 0] = 0;
buffer[indx + 1] = 0;
buffer[indx + 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 indx = 0; indx < (numItems * stride); indx += stride )
buffer[indx] = 0;
}
}

61
src/ALAC/alac_decoder.h Normal file
View File

@ -0,0 +1,61 @@
/*
* 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: alac_decoder.h
*/
#ifndef ALAC_DECODER_H
#define ALAC_DECODER_H
#include <stdint.h>
#include "ALACAudioTypes.h"
typedef enum
{
false = 0,
ALAC_TRUE = 1
} bool ;
struct BitBuffer;
typedef struct alac_decoder
{
// decoding parameters (public for use in the analyzer)
ALACSpecificConfig mConfig;
uint16_t mActiveElements;
// decoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictor;
uint16_t * mShiftBuffer; // note: this points to mPredictor's memory but different
// variable for clarity and type difference
} alac_decoder ;
alac_decoder * alac_decoder_new (void) ;
void alac_decoder_delete (alac_decoder *) ;
int32_t alac_init (alac_decoder *p, void * inMagicCookie, uint32_t inMagicCookieSize) ;
int32_t alac_decode (alac_decoder *, struct BitBuffer * bits, uint8_t * sampleBuffer, uint32_t numSamples, uint32_t numChannels, uint32_t * outNumSamples) ;
#endif /* ALAC_DECODER_H */

1358
src/ALAC/alac_encoder.c Normal file

File diff suppressed because it is too large Load Diff

98
src/ALAC/alac_encoder.h Normal file
View File

@ -0,0 +1,98 @@
/*
* 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: alac_encoder.h
*/
#ifndef ALAC_ENCODER_H
#define ALAC_ENCODER_H
#include <stdint.h>
#include "ALACAudioTypes.h"
typedef enum
{
false = 0,
true = 1
} bool ;
struct BitBuffer;
typedef struct alac_encoder
{
// ALAC encoder parameters
int16_t mBitDepth;
bool mFastMode;
// encoding state
int16_t mLastMixRes[kALACMaxChannels];
// encoding buffers
int32_t * mMixBufferU;
int32_t * mMixBufferV;
int32_t * mPredictorU;
int32_t * mPredictorV;
uint16_t * mShiftBufferUV;
uint8_t * mWorkBuffer;
// per-channel coefficients buffers
int16_t mCoefsU[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
int16_t mCoefsV[kALACMaxChannels][kALACMaxSearches][kALACMaxCoefs];
// encoding statistics
uint32_t mTotalBytesGenerated;
uint32_t mAvgBitRate;
uint32_t mMaxFrameBytes;
uint32_t mFrameSize;
uint32_t mMaxOutputBytes;
uint32_t mNumChannels;
uint32_t mOutputSampleRate;
} alac_encoder ;
alac_encoder * alac_encoder_new (void);
void alac_encoder_delete (alac_encoder *);
int32_t Encode(alac_encoder *p, AudioFormatDescription theInputFormat,
unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes);
int32_t Finish(void);
static inline void
SetFastMode(alac_encoder * p, bool fast ) { p->mFastMode = fast; }
// this must be called *before* InitializeEncoder()
static inline void
SetFrameSize(alac_encoder *p, uint32_t frameSize ) { p->mFrameSize = frameSize; }
void GetConfig(alac_encoder *p, ALACSpecificConfig * config );
uint32_t GetMagicCookieSize(uint32_t inNumChannels);
void GetMagicCookie(alac_encoder *p, void * config, uint32_t * ioSize );
int32_t InitializeEncoder(alac_encoder *p, AudioFormatDescription theOutputFormat);
void GetSourceFormat(alac_encoder *p, const AudioFormatDescription * source, AudioFormatDescription * output );
int32_t EncodeStereo(alac_encoder *p, struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoFast(alac_encoder *p, struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
int32_t EncodeStereoEscape(alac_encoder *p, struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t numSamples );
int32_t EncodeMono(alac_encoder *p, struct BitBuffer * bitstream, void * input, uint32_t stride, uint32_t channelIndex, uint32_t numSamples );
#endif

375
src/ALAC/dp_dec.c Normal file
View File

@ -0,0 +1,375 @@
/*
* 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: dp_dec.c
Contains: Dynamic Predictor decode routines
Copyright: (c) 2001-2011 Apple, Inc.
*/
#include "dplib.h"
#include <string.h>
#if __GNUC__
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
#define LOOP_ALIGN
static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
{
int32_t negishift;
negishift = ((uint32_t)-i) >> 31;
return negishift | (i >> 31);
}
void unpc_block( int32_t * pc1, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
{
register int16_t a0, a1, a2, a3;
register int32_t b0, b1, b2, b3;
int32_t j, k, lim;
int32_t sum1, sg, sgn, top, dd;
int32_t * pout;
int32_t del, del0;
uint32_t chanshift = 32 - chanbits;
int32_t denhalf = 1<<(denshift-1);
out[0] = pc1[0];
if ( numactive == 0 )
{
// just copy if numactive == 0 (but don't bother if in/out pointers the same)
if ( (num > 1) && (pc1 != out) )
memcpy( &out[1], &pc1[1], (num - 1) * sizeof(int32_t) );
return;
}
if ( numactive == 31 )
{
// short-circuit if numactive == 31
int32_t prev;
/* this code is written such that the in/out buffers can be the same
to conserve buffer space on embedded devices like the iPod
(original code)
for ( j = 1; j < num; j++ )
del = pc1[j] + out[j-1];
out[j] = (del << chanshift) >> chanshift;
*/
prev = out[0];
for ( j = 1; j < num; j++ )
{
del = pc1[j] + prev;
prev = (del << chanshift) >> chanshift;
out[j] = prev;
}
return;
}
for ( j = 1; j <= numactive; j++ )
{
del = pc1[j] + out[j-1];
out[j] = (del << chanshift) >> chanshift;
}
lim = numactive + 1;
if ( numactive == 4 )
{
// optimization for numactive == 4
register int16_t ia0, ia1, ia2, ia3;
register int32_t ib0, ib1, ib2, ib3;
ia0 = coefs[0];
ia1 = coefs[1];
ia2 = coefs[2];
ia3 = coefs[3];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = out[j - lim];
pout = out + j - 1;
ib0 = top - pout[0];
ib1 = top - pout[-1];
ib2 = top - pout[-2];
ib3 = top - pout[-3];
sum1 = (denhalf - ia0 * ib0 - ia1 * ib1 - ia2 * ib2 - ia3 * ib3) >> denshift;
del = pc1[j];
del0 = del;
sg = sign_of_int(del);
del += top + sum1;
out[j] = (del << chanshift) >> chanshift;
if ( sg > 0 )
{
sgn = sign_of_int( ib3 );
ia3 -= sgn;
del0 -= (4 - 3) * ((sgn * ib3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( ib2 );
ia2 -= sgn;
del0 -= (4 - 2) * ((sgn * ib2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( ib1 );
ia1 -= sgn;
del0 -= (4 - 1) * ((sgn * ib1) >> denshift);
if ( del0 <= 0 )
continue;
ia0 -= sign_of_int( ib0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( ib3 );
ia3 -= sgn;
del0 -= (4 - 3) * ((sgn * ib3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( ib2 );
ia2 -= sgn;
del0 -= (4 - 2) * ((sgn * ib2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( ib1 );
ia1 -= sgn;
del0 -= (4 - 1) * ((sgn * ib1) >> denshift);
if ( del0 >= 0 )
continue;
ia0 += sign_of_int( ib0 );
}
}
coefs[0] = ia0;
coefs[1] = ia1;
coefs[2] = ia2;
coefs[3] = ia3;
}
else if ( numactive == 8 )
{
register int16_t a4, a5, a6, a7;
register int32_t b4, b5, b6, b7;
// optimization for numactive == 8
a0 = coefs[0];
a1 = coefs[1];
a2 = coefs[2];
a3 = coefs[3];
a4 = coefs[4];
a5 = coefs[5];
a6 = coefs[6];
a7 = coefs[7];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = out[j - lim];
pout = out + j - 1;
b0 = top - (*pout--);
b1 = top - (*pout--);
b2 = top - (*pout--);
b3 = top - (*pout--);
b4 = top - (*pout--);
b5 = top - (*pout--);
b6 = top - (*pout--);
b7 = top - (*pout);
pout += 8;
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
del = pc1[j];
del0 = del;
sg = sign_of_int(del);
del += top + sum1;
out[j] = (del << chanshift) >> chanshift;
if ( sg > 0 )
{
sgn = sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 <= 0 )
continue;
a0 -= sign_of_int( b0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 >= 0 )
continue;
a0 += sign_of_int( b0 );
}
}
coefs[0] = a0;
coefs[1] = a1;
coefs[2] = a2;
coefs[3] = a3;
coefs[4] = a4;
coefs[5] = a5;
coefs[6] = a6;
coefs[7] = a7;
}
else
{
// general case
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
sum1 = 0;
pout = out + j - 1;
top = out[j-lim];
for ( k = 0; k < numactive; k++ )
sum1 += coefs[k] * (pout[-k] - top);
del = pc1[j];
del0 = del;
sg = sign_of_int( del );
del += top + ((sum1 + denhalf) >> denshift);
out[j] = (del << chanshift) >> chanshift;
if ( sg > 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pout[-k];
sgn = sign_of_int( dd );
coefs[k] -= sgn;
del0 -= (numactive - k) * ((sgn * dd) >> denshift);
if ( del0 <= 0 )
break;
}
}
else if ( sg < 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pout[-k];
sgn = sign_of_int( dd );
coefs[k] += sgn;
del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
if ( del0 >= 0 )
break;
}
}
}
}
}

380
src/ALAC/dp_enc.c Normal file
View File

@ -0,0 +1,380 @@
/*
* 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: dp_enc.c
Contains: Dynamic Predictor encode routines
Copyright: (c) 2001-2011 Apple, Inc.
*/
#include "dplib.h"
#include <string.h>
#if __GNUC__
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
#define LOOP_ALIGN
void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs )
{
int32_t k;
int32_t den = 1 << denshift;
coefs[0] = (AINIT * den) >> 4;
coefs[1] = (BINIT * den) >> 4;
coefs[2] = (CINIT * den) >> 4;
for ( k = 3; k < numPairs; k++ )
coefs[k] = 0;
}
void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs )
{
int32_t k;
for ( k = 0; k < numPairs; k++ )
dstCoefs[k] = srcCoefs[k];
}
static inline int32_t ALWAYS_INLINE sign_of_int( int32_t i )
{
int32_t negishift;
negishift = ((uint32_t)-i) >> 31;
return negishift | (i >> 31);
}
void pc_block( int32_t * in, int32_t * pc1, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift )
{
register int16_t a0, a1, a2, a3;
register int32_t b0, b1, b2, b3;
int32_t j, k, lim;
int32_t * pin;
int32_t sum1, dd;
int32_t sg, sgn;
int32_t top;
int32_t del, del0;
uint32_t chanshift = 32 - chanbits;
int32_t denhalf = 1 << (denshift - 1);
pc1[0] = in[0];
if ( numactive == 0 )
{
// just copy if numactive == 0 (but don't bother if in/out pointers the same)
if ( (num > 1) && (in != pc1) )
memcpy( &pc1[1], &in[1], (num - 1) * sizeof(int32_t) );
return;
}
if ( numactive == 31 )
{
// short-circuit if numactive == 31
for( j = 1; j < num; j++ )
{
del = in[j] - in[j-1];
pc1[j] = (del << chanshift) >> chanshift;
}
return;
}
for ( j = 1; j <= numactive; j++ )
{
del = in[j] - in[j-1];
pc1[j] = (del << chanshift) >> chanshift;
}
lim = numactive + 1;
if ( numactive == 4 )
{
// optimization for numactive == 4
a0 = coefs[0];
a1 = coefs[1];
a2 = coefs[2];
a3 = coefs[3];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = in[j - lim];
pin = in + j - 1;
b0 = top - pin[0];
b1 = top - pin[-1];
b2 = top - pin[-2];
b3 = top - pin[-3];
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3) >> denshift;
del = in[j] - top - sum1;
del = (del << chanshift) >> chanshift;
pc1[j] = del;
del0 = del;
sg = sign_of_int(del);
if ( sg > 0 )
{
sgn = sign_of_int( b3 );
a3 -= sgn;
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b2 );
a2 -= sgn;
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b1 );
a1 -= sgn;
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
if ( del0 <= 0 )
continue;
a0 -= sign_of_int( b0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( b3 );
a3 -= sgn;
del0 -= (4 - 3) * ((sgn * b3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b2 );
a2 -= sgn;
del0 -= (4 - 2) * ((sgn * b2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b1 );
a1 -= sgn;
del0 -= (4 - 1) * ((sgn * b1) >> denshift);
if ( del0 >= 0 )
continue;
a0 += sign_of_int( b0 );
}
}
coefs[0] = a0;
coefs[1] = a1;
coefs[2] = a2;
coefs[3] = a3;
}
else if ( numactive == 8 )
{
// optimization for numactive == 8
register int16_t a4, a5, a6, a7;
register int32_t b4, b5, b6, b7;
a0 = coefs[0];
a1 = coefs[1];
a2 = coefs[2];
a3 = coefs[3];
a4 = coefs[4];
a5 = coefs[5];
a6 = coefs[6];
a7 = coefs[7];
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = in[j - lim];
pin = in + j - 1;
b0 = top - (*pin--);
b1 = top - (*pin--);
b2 = top - (*pin--);
b3 = top - (*pin--);
b4 = top - (*pin--);
b5 = top - (*pin--);
b6 = top - (*pin--);
b7 = top - (*pin);
pin += 8;
sum1 = (denhalf - a0 * b0 - a1 * b1 - a2 * b2 - a3 * b3
- a4 * b4 - a5 * b5 - a6 * b6 - a7 * b7) >> denshift;
del = in[j] - top - sum1;
del = (del << chanshift) >> chanshift;
pc1[j] = del;
del0 = del;
sg = sign_of_int(del);
if ( sg > 0 )
{
sgn = sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 <= 0 )
continue;
sgn = sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 <= 0 )
continue;
a0 -= sign_of_int( b0 );
}
else if ( sg < 0 )
{
// note: to avoid unnecessary negations, we flip the value of "sgn"
sgn = -sign_of_int( b7 );
a7 -= sgn;
del0 -= 1 * ((sgn * b7) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b6 );
a6 -= sgn;
del0 -= 2 * ((sgn * b6) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b5 );
a5 -= sgn;
del0 -= 3 * ((sgn * b5) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b4 );
a4 -= sgn;
del0 -= 4 * ((sgn * b4) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b3 );
a3 -= sgn;
del0 -= 5 * ((sgn * b3) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b2 );
a2 -= sgn;
del0 -= 6 * ((sgn * b2) >> denshift);
if ( del0 >= 0 )
continue;
sgn = -sign_of_int( b1 );
a1 -= sgn;
del0 -= 7 * ((sgn * b1) >> denshift);
if ( del0 >= 0 )
continue;
a0 += sign_of_int( b0 );
}
}
coefs[0] = a0;
coefs[1] = a1;
coefs[2] = a2;
coefs[3] = a3;
coefs[4] = a4;
coefs[5] = a5;
coefs[6] = a6;
coefs[7] = a7;
}
else
{
//pc_block_general:
// general case
for ( j = lim; j < num; j++ )
{
LOOP_ALIGN
top = in[j - lim];
pin = in + j - 1;
sum1 = 0;
for ( k = 0; k < numactive; k++ )
sum1 -= coefs[k] * (top - pin[-k]);
del = in[j] - top - ((sum1 + denhalf) >> denshift);
del = (del << chanshift) >> chanshift;
pc1[j] = del;
del0 = del;
sg = sign_of_int( del );
if ( sg > 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pin[-k];
sgn = sign_of_int( dd );
coefs[k] -= sgn;
del0 -= (numactive - k) * ((sgn * dd) >> denshift);
if ( del0 <= 0 )
break;
}
}
else if ( sg < 0 )
{
for ( k = (numactive - 1); k >= 0; k-- )
{
dd = top - pin[-k];
sgn = sign_of_int( dd );
coefs[k] += sgn;
del0 -= (numactive - k) * ((-sgn * dd) >> denshift);
if ( del0 >= 0 )
break;
}
}
}
}
}

61
src/ALAC/dplib.h Normal file
View File

@ -0,0 +1,61 @@
/*
* 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: dplib.h
Contains: Dynamic Predictor routines
Copyright: Copyright (C) 2001-2011 Apple, Inc.
*/
#ifndef __DPLIB_H__
#define __DPLIB_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// defines
#define DENSHIFT_MAX 15
#define DENSHIFT_DEFAULT 9
#define AINIT 38
#define BINIT (-29)
#define CINIT (-2)
#define NUMCOEPAIRS 16
// prototypes
void init_coefs( int16_t * coefs, uint32_t denshift, int32_t numPairs );
void copy_coefs( int16_t * srcCoefs, int16_t * dstCoefs, int32_t numPairs );
// NOTE: these routines read at least "numactive" samples so the i/o buffers must be at least that big
void pc_block( int32_t * in, int32_t * pc, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
void unpc_block( int32_t * pc, int32_t * out, int32_t num, int16_t * coefs, int32_t numactive, uint32_t chanbits, uint32_t denshift );
#ifdef __cplusplus
}
#endif
#endif /* __DPLIB_H__ */

390
src/ALAC/matrix_dec.c Normal file
View File

@ -0,0 +1,390 @@
/*
* 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: matrix_dec.c
Contains: ALAC mixing/matrixing decode routines.
Copyright: (c) 2004-2011 Apple, Inc.
*/
#include "matrixlib.h"
#include "ALACAudioTypes.h"
// up to 24-bit "offset" macros for the individual bytes of a 20/24-bit word
#if TARGET_RT_BIG_ENDIAN
#define LBYTE 2
#define MBYTE 1
#define HBYTE 0
#else
#define LBYTE 0
#define MBYTE 1
#define HBYTE 2
#endif
/*
There is no plain middle-side option; instead there are various mixing
modes including middle-side, each lossless, as embodied in the mix()
and unmix() functions. These functions exploit a generalized middle-side
transformation:
u := [(rL + (m-r)R)/m];
v := L - R;
where [ ] denotes integer floor. The (lossless) inverse is
L = u + v - [rV/m];
R = L - v;
*/
// 16-bit routines
void unmix16( int32_t * u, int32_t * v, int16_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
int16_t * op = out;
int32_t j;
if ( mixres != 0 )
{
/* matrixed stereo */
for ( j = 0; j < numSamples; j++ )
{
int32_t l, r;
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
op[0] = (int16_t) l;
op[1] = (int16_t) r;
op += stride;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
op[0] = (int16_t) u[j];
op[1] = (int16_t) v[j];
op += stride;
}
}
}
// 20-bit routines
// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
void unmix20( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
uint8_t * op = out;
int32_t j;
if ( mixres != 0 )
{
/* matrixed stereo */
for ( j = 0; j < numSamples; j++ )
{
int32_t l, r;
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
l <<= 4;
r <<= 4;
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
val = u[j] << 4;
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += 3;
val = v[j] << 4;
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
}
// 24-bit routines
// - the 24 bits of data are right-justified in the input/output predictor buffers
void unmix24( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
uint8_t * op = out;
int32_t shift = bytesShifted * 8;
int32_t l, r;
int32_t j, k;
if ( mixres != 0 )
{
/* matrixed stereo */
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
l = (l << shift) | (uint32_t) shiftUV[k + 0];
r = (r << shift) | (uint32_t) shiftUV[k + 1];
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
l = u[j] + v[j] - ((mixres * v[j]) >> mixbits);
r = l - v[j];
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
}
else
{
/* Conventional separated stereo. */
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = u[j];
r = v[j];
l = (l << shift) | (uint32_t) shiftUV[k + 0];
r = (r << shift) | (uint32_t) shiftUV[k + 1];
op[HBYTE] = (uint8_t)((l >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((l >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((l >> 0) & 0xffu);
op += 3;
op[HBYTE] = (uint8_t)((r >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((r >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((r >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
val = u[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += 3;
val = v[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride - 1) * 3;
}
}
}
}
// 32-bit routines
// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
// - otherwise, the calculations might overflow into the 33rd bit and be lost
// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
void unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
int32_t * op = out;
int32_t shift = bytesShifted * 8;
int32_t l, r;
int32_t j, k;
if ( mixres != 0 )
{
//Assert( bytesShifted != 0 );
/* matrixed stereo with shift */
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
int32_t lt, rt;
lt = u[j];
rt = v[j];
l = lt + rt - ((mixres * rt) >> mixbits);
r = l - rt;
op[0] = (l << shift) | (uint32_t) shiftUV[k + 0];
op[1] = (r << shift) | (uint32_t) shiftUV[k + 1];
op += stride;
}
}
else
{
if ( bytesShifted == 0 )
{
/* interleaving w/o shift */
for ( j = 0; j < numSamples; j++ )
{
op[0] = u[j];
op[1] = v[j];
op += stride;
}
}
else
{
/* interleaving with shift */
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
op[0] = (u[j] << shift) | (uint32_t) shiftUV[k + 0];
op[1] = (v[j] << shift) | (uint32_t) shiftUV[k + 1];
op += stride;
}
}
}
}
// 20/24-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
void copyPredictorTo24( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples )
{
uint8_t * op = out;
int32_t j;
for ( j = 0; j < numSamples; j++ )
{
int32_t val = in[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride * 3);
}
}
void copyPredictorTo24Shift( int32_t * in, uint16_t * shift, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
{
uint8_t * op = out;
int32_t shiftVal = bytesShifted * 8;
int32_t j;
//Assert( bytesShifted != 0 );
for ( j = 0; j < numSamples; j++ )
{
int32_t val = in[j];
val = (val << shiftVal) | (uint32_t) shift[j];
op[HBYTE] = (uint8_t)((val >> 16) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 8) & 0xffu);
op[LBYTE] = (uint8_t)((val >> 0) & 0xffu);
op += (stride * 3);
}
}
void copyPredictorTo20( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples )
{
uint8_t * op = out;
int32_t j;
// 32-bit predictor values are right-aligned but 20-bit output values should be left-aligned
// in the 24-bit output buffer
for ( j = 0; j < numSamples; j++ )
{
int32_t val = in[j];
op[HBYTE] = (uint8_t)((val >> 12) & 0xffu);
op[MBYTE] = (uint8_t)((val >> 4) & 0xffu);
op[LBYTE] = (uint8_t)((val << 4) & 0xffu);
op += (stride * 3);
}
}
void copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples )
{
int32_t i, j;
// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
for ( i = 0, j = 0; i < numSamples; i++, j += stride )
out[j] = in[i];
}
void copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted )
{
int32_t * op = out;
uint32_t shiftVal = bytesShifted * 8;
int32_t j;
//Assert( bytesShifted != 0 );
// this is only a subroutine to abstract the "iPod can only output 16-bit data" problem
for ( j = 0; j < numSamples; j++ )
{
op[0] = (in[j] << shiftVal) | (uint32_t) shift[j];
op += stride;
}
}

342
src/ALAC/matrix_enc.c Normal file
View File

@ -0,0 +1,342 @@
/*
* 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: matrix_enc.c
Contains: ALAC mixing/matrixing encode routines.
Copyright: (c) 2004-2011 Apple, Inc.
*/
#include "matrixlib.h"
#include "ALACAudioTypes.h"
// up to 24-bit "offset" macros for the individual bytes of a 20/24-bit word
#if TARGET_RT_BIG_ENDIAN
#define LBYTE 2
#define MBYTE 1
#define HBYTE 0
#else
#define LBYTE 0
#define MBYTE 1
#define HBYTE 2
#endif
/*
There is no plain middle-side option; instead there are various mixing
modes including middle-side, each lossless, as embodied in the mix()
and unmix() functions. These functions exploit a generalized middle-side
transformation:
u := [(rL + (m-r)R)/m];
v := L - R;
where [ ] denotes integer floor. The (lossless) inverse is
L = u + v - [rV/m];
R = L - v;
*/
// 16-bit routines
void mix16( int16_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
int16_t * ip = in;
int32_t j;
if ( mixres != 0 )
{
int32_t mod = 1 << mixbits;
int32_t m2;
/* matrixed stereo */
m2 = mod - mixres;
for ( j = 0; j < numSamples; j++ )
{
int32_t l, r;
l = (int32_t) ip[0];
r = (int32_t) ip[1];
ip += stride;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
u[j] = (int32_t) ip[0];
v[j] = (int32_t) ip[1];
ip += stride;
}
}
}
// 20-bit routines
// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
void mix20( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres )
{
int32_t l, r;
uint8_t * ip = in;
int32_t j;
if ( mixres != 0 )
{
/* matrixed stereo */
int32_t mod = 1 << mixbits;
int32_t m2 = mod - mixres;
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 12;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 12;
ip += (stride - 1) * 3;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
/* Conventional separated stereo. */
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
u[j] = (l << 8) >> 12;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
v[j] = (r << 8) >> 12;
ip += (stride - 1) * 3;
}
}
}
// 24-bit routines
// - the 24 bits of data are right-justified in the input/output predictor buffers
void mix24( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
int32_t l, r;
uint8_t * ip = in;
int32_t shift = bytesShifted * 8;
uint32_t mask = (1ul << shift) - 1;
int32_t j, k;
if ( mixres != 0 )
{
/* matrixed stereo */
int32_t mod = 1 << mixbits;
int32_t m2 = mod - mixres;
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 8;
ip += (stride - 1) * 3;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 8;
ip += (stride - 1) * 3;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
}
else
{
/* Conventional separated stereo. */
if ( bytesShifted != 0 )
{
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
l = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
r = (r << 8) >> 8;
ip += (stride - 1) * 3;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = l;
v[j] = r;
}
}
else
{
for ( j = 0; j < numSamples; j++ )
{
l = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
u[j] = (l << 8) >> 8;
ip += 3;
r = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
v[j] = (r << 8) >> 8;
ip += (stride - 1) * 3;
}
}
}
}
// 32-bit routines
// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
// - otherwise, the calculations might overflow into the 33rd bit and be lost
// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
void mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted )
{
int32_t * ip = in;
int32_t shift = bytesShifted * 8;
uint32_t mask = (1ul << shift) - 1;
int32_t l, r;
int32_t j, k;
if ( mixres != 0 )
{
int32_t mod = 1 << mixbits;
int32_t m2;
//Assert( bytesShifted != 0 );
/* matrixed stereo with shift */
m2 = mod - mixres;
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = ip[0];
r = ip[1];
ip += stride;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = (mixres * l + m2 * r) >> mixbits;
v[j] = l - r;
}
}
else
{
if ( bytesShifted == 0 )
{
/* de-interleaving w/o shift */
for ( j = 0; j < numSamples; j++ )
{
u[j] = ip[0];
v[j] = ip[1];
ip += stride;
}
}
else
{
/* de-interleaving with shift */
for ( j = 0, k = 0; j < numSamples; j++, k += 2 )
{
l = ip[0];
r = ip[1];
ip += stride;
shiftUV[k + 0] = (uint16_t)(l & mask);
shiftUV[k + 1] = (uint16_t)(r & mask);
l >>= shift;
r >>= shift;
u[j] = l;
v[j] = r;
}
}
}
}
// 20/24-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
void copy20ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples )
{
uint8_t * ip = in;
int32_t j;
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
// 20-bit values are left-aligned in the 24-bit input buffer but right-aligned in the 32-bit output buffer
val = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
out[j] = (val << 8) >> 12;
ip += stride * 3;
}
}
void copy24ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples )
{
uint8_t * ip = in;
int32_t j;
for ( j = 0; j < numSamples; j++ )
{
int32_t val;
val = (int32_t)( ((uint32_t)ip[HBYTE] << 16) | ((uint32_t)ip[MBYTE] << 8) | (uint32_t)ip[LBYTE] );
out[j] = (val << 8) >> 8;
ip += stride * 3;
}
}

80
src/ALAC/matrixlib.h Normal file
View File

@ -0,0 +1,80 @@
/*
* 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: matrixlib.h
Contains: ALAC mixing/matrixing routines to/from 32-bit predictor buffers.
Copyright: Copyright (C) 2004 to 2011 Apple, Inc.
*/
#ifndef __MATRIXLIB_H
#define __MATRIXLIB_H
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// 16-bit routines
void mix16( int16_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
void unmix16( int32_t * u, int32_t * v, int16_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
// 20-bit routines
void mix20( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres );
void unmix20( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t mixbits, int32_t mixres );
// 24-bit routines
// - 24-bit data sometimes compresses better by shifting off the bottom byte so these routines deal with
// the specified "unused lower bytes" in the combined "shift" buffer
void mix24( uint8_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
void unmix24( int32_t * u, int32_t * v, uint8_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
// 32-bit routines
// - note that these really expect the internal data width to be < 32-bit but the arrays are 32-bit
// - otherwise, the calculations might overflow into the 33rd bit and be lost
// - therefore, these routines deal with the specified "unused lower" bytes in the combined "shift" buffer
void mix32( int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
void unmix32( int32_t * u, int32_t * v, int32_t * out, uint32_t stride, int32_t numSamples,
int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted );
// 20/24/32-bit <-> 32-bit helper routines (not really matrixing but convenient to put here)
void copy20ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
void copy24ToPredictor( uint8_t * in, uint32_t stride, int32_t * out, int32_t numSamples );
void copyPredictorTo24( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples );
void copyPredictorTo24Shift( int32_t * in, uint16_t * shift, uint8_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
void copyPredictorTo20( int32_t * in, uint8_t * out, uint32_t stride, int32_t numSamples );
void copyPredictorTo32( int32_t * in, int32_t * out, uint32_t stride, int32_t numSamples );
void copyPredictorTo32Shift( int32_t * in, uint16_t * shift, int32_t * out, uint32_t stride, int32_t numSamples, int32_t bytesShifted );
#ifdef __cplusplus
}
#endif
#endif /* __MATRIXLIB_H */