1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "AudioResamplerCubic" 18 19#include <stdint.h> 20#include <string.h> 21#include <sys/types.h> 22 23#include <log/log.h> 24 25#include "AudioResamplerCubic.h" 26 27namespace android { 28// ---------------------------------------------------------------------------- 29 30void AudioResamplerCubic::init() { 31 memset(&left, 0, sizeof(state)); 32 memset(&right, 0, sizeof(state)); 33} 34 35size_t AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount, 36 AudioBufferProvider* provider) { 37 38 // should never happen, but we overflow if it does 39 // ALOG_ASSERT(outFrameCount < 32767); 40 41 // select the appropriate resampler 42 switch (mChannelCount) { 43 case 1: 44 return resampleMono16(out, outFrameCount, provider); 45 case 2: 46 return resampleStereo16(out, outFrameCount, provider); 47 default: 48 LOG_ALWAYS_FATAL("invalid channel count: %d", mChannelCount); 49 return 0; 50 } 51} 52 53size_t AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount, 54 AudioBufferProvider* provider) { 55 56 int32_t vl = mVolume[0]; 57 int32_t vr = mVolume[1]; 58 59 size_t inputIndex = mInputIndex; 60 uint32_t phaseFraction = mPhaseFraction; 61 uint32_t phaseIncrement = mPhaseIncrement; 62 size_t outputIndex = 0; 63 size_t outputSampleCount = outFrameCount * 2; 64 size_t inFrameCount = getInFrameCountRequired(outFrameCount); 65 66 // fetch first buffer 67 if (mBuffer.frameCount == 0) { 68 mBuffer.frameCount = inFrameCount; 69 provider->getNextBuffer(&mBuffer); 70 if (mBuffer.raw == NULL) { 71 return 0; 72 } 73 // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); 74 } 75 int16_t *in = mBuffer.i16; 76 77 while (outputIndex < outputSampleCount) { 78 int32_t x; 79 80 // calculate output sample 81 x = phaseFraction >> kPreInterpShift; 82 out[outputIndex++] += vl * interp(&left, x); 83 out[outputIndex++] += vr * interp(&right, x); 84 // out[outputIndex++] += vr * in[inputIndex*2]; 85 86 // increment phase 87 phaseFraction += phaseIncrement; 88 uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); 89 phaseFraction &= kPhaseMask; 90 91 // time to fetch another sample 92 while (indexIncrement--) { 93 94 inputIndex++; 95 if (inputIndex == mBuffer.frameCount) { 96 inputIndex = 0; 97 provider->releaseBuffer(&mBuffer); 98 mBuffer.frameCount = inFrameCount; 99 provider->getNextBuffer(&mBuffer); 100 if (mBuffer.raw == NULL) { 101 goto save_state; // ugly, but efficient 102 } 103 in = mBuffer.i16; 104 // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount); 105 } 106 107 // advance sample state 108 advance(&left, in[inputIndex*2]); 109 advance(&right, in[inputIndex*2+1]); 110 } 111 } 112 113save_state: 114 // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); 115 mInputIndex = inputIndex; 116 mPhaseFraction = phaseFraction; 117 return outputIndex / 2 /* channels for stereo */; 118} 119 120size_t AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount, 121 AudioBufferProvider* provider) { 122 123 int32_t vl = mVolume[0]; 124 int32_t vr = mVolume[1]; 125 126 size_t inputIndex = mInputIndex; 127 uint32_t phaseFraction = mPhaseFraction; 128 uint32_t phaseIncrement = mPhaseIncrement; 129 size_t outputIndex = 0; 130 size_t outputSampleCount = outFrameCount * 2; 131 size_t inFrameCount = getInFrameCountRequired(outFrameCount); 132 133 // fetch first buffer 134 if (mBuffer.frameCount == 0) { 135 mBuffer.frameCount = inFrameCount; 136 provider->getNextBuffer(&mBuffer); 137 if (mBuffer.raw == NULL) { 138 return 0; 139 } 140 // ALOGW("New buffer: offset=%p, frames=%d", mBuffer.raw, mBuffer.frameCount); 141 } 142 int16_t *in = mBuffer.i16; 143 144 while (outputIndex < outputSampleCount) { 145 int32_t sample; 146 int32_t x; 147 148 // calculate output sample 149 x = phaseFraction >> kPreInterpShift; 150 sample = interp(&left, x); 151 out[outputIndex++] += vl * sample; 152 out[outputIndex++] += vr * sample; 153 154 // increment phase 155 phaseFraction += phaseIncrement; 156 uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits); 157 phaseFraction &= kPhaseMask; 158 159 // time to fetch another sample 160 while (indexIncrement--) { 161 162 inputIndex++; 163 if (inputIndex == mBuffer.frameCount) { 164 inputIndex = 0; 165 provider->releaseBuffer(&mBuffer); 166 mBuffer.frameCount = inFrameCount; 167 provider->getNextBuffer(&mBuffer); 168 if (mBuffer.raw == NULL) { 169 goto save_state; // ugly, but efficient 170 } 171 // ALOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount); 172 in = mBuffer.i16; 173 } 174 175 // advance sample state 176 advance(&left, in[inputIndex]); 177 } 178 } 179 180save_state: 181 // ALOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction); 182 mInputIndex = inputIndex; 183 mPhaseFraction = phaseFraction; 184 return outputIndex; 185} 186 187// ---------------------------------------------------------------------------- 188} // namespace android 189