OpenShot Audio Library | OpenShotAudio: juce_Oversampling.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.0

Loading...
Searching...
No Matches
juce_Oversampling.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12 27th April 2017).
13
14 End User License Agreement: www.juce.com/juce-5-licence
15 Privacy Policy: www.juce.com/juce-5-privacy-policy
16
17 Or: You may also use this code under the terms of the GPL v3 (see
18 www.gnu.org/licenses).
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29namespace dsp
30{
31
35template <typename SampleType>
36 struct Oversampling<SampleType>::OversamplingStage
37{
38 OversamplingStage (size_t numChans, size_t newFactor) : numChannels (numChans), factor (newFactor) {}
39 virtual ~OversamplingStage() {}
40
41 //==============================================================================
42 virtual SampleType getLatencyInSamples() = 0;
43
44 virtual void initProcessing (size_t maximumNumberOfSamplesBeforeOversampling)
45 {
46 buffer.setSize (static_cast<int> (numChannels),
47 static_cast<int> (maximumNumberOfSamplesBeforeOversampling * factor),
48 false, false, true);
49 }
50
51 virtual void reset()
52 {
53 buffer.clear();
54 }
55
56 AudioBlock<SampleType> getProcessedSamples (size_t numSamples)
57 {
58 return AudioBlock<SampleType> (buffer).getSubBlock (0, numSamples);
59 }
60
61 virtual void processSamplesUp (const AudioBlock<const SampleType>&) = 0;
62 virtual void processSamplesDown (AudioBlock<SampleType>&) = 0;
63
64 AudioBuffer<SampleType> buffer;
65 size_t numChannels, factor;
66};
67
68
69//==============================================================================
73template <typename SampleType>
74 struct OversamplingDummy : public Oversampling<SampleType>::OversamplingStage
75{
76 using ParentType = typename Oversampling<SampleType>::OversamplingStage;
77
78 OversamplingDummy (size_t numChans) : ParentType (numChans, 1) {}
79
80 //==============================================================================
81 SampleType getLatencyInSamples() override
82 {
83 return 0;
84 }
85
86 void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override
87 {
88 jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
89 jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
90
91 for (size_t channel = 0; channel < inputBlock.getNumChannels(); ++channel)
92 ParentType::buffer.copyFrom (static_cast<int> (channel), 0,
93 inputBlock.getChannelPointer (channel), static_cast<int> (inputBlock.getNumSamples()));
94 }
95
96 void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
97 {
98 jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
99 jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
100
101 outputBlock.copyFrom (ParentType::getProcessedSamples (outputBlock.getNumSamples()));
102 }
103
104 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OversamplingDummy)
105};
106
107//==============================================================================
113template <typename SampleType>
114 struct Oversampling2TimesEquirippleFIR : public Oversampling<SampleType>::OversamplingStage
115{
116 using ParentType = typename Oversampling<SampleType>::OversamplingStage;
117
118 Oversampling2TimesEquirippleFIR (size_t numChans,
119 SampleType normalisedTransitionWidthUp,
120 SampleType stopbandAmplitudedBUp,
121 SampleType normalisedTransitionWidthDown,
122 SampleType stopbandAmplitudedBDown)
123 : ParentType (numChans, 2)
124 {
125 coefficientsUp = *FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthUp, stopbandAmplitudedBUp);
126 coefficientsDown = *FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);
127
128 auto N = coefficientsUp.getFilterOrder() + 1;
129 stateUp.setSize (static_cast<int> (this->numChannels), static_cast<int> (N));
130
131 N = coefficientsDown.getFilterOrder() + 1;
132 auto Ndiv2 = N / 2;
133 auto Ndiv4 = Ndiv2 / 2;
134
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));
137
138 position.resize (static_cast<int> (this->numChannels));
139 }
140
141 //==============================================================================
142 SampleType getLatencyInSamples() override
143 {
144 return static_cast<SampleType> (coefficientsUp.getFilterOrder() + coefficientsDown.getFilterOrder()) * 0.5f;
145 }
146
147 void reset() override
148 {
149 ParentType::reset();
150
151 stateUp.clear();
152 stateDown.clear();
153 stateDown2.clear();
154
155 position.fill (0);
156 }
157
158 void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override
159 {
160 jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
161 jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
162
163 // Initialization
164 auto fir = coefficientsUp.getRawCoefficients();
165 auto N = coefficientsUp.getFilterOrder() + 1;
166 auto Ndiv2 = N / 2;
167 auto numSamples = inputBlock.getNumSamples();
168
169 // Processing
170 for (size_t channel = 0; channel < inputBlock.getNumChannels(); ++channel)
171 {
172 auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
173 auto buf = stateUp.getWritePointer (static_cast<int> (channel));
174 auto samples = inputBlock.getChannelPointer (channel);
175
176 for (size_t i = 0; i < numSamples; ++i)
177 {
178 // Input
179 buf[N - 1] = 2 * samples[i];
180
181 // Convolution
182 auto out = static_cast<SampleType> (0.0);
183
184 for (size_t k = 0; k < Ndiv2; k += 2)
185 out += (buf[k] + buf[N - k - 1]) * fir[k];
186
187 // Outputs
188 bufferSamples[i << 1] = out;
189 bufferSamples[(i << 1) + 1] = buf[Ndiv2 + 1] * fir[Ndiv2];
190
191 // Shift data
192 for (size_t k = 0; k < N - 2; k += 2)
193 buf[k] = buf[k + 2];
194 }
195 }
196 }
197
198 void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
199 {
200 jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
201 jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
202
203 // Initialization
204 auto fir = coefficientsDown.getRawCoefficients();
205 auto N = coefficientsDown.getFilterOrder() + 1;
206 auto Ndiv2 = N / 2;
207 auto Ndiv4 = Ndiv2 / 2;
208 auto numSamples = outputBlock.getNumSamples();
209
210 // Processing
211 for (size_t channel = 0; channel < outputBlock.getNumChannels(); ++channel)
212 {
213 auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
214 auto buf = stateDown.getWritePointer (static_cast<int> (channel));
215 auto buf2 = stateDown2.getWritePointer (static_cast<int> (channel));
216 auto samples = outputBlock.getChannelPointer (channel);
217 auto pos = position.getUnchecked (static_cast<int> (channel));
218
219 for (size_t i = 0; i < numSamples; ++i)
220 {
221 // Input
222 buf[N - 1] = bufferSamples[i << 1];
223
224 // Convolution
225 auto out = static_cast<SampleType> (0.0);
226
227 for (size_t k = 0; k < Ndiv2; k += 2)
228 out += (buf[k] + buf[N - k - 1]) * fir[k];
229
230 // Output
231 out += buf2[pos] * fir[Ndiv2];
232 buf2[pos] = bufferSamples[(i << 1) + 1];
233
234 samples[i] = out;
235
236 // Shift data
237 for (size_t k = 0; k < N - 2; ++k)
238 buf[k] = buf[k + 2];
239
240 // Circular buffer
241 pos = (pos == 0 ? Ndiv4 : pos - 1);
242 }
243
244 position.setUnchecked (static_cast<int> (channel), pos);
245 }
246
247 }
248
249private:
250 //==============================================================================
251 FIR::Coefficients<SampleType> coefficientsUp, coefficientsDown;
252 AudioBuffer<SampleType> stateUp, stateDown, stateDown2;
253 Array<size_t> position;
254
255 //==============================================================================
256 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oversampling2TimesEquirippleFIR)
257};
258
259
260//==============================================================================
265template <typename SampleType>
266 struct Oversampling2TimesPolyphaseIIR : public Oversampling<SampleType>::OversamplingStage
267{
268 using ParentType = typename Oversampling<SampleType>::OversamplingStage;
269
270 Oversampling2TimesPolyphaseIIR (size_t numChans,
271 SampleType normalisedTransitionWidthUp,
272 SampleType stopbandAmplitudedBUp,
273 SampleType normalisedTransitionWidthDown,
274 SampleType stopbandAmplitudedBDown)
275 : ParentType (numChans, 2)
276 {
277 auto structureUp = FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthUp, stopbandAmplitudedBUp);
278 auto coeffsUp = getCoefficients (structureUp);
279 latency = static_cast<SampleType> (-(coeffsUp.getPhaseForFrequency (0.0001, 1.0)) / (0.0001 * MathConstants<double>::twoPi));
280
281 auto structureDown = FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);
282 auto coeffsDown = getCoefficients (structureDown);
283 latency += static_cast<SampleType> (-(coeffsDown.getPhaseForFrequency (0.0001, 1.0)) / (0.0001 * MathConstants<double>::twoPi));
284
285 for (auto i = 0; i < structureUp.directPath.size(); ++i)
286 coefficientsUp.add (structureUp.directPath.getObjectPointer (i)->coefficients[0]);
287
288 for (auto i = 1; i < structureUp.delayedPath.size(); ++i)
289 coefficientsUp.add (structureUp.delayedPath.getObjectPointer (i)->coefficients[0]);
290
291 for (auto i = 0; i < structureDown.directPath.size(); ++i)
292 coefficientsDown.add (structureDown.directPath.getObjectPointer (i)->coefficients[0]);
293
294 for (auto i = 1; i < structureDown.delayedPath.size(); ++i)
295 coefficientsDown.add (structureDown.delayedPath.getObjectPointer (i)->coefficients[0]);
296
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));
300 }
301
302 //==============================================================================
303 SampleType getLatencyInSamples() override
304 {
305 return latency;
306 }
307
308 void reset() override
309 {
310 ParentType::reset();
311 v1Up.clear();
312 v1Down.clear();
313 delayDown.fill (0);
314 }
315
316 void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override
317 {
318 jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
319 jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
320
321 // Initialization
322 auto coeffs = coefficientsUp.getRawDataPointer();
323 auto numStages = coefficientsUp.size();
324 auto delayedStages = numStages / 2;
325 auto directStages = numStages - delayedStages;
326 auto numSamples = inputBlock.getNumSamples();
327
328 // Processing
329 for (size_t channel = 0; channel < inputBlock.getNumChannels(); ++channel)
330 {
331 auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
332 auto lv1 = v1Up.getWritePointer (static_cast<int> (channel));
333 auto samples = inputBlock.getChannelPointer (channel);
334
335 for (size_t i = 0; i < numSamples; ++i)
336 {
337 // Direct path cascaded allpass filters
338 auto input = samples[i];
339
340 for (auto n = 0; n < directStages; ++n)
341 {
342 auto alpha = coeffs[n];
343 auto output = alpha * input + lv1[n];
344 lv1[n] = input - alpha * output;
345 input = output;
346 }
347
348 // Output
349 bufferSamples[i << 1] = input;
350
351 // Delayed path cascaded allpass filters
352 input = samples[i];
353
354 for (auto n = directStages; n < numStages; ++n)
355 {
356 auto alpha = coeffs[n];
357 auto output = alpha * input + lv1[n];
358 lv1[n] = input - alpha * output;
359 input = output;
360 }
361
362 // Output
363 bufferSamples[(i << 1) + 1] = input;
364 }
365 }
366
367 // Snap To Zero
368 snapToZero (true);
369 }
370
371 void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
372 {
373 jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
374 jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
375
376 // Initialization
377 auto coeffs = coefficientsDown.getRawDataPointer();
378 auto numStages = coefficientsDown.size();
379 auto delayedStages = numStages / 2;
380 auto directStages = numStages - delayedStages;
381 auto numSamples = outputBlock.getNumSamples();
382
383 // Processing
384 for (size_t channel = 0; channel < outputBlock.getNumChannels(); ++channel)
385 {
386 auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
387 auto lv1 = v1Down.getWritePointer (static_cast<int> (channel));
388 auto samples = outputBlock.getChannelPointer (channel);
389 auto delay = delayDown.getUnchecked (static_cast<int> (channel));
390
391 for (size_t i = 0; i < numSamples; ++i)
392 {
393 // Direct path cascaded allpass filters
394 auto input = bufferSamples[i << 1];
395
396 for (auto n = 0; n < directStages; ++n)
397 {
398 auto alpha = coeffs[n];
399 auto output = alpha * input + lv1[n];
400 lv1[n] = input - alpha * output;
401 input = output;
402 }
403
404 auto directOut = input;
405
406 // Delayed path cascaded allpass filters
407 input = bufferSamples[(i << 1) + 1];
408
409 for (auto n = directStages; n < numStages; ++n)
410 {
411 auto alpha = coeffs[n];
412 auto output = alpha * input + lv1[n];
413 lv1[n] = input - alpha * output;
414 input = output;
415 }
416
417 // Output
418 samples[i] = (delay + directOut) * static_cast<SampleType> (0.5);
419 delay = input;
420 }
421
422 delayDown.setUnchecked (static_cast<int> (channel), delay);
423 }
424
425 // Snap To Zero
426 snapToZero (false);
427 }
428
429 void snapToZero (bool snapUpProcessing)
430 {
431 if (snapUpProcessing)
432 {
433 for (auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
434 {
435 auto lv1 = v1Up.getWritePointer (channel);
436 auto numStages = coefficientsUp.size();
437
438 for (auto n = 0; n < numStages; ++n)
439 util::snapToZero (lv1[n]);
440 }
441 }
442 else
443 {
444 for (auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
445 {
446 auto lv1 = v1Down.getWritePointer (channel);
447 auto numStages = coefficientsDown.size();
448
449 for (auto n = 0; n < numStages; ++n)
450 util::snapToZero (lv1[n]);
451 }
452 }
453 }
454
455private:
456 //==============================================================================
460 IIR::Coefficients<SampleType> getCoefficients (typename FilterDesign<SampleType>::IIRPolyphaseAllpassStructure& structure) const
461 {
462 constexpr auto one = static_cast<SampleType> (1.0);
463
464 Polynomial<SampleType> numerator1 ({ one }), denominator1 ({ one }),
465 numerator2 ({ one }), denominator2 ({ one });
466
467 for (auto* i : structure.directPath)
468 {
469 auto coeffs = i->getRawCoefficients();
470
471 if (i->getFilterOrder() == 1)
472 {
473 numerator1 = numerator1 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));
474 denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one, coeffs[2] }));
475 }
476 else
477 {
478 numerator1 = numerator1 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));
479 denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));
480 }
481 }
482
483 for (auto* i : structure.delayedPath)
484 {
485 auto coeffs = i->getRawCoefficients();
486
487 if (i->getFilterOrder() == 1)
488 {
489 numerator2 = numerator2 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));
490 denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one, coeffs[2] }));
491 }
492 else
493 {
494 numerator2 = numerator2 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));
495 denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));
496 }
497 }
498
499 auto numeratorf1 = numerator1.getProductWith (denominator2);
500 auto numeratorf2 = numerator2.getProductWith (denominator1);
501 auto numerator = numeratorf1.getSumWith (numeratorf2);
502 auto denominator = denominator1.getProductWith (denominator2);
503
504 IIR::Coefficients<SampleType> coeffs;
505
506 coeffs.coefficients.clear();
507 auto inversion = one / denominator[0];
508
509 for (auto i = 0; i <= numerator.getOrder(); ++i)
510 coeffs.coefficients.add (numerator[i] * inversion);
511
512 for (auto i = 1; i <= denominator.getOrder(); ++i)
513 coeffs.coefficients.add (denominator[i] * inversion);
514
515 return coeffs;
516 }
517
518 //==============================================================================
519 Array<SampleType> coefficientsUp, coefficientsDown;
520 SampleType latency;
521
522 AudioBuffer<SampleType> v1Up, v1Down;
523 Array<SampleType> delayDown;
524
525 //==============================================================================
526 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oversampling2TimesPolyphaseIIR)
527};
528
529
530//==============================================================================
531template <typename SampleType>
532 Oversampling<SampleType>::Oversampling (size_t newNumChannels)
533 : numChannels (newNumChannels)
534{
535 jassert (numChannels > 0);
536
537 addDummyOversamplingStage();
538}
539
540template <typename SampleType>
541Oversampling<SampleType>::Oversampling (size_t newNumChannels, size_t newFactor,
542 FilterType newType, bool isMaximumQuality)
543 : numChannels (newNumChannels)
544{
545 jassert (isPositiveAndBelow (newFactor, 5) && numChannels > 0);
546
547 if (newFactor == 0)
548 {
549 addDummyOversamplingStage();
550 }
551 else if (newType == FilterType::filterHalfBandPolyphaseIIR)
552 {
553 for (size_t n = 0; n < newFactor; ++n)
554 {
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);
557
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);
562
563 addOversamplingStage (FilterType::filterHalfBandPolyphaseIIR,
564 twUp, gaindBStartUp + gaindBFactorUp * n,
565 twDown, gaindBStartDown + gaindBFactorDown * n);
566 }
567 }
568 else if (newType == FilterType::filterHalfBandFIREquiripple)
569 {
570 for (size_t n = 0; n < newFactor; ++n)
571 {
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);
574
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);
579
580 addOversamplingStage (FilterType::filterHalfBandFIREquiripple,
581 twUp, gaindBStartUp + gaindBFactorUp * n,
582 twDown, gaindBStartDown + gaindBFactorDown * n);
583 }
584 }
585}
586
587template <typename SampleType>
588Oversampling<SampleType>::~Oversampling()
589{
590 stages.clear();
591}
592
593//==============================================================================
594template <typename SampleType>
595 void Oversampling<SampleType>::addDummyOversamplingStage()
596{
597 stages.add (new OversamplingDummy<SampleType> (numChannels));
598}
599
600template <typename SampleType>
601 void Oversampling<SampleType>::addOversamplingStage (FilterType type,
602 float normalisedTransitionWidthUp,
603 float stopbandAmplitudedBUp,
604 float normalisedTransitionWidthDown,
605 float stopbandAmplitudedBDown)
606{
607 if (type == FilterType::filterHalfBandPolyphaseIIR)
608 {
609 stages.add (new Oversampling2TimesPolyphaseIIR<SampleType> (numChannels,
610 normalisedTransitionWidthUp, stopbandAmplitudedBUp,
611 normalisedTransitionWidthDown, stopbandAmplitudedBDown));
612 }
613 else
614 {
615 stages.add (new Oversampling2TimesEquirippleFIR<SampleType> (numChannels,
616 normalisedTransitionWidthUp, stopbandAmplitudedBUp,
617 normalisedTransitionWidthDown, stopbandAmplitudedBDown));
618 }
619
620 factorOversampling *= 2;
621}
622
623template <typename SampleType>
624 void Oversampling<SampleType>::clearOversamplingStages()
625{
626 stages.clear();
627 factorOversampling = 1u;
628}
629
630//==============================================================================
631template <typename SampleType>
632SampleType Oversampling<SampleType>::getLatencyInSamples() noexcept
633{
634 auto latency = static_cast<SampleType> (0);
635 size_t order = 1;
636
637 for (auto* stage : stages)
638 {
639 order *= stage->factor;
640 latency += stage->getLatencyInSamples() / static_cast<SampleType> (order);
641 }
642
643 return latency;
644}
645
646template <typename SampleType>
647 size_t Oversampling<SampleType>::getOversamplingFactor() noexcept
648{
649 return factorOversampling;
650}
651
652//==============================================================================
653template <typename SampleType>
654 void Oversampling<SampleType>::initProcessing (size_t maximumNumberOfSamplesBeforeOversampling)
655{
656 jassert (! stages.isEmpty());
657 auto currentNumSamples = maximumNumberOfSamplesBeforeOversampling;
658
659 for (auto* stage : stages)
660 {
661 stage->initProcessing (currentNumSamples);
662 currentNumSamples *= stage->factor;
663 }
664
665 isReady = true;
666 reset();
667}
668
669template <typename SampleType>
670 void Oversampling<SampleType>::reset() noexcept
671{
672 jassert (! stages.isEmpty());
673
674 if (isReady)
675 for (auto* stage : stages)
676 stage->reset();
677}
678
679template <typename SampleType>
680 AudioBlock<SampleType> Oversampling<SampleType>::processSamplesUp (const AudioBlock<const SampleType>& inputBlock) noexcept
681{
682 jassert (! stages.isEmpty());
683
684 if (! isReady)
685 return {};
686
687 auto* firstStage = stages.getUnchecked (0);
688 firstStage->processSamplesUp (inputBlock);
689 auto block = firstStage->getProcessedSamples (inputBlock.getNumSamples() * firstStage->factor);
690
691 for (int i = 1; i < stages.size(); ++i)
692 {
693 stages[i]->processSamplesUp (block);
694 block = stages[i]->getProcessedSamples (block.getNumSamples() * stages[i]->factor);
695 }
696
697 return block;
698}
699
700template <typename SampleType>
701 void Oversampling<SampleType>::processSamplesDown (AudioBlock<SampleType>& outputBlock) noexcept
702{
703 jassert (! stages.isEmpty());
704
705 if (! isReady)
706 return;
707
708 auto currentNumSamples = outputBlock.getNumSamples();
709
710 for (int n = 0; n < stages.size() - 1; ++n)
711 currentNumSamples *= stages.getUnchecked(n)->factor;
712
713 for (int n = stages.size() - 1; n > 0; --n)
714 {
715 auto& stage = *stages.getUnchecked(n);
716 auto audioBlock = stages.getUnchecked (n - 1)->getProcessedSamples (currentNumSamples);
717 stage.processSamplesDown (audioBlock);
718
719 currentNumSamples /= stage.factor;
720 }
721
722 stages.getFirst()->processSamplesDown (outputBlock);
723}
724
725template class Oversampling<float>;
726template class Oversampling<double>;
727
728} // namespace dsp
729} // namespace juce
juce::Array
Definition: juce_Array.h:56
juce::Array::setUnchecked
void setUnchecked(int indexToChange, ParameterType newValue)
Definition: juce_Array.h:568
juce::Array::getUnchecked
ElementType getUnchecked(int index) const
Definition: juce_Array.h:252
juce::Array::size
int size() const noexcept
Definition: juce_Array.h:215
juce::Array::fill
void fill(const ParameterType &newValue) noexcept
Definition: juce_Array.h:205
juce::Array::getRawDataPointer
ElementType * getRawDataPointer() noexcept
Definition: juce_Array.h:310
juce::Array::add
void add(const ElementType &newElement)
Definition: juce_Array.h:418
juce::Array::resize
void resize(int targetNumItems)
Definition: juce_Array.h:670
juce::Array::clear
void clear()
Definition: juce_Array.h:188
juce::AudioBuffer
Definition: juce_AudioSampleBuffer.h:34
juce::AudioBuffer::setSize
void setSize(int newNumChannels, int newNumSamples, bool keepExistingContent=false, bool clearExtraSpace=false, bool avoidReallocating=false)
Definition: juce_AudioSampleBuffer.h:331
juce::AudioBuffer::getWritePointer
Type * getWritePointer(int channelNumber) noexcept
Definition: juce_AudioSampleBuffer.h:273
juce::AudioBuffer::clear
void clear() noexcept
Definition: juce_AudioSampleBuffer.h:506
juce::dsp::AudioBlock
Definition: juce_AudioBlock.h:65
juce::dsp::AudioBlock::getSubBlock
AudioBlock getSubBlock(size_t newOffset, size_t newLength) const noexcept
Definition: juce_AudioBlock.h:354
juce::dsp::AudioBlock::getNumChannels
constexpr size_t getNumChannels() const noexcept
Definition: juce_AudioBlock.h:217
juce::dsp::AudioBlock::getChannelPointer
SampleType * getChannelPointer(size_t channel) const noexcept
Definition: juce_AudioBlock.h:223
juce::dsp::AudioBlock::copyFrom
AudioBlock & copyFrom(const AudioBlock< OtherSampleType > &src) noexcept
Definition: juce_AudioBlock.h:296
juce::dsp::AudioBlock::getNumSamples
constexpr size_t getNumSamples() const noexcept
Definition: juce_AudioBlock.h:220
juce::dsp::Oversampling
Definition: juce_Oversampling.h:58
juce::dsp::Oversampling::processSamplesDown
void processSamplesDown(AudioBlock< SampleType > &outputBlock) noexcept
Definition: juce_Oversampling.cpp:701
juce::dsp::Oversampling::FilterType
FilterType
Definition: juce_Oversampling.h:62
juce::dsp::Oversampling::clearOversamplingStages
void clearOversamplingStages()
Definition: juce_Oversampling.cpp:624
juce::dsp::Oversampling::initProcessing
void initProcessing(size_t maximumNumberOfSamplesBeforeOversampling)
Definition: juce_Oversampling.cpp:654
juce::dsp::Oversampling::Oversampling
Oversampling(size_t numChannels, size_t factor, FilterType type, bool isMaxQuality=true)
Definition: juce_Oversampling.cpp:541
juce::dsp::Oversampling::getLatencyInSamples
SampleType getLatencyInSamples() noexcept
Definition: juce_Oversampling.cpp:632
juce::dsp::Oversampling::processSamplesUp
AudioBlock< SampleType > processSamplesUp(const AudioBlock< const SampleType > &inputBlock) noexcept
Definition: juce_Oversampling.cpp:680
juce::dsp::Oversampling::getOversamplingFactor
size_t getOversamplingFactor() noexcept
Definition: juce_Oversampling.cpp:647
juce::dsp::Oversampling::reset
void reset() noexcept
Definition: juce_Oversampling.cpp:670
juce::dsp::Oversampling::addDummyOversamplingStage
void addDummyOversamplingStage()
Definition: juce_Oversampling.cpp:595
juce::dsp::Oversampling::~Oversampling
~Oversampling()
Definition: juce_Oversampling.cpp:588
juce::dsp::Oversampling::addOversamplingStage
void addOversamplingStage(FilterType, float normalisedTransitionWidthUp, float stopbandAmplitudedBUp, float normalisedTransitionWidthDown, float stopbandAmplitudedBDown)
Definition: juce_Oversampling.cpp:601
juce::dsp::Polynomial
Definition: juce_Polynomial.h:39
juce::dsp::Polynomial::getProductWith
Polynomial< FloatingType > getProductWith(const Polynomial< FloatingType > &other) const
Definition: juce_Polynomial.h:136
juce::MathConstants
Definition: juce_MathsFunctions.h:363
juce::dsp::FIR::Coefficients
Definition: juce_FIRFilter.h:221
juce::dsp::FIR::Coefficients::getFilterOrder
size_t getFilterOrder() const noexcept
Definition: juce_FIRFilter.h:244
juce::dsp::FIR::Coefficients::getRawCoefficients
NumericType * getRawCoefficients() noexcept
Definition: juce_FIRFilter.h:269
juce::dsp::FilterDesign::designIIRLowpassHalfBandPolyphaseAllpassMethod
static IIRPolyphaseAllpassStructure designIIRLowpassHalfBandPolyphaseAllpassMethod(FloatType normalisedTransitionWidth, FloatType stopbandAmplitudedB)
Definition: juce_FilterDesign.cpp:613
juce::dsp::FilterDesign::designFIRLowpassHalfBandEquirippleMethod
static FIRCoefficientsPtr designFIRLowpassHalfBandEquirippleMethod(FloatType normalisedTransitionWidth, FloatType amplitudedB)
Definition: juce_FilterDesign.cpp:239
juce::dsp::FilterDesign::IIRPolyphaseAllpassStructure
Definition: juce_FilterDesign.h:260
juce::dsp::IIR::Coefficients
Definition: juce_dsp/processors/juce_IIRFilter.h:158
juce::dsp::IIR::Coefficients::coefficients
Array< NumericType > coefficients
Definition: juce_dsp/processors/juce_IIRFilter.h:295
juce::dsp::Oversampling2TimesEquirippleFIR
Definition: juce_Oversampling.cpp:115
juce::dsp::Oversampling2TimesPolyphaseIIR
Definition: juce_Oversampling.cpp:267
juce::dsp::OversamplingDummy
Definition: juce_Oversampling.cpp:75
juce::dsp::Oversampling::OversamplingStage
Definition: juce_Oversampling.cpp:37