AndroidAudio系统概述.docx
《AndroidAudio系统概述.docx》由会员分享,可在线阅读,更多相关《AndroidAudio系统概述.docx(28页珍藏版)》请在冰豆网上搜索。
![AndroidAudio系统概述.docx](https://file1.bdocx.com/fileroot1/2023-2/23/c39c42cb-7ece-4554-a4c3-1e7b976884b8/c39c42cb-7ece-4554-a4c3-1e7b976884b81.gif)
AndroidAudio系统概述
AndroidAudio系统
7.1 Audio系统综述
Audio系统在Android中负责音频方面的数据流传输和控制功能,也负责音频设备的管理。
这个部分作为Android的Audio系统的输入/输出层次,一般负责播放PCM声音输出和从外部获取PCM声音,以及管理声音设备和设置。
Audio系统主要分成如下几个层次:
1.
(1)media库提供的Audio系统本地部分接口;
2.
(2)AudioFlinger作为Audio系统的中间层;
3.(3)Audio的硬件抽象层提供底层支持;
4.(4)Audio接口通过JNI和Java框架提供给上层。
Audio系统的各个层次接口主要提供了两方面功能:
放音(Track)和录音(Recorder)。
Android的Audio系统结构如图7-1所示。
图7-1 Android的Audio系统结构
Android系统的代码分布情况如下所示:
(1)Audio的Java部分
代码路径:
frameworks/base/media/java/android/media
与Audio相关的Java包是android.media,主要包含AudioManager和Audio系统的几个类。
(2)Audio的JNI部分
代码路径:
frameworks/base/core/jni
生成库libandroid_runtime.so,Audio的JNI是其中的一个部分。
(3)Audio的框架部分
头文件路径:
frameworks/base/include/media/
源代码路径:
frameworks/base/media/libmedia/
Audio本地框架是media库的一部分,本部分内容被编译成库libmedia.so,提供Audio部分的接口(包括基于Binder的IPC机制)。
(4)AudioFlinger
代码路径:
frameworks/base/libs/audioflinger
这部分内容被编译成库libaudioflinger.so,它是Audio系统的本地服务部分。
(5)Audio的硬件抽象层接口
头文件路径:
hardware/libhardware_legacy/include/hardware/
Audio硬件抽象层的实现在各个系统中可能是不同的,需要使用代码去继承相应的类并实现它们,作为Android系统本地框架层和驱动程序接口。
7.2 Audio系统和上层接口
在Android中,Audio系统自上而下由Java的Audio类、Audio本地框架类、AudioFlinger和Audio的硬件抽象层几个部分组成。
è7.2.1 Audio系统的各个层次
Audio系统的各层次情况如下所示。
Audio本地框架类是libmedia.so的一个部分,这些Audio接口对上层提供接口,由下层的本地代码去实现。
AudioFlinger继承libmeida中的接口,提供实现库libaudiofilnger.so。
这部分内容没有自己的对外头文件,上层调用的只是libmedia本部分的接口,但实际调用的内容是libaudioflinger.so。
Audio使用JNI和Java对上层提供接口,JNI部分通过调用libmedia库提供的接口来实现。
Audio的硬件抽象层提供到硬件的接口,供AudioFlinger调用。
Audio的硬件抽象层实际上是各个平台开发过程中需要主要关注和独立完成的部分。
提示:
Android的Audio系统不涉及编解码环节,只是负责上层系统和底层Audio硬件的交互,一般以PCM作为输入/输出格式。
在Android的Audio系统中,无论上层还是下层,都使用一个管理类和输出输入两个类来表示整个Audio系统,输出输入两个类负责数据通道。
在各个层次之间具有对应关系,如表7-1所示所示。
表7-1 Android各个层次的对应关系
Audio管理环节
Audio输出
Audio输入
Java层
android.media.AudioSystem
android.media.AudioTrack
android.media.AudioRecorder
本地框架层
AudioSystem
AudioTrack
AudioRecorder
AudioFlinger
IAudioFlinger
IAudioTrack
IAudioRecorder
硬件抽象层
AudioHardwareInterface
AudioStreamOut
AudioStreamIn
è7.2.2 media库中的Audio框架部分
Android的Audio系统的核心框架在media库中提供,对上面主要实现AudioSystem、AudioTrack和AudioRecorder三个类。
提供了IAudioFlinger类接口,在这个类中,可以获得IAudioTrack和IAudioRecorder两个接口,分别用于声音的播放和录制。
AudioTrack和AudioRecorder分别通过调用IAudioTrack和IAudioRecorder来实现。
Audio系统的头文件在frameworks/base/include/media/目录中,主要的头文件如下:
n AudioSystem.h:
media库的Audio部分对上层的总管接口;
n IAudioFlinger.h:
需要下层实现的总管接口;
n AudioTrack.h:
放音部分对上接口;
n IAudioTrack.h:
放音部分需要下层实现的接口;
n AudioRecorder.h:
录音部分对上接口;
n IAudioRecorder.h:
录音部分需要下层实现的接口。
IaudioFlinger.h、IAudioTrack.h和IAudioRecorder.h这三个接口通过下层的继承来实现(即AudioFlinger)。
AudioFlinger.h、AudioTrack.h和AudioRecorder.h是对上层提供的接口,它们既供本地程序调用(例如声音的播放器、录制器等),也可以通过JNI向Java层提供接口。
meida库中Audio部分的结构如图7-2所示。
meida库中Audio部分的结构
从功能上看,AudioSystem负责的是Audio系统的综合管理功能,而AudioTrack和AudioRecorder分别负责音频数据的输出和输入,即播放和录制。
AudioSystem.h中主要定义了一些枚举值和set/get等一系列接口,如下所示:
classAudioSystem
{
public:
enumstream_type{ //Audio流的类型
SYSTEM =1,
RING =2,
MUSIC =3,
ALARM =4,
NOTIFICATION =5,
BLUETOOTH_SCO =6,
ENFORCED_AUDIBLE=7,
NUM_STREAM_TYPES
};
enumaudio_output_type{ //Audio数据输出类型
//……省略部分内容 };
enumaudio_format{ //Audio数据格式
FORMAT_DEFAULT=0,
PCM_16_BIT,
PCM_8_BIT,
INVALID_FORMAT
};
enumaudio_mode{ //Audio模式
//……省略部分内容 };
enumaudio_routes{ //Audio路径类型
ROUTE_EARPIECE =(1<<0),
ROUTE_SPEAKER =(1<<1),
ROUTE_BLUETOOTH_SCO =(1<<2),
ROUTE_HEADSET =(1<<3),
ROUTE_BLUETOOTH_A2DP =(1<<4),
ROUTE_ALL =-1UL,
};
//……省略部分内容
staticstatus_tsetMasterVolume(floatvalue);
staticstatus_tsetMasterMute(boolmute);
staticstatus_tgetMasterVolume(float*volume);
staticstatus_tgetMasterMute(bool*mute);
staticstatus_tsetStreamVolume(intstream,floatvalue);
staticstatus_tsetStreamMute(intstream,boolmute);
staticstatus_tgetStreamVolume(intstream,float*volume);
staticstatus_tgetStreamMute(intstream,bool*mute);
staticstatus_tsetMode(intmode);
staticstatus_tgetMode(int*mode);
staticstatus_tsetRouting(intmode,uint32_troutes,uint32_tmask);
staticstatus_tgetRouting(intmode,uint32_t*routes);
//……省略部分内容
};
在Audio系统的几个枚举值中,audio_routes是由单独的位来表示的,而不是由顺序的枚举值表示,因此这个值在使用过程中可以使用“或”的方式。
例如,表示声音可以既从耳机(EARPIECE)输出,也从扬声器(SPEAKER)输出,这样是否能实现,由下层提供支持。
在这个类中,set/get等接口控制的也是相关的内容,例如Audio声音的大小、Audio的模式、路径等。
AudioTrack是Audio输出环节的类,其中最重要的接口是write(),主要的函数如下所示。
classAudioTrack
{
typedefvoid(*callback_t)(intevent,void*user,void*info);
AudioTrack(intstreamType,
uint32_tsampleRate =0, //音频的采样律
intformat =0, //音频的格式(例如8位或者16位的PCM)
intchannelCount =0, //音频的通道数
intframeCount =0, //音频的帧数
uint32_tflags =0,
callback_tcbf =0,
void*user =0,
intnotificationFrames=0);
void start();
void stop();
void flush();
void pause();
void mute(bool);
ssize_t write(constvoid*buffer,size_tsize);
//……省略部分内容
}
AudioRecord是Audio输入环节的类,其中最重要的接口为read(),主要的函数如下所示。
classAudioRecord
{
public:
AudioRecord(intstreamType,
uint32_tsampleRate =0, //音频的采样律
intformat =0, //音频的格式(例如8位或者16位的PCM)
intchannelCount =0, //音频的通道数
intframeCount =0, //音频的帧数
uint32_tflags =0,
callback_tcbf=0,
void*user=0,
intnotificationFrames=0);
status_t start();
status_t stop();
ssize_t read(void*buffer,size_tsize);
//……省略部分内容
}
AudioTrack和AudioRecord的read/write函数的参数都是内存的指针及其大小,内存中的内容一般表示的是Audio的原始数据(PCM数据)。
这两个类还涉及Auido数据格式、通道数、帧数目等参数,可以在建立时指定,也可以在建立之后使用set()函数进行设置。
在libmedia库中提供的只是一个Audio系统框架,AudioSystem、AudioTrack和AudioRecord分别调用下层的IAudioFlinger、IAudioTrack和IAudioRecord来实现。
另外的一个接口是IAudioFlingerClient,它作为向IAudioFlinger中注册的监听器,相当于使用回调函数获取IAudioFlinger运行时信息。
è7.2.3 AudioFlinger本地代码
AudioFlinger是Audio系统的中间层,在系统中起到服务作用,它主要作为libmedia提供的Audio部分接口的实现,其代码路径为:
frameworks/base/libs/audioflinger
AudioFlinger的核心文件是AudioFlinger.h和AudioFlinger.cpp,提供了类AudioFlinger,这个类是一个IAudioFlinger的实现,其主要接口如下所示:
classAudioFlinger:
publicBnAudioFlinger,publicIBinder:
:
DeathRecipient
{
public:
//……省略部分内容
virtualspcreateTrack( //获得音频输出接口(Track)
pid_tpid,
intstreamType,
uint32_tsampleRate,
intformat,
intchannelCount,
intframeCount,
uint32_tflags,
constsp&sharedBuffer,
status_t*status);
//……省略部分内容
virtual status_t setMasterVolume(floatvalue);
virtual status_t setMasterMute(boolmuted);
virtual status_t setStreamVolume(intstream,floatvalue);
virtual status_t setStreamMute(intstream,boolmuted);
virtual status_t setRouting(intmode,uint32_troutes,uint32_tmask);
virtual uint32_t getRouting(intmode)const;
virtual status_t setMode(intmode);
virtual int getMode()const;
virtualspopenRecord( //获得音频输出接口(Record)
pid_tpid,
intstreamType,
uint32_tsampleRate,
intformat,
intchannelCount,
intframeCount,
uint32_tflags,
status_t*status);
}
AudioFlinger主要提供createTrack()创建音频的输出设备IAudioTrack,openRecord()创建音频的输入设备IAudioRecord。
另外包含的就是一个get/set接口,用于控制。
AudioFlinger构造函数片段如下所示:
AudioFlinger:
:
AudioFlinger()
{
mHardwareStatus=AUDIO_HW_IDLE;
mAudioHardware=AudioHardwareInterface:
:
create();
mHardwareStatus=AUDIO_HW_INIT;
if(mAudioHardware->initCheck()==NO_ERROR){
mHardwareStatus=AUDIO_HW_OUTPUT_OPEN;
status_tstatus;
AudioStreamOut*hwOutput=
mAudioHardware->openOutputStream(AudioSystem:
:
PCM_16_BIT,0,0,&status);
mHardwareStatus=AUDIO_HW_IDLE;
if(hwOutput){
mHardwareMixerThread=
newMixerThread(this,hwOutput,AudioSystem:
:
AUDIO_OUTPUT_HARDWARE);
}else{
LOGE("Failedtoinitializehardwareoutputstream,status:
%d",status);
}
//……省略部分内容
mAudioRecordThread=newAudioRecordThread(mAudioHardware,this);
if(mAudioRecordThread!
=0){
mAudioRecordThread->run("AudioRecordThread",PRIORITY_URGENT_AUDIO);
}
}else{
LOGE("Couldn'teveninitializethestubbedaudiohardware!
");
}
}
从工作的角度看,AudioFlinger在初始化之后,首先获得放音设备,然后为混音器(Mixer)建立线程,接着建立放音设备线程,在线程中获得放音设备。
在AudioFlinger的AudioResampler.h中定义了一个音频重取样器工具类,如下所示:
classAudioResampler{
public:
enumsrc_quality{
DEFAULT=0,
LOW_QUALITY=1, //线性差值算法
MED_QUALITY=2, //立方差值算法
HIGH_QUALITY=3 //fixedmulti-tapFIR算法
};
staticAudioResampler*create(intbitDepth,intinChannelCount, //静态地创建函数
int32_tsampleRate,intquality=DEFAULT);
virtual~AudioResampler();
virtualvoidinit()=0;
virtualvoidsetSampleRate(int32_tinSampleRate); //设置重采样率
virtualvoidsetVolume(int16_tleft,int16_tright); //设置音量
virtualvoidresample(int32_t*out,size_toutFrameCount,
AudioBufferProvider*provider)=0;
};
这个音频重取样工具包含3种质量:
低等质量(LOW_QUALITY)将使用线性差值算法实现;中等质量(MED_QUALITY)将使用立方差值算法实现;高等质量(HIGH_QUALITY)将使用FIR(有限阶滤波器)实现。
AudioResampler中的AudioResamplerOrder1是线性实现,AudioResamplerCubic.*文件提供立方实现方式,AudioResamplerSinc.*提供FIR实现。
AudioMixer.h和AudioMixer.cpp中实现的是一个Audio系统混音器,它被AudioFlinger调用,一般用于在声音输出之前的处理,提供多通道处理、声音缩放、重取样。
AudioMixer调用了AudioResampler。
7.2.4 Audio系统的JNI代码
Android的Audio部分通过JNI向Java层提供接口,在Java层可以通过JNI接口完成Audio系统的大部分操作。
AudioJNI部分的代码路径为:
frameworks/base/core/jni。
其中,主要实现的3个文件为:
android_media_AudioSystem.cpp、android_media_AudioTrack.cpp和android_media_AudioRecord.cpp,它们分别对应了AndroidJava框架中的3个类的支持:
n android.media.AudioSystem:
负责Audio系统的总体控制;
n android.media.AudioTrack:
负责Audio系统的输出环节;
n android.media.AudioRecorder:
负责Audio系统的输入环节。
在Android的Java层中,可以对Audio系统进行控制和数据流操作,对于控制操作,和底层的处理基本一致;但是对于数据流操作,由于Java不支持指针,因此接口被封装成了另外的形式。
例如,对于音频输出,android_media_AudioTrack.cpp提供的是写字节和写短整型的接口类型。
staticjintandroid_