acoustics和汽车audio是什么意思意思的区别

Bongiovi Acoustics | The Ultimate Audio Solution
Element Electronics and Bongiovi Acoustics Break the “Sound” Barrier
Wicked Audio Unveils Revolt Headphones with DPS technology
An exciting technology announcement…
Bongiovi Acoustics Digital Power Station(TM)
What is DPS?博客访问: 275290
博文数量: 168
博客积分: 3010
博客等级: 中校
技术积分: 1774
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: LINUX
/art/672.htm第7章 Android的Audio系统
本章介绍Android的音频系统内容,主要是音频的输入/输出环节,不涉及编解码的内容(音频系统从驱动程序、本地框架到Java框架都具有内
容)。本章介绍Audio系统各个层次的内容、Audio硬件抽象层的实现。
在学习本章的过程中,读者应重点关注以下内容:
Audio系统结构(知识性内容)
在Java中调用Audio系统的方式(知识性内容)
Audio系统本地代码的接口(开发要点)
Audio硬件抽象层的实现(开发要点)
7.1& Audio系统综述
Audio系统在Android中负责音频方面的数据流传输和控制功能,也负责音频设备的管理。这个部分作为Android的Audio系统的输入
/输出层次,一般负责播放PCM声音输出和从外部获取PCM声音,以及管理声音设备和设置。
Audio系统主要分成如下几个层次:
(1)media库提供的Audio系统本地部分接口;
(2)AudioFlinger作为Audio系统的中间层;
(3)Audio的硬件抽象层提供底层支持;
(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)Audio Flinger
代码路径: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各个层次的对应关系
android.media.
AudioSystem
android.media
AudioTrack
android.media.
AudioRecorder
本地框架层
AudioSystem
AudioTrack
AudioRecorder
AudioFlinger
IAudioFlinger
IAudioTrack
IAudioRecorder
硬件抽象层
AudioHardwareInterface
AudioStreamOut
AudioStreamIn7.2.2& media库中的Audio框架部分
Android的Audio系统的核心框架在media库中提供,对上面主要实现AudioSystem、AudioTrack和
AudioRecorder三个类。
提供了IAudioFlinger类接口,在这个类中,可以获得IAudioTrack和IAudioRecorder两个接口,分别用于声音的播
放和录制。AudioTrack和AudioRecorder分别通过调用IAudioTrack和IAudioRecorder来实现。
Audio系统的头文件在frameworks/base/include/media/目录中,主要的头文件如下:
AudioSystem.h:media库的Audio部分对上层的总管接口;
IAudioFlinger.h:需要下层实现的总管接口;
AudioTrack.h:放音部分对上接口;
IAudioTrack.h:放音部分需要下层实现的接口;
AudioRecorder.h:录音部分对上接口;
IAudioRecorder.h:录音部分需要下层实现的接口。
IAudioFlinger.h、IAudioTrack.h和IAudioRecorder.h这三个接口通过下层的继承来实现(即
AudioFlinger)。AudioFlinger.h、AudioTrack.h和AudioRecorder.h是对上层提供的接口,它们既供本
地程序调用(例如声音的播放器、录制器等),也可以通过JNI向Java层提供接口。
meida库中Audio部分的结构如图7-2所示。
(点击查看大图)图7-2&
meida库中Audio部分的结构
从功能上看,AudioSystem负责的是Audio系统的综合管理功能,而AudioTrack和AudioRecorder分别负责音频数据
的输出和输入,即播放和录制。
AudioSystem.h中主要定义了一些枚举值和set/get等一系列接口,如下所示:
class&AudioSystem &{ &public: &&&&&enum&stream_type&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&SYSTEM&&&&&&&&&&=&1, &&&&&&&&&RING&&&&&&&&&&&&=&2, &&&&&&&&&MUSIC&&&&&&&&&&&=&3, &&&&&&&&&ALARM&&&&&&&&&&&=&4, &&&&&&&&&NOTIFICATION&&&&=&5, &&&&&&&&&BLUETOOTH_SCO&&&=&6, &&&&&&&&&ENFORCED_AUDIBLE&=&7, &&&&&&&&&NUM_STREAM_TYPES &&&&&}; &&&&&enum&audio_output_type&{&&&&&&&&&&&&&&&&&&&&&&&&&&enum&audio_format&{&&&&&&&&&&&&&&&&&&&&&&&&&&FORMAT_DEFAULT&=&0, &&&&&&&&&PCM_16_BIT, &&&&&&&&&PCM_8_BIT, &&&&&&&&&INVALID_FORMAT &&&&&}; &&&&&enum&audio_mode&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&enum&audio_routes&{&&&&&&&&&&&&&&&&&&&&&&&&&&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, &&&&&}; &&&&&&&&&&static&status_t&setMasterVolume(float&value); &&&&&static&status_t&setMasterMute(bool&mute); &&&&&static&status_t&getMasterVolume(float*&volume); &&&&&static&status_t&getMasterMute(bool*&mute); &&&&&static&status_t&setStreamVolume(int&stream,&float&value); &&&&&static&status_t&setStreamMute(int&stream,&bool&mute); &&&&&static&status_t&getStreamVolume(int&stream,&float*&volume); &&&&&static&status_t&getStreamMute(int&stream,&bool*&mute); &&&&&static&status_t&setMode(int&mode); &&&&&static&status_t&getMode(int*&mode); &&&&&static&status_t&setRouting(int&mode,uint32_t&routes,&uint32_t&mask); &&&&&static&status_t&getRouting(int&mode,&uint32_t*&routes); &&&&&&};&
在Audio系统的几个枚举值中,audio_routes是由单独的位来表示的,而不是由顺序的枚举值表示,因此这个值在使用过程中可以使用"
或"的方式。例如,表示声音可以既从耳机(EARPIECE)输出,也从扬声器(SPEAKER)输出,这样是否能实现,由下层提供支持。在这个类
中,set/get等接口控制的也是相关的内容,例如Audio声音的大小、Audio的模式、路径等。
AudioTrack是Audio输出环节的类,其中最重要的接口是write(),主要的函数如下所示。class&AudioTrack &{ &&&&&typedef&void&(*callback_t)(int&event,&void*&user,&void&*info); &&&&&AudioTrack(&int&streamType, &&&&&&&&&&&&&&&&&uint32_t&sampleRate&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&int&format&&&&&&&&&&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount&&&&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&int&frameCount&&&&&&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&flags&&&&&&&=&0, &&&&&&&&&&&&&&&&&callback_t&cbf&&&&&&&=&0, &&&&&&&&&&&&&&&&&void*&user&&&&&&&&&&&=&0, &&&&&&&&&&&&&&&&&int&notificationFrames&=&0); &&&&&void&&&&&&&&start(); &&&&&void&&&&&&&&stop(); &&&&&void&&&&&&&&flush(); &&&&&void&&&&&&&&pause(); &&&&&void&&&&&&&&mute(bool); &&&&&ssize_t&&&&&write(const&void*&buffer,&size_t&size); &&}&
AudioRecord是Audio输入环节的类,其中最重要的接口为read(),主要的函数如下所示。class&AudioRecord &{ &public: &&&&&AudioRecord(int&streamType, &&&&&&&&&&&&&&&&&uint32_t&sampleRate&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&int&format&&&&&&&&&&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount&&&&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&int&frameCount&&&&&&&=&0,&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&flags&&&&&&=&0, &&&&&&&&&&&&&&&&&callback_t&cbf&=&0, &&&&&&&&&&&&&&&&&void*&user&=&0, &&&&&&&&&&&&&&&&&int&notificationFrames&=&0); &&&&&status_t&&&&start(); &&&&&status_t&&&&stop(); &&&&&ssize_t&&&&&read(void*&buffer,&size_t&size); &&}&
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的实现,其主要接口如下所示:class&AudioFlinger&:&public&BnAudioFlinger,&public&IBinder::DeathRecipient &{ &public: &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&virtual&sp&createTrack(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pid_t&pid, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&streamType, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&sampleRate, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&format, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&frameCount, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&flags, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&const&sp&&sharedBuffer, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&status_t&*status); &&&&&&&&&&virtual&&&&&status_t&&&&setMasterVolume(float&value); &&&&&virtual&&&&&status_t&&&&setMasterMute(bool&muted); &&&&&virtual&&&&&status_t&&&&setStreamVolume(int&stream,&float&value); &&&&&virtual&&&&&status_t&&&&setStreamMute(int&stream,&bool&muted); &&&&&virtual&&&&&status_t&&&&setRouting(int&mode,&uint32_t&routes,&uint32_t&mask); &&&&&virtual&&&&&uint32_t&&&&getRouting(int&mode)&const; &&&&&virtual&&&&&status_t&&&&setMode(int&mode); &&&&&virtual&&&&&int&&&&&&&&&getMode()&const; &&&&&virtual&sp&openRecord(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&pid_t&pid, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&streamType, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&sampleRate, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&format, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&frameCount, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&flags, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&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_t& &&&&&&&&&AudioStreamOut&*hwOutput&= &&&&&&&&&&&&&mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT,&0,&0,&&status); &&&&&&&&&mHardwareStatus&=&AUDIO_HW_IDLE; &&&&&&&&&if&(hwOutput)&{ &&&&&&&&&&&&&mHardwareMixerThread&= &&&&&&&&&&&&&new&MixerThread(this,&hwOutput,&AudioSystem::AUDIO_OUTPUT_HARDWARE); &&&&&&&&&}&else&{ &&&&&&&&&&&&&LOGE("Failed&to&initialize&hardware&output&stream,&status:&%d",&status); &&&&&&&&&} &&&&&&&&&&&&&&mAudioRecordThread&=&new&AudioRecordThread(mAudioHardware,&this); &&&&&&&&&if&(mAudioRecordThread&!=&0)&{ &&&&&&&&&&&&&mAudioRecordThread->run("AudioRecordThread",&PRIORITY_URGENT_AUDIO); &&&&&&&&&} &&&&&&}&else&{ &&&&&&&&&LOGE("Couldn't&even&initialize&the&stubbed&audio&hardware!"); &&&&&} &}&
从工作的角度看,AudioFlinger在初始化之后,首先获得放音设备,然后为混音器(Mixer)建立线程,接着建立放音设备线程,在线程中
获得放音设备。
在AudioFlinger的AudioResampler.h中定义了一个音频重取样器工具类,如下所示:class&AudioResampler&{ &public: &&&&&enum&src_quality&{ &&&&&&&&&DEFAULT=0, &&&&&&&&&LOW_QUALITY=1,&&&&&&&&&&&&&&&&&&&&&&&MED_QUALITY=2,&&&&&&&&&&&&&&&&&&&&&&&HIGH_QUALITY=3&&&&&&&&&&&&&&&&&&&}; &&&&&static&AudioResampler*&create(int&bitDepth,int&inChannelCount,&&&&&&&&&&&&&&int32_t&sampleRate,&int&quality=DEFAULT); &&&&&virtual&~AudioResampler(); &&&&&virtual&void&init()&=&0; &&&&&virtual&void&setSampleRate(int32_t&inSampleRate);&&&&&virtual&void&setVolume(int16_t&left,&int16_t&right);&&&&&&virtual&void&resample(int32_t*&out,&size_t&outFrameCount, &&&&&&&&&&&&&&&&&&&&&&&&AudioBufferProvider*&provider)&=&0; &};&
这个音频重取样工具包含3种质量:低等质量(LOW_QUALITY)将使用线性差值算法实现;中等质量(MED_QUALITY)将使用立方差值
算法实现;高等质量(HIGH_
QUALITY)将使用FIR(有限阶滤波器)实现。AudioResampler中的AudioResamplerOrder1是线性实
现,AudioResamplerCubic.*文件提供立方实现方式,AudioResamplerSinc.*提供FIR实现。
AudioMixer.h和AudioMixer.cpp中实现的是一个Audio系统混音器,它被AudioFlinger调用,一般用于在声音
输出之前的处理,提供多通道处理、声音缩放、重取样。AudioMixer调用了AudioResampler。
提示: AudioFlinger本身的实现通过调用下层的Audio硬件抽象层的接口来实现具体的功能,各个接口之间具有对应关系。7.2.4& Audio系统的JNI代码
Android的Audio部分通过JNI向Java层提供接口,在Java层可以通过JNI接口完成Audio系统的大部分操作。
Audio JNI部分的代码路径为:frameworks/base/core/jni。
其中,主要实现的3个文件为:android_media_AudioSystem.cpp、android_media_Audio
Track.cpp和android_media_AudioRecord.cpp,它们分别对应了Android Java框架中的3个类的支持:
android.media.AudioSystem:负责Audio系统的总体控制;
android.media.AudioTrack:负责Audio系统的输出环节;
android.media.AudioRecorder:负责Audio系统的输入环节。
在Android的Java层中,可以对Audio系统进行控制和数据流操作,对于控制操作,和底层的处理基本一致;但是对于数据流操作,由于
Java不支持指针,因此接口被封装成了另外的形式。
例如,对于音频输出,android_media_AudioTrack.cpp提供的是写字节和写短整型的接口类型。static&jint&android_media_AudioTrack_native_write(JNIEnv&*env,&&jobject&thiz, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&jbyteArray&javaAudioData, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&jint&offsetInBytes,&jint&sizeInBytes, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&jint&javaAudioFormat)&{ &&&&&jbyte*&cAudioData&=&NULL; &&&&&AudioTrack&*lpTrack&=&NULL; &&&&&lpTrack&=&(AudioTrack&*)env->GetIntField( &&&&&&&&&&&&&&&&&&thiz,&javaAudioTrackFields.&Native&TrackInJavaObj); &&&&&&&&&&ssize_t&written&=&0; &&&&&if&(lpTrack->sharedBuffer()&==&0)&{ &&&&&&&&&&&&&&written&=&lpTrack->write(cAudioData&+offsetInBytes,&sizeInBytes); &&&&&}&else&{ &&&&&&&&&if&(javaAudioFormat&==&javaAudioTrackFields.PCM16)&{ &&&&&&&&&&&&&memcpy(lpTrack->sharedBuffer()->pointer(), &&&&&&&&&&&&&&&&&&&&&cAudioData+offsetInBytes,&sizeInBytes); &&&&&&&&&&&&&written&=&sizeInB &&&&&&&&&}&else&if&(javaAudioFormat&==&javaAudioTrackFields.PCM8)&{ &&&&&&&&&&&&&int&count&=&sizeInB &&&&&&&&&&&&&int16_t&*dst&=&(int16_t&*)lpTrack->sharedBuffer()->pointer(); &&&&&&&&&&&&&const&int8_t&*src&=&(const&int8_t&*)(cAudioData&+&offsetInBytes);&&&&&&&&&&&& &&&&&&&&&&&&&while(count--)&{ &&&&&&&&&&&&&&&&&*dst++&=&(int16_t)(*src++^0x80)&<<&8; &&&&&&&&&&&&&} &&&&&&&&&&&&&written&=&sizeInB &&&&&&&&&} &&&&&} &&&&&&&&&&env->ReleasePrimitiveArrayCritical(javaAudioData,&cAudioData,&0); &&&&&return&(int) &}&
所定义的JNI接口native_write_byte和native_write_short如下所示:{"native_write_byte",&&&&"([BIII]I",&(void&*)android_media_AudioTrack_native_write), &{"native_write_short",&&&"([SIII]I",&(void&*)android_media_AudioTrack_native_&write_short),&
向Java提供native_write_byte和native_write_short接口,它们一般是通过调用AudioTrack的
write()函数来完成的,只是在Java的数据类型和C++的指针中做了一步转换。7.2.5& Audio系统的Java代码
Android的Audio系统的相关类在android.media 包中,Java部分的代码路径为:
frameworks/base/media/java/android/media
Audio系统主要实现了以下几个类:android.media.AudioSystem、android.media. Audio
Track、android.media.AudioRecorder、android.media.AudioFormat。前面的3个类和本地代码是
对应的,AudioFormat提供了一些Audio相关类型的枚举值。
注意:在Audio系统的Java代码中,虽然可以通过AudioTrack和AudioRecorder的write()和read()接口,在
Java层对Audio的数据流进行操作。但是,更多的时候并不需要这样做,而是在本地代码中直接调用接口进行数据流的输入/输出,而Java层只进行控
制类操作,不处理数据流。7.3& Audio的硬件抽象层
7.3.1& Audio硬件抽象层的接口定义
Audio的硬件抽象层是AudioFlinger和Audio硬件的接口,在各个系统的移植过程中可以有不同的实现方式。Audio硬件抽象层的
接口路径为:
hardware/libhardware_legacy/include/hardware/
其中主要的文件为:AudioHardwareBase.h和AudioHardwareInterface.h。
Android中的Audio硬件抽象层可以基于Linux标准的ALSA或OSS音频驱动实现,也可以基于私有的Audio驱动接口来实现。
在AudioHardwareInterface.h中定义了类:AudioStreamOut、AudioStreamIn和
AudioHardwareInterface。AudioStreamOut和AudioStreamIn的主要定义如下所示:class&AudioStreamOut&{ &public: &&&&&virtual&&&&&&&&&&&&&~AudioStreamOut()&=&0; &&&&&virtual&status_t&&&&setVolume(float&volume)&=&0; &&&&&virtual&ssize_t&&&&&write(const&void*&buffer,&size_t&bytes)&=&0; &&&&&&}; &class&AudioStreamIn&{ &public: &&&&&virtual&&&&&&&&&&&&&~AudioStreamIn()&=&0; &&&&&virtual&status_t&&&&setGain(float&gain)&=&0; &&&&&virtual&ssize_t&&&&&read(void*&buffer,&ssize_t&bytes)&=&0; &&&&&&};&
AudioStreamOut和AudioStreamIn分别对应了音频的输出环节和输入环节,其中负责数据流的接口分别是wirte()和
read(),参数是一块内存的指针和长度;另外还有一些设置和获取接口。
Audio的硬件抽象层主体AudioHardwareInterface类的定义如下所示:class&AudioHardwareInterface &{ &public: &&&&&virtual&status_t&&&&initCheck()&=&0; &&&&&virtual&status_t&&&&setVoiceVolume(float&volume)&=&0; &&&&&virtual&status_t&&&&setMasterVolume(float&volume)&=&0; &&&&&virtual&status_t&&&&setRouting(int&mode,&uint32_t&routes)&=&0; &&&&&virtual&status_t&&&&getRouting(int&mode,&uint32_t*&routes)&=&0; &&&&&virtual&status_t&&&&setMode(int&mode)&=&0; &&&&&virtual&status_t&&&&getMode(int*&mode)&=&0; &&&&&&&&&&virtual&AudioStreamOut*&openOutputStream(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&format=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&sampleRate=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&status_t&*status=0)&=&0; &&&&&virtual&AudioStreamIn*&openInputStream(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&format, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&sampleRate, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&status_t&*status, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&AudioSystem::audio_in_acoustics&acoustics)&=&0; &&&&&static&AudioHardwareInterface*&create(); &};&
在这个AudioHardwareInterface接口中,使用openOutputStream()和openInputStream()函数
分别获取AudioStreamOut和AudioStreamIn两个类,它们作为音频输入/输出设备来& 使用。
此外,AudioHardwareInterface.h定义了C语言的接口来获取一个AudioHardware
Interface类型的指针。extern&"C"&AudioHardwareInterface*&createAudioHardware(void);&
如果实现一个Android的硬件抽象层,则需要实现AudioHardwareInterface、AudioStream
Out和AudioStreamIn三个类,将代码编译成动态库libauido.so。AudioFlinger会连接这个动态库,并调用其中的
createAudioHardware()函数来获取接口。
在AudioHardwareBase.h中定义了类:AudioHardwareBase,它继承了Audio
HardwareInterface,显然继承这个接口也可以实现Audio的硬件抽象层。
提示:Android系统的Audio硬件抽象层可以通过继承类AudioHardwareInterface来实现,其中分为控制部分和输入/输
出处理部分。
7.3.2& AudioFlinger中自带Audio硬件抽象层实现(1)
在AudioFlinger中可以通过编译宏的方式选择使用哪一个Audio硬件抽象层。这些Audio硬件抽象层既可以作为参考设计,也可以在没
有实际的Audio硬件抽象层(甚至没有Audio设备)时使用,以保证系统的正常运行。
在AudioFlinger的编译文件Android.mk中,具有如下的定义:ifeq&($(strip&$(BOARD_USES_GENERIC_AUDIO)),true) &&&LOCAL_STATIC_LIBRARIES&+=&libaudiointerface &else&&&LOCAL_SHARED_LIBRARIES&+=&libaudio &endif &LOCAL_MODULE:=&libaudioflinger &include&$(BUILD_SHARED_LIBRARY)&
定义的含义为:当宏BOARD_USES_GENERIC_AUDIO为true时,连接libaudiointer
face.a静态库;当BOARD_USES_GENERIC_AUDIO为false时,连接libaudiointerface.so动态库。在正常
的情况下,一般是使用后者,即在另外的地方实现libaudiointerface.so动态库,由AudioFlinger的库
libaudioflinger.so来连接使用。
libaudiointerface.a也在这个Android.mk中生成:include&$(CLEAR_VARS) &LOCAL_SRC_FILES:=&\ &&&&&AudioHardwareGeneric.cpp&\ &&&&&AudioHardwareStub.cpp&\ &&&&&AudioDumpInterface.cpp&\ &&&&&AudioHardwareInterface.cpp &LOCAL_SHARED_LIBRARIES&:=&\ &&&&&libcutils&\ &&&&&libutils&\ &&&&&libmedia&\ &&&&&libhardware_legacy &ifeq&($(strip&$(BOARD_USES_GENERIC_AUDIO)),true) &&&LOCAL_CFLAGS&+=&-DGENERIC_AUDIO &endif &LOCAL_MODULE:=&libaudiointerface &include&$(BUILD_STATIC_LIBRARY)&
以上内容通过编译4个源文件,生成了libaudiointerface.a静态库。其中AudioHard
wareInterface.cpp负责实现基础类和管理,而AudioHardwareGeneric.cpp、AudioHard
wareStub.cpp和AudioDumpInterface.cpp三个文件各自代表一种Auido硬件抽象层的实现。
AudioHardwareGeneric.cpp:实现基于特定驱动的通用Audio硬件抽象层;
AudioHardwareStub.cpp:实现Audio硬件抽象层的一个桩;
AudioDumpInterface.cpp:实现输出到文件的Audio硬件抽象层。
在AudioHardwareInterface.cpp中,实现了Audio硬件抽象层的创建函数
AudioHardwareInterface::create(),内容如下所示:AudioHardwareInterface*&AudioHardwareInterface::create() &{ &&&&&AudioHardwareInterface*&hw&=&0; &&&&&char&value[PROPERTY_VALUE_MAX]; &#ifdef&GENERIC_AUDIO &&&&&hw&=&new&AudioHardwareGeneric();&&&&&&&&&&&&#else&&&&&if&(property_get("ro.kernel.qemu",&value,&0))&{ &&&&&&&&&LOGD("Running&in&emulation&-&using&generic&audio&driver"); &&&&&&&&&hw&=&new&AudioHardwareGeneric(); &&&&&} &&&&&else&{ &&&&&&&&&LOGV("Creating&Vendor&Specific&AudioHardware"); &&&&&&&&&hw&=&createAudioHardware();&&&&&&&&&&&&&&&&&} &#endif &&&&&if&(hw->initCheck()&!=&NO_ERROR)&{ &&&&&&&&&LOGW("Using&stubbed&audio&hardware.&No&sound&will&be&produced."); &&&&&&&&&delete& &&&&&&&&&hw&=&new&AudioHardwareStub();&&&&&&&&&&&&&&&} &#ifdef&DUMP_FLINGER_OUT &&&&&hw&=&new&AudioDumpInterface(hw);&&&&&&&&&&&&#endif &&&&&return& &}&
根据GENERIC_AUDIO、DUMP_FLINGER_OUT等宏选择创建几个不同的Audio硬件抽象层,最后返回的接口均为
AudioHardwareInterface类型的指针。
1.用桩实现的Audio硬件抽象层
AudioHardwareStub.h和AudioHardwareStub.cpp是一个Android硬件抽象层的桩实现方式。这个实现不操
作实际的硬件和文件,它所进行的是空操作,在系统没有实际的Audio设备时使用这个实现,来保证系统的正常工作。如果使用这个硬件抽象层,实际上
Audio系统的输入和输出都将为空。
AudioHardwareStub.h定义了AudioStreamOutStub 和AudioStreamInStub类的情况&
如下所示:class&AudioStreamOutStub&:&public&AudioStreamOut&{ &public: &&&&&virtual&status_t&&&&set(int&format,&int&channelCount,&uint32_t&sampleRate); &&&&&virtual&uint32_t&&&&sampleRate()&const&{&return&44100;&} &&&&&virtual&size_t&&&&&&bufferSize()&const&{&return&4096;&} &&&&&virtual&int&&&&&&&&&channelCount()&const&{&return&2;&} &&&&&virtual&int&&&&&&&&&format()&const&{&return&AudioSystem::PCM_16_BIT;&} &&&&&virtual&uint32_t&&&&latency()&const&{&return&0;&} &&&&&virtual&status_t&&&&setVolume(float&volume)&{&return&NO_ERROR;&} &&&&&virtual&ssize_t&&&&&write(const&void*&buffer,&size_t&bytes); &&&&&virtual&status_t&&&&standby(); &&&&&virtual&status_t&&&&dump(int&fd,&const&Vector&&args); &}; &class&AudioStreamInStub&:&public&AudioStreamIn&{ &public: &&&&&virtual&status_t&set(int&format,&int&channelCount,&uint32_t&sampleRate,&AudioSystem::&&&audio_in_acoustics&acoustics); &&&&&virtual&uint32_t&&&&sampleRate()&const&{&return&8000;&} &&&&&virtual&size_t&&&&&&bufferSize()&const&{&return&320;&} &&&&&virtual&int&&&&&&&&&channelCount()&const&{&return&1;&} &&&&&virtual&int&&&&&&&&&format()&const&{&return&AudioSystem::PCM_16_BIT;&} &&&&&virtual&status_t&&&&setGain(float&gain)&{&return&NO_ERROR;&} &&&&&virtual&ssize_t&&&&&read(void*&buffer,&ssize_t&bytes); &&&&&virtual&status_t&&&&dump(int&fd,&const&Vector&&args); &&&&&virtual&status_t&&&&standby()&{&return&NO_ERROR;&} &};&
上面实际上使用了最简单模式,只是用固定的参数(缓冲区大小、采样率、通道数),以及将一些函数直接无错误返回。
使用AudioHardwareStub类来继承AudioHardwareBase,事实上也就是继承
AudioHardwareInterface。class&AudioHardwareStub&:&public&&AudioHardwareBase &{ &public: &&&&&&&&&&&&&&&&&&&&&&&&&AudioHardwareStub(); &&&&&virtual&&&&&&&&&&&&&~AudioHardwareStub(); &&&&&virtual&status_t&&&&initCheck(); &&&&&virtual&status_t&&&&setVoiceVolume(float&volume); &&&&&virtual&status_t&&&&setMasterVolume(float&volume); &&&&&virtual&status_t&&&&setMicMute(bool&state){&mMicMute&=&&&return&&NO_ERROR;&} &&&&&virtual&status_t&&&&getMicMute(bool*&state){&*state&=&mMicMute&;&return&NO_ERROR;&} &&&&&virtual&status_t&&&&setParameter(const&char*&key,&const&char*&value) &&&&&&&&&&&&&{&return&NO_ERROR;&} &&&&&virtual&AudioStreamOut*&openOutputStream(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&format=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&sampleRate=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&status_t&*status=0); &&&&&&virtual&AudioStreamIn*&openInputStream(&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&format, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&sampleRate, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&status_t&*status, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&AudioSystem::audio_in_acoustics&acoustics); &&}; 7.3.2& AudioFlinger中自带Audio硬件抽象层实现(2)
在实现过程中,为了保证声音可以输入和输出,这个桩实现的主要内容是实现AudioStreamOutStub和
AudioStreamInStub类的读/写函数。实现如下所示:ssize_t&AudioStreamOutStub::write(const&void*&buffer,&size_t&bytes) &{ &&&&&usleep(bytes&*&1000000&/&sizeof(int16_t)&/channelCount()&/&sampleRate()); &&&&&return& &} &ssize_t&AudioStreamInStub::read(void*&buffer,&ssize_t&bytes) &{ &&&&&usleep(bytes&*&1000000&/&sizeof(int16_t)&/&channelCount()&/&sampleRate()); &&&&&memset(buffer,&0,&bytes); &&&&&return& &}&
由此可见,使用这个接口进行音频的输入和输出时,和真实的设备没有关系,输出和输入都使用延时来完成。对于输出的情况,不会有声音播出,但是返回值
表示全部内容已经输出完成;对于输入的情况,将返回全部为0的数据。
此外,这种实现支持默认的参数,如果用set()函数设置的参数与默认参数不一致,还会返回错误。
2.Android通用的Audio硬件抽象层
AudioHardwareGeneric.h和AudioHardwareGeneric.cpp是Android通用的一个Audio硬件抽象
层。与前面的桩实现不同,这是一个真正能够使用的Audio硬件抽象层,但是它需要Android的一种特殊的声音驱动程序的支持。
与前面类似,AudioStreamOutGeneric、AudioStreamInGeneric和AudioHardwareGeneric
这3个类分别继承Audio硬件抽象层的3个接口。class&AudioStreamOutGeneric&:&public&AudioStreamOut&{ &&&&&&}; &class&AudioStreamInGeneric&:&public&AudioStreamIn&{ &&&&&&}; &class&AudioHardwareGeneric&:&public&AudioHardwareBase &{ &&&&&&};&
在AudioHardwareGeneric.cpp的实现中,使用的驱动程序是/dev/eac,这是一个非标准程序,定义设备的路径如下所示:static&char&const&*&const&kAudioDeviceName&=&"/dev/eac";&
对于Linux操作系统,这个驱动程序在文件系统中的节点主设备号为10,次设备号自动生成。
提示:eac是Linux中的一个misc驱动程序,作为Android的通用音频驱动,写设备表示放音,读设备表示录音。
在AudioHardwareGeneric的构造函数中,打开这个驱动程序的设备节点。AudioHardwareGeneric::AudioHardwareGeneric() &&&&&:&mOutput(0),&mInput(0),&&mFd(-1),&mMicMute(false) &{ &&&&&mFd&=&::open(kAudioDeviceName,&O_RDWR);&&}&
这个音频设备是一个比较简单的驱动程序,没有很多设置接口,只是用写设备表示录音,读设备表示放音。放音和录音支持的都是16位的PCM。ssize_t&AudioStreamOutGeneric::write(const&void*&buffer,&size_t&bytes) &{ &&&&&Mutex::Autolock&_l(mLock); &&&&&return&ssize_t(::write(mFd,&buffer,&bytes));&&&&&} &ssize_t&AudioStreamInGeneric::read(void*&buffer,&ssize_t&bytes) &{ &&&&&AutoMutex&lock(mLock); &&&&&if&(mFd&<&0)&{ &&&&&&&&&return&NO_INIT; &&&&&} &&&&&return&::read(mFd,&buffer,&bytes);&&&&&&&&&&&&&&&}&
虽然AudioHardwareGeneric是一个可以真正工作的Audio硬件抽象层,但是这种实现方式非常简单,不支持各种设置,参数也只能
使用默认的。而且,这种驱动程序需要在Linux核心加入eac驱动程序的支持。
3.提供Dump功能的Audio硬件抽象层
AudioDumpInterface.h和AudioDumpInterface.cpp是一个提供了Dump功能的Audio硬件抽象层,它所
起到的作用就是将输出的Audio数据写入到文件中。
AudioDumpInterface本身支持Audio的输出功能,不支持输入功能。AudioDumpInterface.h中的类定义如下:class&AudioStreamOutDump&:&public&AudioStreamOut&{ &public: &&&&&&&&&&&&&&&&&&&&&&&&&AudioStreamOutDump(&AudioStreamOut*&FinalStream); &&&&&&&&&&&&&&&&&&&&&&&&&~AudioStreamOutDump(); &&&&&&&&&&&&&&&&&&&&&&&&&virtual&ssize_t&&&&&write(const&void*&buffer,&size_t&bytes); &&&&&virtual&uint32_t&&&&sampleRate()&const&{&return&mFinalStream->sampleRate();&} &&&&&virtual&size_t&&&&&&bufferSize()&const&{&return&mFinalStream->bufferSize();&} &&&&&virtual&int&&&&&&&&&channelCount()&const&{&return&mFinalStream->channelCount();&} &&&&&virtual&int&&&&&&&&&format()&const&{&return&mFinalStream->format();&} &&&&&virtual&uint32_t&&&&latency()&const&{&return&mFinalStream->latency();&} &&&&&virtual&status_t&&&&setVolume(float&volume) &&&&&&&&&&&&&&&&&&&&&&&&&&&&&{&return&mFinalStream->setVolume(volume);&} &&&&&virtual&status_t&&&&standby(); &&&&&&}; &class&AudioDumpInterface&:&public&AudioHardwareBase &{ &&&&&virtual&AudioStreamOut*&openOutputStream( &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&format=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&channelCount=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uint32_t&sampleRate=0, &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&status_t&*status=0); &&&&&&}&
只实现了AudioStreamOut,没有实现AudioStreamIn,因此这个Audio硬件抽象层只支持输出功能,不支持输入功能。
输出文件的名称被定义为:#define&FLINGER_DUMP_NAME&"/data/FlingerOut.pcm"&
在AudioDumpInterface.cpp的AudioStreamOut所实现的写函数中,写入的对象就是这个文件。ssize_t&AudioStreamOutDump::write(const&void*&buffer,&size_t&bytes) &{ &&&&&ssize_t& &&&&&ret&=&mFinalStream->write(buffer,&bytes); &&&&&if(!mOutFile&&&&gFirst)&{ &&&&&&&&&gFirst&=&false; &&&&&&&&&mOutFile&=&fopen(FLINGER_DUMP_NAME,&"r"); &&&&&&&&&if(mOutFile)&{ &&&&&&&&&&&&&fclose(mOutFile); &&&&&&&&&&&&&mOutFile&=&fopen(FLINGER_DUMP_NAME,&"ab");&&&&&&&&&} &&&&&} &&&&&if&(mOutFile)&{ &&&&&&&&&fwrite(buffer,&bytes,&1,&mOutFile);&&&&&&&} &&&&&return& &}&
如果文件是打开的,则使用追加方式写入。因此使用这个Audio硬件抽象层时,播放的内容(PCM)将全部被写入文件。而且这个类支持各种格式的输
出,这取决于调用者的设置。
AudioDumpInterface并不是为了实际的应用使用的,而是为了调试使用的类。当进行音频播放器调试时,有时无法确认是解码器的问题还
是Audio输出单元的问题,这时就可以用这个类来替换实际的Audio硬件抽象层,将解码器输出的Audio的PCM数据写入文件中,由此可以判断解码
器的输出是否正确。
提示:使用AudioDumpInterface音频硬件抽象层,可以通过/data/FlingerOut.pcm文件找到PCM的输出数据。7.3.3& Audio硬件抽象层的真正实现
实现一个真正的Audio硬件抽象层,需要完成的工作和实现以上的硬件抽象层类似。
例如:可以基于Linux标准的音频驱动:OSS(Open Sound System)或者ALSA(Advanced Linux Sound
Architecture)驱动程序来实现。
对于OSS驱动程序,实现方式和前面的AudioHardwareGeneric类似,数据流的读/写操作通过对/dev/dsp设备的读/写来完
成;区别在于OSS支持了更多的ioctl来进行设置,还涉及通过/dev/mixer设备进行控制,并支持更多不同的参数。
对于ALSA驱动程序,实现方式一般不是直接调用驱动程序的设备节点,而是先实现用户空间的alsa-lib,然后Audio硬件抽象层通过调用
alsa-lib来实现。
在实现Audio硬件抽象层时,对于系统中有多个Audio设备的情况,可由硬件抽象层自行处理setRouting()函数设定,例如,可以选择
支持多个设备的同时输出,或者有优先级输出。对于这种情况,数据流一般来自AudioStreamOut::write()函数,可由硬件抽象层确定输出
方法。对于某种特殊的情况,也有可能采用硬件直接连接的方式,此时数据流可能并不来自上面的write(),这样就没有数据通道,只有控制接口。
Audio硬件抽象层也是可以处理这种情况的。====================================================
阅读(3846) | 评论(1) | 转发(0) |
相关热门文章
给主人留下些什么吧!~~
很好的, 收藏了
推荐一个博客,提供很多免费软件编程电子书下载:
http://free-
请登录后评论。

我要回帖

更多关于 embed audio 区别 的文章

 

随机推荐