| 
					
				 | 
			
			
				@@ -0,0 +1,1432 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 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.cpp 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// build stuff 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define VERBOSE_DEBUG		0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// headers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <stdio.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <stdlib.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "ALACEncoder.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "aglib.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "dplib.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "matrixlib.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "ALACBitUtilities.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "ALACAudioTypes.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "EndianPortable.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if (__GNUC__) > 4 || defined (__APPLE__) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#pragma GCC diagnostic ignored "-Wunused-const-variable" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if !defined(__APPLE__)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#pragma GCC diagnostic ignored "-Wunused-but-set-variable" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// Note: in C you can't typecast to a 2-dimensional array pointer but that's what we need when 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// picking which coefs to use so we declare this typedef b/c we *can* typecast to this type 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+typedef int16_t (*SearchCoefs)[kALACMaxCoefs]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// defines/constants 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kALACEncoderMagic	= 'dpge'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kMaxSampleSize		= 32;			// max allowed bit width is 32 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kDefaultMixBits	= 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kDefaultMixRes		= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kMaxRes			= 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kDefaultNumUV		= 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kMinUV				= 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const uint32_t kMaxUV				= 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// static functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if VERBOSE_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void AddFiller( BitBuffer * bits, int32_t numBytes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Map Format: 3-bit field per channel which is the same as the "element tag" that should be placed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				at the beginning of the frame for that channel.  Indicates whether SCE, CPE, or LFE. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				Each particular field is accessed via the current channel index.  Note that the channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index increments by two for channel pairs. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	For example: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			C L R 3-channel input		= (ID_CPE << 3) | (ID_SCE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index 0 value = (map & (0x7ul << (0 * 3))) >> (0 * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index 1 value = (map & (0x7ul << (1 * 3))) >> (1 * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			C L R Ls Rs LFE 5.1-channel input = (ID_LFE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index 0 value = (map & (0x7ul << (0 * 3))) >> (0 * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index 1 value = (map & (0x7ul << (1 * 3))) >> (1 * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index 3 value = (map & (0x7ul << (3 * 3))) >> (3 * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index 5 value = (map & (0x7ul << (5 * 3))) >> (5 * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				index 7 value = (map & (0x7ul << (7 * 3))) >> (7 * 3) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const uint32_t	sChannelMaps[kALACMaxChannels] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ID_SCE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ID_CPE, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(ID_CPE << 3) | (ID_SCE), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(ID_SCE << 9) | (ID_CPE << 3) | (ID_SCE), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(ID_SCE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(ID_SCE << 18) | (ID_SCE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	(ID_SCE << 21) | (ID_CPE << 15) | (ID_CPE << 9) | (ID_CPE << 3) | (ID_SCE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const uint32_t sSupportediPodSampleRates[] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Constructor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ALACEncoder::ALACEncoder() : 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mBitDepth( 0 ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mFastMode( 0 ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mMixBufferU( nil ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mMixBufferV( nil ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mPredictorU( nil ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mPredictorV( nil ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mShiftBufferUV( nil ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mWorkBuffer( nil ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mTotalBytesGenerated( 0 ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mAvgBitRate( 0 ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mMaxFrameBytes( 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// overrides 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mFrameSize = kALACDefaultFrameSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Destructor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ALACEncoder::~ALACEncoder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// delete the matrix mixing buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mMixBufferU ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		free(mMixBufferU); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mMixBufferU = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mMixBufferV ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		free(mMixBufferV); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mMixBufferV = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// delete the dynamic predictor's "corrector" buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mPredictorU ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		free(mPredictorU); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mPredictorU = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mPredictorV ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		free(mPredictorV); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mPredictorV = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// delete the unused byte shift buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mShiftBufferUV ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		free(mShiftBufferUV); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mShiftBufferUV = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// delete the work buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mWorkBuffer ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		free(mWorkBuffer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mWorkBuffer = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if PRAGMA_MARK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#pragma mark - 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	HEADER SPECIFICATION   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        For every segment we adopt the following header: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte reserved			(always 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte flags			(see below) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			[4 byte frame length]	(optional, see below) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			     ---Next, the per-segment ALAC parameters--- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte mixBits			(middle-side parameter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte mixRes			(middle-side parameter, interpreted as signed char) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte shiftU			(4 bits modeU, 4 bits denShiftU) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte filterU			(3 bits pbFactorU, 5 bits numU) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			(numU) shorts			(signed DP coefficients for V channel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			     ---Next, 2nd-channel ALAC parameters in case of stereo mode--- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte shiftV			(4 bits modeV, 4 bits denShiftV) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			1 byte filterV			(3 bits pbFactorV, 5 bits numV) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			(numV) shorts			(signed DP coefficients for V channel) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			     ---After this come the shift-off bytes for (>= 24)-bit data (n-byte shift) if indicated--- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			     ---Then comes the AG-compressor bitstream--- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        FLAGS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ----- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		The presence of certain flag bits changes the header format such that the parameters might 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		not even be sent.  The currently defined flags format is: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			0000psse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			where		0 	= reserved, must be 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						p	= 1-bit field "partial frame" flag indicating 32-bit frame length follows this byte 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						ss	= 2-bit field indicating "number of shift-off bytes ignored by compression" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						e	= 1-bit field indicating "escape" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		The "partial frame" flag means that the following segment is not equal to the frame length specified 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		in the out-of-band decoder configuration.  This allows the decoder to deal with end-of-file partial 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		segments without incurring the 32-bit overhead for each segment. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		The "shift-off" field indicates the number of bytes at the bottom of the word that were passed through 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uncompressed.  The reason for this is that the entropy inherent in the LS bytes of >= 24-bit words 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		quite often means that the frame would have to be "escaped" b/c the compressed size would be >= the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uncompressed size.  However, by shifting the input values down and running the remaining bits through 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		the normal compression algorithm, a net win can be achieved.  If this field is non-zero, it means that 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		the shifted-off bytes follow after the parameter section of the header and before the compressed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bitstream.  Note that doing this also allows us to use matrixing on 32-bit inputs after one or more 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytes are shifted off the bottom which helps the eventual compression ratio.  For stereo channels, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		the shifted off bytes are interleaved. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        The "escape" flag means that this segment was not compressed b/c the compressed size would be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        >= uncompressed size.  In that case, the audio data was passed through uncompressed after the header. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        The other header parameter bytes will not be sent. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		PARAMETERS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		---------- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		If the segment is not a partial or escape segment, the total header size (in bytes) is given exactly by: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			4 + (2 + 2 * numU)                   (mono mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			4 + (2 + 2 * numV) + (2 + 2 * numV)  (stereo mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        where the ALAC filter-lengths numU, numV are bounded by a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        constant (in the current source, numU, numV <= NUMCOEPAIRS), and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this forces an absolute upper bound on header size. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Each segment-decode process loads up these bytes from the front of the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        local stream, in the above order, then follows with the entropy-encoded 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bits for the given segment. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        To generalize middle-side, 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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        In the segment header, m and r are encoded in mixBits and mixRes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        Classical "middle-side" is obtained with m = 2, r = 1, but now 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        we have more generalized mixes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        NOTES 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ----- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        The relevance of the ALAC coefficients is explained in detail 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        in patent documents. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	EncodeStereo() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- encode a channel pair 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int32_t ALACEncoder::EncodeStereo( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t channelIndex, uint32_t numSamples ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBuffer		workBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBuffer		startBits = *bitstream;			// squirrel away copy of current state in case we need to go back and do an escape packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	AGParamRec		agParams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t          bits1, bits2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			dilate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t			mixBits, mixRes, maxRes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			minBits, minBits1, minBits2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			numU, numV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			mode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			pbFactor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			chanBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			denShift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			bytesShifted; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	SearchCoefs		coefsU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	SearchCoefs		coefsV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			partialFrame; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			escapeBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bool			doEscape; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t		status = ALAC_noErr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// make sure we handle this bit-depth before we get going 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	RequireAction( (mBitDepth == 16) || (mBitDepth == 20) || (mBitDepth == 24) || (mBitDepth == 32), return kALAC_ParamError; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// reload coefs pointers for this channel pair 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - note that, while you might think they should be re-initialized per block, retaining state across blocks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//	 actually results in better overall compression 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - strangely, re-using the same coefs for the different passes of the "mixRes" search loop instead of using 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//	 different coefs for the different passes of "mixRes" results in even better compression 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	coefsU = (SearchCoefs) mCoefsU[channelIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	coefsV = (SearchCoefs) mCoefsV[channelIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// matrix encoding adds an extra bit but 32-bit inputs cannot be matrixed b/c 33 is too many 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// so enable 16-bit "shift off" and encode in 17-bit mode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - in addition, 24-bit mode really improves with one byte shifted off 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mBitDepth == 32 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else if ( mBitDepth >= 24 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	chanBits = mBitDepth - (bytesShifted * 8) + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// flag whether or not this is a partial frame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	partialFrame = (numSamples == mFrameSize) ? 0 : 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// brute-force encode optimization loop 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - run over variations of the encoding params to find the best choice 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mixBits		= kDefaultMixBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	maxRes		= kMaxRes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	numU = numV = kDefaultNumUV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	denShift	= DENSHIFT_DEFAULT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mode		= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pbFactor	= 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	dilate		= 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits	= minBits1 = minBits2 = 1ul << 31; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int32_t		bestRes = mLastMixRes[channelIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for ( mixRes = 0; mixRes <= maxRes; mixRes++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // mix the stereo inputs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        switch ( mBitDepth ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case 16: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mix16( (int16_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate, mixBits, mixRes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case 20: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate, mixBits, mixRes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case 24: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // includes extraction of shifted-off bytes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        mixBits, mixRes, mShiftBufferUV, bytesShifted ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            case 32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // includes extraction of shifted-off bytes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                mix32( (int32_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples/dilate, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        mixBits, mixRes, mShiftBufferUV, bytesShifted ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        BitBufferInit( &workBits, mWorkBuffer, mMaxOutputBytes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // run the dynamic predictors 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        pc_block( mMixBufferV, mPredictorV, numSamples/dilate, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // run the lossless compressor on each channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        status = dyn_comp( &agParams, mPredictorU, &workBits, numSamples/dilate, chanBits, &bits1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        status = dyn_comp( &agParams, mPredictorV, &workBits, numSamples/dilate, chanBits, &bits2 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // look for best match 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ( (bits1 + bits2) < minBits1 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            minBits1 = bits1 + bits2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            bestRes = mixRes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mLastMixRes[channelIndex] = (int16_t)bestRes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// mix the stereo inputs with the current best mixRes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mixRes = mLastMixRes[channelIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch ( mBitDepth ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 16: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix16( (int16_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 20: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 24: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// also extracts the shifted off bytes into the shift buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					mixBits, mixRes, mShiftBufferUV, bytesShifted ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// also extracts the shifted off bytes into the shift buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix32( (int32_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					mixBits, mixRes, mShiftBufferUV, bytesShifted ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// now it's time for the predictor coefficient search loop 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	numU = numV = kMinUV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits1 = minBits2 = 1ul << 31; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for ( uint32_t numUV = kMinUV; numUV <= kMaxUV; numUV += 4 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferInit( &workBits, mWorkBuffer, mMaxOutputBytes );		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		dilate = 32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// run the predictor over the same data multiple times to help it converge 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( uint32_t converge = 0; converge < 8; converge++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		    pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numUV-1], numUV, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		    pc_block( mMixBufferV, mPredictorV, numSamples/dilate, coefsV[numUV-1], numUV, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		dilate = 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		set_ag_params( &agParams, MB0, (pbFactor * PB0)/4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = dyn_comp( &agParams, mPredictorU, &workBits, numSamples/dilate, chanBits, &bits1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( (bits1 * dilate + 16 * numUV) < minBits1 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			minBits1 = bits1 * dilate + 16 * numUV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			numU = numUV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		set_ag_params( &agParams, MB0, (pbFactor * PB0)/4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = dyn_comp( &agParams, mPredictorV, &workBits, numSamples/dilate, chanBits, &bits2 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( (bits2 * dilate + 16 * numUV) < minBits2 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			minBits2 = bits2 * dilate + 16 * numUV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			numV = numUV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// test for escape hatch if best calculated compressed size turns out to be more than the input size 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits = minBits1 + minBits2 + (8 /* mixRes/maxRes/etc. */ * 8) + ((partialFrame == true) ? 32 : 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( bytesShifted != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		minBits += (numSamples * (bytesShifted * 8) * 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	escapeBits = (numSamples * mBitDepth * 2) + ((partialFrame == true) ? 32 : 0) + (2 * 8);	/* 2 common header bytes */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	doEscape = (minBits >= escapeBits) ? true : false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( doEscape == false ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// write bitstream header and coefs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, 0, 12 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (partialFrame << 3) | (bytesShifted << 1), 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( partialFrame ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bitstream, numSamples, 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, mixBits, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, mixRes, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//Assert( (mode < 16) && (DENSHIFT_DEFAULT < 16) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//Assert( (pbFactor < 8) && (numU < 32) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//Assert( (pbFactor < 8) && (numV < 32) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (pbFactor << 5) | numU, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( index = 0; index < numU; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bitstream, coefsU[numU - 1][index], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (pbFactor << 5) | numV, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( index = 0; index < numV; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bitstream, coefsV[numV - 1][index], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// if shift active, write the interleaved shift buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( bytesShifted != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			uint32_t		bitShift = bytesShifted * 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			//Assert( bitShift <= 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0; index < (numSamples * 2); index += 2 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				uint32_t			shiftedVal; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				shiftedVal = ((uint32_t)mShiftBufferUV[index + 0] << bitShift) | (uint32_t)mShiftBufferUV[index + 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, shiftedVal, bitShift * 2 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// run the dynamic predictor and lossless compression for the "left" channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// - note: to avoid allocating more buffers, we're mixing and matching between the available buffers instead 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//		   of only using "U" buffers for the U-channel and "V" buffers for the V-channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( mode == 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pc_block( mMixBufferU, mPredictorU, numSamples, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pc_block( mMixBufferU, mPredictorV, numSamples, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pc_block( mPredictorV, mPredictorU, numSamples, nil, 31, chanBits, 0 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = dyn_comp( &agParams, mPredictorU, bitstream, numSamples, chanBits, &bits1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// run the dynamic predictor and lossless compression for the "right" channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( mode == 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pc_block( mMixBufferV, mPredictorV, numSamples, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pc_block( mMixBufferV, mPredictorU, numSamples, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pc_block( mPredictorU, mPredictorV, numSamples, nil, 31, chanBits, 0 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = dyn_comp( &agParams, mPredictorV, bitstream, numSamples, chanBits, &bits2 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/*	if we happened to create a compressed packet that was actually bigger than an escape packet would be, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			chuck it and do an escape packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		minBits = BitBufferGetPosition( bitstream ) - BitBufferGetPosition( &startBits ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( minBits >= escapeBits ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			*bitstream = startBits;		// reset bitstream state 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			doEscape = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			printf( "compressed frame too big: %u vs. %u \n", minBits, escapeBits ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( doEscape == true ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* escape */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = this->EncodeStereoEscape( bitstream, inputBuffer, stride, numSamples ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if VERBOSE_DEBUG		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DebugMsg( "escape!: %lu vs %lu", minBits, escapeBits ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Exit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	EncodeStereoFast() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- encode a channel pair without the search loop for maximum possible speed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int32_t ALACEncoder::EncodeStereoFast( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t channelIndex, uint32_t numSamples ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBuffer		startBits = *bitstream;			// squirrel away current bit position in case we decide to use escape hatch 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	AGParamRec		agParams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t	bits1, bits2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t			mixBits, mixRes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			minBits, minBits1, minBits2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			numU, numV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			mode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			pbFactor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			chanBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			denShift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			bytesShifted; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	SearchCoefs		coefsU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	SearchCoefs		coefsV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			partialFrame; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			escapeBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bool			doEscape;	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t		status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// make sure we handle this bit-depth before we get going 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	RequireAction( (mBitDepth == 16) || (mBitDepth == 20) || (mBitDepth == 24) || (mBitDepth == 32), return kALAC_ParamError; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// reload coefs pointers for this channel pair 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - note that, while you might think they should be re-initialized per block, retaining state across blocks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//	 actually results in better overall compression 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - strangely, re-using the same coefs for the different passes of the "mixRes" search loop instead of using 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//	 different coefs for the different passes of "mixRes" results in even better compression 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	coefsU = (SearchCoefs) mCoefsU[channelIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	coefsV = (SearchCoefs) mCoefsV[channelIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// matrix encoding adds an extra bit but 32-bit inputs cannot be matrixed b/c 33 is too many 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// so enable 16-bit "shift off" and encode in 17-bit mode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - in addition, 24-bit mode really improves with one byte shifted off 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mBitDepth == 32 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else if ( mBitDepth >= 24 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	chanBits = mBitDepth - (bytesShifted * 8) + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// flag whether or not this is a partial frame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	partialFrame = (numSamples == mFrameSize) ? 0 : 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// set up default encoding parameters for "fast" mode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mixBits		= kDefaultMixBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mixRes		= kDefaultMixRes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	numU = numV = kDefaultNumUV; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	denShift	= DENSHIFT_DEFAULT; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mode		= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pbFactor	= 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits	= minBits1 = minBits2 = 1ul << 31; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// mix the stereo inputs with default mixBits/mixRes 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch ( mBitDepth ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 16: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix16( (int16_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 20: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, mixBits, mixRes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 24: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// also extracts the shifted off bytes into the shift buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					mixBits, mixRes, mShiftBufferUV, bytesShifted ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// also extracts the shifted off bytes into the shift buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix32( (int32_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					mixBits, mixRes, mShiftBufferUV, bytesShifted ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* speculatively write the bitstream assuming the compressed version will be smaller */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// write bitstream header and coefs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, 0, 12 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, (partialFrame << 3) | (bytesShifted << 1), 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( partialFrame ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, numSamples, 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, mixBits, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, mixRes, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//Assert( (mode < 16) && (DENSHIFT_DEFAULT < 16) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//Assert( (pbFactor < 8) && (numU < 32) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//Assert( (pbFactor < 8) && (numV < 32) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, (pbFactor << 5) | numU, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for ( index = 0; index < numU; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, coefsU[numU - 1][index], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, (mode << 4) | DENSHIFT_DEFAULT, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, (pbFactor << 5) | numV, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for ( index = 0; index < numV; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, coefsV[numV - 1][index], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// if shift active, write the interleaved shift buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( bytesShifted != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint32_t		bitShift = bytesShifted * 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//Assert( bitShift <= 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( index = 0; index < (numSamples * 2); index += 2 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			uint32_t			shiftedVal; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			shiftedVal = ((uint32_t)mShiftBufferUV[index + 0] << bitShift) | (uint32_t)mShiftBufferUV[index + 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bitstream, shiftedVal, bitShift * 2 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// run the dynamic predictor and lossless compression for the "left" channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - note: we always use mode 0 in the "fast" path so we don't need the code for mode != 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pc_block( mMixBufferU, mPredictorU, numSamples, coefsU[numU - 1], numU, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	status = dyn_comp( &agParams, mPredictorU, bitstream, numSamples, chanBits, &bits1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// run the dynamic predictor and lossless compression for the "right" channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pc_block( mMixBufferV, mPredictorV, numSamples, coefsV[numV - 1], numV, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples, numSamples, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	status = dyn_comp( &agParams, mPredictorV, bitstream, numSamples, chanBits, &bits2 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// do bit requirement calculations 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits1 = bits1 + (numU * sizeof(int16_t) * 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits2 = bits2 + (numV * sizeof(int16_t) * 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// test for escape hatch if best calculated compressed size turns out to be more than the input size 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits = minBits1 + minBits2 + (8 /* mixRes/maxRes/etc. */ * 8) + ((partialFrame == true) ? 32 : 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( bytesShifted != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		minBits += (numSamples * (bytesShifted * 8) * 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	escapeBits = (numSamples * mBitDepth * 2) + ((partialFrame == true) ? 32 : 0) + (2 * 8);	/* 2 common header bytes */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	doEscape = (minBits >= escapeBits) ? true : false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( doEscape == false ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/*	if we happened to create a compressed packet that was actually bigger than an escape packet would be, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			chuck it and do an escape packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		minBits = BitBufferGetPosition( bitstream ) - BitBufferGetPosition( &startBits ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( minBits >= escapeBits ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			doEscape = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			printf( "compressed frame too big: %u vs. %u\n", minBits, escapeBits ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( doEscape == true ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/* escape */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// reset bitstream position since we speculatively wrote the compressed version 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*bitstream = startBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// write escape frame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = this->EncodeStereoEscape( bitstream, inputBuffer, stride, numSamples ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if VERBOSE_DEBUG		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DebugMsg( "escape!: %u vs %u", minBits, (numSamples * mBitDepth * 2) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Exit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	EncodeStereoEscape() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- encode stereo escape frame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int32_t ALACEncoder::EncodeStereoEscape( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t numSamples ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int16_t *		input16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t *		input32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			partialFrame; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// flag whether or not this is a partial frame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	partialFrame = (numSamples == mFrameSize) ? 0 : 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// write bitstream header 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, 0, 12 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bitstream, (partialFrame << 3) | 1, 4 );	// LSB = 1 means "frame not compressed" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( partialFrame ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, numSamples, 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// just copy the input data to the output buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch ( mBitDepth ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 16: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			input16 = (int16_t *) inputBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0; index < (numSamples * stride); index += stride ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, input16[index + 0], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, input16[index + 1], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 20: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// mix20() with mixres param = 0 means de-interleave so use it to simplify things 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix20( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 0, 0 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0; index < numSamples; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, mMixBufferU[index], 20 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, mMixBufferV[index], 20 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 24: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// mix24() with mixres param = 0 means de-interleave so use it to simplify things 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			mix24( (uint8_t *) inputBuffer, stride, mMixBufferU, mMixBufferV, numSamples, 0, 0, mShiftBufferUV, 0 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0; index < numSamples; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, mMixBufferU[index], 24 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, mMixBufferV[index], 24 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			input32 = (int32_t *) inputBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0; index < (numSamples * stride); index += stride ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, input32[index + 0], 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, input32[index + 1], 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			}				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return ALAC_noErr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	EncodeMono() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- encode a mono input buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int32_t ALACEncoder::EncodeMono( BitBuffer * bitstream, void * inputBuffer, uint32_t stride, uint32_t channelIndex, uint32_t numSamples ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBuffer		startBits = *bitstream;			// squirrel away copy of current state in case we need to go back and do an escape packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	AGParamRec		agParams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t	bits1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			numU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	SearchCoefs		coefsU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			dilate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			minBits, bestU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			minU, maxU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			index, index2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			bytesShifted; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			mask; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			chanBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			pbFactor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t			partialFrame; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int16_t *		input16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t *		input32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t			escapeBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bool			doEscape; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t		status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// make sure we handle this bit-depth before we get going 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	RequireAction( (mBitDepth == 16) || (mBitDepth == 20) || (mBitDepth == 24) || (mBitDepth == 32), return kALAC_ParamError; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	status = ALAC_noErr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// reload coefs array from previous frame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	coefsU = (SearchCoefs) mCoefsU[channelIndex]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// pick bit depth for actual encoding 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - we lop off the lower byte(s) for 24-/32-bit encodings 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mBitDepth == 32 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else if ( mBitDepth >= 24 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		bytesShifted = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	shift = bytesShifted * 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mask = (1ul << shift) - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	chanBits = mBitDepth - (bytesShifted * 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// flag whether or not this is a partial frame 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	partialFrame = (numSamples == mFrameSize) ? 0 : 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// convert N-bit data to 32-bit for predictor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	switch ( mBitDepth ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 16: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// convert 16-bit data to 32-bit for predictor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			input16 = (int16_t *) inputBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0, index2 = 0; index < numSamples; index++, index2 += stride ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				mMixBufferU[index] = (int32_t) input16[index2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 20: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// convert 20-bit data to 32-bit for predictor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			copy20ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 24: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// convert 24-bit data to 32-bit for the predictor and extract the shifted off byte(s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			copy24ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0; index < numSamples; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				mShiftBufferUV[index] = (uint16_t)(mMixBufferU[index] & mask); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				mMixBufferU[index] >>= shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		case 32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// just copy the 32-bit input data for the predictor and extract the shifted off byte(s) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			input32 = (int32_t *) inputBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0, index2 = 0; index < numSamples; index++, index2 += stride ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				int32_t			val = input32[index2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				mShiftBufferUV[index] = (uint16_t)(val & mask); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				mMixBufferU[index] = val >> shift; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// brute-force encode optimization loop (implied "encode depth" of 0 if comparing to cmd line tool) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - run over variations of the encoding params to find the best choice 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minU		= 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	maxU		= 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits		= 1ul << 31; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	pbFactor	= 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits	= 1ul << 31; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bestU	= minU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for ( numU = minU; numU <= maxU; numU += 4 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBuffer		workBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint32_t			numBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferInit( &workBits, mWorkBuffer, mMaxOutputBytes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		dilate = 32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( uint32_t converge = 0; converge < 7; converge++ )	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numU-1], numU, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		dilate = 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pc_block( mMixBufferU, mPredictorU, numSamples/dilate, coefsU[numU-1], numU, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		set_ag_params( &agParams, MB0, (pbFactor * PB0) / 4, KB0, numSamples/dilate, numSamples/dilate, MAX_RUN_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = dyn_comp( &agParams, mPredictorU, &workBits, numSamples/dilate, chanBits, &bits1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		numBits = (dilate * bits1) + (16 * numU); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( numBits < minBits ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			bestU	= numU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			minBits = numBits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	}              
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// test for escape hatch if best calculated compressed size turns out to be more than the input size 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - first, add bits for the header bytes mixRes/maxRes/shiftU/filterU 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	minBits += (4 /* mixRes/maxRes/etc. */ * 8) + ((partialFrame == true) ? 32 : 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( bytesShifted != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		minBits += (numSamples * (bytesShifted * 8)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	escapeBits = (numSamples * mBitDepth) + ((partialFrame == true) ? 32 : 0) + (2 * 8);	/* 2 common header bytes */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	doEscape = (minBits >= escapeBits) ? true : false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( doEscape == false ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// write bitstream header 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, 0, 12 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (partialFrame << 3) | (bytesShifted << 1), 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( partialFrame ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bitstream, numSamples, 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, 0, 16 );								// mixBits = mixRes = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// write the params and predictor coefs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		numU = bestU; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (0 << 4) | DENSHIFT_DEFAULT, 8 );	// modeU = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (pbFactor << 5) | numU, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( index = 0; index < numU; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bitstream, coefsU[numU-1][index], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// if shift active, write the interleaved shift buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( bytesShifted != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			for ( index = 0; index < numSamples; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				BitBufferWrite( bitstream, mShiftBufferUV[index], shift ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// run the dynamic predictor with the best result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		pc_block( mMixBufferU, mPredictorU, numSamples, coefsU[numU-1], numU, chanBits, DENSHIFT_DEFAULT ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// do lossless compression 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		set_standard_ag_params( &agParams, numSamples, numSamples ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = dyn_comp( &agParams, mPredictorU, bitstream, numSamples, chanBits, &bits1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		//AssertNoErr( status ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		/*	if we happened to create a compressed packet that was actually bigger than an escape packet would be, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			chuck it and do an escape packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		minBits = BitBufferGetPosition( bitstream ) - BitBufferGetPosition( &startBits ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( minBits >= escapeBits ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			*bitstream = startBits;		// reset bitstream state 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			doEscape = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			printf( "compressed frame too big: %u vs. %u\n", minBits, escapeBits ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( doEscape == true ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// write bitstream header and coefs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, 0, 12 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bitstream, (partialFrame << 3) | 1, 4 );	// LSB = 1 means "frame not compressed" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( partialFrame ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bitstream, numSamples, 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// just copy the input data to the output buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		switch ( mBitDepth ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case 16: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				input16 = (int16_t *) inputBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				for ( index = 0; index < (numSamples * stride); index += stride ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					BitBufferWrite( bitstream, input16[index], 16 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case 20: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// convert 20-bit data to 32-bit for simplicity 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				copy20ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				for ( index = 0; index < numSamples; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					BitBufferWrite( bitstream, mMixBufferU[index], 20 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case 24: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				// convert 24-bit data to 32-bit for simplicity 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				copy24ToPredictor( (uint8_t *) inputBuffer, stride, mMixBufferU, numSamples ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				for ( index = 0; index < numSamples; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					BitBufferWrite( bitstream, mMixBufferU[index], 24 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			case 32: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				input32 = (int32_t *) inputBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				for ( index = 0; index < (numSamples * stride); index += stride ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					BitBufferWrite( bitstream, input32[index], 32 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if VERBOSE_DEBUG		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DebugMsg( "escape!: %lu vs %lu", minBits, (numSamples * mBitDepth) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Exit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if PRAGMA_MARK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#pragma mark - 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Encode() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- encode the next block of samples 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int32_t ALACEncoder::Encode(AudioFormatDescription theInputFormat, AudioFormatDescription theOutputFormat, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                             unsigned char * theReadBuffer, unsigned char * theWriteBuffer, int32_t * ioNumBytes) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t				numFrames; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t				outputSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBuffer			bitstream; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t			status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	numFrames = *ioNumBytes/theInputFormat.mBytesPerPacket; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// create a bit buffer structure pointing to our output buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferInit( &bitstream, theWriteBuffer, mMaxOutputBytes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( theInputFormat.mChannelsPerFrame == 2 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// add 3-bit frame start tag ID_CPE = channel pair & 4-bit element instance tag = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( &bitstream, ID_CPE, 3 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( &bitstream, 0, 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// encode stereo input buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( mFastMode == false ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			status = this->EncodeStereo( &bitstream, theReadBuffer, 2, 0, numFrames ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			status = this->EncodeStereoFast( &bitstream, theReadBuffer, 2, 0, numFrames ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else if ( theInputFormat.mChannelsPerFrame == 1 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// add 3-bit frame start tag ID_SCE = mono channel & 4-bit element instance tag = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( &bitstream, ID_SCE, 3 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( &bitstream, 0, 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// encode mono input buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		status = this->EncodeMono( &bitstream, theReadBuffer, 1, 0, numFrames ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		char *					inputBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint32_t				tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint32_t				channelIndex; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint32_t				inputIncrement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint8_t				stereoElementTag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint8_t				monoElementTag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint8_t				lfeElementTag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		inputBuffer		= (char *) theReadBuffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		inputIncrement	= ((mBitDepth + 7) / 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		stereoElementTag	= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		monoElementTag		= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		lfeElementTag		= 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( channelIndex = 0; channelIndex < theInputFormat.mChannelsPerFrame; ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			tag = (sChannelMaps[theInputFormat.mChannelsPerFrame - 1] & (0x7ul << (channelIndex * 3))) >> (channelIndex * 3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( &bitstream, tag, 3 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			switch ( tag ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				case ID_SCE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// mono 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					BitBufferWrite( &bitstream, monoElementTag, 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					status = this->EncodeMono( &bitstream, inputBuffer, theInputFormat.mChannelsPerFrame, channelIndex, numFrames ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					inputBuffer += inputIncrement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					channelIndex++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					monoElementTag++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				case ID_CPE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// stereo 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					BitBufferWrite( &bitstream, stereoElementTag, 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					status = this->EncodeStereo( &bitstream, inputBuffer, theInputFormat.mChannelsPerFrame, channelIndex, numFrames ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					inputBuffer += (inputIncrement * 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					channelIndex += 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					stereoElementTag++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				case ID_LFE: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// LFE channel (subwoofer) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					BitBufferWrite( &bitstream, lfeElementTag, 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					status = this->EncodeMono( &bitstream, inputBuffer, theInputFormat.mChannelsPerFrame, channelIndex, numFrames ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					inputBuffer += inputIncrement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					channelIndex++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					lfeElementTag++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					printf( "That ain't right! (%u)\n", tag ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					status = kALAC_ParamError; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					goto Exit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			RequireNoErr( status, goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if VERBOSE_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// if there is room left in the output buffer, add some random fill data to test decoder 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t			bitsLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t			bytesLeft; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bitsLeft = BitBufferGetPosition( &bitstream ) - 3;	// - 3 for ID_END tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bytesLeft = bitstream.byteSize - ((bitsLeft + 7) / 8); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( (bytesLeft > 20) && ((bytesLeft & 0x4u) != 0) ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		AddFiller( &bitstream, bytesLeft ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// add 3-bit frame end tag: ID_END 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( &bitstream, ID_END, 3 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// byte-align the output data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferByteAlign( &bitstream, true ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	outputSize = BitBufferGetPosition( &bitstream ) / 8; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//Assert( outputSize <= mMaxOutputBytes ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// all good, let iTunes know what happened and remember the total number of input sample frames 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	*ioNumBytes = outputSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//mEncodedFrames		   	   += encodeMsg->numInputSamples; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// gather encoding stats 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mTotalBytesGenerated += outputSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mMaxFrameBytes = MAX( mMaxFrameBytes, outputSize ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	status = ALAC_noErr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Exit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Finish() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- drain out any leftover samples 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int32_t ALACEncoder::Finish() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/*	// finalize bit rate statistics 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( mSampleSize.numEntries != 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mAvgBitRate = (uint32_t)( (((float)mTotalBytesGenerated * 8.0f) / (float)mSampleSize.numEntries) * ((float)mSampleRate / (float)mFrameSize) ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mAvgBitRate = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return ALAC_noErr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if PRAGMA_MARK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#pragma mark - 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	GetConfig() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void ALACEncoder::GetConfig( ALACSpecificConfig & config ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.frameLength			= Swap32NtoB(mFrameSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.compatibleVersion	= (uint8_t) kALACCompatibleVersion; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.bitDepth				= (uint8_t) mBitDepth; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.pb					= (uint8_t) PB0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.kb					= (uint8_t) KB0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.mb					= (uint8_t) MB0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.numChannels			= (uint8_t) mNumChannels; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.maxRun				= Swap16NtoB((uint16_t) MAX_RUN_DEFAULT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.maxFrameBytes		= Swap32NtoB(mMaxFrameBytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.avgBitRate			= Swap32NtoB(mAvgBitRate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	config.sampleRate			= Swap32NtoB(mOutputSampleRate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+uint32_t ALACEncoder::GetMagicCookieSize(uint32_t inNumChannels) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (inNumChannels > 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return sizeof(ALACSpecificConfig) + kChannelAtomSize + sizeof(ALACAudioChannelLayout); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return sizeof(ALACSpecificConfig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void ALACEncoder::GetMagicCookie(void * outCookie, uint32_t * ioSize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ALACSpecificConfig theConfig = {0}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ALACAudioChannelLayout theChannelLayout = {0}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uint8_t theChannelAtom[kChannelAtomSize] = {0, 0, 0, 0, 'c', 'h', 'a', 'n', 0, 0, 0, 0}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uint32_t theCookieSize = sizeof(ALACSpecificConfig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uint8_t * theCookiePointer = (uint8_t *)outCookie; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GetConfig(theConfig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (theConfig.numChannels > 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        theChannelLayout.mChannelLayoutTag = ALACChannelLayoutTags[theConfig.numChannels - 1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        theCookieSize += (sizeof(ALACAudioChannelLayout) + kChannelAtomSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     if (*ioSize >= theCookieSize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        memcpy(theCookiePointer, &theConfig, sizeof(ALACSpecificConfig)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        theChannelAtom[3] = (sizeof(ALACAudioChannelLayout) + kChannelAtomSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (theConfig.numChannels > 2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            theCookiePointer += sizeof(ALACSpecificConfig); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            memcpy(theCookiePointer, theChannelAtom, kChannelAtomSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            theCookiePointer += kChannelAtomSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            memcpy(theCookiePointer, &theChannelLayout, sizeof(ALACAudioChannelLayout)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        *ioSize = theCookieSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        *ioSize = 0; // no incomplete cookies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	InitializeEncoder() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- initialize the encoder component with the current config 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+int32_t ALACEncoder::InitializeEncoder(AudioFormatDescription theOutputFormat) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int32_t			status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mOutputSampleRate = theOutputFormat.mSampleRate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    mNumChannels = theOutputFormat.mChannelsPerFrame; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    switch(theOutputFormat.mFormatFlags) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case 1: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            mBitDepth = 16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case 2: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            mBitDepth = 20; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case 3: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            mBitDepth = 24; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        case 4: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            mBitDepth = 32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// set up default encoding parameters and state 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - note: mFrameSize is set in the constructor or via SetFrameSize() which must be called before this routine 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for ( uint32_t index = 0; index < kALACMaxChannels; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mLastMixRes[index] = kDefaultMixRes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// the maximum output frame size can be no bigger than (samplesPerBlock * numChannels * ((10 + sampleSize)/8) + 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// but note that this can be bigger than the input size! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - since we don't yet know what our input format will be, use our max allowed sample size in the calculation 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mMaxOutputBytes = mFrameSize * mNumChannels * ((10 + kMaxSampleSize) / 8)  + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// allocate mix buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mMixBufferU = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mMixBufferV = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// allocate dynamic predictor buffers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mPredictorU = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mPredictorV = (int32_t *) calloc( mFrameSize * sizeof(int32_t), 1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// allocate combined shift buffer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mShiftBufferUV = (uint16_t *) calloc( mFrameSize * 2 * sizeof(uint16_t),1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// allocate work buffer for search loop 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	mWorkBuffer = (uint8_t *) calloc( mMaxOutputBytes, 1 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	RequireAction( (mMixBufferU != nil) && (mMixBufferV != nil) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					(mPredictorU != nil) && (mPredictorV != nil) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					(mShiftBufferUV != nil) && (mWorkBuffer != nil ), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					status = kALAC_MemFullError; goto Exit; ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	status = ALAC_noErr; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// initialize coefs arrays once b/c retaining state across blocks actually improves the encode ratio 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for ( int32_t channel = 0; channel < (int32_t)mNumChannels; channel++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( int32_t search = 0; search < kALACMaxSearches; search++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			init_coefs( mCoefsU[channel][search], DENSHIFT_DEFAULT, kALACMaxCoefs ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			init_coefs( mCoefsV[channel][search], DENSHIFT_DEFAULT, kALACMaxCoefs ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+Exit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return status; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	GetSourceFormat() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- given the input format, return one of our supported formats 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void ALACEncoder::GetSourceFormat( const AudioFormatDescription * source, AudioFormatDescription * output ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// default is 16-bit native endian 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - note: for float input we assume that's coming from one of our decoders (mp3, aac) so it only makes sense 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	//		   to encode to 16-bit since the source was lossy in the first place 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// - note: if not a supported bit depth, find the closest supported bit depth to the input one 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( (source->mFormatID != kALACFormatLinearPCM) || ((source->mFormatFlags & kALACFormatFlagIsFloat) != 0) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		( source->mBitsPerChannel <= 16 ) ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mBitDepth = 16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else if ( source->mBitsPerChannel <= 20 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mBitDepth = 20; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else if ( source->mBitsPerChannel <= 24 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mBitDepth = 24; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mBitDepth = 32; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// we support 16/20/24/32-bit integer data at any sample rate and our target number of channels 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// and sample rate were specified when we were configured 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    MakeUncompressedAudioFormat( mNumChannels, (float) mOutputSampleRate, mBitDepth, kAudioFormatFlagsNativeIntegerPacked, output ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if VERBOSE_DEBUG 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#if PRAGMA_MARK 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#pragma mark - 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	AddFiller() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	- add fill and data stream elements to the bitstream to test the decoder 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void AddFiller( BitBuffer * bits, int32_t numBytes ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint8_t		tag; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uint32_t		index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// out of lameness, subtract 6 bytes to deal with header + alignment as required for fill/data elements 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	numBytes -= 6; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( numBytes <= 0 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// randomly pick Fill or Data Stream Element based on numBytes requested 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	tag = (numBytes & 0x8) ? ID_FIL : ID_DSE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	BitBufferWrite( bits, tag, 3 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if ( tag == ID_FIL ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// can't write more than 269 bytes in a fill element 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		numBytes = (numBytes > 269) ? 269 : numBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// fill element = 4-bit size unless >= 15 then 4-bit size + 8-bit extension size 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( numBytes >= 15 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			uint16_t			extensionSize; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, 15, 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// 8-bit extension count field is "extra + 1" which is weird but I didn't define the syntax 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// - otherwise, there's no way to represent 15 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// - for example, to really mean 15 bytes you must encode extensionSize = 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// - why it's not like data stream elements I have no idea 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			extensionSize = (numBytes - 15) + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Assert( extensionSize <= 255 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, extensionSize, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, numBytes, 4 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bits, 0x10, 8 );		// extension_type = FILL_DATA = b0001 or'ed with fill_nibble = b0000 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( index = 0; index < (numBytes - 1); index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, 0xa5, 8 );	// fill_byte = b10100101 = 0xa5 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// can't write more than 510 bytes in a data stream element 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		numBytes = (numBytes > 510) ? 510 : numBytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bits, 0, 4 );			// element instance tag 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferWrite( bits, 1, 1 );			// byte-align flag = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// data stream element = 8-bit size unless >= 255 then 8-bit size + 8-bit size 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if ( numBytes >= 255 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, 255, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, numBytes - 255, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, numBytes, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		BitBufferByteAlign( bits, true );		// byte-align with zeros 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for ( index = 0; index < numBytes; index++ ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			BitBufferWrite( bits, 0x5a, 8 ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif	/* VERBOSE_DEBUG */ 
			 |