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