В настоящее время я пытаюсь воспроизвести функцию getSpectrum
аудиобиблиотеки FMOD. Эта функция считывает данные PCM текущего воспроизводимого буфера, применяет окно к этим данным и применяет FFT для получения спектра.
Он возвращает массив чисел с плавающей запятой, где каждое число с плавающей запятой находится в диапазоне от 0 до 1 дБ (10.0f * ( float)log10(val) * 2.0f
).
Я не уверен, что я делаю, это то, что я должен делать, поэтому я объясню это:
Во-первых, я получаю данные PCM в буфере размером 4096 байт. Согласно документации, данные PCM состоят из выборок, представляющих собой пару данных слева-направо.
В моем случае я работаю с 16-битными образцами, как на изображении выше. Итак, если я хочу работать только с левым каналом, я сохраняю данные левого PCM в коротком массиве, делая:
short *data = malloc(4096);
FMOD_Sound_ReadData(sound, (void *)data, 4096, &read);
Итак, если выборка = 4 байта, у меня есть 1024 выборки, т.е. 1024 коротких, представляющих левый канал, и 1024 коротких, представляющих правый канал.
Чтобы выполнить БПФ, мне нужно иметь массив с плавающей запятой и применить окно (Ханнинг) к моим данным:
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. (для прямоугольного окна)
My Result getSpectrum Result
Как я могу добиться того же результата?