AudioMixer.cpp revision c263ca0ad8b6bdf5b0693996bc5f2f5916e0cd49
1326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams/*
2a04e30dbb5ab11592b03666bb3d102070759c58eAlex Sakhartchouk**
3326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** Copyright 2007, The Android Open Source Project
4326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams**
5326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** Licensed under the Apache License, Version 2.0 (the "License");
6326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** you may not use this file except in compliance with the License.
7326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** You may obtain a copy of the License at
8326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams**
9326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams**     http://www.apache.org/licenses/LICENSE-2.0
10326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams**
11326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** Unless required by applicable law or agreed to in writing, software
12326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** distributed under the License is distributed on an "AS IS" BASIS,
13326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** See the License for the specific language governing permissions and
15326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams** limitations under the License.
16326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams*/
17326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
18326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#define LOG_TAG "AudioMixer"
19326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams//#define LOG_NDEBUG 0
205ae678f2e68e25bd74cdc408df354c3b6fe481bfMathias Agopian
21326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include "Configuration.h"
22158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams#include <stdint.h>
23158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams#include <string.h>
247bf29ddc35450d8064541c42c99a1f48be6cf0ddJason Sams#include <stdlib.h>
25158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams#include <sys/types.h>
2676371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato
2776371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato#include <utils/Errors.h>
28158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams#include <utils/Log.h>
298d957fa762eff6c03a93ddea9405d9575665f1ecJason Sams
308d957fa762eff6c03a93ddea9405d9575665f1ecJason Sams#include <cutils/bitops.h>
31158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams#include <cutils/compiler.h>
32326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <utils/Debug.h>
33326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
34326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <system/audio.h>
35fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Sams
36ca3f09c0924e9515901dfd47fa5f95385d53cf80Stephen Hines#include <audio_utils/primitives.h>
37326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams#include <audio_utils/format.h>
38afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk#include <common_time/local_clock.h>
396b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams#include <common_time/cc_helper.h>
406b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams
414b3de47071d875faaa7d419d050a464b09538797Jason Sams#include <media/EffectsFactoryApi.h>
425c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams
4386d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams#include "AudioMixer.h"
445c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams
456b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Samsnamespace android {
466b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams
476b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams// ----------------------------------------------------------------------------
485c1c79a54c63b9de8c391f7ed890c02f280ec17fJason SamsAudioMixer::DownmixerBufferProvider::DownmixerBufferProvider() : AudioBufferProvider(),
49326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        mTrackBufferProvider(NULL), mDownmixHandle(NULL)
50326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams{
51afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk}
524b3de47071d875faaa7d419d050a464b09538797Jason Sams
5333b6e3b91329080e5cdd0b8fdbcd3e6a906032aeJason SamsAudioMixer::DownmixerBufferProvider::~DownmixerBufferProvider()
5433b6e3b91329080e5cdd0b8fdbcd3e6a906032aeJason Sams{
5560709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    ALOGV("AudioMixer deleting DownmixerBufferProvider (%p)", this);
5660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    EffectRelease(mDownmixHandle);
57c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams}
58c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams
59c946b614ee6c983215cc3de7834a7a334f860d68Jason Samsstatus_t AudioMixer::DownmixerBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
60c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams        int64_t pts) {
61c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams    //ALOGV("DownmixerBufferProvider::getNextBuffer()");
62c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams    if (mTrackBufferProvider != NULL) {
63c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams        status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
6460709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams        if (res == OK) {
6560709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams            mDownmixConfig.inputCfg.buffer.frameCount = pBuffer->frameCount;
6660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams            mDownmixConfig.inputCfg.buffer.raw = pBuffer->raw;
67c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams            mDownmixConfig.outputCfg.buffer.frameCount = pBuffer->frameCount;
68c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams            mDownmixConfig.outputCfg.buffer.raw = mDownmixConfig.inputCfg.buffer.raw;
69c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams            // in-place so overwrite the buffer contents, has been set in prepareTrackForDownmix()
70c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams            //mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
71c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams
72c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams            res = (*mDownmixHandle)->process(mDownmixHandle,
73c946b614ee6c983215cc3de7834a7a334f860d68Jason Sams                    &mDownmixConfig.inputCfg.buffer, &mDownmixConfig.outputCfg.buffer);
7460709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams            //ALOGV("getNextBuffer is downmixing");
7560709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams        }
7633b6e3b91329080e5cdd0b8fdbcd3e6a906032aeJason Sams        return res;
77afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    } else {
7860709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams        ALOGE("DownmixerBufferProvider::getNextBuffer() error: NULL track buffer provider");
791030893d9b99b72468034da13df025bda479bb97Jason Sams        return NO_INIT;
80c61346b91434307c5003029017b54ce9c49112beJason Sams    }
81c9d43db4d216b01b13aebfdb31d5615909591b33Jason Sams}
821030893d9b99b72468034da13df025bda479bb97Jason Sams
831030893d9b99b72468034da13df025bda479bb97Jason Samsvoid AudioMixer::DownmixerBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
84afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    //ALOGV("DownmixerBufferProvider::releaseBuffer()");
852dca84dd6c07992f78ad050177975f16486dd77eJason Sams    if (mTrackBufferProvider != NULL) {
868c401effb0837155fc39ca0364f57a882d127d38Jason Sams        mTrackBufferProvider->releaseBuffer(pBuffer);
872382aba4a55c6ae74789c478eead8fbd96593321Jason Sams    } else {
88c61346b91434307c5003029017b54ce9c49112beJason Sams        ALOGE("DownmixerBufferProvider::releaseBuffer() error: NULL track buffer provider");
892382aba4a55c6ae74789c478eead8fbd96593321Jason Sams    }
908cfdd24fec22080b72266d33f61befc4a98b77c6Jason Sams}
9124371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams
9224371d93cdb6999971c4058f78974da3c3d5fc64Jason Samstemplate <typename T>
93cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason SamsT min(const T& a, const T& b)
94afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk{
95b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    return a < b ? a : b;
9624371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams}
9724371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams
9824371d93cdb6999971c4058f78974da3c3d5fc64Jason SamsAudioMixer::ReformatBufferProvider::ReformatBufferProvider(int32_t channels,
99b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        audio_format_t inputFormat, audio_format_t outputFormat) :
100b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        mTrackBufferProvider(NULL),
101b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        mChannels(channels),
10224371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        mInputFormat(inputFormat),
103cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason Sams        mOutputFormat(outputFormat),
104afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        mInputFrameSize(channels * audio_bytes_per_sample(inputFormat)),
10524371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        mOutputFrameSize(channels * audio_bytes_per_sample(outputFormat)),
10624371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        mOutputData(NULL),
10724371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        mOutputCount(0),
10824371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        mConsumed(0)
109cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason Sams{
110afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    ALOGV("ReformatBufferProvider(%p)(%d, %#x, %#x)", this, channels, inputFormat, outputFormat);
11124371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    if (requiresInternalBuffers()) {
1121d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        mOutputCount = 256;
1131d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        (void)posix_memalign(&mOutputData, 32, mOutputCount * mOutputFrameSize);
11424371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    }
115c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    mBuffer.frameCount = 0;
116c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk}
117c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk
11824371d93cdb6999971c4058f78974da3c3d5fc64Jason SamsAudioMixer::ReformatBufferProvider::~ReformatBufferProvider()
11924371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams{
12024371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    ALOGV("~ReformatBufferProvider(%p)", this);
121afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (mBuffer.frameCount != 0) {
1221d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams        mTrackBufferProvider->releaseBuffer(&mBuffer);
1231d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams    }
124c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    free(mOutputData);
125c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk}
126c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk
127c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchoukstatus_t AudioMixer::ReformatBufferProvider::getNextBuffer(AudioBufferProvider::Buffer *pBuffer,
128afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        int64_t pts) {
129c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    //ALOGV("ReformatBufferProvider(%p)::getNextBuffer(%p (%zu), %lld)",
130c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    //        this, pBuffer, pBuffer->frameCount, pts);
131c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    if (!requiresInternalBuffers()) {
132c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk        status_t res = mTrackBufferProvider->getNextBuffer(pBuffer, pts);
133c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk        if (res == OK) {
1341d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            memcpy_by_audio_format(pBuffer->raw, mOutputFormat, pBuffer->raw, mInputFormat,
1351d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams                    pBuffer->frameCount * mChannels);
136afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        }
13724371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        return res;
13824371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    }
13924371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    if (mBuffer.frameCount == 0) {
14024371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        mBuffer.frameCount = pBuffer->frameCount;
14124371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        status_t res = mTrackBufferProvider->getNextBuffer(&mBuffer, pts);
14224371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        // TODO: Track down a bug in the upstream provider
143afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        // LOG_ALWAYS_FATAL_IF(res == OK && mBuffer.frameCount == 0,
14424371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        //        "ReformatBufferProvider::getNextBuffer():"
14524371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        //        " Invalid zero framecount returned from getNextBuffer()");
14624371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams        if (res != OK || mBuffer.frameCount == 0) {
14724371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams            pBuffer->raw = NULL;
1481d54f10f3c23e0d7ec57e52ec3b0701a2a5ed24eJason Sams            pBuffer->frameCount = 0;
1492dca84dd6c07992f78ad050177975f16486dd77eJason Sams            return res;
1502dca84dd6c07992f78ad050177975f16486dd77eJason Sams        }
1512dca84dd6c07992f78ad050177975f16486dd77eJason Sams    }
15224371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams    ALOG_ASSERT(mConsumed < mBuffer.frameCount);
1532dca84dd6c07992f78ad050177975f16486dd77eJason Sams    size_t count = min(mOutputCount, mBuffer.frameCount - mConsumed);
1542dca84dd6c07992f78ad050177975f16486dd77eJason Sams    count = min(count, pBuffer->frameCount);
15564cd98e83d33011950b88f229d013e06c62b36e9Alex Sakhartchouk    pBuffer->raw = mOutputData;
1562dca84dd6c07992f78ad050177975f16486dd77eJason Sams    pBuffer->frameCount = count;
1572dca84dd6c07992f78ad050177975f16486dd77eJason Sams    //ALOGV("reformatting %d frames from %#x to %#x, %d chan",
1582dca84dd6c07992f78ad050177975f16486dd77eJason Sams    //        pBuffer->frameCount, mInputFormat, mOutputFormat, mChannels);
1592dca84dd6c07992f78ad050177975f16486dd77eJason Sams    memcpy_by_audio_format(pBuffer->raw, mOutputFormat,
160c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk            (uint8_t*)mBuffer.raw + mConsumed * mInputFrameSize, mInputFormat,
161c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk            pBuffer->frameCount * mChannels);
1622dca84dd6c07992f78ad050177975f16486dd77eJason Sams    return OK;
163326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
164326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
165afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid AudioMixer::ReformatBufferProvider::releaseBuffer(AudioBufferProvider::Buffer *pBuffer) {
166900f1616bf33c7ba13cf2a737832a95bcd176388Jason Sams    //ALOGV("ReformatBufferProvider(%p)::releaseBuffer(%p(%zu))",
167721acc495b859c6d884725a4f9b5523583dd11c7Jason Sams    //        this, pBuffer, pBuffer->frameCount);
168c19ff0177a7a0dadfc01b1990f822354fdc95991Alex Sakhartchouk    if (!requiresInternalBuffers()) {
169721acc495b859c6d884725a4f9b5523583dd11c7Jason Sams        mTrackBufferProvider->releaseBuffer(pBuffer);
170c19ff0177a7a0dadfc01b1990f822354fdc95991Alex Sakhartchouk        return;
171c19ff0177a7a0dadfc01b1990f822354fdc95991Alex Sakhartchouk    }
172a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams    // LOG_ALWAYS_FATAL_IF(pBuffer->frameCount == 0, "Invalid framecount");
173326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    mConsumed += pBuffer->frameCount; // TODO: update for efficiency to reuse existing content
174326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    if (mConsumed != 0 && mConsumed >= mBuffer.frameCount) {
175889fe50e7aaebed8cb8284b16a0e51e64e8a3a9cAlex Sakhartchouk        mConsumed = 0;
176721acc495b859c6d884725a4f9b5523583dd11c7Jason Sams        mTrackBufferProvider->releaseBuffer(&mBuffer);
177889fe50e7aaebed8cb8284b16a0e51e64e8a3a9cAlex Sakhartchouk        // ALOG_ASSERT(mBuffer.frameCount == 0);
178889fe50e7aaebed8cb8284b16a0e51e64e8a3a9cAlex Sakhartchouk    }
179afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    pBuffer->raw = NULL;
18076371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato    pBuffer->frameCount = 0;
1811fddd90849deaae89b546ff492c345d485bbce42Jason Sams}
18276371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onorato
18376371fff76412fd020e24ddb8bf1ddb5c75f0ed1Joe Onoratovoid AudioMixer::ReformatBufferProvider::reset() {
184326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    if (mBuffer.frameCount != 0) {
185afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        mTrackBufferProvider->releaseBuffer(&mBuffer);
1860cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk    }
187c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    mConsumed = 0;
188ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk}
189ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk
19009c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk// ----------------------------------------------------------------------------
1910cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchoukbool AudioMixer::sIsMultichannelCapable = false;
1921809bde133e0d66f06cea65887d9ceb3c70f8b95Alex Sakhartchouk
1931809bde133e0d66f06cea65887d9ceb3c70f8b95Alex Sakhartchoukeffect_descriptor_t AudioMixer::sDwnmFxDesc;
19409c67356bbeee0a97a20a06c95b66756838cb541Alex Sakhartchouk
195ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk// Ensure mConfiguredNames bitmask is initialized properly on all architectures.
196c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk// The value of 1 << x is undefined in C when x >= 32.
1970cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk
19809c67356bbeee0a97a20a06c95b66756838cb541Alex SakhartchoukAudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate, uint32_t maxNumTracks)
199c8fb69e4a3e01501a3d38a6d3ea185e583d3f493Alex Sakhartchouk    :   mTrackNames(0), mConfiguredNames((maxNumTracks >= 32 ? 0 : 1 << maxNumTracks) - 1),
2000cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk        mSampleRate(sampleRate)
2011809bde133e0d66f06cea65887d9ceb3c70f8b95Alex Sakhartchouk{
202ca5a454e022caec6c6d3cbb404cc09ea095ba97aAlex Sakhartchouk    // AudioMixer is not yet capable of multi-channel beyond stereo
2030cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(2 == MAX_NUM_CHANNELS);
2040cae59f7d8dd63d1bf0ca4abedecb4cfa3ab1921Alex Sakhartchouk
205afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    ALOG_ASSERT(maxNumTracks <= MAX_NUM_TRACKS, "maxNumTracks %u > MAX_NUM_TRACKS %u",
20683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams            maxNumTracks, MAX_NUM_TRACKS);
207b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk
20883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    // AudioMixer is not yet capable of more than 32 active track inputs
20983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    ALOG_ASSERT(32 >= MAX_NUM_TRACKS, "bad MAX_NUM_TRACKS %d", MAX_NUM_TRACKS);
21083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
211b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    // AudioMixer is not yet capable of multi-channel output beyond stereo
21283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    ALOG_ASSERT(2 == MAX_NUM_CHANNELS, "bad MAX_NUM_CHANNELS %d", MAX_NUM_CHANNELS);
21383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
21483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    pthread_once(&sOnceControl, &sInitRoutine);
21583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
21683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    mState.enabledTracks= 0;
21783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    mState.needsChanged = 0;
21883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    mState.frameCount   = frameCount;
21983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    mState.hook         = process__nop;
22083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    mState.outputTemp   = NULL;
221d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams    mState.resampleTemp = NULL;
22283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    mState.mLog         = &mDummyLog;
22383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    // mState.reserved
22483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
22583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    // FIXME Most of the following initialization is probably redundant since
22683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    // tracks[i] should only be referenced if (mTrackNames & (1 << i)) != 0
22783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    // and mTrackNames is initially 0.  However, leave it here until that's verified.
228d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams    track_t* t = mState.tracks;
229d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams    for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
230d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams        t->resampler = NULL;
231d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams        t->downmixerBufferProvider = NULL;
232d3e7107c60ce06d637d83fa0db783ecdd0ad534cJason Sams        t++;
23383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    }
23483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
23583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams}
23683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
23783c451a4ef4388e002482e383d488ca9b7b7600dJason SamsAudioMixer::~AudioMixer()
23883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams{
23983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    track_t* t = mState.tracks;
24083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    for (unsigned i=0 ; i < MAX_NUM_TRACKS ; i++) {
24183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        delete t->resampler;
24283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        delete t->downmixerBufferProvider;
243c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk        t++;
244da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    }
24583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    delete [] mState.outputTemp;
24683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams    delete [] mState.resampleTemp;
24783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams}
24883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams
249e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Samsvoid AudioMixer::setLog(NBLog::Writer *log)
250e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams{
251e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams    mState.mLog = log;
25283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams}
253e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams
254e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Samsint AudioMixer::getTrackName(audio_channel_mask_t channelMask,
255dc314a172d48479053f258b485d7d0284b5b5b1fJason Sams        audio_format_t format, int sessionId)
256dc314a172d48479053f258b485d7d0284b5b5b1fJason Sams{
257dc314a172d48479053f258b485d7d0284b5b5b1fJason Sams    if (!isValidPcmTrackFormat(format)) {
258dc314a172d48479053f258b485d7d0284b5b5b1fJason Sams        ALOGE("AudioMixer::getTrackName invalid format (%#x)", format);
259dc314a172d48479053f258b485d7d0284b5b5b1fJason Sams        return -1;
260e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams    }
261e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams    uint32_t names = (~mTrackNames) & mConfiguredNames;
262e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams    if (names != 0) {
26383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        int n = __builtin_ctz(names);
2647257c7ee4b66f00c43d9235f3ac600061ae79968Alex Sakhartchouk        ALOGV("add track (%d)", n);
26583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // assume default parameters for the track, except where noted below
26683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        track_t* t = &mState.tracks[n];
267e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams        t->needs = 0;
268e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams        t->volume[0] = UNITY_GAIN_INT;
269dc314a172d48479053f258b485d7d0284b5b5b1fJason Sams        t->volume[1] = UNITY_GAIN_INT;
27083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // no initialization needed
27183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // t->prevVolume[0]
27283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // t->prevVolume[1]
27383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->volumeInc[0] = 0;
27483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->volumeInc[1] = 0;
275e0aab4a8ff1cffd8cfaedc2623db94072549e0e5Jason Sams        t->auxLevel = 0;
27683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->auxInc = 0;
27783c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // no initialization needed
27883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // t->prevAuxLevel
27983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // t->frameCount
28083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->channelCount = audio_channel_count_from_out_mask(channelMask);
28183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->enabled = false;
282ca7c202abc3853e96d1d0d77b672789622eff99dJason Sams        ALOGV_IF(channelMask != AUDIO_CHANNEL_OUT_STEREO,
283ca7c202abc3853e96d1d0d77b672789622eff99dJason Sams                "Non-stereo channel mask: %d\n", channelMask);
28483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->channelMask = channelMask;
28583c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->sessionId = sessionId;
28683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // setBufferProvider(name, AudioBufferProvider *) is required before enable(name)
28786d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams        t->bufferProvider = NULL;
28883c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->buffer.raw = NULL;
28983c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // no initialization needed
29083c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        // t->buffer.frameCount
29183c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->hook = NULL;
29283c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->in = NULL;
29383c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->resampler = NULL;
29483c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->sampleRate = mSampleRate;
29586d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams        // setParameter(name, TRACK, MAIN_BUFFER, mixBuffer) is required before enable(name)
29683c451a4ef4388e002482e383d488ca9b7b7600dJason Sams        t->mainBuffer = NULL;
297326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        t->auxBuffer = NULL;
298326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        t->mInputBufferProvider = NULL;
299741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        t->mReformatBufferProvider = NULL;
300249d453869cca82dcb57123f6d1c8df3ca9f4372Jason Sams        t->downmixerBufferProvider = NULL;
3012e8665de7c0eb4514c67baf8693d61c892e5303dJason Sams        t->mMixerFormat = AUDIO_FORMAT_PCM_16_BIT;
302741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        t->mFormat = format;
303741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        t->mMixerInFormat = AUDIO_FORMAT_PCM_16_BIT;
304741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        if (t->mFormat != t->mMixerInFormat) {
305741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams            prepareTrackForReformat(t, n);
306741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        }
307741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        status_t status = initTrackDownmix(&mState.tracks[n], n, channelMask);
308741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        if (status != OK) {
309741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams            ALOGE("AudioMixer::getTrackName invalid channelMask (%#x)", channelMask);
310741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams            return -1;
311741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        }
312741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        mTrackNames |= 1 << n;
313741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        return TRACK0 + n;
314c700e649ca44d0dcff8b271e42d949ea72fe3c63Alex Sakhartchouk    }
315da6d34a5a6ece8c30d20673b9b6ff07d8c91768bAlex Sakhartchouk    ALOGE("AudioMixer::getTrackName out of available tracks");
316741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams    return -1;
317c7cec1e3577cc77a5a73d5bd5a82733b1b9936a1Jason Sams}
318249d453869cca82dcb57123f6d1c8df3ca9f4372Jason Sams
319cf912de17f1e086ccea707d8607a3d2eda56b98fJason Samsvoid AudioMixer::invalidateState(uint32_t mask)
320741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams{
321741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams    if (mask != 0) {
3222382aba4a55c6ae74789c478eead8fbd96593321Jason Sams        mState.needsChanged |= mask;
3232382aba4a55c6ae74789c478eead8fbd96593321Jason Sams        mState.hook = process__validate;
324ee803446857b14d97f3e90a4f530604b6be9c867Jason Sams    }
325ee803446857b14d97f3e90a4f530604b6be9c867Jason Sams }
326ee803446857b14d97f3e90a4f530604b6be9c867Jason Sams
327ee803446857b14d97f3e90a4f530604b6be9c867Jason Samsstatus_t AudioMixer::initTrackDownmix(track_t* pTrack, int trackNum, audio_channel_mask_t mask)
328ee803446857b14d97f3e90a4f530604b6be9c867Jason Sams{
329ee803446857b14d97f3e90a4f530604b6be9c867Jason Sams    uint32_t channelCount = audio_channel_count_from_out_mask(mask);
3302382aba4a55c6ae74789c478eead8fbd96593321Jason Sams    ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
3312382aba4a55c6ae74789c478eead8fbd96593321Jason Sams    status_t status = OK;
3322382aba4a55c6ae74789c478eead8fbd96593321Jason Sams    if (channelCount > MAX_NUM_CHANNELS) {
333afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        pTrack->channelMask = mask;
334158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams        pTrack->channelCount = channelCount;
335158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams        ALOGV("initTrackDownmix(track=%d, mask=0x%x) calls prepareTrackForDownmix()",
336158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams                trackNum, mask);
337158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams        status = prepareTrackForDownmix(pTrack, trackNum);
3382dca84dd6c07992f78ad050177975f16486dd77eJason Sams    } else {
339158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams        unprepareTrackForDownmix(pTrack, trackNum);
340158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams    }
341158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams    return status;
342158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams}
343158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams
344158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Samsvoid AudioMixer::unprepareTrackForDownmix(track_t* pTrack, int trackName __unused) {
345158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams    ALOGV("AudioMixer::unprepareTrackForDownmix(%d)", trackName);
346158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams
347158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams    if (pTrack->downmixerBufferProvider != NULL) {
3487bf29ddc35450d8064541c42c99a1f48be6cf0ddJason Sams        // this track had previously been configured with a downmixer, delete it
349158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams        ALOGV(" deleting old downmixer");
350158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams        delete pTrack->downmixerBufferProvider;
351158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams        pTrack->downmixerBufferProvider = NULL;
352afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        reconfigureBufferProviders(pTrack);
3535c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    } else {
354326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        ALOGV(" nothing to do, no downmixer to delete");
355326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    }
35686f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams}
357e514b45de8561fbc6ef6770845102ca10b0a69d7Jason Sams
358a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Samsstatus_t AudioMixer::prepareTrackForDownmix(track_t* pTrack, int trackName)
359cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines{
3607b3e9bd825901e33661e3c385e3e7c6f40ca6000Alex Sakhartchouk    ALOGV("AudioMixer::prepareTrackForDownmix(%d) with mask 0x%x", trackName, pTrack->channelMask);
361b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk
36286c6b5fecb3e4e68668fdb5640770545501e778fStephen Hines    // discard the previous downmixer if there was one
3635c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    unprepareTrackForDownmix(pTrack, trackName);
3645c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams
365afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    DownmixerBufferProvider* pDbp = new DownmixerBufferProvider();
3665c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    int32_t status;
367b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk
3685c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    if (!sIsMultichannelCapable) {
3695c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        ALOGE("prepareTrackForDownmix(%d) fails: mixer doesn't support multichannel content",
3705c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams                trackName);
3715c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        goto noDownmixForActiveTrack;
3725c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    }
3735c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams
3745c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    if (EffectCreate(&sDwnmFxDesc.uuid,
375b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk            pTrack->sessionId /*sessionId*/, -2 /*ioId not relevant here, using random value*/,
376b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk            &pDbp->mDownmixHandle/*pHandle*/) != 0) {
377b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        ALOGE("prepareTrackForDownmix(%d) fails: error creating downmixer effect", trackName);
378b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        goto noDownmixForActiveTrack;
379b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    }
380b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk
381afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    // channel input configuration will be overridden per-track
3825c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    pDbp->mDownmixConfig.inputCfg.channels = pTrack->channelMask;
3835c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    pDbp->mDownmixConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
3841a4efa363916977ef9aeab756725b3bdc880a15bJason Sams    pDbp->mDownmixConfig.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
3852382aba4a55c6ae74789c478eead8fbd96593321Jason Sams    pDbp->mDownmixConfig.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
3861a4efa363916977ef9aeab756725b3bdc880a15bJason Sams    pDbp->mDownmixConfig.inputCfg.samplingRate = pTrack->sampleRate;
3875c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    pDbp->mDownmixConfig.outputCfg.samplingRate = pTrack->sampleRate;
3885c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams    pDbp->mDownmixConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
3896b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams    pDbp->mDownmixConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
3906b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams    // input and output buffer provider, and frame count will not be used as the downmix effect
3916b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams    // process() function is called directly (see DownmixerBufferProvider::getNextBuffer())
3926b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams    pDbp->mDownmixConfig.inputCfg.mask = EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS |
3936b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams            EFFECT_CONFIG_FORMAT | EFFECT_CONFIG_ACC_MODE;
394a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams    pDbp->mDownmixConfig.outputCfg.mask = pDbp->mDownmixConfig.inputCfg.mask;
3956b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams
396326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    {// scope for local variables that are not used in goto label "noDownmixForActiveTrack"
397a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams        int cmdStatus;
398a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams        uint32_t replySize = sizeof(int);
399a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams
400fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Sams        // Configure and enable downmixer
401fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Sams        status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
402fb03a22ad2adadc1ff50a8b50d43ad7fcc3fa6edJason Sams                EFFECT_CMD_SET_CONFIG /*cmdCode*/, sizeof(effect_config_t) /*cmdSize*/,
403e57691037aea219562ac686429b4b98202aab7bcJason Sams                &pDbp->mDownmixConfig /*pCmdData*/,
404a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams                &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
405a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams        if ((status != 0) || (cmdStatus != 0)) {
406a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams            ALOGE("error %d while configuring downmixer for track %d", status, trackName);
4075c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams            goto noDownmixForActiveTrack;
408a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams        }
409a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams        replySize = sizeof(int);
4107257c7ee4b66f00c43d9235f3ac600061ae79968Alex Sakhartchouk        status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
411992a0b70d8fd7a14f0c57bc3c7e16c1f269a6609Jason Sams                EFFECT_CMD_ENABLE /*cmdCode*/, 0 /*cmdSize*/, NULL /*pCmdData*/,
41224371d93cdb6999971c4058f78974da3c3d5fc64Jason Sams                &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
413a891933b4c5ab1b63103add167269cfc404c2adfJason Sams        if ((status != 0) || (cmdStatus != 0)) {
4145086938044e0a9b6b1138f915d0d252fe046e102Jason Sams            ALOGE("error %d while enabling downmixer for track %d", status, trackName);
415a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams            goto noDownmixForActiveTrack;
416326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        }
417326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
4185c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        // Set downmix type
4197bf29ddc35450d8064541c42c99a1f48be6cf0ddJason Sams        // parameter size rounded for padding on 32bit boundary
420afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        const int psizePadded = ((sizeof(downmix_params_t) - 1)/sizeof(int) + 1) * sizeof(int);
421181334092f78273d0da2d854ebbe7b24508d3bfcJason Sams        const int downmixParamSize =
422181334092f78273d0da2d854ebbe7b24508d3bfcJason Sams                sizeof(effect_param_t) + psizePadded + sizeof(downmix_type_t);
423181334092f78273d0da2d854ebbe7b24508d3bfcJason Sams        effect_param_t * const param = (effect_param_t *) malloc(downmixParamSize);
4245c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        param->psize = sizeof(downmix_params_t);
4252cfe51e7a9eef3dec091ce7c15d2a5a2216e9d3eJason Sams        const downmix_params_t downmixParam = DOWNMIX_PARAM_TYPE;
4265c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        memcpy(param->data, &downmixParam, param->psize);
4275c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        const downmix_type_t downmixType = DOWNMIX_TYPE_FOLD;
4285c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams        param->vsize = sizeof(downmix_type_t);
429a658e905f14fe500bfee3812b213a73cb37ef6f2Jason Sams        memcpy(param->data + psizePadded, &downmixType, param->vsize);
4305c1c79a54c63b9de8c391f7ed890c02f280ec17fJason Sams
431326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        status = (*pDbp->mDownmixHandle)->command(pDbp->mDownmixHandle,
432326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                EFFECT_CMD_SET_PARAM /* cmdCode */, downmixParamSize/* cmdSize */,
433afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                param /*pCmndData*/, &replySize /*replySize*/, &cmdStatus /*pReplyData*/);
43486d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams
435cf912de17f1e086ccea707d8607a3d2eda56b98fJason Sams        free(param);
436b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk
437b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        if ((status != 0) || (cmdStatus != 0)) {
438b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk            ALOGE("error %d while setting downmix type for track %d", status, trackName);
439b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk            goto noDownmixForActiveTrack;
440b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        } else {
441b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk            ALOGV("downmix type set to %d for track %d", (int) downmixType, trackName);
442326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        }
443b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    }// end of scope for local variables that are not used in goto label "noDownmixForActiveTrack"
444b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk
445326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    // initialization successful:
446b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    pTrack->downmixerBufferProvider = pDbp;
447b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    reconfigureBufferProviders(pTrack);
448b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    return NO_ERROR;
449249d453869cca82dcb57123f6d1c8df3ca9f4372Jason Sams
450b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex SakhartchouknoDownmixForActiveTrack:
451b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    delete pDbp;
452b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    pTrack->downmixerBufferProvider = NULL;
453b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    reconfigureBufferProviders(pTrack);
454b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    return NO_INIT;
455b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk}
456b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk
457326e0ddf89e8df2837752fbfd7a014814b32082cJason Samsvoid AudioMixer::unprepareTrackForReformat(track_t* pTrack, int trackName __unused) {
45886d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams    ALOGV("AudioMixer::unprepareTrackForReformat(%d)", trackName);
459326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    if (pTrack->mReformatBufferProvider != NULL) {
460326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        delete pTrack->mReformatBufferProvider;
4617257c7ee4b66f00c43d9235f3ac600061ae79968Alex Sakhartchouk        pTrack->mReformatBufferProvider = NULL;
4624820e8bb83b1f78e6232ebe853221f737da2a1eaJason Sams        reconfigureBufferProviders(pTrack);
4634b3de47071d875faaa7d419d050a464b09538797Jason Sams    }
464458f2dc26b7d34c2138c7bfbd95914240084e6bdJason Sams}
4657257c7ee4b66f00c43d9235f3ac600061ae79968Alex Sakhartchouk
4664b3de47071d875faaa7d419d050a464b09538797Jason Samsstatus_t AudioMixer::prepareTrackForReformat(track_t* pTrack, int trackName)
4674b3de47071d875faaa7d419d050a464b09538797Jason Sams{
468613cad1702dbb76eb2a6ba0cfcb43b9fe207cebcJason Sams    ALOGV("AudioMixer::prepareTrackForReformat(%d) with format %#x", trackName, pTrack->mFormat);
4694b3de47071d875faaa7d419d050a464b09538797Jason Sams    // discard the previous reformatter if there was one
470771565f47fc44608444c00aa8fa3bda769ceaeceJason Sams     unprepareTrackForReformat(pTrack, trackName);
471a544b6368d7ddae47985da92d6bcf86798b376c6Alex Sakhartchouk     pTrack->mReformatBufferProvider = new ReformatBufferProvider(
472458f2dc26b7d34c2138c7bfbd95914240084e6bdJason Sams             audio_channel_count_from_out_mask(pTrack->channelMask),
473458f2dc26b7d34c2138c7bfbd95914240084e6bdJason Sams             pTrack->mFormat, pTrack->mMixerInFormat);
474458f2dc26b7d34c2138c7bfbd95914240084e6bdJason Sams     reconfigureBufferProviders(pTrack);
475afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk     return NO_ERROR;
4764820e8bb83b1f78e6232ebe853221f737da2a1eaJason Sams}
47786f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams
47886f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Samsvoid AudioMixer::reconfigureBufferProviders(track_t* pTrack)
47986f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams{
480afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    pTrack->bufferProvider = pTrack->mInputBufferProvider;
4814820e8bb83b1f78e6232ebe853221f737da2a1eaJason Sams    if (pTrack->mReformatBufferProvider) {
48286f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams        pTrack->mReformatBufferProvider->mTrackBufferProvider = pTrack->bufferProvider;
48386f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams        pTrack->bufferProvider = pTrack->mReformatBufferProvider;
48486f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams    }
485afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    if (pTrack->downmixerBufferProvider) {
4864820e8bb83b1f78e6232ebe853221f737da2a1eaJason Sams        pTrack->downmixerBufferProvider->mTrackBufferProvider = pTrack->bufferProvider;
487326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        pTrack->bufferProvider = pTrack->downmixerBufferProvider;
488326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    }
489326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
49060709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams
4914820e8bb83b1f78e6232ebe853221f737da2a1eaJason Samsvoid AudioMixer::deleteTrackName(int name)
4928ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams{
4938ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    ALOGV("AudioMixer::deleteTrackName(%d)", name);
4948ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    name -= TRACK0;
4958ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
4968ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    ALOGV("deleteTrackName(%d)", name);
497326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    track_t& track(mState.tracks[ name ]);
498326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams    if (track.enabled) {
49960709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams        track.enabled = false;
5004820e8bb83b1f78e6232ebe853221f737da2a1eaJason Sams        invalidateState(1<<name);
5018ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    }
5028ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    // delete the resampler
5038ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    delete track.resampler;
5048ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    track.resampler = NULL;
5058ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    // delete the downmixer
506cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason Sams    unprepareTrackForDownmix(&mState.tracks[name], name);
507cfb1d11ce6826fce7241d316d8b7dcab661f63a6Jason Sams    // delete the reformatter
50860709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    unprepareTrackForReformat(&mState.tracks[name], name);
5094820e8bb83b1f78e6232ebe853221f737da2a1eaJason Sams
5105fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams    mTrackNames &= ~(1<<name);
5115fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams}
5125fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams
5135fd09d847586f9680b4f495413b6ca5fbb69af6eJason Samsvoid AudioMixer::enable(int name)
5145fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams{
5155fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams    name -= TRACK0;
5165fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams    ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
51760709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams    track_t& track = mState.tracks[name];
5184820e8bb83b1f78e6232ebe853221f737da2a1eaJason Sams
5198ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    if (!track.enabled) {
5208ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams        track.enabled = true;
5218ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams        ALOGV("enable(%d)", name);
5228ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams        invalidateState(1 << name);
5238ce125be69531dbf3a7e856d5e59d1b8e2789db0Jason Sams    }
524326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams}
525326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams
526afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchoukvoid AudioMixer::disable(int name)
527d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk{
528d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    name -= TRACK0;
529d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
530d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    track_t& track = mState.tracks[name];
531d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk
532d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk    if (track.enabled) {
533d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        track.enabled = false;
534d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        ALOGV("disable(%d)", name);
535afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        invalidateState(1 << name);
536a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams    }
537a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams}
538a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams
539a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams/* Sets the volume ramp variables for the AudioMixer.
540a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams *
541afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk * The volume ramp variables are used to transition between the previous
542afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk * volume to the target volume.  The duration of the transition is
543a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams * set by ramp, which is either 0 for immediate, or typically one state
544a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams * framecount period.
545a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams *
546a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams * @param newFloatValue new volume target in float [0.0, 1.0].
547a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams * @param ramp number of frames to increment over. ramp is 0 if the volume
548a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams * should be set immediately.
549a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams * @param volume reference to the U4.12 target volume, set on return.
5501a4efa363916977ef9aeab756725b3bdc880a15bJason Sams * @param prevVolume reference to the U4.27 previous volume, set on return.
5511a4efa363916977ef9aeab756725b3bdc880a15bJason Sams * @param volumeInc reference to the increment per output audio frame, set on return.
552aad4bc5231dd7059fc5148b34a951117d9b5f4adJason Sams * @return true if the volume has changed, false if volume is same.
553aad4bc5231dd7059fc5148b34a951117d9b5f4adJason Sams */
5541a4efa363916977ef9aeab756725b3bdc880a15bJason Samsstatic inline bool setVolumeRampVariables(float newFloatValue, int32_t ramp,
5551a4efa363916977ef9aeab756725b3bdc880a15bJason Sams        int16_t &volume, int32_t &prevVolume, int32_t &volumeInc) {
5568c401effb0837155fc39ca0364f57a882d127d38Jason Sams    int32_t newValue = newFloatValue * AudioMixer::UNITY_GAIN_INT;
5578c401effb0837155fc39ca0364f57a882d127d38Jason Sams    if (newValue > AudioMixer::UNITY_GAIN_INT) {
55887319de2b16a185cf360827c96a42cf1fcaae744Jason Sams        newValue = AudioMixer::UNITY_GAIN_INT;
55987319de2b16a185cf360827c96a42cf1fcaae744Jason Sams    } else if (newValue < 0) {
5601a4efa363916977ef9aeab756725b3bdc880a15bJason Sams        ALOGE("negative volume %.7g", newFloatValue);
5611a4efa363916977ef9aeab756725b3bdc880a15bJason Sams        newValue = 0; // should never happen, but for safety check.
5628c401effb0837155fc39ca0364f57a882d127d38Jason Sams    }
5638c401effb0837155fc39ca0364f57a882d127d38Jason Sams    if (newValue == volume) {
564afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        return false;
565afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    }
5668c401effb0837155fc39ca0364f57a882d127d38Jason Sams    if (ramp != 0) {
5678c401effb0837155fc39ca0364f57a882d127d38Jason Sams        volumeInc = ((newValue - volume) << 16) / ramp;
5688c401effb0837155fc39ca0364f57a882d127d38Jason Sams        prevVolume = (volumeInc == 0 ? newValue : volume) << 16;
5698c401effb0837155fc39ca0364f57a882d127d38Jason Sams    } else {
570afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        volumeInc = 0;
5711a4efa363916977ef9aeab756725b3bdc880a15bJason Sams        prevVolume = newValue << 16;
5728c401effb0837155fc39ca0364f57a882d127d38Jason Sams    }
5735086938044e0a9b6b1138f915d0d252fe046e102Jason Sams    volume = newValue;
57487319de2b16a185cf360827c96a42cf1fcaae744Jason Sams    return true;
575a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams}
576aad4bc5231dd7059fc5148b34a951117d9b5f4adJason Sams
577a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Samsvoid AudioMixer::setParameter(int name, int target, int param, void *value)
578a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams{
579a2cf755a28a1e7ffff2955df656d714f40e4d715Jason Sams    name -= TRACK0;
580afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk    ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
58113e2634a71a30d289ed8d821aef61c7d1687460eJason Sams    track_t& track = mState.tracks[name];
58213e2634a71a30d289ed8d821aef61c7d1687460eJason Sams
58313e2634a71a30d289ed8d821aef61c7d1687460eJason Sams    int valueInt = static_cast<int>(reinterpret_cast<uintptr_t>(value));
58413e2634a71a30d289ed8d821aef61c7d1687460eJason Sams    int32_t *valueBuf = reinterpret_cast<int32_t*>(value);
5856b8552a4f6a44848255d77222e66aa92dd21b1b5Jason Sams
586b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk    switch (target) {
58713e2634a71a30d289ed8d821aef61c7d1687460eJason Sams
588a4a54e42fc710a62b47cbcb9d64c34a190429d9eJason Sams    case TRACK:
589326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        switch (param) {
590a44cb29164726cd9d812117819abdd7b60dfdd93Jason Sams        case CHANNEL_MASK: {
591326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            audio_channel_mask_t mask =
592326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                static_cast<audio_channel_mask_t>(reinterpret_cast<uintptr_t>(value));
593326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            if (track.channelMask != mask) {
594326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                uint32_t channelCount = audio_channel_count_from_out_mask(mask);
595afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                ALOG_ASSERT((channelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX) && channelCount);
5968c88090e8cccab103eebe2ff569e116e9f5fb208Jason Sams                track.channelMask = mask;
597326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                track.channelCount = channelCount;
598afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                // the mask has changed, does this track need a downmixer?
599326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                initTrackDownmix(&mState.tracks[name], name, mask);
600326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", mask);
601326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                invalidateState(1 << name);
602326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            }
603afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk            } break;
604326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        case MAIN_BUFFER:
605326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            if (track.mainBuffer != valueBuf) {
606326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                track.mainBuffer = valueBuf;
607326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
608326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                invalidateState(1 << name);
609326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            }
610326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            break;
611326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        case AUX_BUFFER:
612326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            if (track.auxBuffer != valueBuf) {
613326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                track.auxBuffer = valueBuf;
614afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                ALOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
615ccc010bb7c0f89e162bf60033968a20be90a903aJason Sams                invalidateState(1 << name);
61660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams            }
617326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            break;
618326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        case FORMAT: {
619afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk            audio_format_t format = static_cast<audio_format_t>(valueInt);
620326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            if (track.mFormat != format) {
62160709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams                ALOG_ASSERT(audio_is_linear_pcm(format), "Invalid format %#x", format);
622326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                track.mFormat = format;
623326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                ALOGV("setParameter(TRACK, FORMAT, %#x)", format);
624afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                //if (track.mFormat != track.mMixerInFormat)
6255fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams                {
62660709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams                    ALOGD("Reformatting!");
6275fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams                    prepareTrackForReformat(&track, name);
6285fd09d847586f9680b4f495413b6ca5fbb69af6eJason Sams                }
629afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                invalidateState(1 << name);
630326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams            }
63160709257bbdeb0c50f39b9c8969dc76264d6e142Jason Sams            } break;
632326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        // FIXME do we want to support setting the downmix type from AudioFlinger?
633326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        //         for a specific track? or per mixer?
634afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        /* case DOWNMIX_TYPE:
635d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            break          */
636d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk        case MIXER_FORMAT: {
637d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            audio_format_t format = static_cast<audio_format_t>(valueInt);
638d3e0ad43dc758c409fc23d1893dab67b18520c24Alex Sakhartchouk            if (track.mMixerFormat != format) {
639b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk                track.mMixerFormat = format;
640a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams                ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
64170b83c111beceaf8fbb700580833e7fec99272cfAlex Sakhartchouk            }
642a0a1b6fbece2eb8d72d788422ab3e5f58d5a9216Jason Sams            } break;
643326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams        default:
644afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk            LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
6452353ae303868d04e3a26002b2f2dc456c15e8170Jason Sams        }
646707aaf341a4b068e6ccadf923af85acdd85fd775Jason Sams        break;
6479397e30ce5fe3f6af9212a93b490836b04fdfffaJason Sams
648707aaf341a4b068e6ccadf923af85acdd85fd775Jason Sams    case RESAMPLE:
649707aaf341a4b068e6ccadf923af85acdd85fd775Jason Sams        switch (param) {
650afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        case SAMPLE_RATE:
65186f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams            ALOG_ASSERT(valueInt > 0, "bad sample rate %d", valueInt);
65286f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams            if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
65386f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams                ALOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
654afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk                        uint32_t(valueInt));
65586f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams                invalidateState(1 << name);
65686f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams            }
65786f1b23aaaf9b8822a009d8c3e585e46768abb6aJason Sams            break;
6587257c7ee4b66f00c43d9235f3ac600061ae79968Alex Sakhartchouk        case RESET:
659fa4028663712dbb1a3d13c507c3bc13c6e4be80dMathias Agopian            track.resetResampler();
660613cad1702dbb76eb2a6ba0cfcb43b9fe207cebcJason Sams            invalidateState(1 << name);
661613cad1702dbb76eb2a6ba0cfcb43b9fe207cebcJason Sams            break;
662afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk        case REMOVE:
663158324456b8dbf40f684dd0a4af3493b9549f3f5Jason Sams            delete track.resampler;
664458f2dc26b7d34c2138c7bfbd95914240084e6bdJason Sams            track.resampler = NULL;
665458f2dc26b7d34c2138c7bfbd95914240084e6bdJason Sams            track.sampleRate = mSampleRate;
666afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk            invalidateState(1 << name);
667c21cf40f6ae69091bf24f87b5eeabc95e73dd271Jason Sams            break;
668c21cf40f6ae69091bf24f87b5eeabc95e73dd271Jason Sams        default:
669c21cf40f6ae69091bf24f87b5eeabc95e73dd271Jason Sams            LOG_ALWAYS_FATAL("setParameter resample: bad param %d", param);
670741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        }
671b81a0eb8180791e4eaab1253b59fa8bd562b046bAlex Sakhartchouk        break;
6721dcefab7178f0644b0e0a6998007b1acae5261cfJason Sams
6731dcefab7178f0644b0e0a6998007b1acae5261cfJason Sams    case RAMP_VOLUME:
674c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams    case VOLUME:
67586d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams        switch (param) {
676741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        case VOLUME0:
677741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams        case VOLUME1:
67886d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams            if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
679741aac95b777b2e6cb90f484a05e489a79a6ef05Jason Sams                    target == RAMP_VOLUME ? mState.frameCount : 0,
680326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                    track.volume[param - VOLUME0], track.prevVolume[param - VOLUME0],
681326e0ddf89e8df2837752fbfd7a014814b32082cJason Sams                    track.volumeInc[param - VOLUME0])) {
682c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams                ALOGV("setParameter(%s, VOLUME%d: %04x)",
683186e59154a0fb86e05e283e9c083b69878c06720Jason Sams                        target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
6841a4efa363916977ef9aeab756725b3bdc880a15bJason Sams                                track.volume[param - VOLUME0]);
6851a4efa363916977ef9aeab756725b3bdc880a15bJason Sams                invalidateState(1 << name);
686aad4bc5231dd7059fc5148b34a951117d9b5f4adJason Sams            }
687aad4bc5231dd7059fc5148b34a951117d9b5f4adJason Sams            break;
688c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams        case AUXLEVEL:
689186e59154a0fb86e05e283e9c083b69878c06720Jason Sams            //ALOG_ASSERT(0 <= valueInt && valueInt <= MAX_GAIN_INT, "bad aux level %d", valueInt);
6901a4efa363916977ef9aeab756725b3bdc880a15bJason Sams            if (setVolumeRampVariables(*reinterpret_cast<float*>(value),
691186e59154a0fb86e05e283e9c083b69878c06720Jason Sams                    target == RAMP_VOLUME ? mState.frameCount : 0,
692186e59154a0fb86e05e283e9c083b69878c06720Jason Sams                    track.auxLevel, track.prevAuxLevel, track.auxInc)) {
6931a4efa363916977ef9aeab756725b3bdc880a15bJason Sams                ALOGV("setParameter(%s, AUXLEVEL: %04x)",
6948c401effb0837155fc39ca0364f57a882d127d38Jason Sams                        target == VOLUME ? "VOLUME" : "RAMP_VOLUME", track.auxLevel);
6958c401effb0837155fc39ca0364f57a882d127d38Jason Sams                invalidateState(1 << name);
696c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams            }
6978c401effb0837155fc39ca0364f57a882d127d38Jason Sams            break;
6988c401effb0837155fc39ca0364f57a882d127d38Jason Sams        default:
6998c401effb0837155fc39ca0364f57a882d127d38Jason Sams            LOG_ALWAYS_FATAL("setParameter volume: bad param %d", param);
700c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams        }
7018c401effb0837155fc39ca0364f57a882d127d38Jason Sams        break;
7028c401effb0837155fc39ca0364f57a882d127d38Jason Sams
7038c401effb0837155fc39ca0364f57a882d127d38Jason Sams    default:
704c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams        LOG_ALWAYS_FATAL("setParameter: bad target %d", target);
705c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams    }
706c975cf4a71b63ccbd20f1f3b3341c5f2e6025b45Jason Sams}
707cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines
708cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hinesbool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
70986d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams{
710789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams    if (value != devSampleRate || resampler != NULL) {
711789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams        if (sampleRate != value) {
712cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines            sampleRate = value;
713cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines            if (resampler == NULL) {
714cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines                ALOGV("creating resampler from track %d Hz to device %d Hz", value, devSampleRate);
715789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                AudioResampler::src_quality quality;
716789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                // force lowest quality level resampler if use case isn't music or video
717789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                // FIXME this is flawed for dynamic sample rates, as we choose the resampler
718789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                // quality level based on the initial ratio, but that could change later.
719cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines                // Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
720cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines                if (!((value == 44100 && devSampleRate == 48000) ||
72186d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams                      (value == 48000 && devSampleRate == 44100))) {
722789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                    quality = AudioResampler::DYN_LOW_QUALITY;
723789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                } else {
7249544f76195de22f655fd7a1894934667e7e55f6aJason Sams                    quality = AudioResampler::DEFAULT_QUALITY;
725cbb0b8aceedb9146ba901cba1fbd6d1e9ca88f51Stephen Hines                }
7269544f76195de22f655fd7a1894934667e7e55f6aJason Sams                const int bits = mMixerInFormat == AUDIO_FORMAT_PCM_16_BIT ? 16 : /* FLOAT */ 32;
7279544f76195de22f655fd7a1894934667e7e55f6aJason Sams                resampler = AudioResampler::create(
72886d842a703da80b40eae5a482d4e26d8b2aae048Jason Sams                        bits,
729789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                        // the resampler sees the number of channels after the downmixer, if any
730789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                        (int) (downmixerBufferProvider != NULL ? MAX_NUM_CHANNELS : channelCount),
731789ca83c794cb7196c9bac97d39eaf1f7947af2aJason Sams                        devSampleRate, quality);
732dc763f345db3e796efc28dc4b4d8edffda5a803eAlex Sakhartchouk                resampler->setLocalTimeFreq(sLocalTimeFreq);
733dc763f345db3e796efc28dc4b4d8edffda5a803eAlex Sakhartchouk            }
734afb743aca56c18beb7ab924e75cb6e070ef3e55aAlex Sakhartchouk            return true;
735dc763f345db3e796efc28dc4b4d8edffda5a803eAlex Sakhartchouk        }
736dc763f345db3e796efc28dc4b4d8edffda5a803eAlex Sakhartchouk    }
737dc763f345db3e796efc28dc4b4d8edffda5a803eAlex Sakhartchouk    return false;
738}
739
740inline
741void AudioMixer::track_t::adjustVolumeRamp(bool aux)
742{
743    for (uint32_t i=0 ; i<MAX_NUM_CHANNELS ; i++) {
744        if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
745            ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
746            volumeInc[i] = 0;
747            prevVolume[i] = volume[i]<<16;
748        }
749    }
750    if (aux) {
751        if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
752            ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
753            auxInc = 0;
754            prevAuxLevel = auxLevel<<16;
755        }
756    }
757}
758
759size_t AudioMixer::getUnreleasedFrames(int name) const
760{
761    name -= TRACK0;
762    if (uint32_t(name) < MAX_NUM_TRACKS) {
763        return mState.tracks[name].getUnreleasedFrames();
764    }
765    return 0;
766}
767
768void AudioMixer::setBufferProvider(int name, AudioBufferProvider* bufferProvider)
769{
770    name -= TRACK0;
771    ALOG_ASSERT(uint32_t(name) < MAX_NUM_TRACKS, "bad track name %d", name);
772
773    if (mState.tracks[name].mInputBufferProvider == bufferProvider) {
774        return; // don't reset any buffer providers if identical.
775    }
776    if (mState.tracks[name].mReformatBufferProvider != NULL) {
777        mState.tracks[name].mReformatBufferProvider->reset();
778    } else if (mState.tracks[name].downmixerBufferProvider != NULL) {
779    }
780
781    mState.tracks[name].mInputBufferProvider = bufferProvider;
782    reconfigureBufferProviders(&mState.tracks[name]);
783}
784
785
786void AudioMixer::process(int64_t pts)
787{
788    mState.hook(&mState, pts);
789}
790
791
792void AudioMixer::process__validate(state_t* state, int64_t pts)
793{
794    ALOGW_IF(!state->needsChanged,
795        "in process__validate() but nothing's invalid");
796
797    uint32_t changed = state->needsChanged;
798    state->needsChanged = 0; // clear the validation flag
799
800    // recompute which tracks are enabled / disabled
801    uint32_t enabled = 0;
802    uint32_t disabled = 0;
803    while (changed) {
804        const int i = 31 - __builtin_clz(changed);
805        const uint32_t mask = 1<<i;
806        changed &= ~mask;
807        track_t& t = state->tracks[i];
808        (t.enabled ? enabled : disabled) |= mask;
809    }
810    state->enabledTracks &= ~disabled;
811    state->enabledTracks |=  enabled;
812
813    // compute everything we need...
814    int countActiveTracks = 0;
815    bool all16BitsStereoNoResample = true;
816    bool resampling = false;
817    bool volumeRamp = false;
818    uint32_t en = state->enabledTracks;
819    while (en) {
820        const int i = 31 - __builtin_clz(en);
821        en &= ~(1<<i);
822
823        countActiveTracks++;
824        track_t& t = state->tracks[i];
825        uint32_t n = 0;
826        // FIXME can overflow (mask is only 3 bits)
827        n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
828        if (t.doesResample()) {
829            n |= NEEDS_RESAMPLE;
830        }
831        if (t.auxLevel != 0 && t.auxBuffer != NULL) {
832            n |= NEEDS_AUX;
833        }
834
835        if (t.volumeInc[0]|t.volumeInc[1]) {
836            volumeRamp = true;
837        } else if (!t.doesResample() && t.volumeRL == 0) {
838            n |= NEEDS_MUTE;
839        }
840        t.needs = n;
841
842        if (n & NEEDS_MUTE) {
843            t.hook = track__nop;
844        } else {
845            if (n & NEEDS_AUX) {
846                all16BitsStereoNoResample = false;
847            }
848            if (n & NEEDS_RESAMPLE) {
849                all16BitsStereoNoResample = false;
850                resampling = true;
851                t.hook = track__genericResample;
852                ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
853                        "Track %d needs downmix + resample", i);
854            } else {
855                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
856                    t.hook = track__16BitsMono;
857                    all16BitsStereoNoResample = false;
858                }
859                if ((n & NEEDS_CHANNEL_COUNT__MASK) >= NEEDS_CHANNEL_2){
860                    t.hook = track__16BitsStereo;
861                    ALOGV_IF((n & NEEDS_CHANNEL_COUNT__MASK) > NEEDS_CHANNEL_2,
862                            "Track %d needs downmix", i);
863                }
864            }
865        }
866    }
867
868    // select the processing hooks
869    state->hook = process__nop;
870    if (countActiveTracks > 0) {
871        if (resampling) {
872            if (!state->outputTemp) {
873                state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
874            }
875            if (!state->resampleTemp) {
876                state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
877            }
878            state->hook = process__genericResampling;
879        } else {
880            if (state->outputTemp) {
881                delete [] state->outputTemp;
882                state->outputTemp = NULL;
883            }
884            if (state->resampleTemp) {
885                delete [] state->resampleTemp;
886                state->resampleTemp = NULL;
887            }
888            state->hook = process__genericNoResampling;
889            if (all16BitsStereoNoResample && !volumeRamp) {
890                if (countActiveTracks == 1) {
891                    state->hook = process__OneTrack16BitsStereoNoResampling;
892                }
893            }
894        }
895    }
896
897    ALOGV("mixer configuration change: %d activeTracks (%08x) "
898        "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
899        countActiveTracks, state->enabledTracks,
900        all16BitsStereoNoResample, resampling, volumeRamp);
901
902   state->hook(state, pts);
903
904    // Now that the volume ramp has been done, set optimal state and
905    // track hooks for subsequent mixer process
906    if (countActiveTracks > 0) {
907        bool allMuted = true;
908        uint32_t en = state->enabledTracks;
909        while (en) {
910            const int i = 31 - __builtin_clz(en);
911            en &= ~(1<<i);
912            track_t& t = state->tracks[i];
913            if (!t.doesResample() && t.volumeRL == 0) {
914                t.needs |= NEEDS_MUTE;
915                t.hook = track__nop;
916            } else {
917                allMuted = false;
918            }
919        }
920        if (allMuted) {
921            state->hook = process__nop;
922        } else if (all16BitsStereoNoResample) {
923            if (countActiveTracks == 1) {
924                state->hook = process__OneTrack16BitsStereoNoResampling;
925            }
926        }
927    }
928}
929
930
931void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount,
932        int32_t* temp, int32_t* aux)
933{
934    t->resampler->setSampleRate(t->sampleRate);
935
936    // ramp gain - resample to temp buffer and scale/mix in 2nd step
937    if (aux != NULL) {
938        // always resample with unity gain when sending to auxiliary buffer to be able
939        // to apply send level after resampling
940        // TODO: modify each resampler to support aux channel?
941        t->resampler->setVolume(UNITY_GAIN_INT, UNITY_GAIN_INT);
942        memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
943        t->resampler->resample(temp, outFrameCount, t->bufferProvider);
944        if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
945            volumeRampStereo(t, out, outFrameCount, temp, aux);
946        } else {
947            volumeStereo(t, out, outFrameCount, temp, aux);
948        }
949    } else {
950        if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
951            t->resampler->setVolume(UNITY_GAIN_INT, UNITY_GAIN_INT);
952            memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
953            t->resampler->resample(temp, outFrameCount, t->bufferProvider);
954            volumeRampStereo(t, out, outFrameCount, temp, aux);
955        }
956
957        // constant gain
958        else {
959            t->resampler->setVolume(t->volume[0], t->volume[1]);
960            t->resampler->resample(out, outFrameCount, t->bufferProvider);
961        }
962    }
963}
964
965void AudioMixer::track__nop(track_t* t __unused, int32_t* out __unused,
966        size_t outFrameCount __unused, int32_t* temp __unused, int32_t* aux __unused)
967{
968}
969
970void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
971        int32_t* aux)
972{
973    int32_t vl = t->prevVolume[0];
974    int32_t vr = t->prevVolume[1];
975    const int32_t vlInc = t->volumeInc[0];
976    const int32_t vrInc = t->volumeInc[1];
977
978    //ALOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
979    //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
980    //       (vl + vlInc*frameCount)/65536.0f, frameCount);
981
982    // ramp volume
983    if (CC_UNLIKELY(aux != NULL)) {
984        int32_t va = t->prevAuxLevel;
985        const int32_t vaInc = t->auxInc;
986        int32_t l;
987        int32_t r;
988
989        do {
990            l = (*temp++ >> 12);
991            r = (*temp++ >> 12);
992            *out++ += (vl >> 16) * l;
993            *out++ += (vr >> 16) * r;
994            *aux++ += (va >> 17) * (l + r);
995            vl += vlInc;
996            vr += vrInc;
997            va += vaInc;
998        } while (--frameCount);
999        t->prevAuxLevel = va;
1000    } else {
1001        do {
1002            *out++ += (vl >> 16) * (*temp++ >> 12);
1003            *out++ += (vr >> 16) * (*temp++ >> 12);
1004            vl += vlInc;
1005            vr += vrInc;
1006        } while (--frameCount);
1007    }
1008    t->prevVolume[0] = vl;
1009    t->prevVolume[1] = vr;
1010    t->adjustVolumeRamp(aux != NULL);
1011}
1012
1013void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp,
1014        int32_t* aux)
1015{
1016    const int16_t vl = t->volume[0];
1017    const int16_t vr = t->volume[1];
1018
1019    if (CC_UNLIKELY(aux != NULL)) {
1020        const int16_t va = t->auxLevel;
1021        do {
1022            int16_t l = (int16_t)(*temp++ >> 12);
1023            int16_t r = (int16_t)(*temp++ >> 12);
1024            out[0] = mulAdd(l, vl, out[0]);
1025            int16_t a = (int16_t)(((int32_t)l + r) >> 1);
1026            out[1] = mulAdd(r, vr, out[1]);
1027            out += 2;
1028            aux[0] = mulAdd(a, va, aux[0]);
1029            aux++;
1030        } while (--frameCount);
1031    } else {
1032        do {
1033            int16_t l = (int16_t)(*temp++ >> 12);
1034            int16_t r = (int16_t)(*temp++ >> 12);
1035            out[0] = mulAdd(l, vl, out[0]);
1036            out[1] = mulAdd(r, vr, out[1]);
1037            out += 2;
1038        } while (--frameCount);
1039    }
1040}
1041
1042void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount,
1043        int32_t* temp __unused, int32_t* aux)
1044{
1045    const int16_t *in = static_cast<const int16_t *>(t->in);
1046
1047    if (CC_UNLIKELY(aux != NULL)) {
1048        int32_t l;
1049        int32_t r;
1050        // ramp gain
1051        if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
1052            int32_t vl = t->prevVolume[0];
1053            int32_t vr = t->prevVolume[1];
1054            int32_t va = t->prevAuxLevel;
1055            const int32_t vlInc = t->volumeInc[0];
1056            const int32_t vrInc = t->volumeInc[1];
1057            const int32_t vaInc = t->auxInc;
1058            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
1059            //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1060            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
1061
1062            do {
1063                l = (int32_t)*in++;
1064                r = (int32_t)*in++;
1065                *out++ += (vl >> 16) * l;
1066                *out++ += (vr >> 16) * r;
1067                *aux++ += (va >> 17) * (l + r);
1068                vl += vlInc;
1069                vr += vrInc;
1070                va += vaInc;
1071            } while (--frameCount);
1072
1073            t->prevVolume[0] = vl;
1074            t->prevVolume[1] = vr;
1075            t->prevAuxLevel = va;
1076            t->adjustVolumeRamp(true);
1077        }
1078
1079        // constant gain
1080        else {
1081            const uint32_t vrl = t->volumeRL;
1082            const int16_t va = (int16_t)t->auxLevel;
1083            do {
1084                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1085                int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
1086                in += 2;
1087                out[0] = mulAddRL(1, rl, vrl, out[0]);
1088                out[1] = mulAddRL(0, rl, vrl, out[1]);
1089                out += 2;
1090                aux[0] = mulAdd(a, va, aux[0]);
1091                aux++;
1092            } while (--frameCount);
1093        }
1094    } else {
1095        // ramp gain
1096        if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
1097            int32_t vl = t->prevVolume[0];
1098            int32_t vr = t->prevVolume[1];
1099            const int32_t vlInc = t->volumeInc[0];
1100            const int32_t vrInc = t->volumeInc[1];
1101
1102            // ALOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
1103            //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1104            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
1105
1106            do {
1107                *out++ += (vl >> 16) * (int32_t) *in++;
1108                *out++ += (vr >> 16) * (int32_t) *in++;
1109                vl += vlInc;
1110                vr += vrInc;
1111            } while (--frameCount);
1112
1113            t->prevVolume[0] = vl;
1114            t->prevVolume[1] = vr;
1115            t->adjustVolumeRamp(false);
1116        }
1117
1118        // constant gain
1119        else {
1120            const uint32_t vrl = t->volumeRL;
1121            do {
1122                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1123                in += 2;
1124                out[0] = mulAddRL(1, rl, vrl, out[0]);
1125                out[1] = mulAddRL(0, rl, vrl, out[1]);
1126                out += 2;
1127            } while (--frameCount);
1128        }
1129    }
1130    t->in = in;
1131}
1132
1133void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount,
1134        int32_t* temp __unused, int32_t* aux)
1135{
1136    const int16_t *in = static_cast<int16_t const *>(t->in);
1137
1138    if (CC_UNLIKELY(aux != NULL)) {
1139        // ramp gain
1140        if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc)) {
1141            int32_t vl = t->prevVolume[0];
1142            int32_t vr = t->prevVolume[1];
1143            int32_t va = t->prevAuxLevel;
1144            const int32_t vlInc = t->volumeInc[0];
1145            const int32_t vrInc = t->volumeInc[1];
1146            const int32_t vaInc = t->auxInc;
1147
1148            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
1149            //         t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1150            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
1151
1152            do {
1153                int32_t l = *in++;
1154                *out++ += (vl >> 16) * l;
1155                *out++ += (vr >> 16) * l;
1156                *aux++ += (va >> 16) * l;
1157                vl += vlInc;
1158                vr += vrInc;
1159                va += vaInc;
1160            } while (--frameCount);
1161
1162            t->prevVolume[0] = vl;
1163            t->prevVolume[1] = vr;
1164            t->prevAuxLevel = va;
1165            t->adjustVolumeRamp(true);
1166        }
1167        // constant gain
1168        else {
1169            const int16_t vl = t->volume[0];
1170            const int16_t vr = t->volume[1];
1171            const int16_t va = (int16_t)t->auxLevel;
1172            do {
1173                int16_t l = *in++;
1174                out[0] = mulAdd(l, vl, out[0]);
1175                out[1] = mulAdd(l, vr, out[1]);
1176                out += 2;
1177                aux[0] = mulAdd(l, va, aux[0]);
1178                aux++;
1179            } while (--frameCount);
1180        }
1181    } else {
1182        // ramp gain
1183        if (CC_UNLIKELY(t->volumeInc[0]|t->volumeInc[1])) {
1184            int32_t vl = t->prevVolume[0];
1185            int32_t vr = t->prevVolume[1];
1186            const int32_t vlInc = t->volumeInc[0];
1187            const int32_t vrInc = t->volumeInc[1];
1188
1189            // ALOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
1190            //         t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
1191            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
1192
1193            do {
1194                int32_t l = *in++;
1195                *out++ += (vl >> 16) * l;
1196                *out++ += (vr >> 16) * l;
1197                vl += vlInc;
1198                vr += vrInc;
1199            } while (--frameCount);
1200
1201            t->prevVolume[0] = vl;
1202            t->prevVolume[1] = vr;
1203            t->adjustVolumeRamp(false);
1204        }
1205        // constant gain
1206        else {
1207            const int16_t vl = t->volume[0];
1208            const int16_t vr = t->volume[1];
1209            do {
1210                int16_t l = *in++;
1211                out[0] = mulAdd(l, vl, out[0]);
1212                out[1] = mulAdd(l, vr, out[1]);
1213                out += 2;
1214            } while (--frameCount);
1215        }
1216    }
1217    t->in = in;
1218}
1219
1220// no-op case
1221void AudioMixer::process__nop(state_t* state, int64_t pts)
1222{
1223    uint32_t e0 = state->enabledTracks;
1224    size_t sampleCount = state->frameCount * MAX_NUM_CHANNELS;
1225    while (e0) {
1226        // process by group of tracks with same output buffer to
1227        // avoid multiple memset() on same buffer
1228        uint32_t e1 = e0, e2 = e0;
1229        int i = 31 - __builtin_clz(e1);
1230        {
1231            track_t& t1 = state->tracks[i];
1232            e2 &= ~(1<<i);
1233            while (e2) {
1234                i = 31 - __builtin_clz(e2);
1235                e2 &= ~(1<<i);
1236                track_t& t2 = state->tracks[i];
1237                if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
1238                    e1 &= ~(1<<i);
1239                }
1240            }
1241            e0 &= ~(e1);
1242
1243            memset(t1.mainBuffer, 0, sampleCount
1244                    * audio_bytes_per_sample(t1.mMixerFormat));
1245        }
1246
1247        while (e1) {
1248            i = 31 - __builtin_clz(e1);
1249            e1 &= ~(1<<i);
1250            {
1251                track_t& t3 = state->tracks[i];
1252                size_t outFrames = state->frameCount;
1253                while (outFrames) {
1254                    t3.buffer.frameCount = outFrames;
1255                    int64_t outputPTS = calculateOutputPTS(
1256                        t3, pts, state->frameCount - outFrames);
1257                    t3.bufferProvider->getNextBuffer(&t3.buffer, outputPTS);
1258                    if (t3.buffer.raw == NULL) break;
1259                    outFrames -= t3.buffer.frameCount;
1260                    t3.bufferProvider->releaseBuffer(&t3.buffer);
1261                }
1262            }
1263        }
1264    }
1265}
1266
1267// generic code without resampling
1268void AudioMixer::process__genericNoResampling(state_t* state, int64_t pts)
1269{
1270    int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
1271
1272    // acquire each track's buffer
1273    uint32_t enabledTracks = state->enabledTracks;
1274    uint32_t e0 = enabledTracks;
1275    while (e0) {
1276        const int i = 31 - __builtin_clz(e0);
1277        e0 &= ~(1<<i);
1278        track_t& t = state->tracks[i];
1279        t.buffer.frameCount = state->frameCount;
1280        t.bufferProvider->getNextBuffer(&t.buffer, pts);
1281        t.frameCount = t.buffer.frameCount;
1282        t.in = t.buffer.raw;
1283    }
1284
1285    e0 = enabledTracks;
1286    while (e0) {
1287        // process by group of tracks with same output buffer to
1288        // optimize cache use
1289        uint32_t e1 = e0, e2 = e0;
1290        int j = 31 - __builtin_clz(e1);
1291        track_t& t1 = state->tracks[j];
1292        e2 &= ~(1<<j);
1293        while (e2) {
1294            j = 31 - __builtin_clz(e2);
1295            e2 &= ~(1<<j);
1296            track_t& t2 = state->tracks[j];
1297            if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
1298                e1 &= ~(1<<j);
1299            }
1300        }
1301        e0 &= ~(e1);
1302        // this assumes output 16 bits stereo, no resampling
1303        int32_t *out = t1.mainBuffer;
1304        size_t numFrames = 0;
1305        do {
1306            memset(outTemp, 0, sizeof(outTemp));
1307            e2 = e1;
1308            while (e2) {
1309                const int i = 31 - __builtin_clz(e2);
1310                e2 &= ~(1<<i);
1311                track_t& t = state->tracks[i];
1312                size_t outFrames = BLOCKSIZE;
1313                int32_t *aux = NULL;
1314                if (CC_UNLIKELY(t.needs & NEEDS_AUX)) {
1315                    aux = t.auxBuffer + numFrames;
1316                }
1317                while (outFrames) {
1318                    // t.in == NULL can happen if the track was flushed just after having
1319                    // been enabled for mixing.
1320                   if (t.in == NULL) {
1321                        enabledTracks &= ~(1<<i);
1322                        e1 &= ~(1<<i);
1323                        break;
1324                    }
1325                    size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
1326                    if (inFrames > 0) {
1327                        t.hook(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames,
1328                                state->resampleTemp, aux);
1329                        t.frameCount -= inFrames;
1330                        outFrames -= inFrames;
1331                        if (CC_UNLIKELY(aux != NULL)) {
1332                            aux += inFrames;
1333                        }
1334                    }
1335                    if (t.frameCount == 0 && outFrames) {
1336                        t.bufferProvider->releaseBuffer(&t.buffer);
1337                        t.buffer.frameCount = (state->frameCount - numFrames) -
1338                                (BLOCKSIZE - outFrames);
1339                        int64_t outputPTS = calculateOutputPTS(
1340                            t, pts, numFrames + (BLOCKSIZE - outFrames));
1341                        t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
1342                        t.in = t.buffer.raw;
1343                        if (t.in == NULL) {
1344                            enabledTracks &= ~(1<<i);
1345                            e1 &= ~(1<<i);
1346                            break;
1347                        }
1348                        t.frameCount = t.buffer.frameCount;
1349                    }
1350                }
1351            }
1352            switch (t1.mMixerFormat) {
1353            case AUDIO_FORMAT_PCM_FLOAT:
1354                memcpy_to_float_from_q4_27(reinterpret_cast<float *>(out), outTemp, BLOCKSIZE * 2);
1355                out += BLOCKSIZE * 2; // output is 2 floats/frame.
1356                break;
1357            case AUDIO_FORMAT_PCM_16_BIT:
1358                ditherAndClamp(out, outTemp, BLOCKSIZE);
1359                out += BLOCKSIZE; // output is 1 int32_t (2 int16_t samples)/frame
1360                break;
1361            default:
1362                LOG_ALWAYS_FATAL("bad mixer format: %d", t1.mMixerFormat);
1363            }
1364            numFrames += BLOCKSIZE;
1365        } while (numFrames < state->frameCount);
1366    }
1367
1368    // release each track's buffer
1369    e0 = enabledTracks;
1370    while (e0) {
1371        const int i = 31 - __builtin_clz(e0);
1372        e0 &= ~(1<<i);
1373        track_t& t = state->tracks[i];
1374        t.bufferProvider->releaseBuffer(&t.buffer);
1375    }
1376}
1377
1378
1379// generic code with resampling
1380void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
1381{
1382    // this const just means that local variable outTemp doesn't change
1383    int32_t* const outTemp = state->outputTemp;
1384    const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
1385
1386    size_t numFrames = state->frameCount;
1387
1388    uint32_t e0 = state->enabledTracks;
1389    while (e0) {
1390        // process by group of tracks with same output buffer
1391        // to optimize cache use
1392        uint32_t e1 = e0, e2 = e0;
1393        int j = 31 - __builtin_clz(e1);
1394        track_t& t1 = state->tracks[j];
1395        e2 &= ~(1<<j);
1396        while (e2) {
1397            j = 31 - __builtin_clz(e2);
1398            e2 &= ~(1<<j);
1399            track_t& t2 = state->tracks[j];
1400            if (CC_UNLIKELY(t2.mainBuffer != t1.mainBuffer)) {
1401                e1 &= ~(1<<j);
1402            }
1403        }
1404        e0 &= ~(e1);
1405        int32_t *out = t1.mainBuffer;
1406        memset(outTemp, 0, size);
1407        while (e1) {
1408            const int i = 31 - __builtin_clz(e1);
1409            e1 &= ~(1<<i);
1410            track_t& t = state->tracks[i];
1411            int32_t *aux = NULL;
1412            if (CC_UNLIKELY(t.needs & NEEDS_AUX)) {
1413                aux = t.auxBuffer;
1414            }
1415
1416            // this is a little goofy, on the resampling case we don't
1417            // acquire/release the buffers because it's done by
1418            // the resampler.
1419            if (t.needs & NEEDS_RESAMPLE) {
1420                t.resampler->setPTS(pts);
1421                t.hook(&t, outTemp, numFrames, state->resampleTemp, aux);
1422            } else {
1423
1424                size_t outFrames = 0;
1425
1426                while (outFrames < numFrames) {
1427                    t.buffer.frameCount = numFrames - outFrames;
1428                    int64_t outputPTS = calculateOutputPTS(t, pts, outFrames);
1429                    t.bufferProvider->getNextBuffer(&t.buffer, outputPTS);
1430                    t.in = t.buffer.raw;
1431                    // t.in == NULL can happen if the track was flushed just after having
1432                    // been enabled for mixing.
1433                    if (t.in == NULL) break;
1434
1435                    if (CC_UNLIKELY(aux != NULL)) {
1436                        aux += outFrames;
1437                    }
1438                    t.hook(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount,
1439                            state->resampleTemp, aux);
1440                    outFrames += t.buffer.frameCount;
1441                    t.bufferProvider->releaseBuffer(&t.buffer);
1442                }
1443            }
1444        }
1445        switch (t1.mMixerFormat) {
1446        case AUDIO_FORMAT_PCM_FLOAT:
1447            memcpy_to_float_from_q4_27(reinterpret_cast<float*>(out), outTemp, numFrames*2);
1448            break;
1449        case AUDIO_FORMAT_PCM_16_BIT:
1450            ditherAndClamp(out, outTemp, numFrames);
1451            break;
1452        default:
1453            LOG_ALWAYS_FATAL("bad mixer format: %d", t1.mMixerFormat);
1454        }
1455    }
1456}
1457
1458// one track, 16 bits stereo without resampling is the most common case
1459void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state,
1460                                                           int64_t pts)
1461{
1462    // This method is only called when state->enabledTracks has exactly
1463    // one bit set.  The asserts below would verify this, but are commented out
1464    // since the whole point of this method is to optimize performance.
1465    //ALOG_ASSERT(0 != state->enabledTracks, "no tracks enabled");
1466    const int i = 31 - __builtin_clz(state->enabledTracks);
1467    //ALOG_ASSERT((1 << i) == state->enabledTracks, "more than 1 track enabled");
1468    const track_t& t = state->tracks[i];
1469
1470    AudioBufferProvider::Buffer& b(t.buffer);
1471
1472    int32_t* out = t.mainBuffer;
1473    float *fout = reinterpret_cast<float*>(out);
1474    size_t numFrames = state->frameCount;
1475
1476    const int16_t vl = t.volume[0];
1477    const int16_t vr = t.volume[1];
1478    const uint32_t vrl = t.volumeRL;
1479    while (numFrames) {
1480        b.frameCount = numFrames;
1481        int64_t outputPTS = calculateOutputPTS(t, pts, out - t.mainBuffer);
1482        t.bufferProvider->getNextBuffer(&b, outputPTS);
1483        const int16_t *in = b.i16;
1484
1485        // in == NULL can happen if the track was flushed just after having
1486        // been enabled for mixing.
1487        if (in == NULL || (((uintptr_t)in) & 3)) {
1488            memset(out, 0, numFrames
1489                    * MAX_NUM_CHANNELS * audio_bytes_per_sample(t.mMixerFormat));
1490            ALOGE_IF((((uintptr_t)in) & 3), "process stereo track: input buffer alignment pb: "
1491                                              "buffer %p track %d, channels %d, needs %08x",
1492                    in, i, t.channelCount, t.needs);
1493            return;
1494        }
1495        size_t outFrames = b.frameCount;
1496
1497        switch (t.mMixerFormat) {
1498        case AUDIO_FORMAT_PCM_FLOAT:
1499            do {
1500                uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1501                in += 2;
1502                int32_t l = mulRL(1, rl, vrl);
1503                int32_t r = mulRL(0, rl, vrl);
1504                *fout++ = float_from_q4_27(l);
1505                *fout++ = float_from_q4_27(r);
1506                // Note: In case of later int16_t sink output,
1507                // conversion and clamping is done by memcpy_to_i16_from_float().
1508            } while (--outFrames);
1509            break;
1510        case AUDIO_FORMAT_PCM_16_BIT:
1511            if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) {
1512                // volume is boosted, so we might need to clamp even though
1513                // we process only one track.
1514                do {
1515                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1516                    in += 2;
1517                    int32_t l = mulRL(1, rl, vrl) >> 12;
1518                    int32_t r = mulRL(0, rl, vrl) >> 12;
1519                    // clamping...
1520                    l = clamp16(l);
1521                    r = clamp16(r);
1522                    *out++ = (r<<16) | (l & 0xFFFF);
1523                } while (--outFrames);
1524            } else {
1525                do {
1526                    uint32_t rl = *reinterpret_cast<const uint32_t *>(in);
1527                    in += 2;
1528                    int32_t l = mulRL(1, rl, vrl) >> 12;
1529                    int32_t r = mulRL(0, rl, vrl) >> 12;
1530                    *out++ = (r<<16) | (l & 0xFFFF);
1531                } while (--outFrames);
1532            }
1533            break;
1534        default:
1535            LOG_ALWAYS_FATAL("bad mixer format: %d", t.mMixerFormat);
1536        }
1537        numFrames -= b.frameCount;
1538        t.bufferProvider->releaseBuffer(&b);
1539    }
1540}
1541
1542#if 0
1543// 2 tracks is also a common case
1544// NEVER used in current implementation of process__validate()
1545// only use if the 2 tracks have the same output buffer
1546void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state,
1547                                                            int64_t pts)
1548{
1549    int i;
1550    uint32_t en = state->enabledTracks;
1551
1552    i = 31 - __builtin_clz(en);
1553    const track_t& t0 = state->tracks[i];
1554    AudioBufferProvider::Buffer& b0(t0.buffer);
1555
1556    en &= ~(1<<i);
1557    i = 31 - __builtin_clz(en);
1558    const track_t& t1 = state->tracks[i];
1559    AudioBufferProvider::Buffer& b1(t1.buffer);
1560
1561    const int16_t *in0;
1562    const int16_t vl0 = t0.volume[0];
1563    const int16_t vr0 = t0.volume[1];
1564    size_t frameCount0 = 0;
1565
1566    const int16_t *in1;
1567    const int16_t vl1 = t1.volume[0];
1568    const int16_t vr1 = t1.volume[1];
1569    size_t frameCount1 = 0;
1570
1571    //FIXME: only works if two tracks use same buffer
1572    int32_t* out = t0.mainBuffer;
1573    size_t numFrames = state->frameCount;
1574    const int16_t *buff = NULL;
1575
1576
1577    while (numFrames) {
1578
1579        if (frameCount0 == 0) {
1580            b0.frameCount = numFrames;
1581            int64_t outputPTS = calculateOutputPTS(t0, pts,
1582                                                   out - t0.mainBuffer);
1583            t0.bufferProvider->getNextBuffer(&b0, outputPTS);
1584            if (b0.i16 == NULL) {
1585                if (buff == NULL) {
1586                    buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1587                }
1588                in0 = buff;
1589                b0.frameCount = numFrames;
1590            } else {
1591                in0 = b0.i16;
1592            }
1593            frameCount0 = b0.frameCount;
1594        }
1595        if (frameCount1 == 0) {
1596            b1.frameCount = numFrames;
1597            int64_t outputPTS = calculateOutputPTS(t1, pts,
1598                                                   out - t0.mainBuffer);
1599            t1.bufferProvider->getNextBuffer(&b1, outputPTS);
1600            if (b1.i16 == NULL) {
1601                if (buff == NULL) {
1602                    buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
1603                }
1604                in1 = buff;
1605                b1.frameCount = numFrames;
1606            } else {
1607                in1 = b1.i16;
1608            }
1609            frameCount1 = b1.frameCount;
1610        }
1611
1612        size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
1613
1614        numFrames -= outFrames;
1615        frameCount0 -= outFrames;
1616        frameCount1 -= outFrames;
1617
1618        do {
1619            int32_t l0 = *in0++;
1620            int32_t r0 = *in0++;
1621            l0 = mul(l0, vl0);
1622            r0 = mul(r0, vr0);
1623            int32_t l = *in1++;
1624            int32_t r = *in1++;
1625            l = mulAdd(l, vl1, l0) >> 12;
1626            r = mulAdd(r, vr1, r0) >> 12;
1627            // clamping...
1628            l = clamp16(l);
1629            r = clamp16(r);
1630            *out++ = (r<<16) | (l & 0xFFFF);
1631        } while (--outFrames);
1632
1633        if (frameCount0 == 0) {
1634            t0.bufferProvider->releaseBuffer(&b0);
1635        }
1636        if (frameCount1 == 0) {
1637            t1.bufferProvider->releaseBuffer(&b1);
1638        }
1639    }
1640
1641    delete [] buff;
1642}
1643#endif
1644
1645int64_t AudioMixer::calculateOutputPTS(const track_t& t, int64_t basePTS,
1646                                       int outputFrameIndex)
1647{
1648    if (AudioBufferProvider::kInvalidPTS == basePTS) {
1649        return AudioBufferProvider::kInvalidPTS;
1650    }
1651
1652    return basePTS + ((outputFrameIndex * sLocalTimeFreq) / t.sampleRate);
1653}
1654
1655/*static*/ uint64_t AudioMixer::sLocalTimeFreq;
1656/*static*/ pthread_once_t AudioMixer::sOnceControl = PTHREAD_ONCE_INIT;
1657
1658/*static*/ void AudioMixer::sInitRoutine()
1659{
1660    LocalClock lc;
1661    sLocalTimeFreq = lc.getLocalFreq();
1662
1663    // find multichannel downmix effect if we have to play multichannel content
1664    uint32_t numEffects = 0;
1665    int ret = EffectQueryNumberEffects(&numEffects);
1666    if (ret != 0) {
1667        ALOGE("AudioMixer() error %d querying number of effects", ret);
1668        return;
1669    }
1670    ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
1671
1672    for (uint32_t i = 0 ; i < numEffects ; i++) {
1673        if (EffectQueryEffect(i, &sDwnmFxDesc) == 0) {
1674            ALOGV("effect %d is called %s", i, sDwnmFxDesc.name);
1675            if (memcmp(&sDwnmFxDesc.type, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
1676                ALOGI("found effect \"%s\" from %s",
1677                        sDwnmFxDesc.name, sDwnmFxDesc.implementor);
1678                sIsMultichannelCapable = true;
1679                break;
1680            }
1681        }
1682    }
1683    ALOGW_IF(!sIsMultichannelCapable, "unable to find downmix effect");
1684}
1685
1686// ----------------------------------------------------------------------------
1687}; // namespace android
1688