diff options
-rw-r--r-- | media/libmedia/Android.mk | 9 | ||||
-rw-r--r-- | services/audioflinger/Android.mk | 22 | ||||
-rw-r--r-- | services/audioflinger/AudioMixer.cpp | 13 | ||||
-rw-r--r-- | services/audioflinger/AudioResampler.cpp | 25 | ||||
-rw-r--r-- | services/audioflinger/AudioResampler.h | 3 | ||||
-rw-r--r-- | services/audioflinger/AudioResamplerQTI.cpp | 168 | ||||
-rw-r--r-- | services/audioflinger/AudioResamplerQTI.h | 52 |
7 files changed, 291 insertions, 1 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 4d84bd0..74e4eb1 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -69,6 +69,15 @@ LOCAL_SRC_FILES:= \ StringArray.cpp \ AudioPolicy.cpp + +#QTI Resampler +ifeq ($(call is-vendor-board-platform,QCOM), true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true) +LOCAL_CFLAGS += -DQTI_RESAMPLER +endif +endif +#QTI Resampler + LOCAL_SHARED_LIBRARIES := \ libui liblog libcutils libutils libbinder libsonivox libicuuc libicui18n libexpat \ libcamera_client libstagefright_foundation \ diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index debcdf9..4791ce4 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -71,6 +71,14 @@ LOCAL_STATIC_LIBRARIES := \ libcpustats \ libmedia_helper +#QTI Resampler +ifeq ($(call is-vendor-board-platform,QCOM), true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true) +LOCAL_CFLAGS += -DQTI_RESAMPLER +endif +endif +#QTI Resampler + LOCAL_MODULE:= libaudioflinger LOCAL_32_BIT_ONLY := true @@ -134,7 +142,19 @@ LOCAL_C_INCLUDES := \ LOCAL_SHARED_LIBRARIES := \ libcutils \ libdl \ - liblog + liblog \ + libaudioutils + +#QTI Resampler +ifeq ($(call is-vendor-board-platform,QCOM), true) +ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_RESAMPLER)), true) +LOCAL_SRC_FILES_$(TARGET_2ND_ARCH) += AudioResamplerQTI.cpp.arm +LOCAL_C_INCLUDES_$(TARGET_2ND_ARCH) += $(TARGET_OUT_HEADERS)/mm-audio/audio-src +LOCAL_SHARED_LIBRARIES_$(TARGET_2ND_ARCH) += libqct_resampler +LOCAL_CFLAGS_$(TARGET_2ND_ARCH) += -DQTI_RESAMPLER +endif +endif +#QTI Resampler LOCAL_MODULE := libaudioresampler diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp index 8a9a837..27a2f65 100644 --- a/services/audioflinger/AudioMixer.cpp +++ b/services/audioflinger/AudioMixer.cpp @@ -85,6 +85,9 @@ static const bool kUseFloat = true; // Set to default copy buffer size in frames for input processing. static const size_t kCopyBufferFrameCount = 256; +#ifdef QTI_RESAMPLER +#define QTI_RESAMPLER_MAX_SAMPLERATE 192000 +#endif namespace android { // ---------------------------------------------------------------------------- @@ -779,6 +782,13 @@ bool AudioMixer::track_t::setResampler(uint32_t trackSampleRate, uint32_t devSam // but if none exists, it is the channel count (1 for mono). const int resamplerChannelCount = downmixerBufferProvider != NULL ? mMixerChannelCount : channelCount; +#ifdef QTI_RESAMPLER + if ((trackSampleRate <= QTI_RESAMPLER_MAX_SAMPLERATE) && + (trackSampleRate > devSampleRate * 2) && + ((devSampleRate == 48000)||(devSampleRate == 44100))) { + quality = AudioResampler::QTI_QUALITY; + } +#endif ALOGVV("Creating resampler:" " format(%#x) channels(%d) devSampleRate(%u) quality(%d)\n", mMixerInFormat, resamplerChannelCount, devSampleRate, quality); @@ -1644,6 +1654,9 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, // Note: In case of later int16_t sink output, // conversion and clamping is done by memcpy_to_i16_from_float(). } while (--outFrames); + //assign fout to out, when no more frames are available, so that 0s + //can be filled at the right place + out = (int32_t *)fout; break; case AUDIO_FORMAT_PCM_16_BIT: if (CC_UNLIKELY(uint32_t(vl) > UNITY_GAIN_INT || uint32_t(vr) > UNITY_GAIN_INT)) { diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp index e49b7b1..ab3294a 100644 --- a/services/audioflinger/AudioResampler.cpp +++ b/services/audioflinger/AudioResampler.cpp @@ -28,6 +28,10 @@ #include "AudioResamplerCubic.h" #include "AudioResamplerDyn.h" +#ifdef QTI_RESAMPLER +#include "AudioResamplerQTI.h" +#endif + #ifdef __arm__ #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1 #endif @@ -90,6 +94,9 @@ bool AudioResampler::qualityIsSupported(src_quality quality) case DYN_LOW_QUALITY: case DYN_MED_QUALITY: case DYN_HIGH_QUALITY: +#ifdef QTI_RESAMPLER + case QTI_QUALITY: +#endif return true; default: return false; @@ -110,7 +117,11 @@ void AudioResampler::init_routine() if (*endptr == '\0') { defaultQuality = (src_quality) l; ALOGD("forcing AudioResampler quality to %d", defaultQuality); +#ifdef QTI_RESAMPLER + if (defaultQuality < DEFAULT_QUALITY || defaultQuality > QTI_QUALITY) { +#else if (defaultQuality < DEFAULT_QUALITY || defaultQuality > DYN_HIGH_QUALITY) { +#endif defaultQuality = DEFAULT_QUALITY; } } @@ -129,6 +140,9 @@ uint32_t AudioResampler::qualityMHz(src_quality quality) case HIGH_QUALITY: return 20; case VERY_HIGH_QUALITY: +#ifdef QTI_RESAMPLER + case QTI_QUALITY: //for QTI_QUALITY, currently assuming same as VHQ +#endif return 34; case DYN_LOW_QUALITY: return 4; @@ -204,6 +218,11 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount case DYN_HIGH_QUALITY: quality = DYN_MED_QUALITY; break; +#ifdef QTI_RESAMPLER + case QTI_QUALITY: + quality = DYN_HIGH_QUALITY; + break; +#endif } } pthread_mutex_unlock(&mutex); @@ -250,6 +269,12 @@ AudioResampler* AudioResampler::create(audio_format_t format, int inChannelCount } } break; +#ifdef QTI_RESAMPLER + case QTI_QUALITY: + ALOGV("Create QTI_QUALITY Resampler = %d",quality); + resampler = new AudioResamplerQTI(format, inChannelCount, sampleRate); + break; +#endif } // initialize resampler diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h index a8e3e6f..6669a85 100644 --- a/services/audioflinger/AudioResampler.h +++ b/services/audioflinger/AudioResampler.h @@ -47,6 +47,9 @@ public: DYN_LOW_QUALITY=5, DYN_MED_QUALITY=6, DYN_HIGH_QUALITY=7, +#ifdef QTI_RESAMPLER + QTI_QUALITY=8, +#endif }; static const CONSTEXPR float UNITY_GAIN_FLOAT = 1.0f; diff --git a/services/audioflinger/AudioResamplerQTI.cpp b/services/audioflinger/AudioResamplerQTI.cpp new file mode 100644 index 0000000..44b741e --- /dev/null +++ b/services/audioflinger/AudioResamplerQTI.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AudioResamplerQTI.h" +#include "QCT_Resampler.h" +#include <sys/time.h> +#include <audio_utils/primitives.h> + +namespace android { +AudioResamplerQTI::AudioResamplerQTI(int format, + int inChannelCount, int32_t sampleRate) + :AudioResampler(inChannelCount, sampleRate, QTI_QUALITY), + mOutFrameCount(0), mTmpBuf(0), mResamplerOutBuf(0), mFrameIndex(0) +{ + stateSize = QCT_Resampler::MemAlloc(format, inChannelCount, sampleRate, sampleRate); + mState = new int16_t[stateSize]; + mVolume[0] = mVolume[1] = 0; + mBuffer.frameCount = 0; +} + +AudioResamplerQTI::~AudioResamplerQTI() +{ + if (mState) { + delete [] mState; + } + if (mTmpBuf) { + delete [] mTmpBuf; + } + if(mResamplerOutBuf) { + delete [] mResamplerOutBuf; + } +} + +size_t AudioResamplerQTI::resample(int32_t* out, size_t outFrameCount, + AudioBufferProvider* provider) +{ + int16_t vl = mVolume[0]; + int16_t vr = mVolume[1]; + int16_t *pBuf; + + size_t inFrameRequest; + size_t inFrameCount = getNumInSample(outFrameCount); + size_t index = 0; + size_t frameIndex = mFrameIndex; + size_t out_count = outFrameCount * 2; + float *fout = reinterpret_cast<float *>(out); + + if (mChannelCount == 1) { + inFrameRequest = inFrameCount; + } else { + inFrameRequest = inFrameCount * 2; + } + + if (mOutFrameCount < outFrameCount) { + mOutFrameCount = outFrameCount; + if (mTmpBuf) { + delete [] mTmpBuf; + } + if(mResamplerOutBuf) { + delete [] mResamplerOutBuf; + } + mTmpBuf = new int16_t[inFrameRequest + 16]; + mResamplerOutBuf = new int32_t[out_count]; + } + + if (mChannelCount == 1) { + // buffer is empty, fetch a new one + while (index < inFrameCount) { + if (!mBuffer.frameCount) { + mBuffer.frameCount = inFrameCount; + provider->getNextBuffer(&mBuffer); + frameIndex = 0; + } + + if (mBuffer.raw == NULL) { + while (index < inFrameCount) { + mTmpBuf[index++] = 0; + } + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount); + goto resample_exit; + } + + mTmpBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++)); + + if (frameIndex >= mBuffer.frameCount) { + provider->releaseBuffer(&mBuffer); + } + } + + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount); + } else { + pBuf = &mTmpBuf[inFrameCount]; + // buffer is empty, fetch a new one + while (index < inFrameCount) { + if (!mBuffer.frameCount) { + mBuffer.frameCount = inFrameCount; + provider->getNextBuffer(&mBuffer); + frameIndex = 0; + } + if (mBuffer.raw == NULL) { + while (index < inFrameCount) { + mTmpBuf[index] = 0; + pBuf[index++] = 0; + } + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount); + goto resample_exit; + } + + mTmpBuf[index] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++)); + pBuf[index++] = clamp16_from_float(*((float *)mBuffer.raw + frameIndex++)); + if (frameIndex >= mBuffer.frameCount * 2) { + provider->releaseBuffer(&mBuffer); + } + } + + QCT_Resampler::Resample90dB(mState, mTmpBuf, mResamplerOutBuf, inFrameCount, outFrameCount); + } + +resample_exit: + for (int i = 0; i < out_count; i += 2) { + fout[i] += float_from_q4_27(mResamplerOutBuf[i] * vl); + fout[i+1] += float_from_q4_27(mResamplerOutBuf[i+1] * vr); + } + + mFrameIndex = frameIndex; + return index; +} + +void AudioResamplerQTI::setSampleRate(int32_t inSampleRate) +{ + if (mInSampleRate != inSampleRate) { + mInSampleRate = inSampleRate; + init(); + } +} + +void AudioResamplerQTI::init() +{ + QCT_Resampler::Init(mState, mChannelCount, mInSampleRate, mSampleRate); +} + +size_t AudioResamplerQTI::getNumInSample(size_t outFrameCount) +{ + size_t size = (size_t)QCT_Resampler::GetNumInSamp(mState, outFrameCount); + return size; +} + +void AudioResamplerQTI::reset() +{ + AudioResampler::reset(); +} + +}; // namespace android diff --git a/services/audioflinger/AudioResamplerQTI.h b/services/audioflinger/AudioResamplerQTI.h new file mode 100644 index 0000000..0b30a9f --- /dev/null +++ b/services/audioflinger/AudioResamplerQTI.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014, The Linux Foundation. All rights reserved. + * Not a Contribution. + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <sys/types.h> +#include <cutils/log.h> + +#include "AudioResampler.h" + +namespace android { +// ---------------------------------------------------------------------------- + +class AudioResamplerQTI : public AudioResampler { +public: + AudioResamplerQTI(int format, int inChannelCount, int32_t sampleRate); + ~AudioResamplerQTI(); + size_t resample(int32_t* out, size_t outFrameCount, + AudioBufferProvider* provider); + void setSampleRate(int32_t inSampleRate); + size_t getNumInSample(size_t outFrameCount); + + int16_t *mState; + int16_t *mTmpBuf; + int32_t *mResamplerOutBuf; + size_t mFrameIndex; + size_t stateSize; + size_t mOutFrameCount; + + static const int kNumTmpBufSize = 1024; + + void init(); + void reset(); +}; + +// ---------------------------------------------------------------------------- +}; // namespace android + |