Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9757d3c9 authored by Robert Wu's avatar Robert Wu
Browse files

AAudio: Add resampler changes from Oboe

This change syncs Oboe and AAudio by adding resampler changes

Bug: 262605986
Test: atest test_flowgraph
Test: atest test_resampler
Test: AAudioTests
Change-Id: I69d7e2c3cbbfb2c71a5063fee78a84f041da48b9
parent a96e1149
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ MultiChannelResampler::MultiChannelResampler(const MultiChannelResampler::Builde
    ratio.reduce();
    mNumerator = ratio.getNumerator();
    mDenominator = ratio.getDenominator();
    mIntegerPhase = mDenominator;
    mIntegerPhase = mDenominator; // so we start with a write needed
}

// static factory method
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ Note that the number of output frames generated for a given number of input fram

For example, suppose you are converting from 44100 Hz to 48000 Hz and using an input buffer with 960 frames. If you calculate the number of output frames you get:

    960 * 48000 * 44100 = 1044.897959...
    960.0 * 48000 / 44100 = 1044.897959...

You cannot generate a fractional number of frames. So the resampler will sometimes generate 1044 frames and sometimes 1045 frames. On average it will generate 1044.897959 frames. The resampler stores the fraction internally and keeps track of when to consume or generate a frame.

+21 −28
Original line number Diff line number Diff line
@@ -24,9 +24,10 @@ SincResampler::SincResampler(const MultiChannelResampler::Builder &builder)
        : MultiChannelResampler(builder)
        , mSingleFrame2(builder.getChannelCount()) {
    assert((getNumTaps() % 4) == 0); // Required for loop unrolling.
    mNumRows = kMaxCoefficients / getNumTaps(); // no guard row needed
    mPhaseScaler = (double) mNumRows / mDenominator;
    double phaseIncrement = 1.0 / mNumRows;
    mNumRows = kMaxCoefficients / getNumTaps(); // includes guard row
    const int32_t numRowsNoGuard = mNumRows - 1;
    mPhaseScaler = (double) numRowsNoGuard / mDenominator;
    const double phaseIncrement = 1.0 / numRowsNoGuard;
    generateCoefficients(builder.getInputRate(),
                         builder.getOutputRate(),
                         mNumRows,
@@ -40,39 +41,31 @@ void SincResampler::readFrame(float *frame) {
    std::fill(mSingleFrame2.begin(), mSingleFrame2.end(), 0.0);

    // Determine indices into coefficients table.
    double tablePhase = getIntegerPhase() * mPhaseScaler;
    int index1 = static_cast<int>(floor(tablePhase));
    if (index1 >= mNumRows) { // no guard row needed because we wrap the indices
        tablePhase -= mNumRows;
        index1 -= mNumRows;
    }

    int index2 = index1 + 1;
    if (index2 >= mNumRows) { // no guard row needed because we wrap the indices
        index2 -= mNumRows;
    }

    float *coefficients1 = &mCoefficients[static_cast<size_t>(index1)
    const double tablePhase = getIntegerPhase() * mPhaseScaler;
    const int indexLow = static_cast<int>(floor(tablePhase));
    const int indexHigh = indexLow + 1; // OK because using a guard row.
    assert (indexHigh < mNumRows);
    float *coefficientsLow = &mCoefficients[static_cast<size_t>(indexLow)
                                            * static_cast<size_t>(getNumTaps())];
    float *coefficients2 = &mCoefficients[static_cast<size_t>(index2)
    float *coefficientsHigh = &mCoefficients[static_cast<size_t>(indexHigh)
                                             * static_cast<size_t>(getNumTaps())];

    float *xFrame = &mX[static_cast<size_t>(mCursor) * static_cast<size_t>(getChannelCount())];
    for (int i = 0; i < mNumTaps; i++) {
        float coefficient1 = *coefficients1++;
        float coefficient2 = *coefficients2++;
    for (int tap = 0; tap < mNumTaps; tap++) {
        const float coefficientLow = *coefficientsLow++;
        const float coefficientHigh = *coefficientsHigh++;
        for (int channel = 0; channel < getChannelCount(); channel++) {
            float sample = *xFrame++;
            mSingleFrame[channel] +=  sample * coefficient1;
            mSingleFrame2[channel] += sample * coefficient2;
            const float sample = *xFrame++;
            mSingleFrame[channel] += sample * coefficientLow;
            mSingleFrame2[channel] += sample * coefficientHigh;
        }
    }

    // Interpolate and copy to output.
    float fraction = tablePhase - index1;
    const float fraction = tablePhase - indexLow;
    for (int channel = 0; channel < getChannelCount(); channel++) {
        float low = mSingleFrame[channel];
        float high = mSingleFrame2[channel];
        const float low = mSingleFrame[channel];
        const float high = mSingleFrame2[channel];
        frame[channel] = low + (fraction * (high - low));
    }
}
+0 −3
Original line number Diff line number Diff line
@@ -57,9 +57,6 @@ void SincResamplerStereo::readFrame(float *frame) {
    float *coefficients1 = &mCoefficients[static_cast<size_t>(index1)
            * static_cast<size_t>(getNumTaps())];
    int index2 = (index1 + 1);
    if (index2 >= mNumRows) { // no guard row needed because we wrap the indices
        index2 = 0;
    }
    float *coefficients2 = &mCoefficients[static_cast<size_t>(index2)
            * static_cast<size_t>(getNumTaps())];
    float *xFrame = &mX[static_cast<size_t>(mCursor) * static_cast<size_t>(getChannelCount())];
+9 −0
Original line number Diff line number Diff line
@@ -228,3 +228,12 @@ cc_test {
        "liblog",
    ],
}

cc_test {
    name: "test_resampler",
    defaults: ["libaaudio_tests_defaults"],
    srcs: ["test_resampler.cpp"],
    shared_libs: [
        "libaaudio_internal",
    ],
}
Loading