Итак, я пытаюсь получить значения частоты дБ от 0 Гц до 22 кГц для 1-секундной записи ИКМ. Я получаю сырой PCM от записи микрофона PulseAudio Simple API и пытаюсь сделать FFT на этом с помощью FFTW. Я поэкспериментировал с настройками FFTW взад и вперед (я тоже пробовал fftw_plan_dft_r2c_1d), но мне все еще кажется, что в выводе FFTW я получаю ненужные данные. Кажется, я не могу найти никакой корреляции между выходным сигналом и частотами, которые я записываю.
Я попытался вывести PCM в файл и воспроизвести его с VL C, и он успешно воспроизводился - так что-то что-то не так с моим FFT.
Вот мой код:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <math.h>
#include <pulse/simple.h>
#include <pulse/error.h>
#include <fftw3.h>
static ssize_t loop_write(uint8_t *data, size_t size) {
fftw_complex *in, *out;
fftw_plan p;
in = (fftw_complex*) malloc(sizeof(fftw_complex) * size);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * size);
for (int i = 0; i < size; i++) {
in[i][0] = data[i * 8];
in[i][1] = (float) 0;
}
p = fftw_plan_dft_1d(size, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(p);
double max = 0;
int maxi = 0;
for (int i = 1; i < size; i++) {
double calc = sqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1]);
if (calc > max) {
max = calc;
maxi = i;
}
}
printf("%d: %f\n", maxi, max);
fftw_destroy_plan(p);
fftw_free(in); fftw_free(out);
}
int main(int argc, char*argv[]) {
static const pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 1
};
pa_simple *s = NULL;
int error;
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
goto finish;
}
uint8_t buf[88200];
if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) {
fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
goto finish;
}
loop_write(buf, sizeof(buf) / 8);
finish:
if (s)
pa_simple_free(s);
return 0;
}
Есть идеи, что я делаю неправильно? Как я могу получить значения частоты?