fft_data.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #ifndef MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_
  11. #define MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_
  12. // Defines WEBRTC_ARCH_X86_FAMILY, used below.
  13. #include "rtc_base/system/arch.h"
  14. #if defined(WEBRTC_ARCH_X86_FAMILY)
  15. #include <emmintrin.h>
  16. #endif
  17. #include <algorithm>
  18. #include <array>
  19. #include "api/array_view.h"
  20. #include "modules/audio_processing/aec3/aec3_common.h"
  21. namespace webrtc {
  22. // Struct that holds imaginary data produced from 128 point real-valued FFTs.
  23. struct FftData {
  24. // Copies the data in src.
  25. void Assign(const FftData& src) {
  26. std::copy(src.re.begin(), src.re.end(), re.begin());
  27. std::copy(src.im.begin(), src.im.end(), im.begin());
  28. im[0] = im[kFftLengthBy2] = 0;
  29. }
  30. // Clears all the imaginary.
  31. void Clear() {
  32. re.fill(0.f);
  33. im.fill(0.f);
  34. }
  35. // Computes the power spectrum of the data.
  36. void SpectrumAVX2(rtc::ArrayView<float> power_spectrum) const;
  37. // Computes the power spectrum of the data.
  38. void Spectrum(Aec3Optimization optimization,
  39. rtc::ArrayView<float> power_spectrum) const {
  40. RTC_DCHECK_EQ(kFftLengthBy2Plus1, power_spectrum.size());
  41. switch (optimization) {
  42. #if defined(WEBRTC_ARCH_X86_FAMILY)
  43. case Aec3Optimization::kSse2: {
  44. constexpr int kNumFourBinBands = kFftLengthBy2 / 4;
  45. constexpr int kLimit = kNumFourBinBands * 4;
  46. for (size_t k = 0; k < kLimit; k += 4) {
  47. const __m128 r = _mm_loadu_ps(&re[k]);
  48. const __m128 i = _mm_loadu_ps(&im[k]);
  49. const __m128 ii = _mm_mul_ps(i, i);
  50. const __m128 rr = _mm_mul_ps(r, r);
  51. const __m128 rrii = _mm_add_ps(rr, ii);
  52. _mm_storeu_ps(&power_spectrum[k], rrii);
  53. }
  54. power_spectrum[kFftLengthBy2] = re[kFftLengthBy2] * re[kFftLengthBy2] +
  55. im[kFftLengthBy2] * im[kFftLengthBy2];
  56. } break;
  57. case Aec3Optimization::kAvx2:
  58. SpectrumAVX2(power_spectrum);
  59. break;
  60. #endif
  61. default:
  62. std::transform(re.begin(), re.end(), im.begin(), power_spectrum.begin(),
  63. [](float a, float b) { return a * a + b * b; });
  64. }
  65. }
  66. // Copy the data from an interleaved array.
  67. void CopyFromPackedArray(const std::array<float, kFftLength>& v) {
  68. re[0] = v[0];
  69. re[kFftLengthBy2] = v[1];
  70. im[0] = im[kFftLengthBy2] = 0;
  71. for (size_t k = 1, j = 2; k < kFftLengthBy2; ++k) {
  72. re[k] = v[j++];
  73. im[k] = v[j++];
  74. }
  75. }
  76. // Copies the data into an interleaved array.
  77. void CopyToPackedArray(std::array<float, kFftLength>* v) const {
  78. RTC_DCHECK(v);
  79. (*v)[0] = re[0];
  80. (*v)[1] = re[kFftLengthBy2];
  81. for (size_t k = 1, j = 2; k < kFftLengthBy2; ++k) {
  82. (*v)[j++] = re[k];
  83. (*v)[j++] = im[k];
  84. }
  85. }
  86. std::array<float, kFftLengthBy2Plus1> re;
  87. std::array<float, kFftLengthBy2Plus1> im;
  88. };
  89. } // namespace webrtc
  90. #endif // MODULES_AUDIO_PROCESSING_AEC3_FFT_DATA_H_