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.

839 lines
29KB

  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. struct FFT::Instance
  20. {
  21. virtual ~Instance() {}
  22. virtual void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept = 0;
  23. virtual void performRealOnlyForwardTransform (float*, bool) const noexcept = 0;
  24. virtual void performRealOnlyInverseTransform (float*) const noexcept = 0;
  25. };
  26. struct FFT::Engine
  27. {
  28. Engine (int priorityToUse) : enginePriority (priorityToUse)
  29. {
  30. EnginePriorityComparator comparator;
  31. getEngines().addSorted (comparator, this);
  32. }
  33. virtual ~Engine() {}
  34. virtual FFT::Instance* create (int order) const = 0;
  35. //==============================================================================
  36. static FFT::Instance* createBestEngineForPlatform (int order)
  37. {
  38. for (auto* engine : getEngines())
  39. if (auto* instance = engine->create (order))
  40. return instance;
  41. jassertfalse; // This should never happen as the fallback engine should always work!
  42. return nullptr;
  43. }
  44. private:
  45. struct EnginePriorityComparator
  46. {
  47. static int compareElements (Engine* first, Engine* second) noexcept
  48. {
  49. // sort in reverse order
  50. return DefaultElementComparator<int>::compareElements (second->enginePriority, first->enginePriority);
  51. }
  52. };
  53. static Array<Engine*>& getEngines()
  54. {
  55. static Array<Engine*> engines;
  56. return engines;
  57. }
  58. int enginePriority; // used so that faster engines have priority over slower ones
  59. };
  60. template <typename InstanceToUse>
  61. struct FFT::EngineImpl : public FFT::Engine
  62. {
  63. EngineImpl() : FFT::Engine (InstanceToUse::priority) {}
  64. FFT::Instance* create (int order) const override { return InstanceToUse::create (order); }
  65. };
  66. //==============================================================================
  67. //==============================================================================
  68. struct FFTFallback : public FFT::Instance
  69. {
  70. // this should have the least priority of all engines
  71. static constexpr int priority = -1;
  72. static FFTFallback* create (int order)
  73. {
  74. return new FFTFallback (order);
  75. }
  76. FFTFallback (int order)
  77. {
  78. configForward = new FFTConfig (1 << order, false);
  79. configInverse = new FFTConfig (1 << order, true);
  80. size = 1 << order;
  81. }
  82. void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept override
  83. {
  84. if (size == 1)
  85. {
  86. *output = *input;
  87. return;
  88. }
  89. const SpinLock::ScopedLockType sl(processLock);
  90. jassert (configForward != nullptr);
  91. if (inverse)
  92. {
  93. configInverse->perform (input, output);
  94. const float scaleFactor = 1.0f / size;
  95. for (int i = 0; i < size; ++i)
  96. output[i] *= scaleFactor;
  97. }
  98. else
  99. {
  100. configForward->perform (input, output);
  101. }
  102. }
  103. const size_t maxFFTScratchSpaceToAlloca = 256 * 1024;
  104. void performRealOnlyForwardTransform (float* d, bool) const noexcept override
  105. {
  106. if (size == 1)
  107. return;
  108. const size_t scratchSize = 16 + sizeof (Complex<float>) * (size_t) size;
  109. if (scratchSize < maxFFTScratchSpaceToAlloca)
  110. {
  111. performRealOnlyForwardTransform (static_cast<Complex<float>*> (alloca (scratchSize)), d);
  112. }
  113. else
  114. {
  115. HeapBlock<char> heapSpace (scratchSize);
  116. performRealOnlyForwardTransform (reinterpret_cast<Complex<float>*> (heapSpace.getData()), d);
  117. }
  118. }
  119. void performRealOnlyInverseTransform (float* d) const noexcept override
  120. {
  121. if (size == 1)
  122. return;
  123. const size_t scratchSize = 16 + sizeof (Complex<float>) * (size_t) size;
  124. if (scratchSize < maxFFTScratchSpaceToAlloca)
  125. {
  126. performRealOnlyInverseTransform (static_cast<Complex<float>*> (alloca (scratchSize)), d);
  127. }
  128. else
  129. {
  130. HeapBlock<char> heapSpace (scratchSize);
  131. performRealOnlyInverseTransform (reinterpret_cast<Complex<float>*> (heapSpace.getData()), d);
  132. }
  133. }
  134. void performRealOnlyForwardTransform (Complex<float>* scratch, float* d) const noexcept
  135. {
  136. for (int i = 0; i < size; ++i)
  137. {
  138. scratch[i].real (d[i]);
  139. scratch[i].imag (0);
  140. }
  141. perform (scratch, reinterpret_cast<Complex<float>*> (d), false);
  142. }
  143. void performRealOnlyInverseTransform (Complex<float>* scratch, float* d) const noexcept
  144. {
  145. auto* input = reinterpret_cast<Complex<float>*> (d);
  146. for (auto i = size >> 1; i < size; ++i)
  147. input[i] = std::conj (input[size - i]);
  148. perform (input, scratch, true);
  149. for (int i = 0; i < size; ++i)
  150. {
  151. d[i] = scratch[i].real();
  152. d[i + size] = scratch[i].imag();
  153. }
  154. }
  155. //==============================================================================
  156. struct FFTConfig
  157. {
  158. FFTConfig (int sizeOfFFT, bool isInverse)
  159. : fftSize (sizeOfFFT), inverse (isInverse), twiddleTable ((size_t) sizeOfFFT)
  160. {
  161. const double inverseFactor = (inverse ? 2.0 : -2.0) * double_Pi / (double) fftSize;
  162. if (fftSize <= 4)
  163. {
  164. for (int i = 0; i < fftSize; ++i)
  165. {
  166. const double phase = i * inverseFactor;
  167. twiddleTable[i].real ((float) std::cos (phase));
  168. twiddleTable[i].imag ((float) std::sin (phase));
  169. }
  170. }
  171. else
  172. {
  173. for (int i = 0; i < fftSize / 4; ++i)
  174. {
  175. const double phase = i * inverseFactor;
  176. twiddleTable[i].real ((float) std::cos (phase));
  177. twiddleTable[i].imag ((float) std::sin (phase));
  178. }
  179. for (int i = fftSize / 4; i < fftSize / 2; ++i)
  180. {
  181. const int index = i - fftSize / 4;
  182. twiddleTable[i].real (inverse ? -twiddleTable[index].imag() : twiddleTable[index].imag());
  183. twiddleTable[i].imag (inverse ? twiddleTable[index].real() : -twiddleTable[index].real());
  184. }
  185. twiddleTable[fftSize / 2].real (-1.0f);
  186. twiddleTable[fftSize / 2].imag (0.0f);
  187. for (int i = fftSize / 2; i < fftSize; ++i)
  188. {
  189. const int index = fftSize / 2 - (i - fftSize / 2);
  190. twiddleTable[i] = conj(twiddleTable[index]);
  191. }
  192. }
  193. const int root = (int) std::sqrt ((double) fftSize);
  194. int divisor = 4, n = fftSize;
  195. for (int i = 0; i < numElementsInArray (factors); ++i)
  196. {
  197. while ((n % divisor) != 0)
  198. {
  199. if (divisor == 2) divisor = 3;
  200. else if (divisor == 4) divisor = 2;
  201. else divisor += 2;
  202. if (divisor > root)
  203. divisor = n;
  204. }
  205. n /= divisor;
  206. jassert (divisor == 1 || divisor == 2 || divisor == 4);
  207. factors[i].radix = divisor;
  208. factors[i].length = n;
  209. }
  210. }
  211. void perform (const Complex<float>* input, Complex<float>* output) const noexcept
  212. {
  213. perform (input, output, 1, 1, factors);
  214. }
  215. const int fftSize;
  216. const bool inverse;
  217. struct Factor { int radix, length; };
  218. Factor factors[32];
  219. HeapBlock<Complex<float>> twiddleTable;
  220. void perform (const Complex<float>* input, Complex<float>* output, int stride, int strideIn, const Factor* facs) const noexcept
  221. {
  222. auto factor = *facs++;
  223. auto* originalOutput = output;
  224. auto* outputEnd = output + factor.radix * factor.length;
  225. if (stride == 1 && factor.radix <= 5)
  226. {
  227. for (int i = 0; i < factor.radix; ++i)
  228. perform (input + stride * strideIn * i, output + i * factor.length, stride * factor.radix, strideIn, facs);
  229. butterfly (factor, output, stride);
  230. return;
  231. }
  232. if (factor.length == 1)
  233. {
  234. do
  235. {
  236. *output++ = *input;
  237. input += stride * strideIn;
  238. }
  239. while (output < outputEnd);
  240. }
  241. else
  242. {
  243. do
  244. {
  245. perform (input, output, stride * factor.radix, strideIn, facs);
  246. input += stride * strideIn;
  247. output += factor.length;
  248. }
  249. while (output < outputEnd);
  250. }
  251. butterfly (factor, originalOutput, stride);
  252. }
  253. void butterfly (const Factor factor, Complex<float>* data, int stride) const noexcept
  254. {
  255. switch (factor.radix)
  256. {
  257. case 1: break;
  258. case 2: butterfly2 (data, stride, factor.length); return;
  259. case 4: butterfly4 (data, stride, factor.length); return;
  260. default: jassertfalse; break;
  261. }
  262. auto* scratch = static_cast<Complex<float>*> (alloca (sizeof (Complex<float>) * (size_t) factor.radix));
  263. for (int i = 0; i < factor.length; ++i)
  264. {
  265. for (int k = i, q1 = 0; q1 < factor.radix; ++q1)
  266. {
  267. scratch[q1] = data[k];
  268. k += factor.length;
  269. }
  270. for (int k = i, q1 = 0; q1 < factor.radix; ++q1)
  271. {
  272. int twiddleIndex = 0;
  273. data[k] = scratch[0];
  274. for (int q = 1; q < factor.radix; ++q)
  275. {
  276. twiddleIndex += stride * k;
  277. if (twiddleIndex >= fftSize)
  278. twiddleIndex -= fftSize;
  279. data[k] += scratch[q] * twiddleTable[twiddleIndex];
  280. }
  281. k += factor.length;
  282. }
  283. }
  284. }
  285. void butterfly2 (Complex<float>* data, const int stride, const int length) const noexcept
  286. {
  287. auto* dataEnd = data + length;
  288. auto* tw = twiddleTable.getData();
  289. for (int i = length; --i >= 0;)
  290. {
  291. auto s = *dataEnd;
  292. s *= (*tw);
  293. tw += stride;
  294. *dataEnd++ = *data - s;
  295. *data++ += s;
  296. }
  297. }
  298. void butterfly4 (Complex<float>* data, const int stride, const int length) const noexcept
  299. {
  300. auto lengthX2 = length * 2;
  301. auto lengthX3 = length * 3;
  302. auto strideX2 = stride * 2;
  303. auto strideX3 = stride * 3;
  304. auto* twiddle1 = twiddleTable.getData();
  305. auto* twiddle2 = twiddle1;
  306. auto* twiddle3 = twiddle1;
  307. for (int i = length; --i >= 0;)
  308. {
  309. auto s0 = data[length] * *twiddle1;
  310. auto s1 = data[lengthX2] * *twiddle2;
  311. auto s2 = data[lengthX3] * *twiddle3;
  312. auto s3 = s0; s3 += s2;
  313. auto s4 = s0; s4 -= s2;
  314. auto s5 = *data; s5 -= s1;
  315. *data += s1;
  316. data[lengthX2] = *data;
  317. data[lengthX2] -= s3;
  318. twiddle1 += stride;
  319. twiddle2 += strideX2;
  320. twiddle3 += strideX3;
  321. *data += s3;
  322. if (inverse)
  323. {
  324. data[length].real (s5.real() - s4.imag());
  325. data[length].imag (s5.imag() + s4.real());
  326. data[lengthX3].real (s5.real() + s4.imag());
  327. data[lengthX3].imag (s5.imag() - s4.real());
  328. }
  329. else
  330. {
  331. data[length].real (s5.real() + s4.imag());
  332. data[length].imag (s5.imag() - s4.real());
  333. data[lengthX3].real (s5.real() - s4.imag());
  334. data[lengthX3].imag (s5.imag() + s4.real());
  335. }
  336. ++data;
  337. }
  338. }
  339. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FFTConfig)
  340. };
  341. //==============================================================================
  342. SpinLock processLock;
  343. ScopedPointer<FFTConfig> configForward, configInverse;
  344. int size;
  345. };
  346. FFT::EngineImpl<FFTFallback> fftFallback;
  347. //==============================================================================
  348. //==============================================================================
  349. #if (JUCE_MAC || JUCE_IOS) && JUCE_USE_VDSP_FRAMEWORK
  350. struct AppleFFT : public FFT::Instance
  351. {
  352. static constexpr int priority = 5;
  353. static AppleFFT* create (int order)
  354. {
  355. return new AppleFFT (order);
  356. }
  357. AppleFFT (int orderToUse)
  358. : order (static_cast<vDSP_Length> (orderToUse)),
  359. fftSetup (vDSP_create_fftsetup (order, 2)),
  360. forwardNormalisation (.5f),
  361. inverseNormalisation (1.0f / static_cast<float> (1 << order))
  362. {}
  363. ~AppleFFT() override
  364. {
  365. if (fftSetup != nullptr)
  366. {
  367. vDSP_destroy_fftsetup (fftSetup);
  368. fftSetup = nullptr;
  369. }
  370. }
  371. void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept override
  372. {
  373. auto size = (1 << order);
  374. DSPSplitComplex splitInput (toSplitComplex (const_cast<Complex<float>*> (input)));
  375. DSPSplitComplex splitOutput (toSplitComplex (output));
  376. vDSP_fft_zop (fftSetup, &splitInput, 2, &splitOutput, 2,
  377. order, inverse ? kFFTDirection_Inverse : kFFTDirection_Forward);
  378. float factor = (inverse ? inverseNormalisation : forwardNormalisation * 2.0f);
  379. vDSP_vsmul ((float*) output, 1, &factor, (float*) output, 1, static_cast<size_t> (size << 1));
  380. }
  381. void performRealOnlyForwardTransform (float* inoutData, bool ignoreNegativeFreqs) const noexcept override
  382. {
  383. auto size = (1 << order);
  384. auto* inout = reinterpret_cast<Complex<float>*> (inoutData);
  385. auto splitInOut (toSplitComplex (inout));
  386. inoutData[size] = 0.0f;
  387. vDSP_fft_zrip (fftSetup, &splitInOut, 2, order, kFFTDirection_Forward);
  388. vDSP_vsmul (inoutData, 1, &forwardNormalisation, inoutData, 1, static_cast<size_t> (size << 1));
  389. mirrorResult (inout, ignoreNegativeFreqs);
  390. }
  391. void performRealOnlyInverseTransform (float* inoutData) const noexcept override
  392. {
  393. auto* inout = reinterpret_cast<Complex<float>*> (inoutData);
  394. auto size = (1 << order);
  395. auto splitInOut (toSplitComplex (inout));
  396. // Imaginary part of nyquist and DC frequencies are always zero
  397. // so Apple uses the imaginary part of the DC frequency to store
  398. // the real part of the nyquist frequency
  399. if (size != 1)
  400. inout[0] = Complex<float> (inout[0].real(), inout[size >> 1].real());
  401. vDSP_fft_zrip (fftSetup, &splitInOut, 2, order, kFFTDirection_Inverse);
  402. vDSP_vsmul (inoutData, 1, &inverseNormalisation, inoutData, 1, static_cast<size_t> (size << 1));
  403. vDSP_vclr (inoutData + size, 1, static_cast<size_t> (size));
  404. }
  405. private:
  406. //==============================================================================
  407. void mirrorResult (Complex<float>* out, bool ignoreNegativeFreqs) const noexcept
  408. {
  409. auto size = (1 << order);
  410. auto i = size >> 1;
  411. // Imaginary part of nyquist and DC frequencies are always zero
  412. // so Apple uses the imaginary part of the DC frequency to store
  413. // the real part of the nyquist frequency
  414. out[i++] = { out[0].imag(), 0.0 };
  415. out[0] = { out[0].real(), 0.0 };
  416. if (! ignoreNegativeFreqs)
  417. for (; i < size; ++i)
  418. out[i] = std::conj (out[size - i]);
  419. }
  420. static DSPSplitComplex toSplitComplex (Complex<float>* data) noexcept
  421. {
  422. // this assumes that Complex interleaves real and imaginary parts
  423. // and is tightly packed.
  424. return { reinterpret_cast<float*> (data),
  425. reinterpret_cast<float*> (data) + 1};
  426. }
  427. //==============================================================================
  428. vDSP_Length order;
  429. FFTSetup fftSetup;
  430. float forwardNormalisation, inverseNormalisation;
  431. };
  432. FFT::EngineImpl<AppleFFT> appleFFT;
  433. #endif
  434. //==============================================================================
  435. //==============================================================================
  436. #if JUCE_DSP_USE_SHARED_FFTW || JUCE_DSP_USE_STATIC_FFTW
  437. #if JUCE_DSP_USE_STATIC_FFTW
  438. extern "C"
  439. {
  440. void* fftwf_plan_dft_1d (int, void*, void*, int, int);
  441. void* fftwf_plan_dft_r2c_1d (int, void*, void*, int);
  442. void* fftwf_plan_dft_c2r_1d (int, void*, void*, int);
  443. void fftwf_destroy_plan (void*);
  444. void fftwf_execute_dft (void*, void*, void*);
  445. void fftwf_execute_dft_r2c (void*, void*, void*);
  446. void fftwf_execute_dft_c2r (void*, void*, void*);
  447. }
  448. #endif
  449. struct FFTWImpl : public FFT::Instance
  450. {
  451. #if JUCE_DSP_USE_STATIC_FFTW
  452. // if the JUCE developer has gone through the hassle of statically
  453. // linking in fftw, they probably want to use it
  454. static constexpr int priority = 10;
  455. #else
  456. static constexpr int priority = 3;
  457. #endif
  458. struct FFTWPlan;
  459. using FFTWPlanRef = FFTWPlan*;
  460. enum
  461. {
  462. measure = 0,
  463. unaligned = (1 << 1),
  464. estimate = (1 << 6)
  465. };
  466. struct Symbols
  467. {
  468. FFTWPlanRef (*plan_dft_fftw) (unsigned, Complex<float>*, Complex<float>*, int, unsigned);
  469. FFTWPlanRef (*plan_r2c_fftw) (unsigned, float*, Complex<float>*, unsigned);
  470. FFTWPlanRef (*plan_c2r_fftw) (unsigned, Complex<float>*, float*, unsigned);
  471. void (*destroy_fftw) (FFTWPlanRef);
  472. void (*execute_dft_fftw) (FFTWPlanRef, const Complex<float>*, Complex<float>*);
  473. void (*execute_r2c_fftw) (FFTWPlanRef, float*, Complex<float>*);
  474. void (*execute_c2r_fftw) (FFTWPlanRef, Complex<float>*, float*);
  475. #if JUCE_DSP_USE_STATIC_FFTW
  476. template <typename FuncPtr, typename ActualSymbolType>
  477. static bool symbol (FuncPtr& dst, ActualSymbolType sym)
  478. {
  479. dst = reinterpret_cast<FuncPtr> (sym);
  480. return true;
  481. }
  482. #else
  483. template <typename FuncPtr>
  484. static bool symbol (DynamicLibrary& lib, FuncPtr& dst, const char* name)
  485. {
  486. dst = reinterpret_cast<FuncPtr> (lib.getFunction (name));
  487. return (dst != nullptr);
  488. }
  489. #endif
  490. };
  491. static FFTWImpl* create (int order)
  492. {
  493. DynamicLibrary lib;
  494. #if ! JUCE_DSP_USE_STATIC_FFTW
  495. #if JUCE_MAC
  496. const char* libsuffix = "dylib";
  497. #elif JUCE_WINDOWS
  498. const char* libsuffix = "dll";
  499. #else
  500. const char* libsuffix = "so";
  501. #endif
  502. if (lib.open (String ("libfftw3f.") + libsuffix))
  503. #endif
  504. {
  505. Symbols symbols;
  506. #if JUCE_DSP_USE_STATIC_FFTW
  507. if (! Symbols::symbol (symbols.plan_dft_fftw, fftwf_plan_dft_1d)) return nullptr;
  508. if (! Symbols::symbol (symbols.plan_r2c_fftw, fftwf_plan_dft_r2c_1d)) return nullptr;
  509. if (! Symbols::symbol (symbols.plan_c2r_fftw, fftwf_plan_dft_c2r_1d)) return nullptr;
  510. if (! Symbols::symbol (symbols.destroy_fftw, fftwf_destroy_plan)) return nullptr;
  511. if (! Symbols::symbol (symbols.execute_dft_fftw, fftwf_execute_dft)) return nullptr;
  512. if (! Symbols::symbol (symbols.execute_r2c_fftw, fftwf_execute_dft_r2c)) return nullptr;
  513. if (! Symbols::symbol (symbols.execute_c2r_fftw, fftwf_execute_dft_c2r)) return nullptr;
  514. #else
  515. if (! Symbols::symbol (lib, symbols.plan_dft_fftw, "fftwf_plan_dft_1d")) return nullptr;
  516. if (! Symbols::symbol (lib, symbols.plan_r2c_fftw, "fftwf_plan_dft_r2c_1d")) return nullptr;
  517. if (! Symbols::symbol (lib, symbols.plan_c2r_fftw, "fftwf_plan_dft_c2r_1d")) return nullptr;
  518. if (! Symbols::symbol (lib, symbols.destroy_fftw, "fftwf_destroy_plan")) return nullptr;
  519. if (! Symbols::symbol (lib, symbols.execute_dft_fftw, "fftwf_execute_dft")) return nullptr;
  520. if (! Symbols::symbol (lib, symbols.execute_r2c_fftw, "fftwf_execute_dft_r2c")) return nullptr;
  521. if (! Symbols::symbol (lib, symbols.execute_c2r_fftw, "fftwf_execute_dft_c2r")) return nullptr;
  522. #endif
  523. return new FFTWImpl (static_cast<size_t> (order), static_cast<DynamicLibrary&&> (lib), symbols);
  524. }
  525. return nullptr;
  526. }
  527. FFTWImpl (size_t orderToUse, DynamicLibrary&& libraryToUse, const Symbols& symbols)
  528. : fftwLibrary (std::move (libraryToUse)), fftw (symbols), order (static_cast<size_t> (orderToUse))
  529. {
  530. auto n = (1u << order);
  531. HeapBlock<Complex<float>> in (n), out (n);
  532. c2cForward = fftw.plan_dft_fftw (n, in.getData(), out.getData(), -1, unaligned | estimate);
  533. c2cInverse = fftw.plan_dft_fftw (n, in.getData(), out.getData(), +1, unaligned | estimate);
  534. r2c = fftw.plan_r2c_fftw (n, (float*) in.getData(), in.getData(), unaligned | estimate);
  535. c2r = fftw.plan_c2r_fftw (n, in.getData(), (float*) in.getData(), unaligned | estimate);
  536. }
  537. ~FFTWImpl() override
  538. {
  539. fftw.destroy_fftw (c2cForward);
  540. fftw.destroy_fftw (c2cInverse);
  541. fftw.destroy_fftw (r2c);
  542. fftw.destroy_fftw (c2r);
  543. }
  544. void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept override
  545. {
  546. if (inverse)
  547. {
  548. auto n = (1u << order);
  549. fftw.execute_dft_fftw (c2cInverse, input, output);
  550. FloatVectorOperations::multiply ((float*) output, 1.0f / static_cast<float> (n), (int) n << 1);
  551. }
  552. else
  553. {
  554. fftw.execute_dft_fftw (c2cForward, input, output);
  555. }
  556. }
  557. void performRealOnlyForwardTransform (float* inputOutputData, bool ignoreNegativeFreqs) const noexcept override
  558. {
  559. if (order == 0)
  560. return;
  561. auto* out = reinterpret_cast<Complex<float>*> (inputOutputData);
  562. fftw.execute_r2c_fftw (r2c, inputOutputData, out);
  563. auto size = (1 << order);
  564. if (! ignoreNegativeFreqs)
  565. for (auto i = size >> 1; i < size; ++i)
  566. out[i] = std::conj (out[size - i]);
  567. }
  568. void performRealOnlyInverseTransform (float* inputOutputData) const noexcept override
  569. {
  570. auto n = (1u << order);
  571. fftw.execute_c2r_fftw (c2r, (Complex<float>*) inputOutputData, inputOutputData);
  572. FloatVectorOperations::multiply ((float*) inputOutputData, 1.0f / static_cast<float> (n), (int) n);
  573. }
  574. //==============================================================================
  575. DynamicLibrary fftwLibrary;
  576. Symbols fftw;
  577. size_t order;
  578. FFTWPlanRef c2cForward, c2cInverse, r2c, c2r;
  579. };
  580. FFT::EngineImpl<FFTWImpl> fftwEngine;
  581. #endif
  582. //==============================================================================
  583. //==============================================================================
  584. #if JUCE_DSP_USE_INTEL_MKL
  585. struct IntelFFT : public FFT::Instance
  586. {
  587. static constexpr int priority = 8;
  588. static bool succeeded (MKL_LONG status) noexcept { return status == 0; }
  589. static IntelFFT* create (int orderToUse)
  590. {
  591. DFTI_DESCRIPTOR_HANDLE mklc2c, mklc2r;
  592. if (DftiCreateDescriptor (&mklc2c, DFTI_SINGLE, DFTI_COMPLEX, 1, 1 << orderToUse) == 0)
  593. {
  594. if (succeeded (DftiSetValue (mklc2c, DFTI_PLACEMENT, DFTI_NOT_INPLACE))
  595. && succeeded (DftiSetValue (mklc2c, DFTI_BACKWARD_SCALE, 1.0f / static_cast<float> (1 << orderToUse)))
  596. && succeeded (DftiCommitDescriptor (mklc2c)))
  597. {
  598. if (succeeded (DftiCreateDescriptor (&mklc2r, DFTI_SINGLE, DFTI_REAL, 1, 1 << orderToUse)))
  599. {
  600. if (succeeded (DftiSetValue (mklc2r, DFTI_PLACEMENT, DFTI_INPLACE))
  601. && succeeded (DftiSetValue (mklc2r, DFTI_BACKWARD_SCALE, 1.0f / static_cast<float> (1 << orderToUse)))
  602. && succeeded (DftiCommitDescriptor (mklc2r)))
  603. {
  604. return new IntelFFT (static_cast<size_t> (orderToUse), mklc2c, mklc2r);
  605. }
  606. DftiFreeDescriptor (&mklc2r);
  607. }
  608. }
  609. DftiFreeDescriptor (&mklc2c);
  610. }
  611. return {};
  612. }
  613. IntelFFT (size_t orderToUse, DFTI_DESCRIPTOR_HANDLE c2cToUse, DFTI_DESCRIPTOR_HANDLE cr2ToUse)
  614. : order (orderToUse), c2c (c2cToUse), c2r (cr2ToUse)
  615. {}
  616. ~IntelFFT()
  617. {
  618. DftiFreeDescriptor (&c2c);
  619. DftiFreeDescriptor (&c2r);
  620. }
  621. void perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept override
  622. {
  623. if (inverse)
  624. DftiComputeBackward (c2c, (void*) input, output);
  625. else
  626. DftiComputeForward (c2c, (void*) input, output);
  627. }
  628. void performRealOnlyForwardTransform (float* inputOutputData, bool ignoreNegativeFreqs) const noexcept override
  629. {
  630. if (order == 0)
  631. return;
  632. DftiComputeForward (c2r, inputOutputData);
  633. auto* out = reinterpret_cast<Complex<float>*> (inputOutputData);
  634. auto size = (1 << order);
  635. if (! ignoreNegativeFreqs)
  636. for (auto i = size >> 1; i < size; ++i)
  637. out[i] = std::conj (out[size - i]);
  638. }
  639. void performRealOnlyInverseTransform (float* inputOutputData) const noexcept override
  640. {
  641. DftiComputeBackward (c2r, inputOutputData);
  642. }
  643. size_t order;
  644. DFTI_DESCRIPTOR_HANDLE c2c, c2r;
  645. };
  646. FFT::EngineImpl<IntelFFT> fftwEngine;
  647. #endif
  648. //==============================================================================
  649. //==============================================================================
  650. FFT::FFT (int order)
  651. : engine (FFT::Engine::createBestEngineForPlatform (order)),
  652. size (1 << order)
  653. {}
  654. FFT::~FFT() {}
  655. void FFT::perform (const Complex<float>* input, Complex<float>* output, bool inverse) const noexcept
  656. {
  657. if (engine != nullptr)
  658. engine->perform (input, output, inverse);
  659. }
  660. void FFT::performRealOnlyForwardTransform (float* inputOutputData, bool ignoreNeagtiveFreqs) const noexcept
  661. {
  662. if (engine != nullptr)
  663. engine->performRealOnlyForwardTransform (inputOutputData, ignoreNeagtiveFreqs);
  664. }
  665. void FFT::performRealOnlyInverseTransform (float* inputOutputData) const noexcept
  666. {
  667. if (engine != nullptr)
  668. engine->performRealOnlyInverseTransform (inputOutputData);
  669. }
  670. void FFT::performFrequencyOnlyForwardTransform (float* inputOutputData) const noexcept
  671. {
  672. if (size == 1)
  673. return;
  674. performRealOnlyForwardTransform (inputOutputData);
  675. auto* out = reinterpret_cast<Complex<float>*> (inputOutputData);
  676. for (auto i = 0; i < size; ++i)
  677. inputOutputData[i] = std::abs (out[i]);
  678. zeromem (&inputOutputData[size], sizeof (float) * static_cast<size_t> (size));
  679. }