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.

728 lines
28KB

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