1/*
2Copyright 2018 Google Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS-IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef RESONANCE_AUDIO_DSP_FFT_MANAGER_H_
18#define RESONANCE_AUDIO_DSP_FFT_MANAGER_H_
19
20#include "pffft.h"
21#include "base/audio_buffer.h"
22
23namespace vraudio {
24
25// This class wraps the pffft library and enables reall FFT transformations to
26// be performed on aligned float buffers of data. The class also manages all
27// necessary data buffers and zero padding. This class is not thread safe.
28class FftManager {
29 public:
30 // Minimum required FFT size.
31 static const size_t kMinFftSize;
32
33 // Constructs a FftManager insatnce. One instance of this class can be shared.
34 // This class is not thread safe.
35 //
36 // @param frames_per_buffer System's number of frames per buffer.
37 explicit FftManager(size_t frames_per_buffer);
38
39 // Destroys a FftManager instance freeing associated aligned memory.
40 ~FftManager();
41
42 // Transforms a single channel of time domain input data into a frequency
43 // domain representation.
44 //
45 // @param time_channel Time domain input. If the length is less than
46 // |fft_size_|, the input is zeropadded. The max length is |fft_size_|.
47 // @param freq_channel Frequency domain output, |fft_size| samples long.
48 void FreqFromTimeDomain(const AudioBuffer::Channel& time_channel,
49 AudioBuffer::Channel* freq_channel);
50
51 // Transforms a single channel of frequency domain input data into a time
52 // domain representation. Note: The input must be in pffft format see:
53 // goo.gl/LYbgX7. This method can output to a buffer of either
54 // |frames_per_buffer_| or |fft_size_| in length. This feature ensures an
55 // additional copy is not needed where this method is to be used with an
56 // overlap add.
57 //
58 // @param freq_channel Frequency domain input, |fft_size| samples long.
59 // @param time_channel Time domain output, |frames_per_buffer_| samples long
60 // OR |fft_size_| samples long.
61 void TimeFromFreqDomain(const AudioBuffer::Channel& freq_channel,
62 AudioBuffer::Channel* time_channel);
63
64 // Applies a 1/|fft_size_| scaling to time domain output. NOTE this need not
65 // be applied where a convolution is taking place as the scaling will be
66 // included therein.
67 //
68 // @param time_channel Time domain data to be scaled.
69 void ApplyReverseFftScaling(AudioBuffer::Channel* time_channel);
70
71 // Transforms a pffft frequency domain format buffer into canonical format
72 // with alternating real and imaginary values with increasing frequency. The
73 // first two entries of |output| are the real part of the DC and Nyquist
74 // frequencies (imaginary part is zero). The alternating real and imaginary
75 // parts start from the third entry in |output|. For more info on the pffft
76 // format see: goo.gl/LYbgX7
77 //
78 // @param input Frequency domain input channel, |fft_size| samples long.
79 // @param output Frequency domain output channel,|fft_size| samples long.
80 void GetCanonicalFormatFreqBuffer(const AudioBuffer::Channel& input,
81 AudioBuffer::Channel* output);
82
83 // Transforms a canonical frequency domain format buffer into pffft format.
84 // For more info on the pffft format see: goo.gl/LYbgX7
85 //
86 // @param input Frequency domain input channel, |fft_size| samples long.
87 // @param output Frequency domain output channel, |fft_size| samples long.
88 void GetPffftFormatFreqBuffer(const AudioBuffer::Channel& input,
89 AudioBuffer::Channel* output);
90
91 // Genarates a buffer containing the single sided magnitude spectrum of a
92 // frequency domain buffer. The input must be in Canonical format. The output
93 // will have DC frequency as it's first entry and the Nyquist as it's last.
94 //
95 // @param freq_channel Canonical format frequency domain buffer,
96 // |fft_size_| samples long.
97 // @param magnitude_channel Magnitude of the |freq_channel|.
98 // |frames_per_buffer_| + 1 samples long.
99 void MagnitudeFromCanonicalFreqBuffer(
100 const AudioBuffer::Channel& freq_channel,
101 AudioBuffer::Channel* magnitude_channel);
102
103 // Combines single sided magnitude and phase spectra into a canonical format
104 // frequency domain buffer. The inputs must have DC frequency as their first
105 // entry and the Nyquist as their last.
106 //
107 // @param magnitude_channel Magnitude of the |frequency_buffer|.
108 // |frames_per_buffer_| + 1 samples long.
109 // @param phase_channel Phase of the |frequency_buffer|.
110 // |frames_per_buffer_| + 1 samples long.
111 // @param canonical_freq_channel Canonical format frequency domain buffer,
112 // |fft_size_| samples long.
113 void CanonicalFreqBufferFromMagnitudeAndPhase(
114 const AudioBuffer::Channel& magnitude_channel,
115 const AudioBuffer::Channel& phase_channel,
116 AudioBuffer::Channel* canonical_freq_channel);
117
118 // Combines single sided magnitude spectrum and the cosine and sine of a phase
119 // spectrum into a canonical format frequency domain buffer. The inputs must
120 // have DC frequency as their first entry and the Nyquist as their last.
121 // The phase spectra channels can be offset by |phase_offset|. This feature
122 // is specifically for use as an optimization in the |SpectralReverb|.
123 //
124 // @param phase_offset An offset into the channels of the phase buffer.
125 // @param magnitude_channel Magnitude of the |frequency_buffer|.
126 // |frames_per_buffer_| + 1 samples long.
127 // @param sin_phase_channel Sine of the phase of the |frequency_buffer|.
128 // |frames_per_buffer_| + 1 samples long.
129 // @param cos_phase_channel Cosine of the phase of the |frequency_buffer|.
130 // |frames_per_buffer_| + 1 samples long.
131 // @param canonical_freq_channel Canonical format frequency domain buffer,
132 // |fft_size_| samples long.
133 void CanonicalFreqBufferFromMagnitudeAndSinCosPhase(
134 size_t phase_offset, const AudioBuffer::Channel& magnitude_channel,
135 const AudioBuffer::Channel& sin_phase_channel,
136 const AudioBuffer::Channel& cos_phase_channel,
137 AudioBuffer::Channel* canonical_freq_channel);
138
139 // Performs a pointwise complex multiplication of two frequency domain buffers
140 // and applies tha inverse scaling factor of 1/|fft_size_|. This operation is
141 // equivalent to a time domain circular convolution.
142 //
143 // @param input_a Frequency domain input channel, |fft_size| samples long.
144 // @param input_b Frequency domain input channel, |fft_size| samples long.
145 // @param scaled_output Frequency domain output channel, |fft_size| samples
146 // long.
147 void FreqDomainConvolution(const AudioBuffer::Channel& input_a,
148 const AudioBuffer::Channel& input_b,
149 AudioBuffer::Channel* scaled_output);
150
151 // Returns the number of points in the FFT.
152 size_t GetFftSize() const { return fft_size_; }
153
154 private:
155 // FFT size in samples.
156 const size_t fft_size_;
157
158 // Number of frames in each buffer of input data.
159 const size_t frames_per_buffer_;
160
161 // Inverse scale to be applied to buffers transformed from frequency to time
162 // domain.
163 const float inverse_fft_scale_;
164
165 // Temporary time domain buffer to store zeropadded input.
166 AudioBuffer temp_zeropad_buffer_;
167
168 // Temporary freq domain buffer to store.
169 AudioBuffer temp_freq_buffer_;
170
171 // pffft states.
172 PFFFT_Setup* fft_;
173
174 // Workspace for pffft. This pointer should be set to null for |fft_size_|
175 // less than 2^14. In which case the stack is used. This is the recommendation
176 // by the author of the pffft library.
177 float* pffft_workspace_ = nullptr;
178};
179
180} // namespace vraudio
181
182#endif // RESONANCE_AUDIO_DSP_FFT_MANAGER_H_
183

source code of qtmultimedia/src/3rdparty/resonance-audio/resonance_audio/dsp/fft_manager.h