diff options
| author | crueter <crueter@eden-emu.dev> | 2025-08-04 04:50:14 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2025-08-04 04:50:14 +0200 |
| commit | 51b170b470ed587f99a7c2a773e4464687f0d07a (patch) | |
| tree | 4c03c510cfb17a5f5d6233df490d78f06dcfa7f7 /externals/oboe/src/flowgraph/resampler/MultiChannelResampler.cpp | |
| parent | 04e5e6453875ffa5c79cdb421a29bc19985b1049 (diff) | |
[cmake] refactor: Use CPM over submodules (#143)
Transfers the majority of submodules and large externals to CPM, using source archives rather than full Git clones. Not only does this save massive amounts of clone and configure time, but dependencies are grabbed on-demand rather than being required by default. Additionally, CPM will (generally) automatically search for system dependencies, though certain dependencies have options to control this.
Testing shows gains ranging from 5x to 10x in terms of overall clone/configure time.
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/143
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Diffstat (limited to 'externals/oboe/src/flowgraph/resampler/MultiChannelResampler.cpp')
| -rw-r--r-- | externals/oboe/src/flowgraph/resampler/MultiChannelResampler.cpp | 171 |
1 files changed, 0 insertions, 171 deletions
diff --git a/externals/oboe/src/flowgraph/resampler/MultiChannelResampler.cpp b/externals/oboe/src/flowgraph/resampler/MultiChannelResampler.cpp deleted file mode 100644 index 245b669db4..0000000000 --- a/externals/oboe/src/flowgraph/resampler/MultiChannelResampler.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <math.h> - -#include "IntegerRatio.h" -#include "LinearResampler.h" -#include "MultiChannelResampler.h" -#include "PolyphaseResampler.h" -#include "PolyphaseResamplerMono.h" -#include "PolyphaseResamplerStereo.h" -#include "SincResampler.h" -#include "SincResamplerStereo.h" - -using namespace RESAMPLER_OUTER_NAMESPACE::resampler; - -MultiChannelResampler::MultiChannelResampler(const MultiChannelResampler::Builder &builder) - : mNumTaps(builder.getNumTaps()) - , mX(static_cast<size_t>(builder.getChannelCount()) - * static_cast<size_t>(builder.getNumTaps()) * 2) - , mSingleFrame(builder.getChannelCount()) - , mChannelCount(builder.getChannelCount()) - { - // Reduce sample rates to the smallest ratio. - // For example 44100/48000 would become 147/160. - IntegerRatio ratio(builder.getInputRate(), builder.getOutputRate()); - ratio.reduce(); - mNumerator = ratio.getNumerator(); - mDenominator = ratio.getDenominator(); - mIntegerPhase = mDenominator; // so we start with a write needed -} - -// static factory method -MultiChannelResampler *MultiChannelResampler::make(int32_t channelCount, - int32_t inputRate, - int32_t outputRate, - Quality quality) { - Builder builder; - builder.setInputRate(inputRate); - builder.setOutputRate(outputRate); - builder.setChannelCount(channelCount); - - switch (quality) { - case Quality::Fastest: - builder.setNumTaps(2); - break; - case Quality::Low: - builder.setNumTaps(4); - break; - case Quality::Medium: - default: - builder.setNumTaps(8); - break; - case Quality::High: - builder.setNumTaps(16); - break; - case Quality::Best: - builder.setNumTaps(32); - break; - } - - // Set the cutoff frequency so that we do not get aliasing when down-sampling. - if (inputRate > outputRate) { - builder.setNormalizedCutoff(kDefaultNormalizedCutoff); - } - return builder.build(); -} - -MultiChannelResampler *MultiChannelResampler::Builder::build() { - if (getNumTaps() == 2) { - // Note that this does not do low pass filteringh. - return new LinearResampler(*this); - } - IntegerRatio ratio(getInputRate(), getOutputRate()); - ratio.reduce(); - bool usePolyphase = (getNumTaps() * ratio.getDenominator()) <= kMaxCoefficients; - if (usePolyphase) { - if (getChannelCount() == 1) { - return new PolyphaseResamplerMono(*this); - } else if (getChannelCount() == 2) { - return new PolyphaseResamplerStereo(*this); - } else { - return new PolyphaseResampler(*this); - } - } else { - // Use less optimized resampler that uses a float phaseIncrement. - // TODO mono resampler - if (getChannelCount() == 2) { - return new SincResamplerStereo(*this); - } else { - return new SincResampler(*this); - } - } -} - -void MultiChannelResampler::writeFrame(const float *frame) { - // Move cursor before write so that cursor points to last written frame in read. - if (--mCursor < 0) { - mCursor = getNumTaps() - 1; - } - float *dest = &mX[static_cast<size_t>(mCursor) * static_cast<size_t>(getChannelCount())]; - int offset = getNumTaps() * getChannelCount(); - for (int channel = 0; channel < getChannelCount(); channel++) { - // Write twice so we avoid having to wrap when reading. - dest[channel] = dest[channel + offset] = frame[channel]; - } -} - -float MultiChannelResampler::sinc(float radians) { - if (fabsf(radians) < 1.0e-9f) return 1.0f; // avoid divide by zero - return sinf(radians) / radians; // Sinc function -} - -// Generate coefficients in the order they will be used by readFrame(). -// This is more complicated but readFrame() is called repeatedly and should be optimized. -void MultiChannelResampler::generateCoefficients(int32_t inputRate, - int32_t outputRate, - int32_t numRows, - double phaseIncrement, - float normalizedCutoff) { - mCoefficients.resize(static_cast<size_t>(getNumTaps()) * static_cast<size_t>(numRows)); - int coefficientIndex = 0; - double phase = 0.0; // ranges from 0.0 to 1.0, fraction between samples - // Stretch the sinc function for low pass filtering. - const float cutoffScaler = (outputRate < inputRate) - ? (normalizedCutoff * (float)outputRate / inputRate) - : 1.0f; // Do not filter when upsampling. - const int numTapsHalf = getNumTaps() / 2; // numTaps must be even. - const float numTapsHalfInverse = 1.0f / numTapsHalf; - for (int i = 0; i < numRows; i++) { - float tapPhase = phase - numTapsHalf; - float gain = 0.0; // sum of raw coefficients - int gainCursor = coefficientIndex; - for (int tap = 0; tap < getNumTaps(); tap++) { - float radians = tapPhase * M_PI; - -#if MCR_USE_KAISER - float window = mKaiserWindow(tapPhase * numTapsHalfInverse); -#else - float window = mCoshWindow(static_cast<double>(tapPhase) * numTapsHalfInverse); -#endif - float coefficient = sinc(radians * cutoffScaler) * window; - mCoefficients.at(coefficientIndex++) = coefficient; - gain += coefficient; - tapPhase += 1.0; - } - phase += phaseIncrement; - while (phase >= 1.0) { - phase -= 1.0; - } - - // Correct for gain variations. - float gainCorrection = 1.0 / gain; // normalize the gain - for (int tap = 0; tap < getNumTaps(); tap++) { - mCoefficients.at(gainCursor + tap) *= gainCorrection; - } - } -} |
