2016-09-15 78 views
2

我与wav文件工作,想申请FFT它。我正在使用Aquila C++库和SDL2.0。 我已经使用SDL的“SDL_LoadWav”功能已经加载wav文件。现在我有一个float类型的向量缓冲区。我想对其应用FFT。 我不知道怎么给(常量SampleType X [])参数FFT。SDL与Aquila FFT

这里是我做过什么,当我申请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** 
} 

这是我收到的错误:

error: no matching function for call to ‘Aquila::Fft::fft(std::vector&)’ spect = fft->fft(buffer_vector1); /usr/local/include/aquila/transform/Fft.h:70:30: note: candidate: virtual Aquila::SpectrumType Aquila::Fft::fft(const SampleType*) virtual SpectrumType fft(const SampleType x[]) = 0; ^/usr/local/include/aquila/transform/Fft.h:70:30: note: no known conversion for argument 1 from ‘std::vector’ to ‘const SampleType* {aka const double*}’

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

编辑:

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

一旦我得到了FFT的工作,我如何提取实部和虚值?

感谢,

+0

尝试:'FFT的> FFT(&buffer_vector1 [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

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

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

还看到:How to get std::vector pointer to the raw data?

要编译和链接代码,与2个库链接:-lAquila -lOoura_fft

关于你的声音的问题,以及你应该尽量缩小下来,问了另一个问题?

+0

谢谢,这解决了错误。但是我得到另一个错误: //usr/local/lib/libAquila.a(OouraFft.cpp.o):函数'Aquila :: OouraFft :: fft(double const *)': OouraFft.cpp: (。文本+ 0x2c1):未定义的引用'cdft' //usr/local/lib/libAquila.a(OouraFft.cpp.o):在函数'Aquila :: OouraFft :: ifft(std :: vector ,std :: allocator >>,double *)': OouraFft.cpp :(。text + 0x412):undefined reference to'cdft' –

+0

如何编译&链接你的代码?根据https://github.com/zsiciarz/aquila-standalone-example/issues/1,它应该有2个库:'-lAquila -lOoura_fft' –

+0

是的,工作。 –