FFTFrameGStreamer.cpp [plain text]
#include "config.h"
#if USE(WEBAUDIO_GSTREAMER)
#include "FFTFrame.h"
#include "VectorMath.h"
#include <wtf/FastMalloc.h>
#include <wtf/StdLibExtras.h>
namespace {
const int kMinFFTPow2Size = 2;
const int kMaxFFTPow2Size = 24;
size_t unpackedFFTDataSize(unsigned fftSize)
{
return fftSize / 2 + 1;
}
}
namespace WebCore {
FFTFrame::FFTFrame(unsigned fftSize)
: m_FFTSize(fftSize)
, m_log2FFTSize(static_cast<unsigned>(log2(fftSize)))
, m_complexData(makeUniqueArray<GstFFTF32Complex>(unpackedFFTDataSize(m_FFTSize)))
, m_realData(unpackedFFTDataSize(m_FFTSize))
, m_imagData(unpackedFFTDataSize(m_FFTSize))
{
int fftLength = gst_fft_next_fast_length(m_FFTSize);
m_fft = gst_fft_f32_new(fftLength, FALSE);
m_inverseFft = gst_fft_f32_new(fftLength, TRUE);
}
FFTFrame::FFTFrame()
: m_FFTSize(0)
, m_log2FFTSize(0)
{
int fftLength = gst_fft_next_fast_length(m_FFTSize);
m_fft = gst_fft_f32_new(fftLength, FALSE);
m_inverseFft = gst_fft_f32_new(fftLength, TRUE);
}
FFTFrame::FFTFrame(const FFTFrame& frame)
: m_FFTSize(frame.m_FFTSize)
, m_log2FFTSize(frame.m_log2FFTSize)
, m_complexData(makeUniqueArray<GstFFTF32Complex>(unpackedFFTDataSize(m_FFTSize)))
, m_realData(unpackedFFTDataSize(frame.m_FFTSize))
, m_imagData(unpackedFFTDataSize(frame.m_FFTSize))
{
int fftLength = gst_fft_next_fast_length(m_FFTSize);
m_fft = gst_fft_f32_new(fftLength, FALSE);
m_inverseFft = gst_fft_f32_new(fftLength, TRUE);
memcpy(realData(), frame.realData(), sizeof(float) * unpackedFFTDataSize(m_FFTSize));
memcpy(imagData(), frame.imagData(), sizeof(float) * unpackedFFTDataSize(m_FFTSize));
}
void FFTFrame::initialize()
{
}
void FFTFrame::cleanup()
{
}
FFTFrame::~FFTFrame()
{
if (!m_fft)
return;
gst_fft_f32_free(m_fft);
m_fft = 0;
gst_fft_f32_free(m_inverseFft);
m_inverseFft = 0;
}
void FFTFrame::multiply(const FFTFrame& frame)
{
FFTFrame& frame1 = *this;
FFTFrame& frame2 = const_cast<FFTFrame&>(frame);
float* realP1 = frame1.realData();
float* imagP1 = frame1.imagData();
const float* realP2 = frame2.realData();
const float* imagP2 = frame2.imagData();
size_t size = unpackedFFTDataSize(m_FFTSize);
VectorMath::zvmul(realP1, imagP1, realP2, imagP2, realP1, imagP1, size);
float scale = 0.5f;
VectorMath::vsmul(realP1, 1, &scale, realP1, 1, size);
VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, size);
}
void FFTFrame::doFFT(const float* data)
{
gst_fft_f32_fft(m_fft, data, m_complexData.get());
float scaleFactor = 2;
float* imagData = m_imagData.data();
float* realData = m_realData.data();
for (unsigned i = 0; i < unpackedFFTDataSize(m_FFTSize); ++i) {
imagData[i] = m_complexData[i].i * scaleFactor;
realData[i] = m_complexData[i].r * scaleFactor;
}
}
void FFTFrame::doInverseFFT(float* data)
{
float* realData = m_realData.data();
float* imagData = m_imagData.data();
for (size_t i = 0; i < unpackedFFTDataSize(m_FFTSize); ++i) {
m_complexData[i].i = imagData[i];
m_complexData[i].r = realData[i];
}
gst_fft_f32_inverse_fft(m_inverseFft, m_complexData.get(), data);
const float scaleFactor = 1.0 / (2 * m_FFTSize);
VectorMath::vsmul(data, 1, &scaleFactor, data, 1, m_FFTSize);
}
float* FFTFrame::realData() const
{
return const_cast<float*>(m_realData.data());
}
float* FFTFrame::imagData() const
{
return const_cast<float*>(m_imagData.data());
}
int FFTFrame::minFFTSize()
{
return 1 << kMinFFTPow2Size;
}
int FFTFrame::maxFFTSize()
{
return 1 << kMaxFFTPow2Size;
}
}
#endif // USE(WEBAUDIO_GSTREAMER)