1b815c7f3Sopenharmony_ci/*
2b815c7f3Sopenharmony_ci * Copyright (c) 2011 Apple Inc. All rights reserved.
3b815c7f3Sopenharmony_ci * Copyright (C) 2012-2014 Erik de Castro Lopo <erikd@mega-nerd.com>
4b815c7f3Sopenharmony_ci *
5b815c7f3Sopenharmony_ci * @APPLE_APACHE_LICENSE_HEADER_START@
6b815c7f3Sopenharmony_ci *
7b815c7f3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License") ;
8b815c7f3Sopenharmony_ci * you may not use this file except in compliance with the License.
9b815c7f3Sopenharmony_ci * You may obtain a copy of the License at
10b815c7f3Sopenharmony_ci *
11b815c7f3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
12b815c7f3Sopenharmony_ci *
13b815c7f3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14b815c7f3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15b815c7f3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16b815c7f3Sopenharmony_ci * See the License for the specific language governing permissions and
17b815c7f3Sopenharmony_ci * limitations under the License.
18b815c7f3Sopenharmony_ci *
19b815c7f3Sopenharmony_ci * @APPLE_APACHE_LICENSE_HEADER_END@
20b815c7f3Sopenharmony_ci */
21b815c7f3Sopenharmony_ci
22b815c7f3Sopenharmony_ci/*
23b815c7f3Sopenharmony_ci	File:		matrix_enc.c
24b815c7f3Sopenharmony_ci
25b815c7f3Sopenharmony_ci	Contains:	ALAC mixing/matrixing encode routines.
26b815c7f3Sopenharmony_ci
27b815c7f3Sopenharmony_ci	Copyright:	(c) 2004-2011 Apple, Inc.
28b815c7f3Sopenharmony_ci*/
29b815c7f3Sopenharmony_ci
30b815c7f3Sopenharmony_ci#include "matrixlib.h"
31b815c7f3Sopenharmony_ci#include "ALACAudioTypes.h"
32b815c7f3Sopenharmony_ci
33b815c7f3Sopenharmony_ci/*
34b815c7f3Sopenharmony_ci    There is no plain middle-side option ; instead there are various mixing
35b815c7f3Sopenharmony_ci    modes including middle-side, each lossless, as embodied in the mix ()
36b815c7f3Sopenharmony_ci    and unmix () functions.  These functions exploit a generalized middle-side
37b815c7f3Sopenharmony_ci    transformation:
38b815c7f3Sopenharmony_ci
39b815c7f3Sopenharmony_ci    u := [(rL + (m-r)R)/m] ;
40b815c7f3Sopenharmony_ci    v := L - R ;
41b815c7f3Sopenharmony_ci
42b815c7f3Sopenharmony_ci    where [ ] denotes integer floor.  The (lossless) inverse is
43b815c7f3Sopenharmony_ci
44b815c7f3Sopenharmony_ci    L = u + v - [rV/m] ;
45b815c7f3Sopenharmony_ci    R = L - v ;
46b815c7f3Sopenharmony_ci*/
47b815c7f3Sopenharmony_ci
48b815c7f3Sopenharmony_ci// 16-bit routines
49b815c7f3Sopenharmony_ci
50b815c7f3Sopenharmony_civoid
51b815c7f3Sopenharmony_cimix16 (const int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres)
52b815c7f3Sopenharmony_ci{
53b815c7f3Sopenharmony_ci	int32_t		j ;
54b815c7f3Sopenharmony_ci
55b815c7f3Sopenharmony_ci	if (mixres != 0)
56b815c7f3Sopenharmony_ci	{
57b815c7f3Sopenharmony_ci		int32_t		mod = 1 << mixbits ;
58b815c7f3Sopenharmony_ci		int32_t		m2 ;
59b815c7f3Sopenharmony_ci
60b815c7f3Sopenharmony_ci		/* matrixed stereo */
61b815c7f3Sopenharmony_ci		m2 = mod - mixres ;
62b815c7f3Sopenharmony_ci		for (j = 0 ; j < numSamples ; j++)
63b815c7f3Sopenharmony_ci		{
64b815c7f3Sopenharmony_ci			int32_t		l, r ;
65b815c7f3Sopenharmony_ci
66b815c7f3Sopenharmony_ci			l = in [0] >> 16 ;
67b815c7f3Sopenharmony_ci			r = in [1] >> 16 ;
68b815c7f3Sopenharmony_ci			in += stride ;
69b815c7f3Sopenharmony_ci			u [j] = (mixres * l + m2 * r) >> mixbits ;
70b815c7f3Sopenharmony_ci			v [j] = l - r ;
71b815c7f3Sopenharmony_ci		}
72b815c7f3Sopenharmony_ci	}
73b815c7f3Sopenharmony_ci	else
74b815c7f3Sopenharmony_ci	{
75b815c7f3Sopenharmony_ci		/* Conventional separated stereo. */
76b815c7f3Sopenharmony_ci		for (j = 0 ; j < numSamples ; j++)
77b815c7f3Sopenharmony_ci		{
78b815c7f3Sopenharmony_ci			u [j] = in [0] >> 16 ;
79b815c7f3Sopenharmony_ci			v [j] = in [1] >> 16 ;
80b815c7f3Sopenharmony_ci			in += stride ;
81b815c7f3Sopenharmony_ci		}
82b815c7f3Sopenharmony_ci	}
83b815c7f3Sopenharmony_ci}
84b815c7f3Sopenharmony_ci
85b815c7f3Sopenharmony_ci// 20-bit routines
86b815c7f3Sopenharmony_ci// - the 20 bits of data are left-justified in 3 bytes of storage but right-aligned for input/output predictor buffers
87b815c7f3Sopenharmony_ci
88b815c7f3Sopenharmony_civoid
89b815c7f3Sopenharmony_cimix20 (const int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples, int32_t mixbits, int32_t mixres)
90b815c7f3Sopenharmony_ci{
91b815c7f3Sopenharmony_ci	int32_t		l, r ;
92b815c7f3Sopenharmony_ci	int32_t		j ;
93b815c7f3Sopenharmony_ci
94b815c7f3Sopenharmony_ci	if (mixres != 0)
95b815c7f3Sopenharmony_ci	{
96b815c7f3Sopenharmony_ci		/* matrixed stereo */
97b815c7f3Sopenharmony_ci		int32_t		mod = 1 << mixbits ;
98b815c7f3Sopenharmony_ci		int32_t		m2 = mod - mixres ;
99b815c7f3Sopenharmony_ci
100b815c7f3Sopenharmony_ci		for (j = 0 ; j < numSamples ; j++)
101b815c7f3Sopenharmony_ci		{
102b815c7f3Sopenharmony_ci			l = in [0] >> 12 ;
103b815c7f3Sopenharmony_ci			r = in [1] >> 12 ;
104b815c7f3Sopenharmony_ci			in += stride ;
105b815c7f3Sopenharmony_ci
106b815c7f3Sopenharmony_ci			u [j] = (mixres * l + m2 * r) >> mixbits ;
107b815c7f3Sopenharmony_ci			v [j] = l - r ;
108b815c7f3Sopenharmony_ci		}
109b815c7f3Sopenharmony_ci	}
110b815c7f3Sopenharmony_ci	else
111b815c7f3Sopenharmony_ci	{
112b815c7f3Sopenharmony_ci		/* Conventional separated stereo. */
113b815c7f3Sopenharmony_ci		for (j = 0 ; j < numSamples ; j++)
114b815c7f3Sopenharmony_ci		{
115b815c7f3Sopenharmony_ci			u [j] = in [0] >> 12 ;
116b815c7f3Sopenharmony_ci			v [j] = in [1] >> 12 ;
117b815c7f3Sopenharmony_ci			in += stride ;
118b815c7f3Sopenharmony_ci		}
119b815c7f3Sopenharmony_ci	}
120b815c7f3Sopenharmony_ci}
121b815c7f3Sopenharmony_ci
122b815c7f3Sopenharmony_ci// 24-bit routines
123b815c7f3Sopenharmony_ci// - the 24 bits of data are right-justified in the input/output predictor buffers
124b815c7f3Sopenharmony_ci
125b815c7f3Sopenharmony_civoid
126b815c7f3Sopenharmony_cimix24 (const int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
127b815c7f3Sopenharmony_ci			int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted)
128b815c7f3Sopenharmony_ci{
129b815c7f3Sopenharmony_ci	int32_t		l, r ;
130b815c7f3Sopenharmony_ci	int32_t		shift = bytesShifted * 8 ;
131b815c7f3Sopenharmony_ci	uint32_t	mask = (1ul << shift) - 1 ;
132b815c7f3Sopenharmony_ci	int32_t		j, k ;
133b815c7f3Sopenharmony_ci
134b815c7f3Sopenharmony_ci	if (mixres != 0)
135b815c7f3Sopenharmony_ci	{
136b815c7f3Sopenharmony_ci		/* matrixed stereo */
137b815c7f3Sopenharmony_ci		int32_t		mod = 1 << mixbits ;
138b815c7f3Sopenharmony_ci		int32_t		m2 = mod - mixres ;
139b815c7f3Sopenharmony_ci
140b815c7f3Sopenharmony_ci		if (bytesShifted != 0)
141b815c7f3Sopenharmony_ci		{
142b815c7f3Sopenharmony_ci			for (j = 0, k = 0 ; j < numSamples ; j++, k += 2)
143b815c7f3Sopenharmony_ci			{
144b815c7f3Sopenharmony_ci				l = in [0] >> 8 ;
145b815c7f3Sopenharmony_ci				r = in [1] >> 8 ;
146b815c7f3Sopenharmony_ci				in += stride ;
147b815c7f3Sopenharmony_ci
148b815c7f3Sopenharmony_ci				shiftUV [k + 0] = (uint16_t) (l & mask) ;
149b815c7f3Sopenharmony_ci				shiftUV [k + 1] = (uint16_t) (r & mask) ;
150b815c7f3Sopenharmony_ci
151b815c7f3Sopenharmony_ci				l >>= shift ;
152b815c7f3Sopenharmony_ci				r >>= shift ;
153b815c7f3Sopenharmony_ci
154b815c7f3Sopenharmony_ci				u [j] = (mixres * l + m2 * r) >> mixbits ;
155b815c7f3Sopenharmony_ci				v [j] = l - r ;
156b815c7f3Sopenharmony_ci			}
157b815c7f3Sopenharmony_ci		}
158b815c7f3Sopenharmony_ci		else
159b815c7f3Sopenharmony_ci		{
160b815c7f3Sopenharmony_ci			for (j = 0 ; j < numSamples ; j++)
161b815c7f3Sopenharmony_ci			{
162b815c7f3Sopenharmony_ci				l = in [0] >> 8 ;
163b815c7f3Sopenharmony_ci				r = in [1] >> 8 ;
164b815c7f3Sopenharmony_ci				in += stride ;
165b815c7f3Sopenharmony_ci
166b815c7f3Sopenharmony_ci				u [j] = (mixres * l + m2 * r) >> mixbits ;
167b815c7f3Sopenharmony_ci				v [j] = l - r ;
168b815c7f3Sopenharmony_ci			}
169b815c7f3Sopenharmony_ci		}
170b815c7f3Sopenharmony_ci	}
171b815c7f3Sopenharmony_ci	else
172b815c7f3Sopenharmony_ci	{
173b815c7f3Sopenharmony_ci		/* Conventional separated stereo. */
174b815c7f3Sopenharmony_ci		if (bytesShifted != 0)
175b815c7f3Sopenharmony_ci		{
176b815c7f3Sopenharmony_ci			for (j = 0, k = 0 ; j < numSamples ; j++, k += 2)
177b815c7f3Sopenharmony_ci			{
178b815c7f3Sopenharmony_ci				l = in [0] >> 8 ;
179b815c7f3Sopenharmony_ci				r = in [1] >> 8 ;
180b815c7f3Sopenharmony_ci				in += stride ;
181b815c7f3Sopenharmony_ci
182b815c7f3Sopenharmony_ci				shiftUV [k + 0] = (uint16_t) (l & mask) ;
183b815c7f3Sopenharmony_ci				shiftUV [k + 1] = (uint16_t) (r & mask) ;
184b815c7f3Sopenharmony_ci
185b815c7f3Sopenharmony_ci				l >>= shift ;
186b815c7f3Sopenharmony_ci				r >>= shift ;
187b815c7f3Sopenharmony_ci
188b815c7f3Sopenharmony_ci				u [j] = l ;
189b815c7f3Sopenharmony_ci				v [j] = r ;
190b815c7f3Sopenharmony_ci			}
191b815c7f3Sopenharmony_ci		}
192b815c7f3Sopenharmony_ci		else
193b815c7f3Sopenharmony_ci		{
194b815c7f3Sopenharmony_ci			for (j = 0 ; j < numSamples ; j++)
195b815c7f3Sopenharmony_ci			{
196b815c7f3Sopenharmony_ci				l = in [0] >> 8 ;
197b815c7f3Sopenharmony_ci				r = in [1] >> 8 ;
198b815c7f3Sopenharmony_ci				in += stride ;
199b815c7f3Sopenharmony_ci			}
200b815c7f3Sopenharmony_ci		}
201b815c7f3Sopenharmony_ci	}
202b815c7f3Sopenharmony_ci}
203b815c7f3Sopenharmony_ci
204b815c7f3Sopenharmony_ci// 32-bit routines
205b815c7f3Sopenharmony_ci// - note that these really expect the internal data width to be < 32 but the arrays are 32-bit
206b815c7f3Sopenharmony_ci// - otherwise, the calculations might overflow into the 33rd bit and be lost
207b815c7f3Sopenharmony_ci// - therefore, these routines deal with the specified "unused lower" bytes in the "shift" buffers
208b815c7f3Sopenharmony_ci
209b815c7f3Sopenharmony_civoid
210b815c7f3Sopenharmony_cimix32 (const int32_t * in, uint32_t stride, int32_t * u, int32_t * v, int32_t numSamples,
211b815c7f3Sopenharmony_ci			int32_t mixbits, int32_t mixres, uint16_t * shiftUV, int32_t bytesShifted)
212b815c7f3Sopenharmony_ci{
213b815c7f3Sopenharmony_ci	int32_t		shift = bytesShifted * 8 ;
214b815c7f3Sopenharmony_ci	uint32_t	mask = (1ul << shift) - 1 ;
215b815c7f3Sopenharmony_ci	int32_t		l, r ;
216b815c7f3Sopenharmony_ci	int32_t		j, k ;
217b815c7f3Sopenharmony_ci
218b815c7f3Sopenharmony_ci	if (mixres != 0)
219b815c7f3Sopenharmony_ci	{
220b815c7f3Sopenharmony_ci		int32_t		mod = 1 << mixbits ;
221b815c7f3Sopenharmony_ci		int32_t		m2 ;
222b815c7f3Sopenharmony_ci
223b815c7f3Sopenharmony_ci		//Assert (bytesShifted != 0) ;
224b815c7f3Sopenharmony_ci
225b815c7f3Sopenharmony_ci		/* matrixed stereo with shift */
226b815c7f3Sopenharmony_ci		m2 = mod - mixres ;
227b815c7f3Sopenharmony_ci		for (j = 0, k = 0 ; j < numSamples ; j++, k += 2)
228b815c7f3Sopenharmony_ci		{
229b815c7f3Sopenharmony_ci			l = in [0] ;
230b815c7f3Sopenharmony_ci			r = in [1] ;
231b815c7f3Sopenharmony_ci			in += stride ;
232b815c7f3Sopenharmony_ci
233b815c7f3Sopenharmony_ci			shiftUV [k + 0] = (uint16_t) (l & mask) ;
234b815c7f3Sopenharmony_ci			shiftUV [k + 1] = (uint16_t) (r & mask) ;
235b815c7f3Sopenharmony_ci
236b815c7f3Sopenharmony_ci			l >>= shift ;
237b815c7f3Sopenharmony_ci			r >>= shift ;
238b815c7f3Sopenharmony_ci
239b815c7f3Sopenharmony_ci			u [j] = (mixres * l + m2 * r) >> mixbits ;
240b815c7f3Sopenharmony_ci			v [j] = l - r ;
241b815c7f3Sopenharmony_ci		}
242b815c7f3Sopenharmony_ci	}
243b815c7f3Sopenharmony_ci	else
244b815c7f3Sopenharmony_ci	{
245b815c7f3Sopenharmony_ci		if (bytesShifted == 0)
246b815c7f3Sopenharmony_ci		{
247b815c7f3Sopenharmony_ci			/* de-interleaving w/o shift */
248b815c7f3Sopenharmony_ci			for (j = 0 ; j < numSamples ; j++)
249b815c7f3Sopenharmony_ci			{
250b815c7f3Sopenharmony_ci				u [j] = in [0] ;
251b815c7f3Sopenharmony_ci				v [j] = in [1] ;
252b815c7f3Sopenharmony_ci				in += stride ;
253b815c7f3Sopenharmony_ci			}
254b815c7f3Sopenharmony_ci		}
255b815c7f3Sopenharmony_ci		else
256b815c7f3Sopenharmony_ci		{
257b815c7f3Sopenharmony_ci			/* de-interleaving with shift */
258b815c7f3Sopenharmony_ci			for (j = 0, k = 0 ; j < numSamples ; j++, k += 2)
259b815c7f3Sopenharmony_ci			{
260b815c7f3Sopenharmony_ci				l = in [0] ;
261b815c7f3Sopenharmony_ci				r = in [1] ;
262b815c7f3Sopenharmony_ci				in += stride ;
263b815c7f3Sopenharmony_ci
264b815c7f3Sopenharmony_ci				shiftUV [k + 0] = (uint16_t) (l & mask) ;
265b815c7f3Sopenharmony_ci				shiftUV [k + 1] = (uint16_t) (r & mask) ;
266b815c7f3Sopenharmony_ci
267b815c7f3Sopenharmony_ci				l >>= shift ;
268b815c7f3Sopenharmony_ci				r >>= shift ;
269b815c7f3Sopenharmony_ci
270b815c7f3Sopenharmony_ci				u [j] = l ;
271b815c7f3Sopenharmony_ci				v [j] = r ;
272b815c7f3Sopenharmony_ci			}
273b815c7f3Sopenharmony_ci		}
274b815c7f3Sopenharmony_ci	}
275b815c7f3Sopenharmony_ci}
276