我正在使用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工作,我该如何提取实数和虚数值?
谢谢,
答案 0 :(得分:2)
您将数据存储在向量中,这在使用C ++进行编码时是一种很好的做法。
现在你正在调用一个不知道std::vector
(羞耻)的API,可能是因为C ++接口是C库的廉价包装器。
您必须将指针传递给矢量的原始数据,如下所示:
fft->fft(&buffer_vector1[0]);
由于buffer_vector1
是std::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
关于你的声音问题,你应该尝试缩小它并提出另一个问题......