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