一、AudioTrack的使用
//设置音频属性
AudioAttributes audioAttributes = new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build();
//设置音频格式
AudioFormat audioFormat = new AudioFormat.Builder()
.setEncoding(AudioFormat.ENCODING_PCM_8BIT)
.setSampleRate(44100)
.setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
.build();
//计算最小缓冲区
int bufferSize = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_8BIT);
//创建AudioTrack对象
final AudioTrack audioTracker = new AudioTrack(audioAttributes, audioFormat, bufferSize, AudioTrack.MODE_STREAM, AudioManager.AUDIO_SESSION_ID_GENERATE);
//开始播放
audioTracker.play();
//创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(new Runnable() {
@Override
public void run() {
byte[] data = new byte[1024]; // small buffer size to not overflow AudioTrack's internal buffer
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(new File(PCM_FILE));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int readSize = 0;
while (readSize != -1) {
try {
readSize = fileInputStream.read(data);
} catch (IOException e) {
e.printStackTrace();
continue;
}
Log.d(TAG, "start play read size is " + readSize);
if (readSize > 0) {
//写入数据
audioTracker.write(data, 0, readSize);
}
}
try {
fileInputStream.close();
}
catch (IOException e) {
// handle exception
}
//播放结束
audioTracker.stop();
//释放资源
audioTracker.release();
}
});
1.mode模式: mode分为MODE_STREAM和MODE_STATIC模式,static模式是指将数据一次性写入到共享内存;stream模式是指将数据分多次写入共享内存。
2.输出流程: (attr、format、mode等) -> streamType -> strategy ->device -> output
二、output输出通道的选择
private AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,
int mode, int sessionId, boolean offload)
throws IllegalArgumentException {
........................................................................................
// Check if we should enable deep buffer mode
if (shouldEnablePowerSaving(mAttributes, format, bufferSizeInBytes, mode)) {
mAttributes = new AudioAttributes.Builder(mAttributes)
.replaceFlags((mAttributes.getAllFlags()
| AudioAttributes.FLAG_DEEP_BUFFER)
& ~AudioAttributes.FLAG_LOW_LATENCY)
.build();
}
.......................................................................................
int[] sampleRate = new int[] {mSampleRate};
int[] session = new int[1];
session[0] = sessionId;
// native initialization
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/,
offload);
.......................................................................................
}
应用层创建AudioTrack,会调用native_setup方法,native_setup方法对应android_media_AudioTrack.cpp类中的android_media_AudioTrack_setup方法。
xref: /frameworks/base/core/jni/android_media_AudioTrack.cpp
static const JNINativeMethod gMethods[] = {
..............................................................................
{"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZ)I",
(void *)android_media_AudioTrack_setup},
.............................................................................
};
android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa,
jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask,
jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession,
jlong nativeAudioTrack, jboolean offload) {
............................................................................................
// if we pass in an existing *Native* AudioTrack, we don't need to create/initialize one.
if (nativeAudioTrack == 0) {
............................................................................................
// 创建native端的AudioTrack对象
lpTrack = new AudioTrack();
............................................................................................
switch (memoryMode) {// 针对两种不同的模式设置不同的参数
case MODE_STREAM:// 多次写入数据模式
status = lpTrack->set(
AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
sampleRateInHertz,
format,// word length, PCM
nativeChannelMask,
offload ? 0 : frameCount,
offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_NONE,
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
0,// shared mem
true,// thread can call Java
sessionId,// audio session ID
offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK : AudioTrack::TRANSFER_SYNC,
offload ? &offloadInfo : NULL,
-1, -1, // default uid, pid values
paa.get());
break;
case MODE_STATIC:// 一次写入数据模式
// AudioTrack is using shared memory
if (!lpJniStorage->allocSharedMem(buffSizeInBytes)) {
ALOGE("Error creating AudioTrack in static mode: error creating mem heap base");
goto native_init_failure;
}
status = lpTrack->set(
AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
sampleRateInHertz,
format,// word length, PCM
nativeChannelMask,
frameCount,
AUDIO_OUTPUT_FLAG_NONE,
audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
lpJniStorage->mMemBase,// shared mem
true,// thread can call Java
sessionId,// audio session ID
AudioTrack::TRANSFER_SHARED,
NULL, // default offloadInfo
-1, -1, // default uid, pid values
paa.get());
break;
............................................................................................
} else { // end if (nativeAudioTrack == 0)
............................................................................................
}
lpTrack = new AudioTrack()创建AudioTrack,pTrack->set调用AudioTrack.cpp的set方法设置参数。
xref: /frameworks/av/media/libaudioclient/AudioTrack.cpp
status_t AudioTrack::set(
audio_stream_type_t streamType,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
audio_output_flags_t flags,
callback_t cbf,
void* user,
int32_t notificationFrames,
const sp<IMemory>& sharedBuffer,
bool threadCanCallJava,
audio_session_t sessionId,
transfer_type transferType,
const audio_offload_info_t *offloadInfo,
uid_t uid,
pid_t pid,
const audio_attributes_t* pAttributes,
bool doNotReconnect,
float maxRequiredSpeed,
audio_port_handle_t selectedDeviceId)
{
.............................................................................................
mCbf = cbf;
if (cbf != NULL) {// 如果设置了回调函数,则创建AudioTrackThread线程来提供音频数据
mAudioTrackThread = new AudioTrackThread(*this);
mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
// thread begins in paused state, and will not reference us until start()
}
// 创建IAudioTrack
{
AutoMutex lock(mLock);
status = createTrack_l();
}
if (status != NO_ERROR) {
if (mAudioTrackThread != 0) {
mAudioTrackThread->requestExit(); // see comment in AudioTrack.h
mAudioTrackThread->requestExitAndWait();
mAudioTrackThread.clear();
}
goto exit;
}
.............................................................................................
}
streamType: 音频流类型,如 Music、Voice-Call、DTMF、Alarm 等等
sampleRate: 音频采样率,如 16KHz、44.1KHz、48KHz 等等
format:音频格式,如 PCM、MP3、AAC 等等
channelMask: 声道数, 如 Mono(单声道)、Stereo(双声道)
frameCount: 帧数, 用于audioFlinger申请内存

4019

被折叠的 条评论
为什么被折叠?



