1 /* 2 * Copyright 2019 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 #include <algorithm> // Do NOT delete. Needed for LLVM. See #1746 18 #include <cassert> 19 #include <math.h> 20 21 #include "SincResamplerStereo.h" 22 23 using namespace RESAMPLER_OUTER_NAMESPACE::resampler; 24 25 #define STEREO 2 26 SincResamplerStereo(const MultiChannelResampler::Builder & builder)27SincResamplerStereo::SincResamplerStereo(const MultiChannelResampler::Builder &builder) 28 : SincResampler(builder) { 29 assert(builder.getChannelCount() == STEREO); 30 } 31 writeFrame(const float * frame)32void SincResamplerStereo::writeFrame(const float *frame) { 33 // Move cursor before write so that cursor points to last written frame in read. 34 if (--mCursor < 0) { 35 mCursor = getNumTaps() - 1; 36 } 37 float *dest = &mX[mCursor * STEREO]; 38 const int offset = mNumTaps * STEREO; 39 // Write each channel twice so we avoid having to wrap when running the FIR. 40 const float left = frame[0]; 41 const float right = frame[1]; 42 // Put ordered writes together. 43 dest[0] = left; 44 dest[1] = right; 45 dest[offset] = left; 46 dest[1 + offset] = right; 47 } 48 49 // Multiply input times windowed sinc function. readFrame(float * frame)50void SincResamplerStereo::readFrame(float *frame) { 51 // Clear accumulator for mixing. 52 std::fill(mSingleFrame.begin(), mSingleFrame.end(), 0.0); 53 std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0); 54 55 // Determine indices into coefficients table. 56 double tablePhase = getIntegerPhase() * mPhaseScaler; 57 int index1 = static_cast<int>(floor(tablePhase)); 58 float *coefficients1 = &mCoefficients[static_cast<size_t>(index1) 59 * static_cast<size_t>(getNumTaps())]; 60 int index2 = (index1 + 1); 61 float *coefficients2 = &mCoefficients[static_cast<size_t>(index2) 62 * static_cast<size_t>(getNumTaps())]; 63 float *xFrame = &mX[static_cast<size_t>(mCursor) * static_cast<size_t>(getChannelCount())]; 64 for (int i = 0; i < mNumTaps; i++) { 65 float coefficient1 = *coefficients1++; 66 float coefficient2 = *coefficients2++; 67 for (int channel = 0; channel < getChannelCount(); channel++) { 68 float sample = *xFrame++; 69 mSingleFrame[channel] += sample * coefficient1; 70 mSingleFrame2[channel] += sample * coefficient2; 71 } 72 } 73 74 // Interpolate and copy to output. 75 float fraction = tablePhase - index1; 76 for (int channel = 0; channel < getChannelCount(); channel++) { 77 float low = mSingleFrame[channel]; 78 float high = mSingleFrame2[channel]; 79 frame[channel] = low + (fraction * (high - low)); 80 } 81 } 82