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.

764 lines
29KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE 6 technical preview.
  4. Copyright (c) 2020 - Raw Material Software Limited
  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. #if JUCE_SNAP_TO_ZERO
  285. snapToZero (true);
  286. #endif
  287. }
  288. void processSamplesDown (AudioBlock<SampleType>& outputBlock) override
  289. {
  290. jassert (outputBlock.getNumChannels() <= static_cast<size_t> (ParentType::buffer.getNumChannels()));
  291. jassert (outputBlock.getNumSamples() * ParentType::factor <= static_cast<size_t> (ParentType::buffer.getNumSamples()));
  292. // Initialization
  293. auto coeffs = coefficientsDown.getRawDataPointer();
  294. auto numStages = coefficientsDown.size();
  295. auto delayedStages = numStages / 2;
  296. auto directStages = numStages - delayedStages;
  297. auto numSamples = outputBlock.getNumSamples();
  298. // Processing
  299. for (size_t channel = 0; channel < outputBlock.getNumChannels(); ++channel)
  300. {
  301. auto bufferSamples = ParentType::buffer.getWritePointer (static_cast<int> (channel));
  302. auto lv1 = v1Down.getWritePointer (static_cast<int> (channel));
  303. auto samples = outputBlock.getChannelPointer (channel);
  304. auto delay = delayDown.getUnchecked (static_cast<int> (channel));
  305. for (size_t i = 0; i < numSamples; ++i)
  306. {
  307. // Direct path cascaded allpass filters
  308. auto input = bufferSamples[i << 1];
  309. for (auto n = 0; n < directStages; ++n)
  310. {
  311. auto alpha = coeffs[n];
  312. auto output = alpha * input + lv1[n];
  313. lv1[n] = input - alpha * output;
  314. input = output;
  315. }
  316. auto directOut = input;
  317. // Delayed path cascaded allpass filters
  318. input = bufferSamples[(i << 1) + 1];
  319. for (auto n = directStages; n < numStages; ++n)
  320. {
  321. auto alpha = coeffs[n];
  322. auto output = alpha * input + lv1[n];
  323. lv1[n] = input - alpha * output;
  324. input = output;
  325. }
  326. // Output
  327. samples[i] = (delay + directOut) * static_cast<SampleType> (0.5);
  328. delay = input;
  329. }
  330. delayDown.setUnchecked (static_cast<int> (channel), delay);
  331. }
  332. #if JUCE_SNAP_TO_ZERO
  333. snapToZero (false);
  334. #endif
  335. }
  336. void snapToZero (bool snapUpProcessing)
  337. {
  338. if (snapUpProcessing)
  339. {
  340. for (auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
  341. {
  342. auto lv1 = v1Up.getWritePointer (channel);
  343. auto numStages = coefficientsUp.size();
  344. for (auto n = 0; n < numStages; ++n)
  345. util::snapToZero (lv1[n]);
  346. }
  347. }
  348. else
  349. {
  350. for (auto channel = 0; channel < ParentType::buffer.getNumChannels(); ++channel)
  351. {
  352. auto lv1 = v1Down.getWritePointer (channel);
  353. auto numStages = coefficientsDown.size();
  354. for (auto n = 0; n < numStages; ++n)
  355. util::snapToZero (lv1[n]);
  356. }
  357. }
  358. }
  359. private:
  360. //==============================================================================
  361. /** This function calculates the equivalent high order IIR filter of a given
  362. polyphase cascaded allpass filters structure.
  363. */
  364. IIR::Coefficients<SampleType> getCoefficients (typename FilterDesign<SampleType>::IIRPolyphaseAllpassStructure& structure) const
  365. {
  366. constexpr auto one = static_cast<SampleType> (1.0);
  367. Polynomial<SampleType> numerator1 ({ one }), denominator1 ({ one }),
  368. numerator2 ({ one }), denominator2 ({ one });
  369. for (auto* i : structure.directPath)
  370. {
  371. auto coeffs = i->getRawCoefficients();
  372. if (i->getFilterOrder() == 1)
  373. {
  374. numerator1 = numerator1 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));
  375. denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one, coeffs[2] }));
  376. }
  377. else
  378. {
  379. numerator1 = numerator1 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));
  380. denominator1 = denominator1.getProductWith (Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));
  381. }
  382. }
  383. for (auto* i : structure.delayedPath)
  384. {
  385. auto coeffs = i->getRawCoefficients();
  386. if (i->getFilterOrder() == 1)
  387. {
  388. numerator2 = numerator2 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1] }));
  389. denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one, coeffs[2] }));
  390. }
  391. else
  392. {
  393. numerator2 = numerator2 .getProductWith (Polynomial<SampleType> ({ coeffs[0], coeffs[1], coeffs[2] }));
  394. denominator2 = denominator2.getProductWith (Polynomial<SampleType> ({ one, coeffs[3], coeffs[4] }));
  395. }
  396. }
  397. auto numeratorf1 = numerator1.getProductWith (denominator2);
  398. auto numeratorf2 = numerator2.getProductWith (denominator1);
  399. auto numerator = numeratorf1.getSumWith (numeratorf2);
  400. auto denominator = denominator1.getProductWith (denominator2);
  401. IIR::Coefficients<SampleType> coeffs;
  402. coeffs.coefficients.clear();
  403. auto inversion = one / denominator[0];
  404. for (int i = 0; i <= numerator.getOrder(); ++i)
  405. coeffs.coefficients.add (numerator[i] * inversion);
  406. for (int i = 1; i <= denominator.getOrder(); ++i)
  407. coeffs.coefficients.add (denominator[i] * inversion);
  408. return coeffs;
  409. }
  410. //==============================================================================
  411. Array<SampleType> coefficientsUp, coefficientsDown;
  412. SampleType latency;
  413. AudioBuffer<SampleType> v1Up, v1Down;
  414. Array<SampleType> delayDown;
  415. //==============================================================================
  416. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Oversampling2TimesPolyphaseIIR)
  417. };
  418. //==============================================================================
  419. template <typename SampleType>
  420. Oversampling<SampleType>::Oversampling (size_t newNumChannels)
  421. : numChannels (newNumChannels)
  422. {
  423. jassert (numChannels > 0);
  424. addDummyOversamplingStage();
  425. }
  426. template <typename SampleType>
  427. Oversampling<SampleType>::Oversampling (size_t newNumChannels, size_t newFactor,
  428. FilterType newType, bool isMaximumQuality,
  429. bool useIntegerLatency)
  430. : numChannels (newNumChannels), shouldUseIntegerLatency (useIntegerLatency)
  431. {
  432. jassert (isPositiveAndBelow (newFactor, 5) && numChannels > 0);
  433. if (newFactor == 0)
  434. {
  435. addDummyOversamplingStage();
  436. }
  437. else if (newType == FilterType::filterHalfBandPolyphaseIIR)
  438. {
  439. for (size_t n = 0; n < newFactor; ++n)
  440. {
  441. auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f);
  442. auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f);
  443. auto gaindBStartUp = (isMaximumQuality ? -90.0f : -70.0f);
  444. auto gaindBStartDown = (isMaximumQuality ? -75.0f : -60.0f);
  445. auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f);
  446. auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f);
  447. addOversamplingStage (FilterType::filterHalfBandPolyphaseIIR,
  448. twUp, gaindBStartUp + gaindBFactorUp * n,
  449. twDown, gaindBStartDown + gaindBFactorDown * n);
  450. }
  451. }
  452. else if (newType == FilterType::filterHalfBandFIREquiripple)
  453. {
  454. for (size_t n = 0; n < newFactor; ++n)
  455. {
  456. auto twUp = (isMaximumQuality ? 0.10f : 0.12f) * (n == 0 ? 0.5f : 1.0f);
  457. auto twDown = (isMaximumQuality ? 0.12f : 0.15f) * (n == 0 ? 0.5f : 1.0f);
  458. auto gaindBStartUp = (isMaximumQuality ? -90.0f : -70.0f);
  459. auto gaindBStartDown = (isMaximumQuality ? -75.0f : -60.0f);
  460. auto gaindBFactorUp = (isMaximumQuality ? 10.0f : 8.0f);
  461. auto gaindBFactorDown = (isMaximumQuality ? 10.0f : 8.0f);
  462. addOversamplingStage (FilterType::filterHalfBandFIREquiripple,
  463. twUp, gaindBStartUp + gaindBFactorUp * n,
  464. twDown, gaindBStartDown + gaindBFactorDown * n);
  465. }
  466. }
  467. }
  468. template <typename SampleType>
  469. Oversampling<SampleType>::~Oversampling()
  470. {
  471. stages.clear();
  472. }
  473. //==============================================================================
  474. template <typename SampleType>
  475. void Oversampling<SampleType>::addDummyOversamplingStage()
  476. {
  477. stages.add (new OversamplingDummy<SampleType> (numChannels));
  478. }
  479. template <typename SampleType>
  480. void Oversampling<SampleType>::addOversamplingStage (FilterType type,
  481. float normalisedTransitionWidthUp,
  482. float stopbandAmplitudedBUp,
  483. float normalisedTransitionWidthDown,
  484. float stopbandAmplitudedBDown)
  485. {
  486. if (type == FilterType::filterHalfBandPolyphaseIIR)
  487. {
  488. stages.add (new Oversampling2TimesPolyphaseIIR<SampleType> (numChannels,
  489. normalisedTransitionWidthUp, stopbandAmplitudedBUp,
  490. normalisedTransitionWidthDown, stopbandAmplitudedBDown));
  491. }
  492. else
  493. {
  494. stages.add (new Oversampling2TimesEquirippleFIR<SampleType> (numChannels,
  495. normalisedTransitionWidthUp, stopbandAmplitudedBUp,
  496. normalisedTransitionWidthDown, stopbandAmplitudedBDown));
  497. }
  498. factorOversampling *= 2;
  499. }
  500. template <typename SampleType>
  501. void Oversampling<SampleType>::clearOversamplingStages()
  502. {
  503. stages.clear();
  504. factorOversampling = 1u;
  505. }
  506. //==============================================================================
  507. template <typename SampleType>
  508. void Oversampling<SampleType>::setUsingIntegerLatency (bool useIntegerLatency) noexcept
  509. {
  510. shouldUseIntegerLatency = useIntegerLatency;
  511. }
  512. template <typename SampleType>
  513. SampleType Oversampling<SampleType>::getLatencyInSamples() const noexcept
  514. {
  515. auto latency = getUncompensatedLatency();
  516. return shouldUseIntegerLatency ? latency + fractionalDelay : latency;
  517. }
  518. template <typename SampleType>
  519. SampleType Oversampling<SampleType>::getUncompensatedLatency() const noexcept
  520. {
  521. auto latency = static_cast<SampleType> (0);
  522. size_t order = 1;
  523. for (auto* stage : stages)
  524. {
  525. order *= stage->factor;
  526. latency += stage->getLatencyInSamples() / static_cast<SampleType> (order);
  527. }
  528. return latency;
  529. }
  530. template <typename SampleType>
  531. size_t Oversampling<SampleType>::getOversamplingFactor() const noexcept
  532. {
  533. return factorOversampling;
  534. }
  535. //==============================================================================
  536. template <typename SampleType>
  537. void Oversampling<SampleType>::initProcessing (size_t maximumNumberOfSamplesBeforeOversampling)
  538. {
  539. jassert (! stages.isEmpty());
  540. auto currentNumSamples = maximumNumberOfSamplesBeforeOversampling;
  541. for (auto* stage : stages)
  542. {
  543. stage->initProcessing (currentNumSamples);
  544. currentNumSamples *= stage->factor;
  545. }
  546. ProcessSpec spec = { 0.0, (uint32) maximumNumberOfSamplesBeforeOversampling, (uint32) numChannels };
  547. delay.prepare (spec);
  548. updateDelayLine();
  549. isReady = true;
  550. reset();
  551. }
  552. template <typename SampleType>
  553. void Oversampling<SampleType>::reset() noexcept
  554. {
  555. jassert (! stages.isEmpty());
  556. if (isReady)
  557. for (auto* stage : stages)
  558. stage->reset();
  559. delay.reset();
  560. }
  561. template <typename SampleType>
  562. AudioBlock<SampleType> Oversampling<SampleType>::processSamplesUp (const AudioBlock<const SampleType>& inputBlock) noexcept
  563. {
  564. jassert (! stages.isEmpty());
  565. if (! isReady)
  566. return {};
  567. auto* firstStage = stages.getUnchecked (0);
  568. firstStage->processSamplesUp (inputBlock);
  569. auto block = firstStage->getProcessedSamples (inputBlock.getNumSamples() * firstStage->factor);
  570. for (int i = 1; i < stages.size(); ++i)
  571. {
  572. stages[i]->processSamplesUp (block);
  573. block = stages[i]->getProcessedSamples (block.getNumSamples() * stages[i]->factor);
  574. }
  575. return block;
  576. }
  577. template <typename SampleType>
  578. void Oversampling<SampleType>::processSamplesDown (AudioBlock<SampleType>& outputBlock) noexcept
  579. {
  580. jassert (! stages.isEmpty());
  581. if (! isReady)
  582. return;
  583. auto currentNumSamples = outputBlock.getNumSamples();
  584. for (int n = 0; n < stages.size() - 1; ++n)
  585. currentNumSamples *= stages.getUnchecked(n)->factor;
  586. for (int n = stages.size() - 1; n > 0; --n)
  587. {
  588. auto& stage = *stages.getUnchecked(n);
  589. auto audioBlock = stages.getUnchecked (n - 1)->getProcessedSamples (currentNumSamples);
  590. stage.processSamplesDown (audioBlock);
  591. currentNumSamples /= stage.factor;
  592. }
  593. stages.getFirst()->processSamplesDown (outputBlock);
  594. if (shouldUseIntegerLatency && fractionalDelay > static_cast<SampleType> (0.0))
  595. {
  596. auto context = ProcessContextReplacing<SampleType> (outputBlock);
  597. delay.process (context);
  598. }
  599. }
  600. template <typename SampleType>
  601. void Oversampling<SampleType>::updateDelayLine()
  602. {
  603. auto latency = getUncompensatedLatency();
  604. fractionalDelay = static_cast<SampleType> (1.0) - (latency - std::floor (latency));
  605. if (fractionalDelay == static_cast<SampleType> (1.0))
  606. fractionalDelay = static_cast<SampleType> (0.0);
  607. else if (fractionalDelay < static_cast<SampleType> (0.618))
  608. fractionalDelay += static_cast<SampleType> (1.0);
  609. delay.setDelay (fractionalDelay);
  610. }
  611. template class Oversampling<float>;
  612. template class Oversampling<double>;
  613. } // namespace dsp
  614. } // namespace juce