FFTRealPassDirect.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*****************************************************************************
  2. FFTRealPassDirect.hpp
  3. By Laurent de Soras
  4. --- Legal stuff ---
  5. This program is free software. It comes without any warranty, to
  6. the extent permitted by applicable law. You can redistribute it
  7. and/or modify it under the terms of the Do What The Fuck You Want
  8. To Public License, Version 2, as published by Sam Hocevar. See
  9. http://sam.zoy.org/wtfpl/COPYING for more details.
  10. *Tab=3***********************************************************************/
  11. #if defined (ffft_FFTRealPassDirect_CURRENT_CODEHEADER)
  12. #error Recursive inclusion of FFTRealPassDirect code header.
  13. #endif
  14. #define ffft_FFTRealPassDirect_CURRENT_CODEHEADER
  15. #if ! defined (ffft_FFTRealPassDirect_CODEHEADER_INCLUDED)
  16. #define ffft_FFTRealPassDirect_CODEHEADER_INCLUDED
  17. /*\\\ INCLUDE FILES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  18. #include "ffft/FFTRealUseTrigo.h"
  19. namespace ffft
  20. {
  21. /*\\\ PUBLIC \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  22. template <>
  23. inline void FFTRealPassDirect <1>::process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list [])
  24. {
  25. // First and second pass at once
  26. const long qlen = len >> 2;
  27. long coef_index = 0;
  28. do
  29. {
  30. // To do: unroll the loop (2x).
  31. const long ri_0 = br_ptr [coef_index >> 2];
  32. const long ri_1 = ri_0 + 2 * qlen; // bit_rev_lut_ptr [coef_index + 1];
  33. const long ri_2 = ri_0 + 1 * qlen; // bit_rev_lut_ptr [coef_index + 2];
  34. const long ri_3 = ri_0 + 3 * qlen; // bit_rev_lut_ptr [coef_index + 3];
  35. DataType * const df2 = dest_ptr + coef_index;
  36. df2 [1] = x_ptr [ri_0] - x_ptr [ri_1];
  37. df2 [3] = x_ptr [ri_2] - x_ptr [ri_3];
  38. const DataType sf_0 = x_ptr [ri_0] + x_ptr [ri_1];
  39. const DataType sf_2 = x_ptr [ri_2] + x_ptr [ri_3];
  40. df2 [0] = sf_0 + sf_2;
  41. df2 [2] = sf_0 - sf_2;
  42. coef_index += 4;
  43. }
  44. while (coef_index < len);
  45. }
  46. template <>
  47. inline void FFTRealPassDirect <2>::process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list [])
  48. {
  49. // Executes "previous" passes first. Inverts source and destination buffers
  50. FFTRealPassDirect <1>::process (
  51. len,
  52. src_ptr,
  53. dest_ptr,
  54. x_ptr,
  55. cos_ptr,
  56. cos_len,
  57. br_ptr,
  58. osc_list
  59. );
  60. // Third pass
  61. const DataType sqrt2_2 = DataType (SQRT2 * 0.5);
  62. long coef_index = 0;
  63. do
  64. {
  65. dest_ptr [coef_index ] = src_ptr [coef_index] + src_ptr [coef_index + 4];
  66. dest_ptr [coef_index + 4] = src_ptr [coef_index] - src_ptr [coef_index + 4];
  67. dest_ptr [coef_index + 2] = src_ptr [coef_index + 2];
  68. dest_ptr [coef_index + 6] = src_ptr [coef_index + 6];
  69. DataType v;
  70. v = (src_ptr [coef_index + 5] - src_ptr [coef_index + 7]) * sqrt2_2;
  71. dest_ptr [coef_index + 1] = src_ptr [coef_index + 1] + v;
  72. dest_ptr [coef_index + 3] = src_ptr [coef_index + 1] - v;
  73. v = (src_ptr [coef_index + 5] + src_ptr [coef_index + 7]) * sqrt2_2;
  74. dest_ptr [coef_index + 5] = v + src_ptr [coef_index + 3];
  75. dest_ptr [coef_index + 7] = v - src_ptr [coef_index + 3];
  76. coef_index += 8;
  77. }
  78. while (coef_index < len);
  79. }
  80. template <int PASS>
  81. void FFTRealPassDirect <PASS>::process (long len, DataType dest_ptr [], DataType src_ptr [], const DataType x_ptr [], const DataType cos_ptr [], long cos_len, const long br_ptr [], OscType osc_list [])
  82. {
  83. // Executes "previous" passes first. Inverts source and destination buffers
  84. FFTRealPassDirect <PASS - 1>::process (
  85. len,
  86. src_ptr,
  87. dest_ptr,
  88. x_ptr,
  89. cos_ptr,
  90. cos_len,
  91. br_ptr,
  92. osc_list
  93. );
  94. const long dist = 1L << (PASS - 1);
  95. const long c1_r = 0;
  96. const long c1_i = dist;
  97. const long c2_r = dist * 2;
  98. const long c2_i = dist * 3;
  99. const long cend = dist * 4;
  100. const long table_step = cos_len >> (PASS - 1);
  101. enum { TRIGO_OSC = PASS - FFTRealFixLenParam::TRIGO_BD_LIMIT };
  102. enum { TRIGO_DIRECT = (TRIGO_OSC >= 0) ? 1 : 0 };
  103. long coef_index = 0;
  104. do
  105. {
  106. const DataType * const sf = src_ptr + coef_index;
  107. DataType * const df = dest_ptr + coef_index;
  108. // Extreme coefficients are always real
  109. df [c1_r] = sf [c1_r] + sf [c2_r];
  110. df [c2_r] = sf [c1_r] - sf [c2_r];
  111. df [c1_i] = sf [c1_i];
  112. df [c2_i] = sf [c2_i];
  113. FFTRealUseTrigo <TRIGO_DIRECT>::prepare (osc_list [TRIGO_OSC]);
  114. // Others are conjugate complex numbers
  115. for (long i = 1; i < dist; ++ i)
  116. {
  117. DataType c;
  118. DataType s;
  119. FFTRealUseTrigo <TRIGO_DIRECT>::iterate (
  120. osc_list [TRIGO_OSC],
  121. c,
  122. s,
  123. cos_ptr,
  124. i * table_step,
  125. (dist - i) * table_step
  126. );
  127. const DataType sf_r_i = sf [c1_r + i];
  128. const DataType sf_i_i = sf [c1_i + i];
  129. const DataType v1 = sf [c2_r + i] * c - sf [c2_i + i] * s;
  130. df [c1_r + i] = sf_r_i + v1;
  131. df [c2_r - i] = sf_r_i - v1;
  132. const DataType v2 = sf [c2_r + i] * s + sf [c2_i + i] * c;
  133. df [c2_r + i] = v2 + sf_i_i;
  134. df [cend - i] = v2 - sf_i_i;
  135. }
  136. coef_index += cend;
  137. }
  138. while (coef_index < len);
  139. }
  140. /*\\\ PROTECTED \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  141. /*\\\ PRIVATE \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
  142. } // namespace ffft
  143. #endif // ffft_FFTRealPassDirect_CODEHEADER_INCLUDED
  144. #undef ffft_FFTRealPassDirect_CURRENT_CODEHEADER
  145. /*\\\ EOF \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/