I'm using the PulseAudio API to get the current microphone input in "realtime". The buffer data is being delivered as a 16bit little endian byte array. What I'd like to do is to find out the maximum peak level in the buffer and transform it into a decibel value. To do that I have to convert each two byte array values into one integer value. In the same loop-process I am also looking for the max value. After that I convert the maximum value into a decibel value. Here is the C code:
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;
}
To my knowledge the amplitude value should be between 0 and 32768 for PA_SAMPLE_S16LE. But I am getting values between 0 and 65536 before the decibel conversion. Is there anything wrong with my conversion?
For the sake of completeness I am also posting my pulseaudio setup:
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;
}