Android的Audio音频系统

合集下载

audiotrack播放原理

audiotrack播放原理

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的Audio音频系统

Android的Audio音频系统

重新启动
如果 AudioFlinger 运行的 media_server 进程异常死掉,AudioSystem 会收到一个事件通知, void AudioSystem::DeathNotifier::binderDied(const wp<IBinder>& who) { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); if (gAudioErrorCallback) { gAudioErrorCallback(DEAD_OBJECT); } LOGW("AudioFlinger server died!"); } 从而调用 android_media_AudioSystem.cpp 注册下来的回调函数,该函数又是通过 JNI 来调 用 AudioService.java 注册下来的回调函数, 在该函数中会发送 MSG_MEDIA_SERVER_DIED 消息,AudioService 会监听这个消息,这样 AudioService 就能知道 AudioFlinger 已不工作, 它就接着调用 getMode 来尝试连接到重启后的 AudioFlinger。 case MSG_MEDIA_SERVER_DIED: Log.e(TAG, "Media server died."); // Force creation of new IAudioflinger interface mMediaServerOk = false; AudioSystem.getMode(); break; 当连接成功后,AudioFlinger 会调用 android_media_AudioSystem.cpp 注册下来的回调函数, 该函数又是通过 JNI 来调用 AudioService.java 注册下来的回调函数,在该函数中会发送 MSG_MEDIA_SERVER_STARTED 消息。接着 AudioService 就去配置底层音频系统,包括 模式、路由、每一路流的音量大小和 Ringer 状态。 case MSG_MEDIA_SERVER_STARTED: // Restore audio routing and stream volumes applyAudioSettings(); for (int streamType = AudioSystem.NUM_STREAMS - 1; streamType >= 0; streamType--) { int volume; VolumeStreamState streamState = mStreamStates[streamType]; if (streamState.muteCount() == 0) { volume = streamState.mVolumes[streamState.mIndex];

Android Audio System

Android Audio System

引子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的Audio系统

_Android的Audio系统

2.1 Audio 系统的各个层次
Audio 管理环节 Audio 输出 Audio 输入
Java 层
AudioSystem
AudioTrack
AudioRecorder
本地框架层
AudioSystem
AudioTrack
AudioRecorderห้องสมุดไป่ตู้
AudioFlinger
IAudioFlinger
2.2 media 库中的 Audio 框架部分 AudioSystem.h :
class AudioSystem { public: enum stream_type { // Audio 流的类型 SYSTEM = 1, RING = 2, MUSIC = 3, ALARM = 4, NOTIFICATION = 5, BLUETOOTH_SCO = 6, ENFORCED_AUDIBLE = 7, NUM_STREAM_TYPES }; enum audio_output_type { // Audio 数据输出类型 // …… 省略部分内容 }; enum audio_format { // Audio 数据格式 FORMAT_DEFAULT = 0, PCM_16_BIT, PCM_8_BIT, INVALID_FORMAT };
第二部分 Audio 系统和上层接口
2.1 2.2 2.3 2.4 2.5
Audio 系统的各个层次 media 库中的 Audio 框架部分 AudioFlinger 本地代码 Audio 系统的 JNI 代码 Audio 系统的 Java 代码
2.1 Audio 系统的各个层次
Audio 系统的结构: libmedia.so 提供 Audio 接口,这些 Audio 接 口既像上层开放,也向本地代码开发。 libaudiofilnger.so 提供 Audio 接口实现。 Audio 硬件抽象层提供到硬件的接口,供 AudioFlinger 调用。 Audio 使用 JNI 和 JAVA 对上层提供接口。

android audio系统介绍

android audio系统介绍

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系统

AndroidN的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 Native服务之启动流程分析(一)

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使用方法详解

Android音频系统AudioTrack使用方法详解

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();//释放底层资源。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

} else { volume = streamState.mVolumes[0]; } AudioSystem.setVolume(streamType, volume); } setRingerMode(); Note: AudioSystem 的 Native device/libs/android_runtime/android_media_AudioSystem.cpp 中。
((1 << AudioSystem.STREAM_MUSIC)|(1 AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM))); // Each stream will read its own persisted settings // Broadcast the sticky intent broadcastRingerMode(); // Broadcast vibrate settings broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_RINGER); broadcastVibrateSetting(AudioManager.VIBRATE_TYPE_NOTIFICATION);
} binder->linkToDeath(gDeathNotifier); = interface_cast<IAudioFlinger>(binder); } LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?"); return gAudioFlinger; } 到此,整个音频系统初始化完毕。
<<
} 同时也会从底层音频系统读取模式和路由信息: private void readAudioSettings() { synchronized (mSettingsLock) { mMicMute = AudioSystem.isMicrophoneMuted(); mMode = AudioSystem.getMode(); for (int mode = 0; mode < AudioSystem.NUM_MODES; mode++) { mRoutes[mode] = AudioSystem.getRouting(mode); } } } 在 AudioSystem.cpp 第一次调用 get_audio_flinger 成功后,它会通过 binder 来监听运行在 media_server 进程中的 AudioFlinger 是否活着。 // establish binder interface to AudioFlinger service const sp<IAudioFlinger>& AudioSystem::get_audio_flinger() { Mutex::Autolock _l(gLock); if (gAudioFlinger.get() == 0) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16("media.audio_flinger")); if (binder != 0) break; LOGW("AudioFlinger not published, waiting..."); usleep(500000); // 0.5 s } while(true); if (gDeathNotifier == NULL) { gDeathNotifier = new DeathNotifier(); } else { if (gAudioErrorCallback) { gAudioErrorCallback(NO_ERROR); }
音频系统
JNI
JNI
JNI
初始化
在 system_init(运行在 Simulator 上)或者 main_Mediaserver 中,AudioFlinger 被创建,会生 成一个 AudioHardwareInterface 实例(Android 定义的音频设备的一个抽象层) ,并且初始化 音频系统的模式和路由信息如下: mHardwareStatus = AUDIO_HW_IDLE; mAudioHardware = AudioHardwareInterface::create(); mHardwareStatus = AUDIO_HW_INIT; if (mAudioHardware->initCheck() == NO_ERROR) { // open 16-bit output stream for s/w mixer mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; mOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT); mHardwareStatus = AUDIO_HW_IDLE; if (mOutput) { mSampleRate = mOutput->sampleRate(); mChannelCount = mOutput->channelCount();
重新启动
如果 AudioFlinger 运行的 media_server 进程异常死掉,AudioSystem 会收到一个事件通知, void AudioSystem::DeathNotifier::binderDied(const wp<IBinder>& who) { Mutex::Autolock _l(AudioSystem::gLock); AudioSystem::gAudioFlinger.clear(); if (gAudioErrorCallback) { gAudioErrorCallback(DEAD_OBJECT); } LOGW("AudioFlinger server died!"); } 从而调用 android_media_AudioSystem.cpp 注册下来的回调函数,该函数又是通过 JNI 来调 用 AudioService.java 注册下来的回调函数, 在该函数中会发送 MSG_MEDIA_SERVER_DIED 消息,AudioService 会监听这个消息,这样 AudioService 就能知道 AudioFlinger 已不工作, 它就接着调用 getMode 来尝试连接到重启后的 AudioFlinger。 case MSG_MEDIA_SERVER_DIED: Log.e(TAG, "Media server died."); // Force creation of new IAudioflinger interface mMediaServerOk = false; AudioSystem.getMode(); break; 当连接成功后,AudioFlinger 会调用 android_media_AudioSystem.cpp 注册下来的回调函数, 该函数又是通过 JNI 来调用 AudioService.java 注册下来的回调函数,在该函数中会发送 MSG_MEDIA_SERVER_STARTED 消息。接着 AudioService 就去配置底层音频系统,包括 模式、路由、每一路流的音量大小和 Ringer 状态。 case MSG_MEDIA_SERVER_STARTED: // Restore audio routing and stream volumes applyAudioSettings(); for (int streamType = AudioSystem.NUM_STREAMS - 1; streamType >= 0; streamType--) { int volume; VolumeStreamState streamState = mStreamStates[streamType]; if (streamState.muteCount() == 0) { volume = streamState.mVolumes[streamState.mIndex];
mFormat = mOutput->format(); mMixBufferSize = mOutput->bufferSize(); mFrameCount = mMixBufferSize / mChannelCount / sizeof(int16_t); mMixBuffer = new int16_t[mFrameCount * mChannelCount]; memset(mMixBuffer, 0, mMixBufferSize); mAudioMixer = new AudioMixer(mFrameCount, mSampleRate); // FIXME - this should come from settings setMasterVolume(1.0f); setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL); setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL); setMode(AudioSystem::MODE_NORMAL); mMasterMute = false; } else { LOGE("Failed to initialize output stream"); } } else { LOGE("Couldn't even initialize the stubbed audio hardware!"); } 在 SystemServer 启动的时候,会生成一个 AudioService 的实例, try { Log.i(TAG, "Starting Audio Service"); ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context)); } catch (Throwable e) { Log.e(TAG, "Failure starting Volume Service", e); } AudioService 的构造函数会读取一些关于音频的配置信息,比如 Ringer 和 vibrate 信息, private void readPersistedSettings() { final ContentResolver cr = mContentResolver; mRingerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL); mRingerModeAffectedStreams = System.getInt(mContentResolver, System.MODE_RINGER_STREAMS_AFFECTED, 1 << AudioSystem.STREAM_RING); mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0); mMuteAffectedStreams = System.getInt(cr, System.MUTE_STREAMS_AFFECTED,
相关文档
最新文档