Android的10毫秒问题 解读Android系统音频通道延迟缺陷
Gabor、Patrick 于 2015.12.07 02:25:27 | 源自:www.soomal.com | 版权:编译 | 平均/总评分:09.48/275

许多移动应用在很大程度上依赖于低延迟音频功能,例如一些游戏、合成器和数字音频工作站[Digital Audio Workstations,DAWs],交互式音频应用和乐器模拟应用,以及即将成为下一波潮流的虚拟现实应用,在苹果的平台上[App Store+iOS设备]发展兴盛——并让App Store和iOS开发者获得的巨大收益而Android上是基本不存在的。

Android的10毫秒问题,是对造成目前这个巨大差异的极端技术难题的一个简单理解,它阻碍了这类收费应用在目前Android平台上的可用性和发布。

由于害怕糟糕的音频性能造成的负面口碑对品牌和专业声誉带来打击,发行商和开发者并不愿意把这些成功的iOS音频应用[需要约10ms的音频延迟性能]移植发布到Android平台上。

iOS在这些应用领域获得的收入数据,而有强烈购买欲望的消费者由于目前的技术问题无法在Android上获得这类应用导致客户流失。如果你考虑到所谓的“下一个10亿”消费者将是“移动平台为主”的时候,就能理解这个问题和机遇有多大的规模。

而我们正解决这个问题,这篇解读以Google Nexus 9的实际延迟数据对Android 的10毫秒问题提供了一个易于理解的概述。

Android的10毫秒问题和音频通道的延迟是如何影响应用开发者和Android OEM厂商的

  • 尽管音乐类应用在iOS App Store的下载量中只占3%,但音乐应用分类的创收排名位列第三,仅次于游戏和社交网络。这表明,像App Store/iOS设备这样能提供低延迟性能的平台上的音乐应用能带来非常可观的收益比例。

    而在Android上就完全是另一回事了,音乐类应用的收入甚至进不了创收应用分类的前五。绝大多数安卓设备受困于极高的音频延迟,无法让开发者在Android上构建这类应用,以满足消费者的需求。因此,由于Android的10毫秒问题,Google和Android应用开发者就将这几十亿美元的蛋糕留给了苹果和iOS。

    这篇解释的目的,音频回路延迟可以简单概括为一段音频输入移动设备,经过一些必要的处理后,从同一设备输出的时间差。正如任何音乐人会告诉你的,我们人类在约10毫秒左右的延迟是最适合的,任何明显更高的延迟会给我们带来干扰。

    乐器应用和音效应用:音乐家无法在舞台上演奏,使用Android设备的演奏者总比其它人慢半拍。甚至无法用于练习。

    DJ无法进行节拍匹配,因为他们在耳机听到的信号要远远落后于播放给听众的主信号。使用循环滚动或回声等效果也是非常困难的。

    游戏:声音效果,例如爆炸和枪声会卡顿延迟几帧,使游戏音频“超脱”于视觉效果,这种糟糕的用户感受,无法带来身临其境的游戏体验。

    VoIP应用,如Skype:如果用户使用的是Android手机,整体的音频延迟要高于网络延迟。也就是说,“通过”安卓所花费的时间比数据包在各大洲之间传输的时间要更长。

    虚拟现实[VR]:当用户转头,音频“跟随”变化太晚,破坏了三维音频的体验。去试试Paul McCartney的Google纸板眼镜的app就是一个例子。Google将会在虚拟现实领域将十亿美元的收入拱手让给苹果。

    为了教导和提醒技术行业的领导者,应用开发者,技术人员,产品经理,管理人员,记者,企业家,音乐家,受Android的10毫秒问题影响的所有玩家和投资者,其存在对任何人都没有好处。你正在阅读的正是由我们Superpowered开发的一篇解读,对整个Android音频链和潜在的瓶颈作易于消化的概述分析。

    我们的目标是团结一致,挑战Android的10毫秒音频回路延迟,并将它转换成一个鼓励创新的机会,提供更好的用户体验,给Google Play用户、Android开发者、Android OEM厂商和整个Android生态系统带来获益。

    关于音频延迟的注意事项:

    毫秒(毫秒):一秒钟的1/1000。大多数的延迟使用这一测量单位,并发生在这个时间尺度。

    采样(或帧):表示音频流中的一个离散数字点(数字)。采样是软件将类似声波的连续信号转换成样本序列。样本是独立音频通道的数量。对于一个单通道信号,一个样本意味着一个数字。一个两声道信号的样本意味着两个数字等,以此类推。

    我们测量的是在以最好的条件下音频信号流的整体延迟:

    在Android的原生层音频[Android NDK]使用的是谷歌推荐的低延迟配置建议。不幸的是大多数安卓应用程序不遵循谷歌的低延迟推荐。

    在Andorid设备上配置得当,就可以使用“Fast Mixer混音器”用于音频输入和输出的通道。除了最新的Nexus机型[Nexus 9],大多数厂商并没未对Android系统配置支持Fast Mixer,因此这些设备的回路延迟将明显更高。可查看Superpowered's Mobile Audio Census and Latency Test App了解许多流行的Android设备的延迟测试数据。

    使用文本解释Android 5.0 Lollipop音频通道的延迟

    模拟音频输入

    可能会有几个模拟元件,例如内置麦克风的前级放大器。在这种情况下模拟组件可以被认为是“零延迟”,它们的延迟幅度通常低于1毫秒。

    延迟:0

    模拟数字转换(ADC)

    音频芯片在预定的时间间隔测量传入的音频流,并将每一次测量转换为一个数字。这个预定义的时间间隔被称为采样率,单位为Hz。我们的Mobile Audio Census and Latency Test App测试表明,48000Hz是多数Android和iOS设备上的音频芯片的原生采样率。这意味着音频流在每一秒被采样48000次。

    因为ADC的实现通常包含一个超采样滤波器,从大概经验上来说ADC的步骤会算为1毫秒。

    现在,音频流已经被数字化,从这点开始音频流成为了数字音频。数字音频几乎从未进行过一个接一个的传输,相反都是成堆的来,被称为缓冲[Buffers]或周期[Periods]。

    延迟:1ms

    从音频芯片到音频驱动的总线传输

    音频芯片有几个任务,它处理着ADC和DAC,交换或是混合多个输入和输出、音量控制等。并将分离的数字音频采样“集结”为缓冲并处理着这些缓冲区传递至操作系统。

    音频芯片通过一个总线连接至CPU,如USB、PCI、火线等。不同数据总线的延迟取决于它内部缓冲区的大小和数量。这里的延迟通常从1毫秒[内部系统总线的音频芯片]到6毫秒[USB声卡的在保守设置的USB总线上]。

    延迟:1-6ms

    音频驱动[ALSA、OSS等]

    音频驱动通过“总线缓冲区大小”步骤使用音频芯片的原生采样率[通常情况下是48000Hz]将接收的音频放入环形缓冲区[Ring Buffer]。

    此缓冲区是平滑总线传输抖动[Jitter]的重要组成部分,并将总线传输缓冲区与操作系统音频堆栈的缓冲区连接起来。环形缓冲的数消耗发生在操作系统音频堆栈的缓冲区,自然会增加一些延迟。

    Android运行于Linux之上,而且多数Android使用最流行的Linux音频驱动系统,ALSA[Advanced Linux Sound Architecture,高级Linux声音架构],ALSA是这样处理环形缓冲区的:

    音频从“周期大小”的环缓冲区中消耗。

    环形缓冲区的大小是“周期大小”的倍数。

    例如:

    周期大小= 480个采样。

    周期数= 2。

    环形缓冲区的大小是480x2 = 960采样。

    音频输入被接收到一个周期(480个样本),而音频堆栈读取/处理其他周期(480个样本)。

    延迟= 1周期,480个样本。它相当于48000Hz内的10毫秒。

    一个常见的周期数是2,但一些系统可能会更高..

    延迟:1个或多个周期

    Android音频硬件抽象层(HAL)

    HAL作为Android的媒体服务和Linux音频驱动之间的中间人,HAL是通过移动设备制造商将Android“移植”到Android设备上的实现。

    实现方式是开放的,厂商可以自由创建任何类型的HAL的代码,使用预定义的结构与媒体服务产生通信。媒体服务读取HAL并要求以可选的如采样率、缓冲区大小或音效等优化参数创建输入或输出流。

    注意:HAL可能或不会根据参数来运行,所以媒体服务必须“适配”HAL。

    TinyALSA就是典型的HAL实现,用于与ALSA音频驱动的通信。一些厂商在这里将他们认为重要的部分使用闭源代码实现音频功能。

    在分析了Android源代码库的多个开源的HAL实现代码后,我们发现有一些由于奇怪的配置和糟糕的代码显著增加了不必要的延迟和CPU负载。

    一个好的HAL实现不应有任何延迟。

    延迟:0或多个采样

    Audio Flinger

    Android的媒体服务由两个部分组成:

    AudioPolicy服务负责处理音频的会话和权限管理,如允许访问麦克风或通话中断,和iOS的音频会话管理非常类似。

    AudioFlinger服务处理音频流。

    Audio Flinger创建一个记录线程[RecordThread],作为应用程序和音频驱动之间的中间人。它的基本工作是:

    使用Android HAL在驱动的环形缓冲区获取下一个输入音频缓冲区。

    如果程序请求的缓冲采样率不同于原生的采样率,则进行重采样[SRC]。

    如果程序请求的缓冲大小与原生的不同,则执行附加缓冲。

    如果Android系统设置得当,Audio Flinger有一个“快速混音”通道。如果用户程序使用的是原生[Android NDK]代码并以原生的硬件采样率和周期大小设置音频缓冲队列,在这个步骤下就不会出现重采样、增加缓冲和混合[MixerThread]。

    记录线程[RecordThread]使用推送[push]的方式工作,不与音频驱动进行严格的同步。尝试以一种“受教猜测”的方式判断在何时候唤醒和执行,但push方式对中途放弃更加敏感。低延迟音频系统总是用拉送[pull]的方法,在音频驱动“决定”整个音频链的的输入和输出。很显然Android系统在最初设想,设计和开发中,低延迟音频并不是一个优先级。

    延迟:1周期[最佳情况]

    Binder

    在Android的主要进程间通信系统的共享内存用于Audio Flinger和用户程序之间的音频缓冲传输,它是Android的核心,在系统中无处不在。

    延迟:0

    AudioRecord

    现在我们在用户程序的进程里了,AudioRecord实现音频输入端的应用,这是一个客户端功能库[以通过OpenGL ES为例]。

    AudioRecord会以推送的机制理念定期运行一个线程从Audio Flinger处请求新的缓冲。如果开发者将其设置为只使用一组缓冲,就不会再音频通道中产生延迟。

    延迟:0+采样

    用户程序

    最后,音频输入到达它的目的地,用户应用程序。

    由于输入和输出线程是不同的,应用程序必须实现线程之间的环形缓冲区。它的大小是最低两个周期(1个音频输入和1个音频输出),但写不好的应用程序经常使用蛮力和更多的时间来解决处理器瓶颈。

    从这里开始,我们通过音频输出旅行回来了。

    延迟:大于1个周期,典型周期接近2[最佳情况]

    AudioTrack

    AudioTrack是用户程序段音频输出的实现。这是一个用户端功能库[以OpenGL ES为例],它定期发送一个线程向Audio Flinger发送音频缓冲。在Android 4.4.4以后,只使用一组缓冲的设置下不会为音频通道增加延迟。

    延迟:0+采样

    Binder

    同音频输入

    延迟:0

    Audio Flinger

    创建一个回放线程[PlaybackThread],工作流程和音频输入中RecordThread的描述相反。

    延迟:1周期[最佳情况]

    HAL

    和音频输入相同

    延迟:0或多个采样

    音频驱动[ALSA、OSS等]

    音频输出在音频驱动中的工作方式和音频输入一致,也使用一个环形缓冲区。

    延迟:0或更多周期

    从音频驱动到音频芯片的总线输出

    类似于音频输入的总线传输,这里的延迟通常也是1~6毫秒

    延迟:1~6毫秒

    数字模拟转换[DAC]

    ADC的逆向工作流程,数字音频“转换”回模拟音频。和在ADC的原因一样[超采样等],经验上架设DAC的延迟为1毫秒。

    延迟:1毫秒

    模拟音频输出

    DAC输出的信号是模拟音频,因此需要额外的元件来驱动外接设备,如耳机等,类似模拟音频输入,模拟组件可以被认为是“零延迟”。

     

     

     

     

    Android音频通道延迟的动画展示

    Android 5.0 Lollipop Audio Path Latency

    Android音频通道延迟的实例:Google Nexus 9

    到目前为止[2015年4月],Google Nexus 9是音频回路延迟测试中表现最好的Android设备。使用USB声卡或特殊的音频适配器直接连接耳机接口的麦克风输入和输出,以禁用内置麦克风阵列的降噪/反馈功能带来的约13毫秒的延迟,最低可以达到35毫秒。

    以上文的模型,让我们将Nexus 9的最低35ms延迟进行分解:

  • 点我查看各类手机的音频延迟测试成绩

    请评分
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    03
    我今天收到邮件,说他们已经解决10ms问题了,让安卓延迟在8ms左右,soomal有做下测试的打算么?
    发表于2016.06.16 18:52:41
    49
    113.116.031.***
    113.116.031.***
    发表于2016.03.31 16:44:09
    48
    113.066.131.***
    113.066.131.***
    发表于2016.03.28 14:47:05
    47
    119.140.207.***
    119.140.207.***
    发表于2016.02.15 15:39:58
    45
    060.010.071.***
    060.010.071.***
    发表于2016.02.04 23:15:35
    44
    116.023.245.***
    116.023.245.***
    发表于2016.02.02 13:02:52
    42
    03
    发表于2016.01.11 13:58:02
    41
    03
    看不懂,就知道安卓音频系统烂
    此帖使用SM-N9005提交
    发表于2016.01.10 13:21:43
    40
    10
    内含嵌入式文章,系统自动隐藏——详细阅读
    发表于2015.12.20 04:41:34
    39
    122.013.***.***
    122.013.***.***
    那么vivo的卡拉OK手机是怎样解决延迟的问题的
    发表于2015.12.19 22:28:10
    38
    113.065.254.***
    113.065.254.***
    发表于2015.12.18 12:52:15
    37
    所以我的锤子录唱吧,录全民K歌, 全部都要调2格人声才能跟伴奏对齐。

    这最少也有200ms的延迟吧。
    发表于2015.12.17 12:15:17
    36
    125.227.009.***
    125.227.009.***
    发表于2015.12.09 12:53:35
    34
    03
    搜索了下国产的几款手机,都在后半部分啊!
    发表于2015.12.08 13:15:27
    33
    061.230.159.***
    061.230.159.***
    发表于2015.12.07 22:59:47
    32
    113.071.***.***
    113.071.***.***
    所以很好奇像之前HTC的wp版手机音质到底如何 还有小米的刷了会怎样 特别是小米note后续也可以刷的情况下 音质会怎么 不过你们现在都不会测小米的产品了是吧
    发表于2015.12.07 22:46:56
    31
    134.117.***.***
    134.117.***.***
    你去随便写个比较复杂的Android音乐应用就知道Android这块的代码有多烂了,无数bug没修复。文档上显示的功能无法实现。整个就一团糟。
    此帖使用iPhone提交
    发表于2015.12.07 21:23:56
    30
    提示
    本贴不可匿名回复,回复等级为:1 ,您现在正处在潜水状态
    回复
    验证码
    9778 为防止广告机贴垃圾,不得已而为之
    表情
    正文