EffectDownmix.c revision 7d5b26230a179cd7bcc01f6578cd80d8c15a92a5
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"
1804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-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
2504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
2604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
2704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// effect_handle_t interface implementation for downmix effect
2804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviconst struct effect_interface_s gDownmixInterface = {
2904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        Downmix_Process,
3004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        Downmix_Command,
3104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        Downmix_GetDescriptor,
3204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        NULL /* no process_reverse function, no reference stream needed */
3304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi};
3404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
3504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
3604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    tag : AUDIO_EFFECT_LIBRARY_TAG,
3704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    version : EFFECT_LIBRARY_API_VERSION,
3804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    name : "Downmix Library",
3904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    implementor : "The Android Open Source Project",
4004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    query_num_effects : DownmixLib_QueryNumberEffects,
4104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    query_effect : DownmixLib_QueryEffect,
4204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    create_effect : DownmixLib_Create,
4304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    release_effect : DownmixLib_Release,
4404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    get_descriptor : DownmixLib_GetDescriptor,
4504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi};
4604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
4704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
4804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// AOSP insert downmix UUID: 93f04452-e4fe-41cc-91f9-e475b6d1d69f
4904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic const effect_descriptor_t gDownmixDescriptor = {
5004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        EFFECT_UIID_DOWNMIX__, //type
5104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        {0x93f04452, 0xe4fe, 0x41cc, 0x91f9, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid
5204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        EFFECT_CONTROL_API_VERSION,
5304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
5404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        0, //FIXME what value should be reported? // cpu load
5504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        0, //FIXME what value should be reported? // memory usage
5604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        "Multichannel Downmix To Stereo", // human readable effect name
5704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        "The Android Open Source Project" // human readable effect implementor name
5804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi};
5904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
6004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// gDescriptors contains pointers to all defined effect descriptor in this library
6104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic const effect_descriptor_t * const gDescriptors[] = {
6204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        &gDownmixDescriptor
6304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi};
6404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
6504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi// number of effects in this library
6604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviconst int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
6704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
6804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
6904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
7004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Effect API implementation
7104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *--------------------------------------------------------------------------*/
7204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
7304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*--- Effect Library Interface Implementation ---*/
7404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
7504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_QueryNumberEffects(uint32_t *pNumEffects) {
7604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("DownmixLib_QueryNumberEffects()");
7704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    *pNumEffects = kNbEffects;
7804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
7904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
8004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
8104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
8204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("DownmixLib_QueryEffect() index=%d", index);
8304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pDescriptor == NULL) {
8404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
8504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
8604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (index >= (uint32_t)kNbEffects) {
8704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
8804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
8904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    memcpy(pDescriptor, gDescriptors[index], sizeof(effect_descriptor_t));
9004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
9104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
9204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
9304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
9404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_Create(const effect_uuid_t *uuid,
9504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        int32_t sessionId,
9604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        int32_t ioId,
9704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        effect_handle_t *pHandle) {
9804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int ret;
9904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int i;
10004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_module_t *module;
10104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    const effect_descriptor_t *desc;
10204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
10304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("DownmixLib_Create()");
10404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
10504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pHandle == NULL || uuid == NULL) {
10604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
10704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
10804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
10904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    for (i = 0 ; i < kNbEffects ; i++) {
11004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        desc = gDescriptors[i];
11104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t)) == 0) {
11204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            break;
11304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
11404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
11504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
11604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (i == kNbEffects) {
11704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -ENOENT;
11804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
11904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
12004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    module = malloc(sizeof(downmix_module_t));
12104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
12204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    module->itfe = &gDownmixInterface;
12304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
12404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    module->context.state = DOWNMIX_STATE_UNINITIALIZED;
12504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
12604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ret = Downmix_Init(module);
12704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (ret < 0) {
12804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGW("DownmixLib_Create() init failed");
12904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        free(module);
13004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return ret;
13104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
13204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
13304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    *pHandle = (effect_handle_t) module;
13404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
13504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("DownmixLib_Create() %p , size %d", module, sizeof(downmix_module_t));
13604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
13704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
13804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
13904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
14004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
14104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_Release(effect_handle_t handle) {
14204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_module_t *pDwmModule = (downmix_module_t *)handle;
14304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
14404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("DownmixLib_Release() %p", handle);
14504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (handle == NULL) {
14604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
14704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
14804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
14904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->context.state = DOWNMIX_STATE_UNINITIALIZED;
15004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
15104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    free(pDwmModule);
15204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
15304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
15404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
15504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
15604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
15704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("DownmixLib_GetDescriptor()");
15804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int i;
15904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
16004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pDescriptor == NULL || uuid == NULL){
16104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGE("DownmixLib_Create() called with NULL pointer");
16204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
16304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
16404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("DownmixLib_GetDescriptor() nb effects=%d", kNbEffects);
16504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    for (i = 0; i < kNbEffects; i++) {
16604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("DownmixLib_GetDescriptor() i=%d", i);
16704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
16804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
16904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %x",
17004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                 i, gDescriptors[i]->uuid.timeLow);
17104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return 0;
17204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
17304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
17404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
17504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return -EINVAL;
17604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
17704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
17804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
17904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*--- Effect Control Interface Implementation ---*/
18004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
18104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic int Downmix_Process(effect_handle_t self,
18204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
18304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
18404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_object_t *pDownmixer;
18504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int16_t *pSrc, *pDst;
18604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_module_t *pDwmModule = (downmix_module_t *)self;
18704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
18804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pDwmModule == NULL) {
18904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
19004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
19104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
19204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (inBuffer == NULL || inBuffer->raw == NULL ||
19304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        outBuffer == NULL || outBuffer->raw == NULL ||
19404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        inBuffer->frameCount != outBuffer->frameCount) {
19504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
19604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
19704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
19804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDownmixer = (downmix_object_t*) &pDwmModule->context;
19904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
20004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pDownmixer->state == DOWNMIX_STATE_UNINITIALIZED) {
20104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGE("Downmix_Process error: trying to use an uninitialized downmixer");
20204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
20304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    } else if (pDownmixer->state == DOWNMIX_STATE_INITIALIZED) {
20404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGE("Downmix_Process error: trying to use a non-configured downmixer");
20504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -ENODATA;
20604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
20704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
20804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pSrc = inBuffer->s16;
20904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDst = outBuffer->s16;
21004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    size_t numFrames = outBuffer->frameCount;
21104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
21204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    const bool accumulate =
21304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            (pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
21404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
21504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    switch(pDownmixer->type) {
21604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
21704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      case DOWNMIX_TYPE_STRIP:
21804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi          if (accumulate) {
21904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi              while (numFrames) {
22004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pDst[0] = clamp16(pDst[0] + pSrc[0]);
22104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pDst[1] = clamp16(pDst[1] + pSrc[1]);
22204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pSrc += pDownmixer->input_channel_count;
22304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pDst += 2;
22404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  numFrames--;
22504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi              }
22604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi          } else {
22704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi              while (numFrames) {
22804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pDst[0] = pSrc[0];
22904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pDst[1] = pSrc[1];
23004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pSrc += pDownmixer->input_channel_count;
23104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  pDst += 2;
23204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                  numFrames--;
23304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi              }
23404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi          }
23504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi          break;
23604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
23704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      case DOWNMIX_TYPE_FOLD:
23804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        // optimize for the common formats
23904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        switch(pDwmModule->config.inputCfg.channels) {
24004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        case AUDIO_CHANNEL_OUT_QUAD:
24104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            Downmix_foldFromQuad(pSrc, pDst, numFrames, accumulate);
24204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            break;
24304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        case AUDIO_CHANNEL_OUT_SURROUND:
24404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            Downmix_foldFromSurround(pSrc, pDst, numFrames, accumulate);
24504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            break;
24604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        case AUDIO_CHANNEL_OUT_5POINT1:
24704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate);
24804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            break;
24904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        case AUDIO_CHANNEL_OUT_7POINT1:
25004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate);
25104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            break;
25204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        default:
25304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FIXME implement generic downmix
25404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            ALOGE("Multichannel configurations other than quad, 4.0, 5.1 and 7.1 are not supported");
25504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            break;
25604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
25704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
25804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
25904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      default:
26004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
26104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
26204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
26304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
26404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
26504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
26604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
26704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivistatic int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
26804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        void *pCmdData, uint32_t *replySize, void *pReplyData) {
26904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
27004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_module_t *pDwmModule = (downmix_module_t *) self;
27104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_object_t *pDownmixer;
27204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int retsize;
27304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
27404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pDwmModule == NULL || pDwmModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
27504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
27604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
27704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
27804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDownmixer = (downmix_object_t*) &pDwmModule->context;
27904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
28004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("Downmix_Command command %d cmdSize %d",cmdCode, cmdSize);
28104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
28204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    switch (cmdCode) {
28304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_INIT:
28404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pReplyData == NULL || *replySize != sizeof(int)) {
28504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
28604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
28704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        *(int *) pReplyData = Downmix_Init(pDwmModule);
28804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
28904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
29004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_CONFIG:
29104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
29204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                || pReplyData == NULL || *replySize != sizeof(int)) {
29304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
29404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
29504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        *(int *) pReplyData = Downmix_Configure(pDwmModule,
29604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                (effect_config_t *)pCmdData, false);
29704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
29804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
29904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_RESET:
30004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        Downmix_Reset(pDownmixer, false);
30104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
30204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
30304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_GET_PARAM:
30404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",
30504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                pCmdData, *replySize, pReplyData);
30604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
30704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                pReplyData == NULL ||
30804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                *replySize < (int) sizeof(effect_param_t) + 2 * sizeof(int32_t)) {
30904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
31004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
31104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        effect_param_t *rep = (effect_param_t *) pReplyData;
31204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
31304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",
31404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                *(int32_t *)rep->data, rep->vsize);
31504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        rep->status = Downmix_getParameter(pDownmixer, *(int32_t *)rep->data, &rep->vsize,
31604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                rep->data + sizeof(int32_t));
31704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize;
31804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
31904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
32004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_PARAM:
32104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, " \
32204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                "pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
32304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
32404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
32504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
32604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
32704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        effect_param_t *cmd = (effect_param_t *) pCmdData;
32804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        *(int *)pReplyData = Downmix_setParameter(pDownmixer, *(int32_t *)cmd->data,
32904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                cmd->vsize, cmd->data + sizeof(int32_t));
33004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
33104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
33204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_PARAM_DEFERRED:
33304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        //FIXME implement
33404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_DEFERRED not supported, FIXME");
33504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
33604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
33704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_PARAM_COMMIT:
33804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        //FIXME implement
33904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_COMMIT not supported, FIXME");
34004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
34104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
34204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_ENABLE:
34304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pReplyData == NULL || *replySize != sizeof(int)) {
34404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
34504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
34604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pDownmixer->state != DOWNMIX_STATE_INITIALIZED) {
34704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -ENOSYS;
34804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
34904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        pDownmixer->state = DOWNMIX_STATE_ACTIVE;
35004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("EFFECT_CMD_ENABLE() OK");
35104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        *(int *)pReplyData = 0;
35204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
35304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
35404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_DISABLE:
35504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pReplyData == NULL || *replySize != sizeof(int)) {
35604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
35704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
35804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pDownmixer->state != DOWNMIX_STATE_ACTIVE) {
35904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -ENOSYS;
36004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
36104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        pDownmixer->state = DOWNMIX_STATE_INITIALIZED;
36204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("EFFECT_CMD_DISABLE() OK");
36304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        *(int *)pReplyData = 0;
36404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
36504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
36604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_DEVICE:
36704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
36804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
36904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
37004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        // FIXME change type if playing on headset vs speaker
37104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData);
37204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
37304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
37404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_VOLUME: {
37504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        // audio output is always stereo => 2 channel volumes
37604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) {
37704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
37804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
37904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        // FIXME change volume
38004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGW("Downmix_Command command EFFECT_CMD_SET_VOLUME not supported, FIXME");
38104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
38204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
38304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("Downmix_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right);
38404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
38504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
38604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
38704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_AUDIO_MODE:
38804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
38904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
39004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
39104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
39204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
39304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
39404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_CONFIG_REVERSE:
39504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case EFFECT_CMD_SET_INPUT_DEVICE:
39604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        // these commands are ignored by a downmix effect
39704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
39804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
39904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    default:
40004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGW("Downmix_Command invalid command %d",cmdCode);
40104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
40204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
40304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
40404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
40504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
40604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
40704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
40804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_GetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor)
40904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi{
41004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_module_t *pDwnmxModule = (downmix_module_t *) self;
41104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
41204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pDwnmxModule == NULL ||
41304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDwnmxModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
41404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
41504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
41604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
41704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    memcpy(pDescriptor, &gDownmixDescriptor, sizeof(effect_descriptor_t));
41804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
41904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
42004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
42104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
42204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
42304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
42404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix internal functions
42504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *--------------------------------------------------------------------------*/
42604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
42704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
42804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_Init()
42904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
43004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
43104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Initialize downmix context and apply default parameters
43204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
43304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
43404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDwmModule    pointer to downmix effect module
43504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
43604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
43704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
43804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns:
43904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  0             indicates success
44004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
44104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects:
44204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  updates:
44304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->context.type
44404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->context.apply_volume_correction
44504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->config.inputCfg
44604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->config.outputCfg
44704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->config.inputCfg.samplingRate
44804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->config.outputCfg.samplingRate
44904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->context.state
45004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  doesn't set:
45104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *           pDwmModule->itfe
45204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
45304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
45404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
45504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
45604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_Init(downmix_module_t *pDwmModule) {
45704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
45804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("Downmix_Init module %p", pDwmModule);
45904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int ret = 0;
46004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
46104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    memset(&pDwmModule->context, 0, sizeof(downmix_object_t));
46204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
46304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
46404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
46504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
46604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.bufferProvider.getBuffer = NULL;
46704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
46804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.bufferProvider.cookie = NULL;
46904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
47004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
47104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.inputCfg.samplingRate = 44100;
47204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.samplingRate = pDwmModule->config.inputCfg.samplingRate;
47304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
47404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // set a default value for the access mode, but should be overwritten by caller
47504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
47604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
47704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
47804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.bufferProvider.getBuffer = NULL;
47904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
48004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.bufferProvider.cookie = NULL;
48104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    pDwmModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
48204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
48304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ret = Downmix_Configure(pDwmModule, &pDwmModule->config, true);
48404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (ret != 0) {
48504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("Downmix_Init error %d on module %p", ret, pDwmModule);
48604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    } else {
48704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        pDwmModule->context.state = DOWNMIX_STATE_INITIALIZED;
48804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
48904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
49004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return ret;
49104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
49204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
49304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
49404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
49504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_Configure()
49604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
49704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
49804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  Set input and output audio configuration.
49904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
50004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
50104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDwmModule  pointer to downmix effect module
50204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pConfig     pointer to effect_config_t structure containing input
50304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *                  and output audio parameters configuration
50404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  init        true if called from init function
50504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
50604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
50704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
50804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns:
50904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  0           indicates success
51004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
51104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects:
51204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
51304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
51404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
51504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
51604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init) {
51704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
51804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    downmix_object_t *pDownmixer = &pDwmModule->context;
51904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
52004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // Check configuration compatibility with build options, and effect capabilities
52104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate
52204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        || pConfig->outputCfg.channels != DOWNMIX_OUTPUT_CHANNELS
52304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT
52404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
52504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGE("Downmix_Configure error: invalid config");
52604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
52704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
52804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
52904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t));
53004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
53104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (init) {
53204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        pDownmixer->type = DOWNMIX_TYPE_FOLD;
53304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        pDownmixer->apply_volume_correction = false;
53404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        pDownmixer->input_channel_count = 8; // matches default input of AUDIO_CHANNEL_OUT_7POINT1
53504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    } else {
53604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        // when configuring the effect, do not allow a blank channel mask
53704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (pConfig->inputCfg.channels == 0) {
53804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            ALOGE("Downmix_Configure error: input channel mask can't be 0");
53904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
54004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
54104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        pDownmixer->input_channel_count = popcount(pConfig->inputCfg.channels);
54204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
54304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
54404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    Downmix_Reset(pDownmixer, init);
54504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
54604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
54704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
54804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
54904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
55004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
55104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_Reset()
55204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
55304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
55404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  Reset internal states.
55504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
55604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
55704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDownmixer   pointer to downmix context
55804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  init         true if called from init function
55904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
56004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
56104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi*
56204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns:
56304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  0            indicates success
56404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
56504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects:
56604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
56704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
56804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
56904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
57004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_Reset(downmix_object_t *pDownmixer, bool init) {
57104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // nothing to do here
57204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
57304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
57404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
57504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
57604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
57704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_setParameter()
57804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
57904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
58004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Set a Downmix parameter
58104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
58204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
58304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDownmixer    handle to instance data
58404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  param         parameter
58504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pValue        pointer to parameter value
58604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  size          value size
58704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
58804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
58904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
59004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns:
59104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  0             indicates success
59204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
59304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects:
59404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
59504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
59604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
59704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue) {
59804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
59904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int16_t value16;
60004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d",
60104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDownmixer, param, *(int16_t *)pValue, *(int32_t *)pValue);
60204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
60304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    switch (param) {
60404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
60504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      case DOWNMIX_PARAM_TYPE:
60604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        if (size != sizeof(downmix_type_t)) {
60704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %d, should be %d",
60804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                    size, sizeof(downmix_type_t));
60904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
61004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
61104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        value16 = *(int16_t *)pValue;
61204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGV("set DOWNMIX_PARAM_TYPE, type %d", value16);
6137d5b26230a179cd7bcc01f6578cd80d8c15a92a5Jean-Michel Trivi        if (!((value16 > DOWNMIX_TYPE_INVALID) && (value16 <= DOWNMIX_TYPE_LAST))) {
61404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %d", value16);
61504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            return -EINVAL;
61604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        } else {
61704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDownmixer->type = (downmix_type_t) value16;
61804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        break;
61904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
62004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      default:
62104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        ALOGE("Downmix_setParameter unknown parameter %d", param);
62204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        return -EINVAL;
62304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
62404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
62504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
62604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
62704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} /* end Downmix_setParameter */
62804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
62904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
63004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
63104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_getParameter()
63204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
63304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
63404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Get a Downmix parameter
63504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
63604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
63704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDownmixer    handle to instance data
63804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  param         parameter
63904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pValue        pointer to variable to hold retrieved value
64004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pSize         pointer to value size: maximum size as input
64104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
64204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
64304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  *pValue updated with parameter value
64404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  *pSize updated with actual value size
64504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
64604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Returns:
64704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  0             indicates success
64804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
64904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Side Effects:
65004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
65104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
65204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
65304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Triviint Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue) {
65404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int16_t *pValue16;
65504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
65604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    switch (param) {
65704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
65804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    case DOWNMIX_PARAM_TYPE:
65904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      if (*pSize < sizeof(int16_t)) {
66004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi          ALOGE("Downmix_getParameter invalid parameter size %d for DOWNMIX_PARAM_TYPE", *pSize);
66104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi          return -EINVAL;
66204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      }
66304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      pValue16 = (int16_t *)pValue;
66404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      *pValue16 = (int16_t) pDownmixer->type;
66504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      *pSize = sizeof(int16_t);
66604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %d", *pValue16);
66704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      break;
66804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
66904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    default:
67004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      ALOGE("Downmix_getParameter unknown parameter %d", param);
67104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi      return -EINVAL;
67204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
67304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
67404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    return 0;
67504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi} /* end Downmix_getParameter */
67604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
67704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
67804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
67904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFromQuad()
68004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
68104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
68204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a quad signal to stereo
68304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
68404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
68504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pSrc       quad audio samples to downmix
68604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  numFrames  the number of quad frames to downmix
68704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
68804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
68904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDst       downmixed stereo audio samples
69004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
69104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
69204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
69304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
69404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 0 is FL
69504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 1 is FR
69604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 2 is RL
69704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 3 is RR
69804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (accumulate) {
69904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
70004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + RL
70104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(pDst[0] + pSrc[0] + pSrc[2]);
70204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + RR
70304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(pDst[1] + pSrc[1] + pSrc[3]);
70404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 4;
70504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
70604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
70704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
70804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    } else { // same code as above but without adding and clamping pDst[i] to itself
70904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
71004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + RL
71104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(pSrc[0] + pSrc[2]);
71204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + RR
71304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(pSrc[1] + pSrc[3]);
71404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 4;
71504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
71604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
71704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
71804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
71904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
72004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
72104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
72204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
72304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFromSurround()
72404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
72504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
72604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a "surround sound" (mono rear) signal to stereo
72704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
72804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
72904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pSrc       surround signal to downmix
73004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  numFrames  the number of surround frames to downmix
73104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
73204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
73304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDst       downmixed stereo audio samples
73404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
73504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
73604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
73704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
73804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int32_t lt, rt, centerPlusRearContrib; // samples in Q19.12 format
73904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 0 is FL
74004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 1 is FR
74104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 2 is FC
74204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 3 is RC
74304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (accumulate) {
74404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
74504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // centerPlusRearContrib = FC(-3dB) + RC(-3dB)
74604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
74704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + centerPlusRearContrib
74804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            lt = (pSrc[0] << 12) + centerPlusRearContrib;
74904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + centerPlusRearContrib
75004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            rt = (pSrc[1] << 12) + centerPlusRearContrib;
75104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(pDst[0] + (lt >> 12));
75204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(pDst[1] + (rt >> 12));
75304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 4;
75404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
75504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
75604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
75704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    } else { // same code as above but without adding and clamping pDst[i] to itself
75804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
75904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // centerPlusRearContrib = FC(-3dB) + RC(-3dB)
76004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
76104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + centerPlusRearContrib
76204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            lt = (pSrc[0] << 12) + centerPlusRearContrib;
76304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + centerPlusRearContrib
76404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            rt = (pSrc[1] << 12) + centerPlusRearContrib;
76504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(lt >> 12);
76604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(rt >> 12);
76704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 4;
76804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
76904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
77004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
77104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
77204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
77304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
77404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
77504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
77604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFrom5Point1()
77704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
77804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
77904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a 5.1 signal to stereo
78004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
78104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
78204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pSrc       5.1 audio samples to downmix
78304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  numFrames  the number of 5.1 frames to downmix
78404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
78504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
78604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDst       downmixed stereo audio samples
78704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
78804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
78904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
79004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
79104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
79204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 0 is FL
79304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 1 is FR
79404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 2 is FC
79504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 3 is LFE
79604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 4 is RL
79704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 5 is RR
79804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (accumulate) {
79904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
80004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
80104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
80204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
80304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + centerPlusLfeContrib + RL
80404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
80504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + centerPlusLfeContrib + RR
80604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
80704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(pDst[0] + (lt >> 12));
80804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(pDst[1] + (rt >> 12));
80904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 6;
81004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
81104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
81204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
81304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    } else { // same code as above but without adding and clamping pDst[i] to itself
81404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
81504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
81604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
81704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
81804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + centerPlusLfeContrib + RL
81904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
82004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + centerPlusLfeContrib + RR
82104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
82204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(lt >> 12);
82304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(rt >> 12);
82404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 6;
82504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
82604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
82704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
82804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
82904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
83004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
83104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
83204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi/*----------------------------------------------------------------------------
83304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Downmix_foldFrom7Point1()
83404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
83504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Purpose:
83604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * downmix a 7.1 signal to stereo
83704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
83804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Inputs:
83904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pSrc       7.1 audio samples to downmix
84004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  numFrames  the number of 7.1 frames to downmix
84104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
84204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi * Outputs:
84304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *  pDst       downmixed stereo audio samples
84404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *
84504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi *----------------------------------------------------------------------------
84604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi */
84704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivivoid Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
84804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
84904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 0 is FL
85004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 1 is FR
85104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 2 is FC
85204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 3 is LFE
85304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 4 is RL
85404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 5 is RR
85504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 6 is SL
85604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    // sample at index 7 is SR
85704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    if (accumulate) {
85804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
85904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
86004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
86104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
86204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + centerPlusLfeContrib + SL + RL
86304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
86404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + centerPlusLfeContrib + SR + RR
86504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
86604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(lt >> 12);
86704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(rt >> 12);
86804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 8;
86904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
87004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
87104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
87204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    } else { // same code as above but without adding and clamping pDst[i] to itself
87304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        while (numFrames) {
87404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
87504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
87604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
87704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FL + centerPlusLfeContrib + SL + RL
87804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
87904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            // FR + centerPlusLfeContrib + SR + RR
88004c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
88104c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[0] = clamp16(pDst[0] + (lt >> 12));
88204c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst[1] = clamp16(pDst[1] + (rt >> 12));
88304c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pSrc += 8;
88404c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            pDst += 2;
88504c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi            numFrames--;
88604c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi        }
88704c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi    }
88804c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi}
88904c1e531b5913c09aa9b2e59e2b8ed9b4d8a4cbaJean-Michel Trivi
890