Проблема БПФ (возвращает случайные результаты)

У меня есть этот код, но он постоянно возвращает случайные частоты от 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 Гц. Я ожидаю, что вы увидите комбинацию множества частот, но я бы не назвал их "случайными".

Почему вы удивлены? Что я упустил?

Другие вопросы по тегам