MediaPlayer和AudioTrack播放Audio的区别与联系
转自http://blog.csdn.net/ameyume/article/details/7618820
播放声音可以用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播放音乐的示例,音乐文件是从数据库中取出的。
- 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;
- }
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
- 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) {
- }
- }
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等。
MediaPlayer和AudioTrack播放Audio的区别与联系的更多相关文章
- Android 音视频开发(三):使用 AudioTrack 播放PCM音频
一.AudioTrack 基本使用 AudioTrack 类可以完成Android平台上音频数据的输出任务.AudioTrack有两种数据加载模式(MODE_STREAM和MODE_STATIC),对 ...
- 使用AudioTrack播放PCM音频数据(android)
众所周知,Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的.MediaPl ...
- Android音视频之AudioTrack播放音频(二)
前一篇讲了如何录制wav音频文件,本篇就来讲讲如何播放wav文件,这里就是使用AudioTrack来播放音频,确切的说是播放pcm格式数据,使用AudioTrack播放也没什么难度,主要就是将数据写入 ...
- android开发之MediaPlayer+Service MP3播放器
import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Lis ...
- Android开发 MediaPlayer入门_播放本地视频
前言 MediaPlayer,可以播放视频/音频,并且它支持本地和网络文件的播放.本片博客作为入门教程,先以最通俗的方式解释播放文件本地视频.(如果你嫌MediaPlayer还是太麻烦可以试试选择Vi ...
- Android音频: 怎样使用AudioTrack播放一个WAV格式文件?
翻译 By Long Luo 原文链接:Android Audio: Play a WAV file on an AudioTrack 译者注: 1. 因为这是技术文章,所以有些词句使用原文,表达更准 ...
- 【Android 多媒体应用】使用MediaCodec解码使用AudioTrack播放音频数据
1.MainActivity.java import android.app.Activity; import android.os.Bundle; import android.os.Environ ...
- audio 基本功能实现(audio停止播放,audio如何静音,audio音量控制等)
audio最简单原始的播放.暂停.停止.静音.音量大小控制的功能,注意某些浏览器会有权限无法自动播放噢(video也会如此) <!doctype html> <html> &l ...
- Android Multimedia框架总结(二)MediaPlayer框架及播放网络视频案例
前言:前面一篇我们介绍MediaPlayer相关方法,有人说,没有实际例子,看得不是很明白,今天在分析MediaPlayer时,顺带一个播放网络视频例子.可以自行试试.今天分析的都是下几篇介绍各个模块 ...
随机推荐
- c#中const与readonly区别
const 的概念就是一个包含不能修改的值的变量.常数表达式是在编译时可被完全计算的表达式.因此不能从一个变量中提取的值来初始化常量.如果 const int a = b+1;b是一个变量,显然不能再 ...
- IE11下ASP.NET Forms身份认证无法保存Cookie的问题
IE11下ASP.NET Forms身份认证无法保存Cookie的问题 折腾了三四天,今天才找到资料,解决了. 以下会转贴,还没来得及深究,先放着,有空再学习下. ASP.NET中使用Forms身份认 ...
- 由于Linux操作平台屡次受到黑客的“青睐”,LINUX公司也越来越注重产品的安全问题。
Guardian Digital公司和安全管理服务提供商(MSSP)Guardent公司推出的新产品将提高开放式源代码和Linux产品的安全性能. Guardian Digital公司将于本月底在纽约 ...
- Spark Streaming揭秘 Day32 WAL框架及实现
Spark Streaming揭秘 Day32 WAL框架及实现 今天会聚焦于SparkStreaming中非常重要的数据安全机制WAL(预写日志). 设计要点 从本质点说,WAL框架是一个存储系统, ...
- N皇后问题2
Description Examine the checkerboard below and note that the six checkers are arranged on the board ...
- 十六、mysql 分区之 简单sql优化2
.索引的分类 B-Tree 基本支持 HASH 只有memory支持 R-Tree myisam支持 Full-text myisam支持(全文索引) .Memory引擎下只有“=”条件才会使用索引 ...
- [译] ASP.NET 生命周期 – ASP.NET 上下文对象(六)
使用 HttpApplication 对象 ASP.NET 框架中的许多类都提供了许多很方便的属性可以直接映射到 HttpContext 类中定义的属性.这种交叠有一个很好的例子就是 HttpAppl ...
- 【BZOJ 2878】 [Noi2012]迷失游乐园
Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环( ...
- google calendar api v3
google api for .net nuget Install-Package Google.Apis.Calendar.v3 oauth2 for asp.net http://www.code ...
- multimap和multiset 认知和使用
之前只是在C++ Primer里面看过关联容器,可能因为没有实际用过,只是看看,所以导致用的时候并不熟悉: 在这之前,map和set的特性应该要了解,map是关联数组,也就是由键值对组成的,而set只 ...