12228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
22228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* -----------------------------------------------------------------------------------------------------------
32228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectSoftware License for The Fraunhofer FDK AAC Codec Library for Android
42228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
54f0d97057c5c640b25518358886f8c47da9fc052Jean-Michel Trivi� Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
62228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  All rights reserved.
72228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
82228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project 1.    INTRODUCTION
92228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThe Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectthe MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
112228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThis FDK AAC Codec software is intended to be used on a wide variety of Android devices.
122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
132228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectAAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectaudio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectindependent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectof the MPEG specifications.
172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
182228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPatent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectmay be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectindividually for the purpose of encoding or decoding bit streams in products that are compliant with
212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectthe ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectthese patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectsoftware may already be covered under those patent licenses when it is used for those licensed purposes only.
242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
252228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectCommercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectare also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectapplications information and documentation.
282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project2.    COPYRIGHT LICENSE
302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
312228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectRedistribution and use in source and binary forms, with or without modification, are permitted without
322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectpayment of copyright license fees provided that you satisfy the following conditions:
332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
342228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou must retain the complete text of this software license in redistributions of the FDK AAC Codec or
352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectyour modifications thereto in source code form.
362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
372228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou must retain the complete text of this software license in the documentation and/or other materials
382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectprovided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
392228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou must make available free of charge copies of the complete source code of the FDK AAC Codec and your
402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectmodifications thereto to recipients of copies in binary form.
412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
422228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThe name of Fraunhofer may not be used to endorse or promote products derived from this library without
432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectprior written permission.
442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
452228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectsoftware or your modifications thereto.
472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
482228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYour modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectand the date of any change. For modified versions of the FDK AAC Codec, the term
502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project3.    NO PATENT LICENSE
542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
552228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectNO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
562228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectrespect to this software.
582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
592228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectYou may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectby appropriate patent licenses.
612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project4.    DISCLAIMER
632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
642228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectThis FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectof merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
672228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectCONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectincluding but not limited to procurement of substitute goods or services; loss of use, data, or profits,
692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projector business interruption, however caused and on any theory of liability, whether in contract, strict
702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectliability, or tort (including negligence), arising in any way out of the use of this software, even if
712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectadvised of the possibility of such damage.
722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project5.    CONTACT INFORMATION
742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
752228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectFraunhofer Institute for Integrated Circuits IIS
762228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectAttention: Audio and Multimedia Departments - FDK AAC LL
772228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectAm Wolfsmantel 33
782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project91058 Erlangen, Germany
792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectwww.iis.fraunhofer.de/amm
812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectamm-info@iis.fraunhofer.de
822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project----------------------------------------------------------------------------------------------------------- */
832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/****************************  FDK PCM utils module  **************************
852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project   Author(s):   Christian Griebel
8747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi   Description: Defines functions that perform downmixing or a simple channel
8847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                expansion in the PCM time domain.
892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project*******************************************************************************/
912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "pcmutils_lib.h"
932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "genericStds.h"
952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#include "fixpoint_math.h"
9647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#include "FDK_core.h"
9747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
9847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
9947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* ------------------------ *
10047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  GLOBAL SETTINGS (GFR):  *
10147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * ------------------------ */
10247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define DSE_METADATA_ENABLE          /*!< Enable this to support MPEG/ETSI DVB ancillary data for
10347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                          encoder assisted downmixing of MPEG-4 AAC and
10447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                          MPEG-1/2 layer 2 streams.                             */
10547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCE_METADATA_ENABLE          /*!< Enable this to support MPEG matrix mixdown with a
10647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                          coefficient carried in the PCE.                       */
10747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
10847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCM_DMX_MAX_IN_CHANNELS          ( 8 )   /* Neither the maximum number of input nor the maximum number of output channels ... */
10947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCM_DMX_MAX_OUT_CHANNELS         ( 8 )   /* ... must exceed the maximum number of channels that the framework can handle. */
11047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
11147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* ------------------------ *
11247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *    SPECIFIC SETTINGS:    *
11347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * ------------------------ */
11447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCM_CHANNEL_EXTENSION_ENABLE             /*!< Allow module to duplicate mono signals or add zero channels to achieve the
11547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                                      desired number of output channels. */
11647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
11747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCM_DMX_DFLT_MAX_OUT_CHANNELS    ( 6 )   /*!< The maximum number of output channels. If the value is greater than 0 the module
11847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                                      will automatically create a mixdown for all input signals with more channels
11947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                                      than specified. */
12047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCM_DMX_DFLT_MIN_OUT_CHANNELS    ( 0 )   /*!< The minimum number of output channels. If the value is greater than 0 the module
12147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                                      will do channel extension automatically for all input signals with less channels
12247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                                      than specified. */
12347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCM_DMX_MAX_DELAY_FRAMES         ( 1 )   /*!< The maximum delay frames to align the bitstreams payload with the PCM output. */
12447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCM_DMX_DFLT_EXPIRY_FRAME        ( 50 )  /*!< If value is greater than 0 the mixdown coefficients will expire by default after the
12547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                                      given number of frames. The value 50 corresponds to at least 500ms (FL 960 @ 96kHz) */
12647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* #define PCMDMX_DEBUG */
12747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
12847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* Derived setting:
12947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *   No need to edit beyond this line. */
13047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if defined(DSE_METADATA_ENABLE) || defined(PCE_METADATA_ENABLE) || defined(ARIB_MIXDOWN_ENABLE)
13147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DOWNMIX_ENABLE                      /*!< Generally enable down mixing.                         */
13247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
13347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_IN_CHANNELS > 2) || (PCM_DMX_MAX_OUT_CHANNELS > 2)
13447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_CHANNELS            ( 8 )
13547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_CHANNEL_GROUPS      ( 4 )
13647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_CHANNELS_PER_GROUP  PCM_DMX_MAX_CHANNELS   /* All channels can be in one group */
13747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#else
13847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_CHANNELS            ( 3 )   /* Need to add 1 because there are three channel positions in first channel group. */
13947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_CHANNEL_GROUPS      ( 1 )   /* Only front channels supported. */
14047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_CHANNELS_PER_GROUP  ( 2 )   /* The maximum over all channel groups */
14147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
14247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_IN_CHANNELS > PCM_DMX_MAX_OUT_CHANNELS)
14347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_IO_CHANNELS  PCM_DMX_MAX_IN_CHANNELS
14447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#else
14547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define PCM_DMX_MAX_IO_CHANNELS  PCM_DMX_MAX_OUT_CHANNELS
14647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
1472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* Decoder library info */
1492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define PCMDMX_LIB_VL0 2
1504f0d97057c5c640b25518358886f8c47da9fc052Jean-Michel Trivi#define PCMDMX_LIB_VL1 4
151603f48ab99ce76f552f4f6f85d06b8c5b94c698eJean-Michel Trivi#define PCMDMX_LIB_VL2 2
1522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define PCMDMX_LIB_TITLE "PCM Downmix Lib"
1532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define PCMDMX_LIB_BUILD_DATE __DATE__
1542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define PCMDMX_LIB_BUILD_TIME __TIME__
1552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* Fixed and unique channel group indices.
1582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * The last group index has to be smaller than PCM_DMX_MAX_CHANNEL_GROUPS. */
1592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define CH_GROUP_FRONT ( 0 )
1602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define CH_GROUP_SIDE  ( 1 )
1612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define CH_GROUP_REAR  ( 2 )
1622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define CH_GROUP_LFE   ( 3 )
1632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* The ordering of the following fixed channel labels has to be in MPEG-4 style.
1652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * From the center to the back with left and right channel interleaved (starting with left).
1662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * The last channel label index has to be smaller than PCM_DMX_MAX_CHANNELS. */
1672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define CENTER_FRONT_CHANNEL    ( 0 )     /* C  */
1682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define LEFT_FRONT_CHANNEL      ( 1 )     /* L  */
1692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define RIGHT_FRONT_CHANNEL     ( 2 )     /* R  */
17047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define LEFT_REAR_CHANNEL       ( 3 )     /* Lr (aka left back channel) or center back channel */
17147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define RIGHT_REAR_CHANNEL      ( 4 )     /* Rr (aka right back channel) */
17247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define LOW_FREQUENCY_CHANNEL   ( 5 )     /* Lf */
17347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define LEFT_MULTIPRPS_CHANNEL  ( 6 )     /* Left multipurpose channel */
17447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define RIGHT_MULTIPRPS_CHANNEL ( 7 )     /* Right multipurpose channel */
1752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
1762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* More constants */
17747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define ONE_CHANNEL             ( 1 )
1782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#define TWO_CHANNEL             ( 2 )
17947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define SIX_CHANNEL             ( 6 )
18047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define EIGHT_CHANNEL           ( 8 )
18147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
18247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCMDMX_A_IDX_DEFAULT    ( 2 )
18347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCMDMX_B_IDX_DEFAULT    ( 2 )
18447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCMDMX_LFE_IDX_DEFAULT  ( 15 )
18547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCMDMX_GAIN_5_DEFAULT   ( 0 )
18647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCMDMX_GAIN_2_DEFAULT   ( 0 )
18747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
18847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define PCMDMX_MAX_HEADROOM     ( 3 )     /* Defines the maximum PCM scaling headroom that can be done by a
18947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                             postprocessing step. This value must be greater or equal to 0. */
19047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
19147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define FALSE  0
19247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define TRUE   1
19347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define IN     0
19447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define OUT    1
19547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
19647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* Type definitions: */
19747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifndef DMX_HIGH_PRECISION_ENABLE
19847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FIXP_DMX          FIXP_SGL
19947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DMX2FX_DBL(x)  FX_SGL2FX_DBL((FIXP_SGL)(x))
20047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DBL2FX_DMX(x)  FX_DBL2FX_SGL(x)
20147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FL2FXCONST_DMX(x) FL2FXCONST_SGL(x)
20247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define MAXVAL_DMX        MAXVAL_SGL
20347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DMX2SHRT(x)    ((SHORT)(x))
20447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DMX2FL(x)      FX_DBL2FL(FX_DMX2FX_DBL(x))
20547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#else
20647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FIXP_DMX          FIXP_DBL
20747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DMX2FX_DBL(x)  ((FIXP_DBL)(x))
20847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DBL2FX_DMX(x)  ((FIXP_DBL)(x)
20947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FL2FXCONST_DMX(x) FL2FXCONST_DBL(x)
21047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define MAXVAL_DMX        MAXVAL_DBL
21147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DMX2SHRT(x)    ((SHORT)((x)>>FRACT_BITS))
21247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #define FX_DMX2FL(x)      FX_DBL2FL(x)
21347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
2142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* The number of channels positions for each group in the internal representation.
21647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * See the channel labels above. */
21747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic const UCHAR maxChInGrp[PCM_DMX_MAX_CHANNEL_GROUPS] = {
21847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNELS > 3)
21947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  3, 0, 2, 1
22047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#else
22147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCM_DMX_MAX_CHANNELS_PER_GROUP
22247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
22347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi};
2242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* List of packed channel modes */
2262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projecttypedef enum
22747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{ /* CH_MODE_<numFrontCh>_<numSideCh>_<numBackCh>_<numLfCh> */
2282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_UNDEFINED = 0x0000,
2292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 1 channel */
2302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_1_0_0_0   = 0x0001,   /* chCfg 1 */
2312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 2 channels */
2322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_0_0_0   = 0x0002,   /* chCfg 2 */
2332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 3 channels */
2342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_0_0_0   = 0x0003,   /* chCfg 3 */
2352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_0_1_0   = 0x0102,
2362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_0_0_1   = 0x1002,
2372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 4 channels */
2382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_0_1_0   = 0x0103,   /* chCfg 4 */
2392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_0_2_0   = 0x0202,
2402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_0_1_1   = 0x1102,
24147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_4_0_0_0   = 0x0004,
2422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 5 channels */
2432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_0_2_0   = 0x0203,   /* chCfg 5 */
2442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_0_2_1   = 0x1202,
2452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_0_1_1   = 0x1103,
2462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_2_0_0   = 0x0023,
24747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_5_0_0_0   = 0x0005,
2482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 6 channels */
2492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_0_2_1   = 0x1203,   /* chCfg 6 */
25047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_2_0_1   = 0x1023,
2512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_2_1_0   = 0x0123,
25247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_5_0_1_0   = 0x0105,
25347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_6_0_0_0   = 0x0006,
2542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 7 channels */
2552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_2_2_1   = 0x1222,
25647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_0_3_1   = 0x1303,   /* chCfg 11 */
2572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_2_1_1   = 0x1123,
2582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_2_2_0   = 0x0223,
25947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_0_2_2   = 0x2203,
26047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_5_0_2_0   = 0x0205,
26147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_5_0_1_1   = 0x1105,
26247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_7_0_0_0   = 0x0007,
2632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* 8 channels */
26447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_2_2_1   = 0x1223,
26547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_0_4_1   = 0x1403,   /* chCfg 12 */
26647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_5_0_2_1   = 0x1205,   /* chCfg 7 + 14 */
26747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_5_2_1_0   = 0x0125,
2682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_2_1_2   = 0x2123,
26947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_2_2_2_2   = 0x2222,
27047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_0_3_2   = 0x2303,
27147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_8_0_0_0   = 0x0008
2722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project} PCM_DMX_CHANNEL_MODE;
2742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* These are the channel configurations linked to
2772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project   the number of output channels give by the user: */
27847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic const PCM_DMX_CHANNEL_MODE outChModeTable[PCM_DMX_MAX_CHANNELS+1] =
2792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
28047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_UNDEFINED,
2812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_1_0_0_0,  /* 1 channel  */
2822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_2_0_0_0,  /* 2 channels */
28347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_0_0_0   /* 3 channels */
28447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNELS > 3)
28547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi ,CH_MODE_3_0_1_0,  /* 4 channels */
2862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_0_2_0,  /* 5 channels */
2872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  CH_MODE_3_0_2_1,  /* 6 channels */
28847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_0_3_1,  /* 7 channels */
28947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  CH_MODE_3_0_4_1   /* 8 channels */
29047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
2912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project};
2922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
29347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic const FIXP_DMX abMixLvlValueTab[8] =
2942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
29547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.500f),   /* scaled by 1 */
29647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.841f),
29747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.707f),
29847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.596f),
29947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.500f),
30047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.422f),
30147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.355f),
30247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.0f)
30347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi};
30447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
30547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic const FIXP_DMX lfeMixLvlValueTab[16] =
30647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{ /*             value,        scale */
30747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.7905f),  /*     2 */
30847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.5000f),  /*     2 */
30947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.8395f),  /*     1 */
31047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.7065f),  /*     1 */
31147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.5945f),  /*     1 */
31247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.500f),   /*     1 */
31347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.841f),   /*     0 */
31447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.707f),   /*     0 */
31547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.596f),   /*     0 */
31647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.500f),   /*     0 */
31747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.316f),   /*     0 */
31847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.178f),   /*     0 */
31947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.100f),   /*     0 */
32047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.032f),   /*     0 */
32147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.010f),   /*     0 */
32247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FL2FXCONST_DMX(0.000f)    /*     0 */
3232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project};
3242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
32647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
32747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCE_METADATA_ENABLE
3282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* MPEG matrix mixdown:
3292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Set 1:  L' = (1 + 2^-0.5 + A )^-1 * [L + C * 2^-0.5 + A * Ls];
3302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              R' = (1 + 2^-0.5 + A )^-1 * [R + C * 2^-0.5 + A * Rs];
3312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      Set 2:  L' = (1 + 2^-0.5 + 2A )^-1 * [L + C * 2^-0.5 - A * (Ls + Rs)];
3332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              R' = (1 + 2^-0.5 + 2A )^-1 * [R + C * 2^-0.5 + A * (Ls + Rs)];
3342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      M = (3 + 2A)^-1 * [L + C + R + A*(Ls + Rs)];
3362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  */
33747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  static const FIXP_DMX mpegMixDownIdx2Coef[4] =
3382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
33947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.70710678f),
34047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.5f),
34147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.35355339f),
34247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.0f)
3432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  };
3442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
34547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  static const FIXP_SGL mpegMixDownIdx2PreFact[3][4] =
34647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  { {  /* Set 1: */
34747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.4142135623730950f),
34847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.4530818393219728f),
34947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.4852813742385703f),
35047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.5857864376269050f)
35147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  },{  /* Set 2: */
35247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.3203772410170407f),
35347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.3693980625181293f),
35447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.4142135623730950f),
35547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.5857864376269050f)
35647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  },{  /* Mono DMX set: */
35747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.2265409196609864f),
35847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.25f),
35947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.2697521433898179f),
36047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FL2FXCONST_DMX(0.3333333333333333f) }
3612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  };
36247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif  /* PCE_METADATA_ENABLE */
3632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
36547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define TYPE_NONE      ( 0x0 )
36647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define TYPE_DSE_DATA  ( 0x1 )
36747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define TYPE_PCE_DATA  ( 0x2 )
3682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
3692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projecttypedef struct
3702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
37147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UINT   typeFlags;
37247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* From DSE */
37347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  cLevIdx;
37447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  sLevIdx;
37547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  dmixIdxA;
37647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  dmixIdxB;
37747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  dmixIdxLfe;
37847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  dmxGainIdx2;
37947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  dmxGainIdx5;
38047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCE_METADATA_ENABLE
38147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* From PCE */
38247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  matrixMixdownIdx;
38347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
38447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Attributes: */
38547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  SCHAR  pseudoSurround;               /*!< If set to 1 the signal is pseudo surround compatible. The value 0 tells
38647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                            that it is not. If the value is -1 the information is not available.  */
38747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UINT   expiryCount;                  /*!< Counter to monitor the life time of a meta data set. */
38847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
38947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi} DMX_BS_META_DATA;
39047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
39147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* Default metadata */
39247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic const DMX_BS_META_DATA  dfltMetaData = {
39347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  0, 2, 2, 2, 2, 15, 0, 0,
39447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCE_METADATA_ENABLE
39547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  0,
39647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
39747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  -1, 0
39847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi};
3992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
40047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/* Dynamic (user) params:
40147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi     See the definition of PCMDMX_PARAM for details on the specific fields. */
40247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivitypedef struct
40347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
40447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UINT   expiryFrame;                   /*!< Linked to DMX_BS_DATA_EXPIRY_FRAME       */
40547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  DUAL_CHANNEL_MODE dualChannelMode;    /*!< Linked to DMX_DUAL_CHANNEL_MODE          */
40647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PSEUDO_SURROUND_MODE pseudoSurrMode;  /*!< Linked to DMX_PSEUDO_SURROUND_MODE       */
40747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  SHORT  numOutChannelsMin;             /*!< Linked to MIN_NUMBER_OF_OUTPUT_CHANNELS  */
40847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  SHORT  numOutChannelsMax;             /*!< Linked to MAX_NUMBER_OF_OUTPUT_CHANNELS  */
40947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  frameDelay;                    /*!< Linked to DMX_BS_DATA_DELAY              */
4102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
41147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi} PCM_DMX_USER_PARAMS;
4122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* Modules main data structure: */
4142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectstruct PCM_DMX_INSTANCE
4152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
41647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Metadata */
41747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  DMX_BS_META_DATA     bsMetaData[PCM_DMX_MAX_DELAY_FRAMES+1];
41847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCM_DMX_USER_PARAMS  userParams;
41947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
42047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR  applyProcessing;              /*!< Flag to en-/disable modules processing.
42147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                            The max channel limiting is done independently. */
4222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project};
4232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/* Memory allocation macro */
4252228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectC_ALLOC_MEM_STATIC(PcmDmxInstance, struct PCM_DMX_INSTANCE, 1)
4262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
42847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/** Evaluate a given channel configuration and extract a packed channel mode. In addition the
42947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  function generates a channel offset table for the mapping to the internal representation.
4302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project *  This function is the inverse to the getChannelDescription() routine.
4312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] The total number of channels of the given configuration.
4322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Array holding the corresponding channel types for each channel.
4332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Array holding the corresponding channel type indices for each channel.
4342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [out] Array where the buffer offsets for each channel are stored into.
43547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [out] The generated packed channel mode that represents the given input configuration.
43647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @returns Returns an error code.
4372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
4382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectstatic
43947c680c62246594107da0a8995c953dfb8040bceJean-Michel TriviPCMDMX_ERROR getChannelMode (
4402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        const INT                numChannels,                           /* in */
4412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        const AUDIO_CHANNEL_TYPE channelType[],                         /* in */
4422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        const UCHAR              channelIndices[],                      /* in */
44347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        UCHAR                    offsetTable[PCM_DMX_MAX_CHANNELS],     /* out */
44447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        PCM_DMX_CHANNEL_MODE    *chMode                                 /* out */
4452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      )
4462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
4472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR chIdx[PCM_DMX_MAX_CHANNEL_GROUPS][PCM_DMX_MAX_CHANNELS_PER_GROUP];
44847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR numChInGrp[PCM_DMX_MAX_CHANNEL_GROUPS]; /* Total num of channels per group of the input config */
44947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR numChFree[PCM_DMX_MAX_CHANNEL_GROUPS];  /* Number of free slots per group in the internal repr. */
45047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR hardToPlace[PCM_DMX_MAX_CHANNELS];      /* List of channels not matching the internal repr. */
45147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UCHAR h2pSortIdx[PCM_DMX_MAX_CHANNELS];
45247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCMDMX_ERROR err = PCMDMX_OK;
45347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   ch, grpIdx;
45447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   numChToPlace = 0;
4552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(channelType != NULL);
4572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(channelIndices != NULL);
4582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(offsetTable != NULL);
45947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_ASSERT(chMode != NULL);
4602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* For details see ISO/IEC 13818-7:2005(E), 8.5.3 Channel configuration */
4622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDKmemclear(numChInGrp, PCM_DMX_MAX_CHANNEL_GROUPS*sizeof(UCHAR));
4632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDKmemset(offsetTable, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR));
4646ab36997af5d5acda4f21d33031f4e45c85f96b7Jean-Michel Trivi  FDKmemset(chIdx, 255, PCM_DMX_MAX_CHANNEL_GROUPS*PCM_DMX_MAX_CHANNELS_PER_GROUP*sizeof(UCHAR));
46547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemset(hardToPlace, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR));
46647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemset(h2pSortIdx, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR));
46747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Get the restrictions of the internal representation */
46847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemcpy(numChFree, maxChInGrp, PCM_DMX_MAX_CHANNEL_GROUPS*sizeof(UCHAR));
46947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
47047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  *chMode = CH_MODE_UNDEFINED;
4712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Categorize channels */
4732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (ch = 0; ch < numChannels; ch += 1) {
47447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UCHAR chGrpIdx = channelIndices[ch];
47547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int i = 0, j;
4762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
4772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    switch (channelType[ch]) {
4782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case ACT_FRONT_TOP:
47947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      chGrpIdx += numChInGrp[CH_GROUP_FRONT];  /* Append after normal plain */
48047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case ACT_FRONT:
4812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      grpIdx = CH_GROUP_FRONT;
4822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
48347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1)
4842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case ACT_SIDE_TOP:
48547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      chGrpIdx += numChInGrp[CH_GROUP_SIDE];   /* Append after normal plain */
48647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case ACT_SIDE:
4872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      grpIdx = CH_GROUP_SIDE;
4882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
4892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case ACT_BACK_TOP:
49047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      chGrpIdx += numChInGrp[CH_GROUP_REAR];   /* Append after normal plain */
49147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case ACT_BACK:
4922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      grpIdx = CH_GROUP_REAR;
4932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
4942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case ACT_LFE:
4952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      grpIdx = CH_GROUP_LFE;
4962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
49747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
4982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    default:
49947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Found a channel that can not be categorized! Most likely due to corrupt input signalling.
50047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         The rescue strategy is to append it to the front channels (=> ignore index).
50147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         This could cause strange behaviour so return an error to signal it. */
50247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      err = PCMDMX_INVALID_MODE;
50347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      grpIdx = CH_GROUP_FRONT;
50447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      chGrpIdx = numChannels + numChToPlace;
50547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      numChToPlace += 1;
50647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
5072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
5082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (numChInGrp[grpIdx] < PCM_DMX_MAX_CHANNELS_PER_GROUP) {
5102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Sort channels by index */
5112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      while ( (i < numChInGrp[grpIdx]) && (chGrpIdx > channelIndices[chIdx[grpIdx][i]]) ) {
5122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        i += 1;
5132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
5142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (j = numChInGrp[grpIdx]; j > i; j -= 1) {
5152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        chIdx[grpIdx][j] = chIdx[grpIdx][j-1];
5162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
5172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chIdx[grpIdx][i] = ch;
5182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      numChInGrp[grpIdx] += 1;
5192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
5202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
5212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
52247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1)
52347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_ASSERT( (numChInGrp[CH_GROUP_FRONT]+numChInGrp[CH_GROUP_SIDE]
52447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              +numChInGrp[CH_GROUP_REAR]+numChInGrp[CH_GROUP_LFE]) == numChannels);
52547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#else
52647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_ASSERT( numChInGrp[CH_GROUP_FRONT] == numChannels );
52747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
52847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
52947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Compose channel offset table:
53047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi   * Map all channels to the internal representation. */
53147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  numChToPlace = 0;
5322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Non-symmetric channels */
5342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (numChInGrp[CH_GROUP_FRONT] & 0x1) {
5352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Odd number of front channels -> we have a center channel.
5362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       In MPEG-4 the center has the index 0. */
5376ab36997af5d5acda4f21d33031f4e45c85f96b7Jean-Michel Trivi    offsetTable[CENTER_FRONT_CHANNEL] = chIdx[CH_GROUP_FRONT][0];
53847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    numChFree[CH_GROUP_FRONT] -= 1;
5392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
5402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (grpIdx = 0; grpIdx < PCM_DMX_MAX_CHANNEL_GROUPS; grpIdx += 1) {
54247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int chMapPos = 0;
54347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    ch = 0;  /* Index of channel within the specific group */
5442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
5452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    switch (grpIdx) {
5462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_FRONT:
5472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chMapPos = LEFT_FRONT_CHANNEL;
5482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      ch = numChInGrp[grpIdx] & 0x1;
5492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
55047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1)
5512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_SIDE:
5522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
5532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_REAR:
5542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chMapPos = LEFT_REAR_CHANNEL;
5552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
5562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_LFE:
5572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chMapPos = LOW_FREQUENCY_CHANNEL;
5582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
55947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
5602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    default:
56147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDK_ASSERT(0);
5622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      continue;
5632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
5642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
56547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Map all channels of the group */
5662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for ( ; ch < numChInGrp[grpIdx]; ch += 1) {
56747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (numChFree[grpIdx] > 0) {
5686ab36997af5d5acda4f21d33031f4e45c85f96b7Jean-Michel Trivi        offsetTable[chMapPos] = chIdx[grpIdx][ch];
5692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        chMapPos += 1;
57047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        numChFree[grpIdx] -= 1;
5712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      } else {
57247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Add to the list of hardship cases considering a MPEG-like sorting order: */
57347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        int pos, sortIdx = grpIdx*PCM_DMX_MAX_CHANNELS_PER_GROUP + channelIndices[chIdx[grpIdx][ch]];
57447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (pos = numChToPlace; pos > 0; pos -= 1) {
57547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (h2pSortIdx[pos-1] > sortIdx) {
57647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            hardToPlace[pos] = hardToPlace[pos-1];
57747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            h2pSortIdx[pos] = h2pSortIdx[pos-1];
57847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          } else {
57947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            /* Insert channel at the current index/position */
58047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            break;
58147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
58247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
58347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        hardToPlace[pos] = chIdx[grpIdx][ch];
58447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        h2pSortIdx[pos] = sortIdx;
58547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        numChToPlace += 1;
5862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
5872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
5882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
5892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
59047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  { /* Assign the hardship cases */
59147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int chMapPos = 0;
59247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int mappingHeat = 0;
59347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    for (ch = 0; ch < numChToPlace; ch+=1) {
59447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      int chAssigned = 0;
59547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
59647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Just assigning the channels to the next best slot can lead to undesired results (especially for x/x/1.x
59747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         configurations). Thus use the MPEG-like sorting index to find the best fitting slot for each channel.
59847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         If this is not possible the sorting index will be ignored (mappingHeat >= 2). */
59947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for ( ; chMapPos < PCM_DMX_MAX_CHANNELS; chMapPos+=1) {
60047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (offsetTable[chMapPos] == 255) {
60147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          int prvSortIdx = 0;
60247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          int nxtSortIdx = (CH_GROUP_LFE+1)*PCM_DMX_MAX_CHANNELS_PER_GROUP;
60347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
60447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (mappingHeat < 2) {
60547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            if (chMapPos < LEFT_REAR_CHANNEL) {
60647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              /* Got front channel slot */
60747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              prvSortIdx = CH_GROUP_FRONT*PCM_DMX_MAX_CHANNELS_PER_GROUP + chMapPos - CENTER_FRONT_CHANNEL;
60847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              nxtSortIdx = CH_GROUP_SIDE *PCM_DMX_MAX_CHANNELS_PER_GROUP;
60947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            }
61047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            else if (chMapPos < LOW_FREQUENCY_CHANNEL) {
61147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              /* Got back channel slot */
61247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              prvSortIdx = CH_GROUP_REAR*PCM_DMX_MAX_CHANNELS_PER_GROUP + chMapPos - LEFT_REAR_CHANNEL;
61347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              nxtSortIdx = CH_GROUP_LFE *PCM_DMX_MAX_CHANNELS_PER_GROUP;
61447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            }
61547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            else if (chMapPos < LEFT_MULTIPRPS_CHANNEL) {
61647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              /* Got lfe channel slot */
61747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              prvSortIdx =  CH_GROUP_LFE   *PCM_DMX_MAX_CHANNELS_PER_GROUP + chMapPos - LOW_FREQUENCY_CHANNEL;
61847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              nxtSortIdx = (CH_GROUP_LFE+1)*PCM_DMX_MAX_CHANNELS_PER_GROUP;
61947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            }
62047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
62147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
62247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          /* Assign the channel only if its sort index is within the range */
62347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if ( (h2pSortIdx[ch] >= prvSortIdx)
62447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            && (h2pSortIdx[ch] <  nxtSortIdx) ) {
62547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            offsetTable[chMapPos++] = hardToPlace[ch];
62647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            chAssigned = 1;
62747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            break;
62847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
62947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
63047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
63147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (chAssigned == 0) {
63247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chMapPos = 0;
63347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        ch -= 1;
63447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        mappingHeat += 1;
63547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        continue;
63647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
63747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
6382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
6392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
64047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Compose the channel mode */
64147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  *chMode = (PCM_DMX_CHANNEL_MODE)( (numChInGrp[CH_GROUP_FRONT] & 0xF)
64247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1)
64347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                  | (numChInGrp[CH_GROUP_SIDE]  & 0xF) <<  4
64447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                  | (numChInGrp[CH_GROUP_REAR]  & 0xF) <<  8
64547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                  | (numChInGrp[CH_GROUP_LFE]   & 0xF) << 12
64647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
64747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                  );
64847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
64947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  return err;
6502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
6512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Generate a channel offset table and complete channel description for a given (packed) channel mode.
65447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  This function is the inverse to the getChannelMode() routine but does not support weird channel
65547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  configurations. All channels have to be in the normal height layer and there must not be more
65647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  channels in each group than given by maxChInGrp.
65747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in] The packed channel mode of the configuration to be processed.
6582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Array containing the channel mapping to be used (From MPEG PCE ordering to whatever is required).
6592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [out] Array where corresponding channel types for each channels are stored into.
6602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [out] Array where corresponding channel type indices for each output channel are stored into.
6612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [out] Array where the buffer offsets for each channel are stored into.
6622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns None.
6632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
66447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic
6652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Projectvoid getChannelDescription (
6662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        const PCM_DMX_CHANNEL_MODE  chMode,                                 /* in */
66747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const UCHAR                 channelMapping[][8],                    /* in */
6682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        AUDIO_CHANNEL_TYPE          channelType[],                          /* out */
6692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        UCHAR                       channelIndices[],                       /* out */
6702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        UCHAR                       offsetTable[PCM_DMX_MAX_CHANNELS]       /* out */
6712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      )
6722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
6732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  const UCHAR *pChannelMap;
6742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int   grpIdx, ch = 0, numChannels = 0;
6752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR numChInGrp[PCM_DMX_MAX_CHANNEL_GROUPS];
6762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(channelType != NULL);
6782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(channelIndices != NULL);
6792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(channelMapping != NULL);
6802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDK_ASSERT(offsetTable != NULL);
6812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Init output arrays */
68347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemclear(channelType,    PCM_DMX_MAX_IO_CHANNELS*sizeof(AUDIO_CHANNEL_TYPE));
68447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemclear(channelIndices, PCM_DMX_MAX_IO_CHANNELS*sizeof(UCHAR));
6852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FDKmemset(offsetTable, 255, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR));
6862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Extract the number of channels per group */
6882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  numChInGrp[CH_GROUP_FRONT] =  chMode        & 0xF;
68947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1)
6902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  numChInGrp[CH_GROUP_SIDE]  = (chMode >>  4) & 0xF;
6912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  numChInGrp[CH_GROUP_REAR]  = (chMode >>  8) & 0xF;
6922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  numChInGrp[CH_GROUP_LFE]   = (chMode >> 12) & 0xF;
69347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
6942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
6952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Summerize to get the total number of channels */
6962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (grpIdx = 0; grpIdx < PCM_DMX_MAX_CHANNEL_GROUPS; grpIdx += 1) {
6972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    numChannels += numChInGrp[grpIdx];
6982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
6992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Get the appropriate channel map */
70147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  switch (chMode) {
70247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_1_0_0_0:
70347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_2_0_0_0:
70447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_3_0_0_0:
70547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_3_0_1_0:
70647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_3_0_2_0:
70747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_3_0_2_1:
70847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pChannelMap = channelMapping[numChannels];
70947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
71047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_3_0_3_1:
71147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pChannelMap = channelMapping[11];
71247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
71347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_3_0_4_1:
71447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pChannelMap = channelMapping[12];
71547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
71647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case CH_MODE_5_0_2_1:
71747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pChannelMap = channelMapping[7];
71847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
71947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  default:
72047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* fallback */
72147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pChannelMap = channelMapping[0];
72247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
72347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
7242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Compose channel offset table */
7262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Non-symmetric channels */
7282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (numChInGrp[CH_GROUP_FRONT] & 0x1) {
7292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Odd number of front channels -> we have a center channel.
7302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       In MPEG-4 the center has the index 0. */
73147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int mappedIdx = pChannelMap[ch];
73247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    offsetTable[CENTER_FRONT_CHANNEL] = mappedIdx;
73347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    channelType[mappedIdx]    = ACT_FRONT;
73447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    channelIndices[mappedIdx] = 0;
7352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    ch += 1;
7362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
7372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (grpIdx = 0; grpIdx < PCM_DMX_MAX_CHANNEL_GROUPS; grpIdx += 1) {
73947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    AUDIO_CHANNEL_TYPE type = ACT_NONE;
74047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int chMapPos = 0, maxChannels = 0;
74147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int chIdx = 0;  /* Index of channel within the specific group */
7422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
7432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    switch (grpIdx) {
7442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_FRONT:
7452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      type = ACT_FRONT;
7462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chMapPos = LEFT_FRONT_CHANNEL;
7472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxChannels = 3;
7482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chIdx = numChInGrp[grpIdx] & 0x1;
7492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
75047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNEL_GROUPS > 1)
7512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_SIDE:
75247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Always map side channels to the multipurpose group. */
7532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      type = ACT_SIDE;
75447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      chMapPos = LEFT_MULTIPRPS_CHANNEL;
7552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
7562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_REAR:
7572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      type = ACT_BACK;
7582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chMapPos = LEFT_REAR_CHANNEL;
7592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxChannels = 2;
7602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
7612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH_GROUP_LFE:
7622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      type = ACT_LFE;
7632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chMapPos = LOW_FREQUENCY_CHANNEL;
7642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      maxChannels = 1;
7652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
76647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
7672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    default:
7682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
7692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
7702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
77147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Map all channels in this group */
77247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    for ( ; chIdx < numChInGrp[grpIdx]; chIdx += 1) {
77347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      int mappedIdx = pChannelMap[ch];
77447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (chIdx == maxChannels) {
77547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* No space left in this channel group!
77647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi           Use the multipurpose group instead: */
77747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chMapPos = LEFT_MULTIPRPS_CHANNEL;
77847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
77947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      offsetTable[chMapPos]     = mappedIdx;
78047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      channelType[mappedIdx]    = type;
78147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      channelIndices[mappedIdx] = chIdx;
7822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      chMapPos += 1;
7832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      ch += 1;
7842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
7852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
7862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
7872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
78847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/** Private helper function for downmix matrix manipulation that initializes
78947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  one row in a given downmix matrix (corresponding to one output channel).
79047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to fixed-point parts of the downmix matrix.
79147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to scale factor matrix associated to the downmix factors.
79247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Index of channel (row) to be initialized.
79347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @returns       Nothing to return.
79447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi **/
79547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic
79647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivivoid dmxInitChannel(
79747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX            mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
79847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT                 mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
79947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const unsigned int  outCh
80047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi       )
80147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
80247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  unsigned int inCh;
80347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) {
80447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (inCh == outCh) {
80547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.5f);
80647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixScales[outCh][inCh]  = 1;
80747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    } else {
80847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.0f);
80947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixScales[outCh][inCh]  = 0;
81047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
81147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
81247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi}
81347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
81447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/** Private helper function for downmix matrix manipulation that does a reset
81547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  of one row in a given downmix matrix (corresponding to one output channel).
81647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to fixed-point parts of the downmix matrix.
81747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to scale factor matrix associated to the downmix factors.
81847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Index of channel (row) to be cleared/reset.
81947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @returns       Nothing to return.
82047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi **/
82147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic
82247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivivoid dmxClearChannel(
82347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX            mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
82447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT                 mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
82547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const unsigned int  outCh
82647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi       )
82747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
82847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemclear(&mixFactors[outCh], PCM_DMX_MAX_CHANNELS*sizeof(FIXP_DMX));
82947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemclear(&mixScales[outCh],  PCM_DMX_MAX_CHANNELS*sizeof(INT));
83047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi}
83147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
83247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/** Private helper function for downmix matrix manipulation that applies a source channel (row)
83347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  scaled by a given mix factor to a destination channel (row) in a given downmix matrix.
83447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  Existing mix factors of the destination channel (row) will get overwritten.
83547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to fixed-point parts of the downmix matrix.
83647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to scale factor matrix associated to the downmix factors.
83747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Index of source channel (row).
83847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Index of destination channel (row).
83947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Fixed-point part of mix factor to be applied.
84047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Scale factor of mix factor to be applied.
84147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @returns       Nothing to return.
84247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi **/
84347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic
84447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivivoid dmxSetChannel(
84547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX            mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
84647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT                 mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
84747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const unsigned int  dstCh,
84847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const unsigned int  srcCh,
84947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const FIXP_DMX      factor,
85047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const INT           scale
85147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi       )
85247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
85347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int ch;
85447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  for (ch=0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) {
85547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (mixFactors[srcCh][ch] != (FIXP_DMX)0) {
85647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[dstCh][ch] = FX_DBL2FX_DMX(fMult(mixFactors[srcCh][ch], factor));
85747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixScales[dstCh][ch]  = mixScales[srcCh][ch] + scale;
85847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
85947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
86047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi}
86147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
86247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/** Private helper function for downmix matrix manipulation that adds a source channel (row)
86347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  scaled by a given mix factor to a destination channel (row) in a given downmix matrix.
86447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to fixed-point parts of the downmix matrix.
86547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to scale factor matrix associated to the downmix factors.
86647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Index of source channel (row).
86747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Index of destination channel (row).
86847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Fixed-point part of mix factor to be applied.
86947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Scale factor of mix factor to be applied.
87047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @returns       Nothing to return.
87147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi **/
87247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic
87347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivivoid dmxAddChannel(
87447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX            mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
87547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT                 mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
87647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const unsigned int  dstCh,
87747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const unsigned int  srcCh,
87847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const FIXP_DMX      factor,
87947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const INT           scale
88047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi       )
88147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
88247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int ch;
88347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  for (ch=0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) {
88447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FIXP_DBL addFact = fMult(mixFactors[srcCh][ch], factor);
88547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (addFact != (FIXP_DMX)0) {
88647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT newScale = mixScales[srcCh][ch] + scale;
88747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (mixFactors[dstCh][ch] != (FIXP_DMX)0) {
88847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (newScale > mixScales[dstCh][ch]) {
88947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          mixFactors[dstCh][ch] >>= newScale - mixScales[dstCh][ch];
89047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        } else {
89147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          addFact >>= mixScales[dstCh][ch] - newScale;
89247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          newScale  = mixScales[dstCh][ch];
89347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
89447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
89547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[dstCh][ch] += FX_DBL2FX_DMX(addFact);
89647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixScales[dstCh][ch]   = newScale;
89747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
89847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
89947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi}
90047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
90147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
90247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/** Private function that creates a downmix factor matrix depending on the input and output
90347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  configuration, the user parameters as well as the given metadata. This function is the modules
90447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *  brain and hold all downmix algorithms.
90547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]  Flag that indicates if inChMode holds a real (packed) channel mode or has been
90647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                converted to a MPEG-4 channel configuration index.
90747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]  Dependent on the inModeIsCfg flag this field hands in a (packed) channel mode or
90847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                the corresponding MPEG-4 channel configuration index.of the input configuration.
90947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]  The (packed) channel mode of the output configuration.
91047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]  Pointer to structure holding all current user parameter.
91147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]  Pointer to field holding all current meta data.
91247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [out] Pointer to fixed-point parts of the downmix matrix. Normalized to one scale factor.
91347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [out] The common scale factor of the downmix matrix.
91447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @returns     An error code.
91547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi **/
91647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivistatic
91747c680c62246594107da0a8995c953dfb8040bceJean-Michel TriviPCMDMX_ERROR getMixFactors (
91847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const UCHAR                 inModeIsCfg,
91947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        PCM_DMX_CHANNEL_MODE        inChMode,
92047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const PCM_DMX_CHANNEL_MODE  outChMode,
92147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const PCM_DMX_USER_PARAMS  *pParams,
92247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const DMX_BS_META_DATA     *pMetaData,
92347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX                    mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS],
92447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT                        *pOutScale
92547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      )
92647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
92747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCMDMX_ERROR err = PCMDMX_OK;
92847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  INT  mixScales[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS];
92947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  INT  maxScale = 0;
93047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int  numInChannel, numOutChannel;
93147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  unsigned int  outCh, inCh, inChCfg = 0;
93247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  unsigned int  valid[PCM_DMX_MAX_CHANNELS] = { 0 };
93347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
93447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_ASSERT(pMetaData  != NULL);
93547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_ASSERT(mixFactors != NULL);
93647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Check on a supported output configuration */
93747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_ASSERT( (outChMode == CH_MODE_1_0_0_0)
93847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi           || (outChMode == CH_MODE_2_0_0_0)
93947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi           || (outChMode == CH_MODE_3_0_2_1) );
94047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
94147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (inModeIsCfg) {
94247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Workaround for the ambiguity of the internal channel modes.
94347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi       Convert channel config to channel mode: */
94447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    inChCfg  = (unsigned int)inChMode;
94547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    switch (inChCfg) {
94647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case 1: case 2: case 3:
94747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_CHANNELS > 3)
94847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case 4: case 5: case 6:
94947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
95047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      inChMode = outChModeTable[inChCfg];
95147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
95247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case 11:
95347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      inChMode = CH_MODE_3_0_3_1;
95447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
95547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case 12:
95647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      inChMode = CH_MODE_3_0_4_1;
95747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
95847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case 7: case 14:
95947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      inChMode = CH_MODE_5_0_2_1;
96047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
96147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    default:
96247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDK_ASSERT(0);
96347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
96447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
96547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
96647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Extract the total number of input channels */
96747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  numInChannel  =  (inChMode&0xF)
96847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                + ((inChMode>> 4)&0xF)
96947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                + ((inChMode>> 8)&0xF)
97047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                + ((inChMode>>12)&0xF);
97147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Extract the total number of output channels */
97247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  numOutChannel =  (outChMode&0xF)
97347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                + ((outChMode>> 4)&0xF)
97447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                + ((outChMode>> 8)&0xF)
97547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                + ((outChMode>>12)&0xF);
97647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
97747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* MPEG ammendment 4 aka ETSI metadata and fallback mode: */
97847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
97947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
98047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Create identity DMX matrix: */
98147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) {
98247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dmxInitChannel( mixFactors, mixScales, outCh );
98347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
98447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (((inChMode>>12)&0xF) == 0) {
98547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Clear empty or wrongly mapped input channel */
98647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dmxClearChannel( mixFactors, mixScales, LOW_FREQUENCY_CHANNEL );
98747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
98847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
98947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* FIRST STAGE: */
99047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (numInChannel > SIX_CHANNEL)
99147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  { /* Always use MPEG equations either with meta data or with default values. */
99247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FIXP_DMX  dMixFactA, dMixFactB;
99347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    INT       dMixScaleA, dMixScaleB;
99447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int       isValidCfg = TRUE;
99547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
99647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Get factors from meta data */
99747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dMixFactA  = abMixLvlValueTab[pMetaData->dmixIdxA];
99847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dMixScaleA = (pMetaData->dmixIdxA==0) ? 1 : 0;
99947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dMixFactB  = abMixLvlValueTab[pMetaData->dmixIdxB];
100047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dMixScaleB = (pMetaData->dmixIdxB==0) ? 1 : 0;
100147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
100247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Check if input is in the list of supported configurations */
100347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    switch (inChMode) {
100447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_0_3_1:   /* chCfg 11 */
100547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* 6.1ch:  C' = C;  L' = L;  R' = R;  LFE' = LFE;
100647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                 Ls' = Ls*dmix_a_idx + Cs*dmix_b_idx;
100747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                 Rs' = Rs*dmix_a_idx + Cs*dmix_b_idx; */
100847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxClearChannel( mixFactors, mixScales, RIGHT_MULTIPRPS_CHANNEL );  /* clear empty input channel */
100947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,  LEFT_REAR_CHANNEL,      dMixFactA, dMixScaleA );
101047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,  LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB );
101147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_REAR_CHANNEL,     dMixFactA, dMixScaleA );
101247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB );
101347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
101447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_2_1_0:
101547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_2_1_1:   /* chCfg 11 but with side channels */
101647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* 6.1ch:  C' = C;  L' = L;  R' = R;  LFE' = LFE;
101747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                 Ls' = Ls*dmix_a_idx + Cs*dmix_b_idx;
101847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                 Rs' = Rs*dmix_a_idx + Cs*dmix_b_idx; */
101947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxClearChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL );  /* clear empty input channel */
102047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, LEFT_REAR_CHANNEL,       dMixFactB, dMixScaleB );
102147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_MULTIPRPS_CHANNEL, dMixFactA, dMixScaleA );
102247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,  LEFT_REAR_CHANNEL,       dMixFactB, dMixScaleB );
102347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,  LEFT_MULTIPRPS_CHANNEL,  dMixFactA, dMixScaleA );
102447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      isValidCfg = FALSE;
102547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      err = PCMDMX_INVALID_MODE;
102647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
102747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_5_2_1_0:
102847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_5_0_1_0:
102947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_5_0_1_1:
103047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /*         Ls' = Cs*dmix_a_idx;
103147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                 Rs' = Cs*dmix_a_idx; */
103247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxClearChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL );  /* clear empty input channel */
103347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA );
103447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,  LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA );
103547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      isValidCfg = FALSE;
103647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      err = PCMDMX_INVALID_MODE;
103747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
103847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_0_4_1:   /* chCfg 12 */
103947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* 7.1ch Surround Back:  C' = C;  L' = L;  R' = R;  LFE' = LFE;
104047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                               Ls' = Ls*dmix_a_idx + Lsr*dmix_b_idx;
104147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                               Rs' = Rs*dmix_a_idx + Rsr*dmix_b_idx; */
104247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,  LEFT_REAR_CHANNEL,       dMixFactA, dMixScaleA );
104347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,  LEFT_MULTIPRPS_CHANNEL,  dMixFactB, dMixScaleB );
104447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_REAR_CHANNEL,      dMixFactA, dMixScaleA );
104547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL, RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB );
104647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
104747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_5_0_2_1:   /* chCfg 7 || 14 */
104847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (inChCfg == 14) {
104947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* 7.1ch Front Height:  C' = C;  Ls' = Ls;  Rs' = Rs;  LFE' = LFE;
105047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                L' = L*dmix_a_idx + Lv*dmix_b_idx;
105147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                R' = R*dmix_a_idx + Rv*dmix_b_idx; */
105247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_FRONT_CHANNEL,      dMixFactA, dMixScaleA );
105347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_MULTIPRPS_CHANNEL,  dMixFactB, dMixScaleB );
105447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL,     dMixFactA, dMixScaleA );
105547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB );
105647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      } else {
105747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* 7.1ch Front:  Ls' = Ls;  Rs' = Rs;  LFE' = LFE;
105847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                         C' = C + (Lc+Rc)*dmix_a_idx;
105947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                         L' = L + Lc*dmix_b_idx;
106047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                         R' = R + Rc*dmix_b_idx;
106147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                         CAUTION: L+R are not at (MPEG) index 1+2. */
106247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, LEFT_FRONT_CHANNEL,      dMixFactA, dMixScaleA );
106347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL,     dMixFactA, dMixScaleA );
106447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,   LEFT_FRONT_CHANNEL,      dMixFactB, dMixScaleB );
106547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,   LEFT_MULTIPRPS_CHANNEL,  FL2FXCONST_DMX(0.5f), 1 );
106647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL,  RIGHT_FRONT_CHANNEL,     dMixFactB, dMixScaleB );
106747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL,  RIGHT_MULTIPRPS_CHANNEL, FL2FXCONST_DMX(0.5f), 1 );
106847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
106947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
107047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    default:
107147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Nothing to do. Just use the identity matrix. */
107247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      isValidCfg = FALSE;
107347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      err = PCMDMX_INVALID_MODE;
107447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
107547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
107647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
107747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Add additional DMX gain */
107847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if ( (isValidCfg == TRUE)
107947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      && (pMetaData->dmxGainIdx5 != 0))
108047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    { /* Apply DMX gain 5 */
108147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FIXP_DMX dmxGain;
108247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT      dmxScale;
108347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT      sign = (pMetaData->dmxGainIdx5 & 0x40) ? -1 : 1;
108447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT      val  = pMetaData->dmxGainIdx5 & 0x3F;
108547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
108647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* 10^(dmx_gain_5/80) */
108747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxGain = FX_DBL2FX_DMX( fLdPow(
108847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                    FL2FXCONST_DBL(0.830482023721841f), 2,  /* log2(10) */
108947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                    (FIXP_DBL)(sign*val*(LONG)FL2FXCONST_DBL(0.0125f)), 0,
109047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                   &dmxScale )
109147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                               );
109247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Currently only positive scale factors supported! */
109347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (dmxScale < 0) {
109447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxGain >>= -dmxScale;
109547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxScale  =  0;
109647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
109747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
109847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL,  CENTER_FRONT_CHANNEL,  dmxGain, dmxScale );
109947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,    LEFT_FRONT_CHANNEL,    dmxGain, dmxScale );
110047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL,   RIGHT_FRONT_CHANNEL,   dmxGain, dmxScale );
110147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LEFT_REAR_CHANNEL,     LEFT_REAR_CHANNEL,     dmxGain, dmxScale );
110247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, RIGHT_REAR_CHANNEL,    RIGHT_REAR_CHANNEL,    dmxGain, dmxScale );
110347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, LOW_FREQUENCY_CHANNEL, LOW_FREQUENCY_CHANNEL, dmxGain, dmxScale );
110447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
110547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
110647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Mark the output channels */
110747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[CENTER_FRONT_CHANNEL]  = 1;
110847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[LEFT_FRONT_CHANNEL]    = 1;
110947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[RIGHT_FRONT_CHANNEL]   = 1;
111047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[LEFT_REAR_CHANNEL]     = 1;
111147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[RIGHT_REAR_CHANNEL]    = 1;
111247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[LOW_FREQUENCY_CHANNEL] = 1;
111347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
111447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Update channel mode for the next stage */
111547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    inChMode = CH_MODE_3_0_2_1;
111647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
111747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
111847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* SECOND STAGE: */
111947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (numOutChannel <= TWO_CHANNEL) {
112047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Create DMX matrix according to input configuration */
112147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    switch (inChMode) {
112247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_2_0_0_0:   /* chCfg 2 */
112347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Apply the dual channel mode. */
112447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      switch (pParams->dualChannelMode) {
112547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      case CH1_MODE:  /* L' = 0.707 * Ch1;
112647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                         R' = 0.707 * Ch1; */
112747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_FRONT_CHANNEL,  FL2FXCONST_DMX(0.707f), 0 );
112847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL,  FL2FXCONST_DMX(0.707f), 0 );
112947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
113047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      case CH2_MODE:  /* L' = 0.707 * Ch2;
113147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                         R' = 0.707 * Ch2; */
113247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 );
113347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 );
113447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
113547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      case MIXED_MODE:  /* L' = 0.5*Ch1 + 0.5*Ch2;
113647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                           R' = 0.5*Ch1 + 0.5*Ch2; */
113747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_FRONT_CHANNEL,  FL2FXCONST_DMX(0.5f), 0 );
113847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0 );
113947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_FRONT_CHANNEL,  FL2FXCONST_DMX(0.5f), 0 );
114047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0 );
114147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
114247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      default:
114347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      case STEREO_MODE:
114447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Nothing to do */
114547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
114647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
114747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
114847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_2_0_1_0:
114947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* L' = L + 0.707*S;
115047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         R' = R + 0.707*S; */
115147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_REAR_CHANNEL,   FL2FXCONST_DMX(0.707f), 0 );
115247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL,   FL2FXCONST_DMX(0.707f), 0 );
115347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
115447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_0_0_0:   /* chCfg 3 */
115547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* L' = L + 0.707*C;
115647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         R' = R + 0.707*C; */
115747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 );
115847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 );
115947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
116047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_0_1_0:   /* chCfg 4 */
116147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* L' = L + 0.707*C + 0.707*S;
116247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         R' = R + 0.707*C + 0.707*S; */
116347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 );
116447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_REAR_CHANNEL,    FL2FXCONST_DMX(0.707f), 0 );
116547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0 );
116647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL,    FL2FXCONST_DMX(0.707f), 0 );
116747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
116847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_0_2_0:   /* chCfg 5 */
116947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case CH_MODE_3_0_2_1:   /* chCfg 6 */
117047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* MPEG + ITU + DLB
117147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         But because the default downmix equations and coefficients are equal we stick to MPEG. */
117247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (  (pMetaData->typeFlags & TYPE_DSE_DATA)
117347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        || !(pMetaData->typeFlags & TYPE_PCE_DATA) )
117447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      {
117547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX  cMixLvl, sMixLvl, lMixLvl;
117647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT       cMixScale, sMixScale, lMixScale;
117747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
117847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Get factors from meta data */
117947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        cMixLvl   = abMixLvlValueTab[pMetaData->cLevIdx];
118047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        cMixScale = (pMetaData->cLevIdx==0) ? 1 : 0;
118147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        sMixLvl   = abMixLvlValueTab[pMetaData->sLevIdx];
118247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        sMixScale = (pMetaData->sLevIdx==0) ? 1 : 0;
118347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        lMixLvl   = lfeMixLvlValueTab[pMetaData->dmixIdxLfe];
118447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (pMetaData->dmixIdxLfe <= 1) {
118547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          lMixScale = 2;
118647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        } else if (pMetaData->dmixIdxLfe <= 5) {
118747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          lMixScale = 1;
118847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        } else {
118947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          lMixScale = 0;
119047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
119147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Setup the DMX matrix */
119247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if ( (pParams->pseudoSurrMode == FORCE_PS_DMX)
119347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          || ((pParams->pseudoSurrMode == AUTO_PS_DMX) && (pMetaData->pseudoSurround==1)))
119447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        { /* L' = L + C*clev - (Ls+Rs)*slev + LFE*lflev;
119547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi             R' = R + C*clev + (Ls+Rs)*slev + LFE*lflev; */
119647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  CENTER_FRONT_CHANNEL,  cMixLvl, cMixScale );
119747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_REAR_CHANNEL,    -sMixLvl, sMixScale );
119847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  RIGHT_REAR_CHANNEL,   -sMixLvl, sMixScale );
119947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale );
120047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL,  cMixLvl, cMixScale );
120147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL,     sMixLvl, sMixScale );
120247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL,    sMixLvl, sMixScale );
120347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale );
120447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
120547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        else
120647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        { /* L' = L + C*clev + Ls*slev + LFE*llev;
120747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi             R' = R + C*clev + Rs*slev + LFE*llev; */
120847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  CENTER_FRONT_CHANNEL,  cMixLvl, cMixScale );
120947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_REAR_CHANNEL,     sMixLvl, sMixScale );
121047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale );
121147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL,  cMixLvl, cMixScale );
121247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL,    sMixLvl, sMixScale );
121347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxAddChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale );
121447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
121547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
121647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Add additional DMX gain */
121747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if ( pMetaData->dmxGainIdx2 != 0 )
121847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        { /* Apply DMX gain 2 */
121947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          FIXP_DMX dmxGain;
122047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          INT      dmxScale;
122147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          INT      sign = (pMetaData->dmxGainIdx2 & 0x40) ? -1 : 1;
122247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          INT      val  = pMetaData->dmxGainIdx2 & 0x3F;
122347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
122447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          /* 10^(dmx_gain_2/80) */
122547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxGain = FX_DBL2FX_DMX( fLdPow(
122647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                        FL2FXCONST_DBL(0.830482023721841f), 2,  /* log2(10) */
122747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                        (FIXP_DBL)(sign*val*(LONG)FL2FXCONST_DBL(0.0125f)), 0,
122847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                       &dmxScale )
122947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                   );
123047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          /* Currently only positive scale factors supported! */
123147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (dmxScale < 0) {
123247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            dmxGain >>= -dmxScale;
123347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            dmxScale  =  0;
123447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
123547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
123647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_FRONT_CHANNEL,  dmxGain, dmxScale );
123747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, dmxGain, dmxScale );
123847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
123947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
124047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCE_METADATA_ENABLE
124147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      else {
124247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX  flev, clev, slevLL, slevLR, slevRL, slevRR;
124347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX  mtrxMixDwnCoef = mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx];
124447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
124547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if ( (pParams->pseudoSurrMode == FORCE_PS_DMX)
124647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          || ((pParams->pseudoSurrMode == AUTO_PS_DMX) && (pMetaData->pseudoSurround==1)))
124747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        { /* 3/2 input: L' = (1.707+2*A)^-1 * [L+0.707*C-A*Ls-A*Rs];
124847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                        R' = (1.707+2*A)^-1 * [R+0.707*C+A*Ls+A*Rs]; */
124947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          flev = mpegMixDownIdx2PreFact[1][pMetaData->matrixMixdownIdx];
125047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          slevRR = slevRL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef));
125147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          slevLL = slevLR = -slevRL;
125247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
125347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        else {
125447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          /* 3/2 input: L' = (1.707+A)^-1 * [L+0.707*C+A*Ls];
125547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                        R' = (1.707+A)^-1 * [R+0.707*C+A*Rs]; */
125647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          flev = mpegMixDownIdx2PreFact[0][pMetaData->matrixMixdownIdx];
125747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          slevRR = slevLL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef));
125847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          slevLR = slevRL = (FIXP_SGL)0;
125947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
126047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* common factor */
126147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        clev  = FX_DBL2FX_DMX(fMult(flev, mpegMixDownIdx2Coef[0] /* 0.707 */));
126247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
126347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_FRONT_CHANNEL,   flev,   0 );
126447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  CENTER_FRONT_CHANNEL, clev,   0 );
126547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  LEFT_REAR_CHANNEL,    slevLL, 0 );
126647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, LEFT_FRONT_CHANNEL,  RIGHT_REAR_CHANNEL,   slevLR, 0 );
126747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
126847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL,  flev,   0 );
126947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, CENTER_FRONT_CHANNEL, clev,   0 );
127047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, LEFT_REAR_CHANNEL,    slevRL, 0 );
127147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        dmxSetChannel( mixFactors, mixScales, RIGHT_FRONT_CHANNEL, RIGHT_REAR_CHANNEL,   slevRR, 0 );
127247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
127347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif  /* PCE_METADATA_ENABLE */
127447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
127547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    default:
127647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* This configuration does not fit to any known downmix equation! */
127747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      err = PCMDMX_INVALID_MODE;
127847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
127947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
128047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Mark the output channels */
128147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKmemclear(valid, PCM_DMX_MAX_CHANNELS*sizeof(unsigned int));
128247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[LEFT_FRONT_CHANNEL]  = 1;
128347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[RIGHT_FRONT_CHANNEL] = 1;
128447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Update channel mode for the next stage */
128547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    inChMode = CH_MODE_2_0_0_0;
128647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
128747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
128847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (numOutChannel == ONE_CHANNEL) {
128947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FIXP_DMX monoMixLevel;
129047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    INT      monoMixScale;
129147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
129247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCE_METADATA_ENABLE
129347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (  (pMetaData->typeFlags & TYPE_PCE_DATA)
129447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      && !(pMetaData->typeFlags & TYPE_DSE_DATA) )
129547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    { /* C' = (3+2*A)^-1 * [C+L+R+A*Ls+A+Rs]; */
129647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      monoMixLevel = mpegMixDownIdx2PreFact[2][pMetaData->matrixMixdownIdx];
129747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      monoMixScale = 0;
129847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
129947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxClearChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL );
130047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[CENTER_FRONT_CHANNEL][CENTER_FRONT_CHANNEL] = monoMixLevel;
130147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[CENTER_FRONT_CHANNEL][LEFT_FRONT_CHANNEL]   = monoMixLevel;
130247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[CENTER_FRONT_CHANNEL][RIGHT_FRONT_CHANNEL]  = monoMixLevel;
130347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      monoMixLevel = FX_DBL2FX_DMX(fMult(monoMixLevel, mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx]));
130447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[CENTER_FRONT_CHANNEL][LEFT_REAR_CHANNEL]    = monoMixLevel;
130547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      mixFactors[CENTER_FRONT_CHANNEL][RIGHT_REAR_CHANNEL]   = monoMixLevel;
130647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
130747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    else
130847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
130947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    { /* C' = L + R; [default] */
131047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      monoMixLevel = FL2FXCONST_DMX(0.5f);
131147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      monoMixScale = 1;
131247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxClearChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL );  /* C is not in the mix */
131347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxSetChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, LEFT_FRONT_CHANNEL,  monoMixLevel, monoMixScale );
131447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      dmxAddChannel( mixFactors, mixScales, CENTER_FRONT_CHANNEL, RIGHT_FRONT_CHANNEL, monoMixLevel, monoMixScale );
131547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
131647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
131747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Mark the output channel */
131847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKmemclear(valid, PCM_DMX_MAX_CHANNELS*sizeof(unsigned int));
131947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    valid[CENTER_FRONT_CHANNEL] = 1;
132047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
132147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
132247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define MAX_SEARCH_START_VAL  ( -7 )
132347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
132447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  {
132547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    LONG chSum[PCM_DMX_MAX_CHANNELS];
132647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    INT  chSumMax = MAX_SEARCH_START_VAL;
132747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
132847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Determine the current maximum scale factor */
132947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) {
133047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (valid[outCh]!=0) {
133147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) {
133247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (mixScales[outCh][inCh] > maxScale)
133347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          { /* Store the new maximum */
133447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            maxScale = mixScales[outCh][inCh];
133547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
133647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
133747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
133847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
133947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
134047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Individualy analyse output chanal levels */
134147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) {
134247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      chSum[outCh] = MAX_SEARCH_START_VAL;
134347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (valid[outCh]!=0) {
134447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        int  ovrflwProtScale = 0;
134547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
134647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Accumulate all factors for each output channel */
134747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chSum[outCh] = 0;
134847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) {
134947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          SHORT addFact = FX_DMX2SHRT(mixFactors[outCh][inCh]);
135047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if ( mixScales[outCh][inCh] <= maxScale ) {
135147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            addFact >>= maxScale - mixScales[outCh][inCh];
135247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          } else {
135347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            addFact <<= mixScales[outCh][inCh] - maxScale;
135447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
135547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          chSum[outCh] += addFact;
135647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
135747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (chSum[outCh] > (LONG)MAXVAL_SGL) {
135847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          while (chSum[outCh] > (LONG)MAXVAL_SGL) {
135947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            ovrflwProtScale += 1;
136047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            chSum[outCh] >>= 1;
136147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
136247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        } else if (chSum[outCh] > 0) {
136347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          while ((chSum[outCh]<<1) <= (LONG)MAXVAL_SGL) {
136447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            ovrflwProtScale -= 1;
136547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            chSum[outCh] <<= 1;
136647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
136747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
136847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Store the differential scaling in the same array */
136947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chSum[outCh] = ovrflwProtScale;
137047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
137147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
137247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
137347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) {
137447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if ( (valid[outCh] != 0)
137547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        && (chSum[outCh] > chSumMax) )
137647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      { /* Store the new maximum */
137747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chSumMax = chSum[outCh];
137847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
137947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
138047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    maxScale = FDKmax(maxScale+chSumMax, 0);
138147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
138247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Normalize all factors */
138347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) {
138447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if (valid[outCh]!=0) {
138547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) {
138647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (mixFactors[outCh][inCh] != (FIXP_DMX)0) {
138747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            if ( mixScales[outCh][inCh] <= maxScale ) {
138847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              mixFactors[outCh][inCh] >>= maxScale - mixScales[outCh][inCh];
138947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            } else {
139047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              mixFactors[outCh][inCh] <<= mixScales[outCh][inCh] - maxScale;
139147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            }
139247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            mixScales[outCh][inCh] = maxScale;
139347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
139447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
139547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
139647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
139747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
139847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
139947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
140047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* return the scale factor */
140147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  *pOutScale = maxScale;
140247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
140347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  return (err);
140447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi}
140547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
14062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Open and initialize an instance of the PCM downmix module
14082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [out] Pointer to a buffer receiving the handle of the new instance.
14092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
14102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
14112228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPCMDMX_ERROR pcmDmx_Open (
14122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    HANDLE_PCM_DOWNMIX *pSelf
14132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  )
14142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
14152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  HANDLE_PCM_DOWNMIX self;
14162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (pSelf == NULL) {
14182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_INVALID_HANDLE);
14192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
14202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *pSelf = NULL;
14222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  self = (HANDLE_PCM_DOWNMIX) GetPcmDmxInstance( 0 );
14242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (self == NULL) {
14252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_OUT_OF_MEMORY);
14262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
14272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Reset the full instance */
14292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  pcmDmx_Reset( self, PCMDMX_RESET_FULL );
14302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *pSelf = self;
14322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return (PCMDMX_OK);
14342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
14352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Reset all static values like e.g. mixdown coefficients.
14382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Handle of PCM downmix module instance.
14392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Flags telling which parts of the module shall be reset.
14402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
14412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
14422228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPCMDMX_ERROR pcmDmx_Reset (
14432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    HANDLE_PCM_DOWNMIX  self,
14442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    UINT                flags
14452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  )
14462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
14472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (self == NULL) { return (PCMDMX_INVALID_HANDLE); }
14482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (flags & PCMDMX_RESET_PARAMS) {
145047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    PCM_DMX_USER_PARAMS *pParams = &self->userParams;
145147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
145247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pParams->dualChannelMode   = STEREO_MODE;
145347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pParams->pseudoSurrMode    = NEVER_DO_PS_DMX;
145447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pParams->numOutChannelsMax = PCM_DMX_DFLT_MAX_OUT_CHANNELS;
145547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pParams->numOutChannelsMin = PCM_DMX_DFLT_MIN_OUT_CHANNELS;
145647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pParams->frameDelay        = 0;
145747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pParams->expiryFrame       = PCM_DMX_DFLT_EXPIRY_FRAME;
145847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
145947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->applyProcessing      = 0;
14602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
14612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (flags & PCMDMX_RESET_BS_DATA) {
14632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int slot;
146447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Init all slots with a default set */
14652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    for (slot = 0; slot <= PCM_DMX_MAX_DELAY_FRAMES; slot += 1) {
146647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKmemcpy(&self->bsMetaData[slot], &dfltMetaData, sizeof(DMX_BS_META_DATA));
14672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
14682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
14692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return (PCMDMX_OK);
14712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
14722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Set one parameter for one instance of the PCM downmix module.
14752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Handle of PCM downmix module instance.
14762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Parameter to be set.
14772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Parameter value.
14782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
14792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
14802228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPCMDMX_ERROR pcmDmx_SetParam (
14812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    HANDLE_PCM_DOWNMIX  self,
148247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    const PCMDMX_PARAM  param,
148347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    const INT           value
14842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  )
14852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
14862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  switch (param)
14872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
14882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  case DMX_BS_DATA_EXPIRY_FRAME:
14892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (self == NULL)
14902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return (PCMDMX_INVALID_HANDLE);
149147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->userParams.expiryFrame = (value > 0) ? (UINT)value : 0;
14922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    break;
14932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
14942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  case DMX_BS_DATA_DELAY:
149547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if ( (value > PCM_DMX_MAX_DELAY_FRAMES)
149647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      || (value < 0) ) {
14972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return (PCMDMX_UNABLE_TO_SET_PARAM);
14982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
14992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (self == NULL) {
15002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return (PCMDMX_INVALID_HANDLE);
15012228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
150247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->userParams.frameDelay = (UCHAR)value;
15032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    break;
15042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
150547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case MIN_NUMBER_OF_OUTPUT_CHANNELS:
150647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    switch (value) {  /* supported output channels */
150747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case -1: case 0: case ONE_CHANNEL: case TWO_CHANNEL:
150847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_OUT_CHANNELS >= 6)
150947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case SIX_CHANNEL:
151047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
151147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_OUT_CHANNELS >= 8)
151247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case EIGHT_CHANNEL:
151347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
15142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
15152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    default:
15162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return (PCMDMX_UNABLE_TO_SET_PARAM);
15172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
15182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (self == NULL)
15192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return (PCMDMX_INVALID_HANDLE);
152047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Store the new value */
152147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->userParams.numOutChannelsMin = (value > 0) ? value : -1;
152247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if ( (value > 0)
152347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      && (self->userParams.numOutChannelsMax > 0)
152447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      && (value > self->userParams.numOutChannelsMax) )
152547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    { /* MIN > MAX would be an invalid state. Thus set MAX = MIN in this case. */
152647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      self->userParams.numOutChannelsMax = self->userParams.numOutChannelsMin;
15272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
15282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    break;
15292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
153047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case MAX_NUMBER_OF_OUTPUT_CHANNELS:
153147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    switch (value) {  /* supported output channels */
153247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case -1: case 0: case ONE_CHANNEL: case TWO_CHANNEL:
153347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_OUT_CHANNELS >= 6)
153447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case SIX_CHANNEL:
153547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
153647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_OUT_CHANNELS >= 8)
153747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case EIGHT_CHANNEL:
153847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
153947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
154047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    default:
154147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      return (PCMDMX_UNABLE_TO_SET_PARAM);
154247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
154347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (self == NULL)
154447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      return (PCMDMX_INVALID_HANDLE);
154547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Store the new value */
154647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->userParams.numOutChannelsMax = (value > 0) ? value : -1;
154747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if ( (value > 0)
154847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      && (value < self->userParams.numOutChannelsMin) )
154947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    { /* MAX < MIN would be an invalid state. Thus set MIN = MAX in this case. */
155047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      self->userParams.numOutChannelsMin = self->userParams.numOutChannelsMax;
155147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
155247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
155347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
155447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case DMX_DUAL_CHANNEL_MODE:
15552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    switch ((DUAL_CHANNEL_MODE)value) {
15562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case STEREO_MODE:
15572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH1_MODE:
15582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case CH2_MODE:
15592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case MIXED_MODE:
15602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
15612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    default:
15622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return (PCMDMX_UNABLE_TO_SET_PARAM);
15632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
15642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (self == NULL)
15652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      return (PCMDMX_INVALID_HANDLE);
156647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->userParams.dualChannelMode = (DUAL_CHANNEL_MODE)value;
156747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->applyProcessing = 1;  /* Force processing */
156847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
156947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
157047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case DMX_PSEUDO_SURROUND_MODE:
157147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    switch ((PSEUDO_SURROUND_MODE)value) {
157247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case NEVER_DO_PS_DMX:
157347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case AUTO_PS_DMX:
157447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    case FORCE_PS_DMX:
157547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      break;
157647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    default:
157747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      return (PCMDMX_UNABLE_TO_SET_PARAM);
157847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
157947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (self == NULL)
158047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      return (PCMDMX_INVALID_HANDLE);
158147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    self->userParams.pseudoSurrMode = (PSEUDO_SURROUND_MODE)value;
15822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    break;
15832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  default:
15852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_UNKNOWN_PARAM);
15862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
15872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
15882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return (PCMDMX_OK);
15892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
15902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
159147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/** Get one parameter value of one PCM downmix module instance.
15922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Handle of PCM downmix module instance.
159347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in] Parameter to be set.
159447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [out] Pointer to buffer receiving the parameter value.
15952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
15962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
159747c680c62246594107da0a8995c953dfb8040bceJean-Michel TriviPCMDMX_ERROR pcmDmx_GetParam (
15982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    HANDLE_PCM_DOWNMIX  self,
159947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    const PCMDMX_PARAM  param,
160047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    INT * const         pValue
160147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  )
160247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
160347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCM_DMX_USER_PARAMS *pUsrParams;
160447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
160547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (self == NULL)
160647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (pValue == NULL) ) {
160747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    return (PCMDMX_INVALID_HANDLE);
160847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
160947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  pUsrParams = &self->userParams;
161047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
161147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  switch (param)
161247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  {
161347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case DMX_BS_DATA_EXPIRY_FRAME:
161447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pValue = (INT)pUsrParams->expiryFrame;
161547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
161647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case DMX_BS_DATA_DELAY:
161747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pValue = (INT)pUsrParams->frameDelay;
161847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
161947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case MIN_NUMBER_OF_OUTPUT_CHANNELS:
162047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pValue = (INT)pUsrParams->numOutChannelsMin;
162147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
162247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case MAX_NUMBER_OF_OUTPUT_CHANNELS:
162347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pValue = (INT)pUsrParams->numOutChannelsMax;
162447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
162547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case DMX_DUAL_CHANNEL_MODE:
162647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pValue = (INT)pUsrParams->dualChannelMode;
162747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
162847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  case DMX_PSEUDO_SURROUND_MODE:
162947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pValue = (INT)pUsrParams->pseudoSurrMode;
163047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    break;
163147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  default:
163247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    return (PCMDMX_UNKNOWN_PARAM);
163347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
163447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
163547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  return (PCMDMX_OK);
163647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi}
163747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
163847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
163947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef DSE_METADATA_ENABLE
164047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
164147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define MAX_DSE_ANC_BYTES       ( 16 )    /* 15 bytes */
164247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#define ANC_DATA_SYNC_BYTE      ( 0xBC )  /* ancillary data sync byte. */
164347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
164447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/*
164547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * Read DMX meta-data from a data stream element.
164647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi */
164747c680c62246594107da0a8995c953dfb8040bceJean-Michel TriviPCMDMX_ERROR pcmDmx_Parse (
164847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    HANDLE_PCM_DOWNMIX  self,
164947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    HANDLE_FDK_BITSTREAM  hBs,
165047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UINT  ancDataBits,
16512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int    isMpeg2
16522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  )
16532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
165447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCMDMX_ERROR errorStatus = PCMDMX_OK;
165547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  DMX_BS_META_DATA *pBsMetaData = &self->bsMetaData[0];
16562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
165747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   skip4Dmx = 0, skip4Ext = 0;
165847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   dmxLvlAvail = 0, extDataAvail = 0;
165947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   foundNewData = 0;
166047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  UINT  minAncBits = ((isMpeg2) ? 5 : 3)*8;
16612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
166247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (self == NULL)
166347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (hBs  == NULL) ) { return (PCMDMX_INVALID_HANDLE); }
166447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
166547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  ancDataBits = FDKgetValidBits(hBs);
16662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* sanity checks */
166847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (ancDataBits < minAncBits)
166947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (ancDataBits > FDKgetValidBits(hBs)) ) {
16702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_CORRUPT_ANC_DATA);
16712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
167347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  pBsMetaData = &self->bsMetaData[0];
167447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
167547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (isMpeg2) {
167647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* skip DVD ancillary data */
167747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKpushFor(hBs, 16);
167847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
167947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
16802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* check sync word */
168147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (FDKreadBits(hBs,8) != ANC_DATA_SYNC_BYTE) {
16822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_CORRUPT_ANC_DATA);
16832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
16842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
168547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* skip MPEG audio type and Dolby surround mode */
168647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKpushFor(hBs, 4);
16872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
16882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (isMpeg2) {
168947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* int numAncBytes = */ FDKreadBits(hBs, 4);
169047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* advanced dynamic range control */
169147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (FDKreadBit(hBs)) skip4Dmx += 24;
169247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* dialog normalization */
169347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (FDKreadBit(hBs)) skip4Dmx += 8;
169447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* reproduction_level */
169547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (FDKreadBit(hBs)) skip4Dmx += 8;
169647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  } else {
169747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKpushFor(hBs, 2);   /* drc presentation mode */
169847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pBsMetaData->pseudoSurround = FDKreadBit(hBs);
169947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKpushFor(hBs, 4);   /* reserved bits */
17002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
170147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
170247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* downmixing levels MPEGx status */
170347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  dmxLvlAvail  = FDKreadBit(hBs);
170447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
170547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (isMpeg2) {
170647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* scale factor CRC status */
170747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (FDKreadBit(hBs)) skip4Ext += 16;
170847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  } else {
170947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* ancillary data extension status */
171047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    extDataAvail = FDKreadBit(hBs);
17112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
17122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
171347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* audio coding and compression status */
171447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (FDKreadBit(hBs)) skip4Ext += 16;
171547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* coarse grain timecode status */
171647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (FDKreadBit(hBs)) skip4Ext += 16;
171747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* fine grain timecode status */
171847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (FDKreadBit(hBs)) skip4Ext += 16;
171947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
172047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* skip the useless data to get to the DMX levels */
172147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKpushFor(hBs, skip4Dmx);
172247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
17232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* downmix_levels_MPEGX */
172447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (dmxLvlAvail)
17252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
172647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (FDKreadBit(hBs)) {  /* center_mix_level_on */
172747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pBsMetaData->cLevIdx = FDKreadBits(hBs, 3);
17282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      foundNewData = 1;
17292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } else {
173047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKreadBits(hBs, 3);
17312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
173247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (FDKreadBit(hBs)) {  /* surround_mix_level_on */
173347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pBsMetaData->sLevIdx = FDKreadBits(hBs, 3);
17342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      foundNewData = 1;
17352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    } else {
173647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKreadBits(hBs, 3);
173747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
173847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
173947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
174047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* skip the useless data to get to the ancillary data extension */
174147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKpushFor(hBs, skip4Ext);
174247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
174347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* anc data extension (MPEG-4 only) */
174447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (extDataAvail) {
174547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int extDmxLvlSt, extDmxGainSt, extDmxLfeSt;
174647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
174747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKreadBit(hBs);        /* reserved bit */
174847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    extDmxLvlSt  = FDKreadBit(hBs);
174947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    extDmxGainSt = FDKreadBit(hBs);
175047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    extDmxLfeSt  = FDKreadBit(hBs);
175147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKreadBits(hBs, 4);    /* reserved bits */
175247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
175347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (extDmxLvlSt) {
175447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pBsMetaData->dmixIdxA = FDKreadBits(hBs, 3);
175547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pBsMetaData->dmixIdxB = FDKreadBits(hBs, 3);
175647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKreadBits(hBs, 2);  /* reserved bits */
175747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      foundNewData = 1;
175847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
175947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (extDmxGainSt) {
176047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pBsMetaData->dmxGainIdx5 = FDKreadBits(hBs, 7);
176147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKreadBit(hBs);      /* reserved bit */
176247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pBsMetaData->dmxGainIdx2 = FDKreadBits(hBs, 7);
176347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKreadBit(hBs);      /* reserved bit */
176447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      foundNewData = 1;
176547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
176647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (extDmxLfeSt) {
176747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pBsMetaData->dmixIdxLfe = FDKreadBits(hBs, 4);
176847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKreadBits(hBs, 4);  /* reserved bits */
176947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      foundNewData = 1;
17702228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
177147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
17722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
177347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* final sanity check on the amount of read data */
177447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ((INT)FDKgetValidBits(hBs) < 0) {
177547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    errorStatus = PCMDMX_CORRUPT_ANC_DATA;
17762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
17772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
177847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (errorStatus  == PCMDMX_OK)
177947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    && (foundNewData == 1) ) {
178047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* announce new data */
178147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pBsMetaData->typeFlags |= TYPE_DSE_DATA;
178247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* reset expiry counter */
178347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pBsMetaData->expiryCount = 0;
178447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
17852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
178647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  return (errorStatus);
178747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi}
178847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
178947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi/*
179047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * Read DMX meta-data from a data stream element.
179147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi */
179247c680c62246594107da0a8995c953dfb8040bceJean-Michel TriviPCMDMX_ERROR pcmDmx_ReadDvbAncData (
179347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    HANDLE_PCM_DOWNMIX  self,
179447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UCHAR *pAncDataBuf,
179547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UINT   ancDataBytes,
179647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int    isMpeg2
179747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  )
179847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi{
179947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_BITSTREAM bs;
180047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  HANDLE_FDK_BITSTREAM hBs = &bs;
180147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCMDMX_ERROR errorStatus = PCMDMX_OK;
180247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
180347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (self == NULL) { return (PCMDMX_INVALID_HANDLE); }
180447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
180547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* sanity checks */
180647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (pAncDataBuf == NULL)
180747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (ancDataBytes == 0) ) {
180847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    return (PCMDMX_CORRUPT_ANC_DATA);
180947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
181047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
181147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKinitBitStream (hBs, pAncDataBuf, MAX_DSE_ANC_BYTES, ancDataBytes*8, BS_READER);
181247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
181347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  errorStatus = pcmDmx_Parse (
181447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                        self,
181547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                        hBs,
181647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                        ancDataBytes*8,
181747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                        isMpeg2 );
181847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
181947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  return (errorStatus);
18202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
182147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif  /* DSE_METADATA_ENABLE */
18222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
182347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCE_METADATA_ENABLE
18242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Set the matrix mixdown information extracted from the PCE of an AAC bitstream.
18252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project *  Note: Call only if matrix_mixdown_idx_present is true.
18262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] Handle of PCM downmix module instance.
18272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] The 2 bit matrix mixdown index extracted from PCE.
18282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in] The pseudo surround enable flag extracted from PCE.
18292228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
18302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
18312228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce (
18322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    HANDLE_PCM_DOWNMIX  self,
18332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int                 matrixMixdownPresent,
18342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int                 matrixMixdownIdx,
18352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    int                 pseudoSurroundEnable
18362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  )
18372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
183847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  DMX_BS_META_DATA *pBsMetaData = &self->bsMetaData[0];
18392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (self == NULL) {
18412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_INVALID_HANDLE);
18422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
18432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (matrixMixdownPresent) {
184547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pBsMetaData->pseudoSurround = pseudoSurroundEnable;
184647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pBsMetaData->matrixMixdownIdx = matrixMixdownIdx & 0x03;
184747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pBsMetaData->typeFlags |= TYPE_PCE_DATA;
184847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Reset expiry counter */
184947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pBsMetaData->expiryCount = 0;
18502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
18512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return (PCMDMX_OK);
18532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
185447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif  /* PCE_METADATA_ENABLE */
18552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
18572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Apply down or up mixing.
18582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in]    Handle of PCM downmix module instance.
185947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [inout] Pointer to buffer that hold the time domain signal.
18602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in]    Pointer where the amount of output samples is returned into.
18612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [inout] Pointer where the amount of output channels is returned into.
18622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [in]    Flag which indicates if output time data are writtern interleaved or as subsequent blocks.
18632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [inout] Array where the corresponding channel type for each output audio channel is stored into.
18642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [inout] Array where the corresponding channel type index for each output audio channel is stored into.
186547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [in]    Array containing the out channel mapping to be used (From MPEG PCE ordering to whatever is required).
186647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi * @param [out]   Pointer on a field receiving the scale factor that has to be applied on all samples afterwards.
186747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi *                If the handed pointer is NULL scaling is done internally.
18682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
18692228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
18702228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPCMDMX_ERROR pcmDmx_ApplyFrame (
18712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        HANDLE_PCM_DOWNMIX      self,
18722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        INT_PCM                *pPcmBuf,
18732228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        UINT                    frameSize,
18742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        INT                    *nChannels,
18752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int                     fInterleaved,
18762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        AUDIO_CHANNEL_TYPE      channelType[],
18772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        UCHAR                   channelIndices[],
187847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        const UCHAR             channelMapping[][8],
187947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT                    *pDmxOutScale
18802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  )
18812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
188247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCM_DMX_USER_PARAMS  *pParam = NULL;
18832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  PCMDMX_ERROR  errorStatus = PCMDMX_OK;
18842228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  DUAL_CHANNEL_MODE  dualChannelMode;
18852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  PCM_DMX_CHANNEL_MODE  inChMode;
188647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  PCM_DMX_CHANNEL_MODE  outChMode;
188747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  INT   devNull;  /* Just a dummy to avoid a lot of branches in the code */
188847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   numOutChannels, numInChannels;
188947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   inStride, outStride, offset;
189047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   dmxMaxScale, dmxScale;
189147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  int   ch, slot;
18922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  UCHAR inOffsetTable[PCM_DMX_MAX_CHANNELS];
18932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
189447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  DMX_BS_META_DATA  bsMetaData;
18952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
189647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (self           == NULL)
189747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (nChannels      == NULL)
189847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (channelType    == NULL)
189947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (channelIndices == NULL)
190047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (channelMapping == NULL) ) {
190147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    return (PCMDMX_INVALID_HANDLE);
19022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
19032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
190447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Init the output scaling */
190547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  dmxScale = 0;
190647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (pDmxOutScale != NULL) {
190747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Avoid final scaling internally and hand it to the outside world. */
190847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pDmxOutScale = 0;
190947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dmxMaxScale = PCMDMX_MAX_HEADROOM;
191047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  } else {
191147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Apply the scaling internally. */
191247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    pDmxOutScale = &devNull;  /* redirect to temporal stack memory */
191347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dmxMaxScale = 0;
19142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
19152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
191647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  pParam = &self->userParams;
191747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  numInChannels = *nChannels;
19182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
191947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Perform some input sanity checks */
19202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (pPcmBuf == NULL)     { return (PCMDMX_INVALID_ARGUMENT); }
19212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (frameSize == 0)      { return (PCMDMX_INVALID_ARGUMENT); }
192247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (numInChannels == 0)
192347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (numInChannels > PCM_DMX_MAX_IN_CHANNELS) )
192447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                           { return (PCMDMX_INVALID_ARGUMENT); }
192547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
192647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Check on misconfiguration */
192747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_ASSERT( (pParam->numOutChannelsMax <= 0) \
192847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi           || (pParam->numOutChannelsMax >= pParam->numOutChannelsMin));
192947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
193047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Determine if the module has to do processing */
193147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (   (self->applyProcessing == 0)
193247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    &&  ((pParam->numOutChannelsMax <= 0)
193347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      || (pParam->numOutChannelsMax >= numInChannels))
193447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    &&   (pParam->numOutChannelsMin <= numInChannels) ) {
193547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Nothing to do */
193647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    return (errorStatus);
193747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
19382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
193947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Determine the number of output channels */
194047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (pParam->numOutChannelsMax > 0)
194147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    && (numInChannels > pParam->numOutChannelsMax) ) {
194247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    numOutChannels = pParam->numOutChannelsMax;
194347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
194447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  else if (numInChannels < pParam->numOutChannelsMin) {
194547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    numOutChannels = pParam->numOutChannelsMin;
194647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
194747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  else {
19482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    numOutChannels = numInChannels;
19492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
195047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
195147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  dualChannelMode = pParam->dualChannelMode;
19522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
19532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Analyse input channel configuration and get channel offset
19542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project   * table that can be accessed with the fixed channel labels. */
195547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  errorStatus = getChannelMode(
19562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                   numInChannels,
19572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                   channelType,
19582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                   channelIndices,
195947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                   inOffsetTable,
196047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                  &inChMode
19612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project                 );
196247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( PCMDMX_IS_FATAL_ERROR(errorStatus)
196347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    || (inChMode == CH_MODE_UNDEFINED) ) {
19642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* We don't need to restore because the channel
19652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project       configuration has not been changed. Just exit. */
19662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_INVALID_CH_CONFIG);
19672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
19682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
196947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Set input stride and offset */
197047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if (fInterleaved) {
197147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    inStride  = numInChannels;
197247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    offset = 1;                /* Channel specific offset factor */
197347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  } else {
197447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    inStride  = 1;
197547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    offset = frameSize;        /* Channel specific offset factor */
197647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
197747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
197847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Reset downmix meta data if necessary */
197947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( (pParam->expiryFrame > 0)
198047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    && (++self->bsMetaData[0].expiryCount > pParam->expiryFrame) )
198147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  { /* The metadata read from bitstream is too old. */
198247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    PCMDMX_ERROR err = pcmDmx_Reset(self, PCMDMX_RESET_BS_DATA);
198347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDK_ASSERT(err == PCMDMX_OK);
198447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
198547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDKmemcpy(&bsMetaData, &self->bsMetaData[pParam->frameDelay], sizeof(DMX_BS_META_DATA));
198647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Maintain delay line */
198747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  for (slot = pParam->frameDelay; slot > 0; slot -= 1) {
198847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FDKmemcpy(&self->bsMetaData[slot], &self->bsMetaData[slot-1], sizeof(DMX_BS_META_DATA));
198947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  }
199047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
19912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
199247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCM_DOWNMIX_ENABLE
19932228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( numInChannels > numOutChannels )
19942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  { /* Apply downmix */
199547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    INT_PCM  *pInPcm[PCM_DMX_MAX_IN_CHANNELS] = { NULL };
199647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    INT_PCM  *pOutPcm[PCM_DMX_MAX_OUT_CHANNELS] = { NULL };
199747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    FIXP_DMX  mixFactors[PCM_DMX_MAX_CHANNELS][PCM_DMX_MAX_CHANNELS];
199847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UCHAR     outOffsetTable[PCM_DMX_MAX_CHANNELS];
199947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UINT      sample;
200047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int       chCfg = 0;
200147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    int       bypScale = 0;
200247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
200347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_IN_CHANNELS >= 7)
200447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (numInChannels > SIX_CHANNEL) {
200547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      AUDIO_CHANNEL_TYPE multiPurposeChType[2];
200647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
200747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Get the type of the multipurpose channels */
200847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      multiPurposeChType[0] = channelType[inOffsetTable[LEFT_MULTIPRPS_CHANNEL]];
200947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      multiPurposeChType[1] = channelType[inOffsetTable[RIGHT_MULTIPRPS_CHANNEL]];
201047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
201147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Check if the input configuration is one defined in the standard. */
201247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      switch (inChMode) {
201347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      case CH_MODE_5_0_2_1:  /* chCfg 7 || 14 */
201447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Further analyse the input config to distinguish the two CH_MODE_5_0_2_1 configs. */
201547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if ( (multiPurposeChType[0] == ACT_FRONT_TOP)
201647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          && (multiPurposeChType[1] == ACT_FRONT_TOP) ) {
201747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          chCfg = 14;
201847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        } else {
201947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          chCfg = 7;
202047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
202147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
202247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      case CH_MODE_3_0_3_1:  /* chCfg 11 */
202347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chCfg = 11;
202447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
202547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      case CH_MODE_3_0_4_1:  /* chCfg 12 */
202647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chCfg = 12;
202747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
202847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      default:
202947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        chCfg = 0;  /* Not a known config */
203047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        break;
203147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
20322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
203347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
20342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
203547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Set this stages output stride and channel mode: */
203647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    outStride = (fInterleaved) ? numOutChannels : 1;
203747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    outChMode = outChModeTable[numOutChannels];
203847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
203947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Get channel description and channel mapping for the desired output configuration. */
20402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    getChannelDescription(
204147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            outChMode,
20422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            channelMapping,
20432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            channelType,
20442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            channelIndices,
20452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            outOffsetTable
20462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project           );
20472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Now there is no way back because we modified the channel configuration! */
20482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
204947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Create the DMX matrix */
205047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    errorStatus = getMixFactors (
205147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                       (chCfg>0) ? 1 : 0,
205247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                       (chCfg>0) ? (PCM_DMX_CHANNEL_MODE)chCfg : inChMode,
205347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                       outChMode,
205447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                       pParam,
205547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                      &bsMetaData,
205647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                       mixFactors,
205747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                      &dmxScale
205847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                     );
205947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* No fatal errors can occur here. The function is designed to always return a valid matrix.
206047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi       The error code is used to signal configurations and matrices that are not conform to any standard. */
206147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
206247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Determine the final scaling */
206347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    bypScale = FDKmin(dmxMaxScale, dmxScale);
206447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *pDmxOutScale += bypScale;
206547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    dmxScale -= bypScale;
206647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
206747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    { /* Set channel pointer for input. Remove empty cols. */
206847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      int inCh, outCh, map[PCM_DMX_MAX_CHANNELS];
206947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      ch = 0;
207047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (inCh=0; inCh < PCM_DMX_MAX_CHANNELS; inCh+=1) {
207147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (inOffsetTable[inCh] != 255) {
207247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pInPcm[ch] = &pPcmBuf[inOffsetTable[inCh]*offset];
207347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          map[ch++]  = inCh;
20742228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
20752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
207647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDK_ASSERT(ch == numInChannels);
207747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
207847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Remove unused cols from factor matrix */
207947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (inCh=0; inCh < numInChannels; inCh+=1) {
208047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (inCh != map[inCh]) {
208147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          int outCh;
208247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) {
208347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            mixFactors[outCh][inCh] = mixFactors[outCh][map[inCh]];
208447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
208547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
20862228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
20872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
208847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Set channel pointer for output. Remove empty cols. */
208947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      ch = 0;
209047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (outCh=0; outCh < PCM_DMX_MAX_CHANNELS; outCh+=1) {
209147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (outOffsetTable[outCh] != 255) {
209247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pOutPcm[ch] = &pPcmBuf[outOffsetTable[outCh]*offset];
209347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          map[ch++]  = outCh;
20942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
20952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
209647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDK_ASSERT(ch == numOutChannels);
20972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
209847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Remove unused rows from factor matrix */
209947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (outCh=0; outCh < numOutChannels; outCh+=1) {
210047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (outCh != map[outCh]) {
210147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          FDKmemcpy(&mixFactors[outCh], &mixFactors[map[outCh]], PCM_DMX_MAX_CHANNELS*sizeof(FIXP_DMX));
21022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
21032228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
210447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
21052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
210647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Sample processing loop */
210747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    for (sample = 0; sample < frameSize; sample++)
210847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    {
210947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FIXP_PCM tIn[PCM_DMX_MAX_IN_CHANNELS];
211047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FIXP_DBL tOut[PCM_DMX_MAX_OUT_CHANNELS] = { (FIXP_DBL)0 };
211147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      int inCh, outCh;
211247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
211347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Preload all input samples */
211447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (inCh=0; inCh < numInChannels; inCh+=1) {
211547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        tIn[inCh] = (FIXP_PCM)*pInPcm[inCh];
211647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pInPcm[inCh] += inStride;
21172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
211847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Apply downmix coefficients to input samples and accumulate for output */
211947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (outCh=0; outCh < numOutChannels; outCh+=1) {
212047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (inCh=0; inCh < numInChannels; inCh+=1) {
212147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          tOut[outCh] += fMult(tIn[inCh], mixFactors[outCh][inCh]);
212247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
212347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Write sample */
212447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (SAMPLE_BITS == DFRACT_BITS)
212547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        *pOutPcm[outCh] = (INT_PCM)SATURATE_LEFT_SHIFT(tOut[outCh], dmxScale, SAMPLE_BITS);
21262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#else
212747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        *pOutPcm[outCh] = (INT_PCM)SATURATE_RIGHT_SHIFT(tOut[outCh], DFRACT_BITS-SAMPLE_BITS-dmxScale, SAMPLE_BITS);
21282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project#endif
212947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pOutPcm[outCh] += outStride;
21302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
21312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
213347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Update the number of output channels */
213447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *nChannels = numOutChannels;
21352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
213647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
213747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  else
213847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif /* PCM_DOWNMIX_ENABLE */
213947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCM_CHANNEL_EXTENSION_ENABLE
214047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  if ( numInChannels < numOutChannels )
214147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  { /* Apply rudimentary upmix */
214247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* Set up channel pointer */
214347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UINT     sample;
214447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    UCHAR    outOffsetTable[PCM_DMX_MAX_CHANNELS];
214547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
214647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* FIRST STAGE
214747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         Create a stereo/dual channel signal */
214847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (numInChannels == ONE_CHANNEL)
214947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    {
215047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT_PCM  *pInPcm[PCM_DMX_MAX_CHANNELS];
215147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT_PCM  *pOutLF, *pOutRF;
21522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
215347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Set this stages output stride and channel mode: */
215447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      outStride = (fInterleaved) ? TWO_CHANNEL : 1;
215547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      outChMode = outChModeTable[TWO_CHANNEL];
21562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
21572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* Get channel description and channel mapping for this
215847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi       * stages number of output channels (always STEREO). */
21592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      getChannelDescription(
216047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              outChMode,
21612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              channelMapping,
21622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              channelType,
21632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              channelIndices,
21642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project              outOffsetTable
21652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project             );
216647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Now there is no way back because we modified the channel configuration! */
21672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
216847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Set input channel pointer. The first channel is always at index 0. */
216947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pInPcm[CENTER_FRONT_CHANNEL] = &pPcmBuf[(frameSize-1)*inStride];  /* Considering input mapping could lead to a invalid pointer
217047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                                                                           here if the channel is not declared to be a front channel. */
21712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
217247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Set output channel pointer (for this stage). */
217347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pOutLF = &pPcmBuf[outOffsetTable[LEFT_FRONT_CHANNEL]*offset+(frameSize-1)*outStride];
217447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      pOutRF = &pPcmBuf[outOffsetTable[RIGHT_FRONT_CHANNEL]*offset+(frameSize-1)*outStride];
21752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
217647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* 1/0 input: */
21772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      for (sample = 0; sample < frameSize; sample++) {
217847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* L' = C;  R' = C; */
217947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        *pOutLF = *pOutRF = *pInPcm[CENTER_FRONT_CHANNEL];
21802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
218147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pInPcm[CENTER_FRONT_CHANNEL] -= inStride;
218247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pOutLF -= outStride; pOutRF -= outStride;
21832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
218447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
218547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Prepare for next stage: */
218647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      inStride = outStride;
218747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      inChMode = outChMode;
218847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKmemcpy(inOffsetTable, outOffsetTable, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR));
21892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
21902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
219147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#if (PCM_DMX_MAX_OUT_CHANNELS > 2)
219247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* SECOND STAGE
219347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         Extend with zero channels to achieved the desired number of output channels. */
219447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    if (numOutChannels > TWO_CHANNEL)
219547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    {
219647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT_PCM *pIn[PCM_DMX_MAX_CHANNELS]  = { NULL };
219747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      INT_PCM *pOut[PCM_DMX_MAX_CHANNELS] = { NULL };
219847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      AUDIO_CHANNEL_TYPE  inChTypes[PCM_DMX_MAX_CHANNELS];
219947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      UCHAR    inChIndices[PCM_DMX_MAX_CHANNELS];
220047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      UCHAR    numChPerGrp[2][PCM_DMX_MAX_CHANNEL_GROUPS];
220147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      int      nContentCh = 0;  /* Number of channels with content */
220247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      int      nEmptyCh = 0;    /* Number of channels with content */
220347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      int      ch, chGrp, isCompatible = 1;
220447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
220547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Do not change the signalling which is the channel types and indices.
220647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         Just reorder and add channels. So first save the input signalling. */
220747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKmemcpy(inChTypes, channelType, PCM_DMX_MAX_CHANNELS*sizeof(AUDIO_CHANNEL_TYPE));
220847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      FDKmemcpy(inChIndices, channelIndices, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR));
220947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
221047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Set this stages output stride and channel mode: */
221147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      outStride = (fInterleaved) ? numOutChannels : 1;
221247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      outChMode = outChModeTable[numOutChannels];
221347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
221447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Check if input channel config can be easily mapped to the desired output config. */
221547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (chGrp = 0; chGrp < PCM_DMX_MAX_CHANNEL_GROUPS; chGrp += 1) {
221647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        numChPerGrp[IN][chGrp] = (inChMode >> (chGrp*4)) & 0xF;
221747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        numChPerGrp[OUT][chGrp] = (outChMode >> (chGrp*4)) & 0xF;
221847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
221947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (numChPerGrp[IN][chGrp] > numChPerGrp[OUT][chGrp]) {
222047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          isCompatible = 0;
222147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          break;
222247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
222347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
22242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
222547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if ( isCompatible ) {
222647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Get new channel description and channel
222747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         * mapping for the desired output channel mode. */
222847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        getChannelDescription(
222947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                outChMode,
223047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                channelMapping,
223147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                channelType,
223247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                channelIndices,
223347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                outOffsetTable
223447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi               );
223547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* If the input config has a back center channel but the output
223647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi           config has not, copy it to left and right (if available). */
223747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if (  (numChPerGrp[IN][CH_GROUP_REAR]%2)
223847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          && !(numChPerGrp[OUT][CH_GROUP_REAR]%2) ) {
223947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (numChPerGrp[IN][CH_GROUP_REAR] == 1) {
224047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            inOffsetTable[RIGHT_REAR_CHANNEL] = inOffsetTable[LEFT_REAR_CHANNEL];
224147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          } else if (numChPerGrp[IN][CH_GROUP_REAR] == 3) {
224247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            inOffsetTable[RIGHT_MULTIPRPS_CHANNEL] = inOffsetTable[LEFT_MULTIPRPS_CHANNEL];
224347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
224447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
224547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
224647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      else {
224747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Just copy and extend the original config */
224847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FDKmemcpy(outOffsetTable, inOffsetTable, PCM_DMX_MAX_CHANNELS*sizeof(UCHAR));
224947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
225047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
225147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Set I/O channel pointer.
225247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi         Note: The following assignment algorithm clears the channel offset tables.
225347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi               Thus they can not be used afterwards. */
225447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (ch = 0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) {
225547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        if ( (outOffsetTable[ch] < 255)
225647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          && (inOffsetTable[ch] < 255) )
225747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        { /* Set I/O pointer: */
225847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pIn[nContentCh] = &pPcmBuf[inOffsetTable[ch]*offset+(frameSize-1)*inStride];
225947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pOut[nContentCh] = &pPcmBuf[outOffsetTable[ch]*offset+(frameSize-1)*outStride];
226047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          /* Update signalling */
226147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          channelType[outOffsetTable[ch]] = inChTypes[inOffsetTable[ch]];
226247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          channelIndices[outOffsetTable[ch]] = inChIndices[inOffsetTable[ch]];
226347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          inOffsetTable[ch] = 255;
226447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          outOffsetTable[ch] = 255;
226547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          nContentCh += 1;
226647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
226747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
226847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      if ( isCompatible ) {
226947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Assign the remaining input channels.
227047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi           This is just a safety appliance. We should never need it. */
227147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (ch = 0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) {
227247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (inOffsetTable[ch] < 255) {
227347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            int  outCh;
227447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            for (outCh = 0 ; outCh < PCM_DMX_MAX_CHANNELS; outCh += 1) {
227547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              if (outOffsetTable[outCh] < 255) {
227647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi                break;
227747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              }
227847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            }
227947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            /* Set I/O pointer: */
228047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            pIn[nContentCh] = &pPcmBuf[inOffsetTable[ch]*offset+(frameSize-1)*inStride];
228147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            pOut[nContentCh] = &pPcmBuf[outOffsetTable[outCh]*offset+(frameSize-1)*outStride];
228247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            /* Update signalling */
228347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            channelType[outOffsetTable[outCh]] = inChTypes[inOffsetTable[ch]];
228447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            channelIndices[outOffsetTable[outCh]] = inChIndices[inOffsetTable[ch]];
228547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            inOffsetTable[ch] = 255;
228647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            outOffsetTable[outCh] = 255;
228747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            nContentCh += 1;
228847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
228947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
229047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Set the remaining output channel pointer */
229147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (ch = 0; ch < PCM_DMX_MAX_CHANNELS; ch+=1) {
229247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          if (outOffsetTable[ch] < 255) {
229347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            pOut[nContentCh+nEmptyCh] = &pPcmBuf[outOffsetTable[ch]*offset+(frameSize-1)*outStride];
229447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            /* Expand output signalling */
229547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            channelType[outOffsetTable[ch]] = ACT_NONE;
229647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            channelIndices[outOffsetTable[ch]] = nEmptyCh;
229747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            outOffsetTable[ch] = 255;
229847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            nEmptyCh += 1;
229947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          }
230047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
230147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
230247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      else {
230347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Set the remaining output channel pointer */
230447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (ch = nContentCh; ch < numOutChannels; ch+=1) {
230547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pOut[ch] = &pPcmBuf[ch*offset+(frameSize-1)*outStride];
230647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          /* Expand output signalling */
230747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          channelType[ch] = ACT_NONE;
230847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          channelIndices[ch] = nEmptyCh;
230947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          nEmptyCh += 1;
231047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
231147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
231247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
231347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* First copy the channels that have signal */
231447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (sample = 0; sample < frameSize; sample+=1) {
231547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT_PCM tIn[PCM_DMX_MAX_CHANNELS];
231647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Read all channel samples */
231747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (ch = 0; ch < nContentCh; ch+=1) {
231847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          tIn[ch] = *pIn[ch];
231947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pIn[ch] -= inStride;
232047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
232147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        /* Write all channel samples */
232247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (ch = 0; ch < nContentCh; ch+=1) {
232347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          *pOut[ch] = tIn[ch];
232447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pOut[ch] -= outStride;
232547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
232647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
232747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
232847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      /* Clear all the other channels */
232947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      for (sample = 0; sample < frameSize; sample++) {
233047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        for (ch = nContentCh; ch < numOutChannels; ch+=1) {
233147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          *pOut[ch] = (INT_PCM)0;
233247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi          pOut[ch] -= outStride;
233347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        }
233447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      }
233547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    }
233647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif  /* if (PCM_DMX_MAX_OUT_CHANNELS > 2) */
233747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
233847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    /* update the number of output channels */
233947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi    *nChannels = numOutChannels;
23402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
23412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  else
234247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif /* PCM_CHANNEL_EXTENSION_ENABLE */
23432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if ( numInChannels == numOutChannels )
23442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  {
23452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    /* Don't need to change the channel description here */
23462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    switch (numInChannels)
23482228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    {
23492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    case 2:
23502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      { /* Set up channel pointer */
235147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT_PCM  *pInPcm[PCM_DMX_MAX_CHANNELS];
235247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        INT_PCM  *pOutL, *pOutR;
235347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        FIXP_DMX  flev;
23542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        UINT sample;
23562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        int inStride, outStride, offset;
23572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        if (fInterleaved) {
23592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          inStride  = numInChannels;
23602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          outStride = 2;  /* fixed !!! (below stereo is donwmixed to mono if required */
23612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          offset = 1; /* Channel specific offset factor */
23622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        } else {
23632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          inStride  = 1;
23642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          outStride = 1;
23652228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          offset = frameSize;  /* Channel specific offset factor */
23662228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
23672228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23682228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Set input channel pointer */
236947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pInPcm[LEFT_FRONT_CHANNEL]  = &pPcmBuf[inOffsetTable[LEFT_FRONT_CHANNEL]*offset];
237047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pInPcm[RIGHT_FRONT_CHANNEL] = &pPcmBuf[inOffsetTable[RIGHT_FRONT_CHANNEL]*offset];
23712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Set output channel pointer (same as input) */
237347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pOutL  =  pInPcm[LEFT_FRONT_CHANNEL];
237447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        pOutR  =  pInPcm[RIGHT_FRONT_CHANNEL];
23752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
23762228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* Set downmix levels: */
237747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi        flev = FL2FXCONST_DMX(0.70710678f);
23782228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        /* 2/0 input: */
23792228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        switch (dualChannelMode)
23802228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        {
23812228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case CH1_MODE:  /* L' = 0.707 * Ch1;  R' = 0.707 * Ch1 */
23822228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (sample = 0; sample < frameSize; sample++) {
23832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *pOutL = *pOutR =
238447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              (INT_PCM)SATURATE_RIGHT_SHIFT(fMult((FIXP_PCM)*pInPcm[LEFT_FRONT_CHANNEL], flev), DFRACT_BITS-SAMPLE_BITS, SAMPLE_BITS);
23852228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
238647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            pInPcm[LEFT_FRONT_CHANNEL] += inStride;
23872228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            pOutL += outStride; pOutR += outStride;
23882228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
23892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
23902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case CH2_MODE:  /* L' = 0.707 * Ch2;  R' = 0.707 * Ch2 */
23912228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (sample = 0; sample < frameSize; sample++) {
23922228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            *pOutL = *pOutR =
239347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi              (INT_PCM)SATURATE_RIGHT_SHIFT(fMult((FIXP_PCM)*pInPcm[RIGHT_FRONT_CHANNEL], flev), DFRACT_BITS-SAMPLE_BITS, SAMPLE_BITS);
23942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
239547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            pInPcm[RIGHT_FRONT_CHANNEL] += inStride;
23962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            pOutL += outStride; pOutR += outStride;
23972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
23982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
23992228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case MIXED_MODE:  /* L' = 0.5*Ch1 + 0.5*Ch2;  R' = 0.5*Ch1 + 0.5*Ch2 */
24002228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          for (sample = 0; sample < frameSize; sample++) {
240147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            *pOutL = *pOutR = (*pInPcm[LEFT_FRONT_CHANNEL] >> 1) + (*pInPcm[RIGHT_FRONT_CHANNEL] >> 1);
24022228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
240347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi            pInPcm[LEFT_FRONT_CHANNEL] += inStride;  pInPcm[RIGHT_FRONT_CHANNEL] += inStride;
24042228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project            pOutL += outStride; pOutR += outStride;
24052228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          }
24062228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
24072228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        default:
24082228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        case STEREO_MODE:
24092228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          /* nothing to do */
24102228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project          break;
24112228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project        }
24122228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      }
24132228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
24142228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24152228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    default:
24162228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      /* nothing to do */
24172228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      break;
24182228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    }
24192228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
24202228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24212228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return (errorStatus);
24222228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
24232228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24242228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24252228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Close an instance of the PCM downmix module.
24262228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [inout] Pointer to a buffer containing the handle of the instance.
24272228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
24282228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project **/
24292228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPCMDMX_ERROR pcmDmx_Close (
24302228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    HANDLE_PCM_DOWNMIX *pSelf
24312228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  )
24322228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
24332228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (pSelf == NULL) {
24342228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return (PCMDMX_INVALID_HANDLE);
24352228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
24362228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24372228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  FreePcmDmxInstance( pSelf );
24382228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  *pSelf = NULL;
24392228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24402228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return (PCMDMX_OK);
24412228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
24422228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24432228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24442228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project/** Get library info for this module.
24452228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @param [out] Pointer to an allocated LIB_INFO structure.
24462228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project * @returns Returns an error code.
24472228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project */
24482228e360595641dd906bf1773307f43d304f5b2The Android Open Source ProjectPCMDMX_ERROR pcmDmx_GetLibInfo( LIB_INFO *info )
24492228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project{
24502228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  int i;
24512228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24522228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (info == NULL) {
24532228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return PCMDMX_INVALID_ARGUMENT;
24542228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
24552228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24562228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Search for next free tab */
24572228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  for (i = 0; i < FDK_MODULE_LAST; i++) {
24582228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    if (info[i].module_id == FDK_NONE) break;
24592228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
24602228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  if (i == FDK_MODULE_LAST) {
24612228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project    return PCMDMX_UNKNOWN;
24622228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  }
24632228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24642228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Add the library info */
246547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  info[i].module_id  = FDK_PCMDMX;
246647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  info[i].version    = LIB_VERSION(PCMDMX_LIB_VL0, PCMDMX_LIB_VL1, PCMDMX_LIB_VL2);
246747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  LIB_VERSION_STRING(info+i);
246847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  info[i].build_date = PCMDMX_LIB_BUILD_DATE;
246947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  info[i].build_time = PCMDMX_LIB_BUILD_TIME;
247047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  info[i].title      = PCMDMX_LIB_TITLE;
24712228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24722228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  /* Set flags */
247347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  info[i].flags = 0
247447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCM_DOWNMIX_ENABLE
24752228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      | CAPF_DMX_BLIND   /* At least blind downmixing is possible */
247647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #ifdef PCE_METADATA_ENABLE
24772228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      | CAPF_DMX_PCE     /* Guided downmix with data from MPEG-2/4 Program Config Elements (PCE). */
247847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  #ifdef ARIB_MIXDOWN_ENABLE
247947c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      | CAPF_DMX_ARIB    /* PCE guided downmix with slightly different equations and levels. */
248047c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  #endif
248147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #endif /* PCE_METADATA_ENABLE */
248247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #ifdef DSE_METADATA_ENABLE
24832228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      | CAPF_DMX_DVB     /* Guided downmix with data from DVB ancillary data fields. */
248447c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi #endif
248547c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif /* PCM_DOWNMIX_ENABLE */
248647c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#ifdef PCM_CHANNEL_EXTENSION_ENABLE
248747c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi      | CAPF_DMX_CH_EXP  /* Simple upmixing by dublicating channels or adding zero channels. */
248847c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi#endif
24892228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project      ;
24902228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
249147c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  /* Add lib info for FDK tools (if not yet done). */
249247c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi  FDK_toolsGetLibInfo(info);
249347c680c62246594107da0a8995c953dfb8040bceJean-Michel Trivi
24942228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project  return PCMDMX_OK;
24952228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project}
24962228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24972228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
24982228e360595641dd906bf1773307f43d304f5b2The Android Open Source Project
2499