我正在使用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;
}据我所知,对于PA_SAMPLE_S16LE,振幅值应该在0到32768之间。但在分贝转换之前,我得到的值在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;
}发布于 2013-02-28 20:16:25
根据PulseAudio Simple API的说法
使用连接的
非常类似于普通的read()和write()系统调用。主要区别在于它们被称为pa_simple_read()和pa_simple_write()。请注意,这些操作总是阻塞的。
这似乎意味着返回值非常相似,因为在任何合理的地方似乎都没有提到pa_simple_read的返回值。下面是opengroup's read() manual所说的:
成功完成后,读取() ...应返回一个非负整数,指示实际读取的字节数。
假设pa_simple_read返回的值小于sizeof buffer,那么您的loop_write函数将使用未初始化的值。这是未定义的行为。我建议存储pa_simple_read的返回值,并在检查完错误后将其传递给loop_write而不是sizeof(buf)。
假设传递给pa_simple_read的值是一个奇数,您的loop_write将在最后一次迭代中使用一个未初始化的值。也许,为了应对这种情况,您可以将循环更改为:for (i = 1; i < size; i += 2),并将val声明/初始化更改为:uint16_t val = data[i-1] + ((uint32_t)data[i] << 8);
我要感谢mtrw帮助我得出这个结论。
https://stackoverflow.com/questions/15134740
复制相似问题