Audio播放流程(六)---数据进入AudioTrack
1. 音频数据流的框图
2. AudioTrack播放音频数据的三个套路
先看个音频播放例子吧,我是使用Native的AudioTrack播放PCM的音频,这个例子目前还是存在一些问题的,声音能够播放,但是播放的声音存在underrun的问题,目前还没找到原因。希望在分析完音频流后能够解决吧。
#define BUF_SZ 44100
#define FRAME_COUNT 1024
#define pcm_file "/data/xusong-shzj2.wav"
int AudioTrackTest::Test01() {
long rate = 44100;
int fd = 0;
int length = 0;
unsigned long int MinFrameCount = 0;
unsigned char mBuffer[FRAME_COUNT];
fd = open(pcm_file,O_RDWR);
if(fd < 0)
{
printf("%s open failed\n",pcm_file);
}
/*
* MinFrameCount :
* 要达到正常的播放,那么最小的帧数是这么多
*/
AudioTrack::getMinFrameCount(&MinFrameCount,AUDIO_STREAM_MUSIC,rate);
printf("MinFrameCount = %lu\n",MinFrameCount);
sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_MUSIC,// stream type
rate,
AUDIO_FORMAT_PCM_16_BIT,// word length, PCM
AUDIO_CHANNEL_OUT_STEREO,
MinFrameCount);
status_t status = track->initCheck();
if(status != NO_ERROR) {
track.clear();
ALOGD("Failed for initCheck()");
return -1;
}
// start play
ALOGD("start");
track->start();
int us;
do{
length = read(fd,mBuffer,FRAME_COUNT);
if(length > 0)
track->write(mBuffer,length,false);
us = length*1000*1000/(rate*2*16);
usleep(us);
}while(length > 0);
usleep(20000);
ALOGD("stop");
track->stop();
usleep(20000);
return 0;
}
例程和上面的流程图是相匹配的,声音播放对于AudioTrack而言就三步。第一步:
创建AudioTrack的对象,这里面有个参数是MinFrameCount,它意味着要保证播放流 畅,AudioFlinger的回放线程至少需要分配的匿名内存的大小(MinFrameCount通道数采样深度);第二步:
调用track->start,启动播放;第三步:
调用track->write,持续的向匿名内存上写入音频数据即可。
至于AudioTrack的流程,参考Android 音频系统:从 AudioTrack 到 AudioFlinger