Android NDK sample 之 native-audio

本文最后更新于:1 年前

Reference


启动页

4段音频:

  • Hello:单词hello的音频,存放在hello_clip.h文件中
  • Android:单词Android的音频,存放在android_clip.h文件中
  • Sawtooth:代码生成的单锯齿波,存放在内存中
  • Embedded soundtrack:一段纯音乐,存放在background.mp3文件中

4个控制:

  • Reverb:控制是否启用音频的回声音效(实测可以启用,但是启用后不能取消)
  • Mute:控制是否静音,效果就是不影响正在播放的声音的播放进度,但是听不到声音
  • Enable SP:控制是否启用立体声,启用之后,通过pan_uri可以调整声音从耳机左侧出来多一点 or 从耳机右侧出来多一点
  • volume_url:控制音量大小

URI播放功能不可用:
native uriPlayer is broken in android 21 and over, internal bug id: b/29321867 will re-open after it is fixed in later OSes

录音、播放功能:

  • Record:录音,固定5秒钟,存放到内存中
  • Playback:播放录音

OpenSL ES 基础

OpenSL_ES_Specification_1.0.1.pdf 部分内容摘抄。

(3.1.1)对象的状态机

  • Unrealized(未实现(初始状态)):对象处于活动状态但尚未分配资源。尚不能使用;它的接口方法还不能被调用。
  • Realized(实现): 对象的资源已分配,对象可用。
  • Suspended(挂起):对象的资源少于可用所需的资源,但它保持挂起时的状态。这种状态是可选的,因为面对资源损失,实现可以选择将对象置于挂起状态或未实现状态。

(3.1.5)创建一个对象的步骤

  1. 如果尚未创建引擎对象,则创建并实现引擎对象。
  2. 从此对象获取 SLEngineItf 接口。
  3. 调用此接口的相应对象创建方法。
  4. 如果调用成功,该方法将返回新对象的 SLObjectItf 接口。
  5. 处理完对象后,调用 SLObjectItf 的 Destroy() 方法来释放对象及其资源。

(4.1)OpenSL ES 对象

  1. Engine 对象
  2. Media 对象
  3. Metadata Extractor 对象
  4. Audio Output Mix 对象
  5. LED Array 对象
  6. Vibration Control 对象

(4.1.1)Engine 对象

OpenSL ES API 的入口点。此对象使您能够创建 OpenSL ES 中使用的所有其他对象。

engine 对象是特殊的,因为它是使用全局函数 slCreateEngine() 创建的。创建的结果是 engine 对象的 SLObjectItf 接口。

创建 engine 对象后,大部分工作将通过该对象公开的 SLEngineItf 接口完成。

engine 对象通过唯一的设备 ID 代表系统的各种多媒体相关设备。它支持 enumeration of audio input(枚举音频输入)、audio output(音频输出)、LED 和 vibrator devices(振动器)以及查询其功能的机制。

(4.1.2)Media 对象

media 对象通过在给定一组规定的输入和输出的情况下执行一些媒体处理任务来实现多媒体用例。media 对象包括(但不限于)呈现和捕获媒体流的对象,通常分别称为播放器和记录器。它们对音频数据进行操作。

(4.1.2.1)Data Source(数据源) 和 Sink Structures(接收器)

数据源是 media 对象的输入参数,指定 media 对象将从何处接收特定类型的数据(例如采样音频或 MIDI 数据)。
数据接收器也是 media 对象的输入参数,指定 media 对象将向何处发送特定类型的数据。

数据源和接收器的数量和类型因媒体对象而异。以下特征定义了数据源或接收器:

  • 它的数据定位器标识数据所在的位置。可能的定位器包括:

    • URIs(例如文件名)
    • 内存地址
    • IO设备
    • Output Mixes(输出混音)
    • Buffer queues(缓冲队列)
  • 它的数据格式标识了数据流的特征。可能的格式包括:

    • 基于 MIME 类型的格式
    • PCM 格式

(4.1.3)Metadata Extractor 对象

播放器对象支持读取媒体内容的元数据。但是,有时仅能够读取元数据而不必能够播放媒体就很有用。Metadata Extractor 对象可用于读取元数据,而无需为媒体播放分配资源。当应用程序只对呈现元数据感兴趣而不播放内容以及想要呈现多个文件的元数据时,特别推荐使用此对象。后者对于为演示目的生成播放列表特别有趣,因为播放器对象会不必要地分配播放资源。此外,播放器不能动态改变他们的数据源;因此,对于从多个文件中提取元数据,应用程序需要多次创建和销毁播放器对象,这既低效又可能导致堆碎片化。Metadata Extractor 对象没有数据接收器,但它有一个可以动态更改的数据源。

(4.1.4)Audio Output Mix 对象

API 允许将音频路由到多个音频输出,并包含一个 Audio Output Mix 对象,以促进此功能。应用程序从引擎检索输出混合对象,并且可以将该输出混合指定为媒体对象的接收器。Audio Output Mix 对象被指定为媒体对象的接收器,使用 SL_DATALOCATOR_OUTPUTMIX 数据定位器。引擎使用一组默认音频输出设备填充输出混合。应用程序可以通过 SLOutputMixItf 接口查询此设备列表或请求对其进行更改。API 不提供直接音频输出 IO 设备作为媒体对象的接收器。

(4.1.5)LED Array 对象

设备 LED 的控制是通过 LED 阵列对象处理的。查询 LED 阵列对象的功能和创建 LED 阵列对象是引擎级操作,而对单个 LED 的控制由对象处理。

(4.1.6)Vibration Control 对象

设备振动支持的控制是通过 Vibra 对象处理的。查询 Vibra 对象的能力和创建 Vibra 对象是引擎级别的操作,而实际振动的控制由对象处理。

(4.6)示例用例

(4.6.1)采样音频播放

Audio Player 对象用于采样音频播放。我们使用 engine 对象的 SLEngineItf 接口创建 Audio Player 和 Output Mix。同时,将 Audio Player 和 Output Mix 关联用于音频输出。我们还在创建时设置了 Audio Player 的数据源,数据源可以是指向本地文件系统中的音频文件的 URI。默认情况下,Output Mix 与系统相关的 default output device 相关联。

(4.6.4)录制音频

录音用例由 Audio Recorder 对象处理。我们使用引擎对象的 SLEngineItf 接口创建录音机对象。创建时,我们将其与音频数据源相关联,例如可以是 microphone(音频输入设备)。Audio Recorder 的数据接收器可以是指向本地文件系统中的音频文件的 URI,音频将被记录到该文件系统中。

(4.6.5)读取元数据

Metadata Extractor 对象将读取音频文件的元数据,而无需为音频播放分配资源。与其他用例一样,我们使用引擎对象的 SLEngineItf 接口创建对象,并在创建时设置元数据提取器的数据源。数据源通常是指向本地文件系统中的音频文件的 URI。但是,元数据提取器支持 SLDynamicSourceItf 接口,我们可以使用它来更改数据源。因此,我们可以从多个文件(连续)中提取元数据,而无需为每个文件创建新的 Metadata Extractor 对象。SLMetadataExtractionItf 和 SLMetadataTraversalItf 接口用于从文件中实际读取和遍历元数据。

(4.7.1)电话

(4.7.2)音乐

(4.7.4)数据源


(6.1)slCreateEngine

初始化引擎对象并为用户提供一个句柄。

(7)对象类型

(7.2)Audio Player

音频播放器媒体对象播放由数据源指定的一段内容,执行任何隐式解码,应用任何指定的处理,并将其呈现到数据接收器指定的目的地。

(7.3)Audio Recorder

音频记录器媒体对象将内容片段记录到数据接收器指定的目的地,从数据源指定的输入中捕获它并执行任何指定的编码或处理。

(7.4)Engine Object

此对象类型是 API 的入口点。一个实现应该能够创建至少一个这样的对象,但尝试创建更多实例(通过单个应用程序或多个不同的应用程序)可能会失败。

引擎对象支持通过其 SLEngineItf 接口创建所有 API 的对象,并通过其 SLEngineCapabilitiesItf 接口查询实现的功能。

(7.7)Metadata Extractor Object

此对象可用于读取元数据,而无需为媒体播放分配资源。当应用程序只对呈现元数据感兴趣而不播放内容以及想要呈现多个文件的元数据时,特别推荐使用此对象。后者对于为演示目的生成播放列表特别有趣,因为音频播放器会不必要地分配播放资源。此外,播放器不能动态改变他们的数据源;因此,对于从多个文件中提取元数据,应用程序需要多次创建和销毁播放器对象,这既低效又可能导致堆碎片化。

(7.9)Output Mix

输出混合对象表示一组音频输出设备,一个音频输出流被发送到这些设备。应用程序从引擎检索输出混合对象,并且可以将该输出混合指定为媒体对象的接收器。引擎必须至少支持一种输出混合,但它可能支持更多。API 不提供直接音频输出 IO 设备作为媒体对象的接收器。

输出混合是一个逻辑对象;它并不(必然)代表物理混合。因此,由混合对象及其与媒体对象的关联在逻辑上定义的混合的实际实现是一个实现细节。输出混音不代表系统的主混音。此外,混合对象表示应用程序对输出的贡献;实施可能会将此贡献与其他来源的输出混合。

(8)API

(8.12)SLBufferQueueItf

此接口用于流式传输音频数据。它提供了一种在播放器对象上排队缓冲区以供设备播放的方法。它还提供了每当队列中的缓冲区完成时调用的回调函数。缓冲区按它们排队的顺序播放。可以查询缓冲区队列的状态以提供有关缓冲区队列播放状态的信息。这个接口实现了一个简单的流媒体机制。

  • 尝试在数据源不是 SL_DATALOCATOR_BUFFERQUEUE 或 SL_DATALOCATOR_MIDIBUFFERQUEUE 类型的 media 对象上实例化 SLBufferQueueItf 是无效的,将失败。
  • 当播放器处于由 SLPlayItf 接口控制的 SL_PLAYSTATE_PLAYING 状态时,填充缓冲区将隐式开始播放。在队列中缓冲区不足导致饥饿的情况下,音频数据的播放会停止,但播放器仍保持在 SL_PLAYSTATE_PLAYING 状态,直到再次填充缓冲区,音频数据的播放才会恢复。请注意,排队缓冲区的饥饿会导致音频数据流中出现可听见的间隙。在播放器未处于播放状态的情况下,填充缓冲区不会启动音频播放。
  • 排队的缓冲区就地使用,设备不需要复制,尽管这可能取决于实现。应用程序开发人员应该知道,在缓冲区排队之后修改缓冲区的内容是未定义的,并且可能导致音频损坏。
  • 一旦入队的缓冲区完成播放,如回调通知所通知的那样,删除缓冲区或用新数据填充缓冲区并再次将缓冲区入队以进行播放是安全的。
  • 在转换到 SL_PLAYSTATE_STOPPED 状态时,播放光标返回到当前播放缓冲区的开头。
  • 在转换到 SL_PLAYSTATE_PAUSED 状态时,播放光标保持在缓冲区中的当前位置。
  • 对于数据源是缓冲区队列的播放器,无法在缓冲区内查找。尝试在具有缓冲队列作为数据源的媒体对象上实例化 SLSeekitf 接口将失败。

默认

  • 没有缓冲区排队
  • 没有注册回调方法
Callbacks描述
slBufferQueueCallback播放完缓冲区队列中的缓冲区后调用的回调函数。

Methods|描述|评论
–|–
Enqueue|向队列添加缓冲区。该方法将指向要排队的数据的指针和缓冲区的大小(以字节为单位)作为参数。缓冲区按使用此方法排队的顺序播放。|当播放器处于由 SLPlayItf 接口控制的 SL_PLAYSTATE_PLAYING 状态时,填充缓冲区将隐式开始播放。在队列中缓冲区不足导致饥饿的情况下,音频数据的播放会停止,但播放器仍保持在 SL_PLAYSTATE_PLAYING 状态,直到再次填充缓冲区,音频数据的播放才会恢复。请注意,排队缓冲区的饥饿会导致音频数据流中出现可听见的间隙。在播放器未处于播放状态的情况下,填充缓冲区不会启动音频播放。如果已达到使用 CreateAudioPlayer 或 CreateMidiPlayer 方法创建媒体对象时用作数据源的 SLDataLocator_BufferQueue 结构中指定的最大缓冲区数,则不会将该缓冲区添加到缓冲区队列,并返回 SL_RESULT_BUFFER_INSUFFICIENT。此时客户端应该等待,直到它收到缓冲区完成的回调通知,此时它可以将缓冲区排入队列。
Clear|释放当前在缓冲区队列中排队的所有缓冲区。不调用已释放缓冲区的回调函数。SLBufferQueueState 被重置为初始状态。|此方法会重置用于 GetPosition() 的 SLPlayItf 接口中使用的累积位置信息。
GetState|返回缓冲区队列的当前状态。|
RegisterCallback|设置在缓冲区完成时调用的回调函数。|RegisterCallback() 方法只能在媒体对象处于 SL_PLAYSTATE_STOPPED 状态时调用,以避免回调函数的删除和可能正在处理的回调之间的竞争条件。回调函数可以通过多次调用 RegisterCallback() 方法来更改,但仅限于媒体对象处于停止状态时。如果调用该方法时媒体对象不处于 SL_PLAYSTATE_STOPPED 状态,则返回 SL_RESULT_PRECONDITIONS_VIOLATED。

(8.16)SLEffectSendItf

此接口允许应用程序开发人员控制声音对辅助效果的贡献。辅助效果由其接口指针标识。 规范中唯一标准化的辅助效果是单个混响。一些实现可能会暴露其他辅助效果。

此界面需要启用辅助效果才能产生任何可听效果。对于混响效果,这需要在输出混合对象上公开 PresetReverb 或 EnvironmentalReverb。

音频播放器和 MIDI 播放器对象支持此接口。

默认

  • 直接level:0 mB(无level变化)
  • 没有启用效果发送。

Methods|描述|评论
–|–
EnableEffectSend|启用或禁用播放器对辅助效果的贡献。|如果实现无法将播放器的输出提供给指定的效果,则此方法可能会失败并返回值 SL_RESULT_RESOURCE_ERROR。如果 pAuxEffect 不是与效果发送接口一起使用的有效效果接口,则实现应返回 SL_RESULT_PARAMETER_INVALID。
IsEnabled|返回是否将播放器的输出输入到辅助效果中。|如果 pAuxEffect 不是与效果发送接口一起使用的有效效果接口,则实现应返回 SL_RESULT_PARAMETER_INVALID。
SetDirectLevel|设置声音的干(直接)路径level。
GetDirectLevel|获取播放器的干(直接)路径level。
SetSendLevel|为指定的辅助效果设置播放器的发送路径level。
GetSendLevel|获取指定辅助效果的播放器发送路径level。

(8.17)SLEngineItf

该接口公开了所有 OpenSL ES 对象类型的创建方法。

Methods|描述|评论
–|–
CreateLEDDevice|创建一个 LED 设备。|
CreateVibraDevice|创建振动器设备
CreateAudioPlayer|创建一个音频播放器对象。
CreateAudioRecorder|创建录音机。
CreateMidiPlayer|创建一个 MIDI 播放器。|如果在 pBankSrc 参数中提供了一个库,并且在 MIDI 源中嵌入了一个库,则播放器创建可能会失败并显示 SL_RESULT_FEATURE_UNSUPPORTED 代码。在这种情况下,建议应用程序尝试创建 MIDI 播放器而不在 pBankSrc 中提供库。如果应用程序计划单独使用 MIDI 消息接口 SLMIDIMessageItf 来提供 MIDI,则该应用程序可能希望将 pMIDISrc 设置为 NULL 从单个播放器到 MIDI 合成器的数据。
CreateListener|创建一个监听器。
Create3DGroup|创建一个 3D 组。
CreateOutputMix|创建输出混音器。
CreateMetadataExtractor|创建元数据提取器对象。
CreateExtensionObject|创建一个对象。此方法用于从规范外部定义的扩展对象。规范定义的对象必须由引擎接口中的特定创建方法创建。|如果引擎由于缺乏内存或资源而无法创建对象,它将分别返回 SL_RESULT_MEMORY_FAILURE 或 SL_RESULT_RESOURCE_ERROR 错误。由 pParameters 指向的 ObjectID 和数据结构应由扩展定义。当 ObjectID 无效时,该方法将返回 SL_RESULT_FEATURE_UNSUPPORTED。
QueryNumSupportedInterfaces|查询支持的可用接口数量。|支持的接口数量将包括对象可用的强制接口和可选接口。此方法可用于通过检查返回值来确定实现是否支持对象。
QuerySupportedInterfaces|查询支持的接口。|支持的接口数量将包括可用于对象的强制接口和可选接口。
QueryNumSupportedExtensions|查询支持的扩展数量。|支持的扩展数量将包括 Khronos 注册表中列出的标准化扩展和特定于供应商的扩展。
QuerySupportedExtension|根据给定的索引获取实现支持的扩展名。|如果给定的长度小于所需的大小,则返回 SL_RESULT_BUFFER_INSUFFICIENT 并且只会写入给定大小的数据; 但是,不会写入无效字符串。也就是说,空终止符始终存在,多字节字符不会在中间被截断。
IsExtensionSupported|查询实现是否支持给定的扩展。|这是一种替代方法,用于代替 QueryNumSupportedExtensions() 和 QuerySupportedExtension() 来查询仅一个已知扩展的可用性。

(8.19)SLEnvironmentalReverbItf

在特定声学环境中产生的声音通常通过许多不同的路径到达听众。听众首先听到来自声源本身的直达声。稍后,他会听到一些由附近墙壁、天花板或地板反弹的声音引起的离散回声。这些声音被称为早期反射。后来,随着声波在经过越来越多的反射后到达,各个反射变得难以区分,听众会听到随时间衰减的连续混响。下图说明了这种直接声、反射声和混响声的组合。请注意,反射level和混响level分别是早期反射和后期混响的总(积分)能量level,而不是峰值level。

此接口允许应用程序在全局混响环境中控制这些属性。此接口公开的混响控制基于 I3DL2 指南,限制是高频参考level固定为 5 kHz。

当这个接口暴露在输出混音上时,它作为一个辅助效果;要将混响应用于播放器的输出,SLEffectSendItf 接口必须在播放器上公开。

公开此接口时必须遵守以下限制:

  • 当同一对象的 SLPresetReverbItf 接口已经公开时,无法公开此接口。

输出混合对象支持此接口。

高频衰减
当声音被房间内的物体反射时,其高频通常比低频衰减得更快。此接口可控制对混响和反射的高频分量应用多少衰减。衰减是使用一个设置来控制的,该设置指定了 5 kHz 以上频率(高频)相对于低频的衰减level(以毫贝为单位)。这允许不同的实现为内部低通滤波器使用不同的滤波器设计(例如一极、二极)。

默认

  • 房间level:SL_MILLIBEL_MIN mB
  • 房间高频level:0 mB
  • 衰减时间:1000 毫秒
  • 衰减高频比:500‰
  • 反射延迟:20 毫秒
  • 反射level:SL_MILLIBEL_MIN mB
  • 混响level:SL_MILLIBEL_MIN mB
  • 混响延迟:40 毫秒
  • 扩散:1000‰
  • 密度:1000‰

Methods|描述|评论
–|–
SetRoomLevel|设置环境混响效果的主音量level。
GetRoomLevel|获取环境混响效果的主音量level。
SetRoomHFLevel|相对于整体混响效果的低频音量level,将音量level设置为 5 kHz。|这控制了一个低通滤波器,将降低高频level。
GetRoomHFLevel|获取房间的高频level
SetDecayTime|设置混响level衰减 60 dB 所需的时间。
GetDecayTime|获取混响level衰减 60 dB 所需的时间。
SetDecayHFRatio|设置高频衰减时间(5 kHz)相对于低频衰减时间的比率。
GetDecayHFRatio|获取高频衰减时间(5 kHz)相对于低频衰减时间的比率。
SetReflectionsLevel|设置早期反射的音量level。|此level与整体房间level相结合(使用 SetRoomLevel 设置)
GetReflectionsLevel|获取早期反射的音量level。
SetReflectionsDelay|设置早期反射的延迟时间。|此方法设置听到直接路径和听到第一次反射之间的时间。
GetReflectionsDelay|获取早期反射的延迟时间。
SetReverbLevel|设置后期混响的音量level。|此level与整体房间level(使用 SetRoomLevel 设置)相结合。
GetReverbLevel|获取后期混响的音量level。
SetReverbDelay|设置第一次反射和混响之间的时间。
GetReverbDelay|获取第一次反射和混响之间的时间。
SetDiffusion|设置后期混响衰减中的回声密度。|比例尺应近似线性映射到感知的混响变化。
GetDiffusion|获取后期混响衰减中的回声密度。
SetDensity|控制后期混响衰减的模态密度。|比例应该近似线性映射到混响的感知变化。较低的密度会产生空心的声音,这对于模拟小的混响空间(如浴室)很有用。
GetDensity|获取后期混响衰减的模态密度。
SetEnvironmentalReverbProperties|在一个方法调用中设置所有环境属性。|这可以与环境混响预设定义一起使用。
例如:
SLEnvironmentalReverbSettings ReverbSettings = SL_I3DL2_ENVIRONMENT_PRESET_BATHROOM;
/* Change reverb environment to bathroom.*/
pReverb->SetEnvironmentalReverbProperties(pReverb, &ReverbSettings);
建议开发人员在给定时间更改多个参数时使用此方法,因为这样可以减少不必要的处理量。
GetEnvironmentalReverbProperties|获取环境的所有属性。

(9.1.17)SLEnvironmentalReverbSettings

这个结构可以存储所有的环境混响设置。

Field描述
roomLevel以毫贝尔为单位的环境音量level。有效范围是 [SL_MILLIBEL_MIN, 0]。
roomHFLevel以毫贝尔为单位的高频衰减level。有效范围是 [SL_MILLIBEL_MIN, 0]。
decayTime以毫秒为单位的衰减时间。有效范围是 [100, 20000]。
decayHFRatio使用 permille 标度的高频参考 (5 kHz) 下的相对衰减时间。有效范围是 [100, 2000]。
reflectionsLevel以毫贝尔为单位的早期反射衰减level。有效范围是 [SL_MILLIBEL_MIN, 1000]。
reflectionsDelay早期反射延迟长度以毫秒为单位。有效范围是 [0, 300]。
reverbLevel以毫贝尔为单位的后期混响level。有效范围是 [SL_MILLIBEL_MIN, 2000]。
reverbDelay以毫秒为单位的后期混响延迟。有效范围是 [0, 100]。
diffusion以 permilles 表示的扩散level。有效范围是 [0, 1000]。
density密度level以 permilles 表示。有效范围是 [0, 1000]。

(8.29)SLObjectItf

SLObjectItf 接口为所有对象提供基本的实用方法。此类功能包括对象的销毁、实现和恢复、接口指针的获取、运行时错误的回调以及异步操作终止。

在任何给定时间,一个对象最多可以执行一个异步操作。当对象已经在处理异步调用时尝试调用异步操作等同于中止第一个操作,然后调用第二个操作。

SLObjectItf 是所有对象类型的隐式接口,在创建每个对象时自动可用。

默认

  • 对象处于未实现状态。
  • 没有注册回调。
Callbacks描述
slObjectCallback回调函数,通知运行时错误、异步调用终止或对象资源状态的更改。

Methods|描述|评论
–|–
Realize|同步或异步地将对象从 Unrealized 状态转换到 Realized 状态。|实现对象获取其功能所需的资源。如果可用资源不足,操作可能会失败。在这种情况下,应用程序可能会等到资源变得可用并收到 SL_OBJECT_EVENT_RESOURCES_AVAILABLE 事件,然后重试实现。另一种选择是尝试提高对象的优先级,从而增加对象窃取另一个对象资源的可能性。
Resume|同步或异步地将对象从挂起状态转换到已实现状态。|恢复对象获取其功能所需的资源。如果可用资源不足,操作可能会失败。在这种情况下,应用程序可能会等待资源变得可用并收到 SL_OBJECT_EVENT_RESOURCES_AVAILABLE 事件,然后重试恢复。另一种选择是尝试提高对象的优先级,从而增加对象窃取另一个对象资源的可能性。
GetState|检索当前对象状态。
GetInterface|获取对象暴露的接口|如果对象未公开请求的接口类型,则返回代码将为 SL_RESULT_FEATURE_UNSUPPORTED。
RegisterCallback|在发生运行时错误或异步操作终止时执行的对象上注册回调。|回调将仅报告运行时错误和调用异步函数的结果。
AbortAsyncOperation|中止对象当前处理的异步调用。此方法仅影响从 SLObjectItf 或 XADynamicInterfaceManagementItf 发起的异步调用。如果没有处理此类调用,则忽略该调用。如果注册了回调,它将被调用,SL_OBJECT_EVENT_ASYNC_TERMINATION 作为事件,SL_RESULT_OPERATION_ABORTED 作为返回码。|该方法用于正常超时或用户启动的异步调用中止。
Destroy|销毁对象|Destroy 通过 Unrealized 状态隐式传输对象,从而在释放对象之前释放分配给对象的所有资源。对属于此对象的接口的所有引用都将变为无效,并且如果使用可能会导致未定义的行为。所有挂起的异步操作都被中止,就好像 AbortAsyncOperations() 已被调用。
SetPriority|设置对象的优先级。|尽管可以在指定范围内设置任何优先级,但 SL_PRIORITY 定义了一组固定的优先级用于此方法。
GetPriority|获取对象的优先级。
SetLossOfControllnterfaces|设置/取消设置接口 ID 列表的失控功能。启用标志的默认值由全局设置确定。|对此方法的调用将覆盖指定接口列表的失控功能的全局设置。

(8.32)SLPlayItf

SLPlayItf 是一个用于控制对象播放状态的接口。

默认
最初,播放状态为 SL_PLAYSTATE_STOPPED,位置在内容的开头,更新周期为一秒,没有设置标记,也没有注册回调,回调事件标志被清除。

Callbacks描述
slPlayCallback通知播放器应用程序播放事件。

Methods|描述|评论
–|–
SetPlayState|请求播放器转换到给定的播放状态。|所有状态转换都是合法的。状态默认为 SL_PLAYSTATE_STOPPED。请注意,尽管状态更改是立即发生的,但此方法的执行与其对行为的影响之间可能存在一些延迟。从这个意义上说,播放器的状态在技术上代表了应用程序对播放器的意图。请注意,播放器的状态会影响播放器的预取状态(有关详细信息,请参阅 SLPrefetchStatusItf)。播放器可能会分别返回 SL_RESULT_PERMISSION_DENIED、SL_RESULT_CONTENT_CORRUPTED 或 SL_RESULT_CONTENT_UNSUPPORTED 如果在请求状态更改时检测到权限不足、内容损坏或内容不受支持。当播放器到达内容结尾时,播放状态将转换为暂停和暂停,播放光标将停留在内容的末尾。
GetPlayState|获取播放器当前的播放状态|
GetDuration|获取当前内容的持续时间,以毫秒为单位。|在数据源为缓冲队列的情况下,当前时长是自上次缓冲队列Clear()方法以来所有缓冲的累计时长。
GetPosition|返回播放头相对于内容开头的当前位置。|返回值介于 0 和内容的持续时间之间。在数据源为缓冲队列的情况下,当前位置是自上次缓冲队列Clear()方法以来所有缓冲的累计持续时间。请注意,位置是相对于以 1 倍前进速率播放的内容定义的; 位置不会随着播放速率的变化而缩放。
RegisterCallback|设置播放回调函数。|回调函数默认为 NULL。
应用程序可以使用上下文指针将状态传递给回调函数。
SetCallbackEventsMask|启用/禁用播放事件的通知。|回调事件标志默认为清除所有标志。
GetCallbackEventsMask|查询播放事件的通知状态(启用/禁用)。|
SetMarkerPosition|设置播放标记的位置。|当播放头通过标记时,播放器将通过带有 SL_PLAYEVENT_HEADATMARKER 事件的回调通知应用程序。默认情况下,没有定义标记位置。当标记位置与周期性位置更新(由 SetPositionUpdatePeriod() 指定)重合时,标记位置回调和周期性位置更新回调必须彼此相邻发布。两个回调的顺序无关紧要。
ClearMarkerPosition|清除标记。|即使标记已经清除,此功能也会成功。
GetMarkerPosition|查询播放标记的位置。|
SetPositionUpdatePeriod|设置定期位置通知之间的间隔。|当播放头通过指定时间段所暗示的位置时,播放器将通知应用程序。这些位置被定义为相对于内容开头的周期的整数倍。默认情况下,更新周期为 1000 毫秒。当周期性位置更新与标记位置重合时(由 SetMarkerPosition() 指定),则位置更新周期回调和标记位置回调必须彼此相邻发布。两个回调的顺序无关紧要。
GetPositionUpdatePeriod|查询周期性位置通知的间隔时间。|

(8.37)SLRecordItf

SLRecordItf 是一个用于控制对象录制状态的接口。录制的状态机如下:

如果在记录到文件时存储介质变满,SL_OBJECT_EVENT_RUNTIME_ERROR 将通过 slObjectCallback 发布,SL_RESULT_IO_ERROR 作为此回调的结果参数。在这种情况下,记录器将自动转换到 SL_RECORDSTATE_STOPPED 状态。

默认
记录器默认为 SL_RECORDSTATE_STOPPED 状态,没有标记,没有持续时间限制,更新周期为一秒,没有设置标记,也没有注册回调,回调事件标志被清除。

Callbacks描述
slRecordCallback通知记录器应用程序记录事件。

Methods|描述|评论
–|–
SetRecordState|将记录器转换为给定的记录状态。|所有状态转换都是合法的。
GetRecordState|获取记录器的当前记录状态。|
SetDurationLimit|以毫秒为单位设置当前内容的持续时间。|当记录器达到限制时,它会自动转换到 SL_RECORDSTATE_STOPPED 状态并通过 SL_RECORDEVENT_HEADATLIMIT 事件通知应用程序。
GetPosition|返回记录头相对于内容开头的当前位置。|该位置与记录的内容量同义。
RegisterCallback|注册记录回调函数。|
SetCallbackEventsMask|设置记录事件的通知状态。|回调事件标志默认为清除所有标志。
GetCallbackEventsMask|查询记录事件的通知状态。|
SetMarkerPosition|设置记录标记的位置。|当录音头通过标记时,播放器将通过带有 SL_RECORDEVENT_HEADATMARKER 事件的回调通知应用程序。
ClearMarkerPosition|清除标记。|即使标记已经清除,此功能也会成功
GetMarkerPosition|查询录音标记的位置。|
SetPositionUpdatePeriod|设置定期位置通知之间的间隔。|当记录头通过指定时间段所暗示的位置时,记录器将通知应用程序。这些位置被定义为相对于内容开头的周期的整数倍。
GetPositionUpdatePeriod|查询周期性位置通知的间隔时间。

(8.38)SLSeekItf

SeekItf 是一个操作播放头的接口,包括设置它的位置和循环特性。如果支持,则可以使用搜索,而不管播放状态或速率如何。
音频播放器和 MIDI 播放器对象支持此接口。

默认
播放位置默认为 0 毫秒(当前内容的开始)。默认情况下禁用全局和本地循环。

Methods|描述|评论
–|–
SetPosition|设置播放头的位置|该实现可以将位置设置为最近的离散样本或帧。请注意,位置是相对于以 1 倍前进速率播放的内容定义的;位置不会随着播放速率的变化而缩放。
SetLoop|启用或禁用循环并设置循环的起点和终点。当循环开启并且播放头到达结束位置时,播放器自动将头设置到开始位置并保持在 SL_PLAYSTATE_PLAYING 状态。设置循环不会对播放头产生任何影响,即使在设置循环时头在循环之外。|如果不支持本地循环,则此方法返回 SL_RESULT_FEATURE_UNSUPPORTED。
GetLoop|查询循环是开启还是关闭,并检索循环点。

(8.43)SLVolumeItf

此接口公开用于操作对象的音频音量属性的控件。

此接口还公开了立体声位置控制。它的确切效果取决于对象的格式;如果对象的格式为单声道,则应用平移效果,如果对象的格式为立体声,则应用平衡效果。

音频播放器、MIDI 播放器和输出混合对象支持此接口。

默认

  • 音量level:0 mB
  • 静音:禁用(不静音)
  • 立体声位置:禁用,0‰(中心)

Methods|描述|评论
–|–
SetVolumeLevel|设置对象的音量level。|如果对象被静音,对 SetVolumeLevel() 的调用仍将更改内部音量level,但这在对象取消静音之前不会产生声音效果。
GetVolumeLevel|获取对象的音量level。
GetMaxVolumeLevel|获取支持的最大level。|支持的最大level取决于实现,但始终至少为 0 mB。
SetMute|使对象静音或取消静音|使对象静音不会改变 GetVolumeLevel() 报告的音量level。当对象已经静音时调用 SetMute() 并将静音设置为 true 是一个有效的操作,没有任何效果。调用 SetMute() 时静音设置为 false 对象已经取消静音是一个无效的有效操作。
GetMute|检索对象的静音状态
EnableStereoPosition|启用或禁用立体定位效果。|如果对象的输出是单声道的,则此设置没有任何效果。
IsEnabledStereoPosition|返回立体声定位效果的启用状态。|如果对象的输出是单声道的,则此设置没有任何效果。
SetStereoPosition|设置对象的立体位置;对于单声道对象,这将控制恒定能量平移效果,对于立体声对象,这将控制平衡效果。|用于此方法的确切平移和平衡曲线取决于实现,但要满足参数描述。对于(输入)格式为单声道的对象,此方法控制恒定能量平移效果。对于(输入)格式为立体声的对象 ,此方法控制平衡效果。如果对象的输出是单声道的,则此设置没有任何效果。
GetStereoPosition|获取对象的立体位置设置。


代码

native-audio


分析

1、时序图(app启动后~点击任何按钮前)

2.1、流程图(点击Hello或Android按钮)

2.2、流程图(点击Sawtooth按钮)

2.3、时序图(点击Embedded soundtrack按钮)

2.4、时序图(点击Record按钮)

2.5、流程图(点击Playback按钮)



Android NDK sample 之 native-audio
https://weichao.io/e434a01b9a8a/
作者
魏超
发布于
2021年8月12日
更新于
2021年8月12日
许可协议