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