Android的Audio音频系统
- 格式:pdf
- 大小:168.98 KB
- 文档页数:15
audiotrack播放原理一、Audiotrack简介Audiotrack是Android系统中用于播放音频的一种类。
它提供了一个接口,使开发者能够直接访问底层音频设备,并通过PCM数据流进行音频播放。
二、Audiotrack的工作原理1. 创建Audiotrack对象要使用Audiotrack进行音频播放,首先需要创建一个Audiotrack 对象。
在创建对象时,需要指定音频的参数,包括采样率、声道数、音频格式等。
2. 准备PCM数据PCM(Pulse Code Modulation)是一种常用的音频数据编码格式。
在使用Audiotrack播放音频之前,需要将音频数据转换为PCM格式,并保存在一个缓冲区中。
3. 写入PCM数据将准备好的PCM数据写入到Audiotrack对象中。
可以一次性写入所有数据,也可以分块写入。
写入数据时,需要注意确保写入的数据不超过Audiotrack对象的缓冲区大小。
4. 开始播放调用Audiotrack的play()方法,开始播放音频。
在播放过程中,可以通过调用pause()方法暂停播放,再调用play()方法继续播放。
5. 停止播放调用Audiotrack的stop()方法,停止音频播放。
停止播放后,可以通过调用release()方法释放Audiotrack对象。
三、Audiotrack的应用场景Audiotrack在Android音频应用开发中有广泛的应用场景,包括:1. 音乐播放器:通过Audiotrack可以实现音乐的播放功能,包括播放、暂停、停止等操作。
2. 语音通话:Audiotrack可以用于实现手机通话的语音播放功能,包括接听、拒接、挂断等操作。
3. 游戏开发:在游戏开发中,可以使用Audiotrack实现游戏中的音效播放,提升游戏的交互体验。
4. 多媒体应用:Audiotrack可以用于多媒体应用的音频播放,如播放视频中的音频轨道。
四、Audiotrack的优势和不足1. 优势:- 高效稳定:Audiotrack可以直接访问底层音频设备,能够提供高效稳定的音频播放效果。
引子Android Framework的音频子系统中,每一个音频流对应着一个AudioTrack类的一个实例,每个AudioTrack会在创建时注册到AudioFlinger中,由AudioFlinger把所有的AudioTrack进行混合(Mixer),然后输送到AudioHardware中进行播放,目前Android的Froyo版本设定了同时最多可以创建32个音频流,也就是说,Mixer最多会同时处理32个AudioTrack的数据流。
如何使用AudioTrackAudioTrack的主要代码位于frameworks/base/media/libmedia/audiotrack.cpp中。
现在先通过一个例子来了解一下如何使用AudioTrack,ToneGenerator是android 中产生电话拨号音和其他音调波形的一个实现,我们就以它为例子:ToneGenerator的初始化函数:[c-sharp]view plaincopybool ToneGenerator::initAudioTrack() {// Open audio track in mono, PCM 16bit, default sampling rate,default buffer sizempAudioTrack = new AudioTrack();mpAudioTrack->set(mStreamType,0,AudioSystem::PCM_16_BIT,AudioSystem::CHANNEL_OUT_MONO,0,0,audioCallback,this,0,0,mThreadCanCallJava);if (mpAudioTrack->initCheck() != NO_ERROR) {LOGE("AudioTrack->initCheck failed");goto initAudioTrack_exit;}mpAudioTrack->setVolume(mVolume, mVolume);mState = TONE_INIT;......}可见,创建步骤很简单,先new一个AudioTrack的实例,然后调用set成员函数完成参数的设置并注册到AudioFlinger中,然后可以调用其他诸如设置音量等函数进一步设置音频参数。
Android 音频系统整理在framework中c/c++层的音频系统服务主要有三个。
在base/media/mediaserver/Main_mediaserver.cpp的代码中可以找到。
一个是AudioFlinger, MediaPlayerService, 和AudioPolicyService。
AudioFlinger和AudioPolicyService是android audio系统的服务,负责音频方面的数据流传输和控制功能,也负责音频设备的管理。
这个部分作为Android的Audio系统的输入/输出层次,一般负责播放PCM声音输出和从外部获取PCM声音,以及管理声音设备和设置。
Mediaplayerservice 是Android中很重要也最为复杂的媒体播放器(MediaPlayer)部分的服务。
MediaPlayer在底层是基于OpenCore(PacketVideo)和stagefright的库实现的。
音频服务端和客户端之间的交互包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制。
代码框架:1:Java部分代码(frameworks/base/media/java/android/media)2:Audio的JNI层JNI的cpp分布在两个部分,base/core/jni中有AudioRecord,AudioSystem,AudioTrack,JetPlayer,ToneGenarator,其他的在base/media/jni中。
3:Audio的c/c++层1)Audio框架见下图:Audio本地框架是media库的一部分,本部分内容被编译成库libmedia.so,主要实现AudioSystem、AudioTrack和AudioRecorder三个类,对上面提供接口,由下层的本地代码去实现。
AudioFlinger内容被编译成库libaudioflinger.so,它是Audio系统的本地服务部分,它是audio系统中真正做事的类,它通过硬件抽象层提供到硬件的接口。
AndroidN的Audio系统AudioFlinger 回放录制线程AndioFlinger 作为 Android 的⾳频系统引擎,重任之⼀是负责输⼊输出流设备的管理及⾳频流数据的处理传输,这是由回放线程(PlaybackThread 及其派⽣的⼦类)和录制线程(RecordThread)进⾏的,我们简单看ThreadBase:PlaybackThread 和 RecordThread 的基类RecordThread:录制线程类,由 ThreadBase 派⽣PlaybackThread:回放线程基类,同由 ThreadBase 派⽣MixerThread:混⾳回放线程类,由 PlaybackThread 派⽣,负责处理标识为 AUDIO_OUTPUT_FLAG_PRIMARY、AUDIO_OUTPUT_FLAG_FAST、AUDIO_OUTPUT_FLAG_DEEP_BUFFER 的⾳频流,MixerThread 可以把多个⾳轨的DirectOutputThread:直输回放线程类,由 PlaybackThread 派⽣,负责处理标识为 AUDIO_OUTPUT_FLAG_DIRECT 的⾳频流,这种⾳频流数据不需要软件混⾳,直接输出到⾳频设备即可DuplicatingThread:复制回放线程类,由 MixerThread 派⽣,负责复制⾳频流数据到其他输出设备,使⽤场景如主声卡设备、蓝⽛⽿机设备、USB 声卡设备同时输出OffloadThread:硬解回放线程类,由 DirectOutputThread 派⽣,负责处理标识为 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 的⾳频流,这种⾳频流未经软件解码的(⼀般是 MP3、AAC 等格式的数据),需要输出到硬件解码器PlaybackThread 中有个极为重要的函数 threadLoop(),当 PlaybackThread 被强引⽤时,threadLoop() 会真正运⾏起来进⼊循环主体,处理⾳频流数据相关事务,threadLoop() ⼤致流程如下(以 MixerThread 为例)bool AudioFlinger::PlaybackThread::threadLoop()threadLoop() 循环的条件是 exitPending() 返回 false,如果想要 PlaybackThread 结束循环,则可以调⽤ requestExit() 来请求退出;processConfigEvents_l() :处理配置事件;当有配置改变的事件发⽣时,需要调⽤ sendConfigEvent_l() 来通知 PlaybackThread,这样 PlaybackThread 才能及时处理配置事件;常见的配置事件是切换⾳频通路;检查此时此刻是否符合 standby 条件,⽐如当前并没有 ACTIVE 状态的 Track(mActiveTracks.size() = 0),那么调⽤ threadLoop_standby() 关闭⾳频硬件设备以节省能耗;prepareTracks_l():准备⾳频流和混⾳器,该函数⾮常复杂,这⾥不详细分析了,仅列⼀下流程要点:遍历 mActiveTracks,逐个处理 mActiveTracks 上的 Track,检查该 Track 是否为 ACTIVE 状态;如果 Track 设置是 ACTIVE 状态,则再检查该 Track 的数据是否准备就绪了;根据⾳频流的⾳量值、格式、声道数、⾳轨的采样率、硬件设备的采样率,配置好混⾳器参数;如果 Track 的状态是 PAUSED 或 STOPPED,则把该 Track 添加到 tracksToRemove 向量中;threadLoop_mix():读取所有置了 ACTIVE 状态的⾳频流数据,混⾳器开始处理这些数据;threadLoop_write():把混⾳器处理后的数据写到输出流设备;threadLoop_removeTracks():把 tracksToRemove 上的所有 Track 从 mActiveTracks 中移除出来;这样下⼀次循环时就不会处理这些 Track 了。
Android -- Audio Native服务之启动流程分析(一)Android中的Audio系统是比较庞大、繁杂的一部分内容,其中会涉及较多的音频编解码、多媒体制式与Android Audio HAL设备管理的知识。
随着Android的发展,其所支持的音频设备也变得越来丰富,如扬声器、耳机、听筒等等;这种变化也为Android管理如此丰富的音频设备以及如何正确、合理地切换音频输出提出了更高的要求。
面对如此繁杂的管理要求,我们分析Android Audio服务的历程想必也不会轻松。
接下来,我们会以Audio Native服务的启动为入口,以其基本实现流程为重点,抓住代码中的各个关键点,循序渐进地学习Android Audio部分的知识,先让我们对它有一个基本的认识和了解;其他的代码细节分析,则需要我们在工作、学习中花费更多的时间去揣摩和思考了。
Android Audio部分最主要的Native服务有两个:AudioFlinger和AudioPolicyService。
AudioFlinger是Android Audio系统的核心与中枢。
从上,它为Android Audio API实现提供具体的功能接口;向下,它与Audio HAL层交互,管理音频设备。
我们知道HAL层是Android 对各个物理设备的代码抽象。
HAL层中封装了操作物理设备的接口,通过调用这些接口,我们就可以操作设备,实现我们自己的功能。
又由于AudioFlinger负责管理这些Audio设备,所以我们可以猜测它有一套自己的机制,来区分和管理这些Audio Interface。
同时,AudioFlinger直接与HAL交互,它其中也必然实现了音频数据管理、音频输入输出等功能。
我们也要注意,Android中支持多种音频设备,那么就需要有一位大师来管理音频数据到底从哪种设备输入或者输出;这就牵扯到一种策略制定的问题,它指引音频数据的流向,即与哪种物理设备交互。
Android⾳频系统AudioTrack使⽤⽅法详解今天,简单讲讲AudioTrack的使⽤⽅法。
1、Android AudioTrack简介在android中播放声⾳可以⽤MediaPlayer和AudioTrack两种⽅案的,但是两种⽅案是有很⼤区别的,MediaPlayer可以播放多种格式的声⾳⽂件,例如MP3,AAC,WAV,OGG,MIDI等。
⽽AudioTrack只能播放PCM数据流。
事实上,两种本质上是没啥区别的,MediaPlayer在播放⾳频时,在framework层还是会创建AudioTrack,把解码后的PCM数流传递给AudioTrack,最后由AudioFlinger进⾏混⾳,传递⾳频给硬件播放出来。
利⽤AudioTrack播放只是跳过Mediaplayer 的解码部分⽽已。
Mediaplayer的解码核⼼部分是基于OpenCORE 来实现的,⽀持通⽤的⾳视频和图像格式,codec使⽤的是OpenMAX接⼝来进⾏扩展。
因此使⽤audiotrack播放mp3⽂件的话,要⾃⼰加⼊⼀个⾳频解码器,如libmad。
否则只能播放PCM数据,如⼤多数WAV格式的⾳频⽂件。
如果是实时的⾳频数据,那么只能⽤AudioTrack进⾏播放。
2、如何使⽤AudioTrack进⾏⾳频播放//根据采样率,采样精度,单双声道来得到frame的⼤⼩。
int bufsize = AudioTrack.getMinBufferSize(8000,//每秒8K个点 AudioFormat.CHANNEL_CONFIGURATION_STEREO,//双声道AudioFormat.ENCODING_PCM_16BIT);//⼀个采样点16⽐特-2个字节//注意,按照数字⾳频的知识,这个算出来的是⼀秒钟buffer的⼤⼩。
//创建AudioTrackAudioTrack trackplayer = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_ STEREO, AudioFormat.ENCODING_PCM_16BIT, bufsize,AudioTrack.MODE_STREAM);//trackplayer.play() ;//开始trackplayer.write(bytes_pkg, 0, bytes_pkg.length) ;//往track中写数据….trackplayer.stop();//停⽌播放trackplayer.release();//释放底层资源。
Audio系统研究第一季先看看Audio里边有主要有三个:AudioManager:这个主要是用来管理Audio系统的AudioTrack:这个主要是用来播放声音的AudioRecord:这个主要是用来录音的其中AudioManager的理解需要考虑整个系统上声音的策略问题,例如来电话铃声,短信铃声等,主要是策略上的问题。
AudioPolicyManagerAudioPolicyService的很大一部分管理工作都是在AudioPolicyManager中完成的。
包括音频策略(strategy)管理,音量管理,输入输出设备管理。
1、音频策略管理我想首先要搞清楚stream_type,device,strategy三者之间的关系:•AudioSystem::stream_type 音频流的类型,一共有10种类型•AudioSystem::audio_devices 音频输入输出设备,每一个bit代表一种设备,见前面的说明•AudioPolicyManager::routing_strategy 音频路由策略,可以有4种策略getStrategy(stream_type)根据stream type,返回对应的routing strategy值,getDeviceForStrategy()则是根据routing strategy,返回可用的device。
Android把10种stream type归纳为4种路由策略,然后根据路由策略决定具体的输出设备。
释义:DTMF: dual-tone multifrequency 双音多频,由高频群和低频群组成,高低频群各包含4个频率。
一个高频信号和一个低频信号叠加组成一个组合信号,代表一个数字。
DTMF信号有16个编码。
利用DTMF信令可选择呼叫相应的对讲机的缩写,即从文本到语音、语音合成技术(Text To Speech) TTS:Text To Speech“”……2、声音管理/** @hide Maximum volume index values for audio streams */private int[] MAX_STREAM_VOLUME = new int[] {5, // STREAM_VOICE_CALL7, // STREAM_SYSTEM7, // STREAM_RING15, // STREAM_MUSIC7, // STREAM_ALARM7, // STREAM_NOTIFICATION15, // STREAM_BLUETOOTH_SCO15, // STREAM_FM15, // STREAM_DTMF15, // STREAM_TTS7, // STREAM_SYSTEM_ENFORCED};由此可见,电话铃声可以有7个级别的音量,而音乐则可以有15个音量级别,java的代码通过jni,最后调用AudioPolicyManager的initStreamVolume(),把这个数组的内容传入AudioPolicyManager中,这样AudioPolicyManager也就记住了每一个音频流的音量级别。
Android音频系统之AudioPolicyService1.1 AudioPolicy Service在AudioFlinger小节,我们反复强调它只是策略的执行者,而AudioPolicyService则是策略的制定者。
这种分离方式有效地降低了整个系统的藕合性,而且为各个模块独立扩展功能提供了保障。
1.1.1 AudioPolicyService概述汉语中有很多与策略有关联的俗语,比如“因地制宜”、“具体问题具体分析”;战争中只遵照兵书制定战术的行为也被我们称为是“纸上谈兵”、死读书。
这些都告诉我们,了解策略的执行环境是非常重要的,只有清晰地界定出“问题是什么”,才能有的放矢的制定出正确的Policy来解决问题。
Android系统中声音的种类有很多种,具体分类如下所示:/*AudioManager.java*/public static final intSTREAM_VOICE_CALL = 0; /* 通话声音*/ public static final intSTREAM_SYSTEM = 1; /* 系统声音*/public static final int STREAM_RING = 2; /* 电话铃声和短信提示 */public static final intSTREAM_MUSIC = 3; /* 音乐播放 */public static final intSTREAM_ALARM = 4; /* 闹铃 */public static final intSTREAM_NOTIFICATION = 5; /* 通知声音*//*下面几个是隐藏类型,不对上层应用开放*/public static final intSTREAM_BLUETOOTH_SCO = 6; /*当连接蓝牙时的通话*/public static final intSTREAM_SYSTEM_ENFORCED = 7; /* 强制的系统声音,比如有的国家强制要求摄像头拍照时有声音,以防止偷拍*/public static final intSTREAM_DTMF = 8; /* DTMF声音 */public static final intSTREAM_TTS = 9; /* 即text tospeech(TTS) */针对这么多类型的音频,AudioPolicyService至少面临着如下几个问题:l 上述类型的声音需要输出到哪些对应的硬件设备比如一部典型的手机,它既有听筒、耳机接口,还有蓝牙设备。
AndroidAudioManager控制系统声音的流程AndroidAudioManager 是 Android 系统中一个用于控制系统声音的类,它的目的是使用Android的应用程序能够控制和修改系统声音设置,它可以实现将声音变小变大,改变音量,改变播放模式等功能。
下面就介绍AndroidAudioManager控制系统声音的流程:1、获取AndroidAudioManager实例:首先,通过Context类的getSystemService方法获取AudioManager,它是一个单例类,用于管理所有音频播放的活动;2、设置音量模式:调用AudioManager的setMode方法可以將音量設置為不同的模式,通常有兩種模式:STREAM_MUSIC和STREAM_RING,前者用于控制歌曲音量大小,而后者用于控制鈴聲音量大小;3、设置音量等级:通过调用AudioManager的setStreamVolume方法可以设置当前音量等级,一般可以从0到15等级;4、获取当前音量等级:通过调用AudioManager的getStreamVolume 方法可以获取当前音量等级;5、设置音量增减:可以通过调用AudioManager的adjustStreamVolume方法来进行音量的增减;6、设置音量模式:调用AudioManager的setRingerMode方法可以将音量设置为不同的模式,一般有三种模式:正常模式(NORMAL)、静音模式(SILENT)和震动模式(VIBRATE);7、获取音量模式:通过调用AudioManager的getRingerMode方法可以获取当前的音量模式;8、获取最大音量等级:可以通过调用AudioManager的getStreamMaxVolume方法来获取当前音量的最大等级。
以上就是AndroidAudioManager 控制系统声音的流程。
Android音频系统之AudioFlinger(一)1.1 AudioFlinger在上面的框架图中,我们可以看到AudioFlinger(下面简称AF)是整个音频系统的核心与难点。
作为Android系统中的音频中枢,它同时也是一个系统服务,启到承上(为上层提供访问接口)启下(通过HAL 来管理音频设备)的作用。
只有理解了AudioFlinger,才能以此为基础更好地深入到其它模块,因而我们把它放在前面进行分析。
1.1.1 AudioFlinger服务的启动和运行我们知道,Android中的系统服务分为两类,分别是Java层和Native层的System Services。
其中AudioFlinger和SurfaceFlinger 一样,都属于后者。
Java层服务通常在SystemServer.java中启动,比如后面会看到的AudioService就是这种情况。
而Native层服务则通常是各服务方按照自己的特定部署来决定何时启动、如何启动。
例如AudioFlinger就是利用一个Linux程序来间接创建的,如下所示:/*frameworks/av/media/mediaserver/Main_mediaserver.cp p*/int main(int argc, char** argv){sp<ProcessState>proc(ProcessState::self());sp<IServiceManager>sm = defaultServiceManager();ALOGI("ServiceManager: %p", sm.get());AudioFlinger::instantiate();MediaPlayerService::instantiate();CameraService::instantiate();AudioPolicyService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();}这个mediaserver的目录下只有一个文件,它的任务很简单,就是把所有媒体相关的native层服务(包括AudioFlinger,MediaPlayerService,CameraService和AudioPolicyService)启动起来,可以参考其Android.mk: LOCAL_SRC_FILES:= \main_mediaserver.cppLOCAL_SHARED_LIBRARIES := \libaudioflinger\libcameraservice\libmediaplayerservice\libutils \libbinder…LOCAL_MODULE:= mediaserver根据前面的分析,AudioFlinger的源码实现是放在libaudioflinger库中的,因而在编译mediaserver时要引用这个库,其它服务也是一样的做法。
Android音频系统之AudioFlinger(四)1.1.1 AudioMixer每一个MixerThread都有一个唯一对应的AudioMixer(在MixerThread中用mAudioMixer表示),它的作用如其名所表示的,就是为了完成音频的混音操作。
如上图,MixerThread对外开放的接口主要涉及到Parameter(比如setParameter)、Resampler(比如setResampler)、Volume(比如adjustVolumeRamp)、Buffer(比如setBufferProvider)及Track(比如getTrackName)五个部分。
在内部的实现中,MixerThread的核心是一个mState变量(state_t类型),所有的混音工作都会在这个变量中体现出来——特别是其中的tracks数组,如下所示:struct state_t {uint32_t enabledTracks;uint32_t needsChanged;size_t frameCount;void (*hook)(state_t* state, int64_tpts); // one of process__*, never NULLint32_t *outputTemp;int32_t *resampleTemp;int32_t reserved[2];track_t tracks[MAX_NUM_TRACKS];__attribute__((aligne d(32)));};MAX_NUM_TRACKS=32,也就是说最多支持32路同时混音,这对于大部分情况肯定是足够了。
数据类型track_t是对每个Track的描述,可想而知类似Parameter这种设置,最终影响的就是Track的属性。
struct track_t {…union {int16_t volume[MAX_NUM_CHANNELS];int32_t volumeRL;};//音量相关的属性int32_t prevVolume[MAX_NUM_CHANNELS];int32_t volumeInc[MAX_NUM_CHANNELS];…uint8_t channelCount; //只能是1或2uint8_t format; // 总是16uint16_t enabled; // 实际是布尔类型audio_channel_mask_t channelMask;AudioBufferProvider* bufferProvider;mutableAudioBufferProvider::Buffer buffer; // 8 byteshook_t hook;const void* in; //buffer中的当前位置AudioResampler* resampler;uint32_t sampleRate;int32_t* mainBuffer;int32_t* auxBuffer;…bool setResampler(uint32_t sampleRate,uint32_t devSampleRate);bool doesResample() const { return resampler!= NULL; } void resetResampler() { if (resampler !=NULL)resampler->reset(); }void adjustVolumeRamp(bool aux);size_t getUnreleasedFrames() const { return resampler != NULL ?resampler->getUnreleasedFrames() : 0; };};AudioFlinger的threadLoop中,通过不断调用prepareTracks_l 来准备数据,而每次prepare实际上都是对所有Track的一次调整。
Android -- Audio系统之AudioTrack内部实现简析(二)AudioTrack可以工作在两种模式下:STREAM模式:应用程序通过调用write()方法将连续的音频数据传输给AudioTrack对象。
它的处理是阻塞的,只有当音频数据从Java层传入到Native层,并且加入到回放队列后,它才会返回。
STREAM模式经常用于处理量较大的音频数据。
STA TIC模式:当处理的音频数据量较小,能一次性填充到内存用以播放;且对播放时延要求较高时,会使用这种模式。
可能是MediaPlayer功能太完备,我们使用AudioTrack的机会不多。
但借助它来分析Audio 系统的上下层调用关系和实现流程,还是很有效的。
希望在分析完AudioTrack的内部实现之后,我们都能对Android Audio模块有一些基本的了解和认识。
接下来,我们就借助一个STREAM模式下的代码Demo,一层层分析它的内部实现流程;了解AudioTrack是如何与AudioFlinger/AudioPolicyServcie这些Native服务交互的。
示例代码:[cpp] view plain copy 在CODE上查看代码片派生到我的代码片public void initAudioTrack() {//1、int bufsize = AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT);//2、指定音频流类型、采样率、声道、格式、工作模式等信息AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_STEREO,AudioFormat.ENCODING_PCM_16BIT, bufsize, AudioTrack.MODE_STREAM);//3、track.play();byte pkg[] = new byte[1024];//无效数据,只是用于分析;多数时候会在嵌套在某个循环之中//4、track.write(pkg, 0, pkg.length);//5、track.stop();//6、track.release();}示例代码罗列了使用AudioTrack时所需的一些重要步骤。
[键入文字]Android音频通路架构分析[键入文字]目录1. Abstract (3)2. Introduction (3)3. ARM11侧audio通路设置 (4)3.1 代码位置 (5)3.2 录音通路控制 (6)3.2.1 AudioRecord创建 (6)3.2.2 AudioRecord start (11)4. ARM9侧audio通路设置 (15)4.1 代码位置 (16)4.2 通路控制 (17)4.2.1 RPC&Snd Task (17)4.2.2 DEVMGR (18)4.2.3 AFE(audio codec config) (19)4.2.4 ADIE(ADIE codec config) (21)5. ARM9侧audio通路添加 (22)6. 内部PA和外部PA的使用 (26)7. Audio数据流 (27)1.Abstract主要是分析一下android平台音频通路的设置架构。
2.Introduction音频架构在android系统中非常复杂,本节主要分析audio通路的设置,以Radio通路的设置为例,详细介绍一下ARM9和ARM11侧的audio通路如何设置。
从整体架构上分析,与audio通路设置相关的模块包括ARM11,ARM9,ADSP,MDSP,Codec,音频设备。
其中控制信息主要集中在ARM11,ARM9,Internal Codec部分。
以图中的audio control data的流向为主线,对audio通路的设置进行分析。
主要包含以下几部分:●ARM11侧audio通路设置●ARM9侧audio通路设置●ARM9侧audio通路添加3.ARM11侧audio通路设置FM采取了先录再放的机制来设置声音通路。
如上图所示,总共包含以下几部分:JAVA应用层:包含FM的用户操作界面等,主要是FMRadio.java和FMRadioService.java.JNI层:主要用于连接java和c代码的中间层,主要是android_media_AudioRecord.cpp 和android_media_AudioTrack.cpp。
Android的Audio系统-gowyz的专栏-CSDN博客 Android的Audio系统收藏Android的Audio 系统第一部分 Audio系统综述第二部分 Audio系统和上层接口第三部分 Audio的硬件抽象层第一部分 Audio系统综述Audio系统在Android中负责音频方面的数据流传输和控制功能,也负责音频设备的管理。
Audio系统主要的分成几个层次:1. media中库提供的Audio系统的上层接口2. AudioFlinger作为Audio系统的中枢3. Audio库的硬件抽象层提供底层的支持4. Audio接口通过JNI和Java框架提供给上层Audio系统的上层接口主要提供了两方面的功能:放音(Track)和录音(Recorder)。
Media库(libmedia.so)的Audio部分的目录中:frameworks/base/include/media/frameworks/base/media/libmedia/这部分的内容被编译成库libmedia.so,提供Audio部分的接口。
Audio Flinger (libaudioflinger.so):frameworks/base/libs/audioflinger这部分内容被编译成库libaudioflinger.so。
Audio的JNI部分:frameworks/base/core/jniAudio的JAVA部分:frameworks/base/media/java/android/media主要包含AudioManager和Audio系统的几个类。
Audio硬件抽象层的接口:hardware/libhardware_legacy/include/hardware/第二部分 Audio系统和上层接口2.1 Audio系统的各个层次2.2 media库中的Audio框架部分2.3 AudioFlinger本地代码2.4 Audio系统的JNI代码2.5 Audio系统的Java代码2.1 Audio系统的各个层次Audio系统的结构:libmedia.so提供Audio接口,这些Audio接口既向上层开放,也向本地代码开发。
Android音频系统之AudioTrack(一)1.1 AudioTrack1.1.1 AudioTrack应用实例对于Android应用开发人员来讲,音频回放最熟悉的莫过于MediaPlayer,而AudioTrack相信用的人相对会少很多。
这是因为MediaPlayer提供了更完整的封装和状态控制,使得我们用很少的代码就可以实现一个简单的音乐播放器。
而相比MediaPlayer,AudioTrack更为精练、高效,实际上MediaPlayerService的内部实现就是使用了AudioTrack。
AudioTrack被用于PCM音频流的回放,在数据传送上它有两种方式:Ø调用write(byte[],int,int)或write(short[],int,int)把音频数据“push”到AudioTrack中。
Ø与之相对的,当然就是“pull”形式的数据获取,即数据接收方主动索取的过程,如下图所示:除此之外,AudioTrack还同时支持static和streaming两种模式:§ static静态的言下之意就是数据一次性交付给接收方。
好处是简单高效,只需要进行一次操作就完成了数据的传递;缺点当然也很明显,对于数据量较大的音频回放,显然它是无法胜任的,因而通常只用于播放铃声、系统提醒等对内存小的操作§ streaming流模式和网络上播放视频是类似的,即数据是按照一定规律不断地传递给接收方的。
理论上它可用于任何音频播放的场景,不过我们一般在以下情况下采用:Ø音频文件过大Ø音频属性要求高,比如采样率高、深度大的数据Ø音频数据是实时产生的,这种情况就只能用流模式了下面我们选取AudioTrackTest.java为例来讲解,先从使用者的角度来了解下AudioTrack。
/*cts/tests/tests/media/src/android/media/cts*/public voidtestSetStereoVolumeMax() throwsException {final String TEST_NAME= "testSetStereoVolumeMax";final int TEST_SR =22050;final int TEST_CONF =AudioFormat.CHANNEL_CONFIGURATION_STEREO;final int TEST_FORMAT= AudioFormat.ENCODING_PCM_16BIT;final int TEST_MODE =AudioTrack.MODE_STREAM;final intTEST_STREAM_TYPE = AudioManager.STREAM_MUSIC;// --------initialization --------------/*Step1.*/int minBuffSize = AudioTrack.getMinBufferSize(TEST_SR, TEST_CONF, TEST_FORMAT);/*Step 2.*/AudioTrack track = newAudioTrack(TEST_STREAM_TYPE, TEST_SR, TEST_CONF,TEST_FORMAT, 2 * minBuffSize,TEST_MODE);byte data[] = newbyte[minBuffSize];// -------- test--------------track.write(data, OFFSET_DEFAULT, data.length);track.write(data, OFFSET_DEFAULT, data.length);track.play();float maxVol =AudioTrack.getMaxVolume();assertTrue(TEST_NAME, track.setStereoVolume(maxVol, maxVol) == AudioTrack.SUCCESS);// -------- tear down--------------track.release();}这个TestCase是测试立体声左右声道最大音量的。
Android 音频系统1.系统架构Android的音频系统拥有一个比较标准和健全的架构,从上层应用,java framework服务AudioMananger,本地服务AudioFlinger,抽象层AlsaHAL,本地库,再调用external的tinyalsa外部支持库,最后到底层驱动的codec。
Java服务AudioManager作为服务端,本地服务AudioFlinger作为客户端,两者通过Binder 机制交互。
AudioFlinger对硬件功能的具体实现交给硬件抽象层AlsaHAL完成。
抽象层可以调用本地标准接口,或者直接调用Tinyalsa库去操作底层驱动。
详细调用过程如下图:简单说来,轨迹如下:Java端发起调用,MediaPlayer会转至MediaPlayerService,然后会调用相应的解码工具解码后创建AudioTrack,所有待输出的AudioTrack在AudioFlinger::AudioMixer里合成,然后通过AudioHAL(AudioHardwareInterface的实际实现者)传至实际的硬件来实现播放。
2.AudioFlingerAudioFlinger是android中的一个service,在android启动时就已经被加载。
AudioFlinger 向下访问AudioHardware,实现输出音频数据,控制音频参数。
同时,AudioFlinger向上通过IAudioFinger接口提供服务。
所以,AudioFlinger在Android的音频系统框架中起着承上启下的作用,地位相当重要。
AudioFlinger的类结构下面的图示描述了AudioFlinger类的内部结构和关系:∙IAudioFlinger接口这是AudioFlinger向外提供服务的接口,例如openOutput,openInput,createTrack,openRecord等等,应用程序或者其他service通过ServiceManager可以获得该接口。