• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FFT_H
17 #define FFT_H
18 
19 #include "utils.h"
20 
21 namespace OHOS {
22 namespace Sensors {
23 /**
24  * @brief The parameters and calculation results used in FFT.
25  *   Used to encapsulate 6 parameters in the AlgFFT function.
26  */
27 struct FftParaAndResult {
28     /** Number of samples */
29     int32_t numSamples { 0 };
30     /** The real part of the input */
31     std::vector<float> realIn;
32     /** The imaginary part of the input */
33     std::vector<float> imagIn;
34     /** The real part of the output */
35     std::vector<float> realOut;
36     /** The imaginary part of the output */
37     std::vector<float> imagOut;
38 
39     FftParaAndResult() = default;
FftParaAndResultFftParaAndResult40     explicit FftParaAndResult(int32_t size)
41     {
42         numSamples = size;
43         realIn.resize(size, 0.0F);
44         imagIn.resize(size, 0.0F);
45         realOut.resize(size, 0.0F);
46         imagOut.resize(size, 0.0F);
47     }
48 };
49 
50 class Fft {
51 public:
52     Fft() = default;
53     ~Fft();
54 
55     void Init(int32_t fftSize);
56 
57     std::vector<float> GetReal() const;
58     std::vector<float> GetImg() const;
59 
60     /* Calculate the power spectrum */
61     void CalcFFT(const std::vector<float> &data, const std::vector<float> &window);
62     void ConvertPolar(std::vector<float> &magnitude, std::vector<float> &phase);
63     void CalculatePowerSpectrum(const std::vector<float> &data, const std::vector<float> &window,
64         std::vector<float> &magnitude, std::vector<float> &phase);
65     /** the inverse */
66     void ConvertCart(const std::vector<float> &magnitude, const std::vector<float> &phase);
67     void CalcIFFT(const std::vector<float> &window, std::vector<float> &finalOut);
68     void InverseFFTComplex(const std::vector<float> &window, const std::vector<float> &real,
69         const std::vector<float> &imaginary, std::vector<float> &finalOut);
70     void InversePowerSpectrum(const std::vector<float> &window, const std::vector<float> &magnitude,
71         const std::vector<float> &phase, std::vector<float> &finalOut);
72     void ConvertDB(const std::vector<float> &in, std::vector<float> &out);
73     int32_t GenWindow(int32_t whichFunction, int32_t numSamples, std::vector<float> &window);
74 
75 private:
76     int32_t WindowFunc(int32_t whichFunction, int32_t numSamples, float *out);
77     uint32_t FastReverseBits(uint32_t pos, uint32_t numBits);
78 
79     /**
80      * @brief Power Spectrum
81      *
82      * 1. This function computes the same as AlgRealFFT, above, but adds the squares of the real and imaginary part
83      *  of each coefficient, extracting the power and throwing away the phase.
84      * 2. For speed, it does not call AlgRealFFT, but duplicates some of its code.
85      *
86      * @param numSamples Number of samples.
87      * @param in The part of the input.
88      * @param out The part of the output
89      *
90      * @return Returns <b>0</b> if the operation is successful; returns a negative value otherwise.
91      */
92     int32_t AlgPowerSpectrum(int32_t numSamples, const std::vector<float> &in, std::vector<float> &out);
93 
94     /**
95      * @brief Real Fast Fourier Transform
96      *
97      * 1. This function was based on the code in Numerical Recipes in C.
98      * 2.In Num. Rec., the inner loop is based on a single 1-based array of interleaved real and imaginary numbers.
99      *   Because we have two separate zero-based arrays, our indices are quite different.
100      * 3. Here is the correspondence between Num. Rec.
101      *
102      * @return Returns <b>0</b> if the operation is successful; returns a negative value otherwise.
103      */
104     int32_t AlgRealFFT(FftParaAndResult &paraRes);
105     int32_t AlgFFT(bool inverseTransform, FftParaAndResult &paraRes);
106     int32_t AlgInitFFT();
107 
108 private:
109     /** fftSize */
110     int32_t fftSize_ { 0 };
111     /** halfFFTSize */
112     int32_t half_ { 0 };
113 
114     FftParaAndResult fftParaRes_;
115     /**
116      * 'para_' needs to be created every time the sfft occurs, so it is created once during initialization.
117      * It's half the size of fftParaRes_, only used in one function.
118      */
119     FftParaAndResult para_;
120     uint32_t** fftBitTable_ { nullptr };
121 };
122 } // namespace Sensors
123 } // namespace OHOS
124 #endif // FFT_H