标签:
众所周知,Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的。MediaPlayer在底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaPlayer程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制。但是该类只能对完整的音频文件进行操作,而不能直接对纯PCM音频数据操作。假如我们通过解码得到PCM数据源,又当如何将它们播放?没错,就是用AudioTrack这个类(MediaPlayer内部也是调用该类进行真正的播放音频流操作)下面这个DEMO演示了如何使用AudioTrack来播放PCM音频数据
废话不多说,先上效果图:
工程代码结构也较为简单:
简单说下思路,先把PCM音频数据从指定的路径文件读到内存,然后给AudioPlayer设置数据源,音频参数等,最后执行播放,暂停,停止等操作
贴上部分类代码片段:
- public class AudioParam {
-
- int mFrequency;
-
- int mChannel;
-
- int mSampBit;
-
- }
- public interface PlayState {
-
- public static final int MPS_UNINIT = 0;
-
- public static final int MPS_PREPARE = 1;
-
- public static final int MPS_PLAYING = 2;
-
- public static final int MPS_PAUSE = 3;
- }
AudioPlayer代码片段如下:
- public class AudioPlayer implements IPlayComplete{
-
- private final static String TAG = "AudioPlayer";
-
- public final static int STATE_MSG_ID = 0x0010;
-
- private Handler mHandler;
-
- private AudioParam mAudioParam;
-
- private byte[] mData;
-
- private AudioTrack mAudioTrack;
-
- private boolean mBReady = false;
-
- private PlayAudioThread mPlayAudioThread;
-
- public AudioPlayer(Handler handler)
- {
- mHandler = handler;
- }
-
- public AudioPlayer(Handler handler,AudioParam audioParam)
- {
- mHandler = handler;
- setAudioParam(audioParam);
- }
-
-
- public void setAudioParam(AudioParam audioParam)
- {
- mAudioParam = audioParam;
- }
-
-
- public void setDataSource(byte[] data)
- {
- mData = data;
- }
-
-
-
- public boolean prepare()
- {
- if (mData == null || mAudioParam == null)
- {
- return false;
- }
-
- if (mBReady == true)
- {
- return true;
- }
-
- try {
- createAudioTrack();
- } catch (Exception e) {
-
- e.printStackTrace();
- return false;
- }
-
-
- mBReady = true;
-
- setPlayState(PlayState.MPS_PREPARE);
-
- return true;
- }
- private boolean mThreadExitFlag = false;
-
- private int mPrimePlaySize = 0;
-
- private int mPlayOffset = 0;
-
- private int mPlayState = 0;
-
-
-
- class PlayAudioThread extends Thread
- {
-
-
- @Override
- public void run() {
-
-
-
- Log.d(TAG, "PlayAudioThread run mPlayOffset = " + mPlayOffset);
-
- mAudioTrack.play();
-
- while(true)
- {
-
- if (mThreadExitFlag == true)
- {
- break;
- }
-
- try {
-
- int size = mAudioTrack.write(mData, mPlayOffset, mPrimePlaySize);
- mPlayOffset += mPrimePlaySize;
-
- } catch (Exception e) {
-
- e.printStackTrace();
- AudioPlayer.this.onPlayComplete();
- break;
- }
-
- if (mPlayOffset >= mData.length)
- {
- AudioPlayer.this.onPlayComplete();
- break;
- }
-
-
- }
-
- mAudioTrack.stop();
-
- Log.d(TAG, "PlayAudioThread complete...");
- }
-
-
-
- }
下面来剖析以下如何使用AudioTrack来播放PCM音频数据
首先要构建一个AudioTrack对象:(需要采样率,声道,采样精度参数)
- private void createAudioTrack() throws Exception
- {
-
-
- int minBufSize = AudioTrack.getMinBufferSize(mAudioParam.mFrequency,
- mAudioParam.mChannel,
- mAudioParam.mSampBit);
-
-
- mPrimePlaySize = minBufSize * 2;
- Log.d(TAG, "mPrimePlaySize = " + mPrimePlaySize);
-
- mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
- mAudioParam.mFrequency,
- mAudioParam.mChannel,
- mAudioParam.mSampBit,
- minBufSize,
- AudioTrack.MODE_STREAM);
-
-
-
- }
然后开一个子线程从缓存区里分块取数据然后写入硬件设备进行播放
- private void startThread()
- {
- if (mPlayAudioThread == null)
- {
- mThreadExitFlag = false;
- mPlayAudioThread = new PlayAudioThread();
- mPlayAudioThread.start();
- }
- }
AudioTrack里有三个重要方法:
void play()
int write(byte[] audioData, int offsetInBytes, int sizeInBytes) (该方法是阻塞的)
void stop()
从前面那个线程代码可以看出,我们在写数据之前需要先执行 play(),然后才能进行write操作,当数据播放完毕或是线程被外部终止的时候最后调用stop()停止写数据;若执行了play操作但后面却没有执行write操作的话,或是write操作结束后没有调用stop,观察logcat会不断打印提示信息,这是提示我们对以上三个方法的调用要规范
只要大家设置的音频参数和音频数据都是正确的,就能顺畅的播放出声音,本例已经附带了用于测试的音频文件以及参数说明(已测试通过),具体看工程里音频数据这个文件夹下的readme.txt即可.网上有些童鞋反应说audiotrack播放音频不顺畅,如果数据源没问题的话估计是他们的demo里没有连续地执行write操作而导致的,其它的不多说了,觉得有用的童鞋自己写代码看吧。。。喜欢就顶一下吧!
代码链接如下:
https://github.com/dongweiq/study/AudioPlayerDemo
本文着重介绍audiotrack的使用,关于其底层原理,且看这位仁兄的文章:
http://www.cnblogs.com/innost/archive/2011/01/09/1931457.html
我的github地址:https://github.com/dongweiq/study
欢迎关注,欢迎star o(∩_∩)o 。有什么问题请邮箱联系 dongweiqmail@gmail.com qq714094450
使用AudioTrack播放PCM音频数据(android)
标签:
原文地址:http://www.cnblogs.com/dongweiq/p/4511908.html