首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >16位小端字节数组到整数数组到分贝值

16位小端字节数组到整数数组到分贝值
EN

Stack Overflow用户
提问于 2013-02-28 19:46:37
回答 1查看 2.9K关注 0票数 0

我正在使用PulseAudio接口“实时”获取当前的麦克风输入。缓冲区数据以16位小端字节数组的形式传送。我想做的是找出缓冲区中的最大峰值,并将其转换为分贝值。为此,我必须将每个两个字节的数组值转换为一个整数值。在相同的循环过程中,我也在寻找最大值。之后,我将最大值转换为分贝值。下面是C代码:

代码语言:javascript
复制
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设置:

代码语言:javascript
复制
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;
}
EN

回答 1

Stack Overflow用户

发布于 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帮助我得出这个结论。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15134740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档