SDL和Aquila FFT

3

我正在处理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**
}

这是我收到的错误信息:
错误:没有匹配的函数调用'Aquila::Fft::fft(std :: vector&)' spect = fft->fft(buffer_vector1); /usr/local/include/aquila/transform/Fft.h:70:30: 注意候选: virtual Aquila::SpectrumType Aquila::Fft::fft(const SampleType *) virtual 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工作,如何提取实部和虚部数值?

尝试这样做:fft->fft(&buffer_vector1[0]); - Jean-François Fabre
1个回答

2

当你使用C++编程时,将数据存储在向量中是一个好的实践。

现在你正在调用一个不了解std::vector(糟糕)的API,可能是因为C++接口是C库的廉价包装。

你必须像这样传递指向向量原始数据的指针:

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

更好的方式是使用data成员方法:
fft->fft(buffer_vector1.data());

由于buffer_vector1是一个std::vector<Aquila::SampleType>,获取第一个元素的地址将其转换为Aquila::SampleType *,现在与API期望的const Aquila::SampleType []兼容(向量确保所有数据都是连续的,请勿在std::list上这样做)。

请注意,如果您的向量比您使用fft对象初始化的大小要短,则会出现错误结果/崩溃,因为您没有使用std::vector受保护的数据访问,而是使用原始指针(就像在C中一样)。

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

参见:如何获取std::vector指向原始数据的指针?

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接