Я использую API PulseAudio, чтобы получить текущий вход микрофона в «реальном времени». Данные буфера доставляются в виде 16-битного массива байтов с прямым порядком байтов. Что я хотел бы сделать, так это узнать максимальный пиковый уровень в буфере и преобразовать его в значение в децибелах. Для этого мне нужно преобразовать каждые два значения массива байтов в одно целочисленное значение. В том же цикле я также ищу максимальное значение. После этого я конвертирую максимальное значение в децибел. Вот код C:
static ssize_t loop_write(int fd, const uint8_t *data, size_t size)
{
int newsize = size / 2;
uint16_t max_value = 0;
int i = 0;
for (i = 0; i < size; i += 2)
{
// put two bytes into one integer
uint16_t val = data[i] + ((uint32_t)data[i+1] << 8);
// find max value
if(val > max_value)
max_value = val;
}
// convert to decibel
float decibel = max_value / pow(2, 15);
if(decibel != 0)
decibel = 20 * log(decibel);
// print result
printf("%f, ", decibel);
return size;
}
Насколько мне известно, значение амплитуды должно быть между 0 и 32768 для PA_SAMPLE_S16LE. Но я получаю значения от 0 до 65536 до преобразования децибел. Что-то не так с моей конверсией?
Для полноты картины я также публикую свою настройку pulseaudio:
int main(int argc, char*argv[])
{
char *device = "alsa_input.usb-041e_30d3_121023000184-00-U0x41e0x30d3.analog-mono";
// The sample type to use
static const pa_sample_spec ss = {
.format = PA_SAMPLE_S16LE,
.rate = 44100,
.channels = 1
};
pa_simple *s = NULL;
int ret = 1;
int error;
// Create the recording stream
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, device, "record", &ss, NULL, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
goto finish;
}
for (;;) {
uint8_t buf[BUFSIZE];
// Record some data ...
if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) {
fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
goto finish;
}
// And write it to STDOUT
if (loop_write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) {
fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno));
goto finish;
}
}
ret = 0;
finish:
if (s)
pa_simple_free(s);
return 0;
}