void processSamplesDown (dsp::AudioBlock<SampleType> &outputBlock) override { jassert (outputBlock.getNumChannels() <= static_cast<size_t> (OversamplingEngine<SampleType>::buffer.getNumChannels())); jassert (outputBlock.getNumSamples() * OversamplingEngine<SampleType>::factor <= static_cast<size_t> (OversamplingEngine<SampleType>::buffer.getNumSamples())); // Initialization auto fir = coefficientsDown.getRawCoefficients(); auto N = coefficientsDown.getFilterOrder() + 1; auto Ndiv2 = N / 2; auto Ndiv4 = Ndiv2 / 2; auto numSamples = outputBlock.getNumSamples(); // Processing for (size_t channel = 0; channel < outputBlock.getNumChannels(); channel++) { auto bufferSamples = OversamplingEngine<SampleType>::buffer.getWritePointer (static_cast<int> (channel)); auto buf = stateDown.getWritePointer (static_cast<int> (channel)); auto buf2 = stateDown2.getWritePointer (static_cast<int> (channel)); auto samples = outputBlock.getChannelPointer (channel); auto pos = position.getUnchecked (static_cast<int> (channel)); for (size_t i = 0; i < numSamples; i++) { // Input buf[N - 1] = bufferSamples[i << 1]; // Convolution auto out = static_cast<SampleType> (0.0); for (size_t k = 0; k < Ndiv2; k += 2) out += (buf[k] + buf[N - k - 1]) * fir[k]; // Output out += buf2[pos] * fir[Ndiv2]; buf2[pos] = bufferSamples[(i << 1) + 1]; samples[i] = out; // Shift data for (size_t k = 0; k < N - 2; k++) buf[k] = buf[k + 2]; // Circular buffer pos = (pos == 0 ? Ndiv4 : pos - 1); } position.setUnchecked (static_cast<int> (channel), pos); } }
void processSamplesUp (dsp::AudioBlock<SampleType> &inputBlock) override { jassert (inputBlock.getNumChannels() <= static_cast<size_t> (OversamplingEngine<SampleType>::buffer.getNumChannels())); jassert (inputBlock.getNumSamples() * OversamplingEngine<SampleType>::factor <= static_cast<size_t> (OversamplingEngine<SampleType>::buffer.getNumSamples())); // Initialization auto fir = coefficientsUp.getRawCoefficients(); auto N = coefficientsUp.getFilterOrder() + 1; auto Ndiv2 = N / 2; auto numSamples = inputBlock.getNumSamples(); // Processing for (size_t channel = 0; channel < inputBlock.getNumChannels(); channel++) { auto bufferSamples = OversamplingEngine<SampleType>::buffer.getWritePointer (static_cast<int> (channel)); auto buf = stateUp.getWritePointer (static_cast<int> (channel)); auto samples = inputBlock.getChannelPointer (channel); for (size_t i = 0; i < numSamples; i++) { // Input buf[N - 1] = 2 * samples[i]; // Convolution auto out = static_cast<SampleType> (0.0); for (size_t k = 0; k < Ndiv2; k += 2) out += (buf[k] + buf[N - k - 1]) * fir[k]; // Outputs bufferSamples[i << 1] = out; bufferSamples[(i << 1) + 1] = buf[Ndiv2 + 1] * fir[Ndiv2]; // Shift data for (size_t k = 0; k < N - 2; k += 2) buf[k] = buf[k + 2]; } } }
void Oversampling<SampleType>::processSamplesDown (dsp::AudioBlock<SampleType>& outputBlock) noexcept { jassert (! stages.isEmpty()); if (! isReady) return; auto currentNumSamples = outputBlock.getNumSamples(); for (int n = 0; n < stages.size() - 1; ++n) currentNumSamples *= stages.getUnchecked(n)->factor; for (int n = stages.size() - 1; n > 0; --n) { auto& stage = *stages.getUnchecked(n); auto audioBlock = stages.getUnchecked (n - 1)->getProcessedSamples (currentNumSamples); stage.processSamplesDown (audioBlock); currentNumSamples /= stage.factor; } stages.getFirst()->processSamplesDown (outputBlock); }