18981605d43e24c46d395acb5f145b99589d45917Andy Hung/*
28981605d43e24c46d395acb5f145b99589d45917Andy Hung * Copyright (C) 2017 The Android Open Source Project
38981605d43e24c46d395acb5f145b99589d45917Andy Hung *
48981605d43e24c46d395acb5f145b99589d45917Andy Hung * Licensed under the Apache License, Version 2.0 (the "License");
58981605d43e24c46d395acb5f145b99589d45917Andy Hung * you may not use this file except in compliance with the License.
68981605d43e24c46d395acb5f145b99589d45917Andy Hung * You may obtain a copy of the License at
78981605d43e24c46d395acb5f145b99589d45917Andy Hung *
88981605d43e24c46d395acb5f145b99589d45917Andy Hung *      http://www.apache.org/licenses/LICENSE-2.0
98981605d43e24c46d395acb5f145b99589d45917Andy Hung *
108981605d43e24c46d395acb5f145b99589d45917Andy Hung * Unless required by applicable law or agreed to in writing, software
118981605d43e24c46d395acb5f145b99589d45917Andy Hung * distributed under the License is distributed on an "AS IS" BASIS,
128981605d43e24c46d395acb5f145b99589d45917Andy Hung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138981605d43e24c46d395acb5f145b99589d45917Andy Hung * See the License for the specific language governing permissions and
148981605d43e24c46d395acb5f145b99589d45917Andy Hung * limitations under the License.
158981605d43e24c46d395acb5f145b99589d45917Andy Hung */
168981605d43e24c46d395acb5f145b99589d45917Andy Hung
178981605d43e24c46d395acb5f145b99589d45917Andy Hung#define LOG_TAG "RecordBufferConverter"
188981605d43e24c46d395acb5f145b99589d45917Andy Hung//#define LOG_NDEBUG 0
198981605d43e24c46d395acb5f145b99589d45917Andy Hung
208981605d43e24c46d395acb5f145b99589d45917Andy Hung#include <audio_utils/primitives.h>
218981605d43e24c46d395acb5f145b99589d45917Andy Hung#include <audio_utils/format.h>
228981605d43e24c46d395acb5f145b99589d45917Andy Hung#include <media/AudioMixer.h>  // for UNITY_GAIN_FLOAT
238981605d43e24c46d395acb5f145b99589d45917Andy Hung#include <media/AudioResampler.h>
248981605d43e24c46d395acb5f145b99589d45917Andy Hung#include <media/BufferProviders.h>
258981605d43e24c46d395acb5f145b99589d45917Andy Hung#include <media/RecordBufferConverter.h>
268981605d43e24c46d395acb5f145b99589d45917Andy Hung#include <utils/Log.h>
278981605d43e24c46d395acb5f145b99589d45917Andy Hung
288981605d43e24c46d395acb5f145b99589d45917Andy Hung#ifndef ARRAY_SIZE
298981605d43e24c46d395acb5f145b99589d45917Andy Hung#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
308981605d43e24c46d395acb5f145b99589d45917Andy Hung#endif
318981605d43e24c46d395acb5f145b99589d45917Andy Hung
328981605d43e24c46d395acb5f145b99589d45917Andy Hungtemplate <typename T>
338981605d43e24c46d395acb5f145b99589d45917Andy Hungstatic inline T max(const T& a, const T& b)
348981605d43e24c46d395acb5f145b99589d45917Andy Hung{
358981605d43e24c46d395acb5f145b99589d45917Andy Hung    return a > b ? a : b;
368981605d43e24c46d395acb5f145b99589d45917Andy Hung}
378981605d43e24c46d395acb5f145b99589d45917Andy Hung
388981605d43e24c46d395acb5f145b99589d45917Andy Hungnamespace android {
398981605d43e24c46d395acb5f145b99589d45917Andy Hung
408981605d43e24c46d395acb5f145b99589d45917Andy HungRecordBufferConverter::RecordBufferConverter(
418981605d43e24c46d395acb5f145b99589d45917Andy Hung        audio_channel_mask_t srcChannelMask, audio_format_t srcFormat,
428981605d43e24c46d395acb5f145b99589d45917Andy Hung        uint32_t srcSampleRate,
438981605d43e24c46d395acb5f145b99589d45917Andy Hung        audio_channel_mask_t dstChannelMask, audio_format_t dstFormat,
448981605d43e24c46d395acb5f145b99589d45917Andy Hung        uint32_t dstSampleRate) :
458981605d43e24c46d395acb5f145b99589d45917Andy Hung            mSrcChannelMask(AUDIO_CHANNEL_INVALID), // updateParameters will set following vars
468981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mSrcFormat
478981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mSrcSampleRate
488981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mDstChannelMask
498981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mDstFormat
508981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mDstSampleRate
518981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mSrcChannelCount
528981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mDstChannelCount
538981605d43e24c46d395acb5f145b99589d45917Andy Hung            // mDstFrameSize
548981605d43e24c46d395acb5f145b99589d45917Andy Hung            mBuf(NULL), mBufFrames(0), mBufFrameSize(0),
558981605d43e24c46d395acb5f145b99589d45917Andy Hung            mResampler(NULL),
568981605d43e24c46d395acb5f145b99589d45917Andy Hung            mIsLegacyDownmix(false),
578981605d43e24c46d395acb5f145b99589d45917Andy Hung            mIsLegacyUpmix(false),
588981605d43e24c46d395acb5f145b99589d45917Andy Hung            mRequiresFloat(false),
598981605d43e24c46d395acb5f145b99589d45917Andy Hung            mInputConverterProvider(NULL)
608981605d43e24c46d395acb5f145b99589d45917Andy Hung{
618981605d43e24c46d395acb5f145b99589d45917Andy Hung    (void)updateParameters(srcChannelMask, srcFormat, srcSampleRate,
628981605d43e24c46d395acb5f145b99589d45917Andy Hung            dstChannelMask, dstFormat, dstSampleRate);
638981605d43e24c46d395acb5f145b99589d45917Andy Hung}
648981605d43e24c46d395acb5f145b99589d45917Andy Hung
658981605d43e24c46d395acb5f145b99589d45917Andy HungRecordBufferConverter::~RecordBufferConverter() {
668981605d43e24c46d395acb5f145b99589d45917Andy Hung    free(mBuf);
678981605d43e24c46d395acb5f145b99589d45917Andy Hung    delete mResampler;
688981605d43e24c46d395acb5f145b99589d45917Andy Hung    delete mInputConverterProvider;
698981605d43e24c46d395acb5f145b99589d45917Andy Hung}
708981605d43e24c46d395acb5f145b99589d45917Andy Hung
718981605d43e24c46d395acb5f145b99589d45917Andy Hungvoid RecordBufferConverter::reset() {
728981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mResampler != NULL) {
738981605d43e24c46d395acb5f145b99589d45917Andy Hung        mResampler->reset();
748981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
758981605d43e24c46d395acb5f145b99589d45917Andy Hung}
768981605d43e24c46d395acb5f145b99589d45917Andy Hung
778981605d43e24c46d395acb5f145b99589d45917Andy Hungsize_t RecordBufferConverter::convert(void *dst,
788981605d43e24c46d395acb5f145b99589d45917Andy Hung        AudioBufferProvider *provider, size_t frames)
798981605d43e24c46d395acb5f145b99589d45917Andy Hung{
808981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mInputConverterProvider != NULL) {
818981605d43e24c46d395acb5f145b99589d45917Andy Hung        mInputConverterProvider->setBufferProvider(provider);
828981605d43e24c46d395acb5f145b99589d45917Andy Hung        provider = mInputConverterProvider;
838981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
848981605d43e24c46d395acb5f145b99589d45917Andy Hung
858981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mResampler == NULL) {
868981605d43e24c46d395acb5f145b99589d45917Andy Hung        ALOGV("NO RESAMPLING sampleRate:%u mSrcFormat:%#x mDstFormat:%#x",
878981605d43e24c46d395acb5f145b99589d45917Andy Hung                mSrcSampleRate, mSrcFormat, mDstFormat);
888981605d43e24c46d395acb5f145b99589d45917Andy Hung
898981605d43e24c46d395acb5f145b99589d45917Andy Hung        AudioBufferProvider::Buffer buffer;
908981605d43e24c46d395acb5f145b99589d45917Andy Hung        for (size_t i = frames; i > 0; ) {
918981605d43e24c46d395acb5f145b99589d45917Andy Hung            buffer.frameCount = i;
928981605d43e24c46d395acb5f145b99589d45917Andy Hung            status_t status = provider->getNextBuffer(&buffer);
938981605d43e24c46d395acb5f145b99589d45917Andy Hung            if (status != OK || buffer.frameCount == 0) {
948981605d43e24c46d395acb5f145b99589d45917Andy Hung                frames -= i; // cannot fill request.
958981605d43e24c46d395acb5f145b99589d45917Andy Hung                break;
968981605d43e24c46d395acb5f145b99589d45917Andy Hung            }
978981605d43e24c46d395acb5f145b99589d45917Andy Hung            // format convert to destination buffer
988981605d43e24c46d395acb5f145b99589d45917Andy Hung            convertNoResampler(dst, buffer.raw, buffer.frameCount);
998981605d43e24c46d395acb5f145b99589d45917Andy Hung
1008981605d43e24c46d395acb5f145b99589d45917Andy Hung            dst = (int8_t*)dst + buffer.frameCount * mDstFrameSize;
1018981605d43e24c46d395acb5f145b99589d45917Andy Hung            i -= buffer.frameCount;
1028981605d43e24c46d395acb5f145b99589d45917Andy Hung            provider->releaseBuffer(&buffer);
1038981605d43e24c46d395acb5f145b99589d45917Andy Hung        }
1048981605d43e24c46d395acb5f145b99589d45917Andy Hung    } else {
1058981605d43e24c46d395acb5f145b99589d45917Andy Hung         ALOGV("RESAMPLING mSrcSampleRate:%u mDstSampleRate:%u mSrcFormat:%#x mDstFormat:%#x",
1068981605d43e24c46d395acb5f145b99589d45917Andy Hung                 mSrcSampleRate, mDstSampleRate, mSrcFormat, mDstFormat);
1078981605d43e24c46d395acb5f145b99589d45917Andy Hung
1088981605d43e24c46d395acb5f145b99589d45917Andy Hung         // reallocate buffer if needed
1098981605d43e24c46d395acb5f145b99589d45917Andy Hung         if (mBufFrameSize != 0 && mBufFrames < frames) {
1108981605d43e24c46d395acb5f145b99589d45917Andy Hung             free(mBuf);
1118981605d43e24c46d395acb5f145b99589d45917Andy Hung             mBufFrames = frames;
1128981605d43e24c46d395acb5f145b99589d45917Andy Hung             (void)posix_memalign(&mBuf, 32, mBufFrames * mBufFrameSize);
1138981605d43e24c46d395acb5f145b99589d45917Andy Hung         }
1148981605d43e24c46d395acb5f145b99589d45917Andy Hung        // resampler accumulates, but we only have one source track
1158981605d43e24c46d395acb5f145b99589d45917Andy Hung        memset(mBuf, 0, frames * mBufFrameSize);
1168981605d43e24c46d395acb5f145b99589d45917Andy Hung        frames = mResampler->resample((int32_t*)mBuf, frames, provider);
1178981605d43e24c46d395acb5f145b99589d45917Andy Hung        // format convert to destination buffer
1188981605d43e24c46d395acb5f145b99589d45917Andy Hung        convertResampler(dst, mBuf, frames);
1198981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
1208981605d43e24c46d395acb5f145b99589d45917Andy Hung    return frames;
1218981605d43e24c46d395acb5f145b99589d45917Andy Hung}
1228981605d43e24c46d395acb5f145b99589d45917Andy Hung
1238981605d43e24c46d395acb5f145b99589d45917Andy Hungstatus_t RecordBufferConverter::updateParameters(
1248981605d43e24c46d395acb5f145b99589d45917Andy Hung        audio_channel_mask_t srcChannelMask, audio_format_t srcFormat,
1258981605d43e24c46d395acb5f145b99589d45917Andy Hung        uint32_t srcSampleRate,
1268981605d43e24c46d395acb5f145b99589d45917Andy Hung        audio_channel_mask_t dstChannelMask, audio_format_t dstFormat,
1278981605d43e24c46d395acb5f145b99589d45917Andy Hung        uint32_t dstSampleRate)
1288981605d43e24c46d395acb5f145b99589d45917Andy Hung{
1298981605d43e24c46d395acb5f145b99589d45917Andy Hung    // quick evaluation if there is any change.
1308981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mSrcFormat == srcFormat
1318981605d43e24c46d395acb5f145b99589d45917Andy Hung            && mSrcChannelMask == srcChannelMask
1328981605d43e24c46d395acb5f145b99589d45917Andy Hung            && mSrcSampleRate == srcSampleRate
1338981605d43e24c46d395acb5f145b99589d45917Andy Hung            && mDstFormat == dstFormat
1348981605d43e24c46d395acb5f145b99589d45917Andy Hung            && mDstChannelMask == dstChannelMask
1358981605d43e24c46d395acb5f145b99589d45917Andy Hung            && mDstSampleRate == dstSampleRate) {
1368981605d43e24c46d395acb5f145b99589d45917Andy Hung        return NO_ERROR;
1378981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
1388981605d43e24c46d395acb5f145b99589d45917Andy Hung
1398981605d43e24c46d395acb5f145b99589d45917Andy Hung    ALOGV("RecordBufferConverter updateParameters srcMask:%#x dstMask:%#x"
1408981605d43e24c46d395acb5f145b99589d45917Andy Hung            "  srcFormat:%#x dstFormat:%#x  srcRate:%u dstRate:%u",
1418981605d43e24c46d395acb5f145b99589d45917Andy Hung            srcChannelMask, dstChannelMask, srcFormat, dstFormat, srcSampleRate, dstSampleRate);
1428981605d43e24c46d395acb5f145b99589d45917Andy Hung    const bool valid =
1438981605d43e24c46d395acb5f145b99589d45917Andy Hung            audio_is_input_channel(srcChannelMask)
1448981605d43e24c46d395acb5f145b99589d45917Andy Hung            && audio_is_input_channel(dstChannelMask)
1458981605d43e24c46d395acb5f145b99589d45917Andy Hung            && audio_is_valid_format(srcFormat) && audio_is_linear_pcm(srcFormat)
1468981605d43e24c46d395acb5f145b99589d45917Andy Hung            && audio_is_valid_format(dstFormat) && audio_is_linear_pcm(dstFormat)
1478981605d43e24c46d395acb5f145b99589d45917Andy Hung            && (srcSampleRate <= dstSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX)
1488981605d43e24c46d395acb5f145b99589d45917Andy Hung            ; // no upsampling checks for now
1498981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (!valid) {
1508981605d43e24c46d395acb5f145b99589d45917Andy Hung        return BAD_VALUE;
1518981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
1528981605d43e24c46d395acb5f145b99589d45917Andy Hung
1538981605d43e24c46d395acb5f145b99589d45917Andy Hung    mSrcFormat = srcFormat;
1548981605d43e24c46d395acb5f145b99589d45917Andy Hung    mSrcChannelMask = srcChannelMask;
1558981605d43e24c46d395acb5f145b99589d45917Andy Hung    mSrcSampleRate = srcSampleRate;
1568981605d43e24c46d395acb5f145b99589d45917Andy Hung    mDstFormat = dstFormat;
1578981605d43e24c46d395acb5f145b99589d45917Andy Hung    mDstChannelMask = dstChannelMask;
1588981605d43e24c46d395acb5f145b99589d45917Andy Hung    mDstSampleRate = dstSampleRate;
1598981605d43e24c46d395acb5f145b99589d45917Andy Hung
1608981605d43e24c46d395acb5f145b99589d45917Andy Hung    // compute derived parameters
1618981605d43e24c46d395acb5f145b99589d45917Andy Hung    mSrcChannelCount = audio_channel_count_from_in_mask(srcChannelMask);
1628981605d43e24c46d395acb5f145b99589d45917Andy Hung    mDstChannelCount = audio_channel_count_from_in_mask(dstChannelMask);
1638981605d43e24c46d395acb5f145b99589d45917Andy Hung    mDstFrameSize = mDstChannelCount * audio_bytes_per_sample(mDstFormat);
1648981605d43e24c46d395acb5f145b99589d45917Andy Hung
1658981605d43e24c46d395acb5f145b99589d45917Andy Hung    // do we need to resample?
1668981605d43e24c46d395acb5f145b99589d45917Andy Hung    delete mResampler;
1678981605d43e24c46d395acb5f145b99589d45917Andy Hung    mResampler = NULL;
1688981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mSrcSampleRate != mDstSampleRate) {
1698981605d43e24c46d395acb5f145b99589d45917Andy Hung        mResampler = AudioResampler::create(AUDIO_FORMAT_PCM_FLOAT,
1708981605d43e24c46d395acb5f145b99589d45917Andy Hung                mSrcChannelCount, mDstSampleRate);
1718981605d43e24c46d395acb5f145b99589d45917Andy Hung        mResampler->setSampleRate(mSrcSampleRate);
1728981605d43e24c46d395acb5f145b99589d45917Andy Hung        mResampler->setVolume(AudioMixer::UNITY_GAIN_FLOAT, AudioMixer::UNITY_GAIN_FLOAT);
1738981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
1748981605d43e24c46d395acb5f145b99589d45917Andy Hung
1758981605d43e24c46d395acb5f145b99589d45917Andy Hung    // are we running legacy channel conversion modes?
1768981605d43e24c46d395acb5f145b99589d45917Andy Hung    mIsLegacyDownmix = (mSrcChannelMask == AUDIO_CHANNEL_IN_STEREO
1778981605d43e24c46d395acb5f145b99589d45917Andy Hung                            || mSrcChannelMask == AUDIO_CHANNEL_IN_FRONT_BACK)
1788981605d43e24c46d395acb5f145b99589d45917Andy Hung                   && mDstChannelMask == AUDIO_CHANNEL_IN_MONO;
1798981605d43e24c46d395acb5f145b99589d45917Andy Hung    mIsLegacyUpmix = mSrcChannelMask == AUDIO_CHANNEL_IN_MONO
1808981605d43e24c46d395acb5f145b99589d45917Andy Hung                   && (mDstChannelMask == AUDIO_CHANNEL_IN_STEREO
1818981605d43e24c46d395acb5f145b99589d45917Andy Hung                            || mDstChannelMask == AUDIO_CHANNEL_IN_FRONT_BACK);
1828981605d43e24c46d395acb5f145b99589d45917Andy Hung
1838981605d43e24c46d395acb5f145b99589d45917Andy Hung    // do we need to process in float?
1848981605d43e24c46d395acb5f145b99589d45917Andy Hung    mRequiresFloat = mResampler != NULL || mIsLegacyDownmix || mIsLegacyUpmix;
1858981605d43e24c46d395acb5f145b99589d45917Andy Hung
1868981605d43e24c46d395acb5f145b99589d45917Andy Hung    // do we need a staging buffer to convert for destination (we can still optimize this)?
1878981605d43e24c46d395acb5f145b99589d45917Andy Hung    // we use mBufFrameSize > 0 to indicate both frame size as well as buffer necessity
1888981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mResampler != NULL) {
1898981605d43e24c46d395acb5f145b99589d45917Andy Hung        mBufFrameSize = max(mSrcChannelCount, (uint32_t)FCC_2)
1908981605d43e24c46d395acb5f145b99589d45917Andy Hung                * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT);
1918981605d43e24c46d395acb5f145b99589d45917Andy Hung    } else if (mIsLegacyUpmix || mIsLegacyDownmix) { // legacy modes always float
1928981605d43e24c46d395acb5f145b99589d45917Andy Hung        mBufFrameSize = mDstChannelCount * audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT);
1938981605d43e24c46d395acb5f145b99589d45917Andy Hung    } else if (mSrcChannelMask != mDstChannelMask && mDstFormat != mSrcFormat) {
1948981605d43e24c46d395acb5f145b99589d45917Andy Hung        mBufFrameSize = mDstChannelCount * audio_bytes_per_sample(mSrcFormat);
1958981605d43e24c46d395acb5f145b99589d45917Andy Hung    } else {
1968981605d43e24c46d395acb5f145b99589d45917Andy Hung        mBufFrameSize = 0;
1978981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
1988981605d43e24c46d395acb5f145b99589d45917Andy Hung    mBufFrames = 0; // force the buffer to be resized.
1998981605d43e24c46d395acb5f145b99589d45917Andy Hung
2008981605d43e24c46d395acb5f145b99589d45917Andy Hung    // do we need an input converter buffer provider to give us float?
2018981605d43e24c46d395acb5f145b99589d45917Andy Hung    delete mInputConverterProvider;
2028981605d43e24c46d395acb5f145b99589d45917Andy Hung    mInputConverterProvider = NULL;
2038981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mRequiresFloat && mSrcFormat != AUDIO_FORMAT_PCM_FLOAT) {
2048981605d43e24c46d395acb5f145b99589d45917Andy Hung        mInputConverterProvider = new ReformatBufferProvider(
2058981605d43e24c46d395acb5f145b99589d45917Andy Hung                audio_channel_count_from_in_mask(mSrcChannelMask),
2068981605d43e24c46d395acb5f145b99589d45917Andy Hung                mSrcFormat,
2078981605d43e24c46d395acb5f145b99589d45917Andy Hung                AUDIO_FORMAT_PCM_FLOAT,
2088981605d43e24c46d395acb5f145b99589d45917Andy Hung                256 /* provider buffer frame count */);
2098981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
2108981605d43e24c46d395acb5f145b99589d45917Andy Hung
2118981605d43e24c46d395acb5f145b99589d45917Andy Hung    // do we need a remixer to do channel mask conversion
2128981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (!mIsLegacyDownmix && !mIsLegacyUpmix && mSrcChannelMask != mDstChannelMask) {
2138981605d43e24c46d395acb5f145b99589d45917Andy Hung        (void) memcpy_by_index_array_initialization_from_channel_mask(
2148981605d43e24c46d395acb5f145b99589d45917Andy Hung                mIdxAry, ARRAY_SIZE(mIdxAry), mDstChannelMask, mSrcChannelMask);
2158981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
2168981605d43e24c46d395acb5f145b99589d45917Andy Hung    return NO_ERROR;
2178981605d43e24c46d395acb5f145b99589d45917Andy Hung}
2188981605d43e24c46d395acb5f145b99589d45917Andy Hung
2198981605d43e24c46d395acb5f145b99589d45917Andy Hungvoid RecordBufferConverter::convertNoResampler(
2208981605d43e24c46d395acb5f145b99589d45917Andy Hung        void *dst, const void *src, size_t frames)
2218981605d43e24c46d395acb5f145b99589d45917Andy Hung{
2228981605d43e24c46d395acb5f145b99589d45917Andy Hung    // src is native type unless there is legacy upmix or downmix, whereupon it is float.
2238981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mBufFrameSize != 0 && mBufFrames < frames) {
2248981605d43e24c46d395acb5f145b99589d45917Andy Hung        free(mBuf);
2258981605d43e24c46d395acb5f145b99589d45917Andy Hung        mBufFrames = frames;
2268981605d43e24c46d395acb5f145b99589d45917Andy Hung        (void)posix_memalign(&mBuf, 32, mBufFrames * mBufFrameSize);
2278981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
2288981605d43e24c46d395acb5f145b99589d45917Andy Hung    // do we need to do legacy upmix and downmix?
2298981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mIsLegacyUpmix || mIsLegacyDownmix) {
2308981605d43e24c46d395acb5f145b99589d45917Andy Hung        void *dstBuf = mBuf != NULL ? mBuf : dst;
2318981605d43e24c46d395acb5f145b99589d45917Andy Hung        if (mIsLegacyUpmix) {
2328981605d43e24c46d395acb5f145b99589d45917Andy Hung            upmix_to_stereo_float_from_mono_float((float *)dstBuf,
2338981605d43e24c46d395acb5f145b99589d45917Andy Hung                    (const float *)src, frames);
2348981605d43e24c46d395acb5f145b99589d45917Andy Hung        } else /*mIsLegacyDownmix */ {
2358981605d43e24c46d395acb5f145b99589d45917Andy Hung            downmix_to_mono_float_from_stereo_float((float *)dstBuf,
2368981605d43e24c46d395acb5f145b99589d45917Andy Hung                    (const float *)src, frames);
2378981605d43e24c46d395acb5f145b99589d45917Andy Hung        }
2388981605d43e24c46d395acb5f145b99589d45917Andy Hung        if (mBuf != NULL) {
2398981605d43e24c46d395acb5f145b99589d45917Andy Hung            memcpy_by_audio_format(dst, mDstFormat, mBuf, AUDIO_FORMAT_PCM_FLOAT,
2408981605d43e24c46d395acb5f145b99589d45917Andy Hung                    frames * mDstChannelCount);
2418981605d43e24c46d395acb5f145b99589d45917Andy Hung        }
2428981605d43e24c46d395acb5f145b99589d45917Andy Hung        return;
2438981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
2448981605d43e24c46d395acb5f145b99589d45917Andy Hung    // do we need to do channel mask conversion?
2458981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mSrcChannelMask != mDstChannelMask) {
2468981605d43e24c46d395acb5f145b99589d45917Andy Hung        void *dstBuf = mBuf != NULL ? mBuf : dst;
2478981605d43e24c46d395acb5f145b99589d45917Andy Hung        memcpy_by_index_array(dstBuf, mDstChannelCount,
2488981605d43e24c46d395acb5f145b99589d45917Andy Hung                src, mSrcChannelCount, mIdxAry, audio_bytes_per_sample(mSrcFormat), frames);
2498981605d43e24c46d395acb5f145b99589d45917Andy Hung        if (dstBuf == dst) {
2508981605d43e24c46d395acb5f145b99589d45917Andy Hung            return; // format is the same
2518981605d43e24c46d395acb5f145b99589d45917Andy Hung        }
2528981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
2538981605d43e24c46d395acb5f145b99589d45917Andy Hung    // convert to destination buffer
2548981605d43e24c46d395acb5f145b99589d45917Andy Hung    const void *convertBuf = mBuf != NULL ? mBuf : src;
2558981605d43e24c46d395acb5f145b99589d45917Andy Hung    memcpy_by_audio_format(dst, mDstFormat, convertBuf, mSrcFormat,
2568981605d43e24c46d395acb5f145b99589d45917Andy Hung            frames * mDstChannelCount);
2578981605d43e24c46d395acb5f145b99589d45917Andy Hung}
2588981605d43e24c46d395acb5f145b99589d45917Andy Hung
2598981605d43e24c46d395acb5f145b99589d45917Andy Hungvoid RecordBufferConverter::convertResampler(
2608981605d43e24c46d395acb5f145b99589d45917Andy Hung        void *dst, /*not-a-const*/ void *src, size_t frames)
2618981605d43e24c46d395acb5f145b99589d45917Andy Hung{
2628981605d43e24c46d395acb5f145b99589d45917Andy Hung    // src buffer format is ALWAYS float when entering this routine
2638981605d43e24c46d395acb5f145b99589d45917Andy Hung    if (mIsLegacyUpmix) {
2648981605d43e24c46d395acb5f145b99589d45917Andy Hung        ; // mono to stereo already handled by resampler
2658981605d43e24c46d395acb5f145b99589d45917Andy Hung    } else if (mIsLegacyDownmix
2668981605d43e24c46d395acb5f145b99589d45917Andy Hung            || (mSrcChannelMask == mDstChannelMask && mSrcChannelCount == 1)) {
2678981605d43e24c46d395acb5f145b99589d45917Andy Hung        // the resampler outputs stereo for mono input channel (a feature?)
2688981605d43e24c46d395acb5f145b99589d45917Andy Hung        // must convert to mono
2698981605d43e24c46d395acb5f145b99589d45917Andy Hung        downmix_to_mono_float_from_stereo_float((float *)src,
2708981605d43e24c46d395acb5f145b99589d45917Andy Hung                (const float *)src, frames);
2718981605d43e24c46d395acb5f145b99589d45917Andy Hung    } else if (mSrcChannelMask != mDstChannelMask) {
2728981605d43e24c46d395acb5f145b99589d45917Andy Hung        // convert to mono channel again for channel mask conversion (could be skipped
2738981605d43e24c46d395acb5f145b99589d45917Andy Hung        // with further optimization).
2748981605d43e24c46d395acb5f145b99589d45917Andy Hung        if (mSrcChannelCount == 1) {
2758981605d43e24c46d395acb5f145b99589d45917Andy Hung            downmix_to_mono_float_from_stereo_float((float *)src,
2768981605d43e24c46d395acb5f145b99589d45917Andy Hung                (const float *)src, frames);
2778981605d43e24c46d395acb5f145b99589d45917Andy Hung        }
2788981605d43e24c46d395acb5f145b99589d45917Andy Hung        // convert to destination format (in place, OK as float is larger than other types)
2798981605d43e24c46d395acb5f145b99589d45917Andy Hung        if (mDstFormat != AUDIO_FORMAT_PCM_FLOAT) {
2808981605d43e24c46d395acb5f145b99589d45917Andy Hung            memcpy_by_audio_format(src, mDstFormat, src, AUDIO_FORMAT_PCM_FLOAT,
2818981605d43e24c46d395acb5f145b99589d45917Andy Hung                    frames * mSrcChannelCount);
2828981605d43e24c46d395acb5f145b99589d45917Andy Hung        }
2838981605d43e24c46d395acb5f145b99589d45917Andy Hung        // channel convert and save to dst
2848981605d43e24c46d395acb5f145b99589d45917Andy Hung        memcpy_by_index_array(dst, mDstChannelCount,
2858981605d43e24c46d395acb5f145b99589d45917Andy Hung                src, mSrcChannelCount, mIdxAry, audio_bytes_per_sample(mDstFormat), frames);
2868981605d43e24c46d395acb5f145b99589d45917Andy Hung        return;
2878981605d43e24c46d395acb5f145b99589d45917Andy Hung    }
2888981605d43e24c46d395acb5f145b99589d45917Andy Hung    // convert to destination format and save to dst
2898981605d43e24c46d395acb5f145b99589d45917Andy Hung    memcpy_by_audio_format(dst, mDstFormat, src, AUDIO_FORMAT_PCM_FLOAT,
2908981605d43e24c46d395acb5f145b99589d45917Andy Hung            frames * mDstChannelCount);
2918981605d43e24c46d395acb5f145b99589d45917Andy Hung}
2928981605d43e24c46d395acb5f145b99589d45917Andy Hung
2938981605d43e24c46d395acb5f145b99589d45917Andy Hung// ----------------------------------------------------------------------------
2948981605d43e24c46d395acb5f145b99589d45917Andy Hung} // namespace android
295