165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* 265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Copyright (C) 2007 The Android Open Source Project 365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * you may not use this file except in compliance with the License. 665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * You may obtain a copy of the License at 765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * 1065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * Unless required by applicable law or agreed to in writing, software 1165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 1265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * See the License for the specific language governing permissions and 1465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian * limitations under the License. 1565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian */ 1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 175159c7ec97b575c0486159f0543d2da90c3c3b68Glenn Kasten#define LOG_TAG "AudioSRC" 185159c7ec97b575c0486159f0543d2da90c3c3b68Glenn Kasten 1965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <stdint.h> 2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <string.h> 2165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <sys/types.h> 2265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <cutils/log.h> 2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "AudioResampler.h" 2565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include "AudioResamplerCubic.h" 2665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android { 2865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerCubic::init() { 3165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memset(&left, 0, sizeof(state)); 3265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memset(&right, 0, sizeof(state)); 3365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 3465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount, 3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) { 3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // should never happen, but we overflow if it does 39c1dc1cb1d1eaf84e88669f1a5f22579a0d9237c2Steve Block // ALOG_ASSERT(outFrameCount < 32767); 4065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 4165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // select the appropriate resampler 4265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian switch (mChannelCount) { 4365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case 1: 4465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian resampleMono16(out, outFrameCount, provider); 4565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 4665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case 2: 4765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian resampleStereo16(out, outFrameCount, provider); 4865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian break; 4965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 5265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, 5365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) { 5465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 5565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vl = mVolume[0]; 5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vr = mVolume[1]; 5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inputIndex = mInputIndex; 5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseFraction = mPhaseFraction; 6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseIncrement = mPhaseIncrement; 6165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputIndex = 0; 6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputSampleCount = outFrameCount * 2; 6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; 6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // fetch first buffer 6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.frameCount == 0) { 6765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 684ff14bae91075eb274eb1c2975982358946e7e63John Grossman provider->getNextBuffer(&mBuffer, mPTS); 6965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.raw == NULL) 7065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return; 715ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); 7265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 7365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t *in = mBuffer.i16; 7465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 7665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t sample; 7765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t x; 7865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // calculate output sample 8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian x = phaseFraction >> kPreInterpShift; 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vl * interp(&left, x); 8265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vr * interp(&right, x); 8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // out[outputIndex++] += vr * in[inputIndex*2]; 8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // increment phase 8665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction += phaseIncrement; 8765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); 8865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction &= kPhaseMask; 8965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 9065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // time to fetch another sample 9165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (indexIncrement--) { 9265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 9365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 9465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex == mBuffer.frameCount) { 9565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex = 0; 9665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian provider->releaseBuffer(&mBuffer); 9765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 984ff14bae91075eb274eb1c2975982358946e7e63John Grossman provider->getNextBuffer(&mBuffer, 994ff14bae91075eb274eb1c2975982358946e7e63John Grossman calculateOutputPTS(outputIndex / 2)); 10065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.raw == NULL) 10165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto save_state; // ugly, but efficient 10265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian in = mBuffer.i16; 10390bebef5669a9385c706b042d146a31dca2e5d9bGlenn Kasten // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount); 10465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 10565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 10665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // advance sample state 10765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian advance(&left, in[inputIndex*2]); 10865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian advance(&right, in[inputIndex*2+1]); 10965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 11065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 11165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 11265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiansave_state: 1135ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); 11465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mInputIndex = inputIndex; 11565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mPhaseFraction = phaseFraction; 11665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 11765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 11865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianvoid AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, 11965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) { 12065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vl = mVolume[0]; 12265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vr = mVolume[1]; 12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inputIndex = mInputIndex; 12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseFraction = mPhaseFraction; 12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseIncrement = mPhaseIncrement; 12765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputIndex = 0; 12865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputSampleCount = outFrameCount * 2; 12965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate; 13065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 13165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // fetch first buffer 13265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.frameCount == 0) { 13365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 1344ff14bae91075eb274eb1c2975982358946e7e63John Grossman provider->getNextBuffer(&mBuffer, mPTS); 13565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.raw == NULL) 13665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return; 13790bebef5669a9385c706b042d146a31dca2e5d9bGlenn Kasten // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount); 13865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 13965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t *in = mBuffer.i16; 14065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t sample; 14365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t x; 14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // calculate output sample 14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian x = phaseFraction >> kPreInterpShift; 14765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sample = interp(&left, x); 14865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vl * sample; 14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vr * sample; 15065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // increment phase 15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction += phaseIncrement; 15365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); 15465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction &= kPhaseMask; 15565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // time to fetch another sample 15765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (indexIncrement--) { 15865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 16065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex == mBuffer.frameCount) { 16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex = 0; 16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian provider->releaseBuffer(&mBuffer); 16365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 1644ff14bae91075eb274eb1c2975982358946e7e63John Grossman provider->getNextBuffer(&mBuffer, 1654ff14bae91075eb274eb1c2975982358946e7e63John Grossman calculateOutputPTS(outputIndex / 2)); 16665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.raw == NULL) 16765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto save_state; // ugly, but efficient 1685ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); 16965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian in = mBuffer.i16; 17065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 17165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 17265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // advance sample state 17365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian advance(&left, in[inputIndex]); 17465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 17565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 17665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 17765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiansave_state: 1785ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); 17965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mInputIndex = inputIndex; 18065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mPhaseFraction = phaseFraction; 18165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 18265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 18365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 18465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 18565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian; // namespace android 186