Android AudioTrack音频播放分析

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

Android AudioTrack音频播放分析音频资源在播放时,会经常出现冲突的情况,如在进行音乐播放时有电话呼入、有新消息的提示音需要播放等,此类的并发处理就需要有一个统一的处理策略。

在Android 系统开发中,通过为不同的场景配置不同的播放接口,在底层执行统一的并发策略,使得开发者可以将精力更集中在应用本身。

A udioTrack、MediaPlayer、SoundPool、Ringtone、JetPlayer等都是Android音频处理中常用接口,本文将针对AudioTrack接口进行详细说明。

AudioTrack
AudioTrack用于管理单个的音频资源。

在构造AudioTrack实例时,会涉及到流类型、采样率、通道配置、音频格式、缓冲大小、播放模式等因素。

AudioTrack支持STREAM_VOICE_CALL、STREAM_SYSTEM、STREAM_RING、STREAM_MUSIC和STREAM_ALARM等流类型。

AudioTrack支持44100Hz、22050Hz、11025Hz等采样率。

AudioTrack支持单声道(CHANNEL_OUT_MONO)、立体声(CHANNEL_OUT_STEREO)等两种通道。

AudioTrack支持ENCODING_PCM_16BIT、ENCODING_PCM_8BIT等两种编码格式。

AudioTrack支持两种播放模式:静态模式(static mode)和流模式(Streaming mode)。

其中静态模式由于没有从Java层向原生层传递数据造成的延迟,时延很小,当然受限于音频缓冲的大小,通常在游戏场景中用于播放时长很短的音频资源。

当音频流较大不足以在音频缓冲中一次写入时,可采用流模式。

AudioTrack的播放状态包括PLAYSTA TE_STOPPED、PLAYSTATE_PAUSED、PLAYSTATE_PLAYING等。

AudioTrack实例的状态包括STA TE_INITIALIZED、STA TE_NO_STA TIC_DATA、STA TE_UNINITIALIZED等。

向音频缓冲中添加数据的方法为write()。

在设置音频缓冲时,其大小与采样率、通道和音频格式有关。

其计算公式为:
缓冲大小=最小帧数×(通道==CHANNEL_OUT_STEREO?2:1)×(音频格式== PCM16?2:1)
而最小帧数则受制于采样率和音频设备的延迟等因素。

另外,在Android 2.3中,还引入了会话的概念,便于对单曲的音效进行处理。

相应的方法包括:attachAuxEffect()、getAudioSessionId()、setAuxEffectSendLevel()等。

通过AudioTrack.OnPlaybackPositionUpdateListener监听器可以监听播放进度。

下面是一个背景音频的播放过程:
代码10-3 AudioTrack播放音频文件
public class BackgroundAudio extends Thread {
public static final int SAMPLE_RATE = 16000;
public static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
public static final int BYTES_PER_SAMPLE = 2;
public static final int PLAYBACK_STREAM = AudioManager.STREAM_MUSIC;
……
public BackgroundAudio(byte[] data) {
//计算缓冲大小
final int minBufferSize = (BUFFER_TIME *SAMPLE_RA TE*BYTES_PER_SAMPLE) / 1000;
//计算硬件的最小缓冲
final int minHardwareBufferSize =
AudioTrack.getMinBufferSize(SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,AUDIO_FORMAT);
mBufferSize = Math.max(minHardwareBufferSize, minBufferSize);
mAudioTrack = new AudioTrack(PLAYBACK_STREAM,
SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AUDIO_FORMA T, mBufferSize, AudioTrack.MODE_STREAM);
if (mAudioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
writeAudio();
start(); // 启动背景线程去推送音频数据
mAudioTrack.play();
} else {
Log.e(TAG, "Error initializing audio track.");
}
}
……
private void writeAudio() {
int len = mData.length;
int count;
int maxBytes = Math.min(mBufferSize, len - mPos);
count = mAudioTrack.write(mData, mPos, maxBytes);
if (count < 0) {
Log.e(TAG, "Error writing looped audio data");
halt();
return;
}
mPos += count;
if (mPos == len) {
mPos = 0; // Wraparound
}
}
}
本文选自华清远见Android培训班教材《Android多媒体编程从初学到精通》,本书全部
章节下载见华清远见下载中心。

相关文档
最新文档