tmp
[blender.git] / extern / audaspace / include / fx / FFTConvolver.h
1 /*******************************************************************************
2 * Copyright 2015-2016 Juan Francisco Crespo Gal├ín
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *   http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 ******************************************************************************/
16
17 #pragma once
18
19 /**
20 * @file FFTConvolver.h
21 * @ingroup fx
22 * The FFTConvolver class.
23 */
24
25 #include "IReader.h"
26 #include "ISound.h"
27 #include "util/FFTPlan.h"
28
29 #include <memory>
30 #include <vector>
31
32 AUD_NAMESPACE_BEGIN
33 /**
34 * This class allows to easily convolve a sound using the Fourier transform.
35 */
36 class AUD_API FFTConvolver
37 {
38 private:
39         /**
40         * A shared pointer to an FFT plan.
41         */
42         std::shared_ptr<FFTPlan> m_plan;
43
44         /**
45         * The FFT size, must be at least M+L-1.
46         */
47         int m_N;
48
49         /**
50         * The length of the impulse response.
51         */
52         int m_M;
53
54         /**
55         * The max length of the input slices.
56         */
57         int m_L;
58
59         /**
60         * The real length of the internal buffer in fftwf_complex elements.
61         */
62         int m_realBufLen;
63
64         /**
65         * The internal buffer for the FFTS.
66         */
67         std::complex<sample_t>* m_inBuffer;
68
69         /**
70         * A shift buffer for the FDL method
71         */
72         sample_t* m_shiftBuffer;
73
74         /**
75         * A buffer to store the extra data obtained after each partial convolution.
76         */
77         float* m_tail;
78
79         /**
80         * The provided impulse response.
81         */
82         std::shared_ptr<std::vector<std::complex<sample_t>>> m_irBuffer;
83
84         /**
85         * If the tail is being read, this marks the current position.
86         */
87         int m_tailPos;
88
89         // delete copy constructor and operator=
90         FFTConvolver(const FFTConvolver&) = delete;
91         FFTConvolver& operator=(const FFTConvolver&) = delete;
92
93 public:
94         /**
95         * Creates a new FFTConvolver.
96         * \param ir A shared pointer to a vector with the impulse response data in the frequency domain (see ImpulseResponse class for an easy way to obtain it).
97         * \param plan A shared pointer to and FFT plan.
98         */
99         FFTConvolver(std::shared_ptr<std::vector<std::complex<sample_t>>> ir, std::shared_ptr<FFTPlan> plan);
100         virtual ~FFTConvolver();
101
102         /**
103         * Convolves the data that is provided with the inpulse response.
104         * \param[in] inBuffer A buffer with the input data to be convolved.
105         * \param[in] outBuffer A pointer to the buffer in which the convolution result will be written.
106         * \param[in,out] length The number of samples to be convolved (the length of both the inBuffer and the outBuffer).
107         *                                               The convolution output should be larger than the input, but since this class uses the overlap
108         *                                               add method, the extra length will be saved internally.
109         *                                               It must be equal or lower than N/2 (N=size of the FFTPlan) or the call will fail, setting this variable to 0 since no data would be
110         *                                               written in the outBuffer.
111         */
112         void getNext(const sample_t* inBuffer, sample_t* outBuffer, int& length);
113
114         /**
115         * Convolves the data that is provided with the inpulse response.
116         * \param[in] inBuffer A buffer with the input data to be convolved.
117         * \param[in] outBuffer A pointer to the buffer in which the convolution result will be written.
118         * \param[in,out] length The number of samples to be convolved (the length of both the inBuffer and the outBuffer).
119         *                                               The convolution output should be larger than the input, but since this class uses the overlap
120         *                                               add method, the extra length will be saved internally.
121         *                                               It must be equal or lower than N/2 (N=size of the FFTPlan) or the call will fail, setting this variable to 0 since no data would be
122         *                                               written in the outBuffer.
123         * \param[in] transformedData A pointer to a buffer in which the Fourier transform of the input will be written.
124         */
125         void getNext(const sample_t* inBuffer, sample_t* outBuffer, int& length, fftwf_complex* transformedData);
126
127         /**
128         * Convolves the data that is provided with the inpulse response.
129         * \param[in] inBuffer A buffer with the input data to be convolved. Its length must be N/2 + 1
130         * \param[in] outBuffer A pointer to the buffer in which the convolution result will be written.
131         * \param[in,out] length The number of samples to be convolved and the length of the outBuffer.
132         *                                               The convolution output should be larger than the input, but since this class uses the overlap
133         *                                               add method, the extra length will be saved internally.
134         *                                               It must be equal or lower than N/2 (N=size of the FFTPlan) or the call will fail and set the value of length to 0 since no data would be
135         *                                               written in the outBuffer.
136         */
137         void getNext(const fftwf_complex* inBuffer, sample_t* outBuffer, int& length);
138         
139         /**
140         * Gets the internally stored extra data which is result of the convolution.
141         * \param[in,out] length The count of samples that should be read. Shall
142         *                contain the real count of samples after reading, in case
143         *                there were only fewer samples available.
144         *                A smaller value also indicates the end of the data.
145         * \param[out] eos End of stream, whether the end is reached or not.
146         * \param[in] buffer The pointer to the buffer to read into.
147         */
148         void getTail(int& length, bool& eos, sample_t* buffer);
149
150         /**
151         * Resets the internally stored data so a new convolution can be started.
152         */
153         void clear();
154
155         /**
156         * Calculates the Inverse Fast Fourier Transform of the input array.
157         * \param[in] inBuffer A buffer with the input data to be transformed. Its length must be N/2 + 1
158         * \param[in] outBuffer A pointer to the buffer in which the transform result will be written. 
159         * \param[in,out] length The number of samples to be transformed and the length of the outBuffer.
160         *                                               It must be equal or lower than N, but tipically N/2 should be used (N=size of the FFTPlan) or the call will fail and the value 
161         *                                               of length will be setted to 0, since no data would be written in the outBuffer.
162         */
163         void IFFT_FDL(const fftwf_complex* inBuffer, sample_t* outBuffer, int& length);
164
165         /**
166         * Multiplicates a frequency domain input by the impulse response and accumulates the result to a buffer.
167         * \param[in] inBuffer A buffer of complex numbers, samples in the frequency domain, that will be multiplied by the impulse response. Its length must be N/2 + 1
168         * \param[in] accBuffer A pointer to the buffer into which the result of the multiplication will be summed. Its length must be N/2 + 1
169         */
170         void getNextFDL(const std::complex<sample_t>* inBuffer, std::complex<sample_t>* accBuffer);
171
172         /**
173         * Transforms an input array of real data to the frequency domain and multiplies it by the impulse response. The result is accumulated to a buffer.
174         * \param[in] inBuffer A buffer of real numbers, samples in the time domain, that will be multiplied by the impulse response.
175         * \param[in] accBuffer A pointer to the buffer into which the result of the multiplication will be summed. Its length must be N/2 + 1.
176         * \param[in,out] length The number of samples to be transformed and the length of the inBuffer.
177         *                                               It must be equal or lower than N/2 (N=size of the FFTPlan) or the call will fail and the value
178         *                                               of length will be setted to 0, since no data would be written in the outBuffer.
179         * \param[in] transformedData A pointer to a buffer in which the Fourier transform of the input will be written.
180         */
181         void getNextFDL(const sample_t* inBuffer, std::complex<sample_t>* accBuffer, int& length, fftwf_complex* transformedData);
182
183         /**
184         * Changes the impulse response and resets the FFTConvolver.
185         * \param ir A shared pointer to a vector with the data of the impulse response in the frequency domain.
186         */
187         void setImpulseResponse(std::shared_ptr<std::vector<std::complex<sample_t>>> ir);
188
189         /**
190         * Retrieves the current impulse response being used.
191         * \return The current impulse response.
192         */
193         std::shared_ptr<std::vector<std::complex<sample_t>>> getImpulseResponse();
194 };
195
196 AUD_NAMESPACE_END