The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

722 lines
28KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. You may use this code under the terms of the GPL v3
  6. (see www.gnu.org/licenses).
  7. For this technical preview, this file is not subject to commercial licensing.
  8. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  9. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  10. DISCLAIMED.
  11. ==============================================================================
  12. */
  13. namespace juce
  14. {
  15. namespace dsp
  16. {
  17. /** Abstract class for the provided oversampling stages used internally in
  18. the Oversampling class.
  19. */
  20. template <typename SampleType>
  21. struct Oversampling<SampleType>::OversamplingStage
  22. {
  23. OversamplingStage (size_t numChans, size_t newFactor) : numChannels (numChans), factor (newFactor) {}
  24. virtual ~OversamplingStage() {}
  25. //==============================================================================
  26. virtual SampleType getLatencyInSamples() const = 0;
  27. virtual void initProcessing (size_t maximumNumberOfSamplesBeforeOversampling)
  28. {
  29. buffer.setSize (static_cast<int> (numChannels),
  30. static_cast<int> (maximumNumberOfSamplesBeforeOversampling * factor),
  31. false, false, true);
  32. }
  33. virtual void reset()
  34. {
  35. buffer.clear();
  36. }
  37. AudioBlock<SampleType> getProcessedSamples (size_t numSamples)
  38. {
  39. return AudioBlock<SampleType> (buffer).getSubBlock (0, numSamples);
  40. }
  41. virtual void processSamplesUp (const AudioBlock<const SampleType>&) = 0;
  42. virtual void processSamplesDown (AudioBlock<SampleType>&) = 0;
  43. AudioBuffer<SampleType> buffer;
  44. size_t numChannels, factor;
  45. };
  46. //==============================================================================
  47. /** Dummy oversampling stage class which simply copies and pastes the input
  48. signal, which could be equivalent to a "one time" oversampling processing.
  49. */
  50. template <typename SampleType>
  51. struct OversamplingDummy : public Oversampling<SampleType>::OversamplingStage
  52. {
  53. using ParentType = typename Oversampling<SampleType>::OversamplingStage;
  54. OversamplingDummy (size_t numChans) : ParentType (numChans, 1) {}
  55. //==============================================================================
  56. SampleType getLatencyInSamples() const override
  57. {
  58. return 0;
  59. }
  60. void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override
  61. {
  62. jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
  63. jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
  64. for (size_t channel = 0; channel < inputBlock.getNumChannels(); ++channel)
  65. ParentType::buffer.copyFrom (static_cast<int> (channel), 0,
  66. inputBlock.getChannelPointer (channel), static_cast<int> (inputBlock.getNumSamples()));
  67. }
  68. void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
  69. {
  70. jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
  71. jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
  72. outputBlock.copyFrom (ParentType::getProcessedSamples (outputBlock.getNumSamples()));
  73. }
  74. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OversamplingDummy)
  75. };
  76. //==============================================================================
  77. /** Oversampling stage class performing 2 times oversampling using the Filter
  78. Design FIR Equiripple method. The resulting filter is linear phase,
  79. symmetric, and has every two samples but the middle one equal to zero,
  80. leading to specific processing optimizations.
  81. */
  82. template <typename SampleType>
  83. struct Oversampling2TimesEquirippleFIR : public Oversampling<SampleType>::OversamplingStage
  84. {
  85. using ParentType = typename Oversampling<SampleType>::OversamplingStage;
  86. Oversampling2TimesEquirippleFIR (size_t numChans,
  87. SampleType normalisedTransitionWidthUp,
  88. SampleType stopbandAmplitudedBUp,
  89. SampleType normalisedTransitionWidthDown,
  90. SampleType stopbandAmplitudedBDown)
  91. : ParentType (numChans, 2)
  92. {
  93. coefficientsUp = *FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthUp, stopbandAmplitudedBUp);
  94. coefficientsDown = *FilterDesign<SampleType>::designFIRLowpassHalfBandEquirippleMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);
  95. auto N = coefficientsUp.getFilterOrder() + 1;
  96. stateUp.setSize (static_cast<int> (this->numChannels), static_cast<int> (N));
  97. N = coefficientsDown.getFilterOrder() + 1;
  98. auto Ndiv2 = N / 2;
  99. auto Ndiv4 = Ndiv2 / 2;
  100. stateDown.setSize (static_cast<int> (this->numChannels), static_cast<int> (N));
  101. stateDown2.setSize (static_cast<int> (this->numChannels), static_cast<int> (Ndiv4 + 1));
  102. position.resize (static_cast<int> (this->numChannels));
  103. }
  104. //==============================================================================
  105. SampleType getLatencyInSamples() const override
  106. {
  107. return static_cast<SampleType> (coefficientsUp.getFilterOrder() + coefficientsDown.getFilterOrder()) * 0.5f;
  108. }
  109. void reset() override
  110. {
  111. ParentType::reset();
  112. stateUp.clear();
  113. stateDown.clear();
  114. stateDown2.clear();
  115. position.fill (0);
  116. }
  117. void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override
  118. {
  119. jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
  120. jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
  121. // Initialization
  122. auto fir = coefficientsUp.getRawCoefficients();
  123. auto N = coefficientsUp.getFilterOrder() + 1;
  124. auto Ndiv2 = N / 2;
  125. auto numSamples = inputBlock.getNumSamples();
  126. // Processing
  127. for (size_t channel = 0; channel < inputBlock.getNumChannels(); ++channel)
  128. {
  129. auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
  130. auto buf = stateUp.getWritePointer (static_cast<int> (channel));
  131. auto samples = inputBlock.getChannelPointer (channel);
  132. for (size_t i = 0; i < numSamples; ++i)
  133. {
  134. // Input
  135. buf[N - 1] = 2 * samples[i];
  136. // Convolution
  137. auto out = static_cast<SampleType> (0.0);
  138. for (size_t k = 0; k < Ndiv2; k += 2)
  139. out += (buf[k] + buf[N - k - 1]) * fir[k];
  140. // Outputs
  141. bufferSamples[i << 1] = out;
  142. bufferSamples[(i << 1) + 1] = buf[Ndiv2 + 1] * fir[Ndiv2];
  143. // Shift data
  144. for (size_t k = 0; k < N - 2; k += 2)
  145. buf[k] = buf[k + 2];
  146. }
  147. }
  148. }
  149. void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
  150. {
  151. jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
  152. jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
  153. // Initialization
  154. auto fir = coefficientsDown.getRawCoefficients();
  155. auto N = coefficientsDown.getFilterOrder() + 1;
  156. auto Ndiv2 = N / 2;
  157. auto Ndiv4 = Ndiv2 / 2;
  158. auto numSamples = outputBlock.getNumSamples();
  159. // Processing
  160. for (size_t channel = 0; channel < outputBlock.getNumChannels(); ++channel)
  161. {
  162. auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
  163. auto buf = stateDown.getWritePointer (static_cast<int> (channel));
  164. auto buf2 = stateDown2.getWritePointer (static_cast<int> (channel));
  165. auto samples = outputBlock.getChannelPointer (channel);
  166. auto pos = position.getUnchecked (static_cast<int> (channel));
  167. for (size_t i = 0; i < numSamples; ++i)
  168. {
  169. // Input
  170. buf[N - 1] = bufferSamples[i << 1];
  171. // Convolution
  172. auto out = static_cast<SampleType> (0.0);
  173. for (size_t k = 0; k < Ndiv2; k += 2)
  174. out += (buf[k] + buf[N - k - 1]) * fir[k];
  175. // Output
  176. out += buf2[pos] * fir[Ndiv2];
  177. buf2[pos] = bufferSamples[(i << 1) + 1];
  178. samples[i] = out;
  179. // Shift data
  180. for (size_t k = 0; k < N - 2; ++k)
  181. buf[k] = buf[k + 2];
  182. // Circular buffer
  183. pos = (pos == 0 ? Ndiv4 : pos - 1);
  184. }
  185. position.setUnchecked (static_cast<int> (channel), pos);
  186. }
  187. }
  188. private:
  189. //==============================================================================
  190. FIR::Coefficients<SampleType> coefficientsUp, coefficientsDown;
  191. AudioBuffer<SampleType> stateUp, stateDown, stateDown2;
  192. Array<size_t> position;
  193. //==============================================================================
  194. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oversampling2TimesEquirippleFIR)
  195. };
  196. //==============================================================================
  197. /** Oversampling stage class performing 2 times oversampling using the Filter
  198. Design IIR Polyphase Allpass Cascaded method. The resulting filter is minimum
  199. phase, and provided with a method to get the exact resulting latency.
  200. */
  201. template <typename SampleType>
  202. struct Oversampling2TimesPolyphaseIIR : public Oversampling<SampleType>::OversamplingStage
  203. {
  204. using ParentType = typename Oversampling<SampleType>::OversamplingStage;
  205. Oversampling2TimesPolyphaseIIR (size_t numChans,
  206. SampleType normalisedTransitionWidthUp,
  207. SampleType stopbandAmplitudedBUp,
  208. SampleType normalisedTransitionWidthDown,
  209. SampleType stopbandAmplitudedBDown)
  210. : ParentType (numChans, 2)
  211. {
  212. auto structureUp = FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthUp, stopbandAmplitudedBUp);
  213. auto coeffsUp = getCoefficients (structureUp);
  214. latency = static_cast<SampleType> (-(coeffsUp.getPhaseForFrequency (0.0001, 1.0)) / (0.0001 * MathConstants<double>::twoPi));
  215. auto structureDown = FilterDesign<SampleType>::designIIRLowpassHalfBandPolyphaseAllpassMethod (normalisedTransitionWidthDown, stopbandAmplitudedBDown);
  216. auto coeffsDown = getCoefficients (structureDown);
  217. latency += static_cast<SampleType> (-(coeffsDown.getPhaseForFrequency (0.0001, 1.0)) / (0.0001 * MathConstants<double>::twoPi));
  218. for (auto i = 0; i < structureUp.directPath.size(); ++i)
  219. coefficientsUp.add (structureUp.directPath.getObjectPointer (i)->coefficients[0]);
  220. for (auto i = 1; i < structureUp.delayedPath.size(); ++i)
  221. coefficientsUp.add (structureUp.delayedPath.getObjectPointer (i)->coefficients[0]);
  222. for (auto i = 0; i < structureDown.directPath.size(); ++i)
  223. coefficientsDown.add (structureDown.directPath.getObjectPointer (i)->coefficients[0]);
  224. for (auto i = 1; i < structureDown.delayedPath.size(); ++i)
  225. coefficientsDown.add (structureDown.delayedPath.getObjectPointer (i)->coefficients[0]);
  226. v1Up.setSize (static_cast<int> (this->numChannels), coefficientsUp.size());
  227. v1Down.setSize (static_cast<int> (this->numChannels), coefficientsDown.size());
  228. delayDown.resize (static_cast<int> (this->numChannels));
  229. }
  230. //==============================================================================
  231. SampleType getLatencyInSamples() const override
  232. {
  233. return latency;
  234. }
  235. void reset() override
  236. {
  237. ParentType::reset();
  238. v1Up.clear();
  239. v1Down.clear();
  240. delayDown.fill (0);
  241. }
  242. void processSamplesUp (const AudioBlock<const SampleType>& inputBlock) override
  243. {
  244. jassert (inputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
  245. jassert (inputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
  246. // Initialization
  247. auto coeffs = coefficientsUp.getRawDataPointer();
  248. auto numStages = coefficientsUp.size();
  249. auto delayedStages = numStages / 2;
  250. auto directStages = numStages - delayedStages;
  251. auto numSamples = inputBlock.getNumSamples();
  252. // Processing
  253. for (size_t channel = 0; channel < inputBlock.getNumChannels(); ++channel)
  254. {
  255. auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
  256. auto lv1 = v1Up.getWritePointer (static_cast<int> (channel));
  257. auto samples = inputBlock.getChannelPointer (channel);
  258. for (size_t i = 0; i < numSamples; ++i)
  259. {
  260. // Direct path cascaded allpass filters
  261. auto input = samples[i];
  262. for (auto n = 0; n < directStages; ++n)
  263. {
  264. auto alpha = coeffs[n];
  265. auto output = alpha * input + lv1[n];
  266. lv1[n] = input - alpha * output;
  267. input = output;
  268. }
  269. // Output
  270. bufferSamples[i << 1] = input;
  271. // Delayed path cascaded allpass filters
  272. input = samples[i];
  273. for (auto n = directStages; n < numStages; ++n)
  274. {
  275. auto alpha = coeffs[n];
  276. auto output = alpha * input + lv1[n];
  277. lv1[n] = input - alpha * output;
  278. input = output;
  279. }
  280. // Output
  281. bufferSamples[(i << 1) + 1] = input;
  282. }
  283. }
  284. // Snap To Zero
  285. snapToZero (true);
  286. }
  287. void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
  288. {
  289. jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
  290. jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
  291. // Initialization
  292. auto coeffs = coefficientsDown.getRawDataPointer();
  293. auto numStages = coefficientsDown.size();
  294. auto delayedStages = numStages / 2;
  295. auto directStages = numStages - delayedStages;
  296. auto numSamples = outputBlock.getNumSamples();
  297. // Processing
  298. for (size_t channel = 0; channel < outputBlock.getNumChannels(); ++channel)
  299. {
  300. auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
  301. auto lv1 = v1Down.getWritePointer (static_cast<int> (channel));
  302. auto samples = outputBlock.getChannelPointer (channel);
  303. auto delay = delayDown.getUnchecked (static_cast<int> (channel));
  304. for (size_t i = 0; i < numSamples; ++i)
  305. {
  306. // Direct path cascaded allpass filters
  307. auto input = bufferSamples[i << 1];
  308. for (auto n = 0; n < directStages; ++n)
  309. {
  310. auto alpha = coeffs[n];
  311. auto output = alpha * input + lv1[n];
  312. lv1[n] = input - alpha * output;
  313. input = output;
  314. }
  315. auto directOut = input;
  316. // Delayed path cascaded allpass filters
  317. input = bufferSamples[(i << 1) + 1];
  318. for (auto n = directStages; n < numStages; ++n)
  319. {
  320. auto alpha = coeffs[n];
  321. auto output = alpha * input + lv1[n];
  322. lv1[n] = input - alpha * output;
  323. input = output;
  324. }
  325. // Output
  326. samples[i] = (delay + directOut) * static_cast<SampleType> (0.5);
  327. delay = input;
  328. }
  329. delayDown.setUnchecked (static_cast<int> (channel), delay);
  330. }
  331. // Snap To Zero
  332. snapToZero (false);
  333. }
  334. void snapToZero (bool snapUpProcessing)
  335. {
  336. if (snapUpProcessing)
  337. {
  338. for (auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
  339. {
  340. auto lv1 = v1Up.getWritePointer (channel);
  341. auto numStages = coefficientsUp.size();
  342. for (auto n = 0; n < numStages; ++n)
  343. util::snapToZero (lv1[n]);
  344. }
  345. }
  346. else
  347. {
  348. for (auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
  349. {
  350. auto lv1 = v1Down.getWritePointer (channel);
  351. auto numStages = coefficientsDown.size();
  352. for (auto n = 0; n < numStages; ++n)
  353. util::snapToZero (lv1[n]);
  354. }
  355. }
  356. }
  357. private:
  358. //==============================================================================
  359. /** This function calculates the equivalent high order IIR filter of a given
  360. polyphase cascaded allpass filters structure.
  361. */
  362. IIR::Coefficients<SampleType> getCoefficients (typename FilterDesign<SampleType>::IIRPolyphaseAllpassStructure& structure) const
  363. {
  364. constexpr auto one = static_cast<SampleType> (1.0);
  365. Polynomial<SampleType> numerator1 ({ one }), denominator1 ({ one }),
  366. numerator2 ({ one }), denominator2 ({ one });
  367. for (auto* i : structure.directPath)
  368. {
  369. auto coeffs = i->getRawCoefficients();
  370. if (i->getFilterOrder() == 1)
  371. {
  372. numerator1 = numerator1 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));
  373. denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one, coeffs[2] }));
  374. }
  375. else
  376. {
  377. numerator1 = numerator1 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));
  378. denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));
  379. }
  380. }
  381. for (auto* i : structure.delayedPath)
  382. {
  383. auto coeffs = i->getRawCoefficients();
  384. if (i->getFilterOrder() == 1)
  385. {
  386. numerator2 = numerator2 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));
  387. denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one, coeffs[2] }));
  388. }
  389. else
  390. {
  391. numerator2 = numerator2 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));
  392. denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));
  393. }
  394. }
  395. auto numeratorf1 = numerator1.getProductWith (denominator2);
  396. auto numeratorf2 = numerator2.getProductWith (denominator1);
  397. auto numerator = numeratorf1.getSumWith (numeratorf2);
  398. auto denominator = denominator1.getProductWith (denominator2);
  399. IIR::Coefficients<SampleType> coeffs;
  400. coeffs.coefficients.clear();
  401. auto inversion = one / denominator[0];
  402. for (auto i = 0; i <= numerator.getOrder(); ++i)
  403. coeffs.coefficients.add (numerator[i] * inversion);
  404. for (auto i = 1; i <= denominator.getOrder(); ++i)
  405. coeffs.coefficients.add (denominator[i] * inversion);
  406. return coeffs;
  407. }
  408. //==============================================================================
  409. Array<SampleType> coefficientsUp, coefficientsDown;
  410. SampleType latency;
  411. AudioBuffer<SampleType> v1Up, v1Down;
  412. Array<SampleType> delayDown;
  413. //==============================================================================
  414. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oversampling2TimesPolyphaseIIR)
  415. };
  416. //==============================================================================
  417. template <typename SampleType>
  418. Oversampling<SampleType>::Oversampling (size_t newNumChannels)
  419. : numChannels (newNumChannels)
  420. {
  421. jassert (numChannels > 0);
  422. addDummyOversamplingStage();
  423. }
  424. template <typename SampleType>
  425. Oversampling<SampleType>::Oversampling (size_t newNumChannels, size_t newFactor,
  426. FilterType newType, bool isMaximumQuality)
  427. : numChannels (newNumChannels)
  428. {
  429. jassert (isPositiveAndBelow (newFactor, 5) && numChannels > 0);
  430. if (newFactor == 0)
  431. {
  432. addDummyOversamplingStage();
  433. }
  434. else if (newType == FilterType::filterHalfBandPolyphaseIIR)
  435. {
  436. for (size_t n = 0; n < newFactor; ++n)
  437. {
  438. auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f);
  439. auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f);
  440. auto gaindBStartUp = (isMaximumQuality ? -90.0f : -70.0f);
  441. auto gaindBStartDown = (isMaximumQuality ? -75.0f : -60.0f);
  442. auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f);
  443. auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f);
  444. addOversamplingStage (FilterType::filterHalfBandPolyphaseIIR,
  445. twUp, gaindBStartUp + gaindBFactorUp * n,
  446. twDown, gaindBStartDown + gaindBFactorDown * n);
  447. }
  448. }
  449. else if (newType == FilterType::filterHalfBandFIREquiripple)
  450. {
  451. for (size_t n = 0; n < newFactor; ++n)
  452. {
  453. auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f);
  454. auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f);
  455. auto gaindBStartUp = (isMaximumQuality ? -90.0f : -70.0f);
  456. auto gaindBStartDown = (isMaximumQuality ? -75.0f : -60.0f);
  457. auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f);
  458. auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f);
  459. addOversamplingStage (FilterType::filterHalfBandFIREquiripple,
  460. twUp, gaindBStartUp + gaindBFactorUp * n,
  461. twDown, gaindBStartDown + gaindBFactorDown * n);
  462. }
  463. }
  464. }
  465. template <typename SampleType>
  466. Oversampling<SampleType>::~Oversampling()
  467. {
  468. stages.clear();
  469. }
  470. //==============================================================================
  471. template <typename SampleType>
  472. void Oversampling<SampleType>::addDummyOversamplingStage()
  473. {
  474. stages.add (new OversamplingDummy<SampleType> (numChannels));
  475. }
  476. template <typename SampleType>
  477. void Oversampling<SampleType>::addOversamplingStage (FilterType type,
  478. float normalisedTransitionWidthUp,
  479. float stopbandAmplitudedBUp,
  480. float normalisedTransitionWidthDown,
  481. float stopbandAmplitudedBDown)
  482. {
  483. if (type == FilterType::filterHalfBandPolyphaseIIR)
  484. {
  485. stages.add (new Oversampling2TimesPolyphaseIIR<SampleType> (numChannels,
  486. normalisedTransitionWidthUp, stopbandAmplitudedBUp,
  487. normalisedTransitionWidthDown, stopbandAmplitudedBDown));
  488. }
  489. else
  490. {
  491. stages.add (new Oversampling2TimesEquirippleFIR<SampleType> (numChannels,
  492. normalisedTransitionWidthUp, stopbandAmplitudedBUp,
  493. normalisedTransitionWidthDown, stopbandAmplitudedBDown));
  494. }
  495. factorOversampling *= 2;
  496. }
  497. template <typename SampleType>
  498. void Oversampling<SampleType>::clearOversamplingStages()
  499. {
  500. stages.clear();
  501. factorOversampling = 1u;
  502. }
  503. //==============================================================================
  504. template <typename SampleType>
  505. SampleType Oversampling<SampleType>::getLatencyInSamples() const noexcept
  506. {
  507. auto latency = static_cast<SampleType> (0);
  508. size_t order = 1;
  509. for (auto* stage : stages)
  510. {
  511. order *= stage->factor;
  512. latency += stage->getLatencyInSamples() / static_cast<SampleType> (order);
  513. }
  514. return latency;
  515. }
  516. template <typename SampleType>
  517. size_t Oversampling<SampleType>::getOversamplingFactor() const noexcept
  518. {
  519. return factorOversampling;
  520. }
  521. //==============================================================================
  522. template <typename SampleType>
  523. void Oversampling<SampleType>::initProcessing (size_t maximumNumberOfSamplesBeforeOversampling)
  524. {
  525. jassert (! stages.isEmpty());
  526. auto currentNumSamples = maximumNumberOfSamplesBeforeOversampling;
  527. for (auto* stage : stages)
  528. {
  529. stage->initProcessing (currentNumSamples);
  530. currentNumSamples *= stage->factor;
  531. }
  532. isReady = true;
  533. reset();
  534. }
  535. template <typename SampleType>
  536. void Oversampling<SampleType>::reset() noexcept
  537. {
  538. jassert (! stages.isEmpty());
  539. if (isReady)
  540. for (auto* stage : stages)
  541. stage->reset();
  542. }
  543. template <typename SampleType>
  544. AudioBlock<SampleType> Oversampling<SampleType>::processSamplesUp (const AudioBlock<const SampleType>& inputBlock) noexcept
  545. {
  546. jassert (! stages.isEmpty());
  547. if (! isReady)
  548. return {};
  549. auto* firstStage = stages.getUnchecked (0);
  550. firstStage->processSamplesUp (inputBlock);
  551. auto block = firstStage->getProcessedSamples (inputBlock.getNumSamples() * firstStage->factor);
  552. for (int i = 1; i < stages.size(); ++i)
  553. {
  554. stages[i]->processSamplesUp (block);
  555. block = stages[i]->getProcessedSamples (block.getNumSamples() * stages[i]->factor);
  556. }
  557. return block;
  558. }
  559. template <typename SampleType>
  560. void Oversampling<SampleType>::processSamplesDown (AudioBlock<SampleType>& outputBlock) noexcept
  561. {
  562. jassert (! stages.isEmpty());
  563. if (! isReady)
  564. return;
  565. auto currentNumSamples = outputBlock.getNumSamples();
  566. for (int n = 0; n < stages.size() - 1; ++n)
  567. currentNumSamples *= stages.getUnchecked(n)->factor;
  568. for (int n = stages.size() - 1; n > 0; --n)
  569. {
  570. auto& stage = *stages.getUnchecked(n);
  571. auto audioBlock = stages.getUnchecked (n - 1)->getProcessedSamples (currentNumSamples);
  572. stage.processSamplesDown (audioBlock);
  573. currentNumSamples /= stage.factor;
  574. }
  575. stages.getFirst()->processSamplesDown (outputBlock);
  576. }
  577. template class Oversampling<float>;
  578. template class Oversampling<double>;
  579. } // namespace dsp
  580. } // namespace juce