177 lines
5.6 KiB
C++
Executable File
177 lines
5.6 KiB
C++
Executable File
// ==================================================================================
|
|
// Copyright (c) 2016 HiFi-LoFi
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is furnished
|
|
// to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
// ==================================================================================
|
|
|
|
#ifndef _AUDIOFFT_H
|
|
#define _AUDIOFFT_H
|
|
|
|
|
|
/**
|
|
* AudioFFT provides real-to-complex/complex-to-real FFT routines.
|
|
*
|
|
* Features:
|
|
*
|
|
* - Real-complex FFT and complex-real inverse FFT for power-of-2-sized real data.
|
|
*
|
|
* - Uniform interface to different FFT implementations (currently Ooura, FFTW3 and Apple Accelerate).
|
|
*
|
|
* - Complex data is handled in "split-complex" format, i.e. there are separate
|
|
* arrays for the real and imaginary parts which can be useful for SIMD optimizations
|
|
* (split-complex arrays have to be of length (size/2+1) representing bins from DC
|
|
* to Nyquist frequency).
|
|
*
|
|
* - Output is "ready to use" (all scaling etc. is already handled internally).
|
|
*
|
|
* - No allocations/deallocations after the initialization which makes it usable
|
|
* for real-time audio applications (that's what I wrote it for and using it).
|
|
*
|
|
*
|
|
* How to use it in your project:
|
|
*
|
|
* - Add the .h and .cpp file to your project - that's all.
|
|
*
|
|
* - To get extra speed, you can link FFTW3 to your project and define
|
|
* AUDIOFFT_FFTW3 (however, please check whether your project suits the
|
|
* according license).
|
|
*
|
|
* - To get the best speed on Apple platforms, you can link the Apple
|
|
* Accelerate framework to your project and define
|
|
* AUDIOFFT_APPLE_ACCELERATE (however, please check whether your
|
|
* project suits the according license).
|
|
*
|
|
*
|
|
* Remarks:
|
|
*
|
|
* - AudioFFT is not intended to be the fastest FFT, but to be a fast-enough
|
|
* FFT suitable for most audio applications.
|
|
*
|
|
* - AudioFFT uses the quite liberal MIT license.
|
|
*
|
|
*
|
|
* Example usage:
|
|
* @code
|
|
* #include "AudioFFT.h"
|
|
*
|
|
* void Example()
|
|
* {
|
|
* const size_t fftSize = 1024; // Needs to be power of 2!
|
|
*
|
|
* std::vector<float> input(fftSize, 0.0f);
|
|
* std::vector<float> re(audiofft::AudioFFT::ComplexSize(fftSize));
|
|
* std::vector<float> im(audiofft::AudioFFT::ComplexSize(fftSize));
|
|
* std::vector<float> output(fftSize);
|
|
*
|
|
* audiofft::AudioFFT fft;
|
|
* fft.init(1024);
|
|
* fft.fft(input.data(), re.data(), im.data());
|
|
* fft.ifft(output.data(), re.data(), im.data());
|
|
* }
|
|
* @endcode
|
|
*/
|
|
|
|
|
|
#include <cstddef>
|
|
#include <memory>
|
|
|
|
|
|
namespace audiofft
|
|
{
|
|
|
|
namespace details
|
|
{
|
|
|
|
class AudioFFTImpl
|
|
{
|
|
public:
|
|
AudioFFTImpl() = default;
|
|
virtual ~AudioFFTImpl() = default;
|
|
virtual void init(size_t size) = 0;
|
|
virtual void fft(const float* data, float* re, float* im) = 0;
|
|
virtual void ifft(float* data, const float* re, const float* im) = 0;
|
|
|
|
private:
|
|
AudioFFTImpl(const AudioFFTImpl&) = delete;
|
|
AudioFFTImpl& operator=(const AudioFFTImpl&) = delete;
|
|
};
|
|
}
|
|
|
|
|
|
// ======================================================
|
|
|
|
|
|
/**
|
|
* @class AudioFFT
|
|
* @brief Performs 1D FFTs
|
|
*/
|
|
class AudioFFT
|
|
{
|
|
public:
|
|
/**
|
|
* @brief Constructor
|
|
*/
|
|
AudioFFT();
|
|
|
|
/**
|
|
* @brief Initializes the FFT object
|
|
* @param size Size of the real input (must be power 2)
|
|
*/
|
|
void init(size_t size);
|
|
|
|
/**
|
|
* @brief Performs the forward FFT
|
|
* @param data The real input data (has to be of the length as specified in init())
|
|
* @param re The real part of the complex output (has to be of length as returned by ComplexSize())
|
|
* @param im The imaginary part of the complex output (has to be of length as returned by ComplexSize())
|
|
*/
|
|
void fft(const float* data, float* re, float* im);
|
|
|
|
/**
|
|
* @brief Performs the inverse FFT
|
|
* @param data The real output data (has to be of the length as specified in init())
|
|
* @param re The real part of the complex input (has to be of length as returned by ComplexSize())
|
|
* @param im The imaginary part of the complex input (has to be of length as returned by ComplexSize())
|
|
*/
|
|
void ifft(float* data, const float* re, const float* im);
|
|
|
|
/**
|
|
* @brief Calculates the necessary size of the real/imaginary complex arrays
|
|
* @param size The size of the real data
|
|
* @return The size of the real/imaginary complex arrays
|
|
*/
|
|
static size_t ComplexSize(size_t size);
|
|
|
|
private:
|
|
std::unique_ptr<details::AudioFFTImpl> _impl;
|
|
|
|
AudioFFT(const AudioFFT&) = delete;
|
|
AudioFFT& operator=(const AudioFFT&) = delete;
|
|
};
|
|
|
|
|
|
/**
|
|
* @deprecated
|
|
* @brief Let's keep an AudioFFTBase type around for now because it has been here already in the 1st version in order to avoid breaking existing code.
|
|
*/
|
|
typedef AudioFFT AudioFFTBase;
|
|
|
|
} // End of namespace
|
|
|
|
#endif // Header guard
|