零.声明

最近做蓝牙协议栈的过程中遇到一些客户偶尔提报音频延迟的问题,所以引发了一些感想,跟大家分享下,音频延迟主要的影响范围是对一些要求实时性比较高的场景有比较差的体验

  • 连接蓝牙看视频的过程中,发现音画不同步,比如看电影,看抖音等一些视频类的内容
  • 游戏过程中,需要对声音有实时判断的,比如竞技类游戏之类的
  • 导航过程中,声音延迟,影响比较大,尤其是我直观的体验一个场景的痛点,就是在高速交叉口的时候,有的时候开车并不会一直盯着屏幕看,反而会听语音播报,但是有的时候交叉口很近的才出来播报,导致措手不及

当然还有其他场景,我只是列举了几个我能想到的。说完这些,那我就从理论的角度给大家分析下这个问题,首先我想公布结论:对于蓝牙连接,没办法完全消除延迟,只能尽量让这个延迟变小。

本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:

第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。

第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等

第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等

第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。

第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)

第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等

第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展

第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。

另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。

-------------------------------------------------------------------------------------------------------------------------

蓝牙视频教程(跟韦东山老师合作):

https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.20.5aeb41f98e267j&id=693788592796

蓝牙交流扣扣群:765961169

入手开发板:https://shop220811498.taobao.com/category-1542116976.htm?spm=a1z10.5-c-s.w4010-22329603913.7.39ca7dbe2EA0K3&search=y&catName=%C0%B6%D1%C0%BF%AA%B7%A2%B0%E5#bd

蓝牙学习目录一篇文章足够你学习蓝牙技术,提供史上最全的蓝牙技术(传统蓝牙/低功耗蓝牙)文章总结,文档下载总结(2020/12/11更新)_Wireless_Link的博客-CSDN博客_蓝牙eir

--------------------------------------------------------------------------------------------------------------------------

一. A2DP的架构

我们先来介绍下整个A2DP audio path的框架

A2DP source的发送流程

UL(Upper Layer)收集到PCM数据,然后发送到A2DP,A2DP经过codec算法(SBC/AAC/APTX/LDAC/LHDC..)压缩成特定的音频格式,然后交给AVDTP,AVDTP转交给L2CAP,L2CAP通过ACL格式转交给HCI,然后到达BT chip,通过RF射频出去。

A2DP sink的接收流程

BT chip通过RF接收进来数据,然后通过ACL交给HCI,然后交给L2CAP,L2CAP交给AVDTP,AVDTP交给A2DP,A2DP收到的是remote经过压缩的数据,此时通过codec算法(SBC/AAC/APTX/LDAC/LHDC..)解压成PCM数据,然后交于声卡播放

我们在拿一个Source设备(手机)跟一个Sink设备(车载/耳机/音箱)来举例子看下整个结构

整个流程跟上面的A2DP类似,所以我们就不介绍了

二. 延迟原因分析

所以从这个框架中就可以总结归纳出来整个音频延迟可能原因

NOTED: 在这里注意下,音频延迟跟音频卡顿分析思路完全不同,有的人可能会混淆,有机会我再通过另外一篇文章来介绍下音频卡顿的分析思路。

大体的可能得原因如下:

另外,市面上大部分的实测数据如下:

当然这个是多方面原因造成的音频延迟,我们就来拆解下。

1. codec算法本身造成的音频延迟

编解码器

开发厂商

理论单帧延迟

关键设计原理

帧尺寸(典型值)

SBC

SIG

15~30 ms

固定分帧(4/8子带)

4~6 ms音频数据

AAC

Fraunhofer IIS

5~20 ms

可变分帧(1024/960样本)

20~24 ms音频数据

aptX

高通

1.92 ms

固定4样本块处理(16kHz子带)

1.92 ms音频数据

aptX HD

高通

2.6 ms

增强量化精度(24bit)

2.6 ms音频数据

aptX LL

高通

0.67 ms

超小帧(80样本@48kHz)

1.67 ms音频数据

aptX

Adaptive

高通

1~2 ms

动态帧调整(80~512样本)

1~6 ms音频数据

LDAC

Sony

8~10 ms

大帧优化音质(512/1024样本)

5~10 ms音频数据

LC3

SIG

0.125 ms

超短帧(10样本@48kHz)

0.25 ms音频数据

LHDC

Savitech

3~5 ms

可变分帧(256/512样本)

3~6 ms音频数据

⚠️ 注意

  • 理论延迟 ≠ 实际端到端延迟(需叠加传输/缓冲/渲染等环节)
  • 帧尺寸越小延迟越低,但抗丢包能力下降(需更频繁传输)

当然上面的数据也不一定是绝对的哈·,也要结合多方面因素来考虑

我们来算一个SBC的理论延迟吧,比如一个AVDTP package是1K的数据,然后4-5倍压缩率,所以解压后大概一帧是5K数据,而44.1Khz + 16bit位深 + 2Channel的1S的数据量173Kbyte,是28ms的理论延迟。

也就是你当下要发的数据,必须要等着5K数据压缩完毕才能发送给对方。所以对方收到的第一包数据一定是28ms以前的数据,这个就是理论延迟

2. Sink原因

a. 缓冲buffer过大

为什么会有缓冲buffer呢,在介绍这个之前,我们就要介绍下jitter的概念了,什么是jitter呢?就是比如上面我们介绍了一包数据是28ms的延迟,也可以理解为每包duration如果所有都恒定,那么duration都应该是28ms,但是由于是无线,所以肯定会存在干扰等因素,导致包肯定有重传等,所以在空口的duration肯定不是那么恒定的,比如来了28ms的数据,你就直接播放,那么由于空口有干扰,导致下个包是50ms来(这个是假定制),那么你本应该在29ms播放的时候发现没有数据了,所以这时候会存在22ms的空档没有数据期,所以就会卡存,比如这种空口包

可以看到只要有duration增大的情况,那么后面一定会有duration小的数据过来来补充,我们就成为这种现象为jitter.

为了避免这种情况,所以sink端一定会有缓冲buffer来降低这个卡顿风险,但是谈到这里学问就大了·,你增大缓冲buffer是解决了卡顿的风险,但是就带来了我们本章的问题了,就是莫名其妙多了延迟了,比如你缓冲buffer缓冲100ms,那么就额外多了100ms的延迟。这时候我们就要在特定的平台来权衡这个数值了,这个方面在不同的平台调整的值策略不同,要实测

b. 协议栈调度异常

这个没有啥好介绍的,就是协议栈的调度问题,协议栈的接收或者playback倍其他task或者thread抢占,拿不到资源,这个可能会引起音频卡顿,也可能会引起来音频延迟。

c. 平台驱动问题

平台驱动也会有音频缓冲

ⅰ. Linux驱动缓冲原理

关键参数:

参数

内核结构字段

影响

典型值

buffer_size

runtime->buffer_size

总缓冲区大小

1024-8192帧

period_size

runtime->period_size

单次传输量

256-1024帧

period_count

由buffer_size/period_size推导

中断频率

2-8个周期

ⅱ. Android缓冲原理

AudioFlinger 混合缓冲区

  • FastMixer线程:专用于低延迟场景(游戏/录音)
  • 混合缓冲区大小默认20ms(可动态调节)

AAudio 直通模式

[App] → [AAudio API] → [HAL层] → [DMA Buffer]

  • 绕过AudioFlinger,减少>40ms延迟
  • 要求:Android 8.0+,支持 MMAP 的硬件

层级

延迟范围

可优化极限

应用层缓冲

10-100ms

1ms (AAudio)

AudioFlinger混合

20-40ms

0ms (Bypass)

内核环形缓冲

5-30ms

2ms (MMAP)

DMA传输

0.5-2ms

硬件固定

Codec处理

1-10ms

硬件固定

Android总延迟

36-182ms

<15ms

ⅲ. RTOS

RTOS等就要看SDK的编写源码了

3. Source原因

a. Delay report

Delay report是蓝牙SIG在AVDTP/A2DP提出来的协议规范,就是为了解决音画不同步的问题,但是这个要依赖于sink跟source都支持,什么原理呢?很简单

在连线的时候A2DP sink会告知Source我的delay report时间是多少,Source收到后,在处理视频的时候本来应该当下发送视频,但是因为他知道sink的延迟是多少,所以音频先于视频delay report的时间发送,也就是 音频先于视频早达到delay report的时间,所以就规避了音画不同步的问题·

但是目前看下来支持的Source设备还是比较少,加上现在的一些视频类的APP也不会关注这个点,所以生态个人感觉还不是那么好!

b. UL层送数据延迟

这个也没啥好解释的哈,看标题就能看出来,由于系统问题,Source数据就是送的慢,所以导致到了sink端没有那么及时

三. 未来方向

音频延迟一直在无线领域是一个比较大的课题,想真正解决或者说让end user无感知,还是比较难得,所以百花齐放,有几个点可能要重点关注下。

1. LC3编解码器(LE Audio核心)

通过0.25ms超短帧 + 前向纠错实现端到端<30ms

突破性设计

参数

传统SBC/AAC

LC3

优势

帧长度

5~30ms

0.25ms

降低基础延迟10倍

处理复杂度

50 MIPS

<15 MIPS

功耗降低60%

抗丢包能力

需20%重传

FEC冗余

容忍15%丢包不中断

动态码率范围

固定

64-1024kbps

自适应网络环境

实测延迟表现

场景

端到端延迟

对比传统编解码

语音通话

18-22ms

比aptX LL低40%

游戏音频

25-28ms

比LDAC低85%

多设备广播

32ms

首支持≤50ms同步

2. 双通道直传

如苹果H2芯片的并行串流,规避中继延迟

  1. 异构计算架构
    • 主处理器:处理降噪/空间音频(占用<5% CPU)
    • 射频模块:独立管理双通道时序同步(精度±2μs)
  1. 私有协议优化
    • 频段:2.402-2.481GHz动态避让Wi-Fi
    • 时隙:将传统蓝牙32时隙压缩至8时隙

3. AI预测缓冲

高通S7平台可预测下一帧内容,减少20%缓冲时间

ⅰ. 核心技术创新

模块

功能描述

延迟优化效果

音频特征提取

20ms内识别音乐/语音/枪声

减少分析延迟

LSTM预测模型

预测未来80ms音频内容

缓冲降低20%

动态码率适配

根据网络质量切换aptX Adaptive

避免重传延迟

端侧推理引擎

Hexagon NPU加速(15TOPS)

推理耗时<1ms

ⅱ. 实测数据(Snapdragon Sound Gen 2)

场景

传统方案延迟

AI预测方案

提升幅度

地铁中游戏音频

142ms

89ms

-37%

拥挤WiFi环境

210ms

121ms

-42%

设备跨房间传输

185ms

98ms

-47%

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/83955.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/83955.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/83955.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 8.0 绿色版安装和配置过程

MySQL作为云计算时代&#xff0c;被广泛使用的一款数据库&#xff0c;他的安装方式有很多种&#xff0c;有yum安装、rpm安装、二进制文件安装&#xff0c;当然也有本文提到的绿色版安装&#xff0c;因绿色版与系统无关&#xff0c;且可快速复制生成&#xff0c;具有较强的优势。…

AGV|无人叉车工业语音播报器|预警提示器LBE-LEX系列性能与接线说明

LBE-LEX系列AGV|无人叉车工业语音播报器|预警提示器&#xff0c;涵盖LBE-LEI-M-00、LBE-LESM-00、LBE-LES-M-01、LBE-LEC-M-00、LBE-KEI-M-00、LBE-KES-M-00、LBE-KES-M-01、LBE-KEC-M-00等型号&#xff0c;适用于各种需要语音提示的场景&#xff0c;主要有AGV、AMR机器人、无人…

行为型设计模式之Interpreter(解释器)

行为型设计模式之Interpreter&#xff08;解释器&#xff09; 前言&#xff1a; 自己的话理解&#xff1a;自定义一个解释器用来校验参数或数据是否合法。 1&#xff09;意图 给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;这个解…

C++常用的企业级日志库

黄老师跟大家推荐几款在企业开发中最受欢迎的C++日志库! 1. spdlog spdlog 是一个非常流行的开源C++日志库,以其高性能和易用性著称。它支持多线程、异步日志记录以及多种格式化选项。 安装 可以通过包管理器安装,例如 vcpkg: vcpkg install spdlog示例代码 #include…

Python读取PDF:文本、图片与文档属性

在日常的数据采集、文档归档与信息挖掘过程中&#xff0c;PDF格式因其版式固定、内容稳定而被广泛使用。Python 开发者若希望实现 PDF 内容的自动化提取&#xff0c;选择一个易用且功能完善的库至关重要。本文将介绍如何用Python实现 PDF文本读取、图片提取 以及 文档属性读取 …

excel中数字不满六位在左侧前面补0的方法

如下图“代码”列&#xff0c;想要实现统一的六位&#xff0c;如果不足六位&#xff0c;在前面&#xff08;左侧&#xff09;补0。 实现方法&#xff1a; 使用公式TEXT(A2,"000000")注意务必是用双引号。 目标实现&#xff1a; 如果想要脱离原数据&#xff0c;复制…

软考 系统架构设计师系列知识点之杂项集萃(82)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;81&#xff09; 第148题 “41”视图主要用于描述系统逻辑架构&#xff0c;最早由Philippe Kruchten于1995年提出。其中&#xff08; &#xff09;视图用于描述对象模型&#xff0c;并说明系统应该…

Langgraph实战--自定义embeding

概述 在Langgraph中我想使用第三方的embeding接口来实现文本的embeding。但目前langchain只提供了两个类&#xff0c;一个是AzureOpenAIEmbeddings&#xff0c;一个是&#xff1a;OpenAIEmbeddings。通过ChatOpenAI无法使用第三方的接口&#xff0c;例如&#xff1a;硅基流平台…

(附实例代码及图示)混合策略实现 doc-doc 对称检索

HyDE 混合策略 在前面的文章中&#xff0c;学习的优化策略都是将对应的 查询 生成 新查询&#xff0c;通过 新查询 来执行相应的检索&#xff0c;但是在数据库中存储的数据一般都是 文档 层面上的&#xff0c;数据会远远比 查询 要大很多&#xff0c;所以 query 和 doc 之间是…

webui无法注册如何配置

1. 初始登陆界面 docker部署的脚本为&#xff1a; docker run -d \ -p 8180:8080 --gpusall \ -v ollama:/root/.ollama \ -v /home/pretrained_model/output:/app/backend/output \ --name open-webui \ --restart always ghcr.io/open-webui/open-webui:ollama 2. 新增注册入…

力扣 88.合并两个有序数组

文章目录 题目介绍题解 题目介绍 题解 法一&#xff1a;暴力法 class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {for(int i 0; i < n; i){nums1[mi] nums2[i];}Arrays.sort(nums1);} }法二&#xff1a;倒序双指针 时间复杂度为O(mn) 从右…

conda入门

目录 1. Conda 是什么&#xff1f;2. 为什么需要 Conda&#xff1f;它能解决什么问题&#xff1f;3. Conda 的核心组件和概念4. Conda 基本工作流程和常用命令5. Conda 的主要优势6. Conda 与 Pip 的关系7. 何时使用 Conda&#xff1f; 1. Conda 是什么&#xff1f; 包管理器&…

UE 5 和simulink联合仿真,如果先在UE5这一端结束Play,过一段时间以后**Unreal Engine 5** 中会出现显存不足错误

提问 UE5报错如图。解析原因 回答 你遇到的这个错误提示是&#xff1a; “Out of video memory trying to allocate a rendering resource. Make sure your video card has the minimum required memory, try lowering the resolution and/or closing other applications tha…

第七十三篇 从电影院售票到停车场计数:生活场景解析Java原子类精髓

目录 一、原子类基础&#xff1a;电影院售票系统1.1 传统售票的并发问题1.2 原子类解决方案 二、原子类家族&#xff1a;超市收银系统2.1 基础类型原子类2.2 数组类型原子类 三、CAS机制深度解析&#xff1a;停车场管理系统3.1 CAS工作原理3.2 车位计数器实现 四、高性能实践&a…

Linux(线程控制)

一 线程的操作 1. 创建线程&#xff1a;pthread_create int pthread_create(pthread_t *thread, // 线程 idconst pthread_attr_t *attr, // 线程属性设置void *(*start_routine) (void *), // 回调函数void *arg // 传递…

PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式

PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式 文章目录 PL/SQLDeveloper中数值类型字段查询后显示为科学计数法的处理方式1. 查询效果2. 处理方式3. 再次查询 1. 查询效果 2. 处理方式 3. 再次查询

centos 9/ubuntu 一次性的定时关机

方法一 # 15 表示15分钟以后自动关机 sudo shutdown -h 15方法二&#xff1a; sudo dnf install at -y # 晚上十点半关机 echo "shutdown -h now" | at 22:30 # 检查是否设置成功命令 atq [rootdemo-192 ~]# atq 1 Wed Jun 4 11:12:00 2025 a root # 取消定时计划…

Riverpod与GetX的优缺点对比

Riverpod 与 GetX 的优缺点对比 在 Flutter 开发领域,Riverpod 和 GetX 都是备受关注的状态管理与依赖注入框架,它们各有优劣,适用于不同的开发场景。以下从多个维度详细对比二者的优缺点。 一、Riverpod 的优缺点 (一)优点 架构清晰,数据流向明确:基于 Provider 模…

day 47

注意力可视化 训练模型 包含通道注意力模块和CNN模型的定义&#xff08;通道注意力的插入&#xff09; import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import ma…

《Vuejs设计与实现》第 8 章(挂载与更新)

目录 8.1 挂载子节点与属性 8.2 HTML Attributes 与 DOM Properties 8.3 设置元素属性的正确方式 8.4 处理 class 属性 8.5 卸载操作 8.6 区分 vnode 类型 8.7 事件处理优化 8.8 事件冒泡与更新时机问题 8.9 子节点的更新 8.10 文本节点和注释节点 8.11 片段&#xf…