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.

768 lines
29KB

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