1*05767d91SRobert Wu /*
2*05767d91SRobert Wu * Copyright 2019 The Android Open Source Project
3*05767d91SRobert Wu *
4*05767d91SRobert Wu * Licensed under the Apache License, Version 2.0 (the "License");
5*05767d91SRobert Wu * you may not use this file except in compliance with the License.
6*05767d91SRobert Wu * You may obtain a copy of the License at
7*05767d91SRobert Wu *
8*05767d91SRobert Wu * http://www.apache.org/licenses/LICENSE-2.0
9*05767d91SRobert Wu *
10*05767d91SRobert Wu * Unless required by applicable law or agreed to in writing, software
11*05767d91SRobert Wu * distributed under the License is distributed on an "AS IS" BASIS,
12*05767d91SRobert Wu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*05767d91SRobert Wu * See the License for the specific language governing permissions and
14*05767d91SRobert Wu * limitations under the License.
15*05767d91SRobert Wu */
16*05767d91SRobert Wu
17*05767d91SRobert Wu #include <algorithm> // Do NOT delete. Needed for LLVM. See #1746
18*05767d91SRobert Wu #include <cassert>
19*05767d91SRobert Wu #include <math.h>
20*05767d91SRobert Wu #include "SincResampler.h"
21*05767d91SRobert Wu
22*05767d91SRobert Wu using namespace RESAMPLER_OUTER_NAMESPACE::resampler;
23*05767d91SRobert Wu
SincResampler(const MultiChannelResampler::Builder & builder)24*05767d91SRobert Wu SincResampler::SincResampler(const MultiChannelResampler::Builder &builder)
25*05767d91SRobert Wu : MultiChannelResampler(builder)
26*05767d91SRobert Wu , mSingleFrame2(builder.getChannelCount()) {
27*05767d91SRobert Wu assert((getNumTaps() % 4) == 0); // Required for loop unrolling.
28*05767d91SRobert Wu mNumRows = kMaxCoefficients / getNumTaps(); // includes guard row
29*05767d91SRobert Wu const int32_t numRowsNoGuard = mNumRows - 1;
30*05767d91SRobert Wu mPhaseScaler = (double) numRowsNoGuard / mDenominator;
31*05767d91SRobert Wu const double phaseIncrement = 1.0 / numRowsNoGuard;
32*05767d91SRobert Wu generateCoefficients(builder.getInputRate(),
33*05767d91SRobert Wu builder.getOutputRate(),
34*05767d91SRobert Wu mNumRows,
35*05767d91SRobert Wu phaseIncrement,
36*05767d91SRobert Wu builder.getNormalizedCutoff());
37*05767d91SRobert Wu }
38*05767d91SRobert Wu
readFrame(float * frame)39*05767d91SRobert Wu void SincResampler::readFrame(float *frame) {
40*05767d91SRobert Wu // Clear accumulator for mixing.
41*05767d91SRobert Wu std::fill(mSingleFrame.begin(), mSingleFrame.end(), 0.0);
42*05767d91SRobert Wu std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0);
43*05767d91SRobert Wu
44*05767d91SRobert Wu // Determine indices into coefficients table.
45*05767d91SRobert Wu const double tablePhase = getIntegerPhase() * mPhaseScaler;
46*05767d91SRobert Wu const int indexLow = static_cast<int>(floor(tablePhase));
47*05767d91SRobert Wu const int indexHigh = indexLow + 1; // OK because using a guard row.
48*05767d91SRobert Wu assert (indexHigh < mNumRows);
49*05767d91SRobert Wu float *coefficientsLow = &mCoefficients[static_cast<size_t>(indexLow)
50*05767d91SRobert Wu * static_cast<size_t>(getNumTaps())];
51*05767d91SRobert Wu float *coefficientsHigh = &mCoefficients[static_cast<size_t>(indexHigh)
52*05767d91SRobert Wu * static_cast<size_t>(getNumTaps())];
53*05767d91SRobert Wu
54*05767d91SRobert Wu float *xFrame = &mX[static_cast<size_t>(mCursor) * static_cast<size_t>(getChannelCount())];
55*05767d91SRobert Wu for (int tap = 0; tap < mNumTaps; tap++) {
56*05767d91SRobert Wu const float coefficientLow = *coefficientsLow++;
57*05767d91SRobert Wu const float coefficientHigh = *coefficientsHigh++;
58*05767d91SRobert Wu for (int channel = 0; channel < getChannelCount(); channel++) {
59*05767d91SRobert Wu const float sample = *xFrame++;
60*05767d91SRobert Wu mSingleFrame[channel] += sample * coefficientLow;
61*05767d91SRobert Wu mSingleFrame2[channel] += sample * coefficientHigh;
62*05767d91SRobert Wu }
63*05767d91SRobert Wu }
64*05767d91SRobert Wu
65*05767d91SRobert Wu // Interpolate and copy to output.
66*05767d91SRobert Wu const float fraction = tablePhase - indexLow;
67*05767d91SRobert Wu for (int channel = 0; channel < getChannelCount(); channel++) {
68*05767d91SRobert Wu const float low = mSingleFrame[channel];
69*05767d91SRobert Wu const float high = mSingleFrame2[channel];
70*05767d91SRobert Wu frame[channel] = low + (fraction * (high - low));
71*05767d91SRobert Wu }
72*05767d91SRobert Wu }
73