diff --git a/modules/juce_dsp/processors/juce_Oversampling.cpp b/modules/juce_dsp/processors/juce_Oversampling.cpp index a8d527600a..7f3be92c6d 100644 --- a/modules/juce_dsp/processors/juce_Oversampling.cpp +++ b/modules/juce_dsp/processors/juce_Oversampling.cpp @@ -63,8 +63,8 @@ public: return dsp::AudioBlock (buffer).getSubBlock (0, numSamples); } - virtual void processSamplesUp (dsp::AudioBlock &inputBlock) = 0; - virtual void processSamplesDown (dsp::AudioBlock &outputBlock) = 0; + virtual void processSamplesUp (dsp::AudioBlock&) = 0; + virtual void processSamplesDown (dsp::AudioBlock&) = 0; protected: //=============================================================================== @@ -88,10 +88,10 @@ public: //=============================================================================== SampleType getLatencyInSamples() override { - return 0.f; + return 0; } - void processSamplesUp (dsp::AudioBlock &inputBlock) override + void processSamplesUp (dsp::AudioBlock& inputBlock) override { jassert (inputBlock.getNumChannels() <= static_cast (OversamplingEngine::buffer.getNumChannels())); jassert (inputBlock.getNumSamples() * OversamplingEngine::factor <= static_cast (OversamplingEngine::buffer.getNumSamples())); @@ -101,7 +101,7 @@ public: inputBlock.getChannelPointer (channel), static_cast (inputBlock.getNumSamples())); } - void processSamplesDown (dsp::AudioBlock &outputBlock) override + void processSamplesDown (dsp::AudioBlock& outputBlock) override { jassert (outputBlock.getNumChannels() <= static_cast (OversamplingEngine::buffer.getNumChannels())); jassert (outputBlock.getNumSamples() * OversamplingEngine::factor <= static_cast (OversamplingEngine::buffer.getNumSamples())); @@ -109,8 +109,6 @@ public: outputBlock.copy (OversamplingEngine::getProcessedSamples (outputBlock.getNumSamples())); } -private: - //=============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OversamplingDummy) }; @@ -121,10 +119,9 @@ private: leading to specific processing optimizations. */ template -class Oversampling2TimesEquirippleFIR : public OversamplingEngine +class Oversampling2TimesEquirippleFIR : public OversamplingEngine { public: - //=============================================================================== Oversampling2TimesEquirippleFIR (size_t numChans, SampleType normalizedTransitionWidthUp, SampleType stopbandAttenuationdBUp, @@ -132,7 +129,7 @@ public: SampleType stopbandAttenuationdBDown) : OversamplingEngine (numChans, 2) { - coefficientsUp = *dsp::FilterDesign::designFIRLowpassHalfBandEquirippleMethod (normalizedTransitionWidthUp, stopbandAttenuationdBUp); + coefficientsUp = *dsp::FilterDesign::designFIRLowpassHalfBandEquirippleMethod (normalizedTransitionWidthUp, stopbandAttenuationdBUp); coefficientsDown = *dsp::FilterDesign::designFIRLowpassHalfBandEquirippleMethod (normalizedTransitionWidthDown, stopbandAttenuationdBDown); auto N = coefficientsUp.getFilterOrder() + 1; @@ -167,7 +164,7 @@ public: position.fill (0); } - void processSamplesUp (dsp::AudioBlock &inputBlock) override + void processSamplesUp (dsp::AudioBlock& inputBlock) override { jassert (inputBlock.getNumChannels() <= static_cast (OversamplingEngine::buffer.getNumChannels())); jassert (inputBlock.getNumSamples() * OversamplingEngine::factor <= static_cast (OversamplingEngine::buffer.getNumSamples())); @@ -192,6 +189,7 @@ public: // Convolution auto out = static_cast (0.0); + for (size_t k = 0; k < Ndiv2; k += 2) out += (buf[k] + buf[N - k - 1]) * fir[k]; @@ -206,7 +204,7 @@ public: } } - void processSamplesDown (dsp::AudioBlock &outputBlock) override + void processSamplesDown (dsp::AudioBlock& outputBlock) override { jassert (outputBlock.getNumChannels() <= static_cast (OversamplingEngine::buffer.getNumChannels())); jassert (outputBlock.getNumSamples() * OversamplingEngine::factor <= static_cast (OversamplingEngine::buffer.getNumSamples())); @@ -234,6 +232,7 @@ public: // Convolution auto out = static_cast (0.0); + for (size_t k = 0; k < Ndiv2; k += 2) out += (buf[k] + buf[N - k - 1]) * fir[k]; @@ -273,10 +272,9 @@ private: phase, and provided with a method to get the exact resulting latency. */ template -class Oversampling2TimesPolyphaseIIR : public OversamplingEngine +class Oversampling2TimesPolyphaseIIR : public OversamplingEngine { public: - //=============================================================================== Oversampling2TimesPolyphaseIIR (size_t numChans, SampleType normalizedTransitionWidthUp, SampleType stopbandAttenuationdBUp, @@ -292,14 +290,14 @@ public: dsp::IIR::Coefficients coeffsDown = getCoefficients (structureDown); latency += static_cast (-(coeffsDown.getPhaseForFrequency (0.0001, 1.0)) / (0.0001 * MathConstants::twoPi)); - for (auto i = 0; i < structureUp.directPath.size(); ++i) - coefficientsUp.add (structureUp.directPath[i].coefficients[0]); + for (auto& i : structureUp.directPath) + coefficientsUp.add (i.coefficients[0]); for (auto i = 1; i < structureUp.delayedPath.size(); ++i) coefficientsUp.add (structureUp.delayedPath[i].coefficients[0]); - for (auto i = 0; i < structureDown.directPath.size(); ++i) - coefficientsDown.add (structureDown.directPath[i].coefficients[0]); + for (auto& i : structureDown.directPath) + coefficientsDown.add (i.coefficients[0]); for (auto i = 1; i < structureDown.delayedPath.size(); ++i) coefficientsDown.add (structureDown.delayedPath[i].coefficients[0]); @@ -320,13 +318,12 @@ public: void reset() override { OversamplingEngine::reset(); - v1Up.clear(); v1Down.clear(); delayDown.fill (0); } - void processSamplesUp (dsp::AudioBlock &inputBlock) override + void processSamplesUp (dsp::AudioBlock& inputBlock) override { jassert (inputBlock.getNumChannels() <= static_cast (OversamplingEngine::buffer.getNumChannels())); jassert (inputBlock.getNumSamples() * OversamplingEngine::factor <= static_cast (OversamplingEngine::buffer.getNumSamples())); @@ -349,6 +346,7 @@ public: { // Direct path cascaded allpass filters auto input = samples[i]; + for (auto n = 0; n < directStages; ++n) { auto alpha = coeffs[n]; @@ -362,6 +360,7 @@ public: // Delayed path cascaded allpass filters input = samples[i]; + for (auto n = directStages; n < numStages; ++n) { auto alpha = coeffs[n]; @@ -379,7 +378,7 @@ public: snapToZero (true); } - void processSamplesDown (dsp::AudioBlock &outputBlock) override + void processSamplesDown (dsp::AudioBlock& outputBlock) override { jassert (outputBlock.getNumChannels() <= static_cast (OversamplingEngine::buffer.getNumChannels())); jassert (outputBlock.getNumSamples() * OversamplingEngine::factor <= static_cast (OversamplingEngine::buffer.getNumSamples())); @@ -403,6 +402,7 @@ public: { // Direct path cascaded allpass filters auto input = bufferSamples[i << 1]; + for (auto n = 0; n < directStages; ++n) { auto alpha = coeffs[n]; @@ -410,10 +410,12 @@ public: lv1[n] = input - alpha * output; input = output; } + auto directOut = input; // Delayed path cascaded allpass filters input = bufferSamples[(i << 1) + 1]; + for (auto n = directStages; n < numStages; ++n) { auto alpha = coeffs[n]; @@ -467,12 +469,12 @@ private: */ const dsp::IIR::Coefficients getCoefficients (typename dsp::FilterDesign::IIRPolyphaseAllpassStructure& structure) const { - dsp::Polynomial numerator1 ({ static_cast (1.0) }); - dsp::Polynomial denominator1 ({ static_cast (1.0) }); - dsp::Polynomial numerator2 ({ static_cast (1.0) }); - dsp::Polynomial denominator2 ({ static_cast (1.0) }); + constexpr auto one = static_cast (1.0); - dsp::Polynomial temp; + dsp::Polynomial numerator1 ({ one }); + dsp::Polynomial denominator1 ({ one }); + dsp::Polynomial numerator2 ({ one }); + dsp::Polynomial denominator2 ({ one }); for (auto n = 0; n < structure.directPath.size(); ++n) { @@ -480,19 +482,13 @@ private: if (structure.directPath[n].getFilterOrder() == 1) { - temp = dsp::Polynomial ({ coeffs[0], coeffs[1] }); - numerator1 = numerator1.getProductWith (temp); - - temp = dsp::Polynomial ({ static_cast (1.0), coeffs[2] }); - denominator1 = denominator1.getProductWith (temp); + numerator1 = numerator1.getProductWith (dsp::Polynomial ({ coeffs[0], coeffs[1] })); + denominator1 = denominator1.getProductWith (dsp::Polynomial ({ one, coeffs[2] })); } else { - temp = dsp::Polynomial ({ coeffs[0], coeffs[1], coeffs[2] }); - numerator1 = numerator1.getProductWith (temp); - - temp = dsp::Polynomial ({ static_cast (1.0), coeffs[3], coeffs[4] }); - denominator1 = denominator1.getProductWith (temp); + numerator1 = numerator1.getProductWith (dsp::Polynomial ({ coeffs[0], coeffs[1], coeffs[2] })); + denominator1 = denominator1.getProductWith (dsp::Polynomial ({ one, coeffs[3], coeffs[4] })); } } @@ -502,31 +498,25 @@ private: if (structure.delayedPath[n].getFilterOrder() == 1) { - temp = dsp::Polynomial ({ coeffs[0], coeffs[1] }); - numerator2 = numerator2.getProductWith (temp); - - temp = dsp::Polynomial ({ static_cast (1.0), coeffs[2] }); - denominator2 = denominator2.getProductWith (temp); + numerator2 = numerator2.getProductWith (dsp::Polynomial ({ coeffs[0], coeffs[1] })); + denominator2 = denominator2.getProductWith (dsp::Polynomial ({ one, coeffs[2] })); } else { - temp = dsp::Polynomial ({ coeffs[0], coeffs[1], coeffs[2] }); - numerator2 = numerator2.getProductWith (temp); - - temp = dsp::Polynomial ({ static_cast (1.0), coeffs[3], coeffs[4] }); - denominator2 = denominator2.getProductWith (temp); + numerator2 = numerator2.getProductWith (dsp::Polynomial ({ coeffs[0], coeffs[1], coeffs[2] })); + denominator2 = denominator2.getProductWith (dsp::Polynomial ({ one, coeffs[3], coeffs[4] })); } } - dsp::Polynomial numeratorf1 = numerator1.getProductWith (denominator2); - dsp::Polynomial numeratorf2 = numerator2.getProductWith (denominator1); - dsp::Polynomial numerator = numeratorf1.getSumWith (numeratorf2); - dsp::Polynomial denominator = denominator1.getProductWith (denominator2); + auto numeratorf1 = numerator1.getProductWith (denominator2); + auto numeratorf2 = numerator2.getProductWith (denominator1); + auto numerator = numeratorf1.getSumWith (numeratorf2); + auto denominator = denominator1.getProductWith (denominator2); dsp::IIR::Coefficients coeffs; coeffs.coefficients.clear(); - auto inversion = static_cast (1.0) / denominator[0]; + auto inversion = one / denominator[0]; for (auto i = 0; i <= numerator.getOrder(); ++i) coeffs.coefficients.add (numerator[i] * inversion); @@ -551,7 +541,8 @@ private: //=============================================================================== template -Oversampling::Oversampling (size_t newNumChannels, size_t newFactor, FilterType newType, bool newMaxQuality) +Oversampling::Oversampling (size_t newNumChannels, size_t newFactor, + FilterType newType, bool newMaxQuality) { jassert (newFactor >= 0 && newFactor <= 4 && newNumChannels > 0); @@ -571,13 +562,13 @@ Oversampling::Oversampling (size_t newNumChannels, size_t newFactor, for (size_t n = 0; n < numStages; ++n) { - auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.f); - auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.f); + auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f); + auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f); - auto gaindBStartUp = (isMaximumQuality ? -75.f : -65.f); - auto gaindBStartDown = (isMaximumQuality ? -70.f : -60.f); - auto gaindBFactorUp = (isMaximumQuality ? 10.f : 8.f); - auto gaindBFactorDown = (isMaximumQuality ? 10.f : 8.f); + auto gaindBStartUp = (isMaximumQuality ? -75.0f : -65.0f); + auto gaindBStartDown = (isMaximumQuality ? -70.0f : -60.0f); + auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f); + auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f); engines.add (new Oversampling2TimesPolyphaseIIR (numChannels, twUp, gaindBStartUp + gaindBFactorUp * n, @@ -590,13 +581,13 @@ Oversampling::Oversampling (size_t newNumChannels, size_t newFactor, for (size_t n = 0; n < numStages; ++n) { - auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.f); - auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.f); + auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f); + auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f); - auto gaindBStartUp = (isMaximumQuality ? -90.f : -70.f); - auto gaindBStartDown = (isMaximumQuality ? -70.f : -60.f); - auto gaindBFactorUp = (isMaximumQuality ? 10.f : 8.f); - auto gaindBFactorDown = (isMaximumQuality ? 10.f : 8.f); + auto gaindBStartUp = (isMaximumQuality ? -90.0f : -70.0f); + auto gaindBStartDown = (isMaximumQuality ? -70.0f : -60.0f); + auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f); + auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f); engines.add (new Oversampling2TimesEquirippleFIR (numChannels, twUp, gaindBStartUp + gaindBFactorUp * n, @@ -665,7 +656,7 @@ void Oversampling::reset() noexcept } template -typename dsp::AudioBlock Oversampling::processSamplesUp (const dsp::AudioBlock &inputBlock) noexcept +typename dsp::AudioBlock Oversampling::processSamplesUp (const dsp::AudioBlock& inputBlock) noexcept { jassert (! engines.isEmpty()); @@ -685,7 +676,7 @@ typename dsp::AudioBlock Oversampling::processSamplesUp } template -void Oversampling::processSamplesDown (dsp::AudioBlock &outputBlock) noexcept +void Oversampling::processSamplesDown (dsp::AudioBlock& outputBlock) noexcept { jassert (! engines.isEmpty()); diff --git a/modules/juce_dsp/processors/juce_Oversampling.h b/modules/juce_dsp/processors/juce_Oversampling.h index 5ec971c20c..7ecd7f4bee 100644 --- a/modules/juce_dsp/processors/juce_Oversampling.h +++ b/modules/juce_dsp/processors/juce_Oversampling.h @@ -86,7 +86,10 @@ public: the filters will be more efficient, but the CPU load will increase as well */ - Oversampling (size_t numChannels, size_t factor, FilterType type, bool isMaxQuality = true); + Oversampling (size_t numChannels, + size_t factor, + FilterType type, + bool isMaxQuality = true); /** Destructor. */ ~Oversampling(); @@ -121,14 +124,14 @@ public: Don't forget to set the sample rate of that processing to N times the original sample rate. */ - dsp::AudioBlock processSamplesUp (const dsp::AudioBlock &inputBlock) noexcept; + dsp::AudioBlock processSamplesUp (const dsp::AudioBlock& inputBlock) noexcept; /** Must be called to perform the downsampling, after the upsampling and the non-linear processing. The output signal is probably delayed by the internal latency of the whole oversampling behaviour, so don't forget to take this into account. */ - void processSamplesDown (dsp::AudioBlock &outputBlock) noexcept; + void processSamplesDown (dsp::AudioBlock& outputBlock) noexcept; private: //===============================================================================