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