xref: /aosp_15_r20/frameworks/av/media/libeffects/downmix/EffectDownmix.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "EffectDownmix"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #include <log/log.h>
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include "EffectDownmix.h"
22*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/ChannelMix.h>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker // Do not submit with DOWNMIX_TEST_CHANNEL_INDEX defined, strictly for testing
25*ec779b8eSAndroid Build Coastguard Worker //#define DOWNMIX_TEST_CHANNEL_INDEX 0
26*ec779b8eSAndroid Build Coastguard Worker // Do not submit with DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER defined, strictly for testing
27*ec779b8eSAndroid Build Coastguard Worker //#define DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER 0
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker #define MINUS_3_DB_IN_FLOAT M_SQRT1_2 // -3dB = 0.70710678
30*ec779b8eSAndroid Build Coastguard Worker 
31*ec779b8eSAndroid Build Coastguard Worker typedef enum {
32*ec779b8eSAndroid Build Coastguard Worker     DOWNMIX_STATE_UNINITIALIZED,
33*ec779b8eSAndroid Build Coastguard Worker     DOWNMIX_STATE_INITIALIZED,
34*ec779b8eSAndroid Build Coastguard Worker     DOWNMIX_STATE_ACTIVE,
35*ec779b8eSAndroid Build Coastguard Worker } downmix_state_t;
36*ec779b8eSAndroid Build Coastguard Worker 
37*ec779b8eSAndroid Build Coastguard Worker /* parameters for each downmixer */
38*ec779b8eSAndroid Build Coastguard Worker struct downmix_object_t {
39*ec779b8eSAndroid Build Coastguard Worker     downmix_state_t state;
40*ec779b8eSAndroid Build Coastguard Worker     downmix_type_t type;
41*ec779b8eSAndroid Build Coastguard Worker     bool apply_volume_correction;
42*ec779b8eSAndroid Build Coastguard Worker     uint8_t input_channel_count;
43*ec779b8eSAndroid Build Coastguard Worker     android::audio_utils::channels::ChannelMix<AUDIO_CHANNEL_OUT_STEREO> channelMix;
44*ec779b8eSAndroid Build Coastguard Worker };
45*ec779b8eSAndroid Build Coastguard Worker 
46*ec779b8eSAndroid Build Coastguard Worker typedef struct downmix_module_s {
47*ec779b8eSAndroid Build Coastguard Worker     const struct effect_interface_s *itfe;
48*ec779b8eSAndroid Build Coastguard Worker     effect_config_t config;
49*ec779b8eSAndroid Build Coastguard Worker     downmix_object_t context;
50*ec779b8eSAndroid Build Coastguard Worker } downmix_module_t;
51*ec779b8eSAndroid Build Coastguard Worker 
52*ec779b8eSAndroid Build Coastguard Worker 
53*ec779b8eSAndroid Build Coastguard Worker // Audio Effect API
54*ec779b8eSAndroid Build Coastguard Worker static int32_t DownmixLib_Create(const effect_uuid_t *uuid,
55*ec779b8eSAndroid Build Coastguard Worker         int32_t sessionId,
56*ec779b8eSAndroid Build Coastguard Worker         int32_t ioId,
57*ec779b8eSAndroid Build Coastguard Worker         effect_handle_t *pHandle);
58*ec779b8eSAndroid Build Coastguard Worker static int32_t DownmixLib_Release(effect_handle_t handle);
59*ec779b8eSAndroid Build Coastguard Worker static int32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid,
60*ec779b8eSAndroid Build Coastguard Worker         effect_descriptor_t *pDescriptor);
61*ec779b8eSAndroid Build Coastguard Worker static int32_t Downmix_Process(effect_handle_t self,
62*ec779b8eSAndroid Build Coastguard Worker         audio_buffer_t *inBuffer,
63*ec779b8eSAndroid Build Coastguard Worker         audio_buffer_t *outBuffer);
64*ec779b8eSAndroid Build Coastguard Worker static int32_t Downmix_Command(effect_handle_t self,
65*ec779b8eSAndroid Build Coastguard Worker         uint32_t cmdCode,
66*ec779b8eSAndroid Build Coastguard Worker         uint32_t cmdSize,
67*ec779b8eSAndroid Build Coastguard Worker         void *pCmdData,
68*ec779b8eSAndroid Build Coastguard Worker         uint32_t *replySize,
69*ec779b8eSAndroid Build Coastguard Worker         void *pReplyData);
70*ec779b8eSAndroid Build Coastguard Worker static int32_t Downmix_GetDescriptor(effect_handle_t self,
71*ec779b8eSAndroid Build Coastguard Worker         effect_descriptor_t *pDescriptor);
72*ec779b8eSAndroid Build Coastguard Worker 
73*ec779b8eSAndroid Build Coastguard Worker // Internal methods
74*ec779b8eSAndroid Build Coastguard Worker static int Downmix_Init(downmix_module_t *pDwmModule);
75*ec779b8eSAndroid Build Coastguard Worker static int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init);
76*ec779b8eSAndroid Build Coastguard Worker static int Downmix_Reset(downmix_object_t *pDownmixer, bool init);
77*ec779b8eSAndroid Build Coastguard Worker static int Downmix_setParameter(
78*ec779b8eSAndroid Build Coastguard Worker         downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue);
79*ec779b8eSAndroid Build Coastguard Worker static int Downmix_getParameter(
80*ec779b8eSAndroid Build Coastguard Worker         downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue);
81*ec779b8eSAndroid Build Coastguard Worker 
82*ec779b8eSAndroid Build Coastguard Worker // effect_handle_t interface implementation for downmix effect
83*ec779b8eSAndroid Build Coastguard Worker const struct effect_interface_s gDownmixInterface = {
84*ec779b8eSAndroid Build Coastguard Worker         Downmix_Process,
85*ec779b8eSAndroid Build Coastguard Worker         Downmix_Command,
86*ec779b8eSAndroid Build Coastguard Worker         Downmix_GetDescriptor,
87*ec779b8eSAndroid Build Coastguard Worker         NULL /* no process_reverse function, no reference stream needed */
88*ec779b8eSAndroid Build Coastguard Worker };
89*ec779b8eSAndroid Build Coastguard Worker 
90*ec779b8eSAndroid Build Coastguard Worker // This is the only symbol that needs to be exported
91*ec779b8eSAndroid Build Coastguard Worker __attribute__ ((visibility ("default")))
92*ec779b8eSAndroid Build Coastguard Worker audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
93*ec779b8eSAndroid Build Coastguard Worker     .tag = AUDIO_EFFECT_LIBRARY_TAG,
94*ec779b8eSAndroid Build Coastguard Worker     .version = EFFECT_LIBRARY_API_VERSION,
95*ec779b8eSAndroid Build Coastguard Worker     .name = "Downmix Library",
96*ec779b8eSAndroid Build Coastguard Worker     .implementor = "The Android Open Source Project",
97*ec779b8eSAndroid Build Coastguard Worker     .create_effect = DownmixLib_Create,
98*ec779b8eSAndroid Build Coastguard Worker     .release_effect = DownmixLib_Release,
99*ec779b8eSAndroid Build Coastguard Worker     .get_descriptor = DownmixLib_GetDescriptor,
100*ec779b8eSAndroid Build Coastguard Worker };
101*ec779b8eSAndroid Build Coastguard Worker 
102*ec779b8eSAndroid Build Coastguard Worker // AOSP insert downmix UUID: 93f04452-e4fe-41cc-91f9-e475b6d1d69f
103*ec779b8eSAndroid Build Coastguard Worker static const effect_descriptor_t gDownmixDescriptor = {
104*ec779b8eSAndroid Build Coastguard Worker         EFFECT_UIID_DOWNMIX__, //type
105*ec779b8eSAndroid Build Coastguard Worker         {0x93f04452, 0xe4fe, 0x41cc, 0x91f9, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid
106*ec779b8eSAndroid Build Coastguard Worker         EFFECT_CONTROL_API_VERSION,
107*ec779b8eSAndroid Build Coastguard Worker         EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
108*ec779b8eSAndroid Build Coastguard Worker         0, //FIXME what value should be reported? // cpu load
109*ec779b8eSAndroid Build Coastguard Worker         0, //FIXME what value should be reported? // memory usage
110*ec779b8eSAndroid Build Coastguard Worker         "Multichannel Downmix To Stereo", // human readable effect name
111*ec779b8eSAndroid Build Coastguard Worker         "The Android Open Source Project" // human readable effect implementor name
112*ec779b8eSAndroid Build Coastguard Worker };
113*ec779b8eSAndroid Build Coastguard Worker 
114*ec779b8eSAndroid Build Coastguard Worker // gDescriptors contains pointers to all defined effect descriptor in this library
115*ec779b8eSAndroid Build Coastguard Worker static const effect_descriptor_t * const gDescriptors[] = {
116*ec779b8eSAndroid Build Coastguard Worker         &gDownmixDescriptor
117*ec779b8eSAndroid Build Coastguard Worker };
118*ec779b8eSAndroid Build Coastguard Worker 
119*ec779b8eSAndroid Build Coastguard Worker // number of effects in this library
120*ec779b8eSAndroid Build Coastguard Worker const int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
121*ec779b8eSAndroid Build Coastguard Worker 
clamp_float(float value)122*ec779b8eSAndroid Build Coastguard Worker static inline float clamp_float(float value) {
123*ec779b8eSAndroid Build Coastguard Worker     return fmin(fmax(value, -1.f), 1.f);
124*ec779b8eSAndroid Build Coastguard Worker }
125*ec779b8eSAndroid Build Coastguard Worker 
126*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
127*ec779b8eSAndroid Build Coastguard Worker  * Test code
128*ec779b8eSAndroid Build Coastguard Worker  *--------------------------------------------------------------------------*/
129*ec779b8eSAndroid Build Coastguard Worker #ifdef DOWNMIX_TEST_CHANNEL_INDEX
130*ec779b8eSAndroid Build Coastguard Worker // strictly for testing, logs the indices of the channels for a given mask,
131*ec779b8eSAndroid Build Coastguard Worker // uses the same code as Downmix_foldGeneric()
Downmix_testIndexComputation(uint32_t mask)132*ec779b8eSAndroid Build Coastguard Worker void Downmix_testIndexComputation(uint32_t mask) {
133*ec779b8eSAndroid Build Coastguard Worker     ALOGI("Testing index computation for %#x:", mask);
134*ec779b8eSAndroid Build Coastguard Worker     // check against unsupported channels
135*ec779b8eSAndroid Build Coastguard Worker     if (mask & kUnsupported) {
136*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Unsupported channels (top or front left/right of center)");
137*ec779b8eSAndroid Build Coastguard Worker         return;
138*ec779b8eSAndroid Build Coastguard Worker     }
139*ec779b8eSAndroid Build Coastguard Worker     // verify has FL/FR
140*ec779b8eSAndroid Build Coastguard Worker     if ((mask & AUDIO_CHANNEL_OUT_STEREO) != AUDIO_CHANNEL_OUT_STEREO) {
141*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Front channels must be present");
142*ec779b8eSAndroid Build Coastguard Worker         return;
143*ec779b8eSAndroid Build Coastguard Worker     }
144*ec779b8eSAndroid Build Coastguard Worker     // verify uses SIDE as a pair (ok if not using SIDE at all)
145*ec779b8eSAndroid Build Coastguard Worker     bool hasSides = false;
146*ec779b8eSAndroid Build Coastguard Worker     if ((mask & kSides) != 0) {
147*ec779b8eSAndroid Build Coastguard Worker         if ((mask & kSides) != kSides) {
148*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Side channels must be used as a pair");
149*ec779b8eSAndroid Build Coastguard Worker             return;
150*ec779b8eSAndroid Build Coastguard Worker         }
151*ec779b8eSAndroid Build Coastguard Worker         hasSides = true;
152*ec779b8eSAndroid Build Coastguard Worker     }
153*ec779b8eSAndroid Build Coastguard Worker     // verify uses BACK as a pair (ok if not using BACK at all)
154*ec779b8eSAndroid Build Coastguard Worker     bool hasBacks = false;
155*ec779b8eSAndroid Build Coastguard Worker     if ((mask & kBacks) != 0) {
156*ec779b8eSAndroid Build Coastguard Worker         if ((mask & kBacks) != kBacks) {
157*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Back channels must be used as a pair");
158*ec779b8eSAndroid Build Coastguard Worker             return;
159*ec779b8eSAndroid Build Coastguard Worker         }
160*ec779b8eSAndroid Build Coastguard Worker         hasBacks = true;
161*ec779b8eSAndroid Build Coastguard Worker     }
162*ec779b8eSAndroid Build Coastguard Worker 
163*ec779b8eSAndroid Build Coastguard Worker     const int numChan = audio_channel_count_from_out_mask(mask);
164*ec779b8eSAndroid Build Coastguard Worker     const bool hasFC = ((mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) == AUDIO_CHANNEL_OUT_FRONT_CENTER);
165*ec779b8eSAndroid Build Coastguard Worker     const bool hasLFE =
166*ec779b8eSAndroid Build Coastguard Worker             ((mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) == AUDIO_CHANNEL_OUT_LOW_FREQUENCY);
167*ec779b8eSAndroid Build Coastguard Worker     const bool hasBC = ((mask & AUDIO_CHANNEL_OUT_BACK_CENTER) == AUDIO_CHANNEL_OUT_BACK_CENTER);
168*ec779b8eSAndroid Build Coastguard Worker     // compute at what index each channel is: samples will be in the following order:
169*ec779b8eSAndroid Build Coastguard Worker     //   FL FR FC LFE BL BR BC SL SR
170*ec779b8eSAndroid Build Coastguard Worker     // when a channel is not present, its index is set to the same as the index of the preceding
171*ec779b8eSAndroid Build Coastguard Worker     // channel
172*ec779b8eSAndroid Build Coastguard Worker     const int indexFC  = hasFC    ? 2            : 1;        // front center
173*ec779b8eSAndroid Build Coastguard Worker     const int indexLFE = hasLFE   ? indexFC + 1  : indexFC;  // low frequency
174*ec779b8eSAndroid Build Coastguard Worker     const int indexBL  = hasBacks ? indexLFE + 1 : indexLFE; // back left
175*ec779b8eSAndroid Build Coastguard Worker     const int indexBR  = hasBacks ? indexBL + 1  : indexBL;  // back right
176*ec779b8eSAndroid Build Coastguard Worker     const int indexBC  = hasBC    ? indexBR + 1  : indexBR;  // back center
177*ec779b8eSAndroid Build Coastguard Worker     const int indexSL  = hasSides ? indexBC + 1  : indexBC;  // side left
178*ec779b8eSAndroid Build Coastguard Worker     const int indexSR  = hasSides ? indexSL + 1  : indexSL;  // side right
179*ec779b8eSAndroid Build Coastguard Worker 
180*ec779b8eSAndroid Build Coastguard Worker     ALOGI("  FL FR FC LFE BL BR BC SL SR");
181*ec779b8eSAndroid Build Coastguard Worker     ALOGI("   %d  %d  %d   %d  %d  %d  %d  %d  %d",
182*ec779b8eSAndroid Build Coastguard Worker             0, 1, indexFC, indexLFE, indexBL, indexBR, indexBC, indexSL, indexSR);
183*ec779b8eSAndroid Build Coastguard Worker }
184*ec779b8eSAndroid Build Coastguard Worker #endif
185*ec779b8eSAndroid Build Coastguard Worker 
Downmix_validChannelMask(uint32_t mask)186*ec779b8eSAndroid Build Coastguard Worker static bool Downmix_validChannelMask(uint32_t mask)
187*ec779b8eSAndroid Build Coastguard Worker {
188*ec779b8eSAndroid Build Coastguard Worker     if (!mask) {
189*ec779b8eSAndroid Build Coastguard Worker         return false;
190*ec779b8eSAndroid Build Coastguard Worker     }
191*ec779b8eSAndroid Build Coastguard Worker     // check against unsupported channels (up to FCC_26)
192*ec779b8eSAndroid Build Coastguard Worker     constexpr uint32_t MAXIMUM_CHANNEL_MASK = AUDIO_CHANNEL_OUT_22POINT2
193*ec779b8eSAndroid Build Coastguard Worker             | AUDIO_CHANNEL_OUT_FRONT_WIDE_LEFT | AUDIO_CHANNEL_OUT_FRONT_WIDE_RIGHT;
194*ec779b8eSAndroid Build Coastguard Worker     if (mask & ~MAXIMUM_CHANNEL_MASK) {
195*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Unsupported channels in %#x", mask & ~MAXIMUM_CHANNEL_MASK);
196*ec779b8eSAndroid Build Coastguard Worker         return false;
197*ec779b8eSAndroid Build Coastguard Worker     }
198*ec779b8eSAndroid Build Coastguard Worker     return true;
199*ec779b8eSAndroid Build Coastguard Worker }
200*ec779b8eSAndroid Build Coastguard Worker 
201*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
202*ec779b8eSAndroid Build Coastguard Worker  * Effect API implementation
203*ec779b8eSAndroid Build Coastguard Worker  *--------------------------------------------------------------------------*/
204*ec779b8eSAndroid Build Coastguard Worker 
205*ec779b8eSAndroid Build Coastguard Worker /*--- Effect Library Interface Implementation ---*/
206*ec779b8eSAndroid Build Coastguard Worker 
DownmixLib_Create(const effect_uuid_t * uuid,int32_t,int32_t,effect_handle_t * pHandle)207*ec779b8eSAndroid Build Coastguard Worker static int32_t DownmixLib_Create(const effect_uuid_t *uuid,
208*ec779b8eSAndroid Build Coastguard Worker         int32_t /* sessionId */,
209*ec779b8eSAndroid Build Coastguard Worker         int32_t /* ioId */,
210*ec779b8eSAndroid Build Coastguard Worker         effect_handle_t *pHandle) {
211*ec779b8eSAndroid Build Coastguard Worker     int ret;
212*ec779b8eSAndroid Build Coastguard Worker     int i;
213*ec779b8eSAndroid Build Coastguard Worker     downmix_module_t *module;
214*ec779b8eSAndroid Build Coastguard Worker     const effect_descriptor_t *desc;
215*ec779b8eSAndroid Build Coastguard Worker 
216*ec779b8eSAndroid Build Coastguard Worker     ALOGV("DownmixLib_Create()");
217*ec779b8eSAndroid Build Coastguard Worker 
218*ec779b8eSAndroid Build Coastguard Worker #ifdef DOWNMIX_TEST_CHANNEL_INDEX
219*ec779b8eSAndroid Build Coastguard Worker     // should work (won't log an error)
220*ec779b8eSAndroid Build Coastguard Worker     ALOGI("DOWNMIX_TEST_CHANNEL_INDEX: should work:");
221*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT |
222*ec779b8eSAndroid Build Coastguard Worker                     AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_BACK_CENTER);
223*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_QUAD_SIDE | AUDIO_CHANNEL_OUT_QUAD_BACK);
224*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_5POINT1_SIDE | AUDIO_CHANNEL_OUT_BACK_CENTER);
225*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_5POINT1_BACK | AUDIO_CHANNEL_OUT_BACK_CENTER);
226*ec779b8eSAndroid Build Coastguard Worker     // shouldn't work (will log an error, won't display channel indices)
227*ec779b8eSAndroid Build Coastguard Worker     ALOGI("DOWNMIX_TEST_CHANNEL_INDEX: should NOT work:");
228*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT |
229*ec779b8eSAndroid Build Coastguard Worker                         AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_BACK_LEFT);
230*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT |
231*ec779b8eSAndroid Build Coastguard Worker                             AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_SIDE_LEFT);
232*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT |
233*ec779b8eSAndroid Build Coastguard Worker                         AUDIO_CHANNEL_OUT_BACK_LEFT | AUDIO_CHANNEL_OUT_BACK_RIGHT);
234*ec779b8eSAndroid Build Coastguard Worker     Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT |
235*ec779b8eSAndroid Build Coastguard Worker                             AUDIO_CHANNEL_OUT_SIDE_LEFT | AUDIO_CHANNEL_OUT_SIDE_RIGHT);
236*ec779b8eSAndroid Build Coastguard Worker #endif
237*ec779b8eSAndroid Build Coastguard Worker 
238*ec779b8eSAndroid Build Coastguard Worker     if (pHandle == NULL || uuid == NULL) {
239*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
240*ec779b8eSAndroid Build Coastguard Worker     }
241*ec779b8eSAndroid Build Coastguard Worker 
242*ec779b8eSAndroid Build Coastguard Worker     for (i = 0 ; i < kNbEffects ; i++) {
243*ec779b8eSAndroid Build Coastguard Worker         desc = gDescriptors[i];
244*ec779b8eSAndroid Build Coastguard Worker         if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t)) == 0) {
245*ec779b8eSAndroid Build Coastguard Worker             break;
246*ec779b8eSAndroid Build Coastguard Worker         }
247*ec779b8eSAndroid Build Coastguard Worker     }
248*ec779b8eSAndroid Build Coastguard Worker 
249*ec779b8eSAndroid Build Coastguard Worker     if (i == kNbEffects) {
250*ec779b8eSAndroid Build Coastguard Worker         return -ENOENT;
251*ec779b8eSAndroid Build Coastguard Worker     }
252*ec779b8eSAndroid Build Coastguard Worker 
253*ec779b8eSAndroid Build Coastguard Worker     module = new downmix_module_t{};
254*ec779b8eSAndroid Build Coastguard Worker 
255*ec779b8eSAndroid Build Coastguard Worker     module->itfe = &gDownmixInterface;
256*ec779b8eSAndroid Build Coastguard Worker 
257*ec779b8eSAndroid Build Coastguard Worker     module->context.state = DOWNMIX_STATE_UNINITIALIZED;
258*ec779b8eSAndroid Build Coastguard Worker 
259*ec779b8eSAndroid Build Coastguard Worker     ret = Downmix_Init(module);
260*ec779b8eSAndroid Build Coastguard Worker     if (ret < 0) {
261*ec779b8eSAndroid Build Coastguard Worker         ALOGW("DownmixLib_Create() init failed");
262*ec779b8eSAndroid Build Coastguard Worker         delete module;
263*ec779b8eSAndroid Build Coastguard Worker         return ret;
264*ec779b8eSAndroid Build Coastguard Worker     }
265*ec779b8eSAndroid Build Coastguard Worker 
266*ec779b8eSAndroid Build Coastguard Worker     *pHandle = (effect_handle_t) module;
267*ec779b8eSAndroid Build Coastguard Worker 
268*ec779b8eSAndroid Build Coastguard Worker     ALOGV("DownmixLib_Create() %p , size %zu", module, sizeof(downmix_module_t));
269*ec779b8eSAndroid Build Coastguard Worker 
270*ec779b8eSAndroid Build Coastguard Worker     return 0;
271*ec779b8eSAndroid Build Coastguard Worker }
272*ec779b8eSAndroid Build Coastguard Worker 
DownmixLib_Release(effect_handle_t handle)273*ec779b8eSAndroid Build Coastguard Worker static int32_t DownmixLib_Release(effect_handle_t handle) {
274*ec779b8eSAndroid Build Coastguard Worker     downmix_module_t *pDwmModule = (downmix_module_t *)handle;
275*ec779b8eSAndroid Build Coastguard Worker 
276*ec779b8eSAndroid Build Coastguard Worker     ALOGV("DownmixLib_Release() %p", handle);
277*ec779b8eSAndroid Build Coastguard Worker     if (handle == NULL) {
278*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
279*ec779b8eSAndroid Build Coastguard Worker     }
280*ec779b8eSAndroid Build Coastguard Worker 
281*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->context.state = DOWNMIX_STATE_UNINITIALIZED;
282*ec779b8eSAndroid Build Coastguard Worker 
283*ec779b8eSAndroid Build Coastguard Worker     delete pDwmModule;
284*ec779b8eSAndroid Build Coastguard Worker     return 0;
285*ec779b8eSAndroid Build Coastguard Worker }
286*ec779b8eSAndroid Build Coastguard Worker 
DownmixLib_GetDescriptor(const effect_uuid_t * uuid,effect_descriptor_t * pDescriptor)287*ec779b8eSAndroid Build Coastguard Worker static int32_t DownmixLib_GetDescriptor(
288*ec779b8eSAndroid Build Coastguard Worker         const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
289*ec779b8eSAndroid Build Coastguard Worker     ALOGV("DownmixLib_GetDescriptor()");
290*ec779b8eSAndroid Build Coastguard Worker     int i;
291*ec779b8eSAndroid Build Coastguard Worker 
292*ec779b8eSAndroid Build Coastguard Worker     if (pDescriptor == NULL || uuid == NULL){
293*ec779b8eSAndroid Build Coastguard Worker         ALOGE("DownmixLib_Create() called with NULL pointer");
294*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
295*ec779b8eSAndroid Build Coastguard Worker     }
296*ec779b8eSAndroid Build Coastguard Worker     ALOGV("DownmixLib_GetDescriptor() nb effects=%d", kNbEffects);
297*ec779b8eSAndroid Build Coastguard Worker     for (i = 0; i < kNbEffects; i++) {
298*ec779b8eSAndroid Build Coastguard Worker         ALOGV("DownmixLib_GetDescriptor() i=%d", i);
299*ec779b8eSAndroid Build Coastguard Worker         if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
300*ec779b8eSAndroid Build Coastguard Worker             memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
301*ec779b8eSAndroid Build Coastguard Worker             ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %#x",
302*ec779b8eSAndroid Build Coastguard Worker                  i, gDescriptors[i]->uuid.timeLow);
303*ec779b8eSAndroid Build Coastguard Worker             return 0;
304*ec779b8eSAndroid Build Coastguard Worker         }
305*ec779b8eSAndroid Build Coastguard Worker     }
306*ec779b8eSAndroid Build Coastguard Worker 
307*ec779b8eSAndroid Build Coastguard Worker     return -EINVAL;
308*ec779b8eSAndroid Build Coastguard Worker }
309*ec779b8eSAndroid Build Coastguard Worker 
310*ec779b8eSAndroid Build Coastguard Worker /*--- Effect Control Interface Implementation ---*/
311*ec779b8eSAndroid Build Coastguard Worker 
Downmix_Process(effect_handle_t self,audio_buffer_t * inBuffer,audio_buffer_t * outBuffer)312*ec779b8eSAndroid Build Coastguard Worker static int32_t Downmix_Process(effect_handle_t self,
313*ec779b8eSAndroid Build Coastguard Worker         audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
314*ec779b8eSAndroid Build Coastguard Worker 
315*ec779b8eSAndroid Build Coastguard Worker     downmix_object_t *pDownmixer;
316*ec779b8eSAndroid Build Coastguard Worker     const float *pSrc;
317*ec779b8eSAndroid Build Coastguard Worker     float *pDst;
318*ec779b8eSAndroid Build Coastguard Worker     downmix_module_t *pDwmModule = (downmix_module_t *)self;
319*ec779b8eSAndroid Build Coastguard Worker 
320*ec779b8eSAndroid Build Coastguard Worker     if (pDwmModule == NULL) {
321*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
322*ec779b8eSAndroid Build Coastguard Worker     }
323*ec779b8eSAndroid Build Coastguard Worker 
324*ec779b8eSAndroid Build Coastguard Worker     if (inBuffer == NULL || inBuffer->raw == NULL ||
325*ec779b8eSAndroid Build Coastguard Worker         outBuffer == NULL || outBuffer->raw == NULL ||
326*ec779b8eSAndroid Build Coastguard Worker         inBuffer->frameCount != outBuffer->frameCount) {
327*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
328*ec779b8eSAndroid Build Coastguard Worker     }
329*ec779b8eSAndroid Build Coastguard Worker 
330*ec779b8eSAndroid Build Coastguard Worker     pDownmixer = (downmix_object_t*) &pDwmModule->context;
331*ec779b8eSAndroid Build Coastguard Worker 
332*ec779b8eSAndroid Build Coastguard Worker     if (pDownmixer->state == DOWNMIX_STATE_UNINITIALIZED) {
333*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Downmix_Process error: trying to use an uninitialized downmixer");
334*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
335*ec779b8eSAndroid Build Coastguard Worker     } else if (pDownmixer->state == DOWNMIX_STATE_INITIALIZED) {
336*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Downmix_Process error: trying to use a non-configured downmixer");
337*ec779b8eSAndroid Build Coastguard Worker         return -ENODATA;
338*ec779b8eSAndroid Build Coastguard Worker     }
339*ec779b8eSAndroid Build Coastguard Worker 
340*ec779b8eSAndroid Build Coastguard Worker     pSrc = inBuffer->f32;
341*ec779b8eSAndroid Build Coastguard Worker     pDst = outBuffer->f32;
342*ec779b8eSAndroid Build Coastguard Worker     size_t numFrames = outBuffer->frameCount;
343*ec779b8eSAndroid Build Coastguard Worker 
344*ec779b8eSAndroid Build Coastguard Worker     const bool accumulate =
345*ec779b8eSAndroid Build Coastguard Worker             (pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
346*ec779b8eSAndroid Build Coastguard Worker     const audio_channel_mask_t downmixInputChannelMask =
347*ec779b8eSAndroid Build Coastguard Worker             (audio_channel_mask_t)pDwmModule->config.inputCfg.channels;
348*ec779b8eSAndroid Build Coastguard Worker 
349*ec779b8eSAndroid Build Coastguard Worker     switch(pDownmixer->type) {
350*ec779b8eSAndroid Build Coastguard Worker 
351*ec779b8eSAndroid Build Coastguard Worker       case DOWNMIX_TYPE_STRIP:
352*ec779b8eSAndroid Build Coastguard Worker           if (accumulate) {
353*ec779b8eSAndroid Build Coastguard Worker               while (numFrames) {
354*ec779b8eSAndroid Build Coastguard Worker                   pDst[0] = clamp_float(pDst[0] + pSrc[0]);
355*ec779b8eSAndroid Build Coastguard Worker                   pDst[1] = clamp_float(pDst[1] + pSrc[1]);
356*ec779b8eSAndroid Build Coastguard Worker                   pSrc += pDownmixer->input_channel_count;
357*ec779b8eSAndroid Build Coastguard Worker                   pDst += 2;
358*ec779b8eSAndroid Build Coastguard Worker                   numFrames--;
359*ec779b8eSAndroid Build Coastguard Worker               }
360*ec779b8eSAndroid Build Coastguard Worker           } else {
361*ec779b8eSAndroid Build Coastguard Worker               while (numFrames) {
362*ec779b8eSAndroid Build Coastguard Worker                   pDst[0] = pSrc[0];
363*ec779b8eSAndroid Build Coastguard Worker                   pDst[1] = pSrc[1];
364*ec779b8eSAndroid Build Coastguard Worker                   pSrc += pDownmixer->input_channel_count;
365*ec779b8eSAndroid Build Coastguard Worker                   pDst += 2;
366*ec779b8eSAndroid Build Coastguard Worker                   numFrames--;
367*ec779b8eSAndroid Build Coastguard Worker               }
368*ec779b8eSAndroid Build Coastguard Worker           }
369*ec779b8eSAndroid Build Coastguard Worker           break;
370*ec779b8eSAndroid Build Coastguard Worker 
371*ec779b8eSAndroid Build Coastguard Worker       case DOWNMIX_TYPE_FOLD: {
372*ec779b8eSAndroid Build Coastguard Worker             if (!pDownmixer->channelMix.process(
373*ec779b8eSAndroid Build Coastguard Worker                     pSrc, pDst, numFrames, accumulate, downmixInputChannelMask)) {
374*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Multichannel configuration %#x is not supported",
375*ec779b8eSAndroid Build Coastguard Worker                       downmixInputChannelMask);
376*ec779b8eSAndroid Build Coastguard Worker                 return -EINVAL;
377*ec779b8eSAndroid Build Coastguard Worker             }
378*ec779b8eSAndroid Build Coastguard Worker         }
379*ec779b8eSAndroid Build Coastguard Worker         break;
380*ec779b8eSAndroid Build Coastguard Worker 
381*ec779b8eSAndroid Build Coastguard Worker       default:
382*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
383*ec779b8eSAndroid Build Coastguard Worker     }
384*ec779b8eSAndroid Build Coastguard Worker 
385*ec779b8eSAndroid Build Coastguard Worker     return 0;
386*ec779b8eSAndroid Build Coastguard Worker }
387*ec779b8eSAndroid Build Coastguard Worker 
Downmix_Command(effect_handle_t self,uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)388*ec779b8eSAndroid Build Coastguard Worker static int32_t Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
389*ec779b8eSAndroid Build Coastguard Worker         void *pCmdData, uint32_t *replySize, void *pReplyData) {
390*ec779b8eSAndroid Build Coastguard Worker 
391*ec779b8eSAndroid Build Coastguard Worker     downmix_module_t *pDwmModule = (downmix_module_t *) self;
392*ec779b8eSAndroid Build Coastguard Worker     downmix_object_t *pDownmixer;
393*ec779b8eSAndroid Build Coastguard Worker 
394*ec779b8eSAndroid Build Coastguard Worker     if (pDwmModule == NULL || pDwmModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
395*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
396*ec779b8eSAndroid Build Coastguard Worker     }
397*ec779b8eSAndroid Build Coastguard Worker 
398*ec779b8eSAndroid Build Coastguard Worker     pDownmixer = (downmix_object_t*) &pDwmModule->context;
399*ec779b8eSAndroid Build Coastguard Worker 
400*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Downmix_Command command %u cmdSize %u", cmdCode, cmdSize);
401*ec779b8eSAndroid Build Coastguard Worker 
402*ec779b8eSAndroid Build Coastguard Worker     switch (cmdCode) {
403*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_INIT:
404*ec779b8eSAndroid Build Coastguard Worker         if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
405*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
406*ec779b8eSAndroid Build Coastguard Worker         }
407*ec779b8eSAndroid Build Coastguard Worker         *(int *) pReplyData = Downmix_Init(pDwmModule);
408*ec779b8eSAndroid Build Coastguard Worker         break;
409*ec779b8eSAndroid Build Coastguard Worker 
410*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_CONFIG:
411*ec779b8eSAndroid Build Coastguard Worker         if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
412*ec779b8eSAndroid Build Coastguard Worker                 || pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
413*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
414*ec779b8eSAndroid Build Coastguard Worker         }
415*ec779b8eSAndroid Build Coastguard Worker         *(int *) pReplyData = Downmix_Configure(pDwmModule,
416*ec779b8eSAndroid Build Coastguard Worker                 (effect_config_t *)pCmdData, false);
417*ec779b8eSAndroid Build Coastguard Worker         break;
418*ec779b8eSAndroid Build Coastguard Worker 
419*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_RESET:
420*ec779b8eSAndroid Build Coastguard Worker         Downmix_Reset(pDownmixer, false);
421*ec779b8eSAndroid Build Coastguard Worker         break;
422*ec779b8eSAndroid Build Coastguard Worker 
423*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_GET_PARAM: {
424*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %u, pReplyData: %p",
425*ec779b8eSAndroid Build Coastguard Worker                 pCmdData, *replySize, pReplyData);
426*ec779b8eSAndroid Build Coastguard Worker         if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
427*ec779b8eSAndroid Build Coastguard Worker                 pReplyData == NULL || replySize == NULL ||
428*ec779b8eSAndroid Build Coastguard Worker                 *replySize < (int) sizeof(effect_param_t) + 2 * sizeof(int32_t)) {
429*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
430*ec779b8eSAndroid Build Coastguard Worker         }
431*ec779b8eSAndroid Build Coastguard Worker         effect_param_t *rep = (effect_param_t *) pReplyData;
432*ec779b8eSAndroid Build Coastguard Worker         memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
433*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %d, replySize %u",
434*ec779b8eSAndroid Build Coastguard Worker                 *(int32_t *)rep->data, rep->vsize);
435*ec779b8eSAndroid Build Coastguard Worker         rep->status = Downmix_getParameter(pDownmixer, *(int32_t *)rep->data, &rep->vsize,
436*ec779b8eSAndroid Build Coastguard Worker                 rep->data + sizeof(int32_t));
437*ec779b8eSAndroid Build Coastguard Worker         *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize;
438*ec779b8eSAndroid Build Coastguard Worker         break;
439*ec779b8eSAndroid Build Coastguard Worker     }
440*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_PARAM: {
441*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %u"
442*ec779b8eSAndroid Build Coastguard Worker                 ", pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
443*ec779b8eSAndroid Build Coastguard Worker         if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
444*ec779b8eSAndroid Build Coastguard Worker                 || pReplyData == NULL || replySize == NULL || *replySize != (int)sizeof(int32_t)) {
445*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
446*ec779b8eSAndroid Build Coastguard Worker         }
447*ec779b8eSAndroid Build Coastguard Worker         effect_param_t *cmd = (effect_param_t *) pCmdData;
448*ec779b8eSAndroid Build Coastguard Worker         if (cmd->psize != sizeof(int32_t)) {
449*ec779b8eSAndroid Build Coastguard Worker             android_errorWriteLog(0x534e4554, "63662938");
450*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
451*ec779b8eSAndroid Build Coastguard Worker         }
452*ec779b8eSAndroid Build Coastguard Worker         *(int *)pReplyData = Downmix_setParameter(pDownmixer, *(int32_t *)cmd->data,
453*ec779b8eSAndroid Build Coastguard Worker                 cmd->vsize, cmd->data + sizeof(int32_t));
454*ec779b8eSAndroid Build Coastguard Worker         break;
455*ec779b8eSAndroid Build Coastguard Worker     }
456*ec779b8eSAndroid Build Coastguard Worker 
457*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_PARAM_DEFERRED:
458*ec779b8eSAndroid Build Coastguard Worker         //FIXME implement
459*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_DEFERRED not supported, FIXME");
460*ec779b8eSAndroid Build Coastguard Worker         break;
461*ec779b8eSAndroid Build Coastguard Worker 
462*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_PARAM_COMMIT:
463*ec779b8eSAndroid Build Coastguard Worker         //FIXME implement
464*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_COMMIT not supported, FIXME");
465*ec779b8eSAndroid Build Coastguard Worker         break;
466*ec779b8eSAndroid Build Coastguard Worker 
467*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_ENABLE:
468*ec779b8eSAndroid Build Coastguard Worker         if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
469*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
470*ec779b8eSAndroid Build Coastguard Worker         }
471*ec779b8eSAndroid Build Coastguard Worker         if (pDownmixer->state != DOWNMIX_STATE_INITIALIZED) {
472*ec779b8eSAndroid Build Coastguard Worker             return -ENOSYS;
473*ec779b8eSAndroid Build Coastguard Worker         }
474*ec779b8eSAndroid Build Coastguard Worker         pDownmixer->state = DOWNMIX_STATE_ACTIVE;
475*ec779b8eSAndroid Build Coastguard Worker         ALOGV("EFFECT_CMD_ENABLE() OK");
476*ec779b8eSAndroid Build Coastguard Worker         *(int *)pReplyData = 0;
477*ec779b8eSAndroid Build Coastguard Worker         break;
478*ec779b8eSAndroid Build Coastguard Worker 
479*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_DISABLE:
480*ec779b8eSAndroid Build Coastguard Worker         if (pReplyData == NULL || replySize == NULL || *replySize != sizeof(int)) {
481*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
482*ec779b8eSAndroid Build Coastguard Worker         }
483*ec779b8eSAndroid Build Coastguard Worker         if (pDownmixer->state != DOWNMIX_STATE_ACTIVE) {
484*ec779b8eSAndroid Build Coastguard Worker             return -ENOSYS;
485*ec779b8eSAndroid Build Coastguard Worker         }
486*ec779b8eSAndroid Build Coastguard Worker         pDownmixer->state = DOWNMIX_STATE_INITIALIZED;
487*ec779b8eSAndroid Build Coastguard Worker         ALOGV("EFFECT_CMD_DISABLE() OK");
488*ec779b8eSAndroid Build Coastguard Worker         *(int *)pReplyData = 0;
489*ec779b8eSAndroid Build Coastguard Worker         break;
490*ec779b8eSAndroid Build Coastguard Worker 
491*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_DEVICE:
492*ec779b8eSAndroid Build Coastguard Worker         if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
493*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
494*ec779b8eSAndroid Build Coastguard Worker         }
495*ec779b8eSAndroid Build Coastguard Worker         // FIXME change type if playing on headset vs speaker
496*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: %#x", *(uint32_t *)pCmdData);
497*ec779b8eSAndroid Build Coastguard Worker         break;
498*ec779b8eSAndroid Build Coastguard Worker 
499*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_VOLUME: {
500*ec779b8eSAndroid Build Coastguard Worker         // audio output is always stereo => 2 channel volumes
501*ec779b8eSAndroid Build Coastguard Worker         if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) {
502*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
503*ec779b8eSAndroid Build Coastguard Worker         }
504*ec779b8eSAndroid Build Coastguard Worker         // FIXME change volume
505*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Downmix_Command command EFFECT_CMD_SET_VOLUME not supported, FIXME");
506*ec779b8eSAndroid Build Coastguard Worker         float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
507*ec779b8eSAndroid Build Coastguard Worker         float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
508*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Downmix_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right);
509*ec779b8eSAndroid Build Coastguard Worker         break;
510*ec779b8eSAndroid Build Coastguard Worker     }
511*ec779b8eSAndroid Build Coastguard Worker 
512*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_AUDIO_MODE:
513*ec779b8eSAndroid Build Coastguard Worker         if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
514*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
515*ec779b8eSAndroid Build Coastguard Worker         }
516*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %u", *(uint32_t *)pCmdData);
517*ec779b8eSAndroid Build Coastguard Worker         break;
518*ec779b8eSAndroid Build Coastguard Worker 
519*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_CONFIG_REVERSE:
520*ec779b8eSAndroid Build Coastguard Worker     case EFFECT_CMD_SET_INPUT_DEVICE:
521*ec779b8eSAndroid Build Coastguard Worker         // these commands are ignored by a downmix effect
522*ec779b8eSAndroid Build Coastguard Worker         break;
523*ec779b8eSAndroid Build Coastguard Worker 
524*ec779b8eSAndroid Build Coastguard Worker     default:
525*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Downmix_Command invalid command %u", cmdCode);
526*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
527*ec779b8eSAndroid Build Coastguard Worker     }
528*ec779b8eSAndroid Build Coastguard Worker 
529*ec779b8eSAndroid Build Coastguard Worker     return 0;
530*ec779b8eSAndroid Build Coastguard Worker }
531*ec779b8eSAndroid Build Coastguard Worker 
Downmix_GetDescriptor(effect_handle_t self,effect_descriptor_t * pDescriptor)532*ec779b8eSAndroid Build Coastguard Worker static int32_t Downmix_GetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor)
533*ec779b8eSAndroid Build Coastguard Worker {
534*ec779b8eSAndroid Build Coastguard Worker     downmix_module_t *pDwnmxModule = (downmix_module_t *) self;
535*ec779b8eSAndroid Build Coastguard Worker 
536*ec779b8eSAndroid Build Coastguard Worker     if (pDwnmxModule == NULL ||
537*ec779b8eSAndroid Build Coastguard Worker             pDwnmxModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
538*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
539*ec779b8eSAndroid Build Coastguard Worker     }
540*ec779b8eSAndroid Build Coastguard Worker 
541*ec779b8eSAndroid Build Coastguard Worker     memcpy(pDescriptor, &gDownmixDescriptor, sizeof(effect_descriptor_t));
542*ec779b8eSAndroid Build Coastguard Worker 
543*ec779b8eSAndroid Build Coastguard Worker     return 0;
544*ec779b8eSAndroid Build Coastguard Worker }
545*ec779b8eSAndroid Build Coastguard Worker 
546*ec779b8eSAndroid Build Coastguard Worker 
547*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
548*ec779b8eSAndroid Build Coastguard Worker  * Downmix internal functions
549*ec779b8eSAndroid Build Coastguard Worker  *--------------------------------------------------------------------------*/
550*ec779b8eSAndroid Build Coastguard Worker 
551*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
552*ec779b8eSAndroid Build Coastguard Worker  * Downmix_Init()
553*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
554*ec779b8eSAndroid Build Coastguard Worker  * Purpose:
555*ec779b8eSAndroid Build Coastguard Worker  * Initialize downmix context and apply default parameters
556*ec779b8eSAndroid Build Coastguard Worker  *
557*ec779b8eSAndroid Build Coastguard Worker  * Inputs:
558*ec779b8eSAndroid Build Coastguard Worker  *  pDwmModule    pointer to downmix effect module
559*ec779b8eSAndroid Build Coastguard Worker  *
560*ec779b8eSAndroid Build Coastguard Worker  * Outputs:
561*ec779b8eSAndroid Build Coastguard Worker  *
562*ec779b8eSAndroid Build Coastguard Worker  * Returns:
563*ec779b8eSAndroid Build Coastguard Worker  *  0             indicates success
564*ec779b8eSAndroid Build Coastguard Worker  *
565*ec779b8eSAndroid Build Coastguard Worker  * Side Effects:
566*ec779b8eSAndroid Build Coastguard Worker  *  updates:
567*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->context.type
568*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->context.apply_volume_correction
569*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->config.inputCfg
570*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->config.outputCfg
571*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->config.inputCfg.samplingRate
572*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->config.outputCfg.samplingRate
573*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->context.state
574*ec779b8eSAndroid Build Coastguard Worker  *  doesn't set:
575*ec779b8eSAndroid Build Coastguard Worker  *           pDwmModule->itfe
576*ec779b8eSAndroid Build Coastguard Worker  *
577*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
578*ec779b8eSAndroid Build Coastguard Worker  */
579*ec779b8eSAndroid Build Coastguard Worker 
Downmix_Init(downmix_module_t * pDwmModule)580*ec779b8eSAndroid Build Coastguard Worker static int Downmix_Init(downmix_module_t *pDwmModule) {
581*ec779b8eSAndroid Build Coastguard Worker 
582*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Downmix_Init module %p", pDwmModule);
583*ec779b8eSAndroid Build Coastguard Worker     int ret = 0;
584*ec779b8eSAndroid Build Coastguard Worker 
585*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->context = downmix_object_t{};  // zero initialize (contains class with vtable).
586*ec779b8eSAndroid Build Coastguard Worker 
587*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
588*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
589*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
590*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.bufferProvider.getBuffer = NULL;
591*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
592*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.bufferProvider.cookie = NULL;
593*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
594*ec779b8eSAndroid Build Coastguard Worker 
595*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.inputCfg.samplingRate = 44100;
596*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.samplingRate = pDwmModule->config.inputCfg.samplingRate;
597*ec779b8eSAndroid Build Coastguard Worker 
598*ec779b8eSAndroid Build Coastguard Worker     // set a default value for the access mode, but should be overwritten by caller
599*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
600*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
601*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
602*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.bufferProvider.getBuffer = NULL;
603*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
604*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.bufferProvider.cookie = NULL;
605*ec779b8eSAndroid Build Coastguard Worker     pDwmModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
606*ec779b8eSAndroid Build Coastguard Worker 
607*ec779b8eSAndroid Build Coastguard Worker     ret = Downmix_Configure(pDwmModule, &pDwmModule->config, true);
608*ec779b8eSAndroid Build Coastguard Worker     if (ret != 0) {
609*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Downmix_Init error %d on module %p", ret, pDwmModule);
610*ec779b8eSAndroid Build Coastguard Worker     } else {
611*ec779b8eSAndroid Build Coastguard Worker         pDwmModule->context.state = DOWNMIX_STATE_INITIALIZED;
612*ec779b8eSAndroid Build Coastguard Worker     }
613*ec779b8eSAndroid Build Coastguard Worker 
614*ec779b8eSAndroid Build Coastguard Worker     return ret;
615*ec779b8eSAndroid Build Coastguard Worker }
616*ec779b8eSAndroid Build Coastguard Worker 
617*ec779b8eSAndroid Build Coastguard Worker 
618*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
619*ec779b8eSAndroid Build Coastguard Worker  * Downmix_Configure()
620*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
621*ec779b8eSAndroid Build Coastguard Worker  * Purpose:
622*ec779b8eSAndroid Build Coastguard Worker  *  Set input and output audio configuration.
623*ec779b8eSAndroid Build Coastguard Worker  *
624*ec779b8eSAndroid Build Coastguard Worker  * Inputs:
625*ec779b8eSAndroid Build Coastguard Worker  *  pDwmModule  pointer to downmix effect module
626*ec779b8eSAndroid Build Coastguard Worker  *  pConfig     pointer to effect_config_t structure containing input
627*ec779b8eSAndroid Build Coastguard Worker  *                  and output audio parameters configuration
628*ec779b8eSAndroid Build Coastguard Worker  *  init        true if called from init function
629*ec779b8eSAndroid Build Coastguard Worker  *
630*ec779b8eSAndroid Build Coastguard Worker  * Outputs:
631*ec779b8eSAndroid Build Coastguard Worker  *
632*ec779b8eSAndroid Build Coastguard Worker  * Returns:
633*ec779b8eSAndroid Build Coastguard Worker  *  0           indicates success
634*ec779b8eSAndroid Build Coastguard Worker  *
635*ec779b8eSAndroid Build Coastguard Worker  * Side Effects:
636*ec779b8eSAndroid Build Coastguard Worker  *
637*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
638*ec779b8eSAndroid Build Coastguard Worker  */
639*ec779b8eSAndroid Build Coastguard Worker 
Downmix_Configure(downmix_module_t * pDwmModule,effect_config_t * pConfig,bool init)640*ec779b8eSAndroid Build Coastguard Worker static int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init) {
641*ec779b8eSAndroid Build Coastguard Worker 
642*ec779b8eSAndroid Build Coastguard Worker     downmix_object_t *pDownmixer = &pDwmModule->context;
643*ec779b8eSAndroid Build Coastguard Worker 
644*ec779b8eSAndroid Build Coastguard Worker     // Check configuration compatibility with build options, and effect capabilities
645*ec779b8eSAndroid Build Coastguard Worker     if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate
646*ec779b8eSAndroid Build Coastguard Worker         || pConfig->outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
647*ec779b8eSAndroid Build Coastguard Worker         || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_FLOAT
648*ec779b8eSAndroid Build Coastguard Worker         || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_FLOAT) {
649*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Downmix_Configure error: invalid config");
650*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
651*ec779b8eSAndroid Build Coastguard Worker     }
652*ec779b8eSAndroid Build Coastguard Worker     // when configuring the effect, do not allow a blank or unsupported channel mask
653*ec779b8eSAndroid Build Coastguard Worker     if (!Downmix_validChannelMask(pConfig->inputCfg.channels)) {
654*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Downmix_Configure error: input channel mask(0x%x) not supported",
655*ec779b8eSAndroid Build Coastguard Worker                                                     pConfig->inputCfg.channels);
656*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
657*ec779b8eSAndroid Build Coastguard Worker     }
658*ec779b8eSAndroid Build Coastguard Worker 
659*ec779b8eSAndroid Build Coastguard Worker     if (&pDwmModule->config != pConfig) {
660*ec779b8eSAndroid Build Coastguard Worker         memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t));
661*ec779b8eSAndroid Build Coastguard Worker     }
662*ec779b8eSAndroid Build Coastguard Worker 
663*ec779b8eSAndroid Build Coastguard Worker     if (init) {
664*ec779b8eSAndroid Build Coastguard Worker         pDownmixer->type = DOWNMIX_TYPE_FOLD;
665*ec779b8eSAndroid Build Coastguard Worker         pDownmixer->apply_volume_correction = false;
666*ec779b8eSAndroid Build Coastguard Worker         pDownmixer->input_channel_count = 8; // matches default input of AUDIO_CHANNEL_OUT_7POINT1
667*ec779b8eSAndroid Build Coastguard Worker     } else {
668*ec779b8eSAndroid Build Coastguard Worker         pDownmixer->input_channel_count =
669*ec779b8eSAndroid Build Coastguard Worker                 audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
670*ec779b8eSAndroid Build Coastguard Worker     }
671*ec779b8eSAndroid Build Coastguard Worker 
672*ec779b8eSAndroid Build Coastguard Worker     Downmix_Reset(pDownmixer, init);
673*ec779b8eSAndroid Build Coastguard Worker 
674*ec779b8eSAndroid Build Coastguard Worker     return 0;
675*ec779b8eSAndroid Build Coastguard Worker }
676*ec779b8eSAndroid Build Coastguard Worker 
677*ec779b8eSAndroid Build Coastguard Worker 
678*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
679*ec779b8eSAndroid Build Coastguard Worker  * Downmix_Reset()
680*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
681*ec779b8eSAndroid Build Coastguard Worker  * Purpose:
682*ec779b8eSAndroid Build Coastguard Worker  *  Reset internal states.
683*ec779b8eSAndroid Build Coastguard Worker  *
684*ec779b8eSAndroid Build Coastguard Worker  * Inputs:
685*ec779b8eSAndroid Build Coastguard Worker  *  pDownmixer   pointer to downmix context
686*ec779b8eSAndroid Build Coastguard Worker  *  init         true if called from init function
687*ec779b8eSAndroid Build Coastguard Worker  *
688*ec779b8eSAndroid Build Coastguard Worker  * Outputs:
689*ec779b8eSAndroid Build Coastguard Worker *
690*ec779b8eSAndroid Build Coastguard Worker  * Returns:
691*ec779b8eSAndroid Build Coastguard Worker  *  0            indicates success
692*ec779b8eSAndroid Build Coastguard Worker  *
693*ec779b8eSAndroid Build Coastguard Worker  * Side Effects:
694*ec779b8eSAndroid Build Coastguard Worker  *
695*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
696*ec779b8eSAndroid Build Coastguard Worker  */
697*ec779b8eSAndroid Build Coastguard Worker 
Downmix_Reset(downmix_object_t *,bool)698*ec779b8eSAndroid Build Coastguard Worker static int Downmix_Reset(downmix_object_t* /* pDownmixer */, bool /* init */) {
699*ec779b8eSAndroid Build Coastguard Worker     // nothing to do here
700*ec779b8eSAndroid Build Coastguard Worker     return 0;
701*ec779b8eSAndroid Build Coastguard Worker }
702*ec779b8eSAndroid Build Coastguard Worker 
703*ec779b8eSAndroid Build Coastguard Worker 
704*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
705*ec779b8eSAndroid Build Coastguard Worker  * Downmix_setParameter()
706*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
707*ec779b8eSAndroid Build Coastguard Worker  * Purpose:
708*ec779b8eSAndroid Build Coastguard Worker  * Set a Downmix parameter
709*ec779b8eSAndroid Build Coastguard Worker  *
710*ec779b8eSAndroid Build Coastguard Worker  * Inputs:
711*ec779b8eSAndroid Build Coastguard Worker  *  pDownmixer    handle to instance data
712*ec779b8eSAndroid Build Coastguard Worker  *  param         parameter
713*ec779b8eSAndroid Build Coastguard Worker  *  pValue        pointer to parameter value
714*ec779b8eSAndroid Build Coastguard Worker  *  size          value size
715*ec779b8eSAndroid Build Coastguard Worker  *
716*ec779b8eSAndroid Build Coastguard Worker  * Outputs:
717*ec779b8eSAndroid Build Coastguard Worker  *
718*ec779b8eSAndroid Build Coastguard Worker  * Returns:
719*ec779b8eSAndroid Build Coastguard Worker  *  0             indicates success
720*ec779b8eSAndroid Build Coastguard Worker  *
721*ec779b8eSAndroid Build Coastguard Worker  * Side Effects:
722*ec779b8eSAndroid Build Coastguard Worker  *
723*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
724*ec779b8eSAndroid Build Coastguard Worker  */
Downmix_setParameter(downmix_object_t * pDownmixer,int32_t param,uint32_t size,void * pValue)725*ec779b8eSAndroid Build Coastguard Worker static int Downmix_setParameter(
726*ec779b8eSAndroid Build Coastguard Worker         downmix_object_t *pDownmixer, int32_t param, uint32_t size, void *pValue) {
727*ec779b8eSAndroid Build Coastguard Worker 
728*ec779b8eSAndroid Build Coastguard Worker     int16_t value16;
729*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d",
730*ec779b8eSAndroid Build Coastguard Worker             pDownmixer, param, *(int16_t *)pValue, *(int32_t *)pValue);
731*ec779b8eSAndroid Build Coastguard Worker 
732*ec779b8eSAndroid Build Coastguard Worker     switch (param) {
733*ec779b8eSAndroid Build Coastguard Worker 
734*ec779b8eSAndroid Build Coastguard Worker       case DOWNMIX_PARAM_TYPE:
735*ec779b8eSAndroid Build Coastguard Worker         if (size != sizeof(downmix_type_t)) {
736*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %u, should be %zu",
737*ec779b8eSAndroid Build Coastguard Worker                     size, sizeof(downmix_type_t));
738*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
739*ec779b8eSAndroid Build Coastguard Worker         }
740*ec779b8eSAndroid Build Coastguard Worker         value16 = *(int16_t *)pValue;
741*ec779b8eSAndroid Build Coastguard Worker         ALOGV("set DOWNMIX_PARAM_TYPE, type %d", value16);
742*ec779b8eSAndroid Build Coastguard Worker         if (!((value16 > DOWNMIX_TYPE_INVALID) && (value16 <= DOWNMIX_TYPE_LAST))) {
743*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %d", value16);
744*ec779b8eSAndroid Build Coastguard Worker             return -EINVAL;
745*ec779b8eSAndroid Build Coastguard Worker         } else {
746*ec779b8eSAndroid Build Coastguard Worker             pDownmixer->type = (downmix_type_t) value16;
747*ec779b8eSAndroid Build Coastguard Worker         break;
748*ec779b8eSAndroid Build Coastguard Worker 
749*ec779b8eSAndroid Build Coastguard Worker       default:
750*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Downmix_setParameter unknown parameter %d", param);
751*ec779b8eSAndroid Build Coastguard Worker         return -EINVAL;
752*ec779b8eSAndroid Build Coastguard Worker     }
753*ec779b8eSAndroid Build Coastguard Worker }
754*ec779b8eSAndroid Build Coastguard Worker 
755*ec779b8eSAndroid Build Coastguard Worker     return 0;
756*ec779b8eSAndroid Build Coastguard Worker } /* end Downmix_setParameter */
757*ec779b8eSAndroid Build Coastguard Worker 
758*ec779b8eSAndroid Build Coastguard Worker /*----------------------------------------------------------------------------
759*ec779b8eSAndroid Build Coastguard Worker  * Downmix_getParameter()
760*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
761*ec779b8eSAndroid Build Coastguard Worker  * Purpose:
762*ec779b8eSAndroid Build Coastguard Worker  * Get a Downmix parameter
763*ec779b8eSAndroid Build Coastguard Worker  *
764*ec779b8eSAndroid Build Coastguard Worker  * Inputs:
765*ec779b8eSAndroid Build Coastguard Worker  *  pDownmixer    handle to instance data
766*ec779b8eSAndroid Build Coastguard Worker  *  param         parameter
767*ec779b8eSAndroid Build Coastguard Worker  *  pValue        pointer to variable to hold retrieved value
768*ec779b8eSAndroid Build Coastguard Worker  *  pSize         pointer to value size: maximum size as input
769*ec779b8eSAndroid Build Coastguard Worker  *
770*ec779b8eSAndroid Build Coastguard Worker  * Outputs:
771*ec779b8eSAndroid Build Coastguard Worker  *  *pValue updated with parameter value
772*ec779b8eSAndroid Build Coastguard Worker  *  *pSize updated with actual value size
773*ec779b8eSAndroid Build Coastguard Worker  *
774*ec779b8eSAndroid Build Coastguard Worker  * Returns:
775*ec779b8eSAndroid Build Coastguard Worker  *  0             indicates success
776*ec779b8eSAndroid Build Coastguard Worker  *
777*ec779b8eSAndroid Build Coastguard Worker  * Side Effects:
778*ec779b8eSAndroid Build Coastguard Worker  *
779*ec779b8eSAndroid Build Coastguard Worker  *----------------------------------------------------------------------------
780*ec779b8eSAndroid Build Coastguard Worker  */
Downmix_getParameter(downmix_object_t * pDownmixer,int32_t param,uint32_t * pSize,void * pValue)781*ec779b8eSAndroid Build Coastguard Worker static int Downmix_getParameter(
782*ec779b8eSAndroid Build Coastguard Worker         downmix_object_t *pDownmixer, int32_t param, uint32_t *pSize, void *pValue) {
783*ec779b8eSAndroid Build Coastguard Worker     int16_t *pValue16;
784*ec779b8eSAndroid Build Coastguard Worker 
785*ec779b8eSAndroid Build Coastguard Worker     switch (param) {
786*ec779b8eSAndroid Build Coastguard Worker 
787*ec779b8eSAndroid Build Coastguard Worker     case DOWNMIX_PARAM_TYPE:
788*ec779b8eSAndroid Build Coastguard Worker       if (*pSize < sizeof(int16_t)) {
789*ec779b8eSAndroid Build Coastguard Worker           ALOGE("Downmix_getParameter invalid parameter size %u for DOWNMIX_PARAM_TYPE", *pSize);
790*ec779b8eSAndroid Build Coastguard Worker           return -EINVAL;
791*ec779b8eSAndroid Build Coastguard Worker       }
792*ec779b8eSAndroid Build Coastguard Worker       pValue16 = (int16_t *)pValue;
793*ec779b8eSAndroid Build Coastguard Worker       *pValue16 = (int16_t) pDownmixer->type;
794*ec779b8eSAndroid Build Coastguard Worker       *pSize = sizeof(int16_t);
795*ec779b8eSAndroid Build Coastguard Worker       ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %d", *pValue16);
796*ec779b8eSAndroid Build Coastguard Worker       break;
797*ec779b8eSAndroid Build Coastguard Worker 
798*ec779b8eSAndroid Build Coastguard Worker     default:
799*ec779b8eSAndroid Build Coastguard Worker       ALOGE("Downmix_getParameter unknown parameter %d", param);
800*ec779b8eSAndroid Build Coastguard Worker       return -EINVAL;
801*ec779b8eSAndroid Build Coastguard Worker     }
802*ec779b8eSAndroid Build Coastguard Worker 
803*ec779b8eSAndroid Build Coastguard Worker     return 0;
804*ec779b8eSAndroid Build Coastguard Worker } /* end Downmix_getParameter */
805*ec779b8eSAndroid Build Coastguard Worker 
806