104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/* 204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Copyright (C) 2012 The Android Open Source Project 304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * you may not use this file except in compliance with the License. 604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * You may obtain a copy of the License at 704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 1004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 1104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 1204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * See the License for the specific language governing permissions and 1404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * limitations under the License. 1504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 1604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 1704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#define LOG_TAG "EffectDownmix" 18f28c8792f64e10c3c477d86bf4804a8566ff524eJean-Michel Trivi//#define LOG_NDEBUG 0 1904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#include <cutils/log.h> 2004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#include <stdlib.h> 2104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#include <string.h> 2204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#include <stdbool.h> 2304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#include "EffectDownmix.h" 2404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 256895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi// Do not submit with DOWNMIX_TEST_CHANNEL_INDEX defined, strictly for testing 266895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi//#define DOWNMIX_TEST_CHANNEL_INDEX 0 276895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi// Do not submit with DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER defined, strictly for testing 286895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi//#define DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER 0 296895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 3004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896 3104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 32db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivitypedef enum { 33db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi CHANNEL_MASK_SURROUND = AUDIO_CHANNEL_OUT_SURROUND, 34db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi CHANNEL_MASK_QUAD_BACK = AUDIO_CHANNEL_OUT_QUAD, 35db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi // like AUDIO_CHANNEL_OUT_QUAD with *_SIDE_* instead of *_BACK_*, same channel order 36db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi CHANNEL_MASK_QUAD_SIDE = 37db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_FRONT_LEFT | 38db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_FRONT_RIGHT | 39db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_SIDE_LEFT | 40db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_SIDE_RIGHT, 41db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi CHANNEL_MASK_5POINT1_BACK = AUDIO_CHANNEL_OUT_5POINT1, 42db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi // like AUDIO_CHANNEL_OUT_5POINT1 with *_SIDE_* instead of *_BACK_*, same channel order 43db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi CHANNEL_MASK_5POINT1_SIDE = 44db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_FRONT_LEFT | 45db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_FRONT_RIGHT | 46db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_FRONT_CENTER | 47db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_LOW_FREQUENCY | 48db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_SIDE_LEFT | 49db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi AUDIO_CHANNEL_OUT_SIDE_RIGHT, 50db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi CHANNEL_MASK_7POINT1_SIDE_BACK = AUDIO_CHANNEL_OUT_7POINT1, 51db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi} downmix_input_channel_mask_t; 52db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi 5304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// effect_handle_t interface implementation for downmix effect 5404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviconst struct effect_interface_s gDownmixInterface = { 5504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_Process, 5604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_Command, 5704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_GetDescriptor, 5804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi NULL /* no process_reverse function, no reference stream needed */ 5904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}; 6004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 6104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = { 6204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi tag : AUDIO_EFFECT_LIBRARY_TAG, 6304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi version : EFFECT_LIBRARY_API_VERSION, 6404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi name : "Downmix Library", 6504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi implementor : "The Android Open Source Project", 6604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi query_num_effects : DownmixLib_QueryNumberEffects, 6704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi query_effect : DownmixLib_QueryEffect, 6804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi create_effect : DownmixLib_Create, 6904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi release_effect : DownmixLib_Release, 7004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi get_descriptor : DownmixLib_GetDescriptor, 7104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}; 7204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 7304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 7404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// AOSP insert downmix UUID: 93f04452-e4fe-41cc-91f9-e475b6d1d69f 7504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic const effect_descriptor_t gDownmixDescriptor = { 7604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi EFFECT_UIID_DOWNMIX__, //type 7704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi {0x93f04452, 0xe4fe, 0x41cc, 0x91f9, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid 7804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi EFFECT_CONTROL_API_VERSION, 7904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST, 8004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 0, //FIXME what value should be reported? // cpu load 8104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 0, //FIXME what value should be reported? // memory usage 8204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi "Multichannel Downmix To Stereo", // human readable effect name 8304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi "The Android Open Source Project" // human readable effect implementor name 8404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}; 8504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 8604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// gDescriptors contains pointers to all defined effect descriptor in this library 8704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic const effect_descriptor_t * const gDescriptors[] = { 8804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi &gDownmixDescriptor 8904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}; 9004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 9104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// number of effects in this library 9204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviconst int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *); 9304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 9404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 9504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 966895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * Test code 976895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi *--------------------------------------------------------------------------*/ 986895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi#ifdef DOWNMIX_TEST_CHANNEL_INDEX 996895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi// strictly for testing, logs the indices of the channels for a given mask, 1006895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi// uses the same code as Downmix_foldGeneric() 1016895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivivoid Downmix_testIndexComputation(uint32_t mask) { 1026895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGI("Testing index computation for 0x%x:", mask); 1036895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // check against unsupported channels 1046895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (mask & kUnsupported) { 1056895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Unsupported channels (top or front left/right of center)"); 1066895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return; 1076895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 1086895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // verify has FL/FR 1096895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & AUDIO_CHANNEL_OUT_STEREO) != AUDIO_CHANNEL_OUT_STEREO) { 1106895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Front channels must be present"); 1116895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return; 1126895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 1136895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // verify uses SIDE as a pair (ok if not using SIDE at all) 1146895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi bool hasSides = false; 1156895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kSides) != 0) { 1166895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kSides) != kSides) { 1176895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Side channels must be used as a pair"); 1186895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return; 1196895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 1206895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi hasSides = true; 1216895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 1226895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // verify uses BACK as a pair (ok if not using BACK at all) 1236895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi bool hasBacks = false; 1246895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kBacks) != 0) { 1256895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kBacks) != kBacks) { 1266895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Back channels must be used as a pair"); 1276895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return; 1286895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 1296895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi hasBacks = true; 1306895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 1316895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 1326895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int numChan = popcount(mask); 1336895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const bool hasFC = ((mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) == AUDIO_CHANNEL_OUT_FRONT_CENTER); 1346895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const bool hasLFE = 1356895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ((mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) == AUDIO_CHANNEL_OUT_LOW_FREQUENCY); 1366895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const bool hasBC = ((mask & AUDIO_CHANNEL_OUT_BACK_CENTER) == AUDIO_CHANNEL_OUT_BACK_CENTER); 1376895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // compute at what index each channel is: samples will be in the following order: 1386895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // FL FR FC LFE BL BR BC SL SR 1396895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // when a channel is not present, its index is set to the same as the index of the preceding 1406895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // channel 1416895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexFC = hasFC ? 2 : 1; // front center 1426895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexLFE = hasLFE ? indexFC + 1 : indexFC; // low frequency 1436895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexBL = hasBacks ? indexLFE + 1 : indexLFE; // back left 1446895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexBR = hasBacks ? indexBL + 1 : indexBL; // back right 1456895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexBC = hasBC ? indexBR + 1 : indexBR; // back center 1466895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexSL = hasSides ? indexBC + 1 : indexBC; // side left 1476895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexSR = hasSides ? indexSL + 1 : indexSL; // side right 1486895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 1496895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGI(" FL FR FC LFE BL BR BC SL SR"); 1506895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGI(" %d %d %d %d %d %d %d %d %d", 1516895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 0, 1, indexFC, indexLFE, indexBL, indexBR, indexBC, indexSL, indexSR); 1526895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi} 1536895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi#endif 1546895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 1556895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 1566895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi/*---------------------------------------------------------------------------- 15704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Effect API implementation 15804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *--------------------------------------------------------------------------*/ 15904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 16004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*--- Effect Library Interface Implementation ---*/ 16104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 16204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_QueryNumberEffects(uint32_t *pNumEffects) { 16304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_QueryNumberEffects()"); 16404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *pNumEffects = kNbEffects; 16504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 16604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 16704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 16804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) { 16904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_QueryEffect() index=%d", index); 17004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDescriptor == NULL) { 17104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 17204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 17304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (index >= (uint32_t)kNbEffects) { 17404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 17504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 17604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi memcpy(pDescriptor, gDescriptors[index], sizeof(effect_descriptor_t)); 17704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 17804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 17904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 18004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 18104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_Create(const effect_uuid_t *uuid, 18204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int32_t sessionId, 18304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int32_t ioId, 18404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi effect_handle_t *pHandle) { 18504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int ret; 18604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int i; 18704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_module_t *module; 18804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi const effect_descriptor_t *desc; 18904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 19004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_Create()"); 19104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 1926895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi#ifdef DOWNMIX_TEST_CHANNEL_INDEX 1936895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // should work (won't log an error) 1946895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGI("DOWNMIX_TEST_CHANNEL_INDEX: should work:"); 1956895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT | 1966895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_BACK_CENTER); 1976895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(CHANNEL_MASK_QUAD_SIDE | CHANNEL_MASK_QUAD_BACK); 1986895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(CHANNEL_MASK_5POINT1_SIDE | AUDIO_CHANNEL_OUT_BACK_CENTER); 1996895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(CHANNEL_MASK_5POINT1_BACK | AUDIO_CHANNEL_OUT_BACK_CENTER); 2006895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // shouldn't work (will log an error, won't display channel indices) 2016895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGI("DOWNMIX_TEST_CHANNEL_INDEX: should NOT work:"); 2026895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT | 2036895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_BACK_LEFT); 2046895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | AUDIO_CHANNEL_OUT_FRONT_RIGHT | 2056895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi AUDIO_CHANNEL_OUT_LOW_FREQUENCY | AUDIO_CHANNEL_OUT_SIDE_LEFT); 2066895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | 2076895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi AUDIO_CHANNEL_OUT_BACK_LEFT | AUDIO_CHANNEL_OUT_BACK_RIGHT); 2086895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi Downmix_testIndexComputation(AUDIO_CHANNEL_OUT_FRONT_LEFT | 2096895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi AUDIO_CHANNEL_OUT_SIDE_LEFT | AUDIO_CHANNEL_OUT_SIDE_RIGHT); 2106895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi#endif 2116895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 21204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pHandle == NULL || uuid == NULL) { 21304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 21404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 21504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 21604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi for (i = 0 ; i < kNbEffects ; i++) { 21704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi desc = gDescriptors[i]; 21804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t)) == 0) { 21904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 22004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 22104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 22204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 22304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (i == kNbEffects) { 22404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -ENOENT; 22504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 22604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 22704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi module = malloc(sizeof(downmix_module_t)); 22804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 22904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi module->itfe = &gDownmixInterface; 23004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 23104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi module->context.state = DOWNMIX_STATE_UNINITIALIZED; 23204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 23304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ret = Downmix_Init(module); 23404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (ret < 0) { 23504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGW("DownmixLib_Create() init failed"); 23604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi free(module); 23704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return ret; 23804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 23904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 24004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *pHandle = (effect_handle_t) module; 24104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 24204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_Create() %p , size %d", module, sizeof(downmix_module_t)); 24304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 24404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 24504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 24604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 24704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 24804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_Release(effect_handle_t handle) { 24904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_module_t *pDwmModule = (downmix_module_t *)handle; 25004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 25104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_Release() %p", handle); 25204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (handle == NULL) { 25304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 25404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 25504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 25604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->context.state = DOWNMIX_STATE_UNINITIALIZED; 25704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 25804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi free(pDwmModule); 25904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 26004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 26104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 26204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 26304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) { 26404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_GetDescriptor()"); 26504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int i; 26604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 26704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDescriptor == NULL || uuid == NULL){ 26804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("DownmixLib_Create() called with NULL pointer"); 26904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 27004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 27104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_GetDescriptor() nb effects=%d", kNbEffects); 27204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi for (i = 0; i < kNbEffects; i++) { 27304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("DownmixLib_GetDescriptor() i=%d", i); 27404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) { 27504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t)); 27604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %x", 27704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi i, gDescriptors[i]->uuid.timeLow); 27804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 27904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 28004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 28104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 28204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 28304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 28404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 28504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 28604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*--- Effect Control Interface Implementation ---*/ 28704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 28804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic int Downmix_Process(effect_handle_t self, 28904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) { 29004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 29104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_object_t *pDownmixer; 29204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int16_t *pSrc, *pDst; 29304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_module_t *pDwmModule = (downmix_module_t *)self; 29404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 29504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDwmModule == NULL) { 29604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 29704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 29804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 29904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (inBuffer == NULL || inBuffer->raw == NULL || 30004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi outBuffer == NULL || outBuffer->raw == NULL || 30104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi inBuffer->frameCount != outBuffer->frameCount) { 30204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 30304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 30404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 30504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer = (downmix_object_t*) &pDwmModule->context; 30604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 30704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDownmixer->state == DOWNMIX_STATE_UNINITIALIZED) { 30804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_Process error: trying to use an uninitialized downmixer"); 30904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 31004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else if (pDownmixer->state == DOWNMIX_STATE_INITIALIZED) { 31104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_Process error: trying to use a non-configured downmixer"); 31204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -ENODATA; 31304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 31404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 31504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc = inBuffer->s16; 31604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst = outBuffer->s16; 31704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi size_t numFrames = outBuffer->frameCount; 31804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 31904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi const bool accumulate = 32004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi (pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE); 3216895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const uint32_t downmixInputChannelMask = pDwmModule->config.inputCfg.channels; 32204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 32304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi switch(pDownmixer->type) { 32404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 32504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case DOWNMIX_TYPE_STRIP: 32604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (accumulate) { 32704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 32804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst[0] = clamp16(pDst[0] + pSrc[0]); 32904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst[1] = clamp16(pDst[1] + pSrc[1]); 33004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += pDownmixer->input_channel_count; 33104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 33204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 33304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 33404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { 33504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 33604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst[0] = pSrc[0]; 33704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst[1] = pSrc[1]; 33804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += pDownmixer->input_channel_count; 33904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 34004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 34104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 34204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 34304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 34404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 34504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case DOWNMIX_TYPE_FOLD: 3466895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi#ifdef DOWNMIX_ALWAYS_USE_GENERIC_DOWNMIXER 3476895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // bypass the optimized downmix routines for the common formats 3486895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (!Downmix_foldGeneric( 3496895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) { 3506895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask); 3516895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return -EINVAL; 3526895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 3536895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi break; 3546895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi#endif 35504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // optimize for the common formats 3566895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi switch((downmix_input_channel_mask_t)downmixInputChannelMask) { 357db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi case CHANNEL_MASK_QUAD_BACK: 358db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi case CHANNEL_MASK_QUAD_SIDE: 35904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_foldFromQuad(pSrc, pDst, numFrames, accumulate); 36004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 361db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi case CHANNEL_MASK_SURROUND: 36204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_foldFromSurround(pSrc, pDst, numFrames, accumulate); 36304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 364db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi case CHANNEL_MASK_5POINT1_BACK: 365db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi case CHANNEL_MASK_5POINT1_SIDE: 36604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate); 36704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 368db46b48d24e03f5bcb8de6d0ff852ec4153401e7Jean-Michel Trivi case CHANNEL_MASK_7POINT1_SIDE_BACK: 36904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate); 37004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 37104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi default: 3726895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (!Downmix_foldGeneric( 3736895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi downmixInputChannelMask, pSrc, pDst, numFrames, accumulate)) { 3746895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Multichannel configuration 0x%x is not supported", downmixInputChannelMask); 3756895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return -EINVAL; 3766895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 37704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 37804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 37904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 38004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 38104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi default: 38204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 38304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 38404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 38504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 38604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 38704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 38804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 38904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize, 39004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi void *pCmdData, uint32_t *replySize, void *pReplyData) { 39104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 39204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_module_t *pDwmModule = (downmix_module_t *) self; 39304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_object_t *pDownmixer; 39404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int retsize; 39504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 39604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDwmModule == NULL || pDwmModule->context.state == DOWNMIX_STATE_UNINITIALIZED) { 39704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 39804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 39904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 40004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer = (downmix_object_t*) &pDwmModule->context; 40104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 40204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Command command %d cmdSize %d",cmdCode, cmdSize); 40304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 40404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi switch (cmdCode) { 40504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_INIT: 40604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pReplyData == NULL || *replySize != sizeof(int)) { 40704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 40804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 40904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *(int *) pReplyData = Downmix_Init(pDwmModule); 41004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 41104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 41204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_CONFIG: 41304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pCmdData == NULL || cmdSize != sizeof(effect_config_t) 41404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi || pReplyData == NULL || *replySize != sizeof(int)) { 41504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 41604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 41704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *(int *) pReplyData = Downmix_Configure(pDwmModule, 41804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi (effect_config_t *)pCmdData, false); 41904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 42004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 42104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_RESET: 42204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_Reset(pDownmixer, false); 42304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 42404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 42504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_GET_PARAM: 42604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p", 42704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pCmdData, *replySize, pReplyData); 42804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) || 42904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pReplyData == NULL || 43004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *replySize < (int) sizeof(effect_param_t) + 2 * sizeof(int32_t)) { 43104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 43204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 43304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi effect_param_t *rep = (effect_param_t *) pReplyData; 43404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t)); 43504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %d, replySize %d", 43604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *(int32_t *)rep->data, rep->vsize); 43704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rep->status = Downmix_getParameter(pDownmixer, *(int32_t *)rep->data, &rep->vsize, 43804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rep->data + sizeof(int32_t)); 43904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize; 44004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 44104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 44204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_PARAM: 44304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, " \ 44404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi "pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData); 44504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t))) 44604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) { 44704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 44804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 44904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi effect_param_t *cmd = (effect_param_t *) pCmdData; 45004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *(int *)pReplyData = Downmix_setParameter(pDownmixer, *(int32_t *)cmd->data, 45104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi cmd->vsize, cmd->data + sizeof(int32_t)); 45204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 45304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 45404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_PARAM_DEFERRED: 45504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi //FIXME implement 45604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_DEFERRED not supported, FIXME"); 45704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 45804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 45904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_PARAM_COMMIT: 46004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi //FIXME implement 46104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_COMMIT not supported, FIXME"); 46204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 46304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 46404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_ENABLE: 46504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pReplyData == NULL || *replySize != sizeof(int)) { 46604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 46704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 46804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDownmixer->state != DOWNMIX_STATE_INITIALIZED) { 46904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -ENOSYS; 47004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 47104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer->state = DOWNMIX_STATE_ACTIVE; 47204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("EFFECT_CMD_ENABLE() OK"); 47304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *(int *)pReplyData = 0; 47404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 47504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 47604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_DISABLE: 47704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pReplyData == NULL || *replySize != sizeof(int)) { 47804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 47904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 48004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDownmixer->state != DOWNMIX_STATE_ACTIVE) { 48104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -ENOSYS; 48204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 48304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer->state = DOWNMIX_STATE_INITIALIZED; 48404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("EFFECT_CMD_DISABLE() OK"); 48504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *(int *)pReplyData = 0; 48604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 48704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 48804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_DEVICE: 48904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) { 49004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 49104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 49204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FIXME change type if playing on headset vs speaker 49304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData); 49404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 49504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 49604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_VOLUME: { 49704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // audio output is always stereo => 2 channel volumes 49804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) { 49904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 50004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 50104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FIXME change volume 50204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGW("Downmix_Command command EFFECT_CMD_SET_VOLUME not supported, FIXME"); 50304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi float left = (float)(*(uint32_t *)pCmdData) / (1 << 24); 50404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24); 50504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right); 50604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 50704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 50804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 50904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_AUDIO_MODE: 51004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) { 51104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 51204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 51304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData); 51404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 51504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 51604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_CONFIG_REVERSE: 51704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case EFFECT_CMD_SET_INPUT_DEVICE: 51804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // these commands are ignored by a downmix effect 51904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 52004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 52104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi default: 52204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGW("Downmix_Command invalid command %d",cmdCode); 52304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 52404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 52504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 52604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 52704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 52804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 52904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 53004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_GetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor) 53104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi{ 53204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_module_t *pDwnmxModule = (downmix_module_t *) self; 53304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 53404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pDwnmxModule == NULL || 53504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwnmxModule->context.state == DOWNMIX_STATE_UNINITIALIZED) { 53604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 53704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 53804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 53904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi memcpy(pDescriptor, &gDownmixDescriptor, sizeof(effect_descriptor_t)); 54004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 54104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 54204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 54304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 54404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 54504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 54604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix internal functions 54704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *--------------------------------------------------------------------------*/ 54804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 54904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 55004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_Init() 55104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 55204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 55304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Initialize downmix context and apply default parameters 55404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 55504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 55604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule pointer to downmix effect module 55704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 55804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 55904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 56004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns: 56104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 0 indicates success 56204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 56304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects: 56404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * updates: 56504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->context.type 56604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->context.apply_volume_correction 56704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->config.inputCfg 56804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->config.outputCfg 56904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->config.inputCfg.samplingRate 57004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->config.outputCfg.samplingRate 57104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->context.state 57204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * doesn't set: 57304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule->itfe 57404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 57504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 57604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 57704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 57804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_Init(downmix_module_t *pDwmModule) { 57904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 58004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Init module %p", pDwmModule); 58104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int ret = 0; 58204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 58304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi memset(&pDwmModule->context, 0, sizeof(downmix_object_t)); 58404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 58504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ; 58604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 58704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1; 58804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.bufferProvider.getBuffer = NULL; 58904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.bufferProvider.releaseBuffer = NULL; 59004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.bufferProvider.cookie = NULL; 59104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.mask = EFFECT_CONFIG_ALL; 59204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 59304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.inputCfg.samplingRate = 44100; 59404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.samplingRate = pDwmModule->config.inputCfg.samplingRate; 59504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 59604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // set a default value for the access mode, but should be overwritten by caller 59704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE; 59804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT; 59904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO; 60004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.bufferProvider.getBuffer = NULL; 60104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.bufferProvider.releaseBuffer = NULL; 60204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.bufferProvider.cookie = NULL; 60304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->config.outputCfg.mask = EFFECT_CONFIG_ALL; 60404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 60504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ret = Downmix_Configure(pDwmModule, &pDwmModule->config, true); 60604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (ret != 0) { 60704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_Init error %d on module %p", ret, pDwmModule); 60804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { 60904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDwmModule->context.state = DOWNMIX_STATE_INITIALIZED; 61004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 61104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 61204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return ret; 61304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 61404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 61504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 61604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 61704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_Configure() 61804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 61904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 62004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Set input and output audio configuration. 62104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 62204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 62304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDwmModule pointer to downmix effect module 62404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pConfig pointer to effect_config_t structure containing input 62504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * and output audio parameters configuration 62604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * init true if called from init function 62704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 62804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 62904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 63004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns: 63104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 0 indicates success 63204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 63304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects: 63404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 63504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 63604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 63704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 63804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init) { 63904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 64004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi downmix_object_t *pDownmixer = &pDwmModule->context; 64104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 64204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // Check configuration compatibility with build options, and effect capabilities 64304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate 64404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi || pConfig->outputCfg.channels != DOWNMIX_OUTPUT_CHANNELS 64504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT 64604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) { 64704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_Configure error: invalid config"); 64804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 64904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 65004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 65104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t)); 65204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 65304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (init) { 65404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer->type = DOWNMIX_TYPE_FOLD; 65504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer->apply_volume_correction = false; 65604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer->input_channel_count = 8; // matches default input of AUDIO_CHANNEL_OUT_7POINT1 65704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { 65804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // when configuring the effect, do not allow a blank channel mask 65904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (pConfig->inputCfg.channels == 0) { 66004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_Configure error: input channel mask can't be 0"); 66104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 66204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 66304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer->input_channel_count = popcount(pConfig->inputCfg.channels); 66404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 66504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 66604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi Downmix_Reset(pDownmixer, init); 66704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 66804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 66904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 67004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 67104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 67204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 67304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_Reset() 67404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 67504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 67604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Reset internal states. 67704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 67804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 67904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDownmixer pointer to downmix context 68004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * init true if called from init function 68104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 68204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 68304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi* 68404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns: 68504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 0 indicates success 68604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 68704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects: 68804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 68904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 69004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 69104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 69204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_Reset(downmix_object_t *pDownmixer, bool init) { 69304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // nothing to do here 69404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 69504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 69604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 69704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 69804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 69904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_setParameter() 70004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 70104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 70204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Set a Downmix parameter 70304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 70404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 70504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDownmixer handle to instance data 70604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * param parameter 70704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pValue pointer to parameter value 70804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * size value size 70904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 71004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 71104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 71204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns: 71304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 0 indicates success 71404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 71504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects: 71604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 71704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 71804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 71904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue) { 72004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 72104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int16_t value16; 72204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d", 72304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer, param, *(int16_t *)pValue, *(int32_t *)pValue); 72404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 72504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi switch (param) { 72604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 72704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case DOWNMIX_PARAM_TYPE: 72804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (size != sizeof(downmix_type_t)) { 72904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %d, should be %d", 73004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi size, sizeof(downmix_type_t)); 73104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 73204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 73304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi value16 = *(int16_t *)pValue; 73404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("set DOWNMIX_PARAM_TYPE, type %d", value16); 7357d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi if (!((value16 > DOWNMIX_TYPE_INVALID) && (value16 <= DOWNMIX_TYPE_LAST))) { 73604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %d", value16); 73704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 73804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { 73904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDownmixer->type = (downmix_type_t) value16; 74004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 74104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 74204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi default: 74304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_setParameter unknown parameter %d", param); 74404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 74504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 74604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 74704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 74804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 74904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} /* end Downmix_setParameter */ 75004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 75104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 75204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 75304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_getParameter() 75404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 75504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 75604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Get a Downmix parameter 75704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 75804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 75904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDownmixer handle to instance data 76004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * param parameter 76104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pValue pointer to variable to hold retrieved value 76204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pSize pointer to value size: maximum size as input 76304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 76404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 76504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * *pValue updated with parameter value 76604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * *pSize updated with actual value size 76704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 76804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns: 76904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 0 indicates success 77004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 77104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects: 77204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 77304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 77404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 77504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue) { 77604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int16_t *pValue16; 77704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 77804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi switch (param) { 77904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 78004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi case DOWNMIX_PARAM_TYPE: 78104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (*pSize < sizeof(int16_t)) { 78204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_getParameter invalid parameter size %d for DOWNMIX_PARAM_TYPE", *pSize); 78304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 78404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 78504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pValue16 = (int16_t *)pValue; 78604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *pValue16 = (int16_t) pDownmixer->type; 78704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *pSize = sizeof(int16_t); 78804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %d", *pValue16); 78904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi break; 79004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 79104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi default: 79204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi ALOGE("Downmix_getParameter unknown parameter %d", param); 79304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return -EINVAL; 79404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 79504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 79604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi return 0; 79704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} /* end Downmix_getParameter */ 79804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 79904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 80004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 80104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFromQuad() 80204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 80304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 80404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a quad signal to stereo 80504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 80604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 80704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pSrc quad audio samples to downmix 80804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * numFrames the number of quad frames to downmix 8096895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * accumulate whether to mix (when true) the result of the downmix with the contents of pDst, 8106895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * or overwrite pDst (when false) 81104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 81204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 81304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDst downmixed stereo audio samples 81404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 81504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 81604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 81704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) { 81804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 0 is FL 81904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 1 is FR 82004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 2 is RL 82104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 3 is RR 82204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (accumulate) { 82304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 82404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + RL 825aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(pDst[0] + ((pSrc[0] + pSrc[2]) >> 1)); 82604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + RR 827aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(pDst[1] + ((pSrc[1] + pSrc[3]) >> 1)); 82804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 4; 82904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 83004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 83104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 83204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { // same code as above but without adding and clamping pDst[i] to itself 83304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 83404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + RL 835aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16((pSrc[0] + pSrc[2]) >> 1); 83604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + RR 837aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16((pSrc[1] + pSrc[3]) >> 1); 83804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 4; 83904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 84004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 84104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 84204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 84304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 84404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 84504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 84604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 84704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFromSurround() 84804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 84904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 85004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a "surround sound" (mono rear) signal to stereo 85104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 85204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 85304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pSrc surround signal to downmix 85404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * numFrames the number of surround frames to downmix 8556895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * accumulate whether to mix (when true) the result of the downmix with the contents of pDst, 8566895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * or overwrite pDst (when false) 85704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 85804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 85904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDst downmixed stereo audio samples 86004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 86104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 86204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 86304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) { 86404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int32_t lt, rt, centerPlusRearContrib; // samples in Q19.12 format 86504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 0 is FL 86604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 1 is FR 86704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 2 is FC 86804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 3 is RC 8696895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // code is mostly duplicated between the two values of accumulate to avoid repeating the test 8706895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // for every sample 87104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (accumulate) { 87204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 87304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // centerPlusRearContrib = FC(-3dB) + RC(-3dB) 87404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12); 87504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + centerPlusRearContrib 87604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi lt = (pSrc[0] << 12) + centerPlusRearContrib; 87704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + centerPlusRearContrib 87804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rt = (pSrc[1] << 12) + centerPlusRearContrib; 8796895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // accumulate in destination 880aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(pDst[0] + (lt >> 13)); 881aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(pDst[1] + (rt >> 13)); 88204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 4; 88304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 88404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 88504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 88604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { // same code as above but without adding and clamping pDst[i] to itself 88704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 88804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // centerPlusRearContrib = FC(-3dB) + RC(-3dB) 88904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12); 89004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + centerPlusRearContrib 89104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi lt = (pSrc[0] << 12) + centerPlusRearContrib; 89204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + centerPlusRearContrib 89304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rt = (pSrc[1] << 12) + centerPlusRearContrib; 8946895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // store in destination 895aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above 896aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above 89704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 4; 89804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 89904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 90004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 90104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 90204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 90304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 90404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 90504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 90604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFrom5Point1() 90704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 90804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 90904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a 5.1 signal to stereo 91004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 91104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 91204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pSrc 5.1 audio samples to downmix 91304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * numFrames the number of 5.1 frames to downmix 9146895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * accumulate whether to mix (when true) the result of the downmix with the contents of pDst, 9156895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * or overwrite pDst (when false) 91604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 91704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 91804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDst downmixed stereo audio samples 91904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 92004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 92104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 92204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) { 92304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format 92404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 0 is FL 92504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 1 is FR 92604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 2 is FC 92704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 3 is LFE 92804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 4 is RL 92904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 5 is RR 9306895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // code is mostly duplicated between the two values of accumulate to avoid repeating the test 9316895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // for every sample 93204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (accumulate) { 93304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 93404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB) 93504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) 93604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi + (pSrc[3] * MINUS_3_DB_IN_Q19_12); 93704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + centerPlusLfeContrib + RL 93804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12); 93904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + centerPlusLfeContrib + RR 94004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12); 9416895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // accumulate in destination 942aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(pDst[0] + (lt >> 13)); 943aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(pDst[1] + (rt >> 13)); 94404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 6; 94504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 94604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 94704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 94804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { // same code as above but without adding and clamping pDst[i] to itself 94904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 95004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB) 95104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) 95204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi + (pSrc[3] * MINUS_3_DB_IN_Q19_12); 95304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + centerPlusLfeContrib + RL 95404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12); 95504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + centerPlusLfeContrib + RR 95604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12); 9576895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // store in destination 958aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above 959aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above 96004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 6; 96104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 96204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 96304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 96404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 96504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 96604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 96704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 96804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*---------------------------------------------------------------------------- 96904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFrom7Point1() 97004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 97104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose: 97204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a 7.1 signal to stereo 97304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 97404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs: 97504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pSrc 7.1 audio samples to downmix 97604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * numFrames the number of 7.1 frames to downmix 9776895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * accumulate whether to mix (when true) the result of the downmix with the contents of pDst, 9786895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * or overwrite pDst (when false) 97904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 98004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs: 98104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * pDst downmixed stereo audio samples 98204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * 98304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *---------------------------------------------------------------------------- 98404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */ 98504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) { 98604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format 98704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 0 is FL 98804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 1 is FR 98904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 2 is FC 99004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 3 is LFE 99104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 4 is RL 99204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 5 is RR 99304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 6 is SL 99404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // sample at index 7 is SR 9956895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // code is mostly duplicated between the two values of accumulate to avoid repeating the test 9966895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // for every sample 99704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi if (accumulate) { 99804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 99904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB) 100004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) 100104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi + (pSrc[3] * MINUS_3_DB_IN_Q19_12); 100204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + centerPlusLfeContrib + SL + RL 100304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12); 100404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + centerPlusLfeContrib + SR + RR 100504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12); 10066895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi //accumulate in destination 1007aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(pDst[0] + (lt >> 13)); 1008aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(pDst[1] + (rt >> 13)); 100904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 8; 101004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 101104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 101204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 101304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } else { // same code as above but without adding and clamping pDst[i] to itself 101404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi while (numFrames) { 101504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB) 101604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) 101704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi + (pSrc[3] * MINUS_3_DB_IN_Q19_12); 101804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FL + centerPlusLfeContrib + SL + RL 101904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12); 102004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi // FR + centerPlusLfeContrib + SR + RR 102104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12); 10226895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // store in destination 1023aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above 1024aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above 102504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pSrc += 8; 102604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi pDst += 2; 102704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi numFrames--; 102804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 102904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi } 103004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} 103104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi 10326895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 10336895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi/*---------------------------------------------------------------------------- 10346895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * Downmix_foldGeneric() 10356895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi *---------------------------------------------------------------------------- 10366895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * Purpose: 10376895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * downmix to stereo a multichannel signal whose format is: 10386895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * - has FL/FR 10396895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * - if using AUDIO_CHANNEL_OUT_SIDE*, it contains both left and right 10406895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * - if using AUDIO_CHANNEL_OUT_BACK*, it contains both left and right 10416895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * - doesn't use any of the AUDIO_CHANNEL_OUT_TOP* channels 10426895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * - doesn't use any of the AUDIO_CHANNEL_OUT_FRONT_*_OF_CENTER channels 10436895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * Only handles channel masks not enumerated in downmix_input_channel_mask_t 10446895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * 10456895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * Inputs: 10466895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * mask the channel mask of pSrc 10476895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * pSrc multichannel audio buffer to downmix 10486895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * numFrames the number of multichannel frames to downmix 10496895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * accumulate whether to mix (when true) the result of the downmix with the contents of pDst, 10506895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * or overwrite pDst (when false) 10516895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * 10526895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * Outputs: 10536895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * pDst downmixed stereo audio samples 10546895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * 10556895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * Returns: false if multichannel format is not supported 10566895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi * 10576895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi *---------------------------------------------------------------------------- 10586895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi */ 10596895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivibool Downmix_foldGeneric( 10606895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi uint32_t mask, int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) { 10616895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // check against unsupported channels 10626895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (mask & kUnsupported) { 10636895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Unsupported channels (top or front left/right of center)"); 10646895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return false; 10656895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 10666895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // verify has FL/FR 10676895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & AUDIO_CHANNEL_OUT_STEREO) != AUDIO_CHANNEL_OUT_STEREO) { 10686895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Front channels must be present"); 10696895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return false; 10706895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 10716895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // verify uses SIDE as a pair (ok if not using SIDE at all) 10726895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi bool hasSides = false; 10736895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kSides) != 0) { 10746895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kSides) != kSides) { 10756895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Side channels must be used as a pair"); 10766895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return false; 10776895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 10786895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi hasSides = true; 10796895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 10806895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // verify uses BACK as a pair (ok if not using BACK at all) 10816895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi bool hasBacks = false; 10826895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kBacks) != 0) { 10836895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if ((mask & kBacks) != kBacks) { 10846895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ALOGE("Back channels must be used as a pair"); 10856895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return false; 10866895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 10876895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi hasBacks = true; 10886895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 10896895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 10906895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int numChan = popcount(mask); 10916895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const bool hasFC = ((mask & AUDIO_CHANNEL_OUT_FRONT_CENTER) == AUDIO_CHANNEL_OUT_FRONT_CENTER); 10926895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const bool hasLFE = 10936895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi ((mask & AUDIO_CHANNEL_OUT_LOW_FREQUENCY) == AUDIO_CHANNEL_OUT_LOW_FREQUENCY); 10946895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const bool hasBC = ((mask & AUDIO_CHANNEL_OUT_BACK_CENTER) == AUDIO_CHANNEL_OUT_BACK_CENTER); 10956895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // compute at what index each channel is: samples will be in the following order: 10966895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // FL FR FC LFE BL BR BC SL SR 10976895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // when a channel is not present, its index is set to the same as the index of the preceding 10986895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // channel 10996895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexFC = hasFC ? 2 : 1; // front center 11006895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexLFE = hasLFE ? indexFC + 1 : indexFC; // low frequency 11016895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexBL = hasBacks ? indexLFE + 1 : indexLFE; // back left 11026895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexBR = hasBacks ? indexBL + 1 : indexBL; // back right 11036895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexBC = hasBC ? indexBR + 1 : indexBR; // back center 11046895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexSL = hasSides ? indexBC + 1 : indexBC; // side left 11056895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi const int indexSR = hasSides ? indexSL + 1 : indexSL; // side right 11066895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi 11076895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi int32_t lt, rt, centersLfeContrib; // samples in Q19.12 format 11086895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // code is mostly duplicated between the two values of accumulate to avoid repeating the test 11096895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // for every sample 11106895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (accumulate) { 11116895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi while (numFrames) { 11126895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // compute contribution of FC, BC and LFE 11136895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi centersLfeContrib = 0; 11146895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasFC) { centersLfeContrib += pSrc[indexFC]; } 11156895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasLFE) { centersLfeContrib += pSrc[indexLFE]; } 11166895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasBC) { centersLfeContrib += pSrc[indexBC]; } 11176895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi centersLfeContrib *= MINUS_3_DB_IN_Q19_12; 11186895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // always has FL/FR 11196895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt = (pSrc[0] << 12); 11206895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt = (pSrc[1] << 12); 11216895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // mix in sides and backs 11226895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasSides) { 11236895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt += pSrc[indexSL] << 12; 11246895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt += pSrc[indexSR] << 12; 11256895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 11266895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasBacks) { 11276895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt += pSrc[indexBL] << 12; 11286895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt += pSrc[indexBR] << 12; 11296895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 11306895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt += centersLfeContrib; 11316895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt += centersLfeContrib; 11326895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // accumulate in destination 1133aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(pDst[0] + (lt >> 13)); 1134aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(pDst[1] + (rt >> 13)); 11356895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi pSrc += numChan; 11366895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi pDst += 2; 11376895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi numFrames--; 11386895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 11396895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } else { 11406895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi while (numFrames) { 11416895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // compute contribution of FC, BC and LFE 11426895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi centersLfeContrib = 0; 11436895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasFC) { centersLfeContrib += pSrc[indexFC]; } 11446895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasLFE) { centersLfeContrib += pSrc[indexLFE]; } 11456895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasBC) { centersLfeContrib += pSrc[indexBC]; } 11466895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi centersLfeContrib *= MINUS_3_DB_IN_Q19_12; 11476895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // always has FL/FR 11486895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt = (pSrc[0] << 12); 11496895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt = (pSrc[1] << 12); 11506895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // mix in sides and backs 11516895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasSides) { 11526895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt += pSrc[indexSL] << 12; 11536895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt += pSrc[indexSR] << 12; 11546895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 11556895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi if (hasBacks) { 11566895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt += pSrc[indexBL] << 12; 11576895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt += pSrc[indexBR] << 12; 11586895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 11596895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi lt += centersLfeContrib; 11606895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi rt += centersLfeContrib; 11616895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi // store in destination 1162aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[0] = clamp16(lt >> 13); // differs from when accumulate is true above 1163aea2715e65994e665a3732551880419ba1cecc0dJean-Michel Trivi pDst[1] = clamp16(rt >> 13); // differs from when accumulate is true above 11646895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi pSrc += numChan; 11656895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi pDst += 2; 11666895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi numFrames--; 11676895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 11686895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi } 11696895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi return true; 11706895deeecc8797e6f5b28e7d07ec6bc499355c0cJean-Michel Trivi} 1171