您的位置:首页 > 大数据 > 物联网

MediaPlayer和AudioTrack播放Audio的区别与联系

2016-02-23 10:48 501 查看
转:/article/1392282.html

MediaPlayer和AudioTrack播放Audio的区别与联系

播放声音可以用MediaPlayer和AudioTrack,两者都提供了java API供应用开发者使用。虽然都可以播放声音,但两者还是有很大的区别的。

其中最大的区别是MediaPlayer可以播放多种格式的声音文件,例如MP3,AAC,WAV,OGG,MIDI等。MediaPlayer会在framework层创建对应的音频解码器。

而AudioTrack只能播放已经解码的PCM流,如果是文件的话只支持wav格式的音频文件,因为wav格式的音频文件大部分都是PCM流。AudioTrack不创建解码器,所以只能播放不需要解码的wav文件。

当然两者之间还是有紧密的联系的,MediaPlayer在framework层还是会创建AudioTrack,把解码后的PCM数流传递给AudioTrack,AudioTrack再传递给AudioFlinger进行混音,然后才传递给硬件播放。

所以是MediaPlayer包含了AudioTRack。

通过查看API可以知道,MediaPlayer提供了5个setDataSource方法,分为三类,一类是传递播放文件的字符串路径作为参数,例如直接取sd卡里mp3文件的路径,一类是传递播放文件的FileDescriptor文件描述符作为播放的id,例例如从db中查询的音频文件的id,就可以直接赋给MediaPlayer进行播放。还有一类是Uri类型的资源文件,用于播放content
uri文件。

下面是一个用MediaPlayer播放音乐的示例,音乐文件是从数据库中取出的。

[java] view
plain copy

if (mMediaPlayer == null) {

mMediaPlayer = new MediaPlayer(); // 创建MediaPlayer对象

}

mMediaPlayer.reset();

String dataSource = getDataByPosition(mCursor, mPlayPosition);

mMediaPlayer.setDataSource(dataSource); // 设置需要播放的数据源

mMediaPlayer.prepare(); // 准备播放,如果是流媒体需要调用prepareAsync进行异步准备

if (Common.PLAY_MODE_SINGLE_LOOP == mPlayMode) {

mMediaPlayer.setLooping(true); // 单曲循环

} else {

mMediaPlayer.setLooping(false); // 不循环播放

}

mMediaPlayer.start(); // 开始播放,如果是播放流媒体,需要等到流媒体准备完成才能播放(在prepare的callback函数中调用start进行播放)

// 根据位置来获取歌曲位置

public String getDataByPosition(Cursor c, int position) {

c.moveToPosition(position);

int dataColumn = c.getColumnIndex(MediaStore.Audio.Media.DATA);

String data = c.getString(dataColumn);

return data;

}

AudioTrack播放声音时不能直接把wav文件传递给AudioTrack进行播放,必须传递buffer,通过write函数把需要播放的缓冲区buffer传递给AudioTrack,然后才能播放。

AudioTrack使用的例子参考下面:

此示例转自:http://samyou.iteye.com/blog/1125872

[java] view
plain copy

public class AndroidTest extends Activity implements View.OnClickListener,SurfaceHolder.Callback

{

private SurfaceHolder surfaceHolder = null;

private SurfaceView surfaceView = null;

private AudioTrack audioTrack = null;

private Thread writePCMThread = null;

private File audioFile = null;

private FileInputStream fileInputStream = null;

private byte buffer[] = new byte[16*10000];

// The Handler that gets information back from the other threads

private final Handler msgHandler = new Handler()

{

public void handleMessage(Message msg)

{

switch (msg.what)

{

default:

break;

}

}

};

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

surfaceView = (SurfaceView) findViewById(R.id.surface);

SurfaceHolder surfaceHolder = surfaceView.getHolder();

surfaceHolder.addCallback(this);

surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

findViewById(R.id.button1).setOnClickListener(this);

findViewById(R.id.button2).setOnClickListener(this);

}

public void finish() {

super.finish();

System.out.println("finish");

try {

writePCMThread.interrupt();

} catch (Exception e) {

}

try {

fileInputStream.close();

} catch (Exception e) {

}

try {

audioTrack.stop();

audioTrack.release();

} catch (Exception e) {

}

}

protected void onResume()

{

super.onResume();

System.out.println("back on!!!!!!!!!!!");

initAudioTrack();

audioFile = new File(Environment.getExternalStorageDirectory(),"test.wav");

System.out.println(audioFile.length());

try {

fileInputStream = new FileInputStream(audioFile);

fileInputStream.skip(0x2c);

} catch (Exception e) {

}

writePCMThread = new Thread(new Runnable(){

public void run() {

try

{

while(fileInputStream.read(buffer)>=0)

{

System.out.println("write pcm data");

audioTrack.write(buffer, 0, buffer.length);

}

}

catch (Exception e) {

e.printStackTrace();

}

}

});

}

private void initAudioTrack()

{

int minBufferSize = AudioTrack.getMinBufferSize(0xac44, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);

System.out.println("minBufferSize = "+minBufferSize);

audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 0xac44,

AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize*2,AudioTrack.MODE_STREAM);

audioTrack.setStereoVolume(1.0f, 1.0f);// 设置当前音量大小

System.out.println("initAudioTrack over");

audioTrack.play();

}

public void onClick(View v)

{

switch (v.getId()) {

case R.id.button1:

writePCMThread.start();

break;

case R.id.button2:

break;

default:

break;

}

}

public void surfaceCreated(SurfaceHolder holder) {

System.out.println("surfaceCreated()");

this.surfaceHolder = holder;

}

public void surfaceDestroyed(SurfaceHolder holder) {

}

public void surfaceChanged(SurfaceHolder holder, int format, int width,

int height) {

this.surfaceHolder = holder;

}

public void onActivityResult(int requestCode, int resultCode, Intent data) {

}

}

注:PCM和WAV

以下摘自:http://www.erji.net/read.php?tid=227570

简单来说,pcm是一种数据编码格式,CD唱盘上刻录的就直接用pcm格式编码的数据文件;

wav是一种声音文件格式,wav里面包含的声音数据可以是采用pcm格式编码的声音数据,也可以是采用其它格式编码的声音数据,但目前一般采用pcm编码的声音数据

两者区别就是这些

pcm是一个通信上的概念,脉冲编码调制。wav是媒体概念,体现的是封装。wav文件可以封装pcm编码信息,也可以封装其他编码格式,例如mp3等。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: