音频延时测试方法与实现

33 篇文章 23 订阅
9 篇文章 0 订阅

音频延时测试方法有以下几种
1、使用专业的测试设备,通过专业的音频测试仪器可以准确测量音频延时,如常见声学分析仪、信号发生器、声卡+Smaart(介绍测试延时方法链接:https://blog.csdn.net/weixin_48408892/article/details/127318158?spm=1001.2014.3001.5501)等等。
2、手动测量:可以通过在音频信号进入和离开设备时手动观察信号波形的变化,如从录音设备中录入一个短促的声音,同时再监听设备中观察声音的回放情况,以此来判断音频延时的大小。
3、使用软件测试:通过电脑或手机上的特殊软件来测试音频延时,如Voicemeeter Bannana。

无论用哪种方法都需要注意测试准确性,尽量减少外部干扰。同时,测试结果会受到设备类型,连接方法等因素影响,最好多次测试以获得更准确的数据。
还有通过自定义软件方式实现延时测试,比较2笔音频buf,记录时间戳,确认音频一致性后,计算时间差即延时。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/soundcard.h>

#define SAMPLE_RATE 44100 // 采样率 Hz
#define SAMPLE_SIZE 2 // 采样长度,2字节
#define CHANNELS 2 // 声道数

#define DEVICE_1 “/dev/dsp” // 音频设备路径 1
#define DEVICE_2 “/dev/dsp1” // 音频设备路径 2

// 计算两个时间戳之间的差值(微秒)
unsigned long diff_time(struct timeval *t1, struct timeval *t2)
{
return (t2->tv_sec - t1->tv_sec) * 1000000 + (t2->tv_usec - t1->tv_usec);
}

int main()
{
int fd1, fd2; // 文件描述符
int bufsize; // 缓冲区大小
char *buff1, *buff2; // 缓冲区指针
struct timeval t1, t2; // 时间戳
int i, j; // 循环变量
int chan=CHANNELS;
// 打开音频设备 1
fd1 = open(DEVICE_1 , O_RDONLY);
if (fd1 < 0) {
fprintf(stderr, “Failed to open %s: %s\n”, COREINPUTREC, strerror(errno));
exit(EXIT_FAILURE);
}
// 打开音频设备 2
fd2 = open(DEVICE_2, O_RDONLY);
if (fd2 < 0) {
fprintf(stderr, “Failed to open %s: %s\n”, COREOUTPUTREC, strerror(errno));
exit(EXIT_FAILURE);
}
// 设置音频设备参数
int format = AFMT_S16_LE;
if (ioctl(fd1, SNDCTL_DSP_SETFMT, &format) == -1) {
fprintf(stderr, “Failed to set format: %s\n”, strerror(errno));
exit(EXIT_FAILURE);
}
if (ioctl(fd1, SNDCTL_DSP_CHANNELS, &chan) == -1) {
fprintf(stderr, “Failed to set channels: %s\n”, strerror(errno));
exit(EXIT_FAILURE);
}
int speed = SAMPLE_RATE;
if (ioctl(fd1, SNDCTL_DSP_SPEED, &speed) == -1) {
fprintf(stderr, “Failed to set speed: %s\n”, strerror(errno));
exit(EXIT_FAILURE);
}
// 分配缓冲区
bufsize = chan * SAMPLE_SIZE * SAMPLE_RATE / 10; // 每次读取10毫秒的数据
buff1 = (char *)malloc(bufsize);
buff2 = (char *)malloc(bufsize);
// 循环读取数据,每次读取5次数据
for (i = 0; i < 5; i++) {
// 同时读取2个设备的数据
if (read(fd1, buff1, bufsize) == -1) {
fprintf(stderr, “Failed to read data: %s\n”, strerror(errno));
exit(EXIT_FAILURE);
}
if (read(fd2, buff2, bufsize) == -1) {
fprintf(stderr, “Failed to read data: %s\n”, strerror(errno));
exit(EXIT_FAILURE);
}
// 记录时间戳
gettimeofday(&t1, NULL);
// 循环查找延迟
for (j = 0; j < bufsize; j += SAMPLE_SIZE * CHANNELS) {
// 判断第一个缓冲区是否包含第二个缓冲区的数据
if (memcmp(buff1 + j, buff2, SAMPLE_SIZE * CHANNELS) == 0) {
// 计算延迟时间
gettimeofday(&t2, NULL);
printf(“延迟:%ld 微秒\n”, diff_time(&t1, &t2));
break;
}
}
}
// 释放缓冲区
free(buff1);
free(buff2);
// 关闭音频设备
close(fd1);
close(fd2);
return 0;
}
以上代码根据实际需要进行再调整(不适合超过10ms延时音频测量),如间隔10ms读取一次数据。。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值