35template <
typename SampleType>
38 OversamplingStage (
size_t numChans,
size_t newFactor) : numChannels (numChans), factor (newFactor) {}
44 virtual void initProcessing (
size_t maximumNumberOfSamplesBeforeOversampling)
46 buffer.setSize (
static_cast<int> (numChannels),
47 static_cast<int> (maximumNumberOfSamplesBeforeOversampling * factor),
65 size_t numChannels, factor;
73template <
typename SampleType>
81 SampleType getLatencyInSamples()
override
88 jassert (inputBlock.
getNumChannels() <=
static_cast<size_t> (ParentType::buffer.getNumChannels()));
89 jassert (inputBlock.
getNumSamples() * ParentType::factor <=
static_cast<size_t> (ParentType::buffer.getNumSamples()));
91 for (
size_t channel = 0; channel < inputBlock.
getNumChannels(); ++channel)
92 ParentType::buffer.copyFrom (
static_cast<int> (channel), 0,
98 jassert (outputBlock.
getNumChannels() <=
static_cast<size_t> (ParentType::buffer.getNumChannels()));
99 jassert (outputBlock.
getNumSamples() * ParentType::factor <=
static_cast<size_t> (ParentType::buffer.getNumSamples()));
113template <
typename SampleType>
119 SampleType normalisedTransitionWidthUp,
120 SampleType stopbandAmplitudedBUp,
121 SampleType normalisedTransitionWidthDown,
122 SampleType stopbandAmplitudedBDown)
123 : ParentType (numChans, 2)
129 stateUp.
setSize (
static_cast<int> (this->numChannels),
static_cast<int> (N));
133 auto Ndiv4 = Ndiv2 / 2;
135 stateDown.
setSize (
static_cast<int> (this->numChannels),
static_cast<int> (N));
136 stateDown2.
setSize (
static_cast<int> (this->numChannels),
static_cast<int> (Ndiv4 + 1));
138 position.
resize (
static_cast<int> (this->numChannels));
142 SampleType getLatencyInSamples()
override
147 void reset()
override
160 jassert (inputBlock.
getNumChannels() <=
static_cast<size_t> (ParentType::buffer.getNumChannels()));
161 jassert (inputBlock.
getNumSamples() * ParentType::factor <=
static_cast<size_t> (ParentType::buffer.getNumSamples()));
170 for (
size_t channel = 0; channel < inputBlock.
getNumChannels(); ++channel)
172 auto bufferSamples = ParentType::buffer.getWritePointer (
static_cast<int> (channel));
176 for (
size_t i = 0; i < numSamples; ++i)
179 buf[N - 1] = 2 * samples[i];
182 auto out =
static_cast<SampleType
> (0.0);
184 for (
size_t k = 0; k < Ndiv2; k += 2)
185 out += (buf[k] + buf[N - k - 1]) * fir[k];
188 bufferSamples[i << 1] = out;
189 bufferSamples[(i << 1) + 1] = buf[Ndiv2 + 1] * fir[Ndiv2];
192 for (
size_t k = 0; k < N - 2; k += 2)
200 jassert (outputBlock.
getNumChannels() <=
static_cast<size_t> (ParentType::buffer.getNumChannels()));
201 jassert (outputBlock.
getNumSamples() * ParentType::factor <=
static_cast<size_t> (ParentType::buffer.getNumSamples()));
207 auto Ndiv4 = Ndiv2 / 2;
211 for (
size_t channel = 0; channel < outputBlock.
getNumChannels(); ++channel)
213 auto bufferSamples = ParentType::buffer.getWritePointer (
static_cast<int> (channel));
217 auto pos = position.
getUnchecked (
static_cast<int> (channel));
219 for (
size_t i = 0; i < numSamples; ++i)
222 buf[N - 1] = bufferSamples[i << 1];
225 auto out =
static_cast<SampleType
> (0.0);
227 for (
size_t k = 0; k < Ndiv2; k += 2)
228 out += (buf[k] + buf[N - k - 1]) * fir[k];
231 out += buf2[pos] * fir[Ndiv2];
232 buf2[pos] = bufferSamples[(i << 1) + 1];
237 for (
size_t k = 0; k < N - 2; ++k)
241 pos = (pos == 0 ? Ndiv4 : pos - 1);
244 position.
setUnchecked (
static_cast<int> (channel), pos);
265template <
typename SampleType>
271 SampleType normalisedTransitionWidthUp,
272 SampleType stopbandAmplitudedBUp,
273 SampleType normalisedTransitionWidthDown,
274 SampleType stopbandAmplitudedBDown)
275 : ParentType (numChans, 2)
278 auto coeffsUp = getCoefficients (structureUp);
282 auto coeffsDown = getCoefficients (structureDown);
285 for (
auto i = 0; i < structureUp.directPath.size(); ++i)
286 coefficientsUp.
add (structureUp.directPath.getObjectPointer (i)->coefficients[0]);
288 for (
auto i = 1; i < structureUp.delayedPath.size(); ++i)
289 coefficientsUp.
add (structureUp.delayedPath.getObjectPointer (i)->coefficients[0]);
291 for (
auto i = 0; i < structureDown.directPath.size(); ++i)
292 coefficientsDown.
add (structureDown.directPath.getObjectPointer (i)->coefficients[0]);
294 for (
auto i = 1; i < structureDown.delayedPath.size(); ++i)
295 coefficientsDown.
add (structureDown.delayedPath.getObjectPointer (i)->coefficients[0]);
297 v1Up.
setSize (
static_cast<int> (this->numChannels), coefficientsUp.
size());
298 v1Down.
setSize (
static_cast<int> (this->numChannels), coefficientsDown.
size());
299 delayDown.
resize (
static_cast<int> (this->numChannels));
303 SampleType getLatencyInSamples()
override
308 void reset()
override
318 jassert (inputBlock.
getNumChannels() <=
static_cast<size_t> (ParentType::buffer.getNumChannels()));
319 jassert (inputBlock.
getNumSamples() * ParentType::factor <=
static_cast<size_t> (ParentType::buffer.getNumSamples()));
323 auto numStages = coefficientsUp.
size();
324 auto delayedStages = numStages / 2;
325 auto directStages = numStages - delayedStages;
329 for (
size_t channel = 0; channel < inputBlock.
getNumChannels(); ++channel)
331 auto bufferSamples = ParentType::buffer.getWritePointer (
static_cast<int> (channel));
335 for (
size_t i = 0; i < numSamples; ++i)
338 auto input = samples[i];
340 for (
auto n = 0; n < directStages; ++n)
342 auto alpha = coeffs[n];
343 auto output = alpha * input + lv1[n];
344 lv1[n] = input - alpha * output;
349 bufferSamples[i << 1] = input;
354 for (
auto n = directStages; n < numStages; ++n)
356 auto alpha = coeffs[n];
357 auto output = alpha * input + lv1[n];
358 lv1[n] = input - alpha * output;
363 bufferSamples[(i << 1) + 1] = input;
373 jassert (outputBlock.
getNumChannels() <=
static_cast<size_t> (ParentType::buffer.getNumChannels()));
374 jassert (outputBlock.
getNumSamples() * ParentType::factor <=
static_cast<size_t> (ParentType::buffer.getNumSamples()));
378 auto numStages = coefficientsDown.
size();
379 auto delayedStages = numStages / 2;
380 auto directStages = numStages - delayedStages;
384 for (
size_t channel = 0; channel < outputBlock.
getNumChannels(); ++channel)
386 auto bufferSamples = ParentType::buffer.getWritePointer (
static_cast<int> (channel));
389 auto delay = delayDown.
getUnchecked (
static_cast<int> (channel));
391 for (
size_t i = 0; i < numSamples; ++i)
394 auto input = bufferSamples[i << 1];
396 for (
auto n = 0; n < directStages; ++n)
398 auto alpha = coeffs[n];
399 auto output = alpha * input + lv1[n];
400 lv1[n] = input - alpha * output;
404 auto directOut = input;
407 input = bufferSamples[(i << 1) + 1];
409 for (
auto n = directStages; n < numStages; ++n)
411 auto alpha = coeffs[n];
412 auto output = alpha * input + lv1[n];
413 lv1[n] = input - alpha * output;
418 samples[i] = (delay + directOut) *
static_cast<SampleType
> (0.5);
422 delayDown.
setUnchecked (
static_cast<int> (channel), delay);
429 void snapToZero (
bool snapUpProcessing)
431 if (snapUpProcessing)
433 for (
auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
436 auto numStages = coefficientsUp.
size();
438 for (
auto n = 0; n < numStages; ++n)
439 util::snapToZero (lv1[n]);
444 for (
auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
447 auto numStages = coefficientsDown.
size();
449 for (
auto n = 0; n < numStages; ++n)
450 util::snapToZero (lv1[n]);
462 constexpr auto one =
static_cast<SampleType
> (1.0);
465 numerator2 ({ one }), denominator2 ({ one });
467 for (
auto* i : structure.directPath)
469 auto coeffs = i->getRawCoefficients();
471 if (i->getFilterOrder() == 1)
483 for (
auto* i : structure.delayedPath)
485 auto coeffs = i->getRawCoefficients();
487 if (i->getFilterOrder() == 1)
499 auto numeratorf1 = numerator1.getProductWith (denominator2);
500 auto numeratorf2 = numerator2.getProductWith (denominator1);
501 auto numerator = numeratorf1.getSumWith (numeratorf2);
502 auto denominator = denominator1.getProductWith (denominator2);
507 auto inversion = one / denominator[0];
509 for (
auto i = 0; i <= numerator.getOrder(); ++i)
512 for (
auto i = 1; i <= denominator.getOrder(); ++i)
531template <
typename SampleType>
533 : numChannels (newNumChannels)
535 jassert (numChannels > 0);
540template <
typename SampleType>
543 : numChannels (newNumChannels)
545 jassert (isPositiveAndBelow (newFactor, 5) && numChannels > 0);
551 else if (newType == FilterType::filterHalfBandPolyphaseIIR)
553 for (
size_t n = 0; n < newFactor; ++n)
555 auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f);
556 auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f);
558 auto gaindBStartUp = (isMaximumQuality ? -90.0f : -70.0f);
559 auto gaindBStartDown = (isMaximumQuality ? -75.0f : -60.0f);
560 auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f);
561 auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f);
564 twUp, gaindBStartUp + gaindBFactorUp * n,
565 twDown, gaindBStartDown + gaindBFactorDown * n);
568 else if (newType == FilterType::filterHalfBandFIREquiripple)
570 for (
size_t n = 0; n < newFactor; ++n)
572 auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f);
573 auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f);
575 auto gaindBStartUp = (isMaximumQuality ? -90.0f : -70.0f);
576 auto gaindBStartDown = (isMaximumQuality ? -75.0f : -60.0f);
577 auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f);
578 auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f);
581 twUp, gaindBStartUp + gaindBFactorUp * n,
582 twDown, gaindBStartDown + gaindBFactorDown * n);
587template <
typename SampleType>
594template <
typename SampleType>
600template <
typename SampleType>
602 float normalisedTransitionWidthUp,
603 float stopbandAmplitudedBUp,
604 float normalisedTransitionWidthDown,
605 float stopbandAmplitudedBDown)
607 if (type == FilterType::filterHalfBandPolyphaseIIR)
610 normalisedTransitionWidthUp, stopbandAmplitudedBUp,
611 normalisedTransitionWidthDown, stopbandAmplitudedBDown));
616 normalisedTransitionWidthUp, stopbandAmplitudedBUp,
617 normalisedTransitionWidthDown, stopbandAmplitudedBDown));
620 factorOversampling *= 2;
623template <
typename SampleType>
627 factorOversampling = 1u;
631template <
typename SampleType>
634 auto latency =
static_cast<SampleType
> (0);
637 for (
auto* stage : stages)
639 order *= stage->factor;
640 latency += stage->getLatencyInSamples() /
static_cast<SampleType
> (order);
646template <
typename SampleType>
649 return factorOversampling;
653template <
typename SampleType>
656 jassert (! stages.isEmpty());
657 auto currentNumSamples = maximumNumberOfSamplesBeforeOversampling;
659 for (
auto* stage : stages)
661 stage->initProcessing (currentNumSamples);
662 currentNumSamples *= stage->factor;
669template <
typename SampleType>
672 jassert (! stages.isEmpty());
675 for (
auto* stage : stages)
679template <
typename SampleType>
682 jassert (! stages.isEmpty());
687 auto* firstStage = stages.getUnchecked (0);
688 firstStage->processSamplesUp (inputBlock);
689 auto block = firstStage->getProcessedSamples (inputBlock.getNumSamples() * firstStage->factor);
691 for (
int i = 1; i < stages.size(); ++i)
693 stages[i]->processSamplesUp (block);
694 block = stages[i]->getProcessedSamples (block.getNumSamples() * stages[i]->factor);
700template <
typename SampleType>
703 jassert (! stages.isEmpty());
708 auto currentNumSamples = outputBlock.getNumSamples();
710 for (
int n = 0; n < stages.size() - 1; ++n)
711 currentNumSamples *= stages.getUnchecked(n)->factor;
713 for (
int n = stages.size() - 1; n > 0; --n)
715 auto& stage = *stages.getUnchecked(n);
716 auto audioBlock = stages.getUnchecked (n - 1)->getProcessedSamples (currentNumSamples);
717 stage.processSamplesDown (audioBlock);
719 currentNumSamples /= stage.factor;
722 stages.getFirst()->processSamplesDown (outputBlock);
void setUnchecked(int indexToChange, ParameterType newValue)
Replaces an element with a new value without doing any bounds-checking.
ElementType getUnchecked(int index) const
Returns one of the elements in the array, without checking the index passed in.
int size() const noexcept
Returns the current number of elements in the array.
void fill(const ParameterType &newValue) noexcept
Fills the Array with the provided value.
ElementType * getRawDataPointer() noexcept
Returns a pointer to the actual array data.
void add(const ElementType &newElement)
Appends a new element at the end of the array.
void resize(int targetNumItems)
This will enlarge or shrink the array to the given number of elements, by adding or removing items fr...
void clear()
Removes all elements from the array.
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Changes the buffer's size or number of channels.
Type * getWritePointer(int channelNumber) noexcept
Returns a writeable pointer to one of the buffer's channels.
void clear() noexcept
Clears all the samples in all channels.
Minimal and lightweight data-structure which contains a list of pointers to channels containing some ...
AudioBlock getSubBlock(size_t newOffset, size_t newLength) const noexcept
Return a new AudioBlock pointing to a sub-block inside this block.
constexpr size_t getNumChannels() const noexcept
Returns the number of channels referenced by this block.
SampleType * getChannelPointer(size_t channel) const noexcept
Returns a raw pointer into one of the channels in this block.
AudioBlock & copyFrom(const AudioBlock< OtherSampleType > &src) noexcept
Copies the values in src to this block.
constexpr size_t getNumSamples() const noexcept
Returns the number of samples referenced by this block.
A processing class performing multi-channel oversampling.
void processSamplesDown(AudioBlock< SampleType > &outputBlock) noexcept
Must be called to perform the downsampling, after the upsampling and the non-linear processing.
FilterType
The type of filter that can be used for the oversampling processing.
void clearOversamplingStages()
Removes all the previously registered oversampling stages, so you can add your own from scratch.
void initProcessing(size_t maximumNumberOfSamplesBeforeOversampling)
Must be called before any processing, to set the buffer sizes of the internal buffers of the oversamp...
Oversampling(size_t numChannels, size_t factor, FilterType type, bool isMaxQuality=true)
Constructor of the oversampling class.
SampleType getLatencyInSamples() noexcept
Returns the latency in samples of the whole processing.
AudioBlock< SampleType > processSamplesUp(const AudioBlock< const SampleType > &inputBlock) noexcept
Must be called to perform the upsampling, prior to any oversampled processing.
size_t getOversamplingFactor() noexcept
Returns the current oversampling factor.
void reset() noexcept
Resets the processing pipeline, ready to oversample a new stream of data.
void addDummyOversamplingStage()
Adds a new "dummy" oversampling stage, which does nothing to the signal.
~Oversampling()
Destructor.
void addOversamplingStage(FilterType, float normalisedTransitionWidthUp, float stopbandAmplitudedBUp, float normalisedTransitionWidthDown, float stopbandAmplitudedBDown)
Adds a new oversampling stage to the Oversampling class, multiplying the current oversampling factor ...
A class representing a polynomial.
Polynomial< FloatingType > getProductWith(const Polynomial< FloatingType > &other) const
computes the product of two polynomials and return the result
The structure returned by the function designIIRLowpassHalfBandPolyphaseAllpassMethod.
Commonly used mathematical constants.
size_t getFilterOrder() const noexcept
Returns the filter order associated with the coefficients.
NumericType * getRawCoefficients() noexcept
Returns a raw data pointer to the coefficients.
static IIRPolyphaseAllpassStructure designIIRLowpassHalfBandPolyphaseAllpassMethod(FloatType normalisedTransitionWidth, FloatType stopbandAmplitudedB)
This method generates arrays of IIR::Coefficients for a low-pass filter, with a cutoff frequency at h...
static FIRCoefficientsPtr designFIRLowpassHalfBandEquirippleMethod(FloatType normalisedTransitionWidth, FloatType amplitudedB)
This method generates a FIR::Coefficients for a low-pass filter, with a cutoff frequency at half band...
A set of coefficients for use in an Filter object.
Array< NumericType > coefficients
The raw coefficients.
Oversampling stage class performing 2 times oversampling using the Filter Design FIR Equiripple metho...
Oversampling stage class performing 2 times oversampling using the Filter Design IIR Polyphase Allpas...
Dummy oversampling stage class which simply copies and pastes the input signal, which could be equiva...
Abstract class for the provided oversampling stages used internally in the Oversampling class.