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 176b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung#define LOG_TAG "AudioResamplerCubic" 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 356b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hungsize_t 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: 446b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung return resampleMono16(out, outFrameCount, provider); 4565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian case 2: 466b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung return resampleStereo16(out, outFrameCount, provider); 476b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung default: 486b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung LOG_ALWAYS_FATAL("invalid channel count: %d", mChannelCount); 496b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung return 0; 5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 5265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 536b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hungsize_t AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, 5465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) { 5565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 5665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vl = mVolume[0]; 5765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vr = mVolume[1]; 5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inputIndex = mInputIndex; 6065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseFraction = mPhaseFraction; 6165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseIncrement = mPhaseIncrement; 6265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputIndex = 0; 6365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputSampleCount = outFrameCount * 2; 6424781fff62a4cf7279d3dac83c33e2ac612712baAndy Hung size_t inFrameCount = getInFrameCountRequired(outFrameCount); 6565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 6665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // fetch first buffer 6765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.frameCount == 0) { 6865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 69d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten provider->getNextBuffer(&mBuffer); 706e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten if (mBuffer.raw == NULL) { 716b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung return 0; 726e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten } 735ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); 7465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t *in = mBuffer.i16; 7665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 7765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 7865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t x; 7965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 8065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // calculate output sample 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian x = phaseFraction >> kPreInterpShift; 8265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vl * interp(&left, x); 8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vr * interp(&right, x); 8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // out[outputIndex++] += vr * in[inputIndex*2]; 8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 8665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // increment phase 8765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction += phaseIncrement; 8865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); 8965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction &= kPhaseMask; 9065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 9165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // time to fetch another sample 9265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (indexIncrement--) { 9365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 9465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 9565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex == mBuffer.frameCount) { 9665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex = 0; 9765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian provider->releaseBuffer(&mBuffer); 9865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 99d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten provider->getNextBuffer(&mBuffer); 1006e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten if (mBuffer.raw == NULL) { 10165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto save_state; // ugly, but efficient 1026e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten } 10365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian in = mBuffer.i16; 10490bebef5669a9385c706b042d146a31dca2e5d9bGlenn Kasten // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount); 10565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 10665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 10765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // advance sample state 10865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian advance(&left, in[inputIndex*2]); 10965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian advance(&right, in[inputIndex*2+1]); 11065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 11165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 11265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 11365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiansave_state: 1145ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); 11565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mInputIndex = inputIndex; 11665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mPhaseFraction = phaseFraction; 1176b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung return outputIndex / 2 /* channels for stereo */; 11865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 11965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1206b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hungsize_t AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, 12165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian AudioBufferProvider* provider) { 12265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vl = mVolume[0]; 12465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t vr = mVolume[1]; 12565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 12665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t inputIndex = mInputIndex; 12765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseFraction = mPhaseFraction; 12865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t phaseIncrement = mPhaseIncrement; 12965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputIndex = 0; 13065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian size_t outputSampleCount = outFrameCount * 2; 13124781fff62a4cf7279d3dac83c33e2ac612712baAndy Hung size_t inFrameCount = getInFrameCountRequired(outFrameCount); 13265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 13365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // fetch first buffer 13465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (mBuffer.frameCount == 0) { 13565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 136d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten provider->getNextBuffer(&mBuffer); 1376e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten if (mBuffer.raw == NULL) { 1386b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung return 0; 1396e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten } 14090bebef5669a9385c706b042d146a31dca2e5d9bGlenn Kasten // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount); 14165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 14265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int16_t *in = mBuffer.i16; 14365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (outputIndex < outputSampleCount) { 14565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t sample; 14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian int32_t x; 14765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // calculate output sample 14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian x = phaseFraction >> kPreInterpShift; 15065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian sample = interp(&left, x); 15165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vl * sample; 15265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian out[outputIndex++] += vr * sample; 15365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // increment phase 15565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction += phaseIncrement; 15665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); 15765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian phaseFraction &= kPhaseMask; 15865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 15965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // time to fetch another sample 16065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (indexIncrement--) { 16165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex++; 16365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (inputIndex == mBuffer.frameCount) { 16465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian inputIndex = 0; 16565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian provider->releaseBuffer(&mBuffer); 16665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mBuffer.frameCount = inFrameCount; 167d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten provider->getNextBuffer(&mBuffer); 1686e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten if (mBuffer.raw == NULL) { 16965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian goto save_state; // ugly, but efficient 1706e2ebe97f2ad0a21907f20f9ee644c4eacbb7a40Glenn Kasten } 1715ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); 17265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian in = mBuffer.i16; 17365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 17465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 17565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // advance sample state 17665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian advance(&left, in[inputIndex]); 17765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 17865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 17965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 18065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiansave_state: 1815ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); 18265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mInputIndex = inputIndex; 18365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mPhaseFraction = phaseFraction; 1846b3b7e304e0f8f167241b2c75f1eb04a9ef192ecAndy Hung return outputIndex; 18565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 18665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 18765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian// ---------------------------------------------------------------------------- 18863238efb0d674758902918e3cdaac322126484b7Glenn Kasten} // namespace android 189