Проблема БПФ (возвращает случайные результаты)
У меня есть этот код, но он постоянно возвращает случайные частоты от 0 до 1050. Пожалуйста, вы можете помочь мне понять, почему это происходит.
Длина моих данных - 1024, частота дискретизации - 8192, а данные - это короткий массив, заполненный входными данными с микрофона.
float *iSignal = new float[2048];
float *oSignal = new float[2048];
int pitch = 0;
for(x=0;x<=1024;x++) {
iSignal[x] = data[x];
}
fft(iSignal,oSignal,1024); //Input data, output data, length of input and output data
for(int y=0;y< 2048;y+=2) {
if((pow(oSignal[y],2)+pow(oSignal[y+1],2))>(pow(oSignal[pitch],2)+pow(oSignal[(pitch)+1],2))) {
pitch = y;
}
}
double pitchF = pitch / (8192.0/1024);
printf("Pitch: %f\n",pitchF);
Спасибо,
Найл.
Изменить: изменил код, но он по-прежнему возвращает случайные частоты.
4 ответа
Если предположить, oSignal
заполнен комплексными числами таким образом, что чередуются действительные и мнимые части, это может помочь изменить
for(int y=0;y< 8191;y++)
в
for(int y=0;y< 8191;y+=2)
Изменить: я даже не заметил, что вы передаете только 1024 образцов. Вы должны передать столько выборок во временной области, сколько будет выборок в частотной области, в вашем случае 4096.
Изменить: еще одна вещь: вы, очевидно, пытаетесь найти базовую частоту чего-то. Если что-то не является сгенерированным компьютером тоном или человеческим свистом (оба из которых очень чистые тона), вы можете быть разочарованы результатом. Простой метод, который вы разместили, едва работает для флейты.
Изменить: Для голоса и гитары вам не повезло. Некоторое время назад я написал программу, которая отображает частотную область, попробуйте, вы увидите проблему. Есть также доступные источники, если вам интересно.
Окончательное редактирование: вы можете прочитать статью в Википедии по определению высоты тона. Сконцентрируйтесь на подходах во временной области.
Кажется, iSignal[1025]..iSignal[8191] содержит случайные данные. Вы можете попытаться установить его в 0. Но почему вы передаете 8192 в fft(), если длина ваших данных равна 1024 (или 1025)?
Кроме того, вы теряете некоторую точность в целочисленном делении. Измените это, чтобы удвоить pitchF = pitch / (8192.0/1024);
Ваша функция FFT ожидает реальных или сложных входных данных? В случае, если он ожидает сложных данных, вы должны установить для каждой другой записи iSignal значение 0.
Две вещи:
- Вы уверены, что используете свой
fft
функционировать правильно? Вы обрабатываете вывод, как будто это сложный массив, организованный[R_1 I_1 R_2 I_2 ...]
, но вы рассматриваете входной массив, как будто он организован[R_1 R_2 R_3 ... R_1024 I_1 I_2 ...]
и, как говорит Хенрик, оставьте сложные части неинициализированными. - Ваше обнаружение пика чрезвычайно примитивно, хотя оно должно быть сделано для простого ввода (как один гитарный укус). Для использования с человеческим голосом вам почти наверняка понадобится более сложный подход.
Вы пытались поставить известный простой (то есть чистый синусоидальный) сигнал в качестве входа?
"случайные частоты от 0 до около 1050" - разве типичный аудиосигнал не состоит из комбинации частот? Так как ваша частота дискретизации составляет 8192 Гц, ваше БПФ может обнаруживать до 8192/2 = 4096 Гц. Я ожидаю, что вы увидите комбинацию множества частот, но я бы не назвал их "случайными".
Почему вы удивлены? Что я упустил?