SDL和Aquila FFT

时间:2016-09-15 19:20:52

标签: c++ audio sdl fft spectrum

我正在使用wav文件,并希望将fft应用于它。我正在使用Aquila C ++库和SDL2.0。 我已经使用SDL的“SDL_LoadWav”功能加载了wav文件。现在我有一个float类型的向量缓冲区。我想对它应用FFT。 我不知道如何给fft提供(const SampleType x [])参数。

这是我在应用DCT时所做的,但我觉得我没有正确使用它,因为它没有给出正确的声音输出。

struct SignalComponent {
   float frequency;
  float amplitude;
};

auto buffer = audio_file->GetWavBuffer();  // float vector 
auto buffer_length = audio_file->GetWavLength();
auto sample_rate = audio_file->GetWavFile()->freq;

for (unsigned int i=0; i < buffer_length/sample_rate; i++) {
     // Conversion of float vector into Double vector; 
     std::vector<double> buffer_vector (buffer.begin()+(i*sample_rate),
                                   buffer.begin()+((i+1)*sample_rate));

     std::vector<double> dctCoefficients = dct->dct(buffer_vector, 576);
     int length = dctCoefficients.size();

     auto signal_components = std::vector<SignalComponent>() = {};

     for (int i = 0; i<length; i++) {
         SignalComponent sComponent;
          //sqrt(re*re+im*im) will be the magnitude of the signal at the            frequency of the given bin.
         sComponent.amplitude = dctCoefficients[i];
         sComponent.frequency = (static_cast<float>(i) *
                          (static_cast<float>(sample_rate) /
                           static_cast<float>(length)));
         signal_components.push_back(sComponent); 
}
SignalChunk sChunk = SignalChunk(signal_components);
signal_chunks.push_back(sChunk); // One big signalChunk

auto signal = Signal(signal_chunks);

// Clean up the DCT generator
delete dct; 
}

对于FFT,我不确定它是否涉及复数。所以这就是我的尝试:

for (unsigned int i=0 ; i<buffer.size() ; i++){
  spec1.push_back(0);
  spec1.push_back(buffer[i]) ;  
}
for (unsigned int i=buffer_length-1 ; (signed)i>-1 ; i--){
  spec2.push_back(0);
  spec2.push_back(buffer[i]) ;  
}

mergedSpectrum.resize(spec1.size() + spec2.size());


merge(spec1.begin(),spec1.end(),spec2.begin(),spec2.end(),mergespec.begin());

Aquila::Fft* fft = new Aquila::Fft(576);
Aquila::SpectrumType spect;
for (unsigned int i=0; i < buffer_length/sample_rate; i++) {
    std::vector<Aquila::SampleType> buffer_vector1 (buffer_vector.begin()+(i*sample_rate),
                                   buffer_vector.begin()+((i+1)*sample_rate));  
   calculate the FFT
   auto fft = Aquila::FftFactory::getFft(576);
  **spect = fft->fft(buffer_vector1); // This line is an error, because of complex type**
}

这是我得到的错误:

  

错误:没有匹配的调用函数   阿奎拉:: FFT :: FFT(标准::矢量&安培)'        spect = fft-&gt; fft(buffer_vector1); /usr/local/include/aquila/transform/Fft.h:70:30:注意:候选人:   虚拟Aquila :: SpectrumType Aquila :: Fft :: fft(const SampleType *)            虚拟SpectrumType fft(const SampleType x [])= 0;                                 ^ /usr/local/include/aquila/transform/Fft.h:70:30:注意:不知道   将参数1从'std :: vector'转换为'const   SampleType * {aka const double *}'

有人可以帮我吗?我想在应用DCT时实现类似的功能。

编辑:

Aquila::SpectrumType spect;
typedef complex<double> ComplexType; 
typedef std::vector< ComplexType > SpectrumType  

一旦我完成了fft工作,我该如何提取实数和虚数值?

谢谢,

1 个答案:

答案 0 :(得分:2)

您将数据存储在向量中,这在使用C ++进行编码时是一种很好的做法。

现在你正在调用一个不知道std::vector(羞耻)的API,可能是因为C ++接口是C库的廉价包装器。

您必须将指针传递给矢量的原始数据,如下所示:

fft->fft(&buffer_vector1[0]);

由于buffer_vector1std::vector<Aquila::SampleType>,因此获取第一个元素的地址会将其转换为Aquila::SampleType *,该const Aquila::SampleType []现在与API预期的std::list兼容(矢量确保所有数据都是连续的,请勿在{{1​​}}

上执行此操作

请注意,如果你的向量太短而你初始化fft对象的大小,你会得到错误的结果/崩溃,因为你没有使用std::vector受保护的数据访问但是使用原始指针(如C)

我的FFT技巧有点生疏,但我记得你传递真实信号并在输出中获得复杂信号。一定不要在输入中传递复杂数据(不确定,只是说)。

另见:How to get std::vector pointer to the raw data?

要编译和链接您的代码,请链接这两个库:-lAquila -lOoura_fft

关于你的声音问题,你应该尝试缩小它并提出另一个问题......