Я работаю с wav-файлом и хочу применить к нему fft. Я использую библиотеку Aquila C ++ и SDL2.0.
Я уже загрузил wav-файл, используя функцию SDL «SDL_LoadWav». Теперь у меня есть векторный буфер типа float. Я хочу применить БПФ к нему.
Я не уверен, как дать (const SampleType x []) аргумент для 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;
}
Для БПФ я не совсем уверен, так как он включает в себя комплексные числа. Итак, вот что я попробовал:
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 (станд :: вектор&)»
spect = fft-> 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
Как только я получу работу, как мне извлечь реальные и мнимые значения?
Спасибо,
Вы хранили свои данные в векторах, что является хорошей практикой при кодировании на C ++.
Теперь вы вызываете API, который не знает о std::vector
(позор), вероятно, потому что интерфейс C ++ является дешевой оболочкой библиотеки C.
Вы должны передать указатель на необработанные данные вектора следующим образом:
fft->fft(&buffer_vector1[0]);
поскольку buffer_vector1
это std::vector<Aquila::SampleType>
, получая адрес первого элемента, преобразует его в Aquila::SampleType *
который теперь совместим с const Aquila::SampleType []
ожидается API (вектор гарантирует, что все данные смежны, не делайте этого на std::list
Обратите внимание, что если ваш вектор слишком короткий по сравнению с размером, с которым вы инициализировали объект fft, вы получите неправильные результаты / сбой, так как вы не используете std::vector
защищенный доступ к данным, но необработанный указатель (как в C)
Мои навыки FFT немного ржавые, но я помню, что вы пропускаете реальные сигналы и получаете сложные сигналы на выходе. Будьте уверены, чтобы не передавать сложные данные на входе (не уверен, просто сказать).
смотрите также: Как получить std :: vector указатель на необработанные данные?
Чтобы скомпилировать и связать ваш код, свяжите эти две библиотеки: -lAquila -lOoura_fft
Что касается вашей проблемы со звуком, хорошо, вы должны попытаться сузить это и задать другой вопрос …
Других решений пока нет …