Audio Kit简介
Audio Kit(音频服务),针对提供场景化的音频播放、录制接口,帮助开发者快速构建音频高清采集及沉浸式播放能力。
亮点/特征
-
低时延播放
提供统一音频低时延/非低时延播放能力接口,通过垂直打通硬件,达成最低的音频输出时延。在游戏、提示/告警音、K歌等场景下,可以通过低时延接口,实现音频快速流畅播放。
-
低功耗播放
针对应用播放音乐、听书类长时间音频播放场景,为确保更佳续航体验,在亮/灭屏播放时采用差异化音频缓冲区处理机制,减少CPU被唤醒的频率来降低音频播放功耗。
-
音效模式
提供系统音效模式设置,应用可以按需开/关系统音效,确保最佳音效输出体验。
系统默认为音乐、听书、影院等不同场景进行相应音效处理,但应用内部自身也存在一些定制化音效,为确保最终音效不产生冲突,系统提供音效模式配置开关,允许应用按需开/关系统音效。
-
空间音频
提供空间音频能力,支持用户佩戴TWS耳机时,使用应用播放音源(立体声/多声道/AudioVivid格式),可主观感受到空间音频渲染效果(方位感/空间感)。
-
音振协同
提供音振协同能力接口,实现音频及振动流的低时延同步控制。达成在输入法中开启音频和振动效果,打字输入时音振协同、节奏一致,来电铃声和振动同时响起,铃音和振动节奏同步一致的体验。
开发说明
在每个功能中,会介绍多种实现方式以应对不同的使用场景,以及该场景相关的子功能点。比如在音频播放功能内,会同时介绍音频的并发策略、音量管理和输出设备等在操作系统中的处理方式,帮助开发者能够开发出功能覆盖更全面的应用。
本开发指导仅针对音频播放或录制本身,Audio Kit提供相关能力,不涉及UI界面、图形处理、媒体存储或其他相关领域功能。
在开发音频功能之前,尤其是要实现处理音频数据的功能前,建议开发者先了解声学相关的知识,帮助理解操作系统提供的API是如何控制音频系统,从而开发出更易用、体验更好的音视频类应用。建议了解的相关概念包括但不限于:
-
音频量化的过程:采样 > 量化 > 编码
-
音频量化过程的相关概念:模拟信号和数字信号、采样率、声道、采样格式、位宽、码率、常见编码格式(如AAC、MP3、PCM、WMA等)、常见封装格式(如WAV、MPA、FLAC、AAC、OGG等)
音频流介绍
在开发音频应用之前,还需要了解什么是音频流,它是HarmonyOS音频系统中的关键概念,在之后的章节中会多次提及。
音频流,是指音频系统中一个具备音频格式和音频使用场景信息的独立音频数据处理单元。可以表示播放,也可以表示录制,并且具备独立音量调节和音频设备路由切换能力。
音频流基础信息通过AudioStreamInfo表示,包含采样、声道、位宽、编码信息,是创建音频播放或录制流的必要参数,描述了音频数据的基本属性。在配置时开发者需要保证基础信息与传输的音频数据是相匹配的,音频系统才能正确处理数据。
音频流使用场景信息
除了基本属性,音频流还需要具备使用场景信息。基础信息只能对音频数据进行描述,但在实际的使用过程中,不同的音频流,在音量大小、设备路由、并发策略上是有区别的。系统就是通过音频流所附带的使用场景信息,为不同的音频流制定合适的处理策略,以达到更好的音频用户体验。
-
播放场景
音频播放场景的信息,通过StreamUsage进行描述。
StreamUsage指音频流本身的用途类型,包括媒体、语音通信、语音播报、通知、铃声等。
-
录制场景
音频流录制场景的信息,通过SourceType进行描述。
SourceType指音频流中录音源的类型,包括麦克风音频源、语音识别音频源、语音通话音频源等。
支持的音频格式
audio模块下的接口支持PCM编码,包括AudioRenderer、AudioCapturer、TonePlayer、OpenSL ES等。
音频格式说明:
-
支持的常用的音频采样率(Hz):8000、11025、12000、16000、22050、24000、32000、44100、48000、64000、8820012+、96000,17640012+、19200012+具体参考枚举AudioSamplingRate。
不同设备支持的采样率规格会存在差异。
-
支持单声道、双声道,具体参考AudioChannel。
-
支持的采样格式:U8(无符号8位整数)、S16LE(带符号的16位整数,小尾数)、S24LE(带符号的24位整数,小尾数)、S32LE(带符号的32位整数,小尾数)、F32LE(带符号的32位浮点数,小尾数),具体参考AudioSampleFormat。
由于系统限制,S24LE、S32LE、F32LE仅部分设备支持,请根据实际情况使用。
小尾数指的是小端模式,即数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。这种存储模式将地址的高低和数据的位权有效结合起来,高地址部分权值高,低地址部分权值低。
处理音频焦点事件
音频打断策略
多音频并发,即多个音频流同时播放。此场景下,如果系统不加管控,会造成多个音频流混音播放,容易让用户感到嘈杂,造成不好的用户体验。为了解决这个问题,系统预设了音频打断策略,对多音频播放的并发进行管控,只有持有音频焦点的音频流才可以正常播放,避免多个音频流无序并发播放的现象出现。
当应用开始播放音频时,系统首先为相应的音频流申请音频焦点,获得焦点的音频流可以播放;若焦点申请被拒绝,则不能播放。在音频流播放的过程中,若被其他音频流打断,则会失去音频焦点。当音频流失去音频焦点时,只能暂停播放。在应用播放音频的过程中,这些动作均由系统自行完成,无需应用主动触发。但为了维持应用和系统的状态一致性,保证良好的用户体验,推荐应用监听音频打断事件,并在收到音频打断事件(InterruptEvent)时做出相应处理。
为满足应用对多音频并发策略的不同需求,音频打断策略预设了两种焦点模式,针对同一应用创建的多个音频流,应用可通过设置焦点模式,选择由应用自主管控或由系统统一管控。
音频打断策略决定了应该对音频流采取何种操作,如暂停播放、继续播放、降低音量播放、恢复音量播放等,这些操作可能由系统或应用来执行。音频打断策略预置了两种打断类型,用于区分音频打断事件(InterruptEvent)的执行者。
焦点模式
音频打断策略预设了两种焦点模式(InterruptMode):
-
共享焦点模式(SHARE_MODE):由同一应用创建的多个音频流,共享一个音频焦点。这些音频流之间的并发规则由应用自主决定,音频打断策略不会介入。当其他应用创建的音频流与该应用的音频流并发播放时,才会触发音频打断策略的管控。
-
独立焦点模式(INDEPENDENT_MODE):应用创建的每一个音频流均会独立拥有一个音频焦点,当多个音频流并发播放时,会触发音频打断策略的管控。
应用可以按需选择合适的焦点模式,在创建音频流时,系统默认采用共享焦点模式,应用可主动设置所需的模式。
设置焦点模式的方法:
-
若使用AVPlayer开发音频播放功能,则可以通过修改AVPlayer的audioInterruptMode属性进行设置。
-
若使用AudioRenderer开发音频播放功能,则可以调用AudioRenderer的setInterruptMode函数进行设置。
-
若使用OHAudio开发音频播放功能(C/C++),则可以调用OH_AudioStreamBuilder_SetRendererInterruptMode函数进行设置。
打断类型
音频打断策略(包括两种焦点模式)决定了应该对各个音频流采取何种操作,如暂停播放、继续播放、降低音量播放、恢复音量播放等。而针对这些操作的执行过程,根据执行者的不同,可以分为两种打断类型(InterruptForceType):
-
强制打断类型(INTERRUPT_FORCE):由系统进行操作,强制打断音频播放。
-
共享打断类型(INTERRUPT_SHARE):由应用进行操作,可以选择打断或忽略。
对于音频打断策略的执行,系统默认采用强制打断类型(INTERRUPT_FORCE),应用无法更改。但对于一些策略(如继续播放等),系统无法强制执行,所以这两种打断类型均可能出现。应用可根据音频打断事件(InterruptEvent)的成员变量forceType的值,获取该事件采用的打断类型。
在应用播放音频的过程中,系统自动为音频流执行申请焦点、持有焦点、释放焦点等动作,当发生音频打断事件时,系统强制对音频流执行暂停、停止、降低音量、恢复音量等操作,并向应用发送音频打断事件(InterruptEvent)回调。由于系统会强制改变音频流状态,为了维持应用和系统的状态一致性,保证良好的用户体验,推荐应用监听音频打断事件,并在收到音频打断事件(InterruptEvent)时做出相应处理。
对于一些系统无法强制执行的操作(例如音频流继续播放的场景),会向应用发送包含了共享打断类型的音频打断事件,由应用自行执行相应操作,此时应用可以选择执行或忽略,系统不会干涉。
监听音频打断事件
在应用播放音频时,推荐应用监听音频打断事件,当音频打断事件发生时,系统会根据预设策略,对音频流做出相应的操作,并针对状态发生改变的音频流,向所属的应用发送音频打断事件。
应用收到音频打断事件后,需根据其内容提示,做出相应的处理,避免出现应用状态与预期效果不一致的问题。
监听音频打断事件的方法:
-
若使用AVPlayer开发音频播放功能函数进行监听,当收到音频打断事件(InterruptEvent)时,应用需根据其内容,做出相应的调整。
-
若使用AudioRenderer开发音频播放功能函数进行监听,当收到音频打断事件(InterruptEvent)时,应用需根据其内容,做出相应的调整。
-
若使用OHAudio开发音频播放功能(C/C++),则可以调用OH_AudioStreamBuilder_SetRendererCallback接口注册监听焦点回调事件,当收到音频打断事件(OH_AudioRenderer_OnInterruptEvent)时,应用需根据其内容,做出相应的调整。
为了带给用户更好的体验,针对不同的音频打断事件内容,应用需要做出相应的处理操作。此处以使用AudioRenderer开发音频播放功能为例,展示推荐应用采取的处理方法,提供伪代码供开发者参考(若使用AVPlayer开发音频播放功能或者使用OHAudio接口开发音频播放器功能,处理方法类似),具体的代码实现,开发者可结合实际情况编写,处理方法也可自行调整。
import { audio } from '@kit.AudioKit'; // 导入audio模块
import { BusinessError } from '@kit.BasicServicesKit'; // 导入BusinessError
let isPlay: boolean; // 是否正在播放,实际开发中,对应与音频播放状态相关的模块
let isDucked: boolean; //是否降低音量,实际开发中,对应与音频音量相关的模块
let started: boolean; // 标识符,记录“开始播放(start)”操作是否成功
async function onAudioInterrupt(): Promise<void> {
// 此处以使用AudioRenderer开发音频播放功能举例,变量audioRenderer即为播放时创建的AudioRenderer实例。
audioRenderer.on('audioInterrupt', async(interruptEvent: audio.InterruptEvent) => {
// 在发生音频打断事件时,audioRenderer收到interruptEvent回调,此处根据其内容做相应处理
// 1. 可选:读取interruptEvent.forceType的类型,判断系统是否已强制执行相应操作。
// 注:默认焦点策略下,INTERRUPT_HINT_RESUME为INTERRUPT_SHARE类型,其余hintType均为INTERRUPT_FORCE类型。因此对forceType可不做判断。
// 2. 必选:读取interruptEvent.hintType的类型,做出相应的处理。
if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_FORCE) {
// 强制打断类型(INTERRUPT_FORCE):音频相关处理已由系统执行,应用需更新自身状态,做相应调整
switch (interruptEvent.hintType) {
case audio.InterruptHint.INTERRUPT_HINT_PAUSE:
// 此分支表示系统已将音频流暂停(临时失去焦点),为保持状态一致,应用需切换至音频暂停状态
// 临时失去焦点:待其他音频流释放音频焦点后,本音频流会收到resume对应的音频打断事件,到时可自行继续播放
isPlay = false; // 此句为简化处理,代表应用切换至音频暂停状态的若干操作
break;
case audio.InterruptHint.INTERRUPT_HINT_STOP:
// 此分支表示系统已将音频流停止(永久失去焦点),为保持状态一致,应用需切换至音频暂停状态
// 永久失去焦点:后续不会再收到任何音频打断事件,若想恢复播放,需要用户主动触发。
isPlay = false; // 此句为简化处理,代表应用切换至音频暂停状态的若干操作
break;
case audio.InterruptHint.INTERRUPT_HINT_DUCK:
// 此分支表示系统已将音频音量降低(默认降到正常音量的20%),为保持状态一致,应用需切换至降低音量播放状态
// 若应用不接受降低音量播放,可在此处选择其他处理方式,如主动暂停等
isDucked = true; // 此句为简化处理,代表应用切换至降低音量播放状态的若干操作
break;
case audio.InterruptHint.INTERRUPT_HINT_UNDUCK:
// 此分支表示系统已将音频音量恢复正常,为保持状态一致,应用需切换至正常音量播放状态
isDucked = false; // 此句为简化处理,代表应用切换至正常音量播放状态的若干操作
break;
default:
break;
}
} else if (interruptEvent.forceType === audio.InterruptForceType.INTERRUPT_SHARE) {
// 共享打断类型(INTERRUPT_SHARE):应用可自主选择执行相关操作或忽略音频打断事件
switch (interruptEvent.hintType) {
case audio.InterruptHint.INTERRUPT_HINT_RESUME:
// 此分支表示临时失去焦点后被暂停的音频流此时可以继续播放,建议应用继续播放,切换至音频播放状态
// 若应用此时不想继续播放,可以忽略此音频打断事件,不进行处理即可
// 继续播放,此处主动执行start(),以标识符变量started记录start()的执行结果
await audioRenderer.start().then(() => {
started = true; // start()执行成功
}).catch((err: BusinessError) => {
started = false; // start()执行失败
});
// 若start()执行成功,则切换至音频播放状态
if (started) {
isPlay = true; // 此句为简化处理,代表应用切换至音频播放状态的若干操作
} else {
// 音频继续播放执行失败
}
break;
default:
break;
}
}
});
}
典型场景
以下列举一些典型的焦点适配场景。
先播应用类型 | 推荐流类型 | 后播应用类型 | 推荐流类型 | 推荐体验 | 适配方案 |
---|---|---|---|---|---|
视频 | STREAM_USAGE_MOVIE | 闹铃 | STREAM_USAGE_ALARM | 闹铃响起后,视频暂停播放;闹钟结束后,视频继续播放。 | 注册焦点事件监听,接收到INTERRUPT_HINT_PAUSE事件时,直接暂停视频播放,并更新UI界面。当闹铃结束后,视频应用接收到INTERRUPT_HINT_RESUME事件,重新启动播放。 |
音乐 | STREAM_USAGE_MUSIC | 电话铃声 | STREAM_USAGE_RINGTONE | 电话响铃后,音乐暂停播放;不接通或者接通再挂断后,音乐恢复播放。 | 注册焦点事件监听,接收到INTERRUPT_HINT_PAUSE事件时,直接暂停音乐播放,并更新UI界面。当电话结束后,视频应用接收到INTERRUPT_HINT_RESUME事件,重新启动播放。 |
音乐 | STREAM_USAGE_MUSIC | 音乐 | STREAM_USAGE_MUSIC | 后播音乐正常播放,先播音乐应用停止播放,UI变成停止播放状态。 | 先播应用注册焦点事件监听,接收到INTERRUPT_HINT_STOP事件时,停止音乐播放,并更新UI界面。 |
写在最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。
希望这一份鸿蒙学习文档能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员,可以直接领取这份资料
鸿蒙(HarmonyOS NEXT)5.0最新学习路线
路线图适合人群:
IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习文档
《鸿蒙 (HarmonyOS)开发入门教学视频》
《鸿蒙生态应用开发V3.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
●ArkTS语言
●安装DevEco Studio
●运用你的第一个ArkTS应用
●ArkUI声明式UI开发
.……
《鸿蒙开发进阶》
●Stage模型入门
●网络管理
●数据管理
●电话服务
●分布式应用开发
●通知与窗口管理
●多媒体技术
●安全技能
●任务管理
●WebGL
●国际化开发
●应用测试
●DFX面向未来设计
●鸿蒙系统移植和裁剪定制
……
《鸿蒙进阶实战》
●ArkTS实践
●UIAbility应用
●网络案例
……