1 /*
2  *  Copyright (c) 2012 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 
11 #include "common_audio/signal_processing/include/real_fft.h"
12 
13 #include "common_audio/signal_processing/include/signal_processing_library.h"
14 #include "test/gtest.h"
15 
16 namespace webrtc {
17 namespace {
18 
19 // FFT order.
20 const int kOrder = 5;
21 // Lengths for real FFT's time and frequency bufffers.
22 // For N-point FFT, the length requirements from API are N and N+2 respectively.
23 const int kTimeDataLength = 1 << kOrder;
24 const int kFreqDataLength = (1 << kOrder) + 2;
25 // For complex FFT's time and freq buffer. The implementation requires
26 // 2*N 16-bit words.
27 const int kComplexFftDataLength = 2 << kOrder;
28 // Reference data for time signal.
29 const int16_t kRefData[kTimeDataLength] = {
30     11739,  6848,  -8688,  31980, -30295, 25242, 27085,  19410,
31     -26299, 15607, -10791, 11778, -23819, 14498, -25772, 10076,
32     1173,   6848,  -8688,  31980, -30295, 2522,  27085,  19410,
33     -2629,  5607,  -3,     1178,  -23819, 1498,  -25772, 10076};
34 
TEST(RealFFTTest,CreateFailsOnBadInput)35 TEST(RealFFTTest, CreateFailsOnBadInput) {
36   RealFFT* fft = WebRtcSpl_CreateRealFFT(11);
37   EXPECT_TRUE(fft == nullptr);
38   fft = WebRtcSpl_CreateRealFFT(-1);
39   EXPECT_TRUE(fft == nullptr);
40 }
41 
TEST(RealFFTTest,RealAndComplexMatch)42 TEST(RealFFTTest, RealAndComplexMatch) {
43   int i = 0;
44   int j = 0;
45   int16_t real_fft_time[kTimeDataLength] = {0};
46   int16_t real_fft_freq[kFreqDataLength] = {0};
47   // One common buffer for complex FFT's time and frequency data.
48   int16_t complex_fft_buff[kComplexFftDataLength] = {0};
49 
50   // Prepare the inputs to forward FFT's.
51   memcpy(real_fft_time, kRefData, sizeof(kRefData));
52   for (i = 0, j = 0; i < kTimeDataLength; i += 1, j += 2) {
53     complex_fft_buff[j] = kRefData[i];
54     complex_fft_buff[j + 1] = 0;  // Insert zero's to imaginary parts.
55   }
56 
57   // Create and run real forward FFT.
58   RealFFT* fft = WebRtcSpl_CreateRealFFT(kOrder);
59   EXPECT_TRUE(fft != nullptr);
60   EXPECT_EQ(0, WebRtcSpl_RealForwardFFT(fft, real_fft_time, real_fft_freq));
61 
62   // Run complex forward FFT.
63   WebRtcSpl_ComplexBitReverse(complex_fft_buff, kOrder);
64   EXPECT_EQ(0, WebRtcSpl_ComplexFFT(complex_fft_buff, kOrder, 1));
65 
66   // Verify the results between complex and real forward FFT.
67   for (i = 0; i < kFreqDataLength; i++) {
68     EXPECT_EQ(real_fft_freq[i], complex_fft_buff[i]);
69   }
70 
71   // Prepare the inputs to inverse real FFT.
72   // We use whatever data in complex_fft_buff[] since we don't care
73   // about data contents. Only kFreqDataLength 16-bit words are copied
74   // from complex_fft_buff to real_fft_freq since remaining words (2nd half)
75   // are conjugate-symmetric to the first half in theory.
76   memcpy(real_fft_freq, complex_fft_buff, sizeof(real_fft_freq));
77 
78   // Run real inverse FFT.
79   int real_scale = WebRtcSpl_RealInverseFFT(fft, real_fft_freq, real_fft_time);
80   EXPECT_GE(real_scale, 0);
81 
82   // Run complex inverse FFT.
83   WebRtcSpl_ComplexBitReverse(complex_fft_buff, kOrder);
84   int complex_scale = WebRtcSpl_ComplexIFFT(complex_fft_buff, kOrder, 1);
85 
86   // Verify the results between complex and real inverse FFT.
87   // They are not bit-exact, since complex IFFT doesn't produce
88   // exactly conjugate-symmetric data (between first and second half).
89   EXPECT_EQ(real_scale, complex_scale);
90   for (i = 0, j = 0; i < kTimeDataLength; i += 1, j += 2) {
91     EXPECT_LE(abs(real_fft_time[i] - complex_fft_buff[j]), 1);
92   }
93 
94   WebRtcSpl_FreeRealFFT(fft);
95 }
96 
97 }  // namespace
98 }  // namespace webrtc
99