FFT - применение окна к данным PCM - PullRequest
2 голосов
/ 10 марта 2012

В настоящее время я пытаюсь воспроизвести функцию getSpectrum аудиобиблиотеки FMOD.Эта функция считывает данные PCM текущего воспроизводимого буфера, применяет окно к этим данным и применяет БПФ для получения спектра.

Возвращает массив значений с плавающей точкой, где каждое значение с плавающей точкой находится в диапазоне от 0 до 1 дБ (10.0f * ( float)log10(val) * 2.0f).

Я не уверен, что я должен делать, поэтому я объясню это:

Сначала я получаю данные PCM в буфере 4096 байт,согласно документации, данные PCM состоят из семплов, которые представляют собой левую-правую пару данных.

data

В моем случае я работаю с 16-битными семплами, как на изображениивыше.Итак, если я хочу работать только с левым каналом, я сохраняю данные левого ИКМ в коротком массиве, выполняя:

short *data = malloc(4096);
FMOD_Sound_ReadData(sound, (void *)data, 4096, &read);  

Так что если сэмпл = 4 байта, у меня есть 1024 сэмпла, т.е.левый канал и 1024 шорт, представляющих правый канал.

Чтобы выполнить БПФ, мне нужно иметь массив с плавающей точкой и применить окно (Hanning) к моим данным:

float hanningWindow(short in, size_t i, size_t s)
{
    return in*0.5f*(1.0f-cos(2.0f*M_PI*(float)(i)/(float)(s-1.0f)));
}

whew in - это ввод, i - позиция в массиве и s размер массива (1024).

Чтобы получить только левый канал:

float *input = malloc(1024*sizeof(float));
for (i = 0; i < 1024; i++)
    input[i] = hanningWindow(data[i*2], i, 1024);

Затем я выполняю БПФ благодаря kiss_fft (от реального к сложному).Я получаю kiss_fft_cpx *ouput (массив комплексных) размером 1024/2 + 1 = 513.

Я рассчитываю амплитуду каждой частоты с помощью:

kiss_fft_cpx   c = output[i];
float          amp = sqrt(c.r*c.r + c.i*c.i);

рассчитываем в дБ:

amp = 10.0f * (float)log10(amp) * 2.0f;

amp не между 0 и 1. Я не знаю, где я должен нормализовать свои данные (данные PCM или в конце).Кроме того, я не уверен в том, как я применяю свое окно к данным PCM.

Вот результат, который я получаю из песни от 0 до 20 кГц по сравнению с результатом функции getSpectrum.(для прямоугольного окна )

results

             My Result                         getSpectrum Result

Как добиться того же результата?

1 Ответ

2 голосов
/ 10 марта 2012

Вы немного запутались в масштабах журнала (дБ) - вы не получаете диапазон 0 - 1 дБ, вы получаете диапазон обычно 96 дБ для 16-битного звука, где верхний и нижний уровни несколькопроизвольный, например, от 0 до -96 дБ, или от 96 дБ до 0 дБ, или любой другой диапазон, который вам нравится, в зависимости от различных факторов.Вам, вероятно, просто нужно сместить и масштабировать график спектрограммы с помощью подходящего смещения и коэффициента, чтобы учесть это.

(Примечание: диапазон 96 дБ исходит из формулы 20 * log10(2^16), где 16 - это числобит.)

...