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

2024-04-22 17:32

本文主要是介绍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
  1. if (mMediaPlayer == null) {  
  2.     mMediaPlayer = new MediaPlayer(); // 创建MediaPlayer对象  
  3. }  
  4.   
  5. mMediaPlayer.reset();  
  6. String dataSource = getDataByPosition(mCursor, mPlayPosition);  
  7. mMediaPlayer.setDataSource(dataSource); // 设置需要播放的数据源  
  8. mMediaPlayer.prepare(); // 准备播放,如果是流媒体需要调用prepareAsync进行异步准备  
  9. if (Common.PLAY_MODE_SINGLE_LOOP == mPlayMode) {  
  10.     mMediaPlayer.setLooping(true); // 单曲循环  
  11. else {  
  12.     mMediaPlayer.setLooping(false); // 不循环播放  
  13. }  
  14. mMediaPlayer.start(); // 开始播放,如果是播放流媒体,需要等到流媒体准备完成才能播放(在prepare的callback函数中调用start进行播放)  
  15.   
  16. // 根据位置来获取歌曲位置  
  17. public String getDataByPosition(Cursor c, int position) {  
  18.     c.moveToPosition(position);  
  19.     int dataColumn = c.getColumnIndex(MediaStore.Audio.Media.DATA);  
  20.     String data = c.getString(dataColumn);  
  21.     return data;  
  22. }  
AudioTrack播放声音时不能直接把wav文件传递给AudioTrack进行播放,必须传递buffer,通过write函数把需要播放的缓冲区buffer传递给AudioTrack,然后才能播放。

AudioTrack使用的例子参考下面:
此示例转自:http://samyou.iteye.com/blog/1125872
[java] view plain copy
  1. public class AndroidTest extends Activity implements View.OnClickListener,SurfaceHolder.Callback  
  2. {  
  3.     private SurfaceHolder surfaceHolder = null;  
  4.     private SurfaceView surfaceView = null;  
  5.     private AudioTrack audioTrack = null;  
  6.     private Thread writePCMThread = null;  
  7.     private File audioFile = null;  
  8.     private FileInputStream fileInputStream = null;  
  9.     private byte buffer[] = new byte[16*10000];  
  10.   
  11.     // The Handler that gets information back from the other threads  
  12.     private final Handler msgHandler = new Handler()  
  13.     {  
  14.         public void handleMessage(Message msg)  
  15.         {  
  16.             switch (msg.what)  
  17.             {  
  18.             default:  
  19.                 break;  
  20.             }  
  21.         }  
  22.     };  
  23.   
  24.   
  25.     /** Called when the activity is first created. */  
  26.     @Override  
  27.     public void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         setContentView(R.layout.main);  
  30.         surfaceView = (SurfaceView) findViewById(R.id.surface);  
  31.         SurfaceHolder surfaceHolder = surfaceView.getHolder();  
  32.         surfaceHolder.addCallback(this);  
  33.         surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  
  34.         findViewById(R.id.button1).setOnClickListener(this);  
  35.         findViewById(R.id.button2).setOnClickListener(this);  
  36.     }  
  37.   
  38.     public void finish() {  
  39.         super.finish();  
  40.         System.out.println("finish");  
  41.         try {  
  42.             writePCMThread.interrupt();  
  43.         } catch (Exception e) {  
  44.         }  
  45.         try {  
  46.             fileInputStream.close();  
  47.         } catch (Exception e) {  
  48.         }  
  49.         try {  
  50.             audioTrack.stop();  
  51.             audioTrack.release();  
  52.         } catch (Exception e) {  
  53.         }  
  54.     }  
  55.   
  56.   
  57.   
  58.     protected void onResume()  
  59.     {  
  60.         super.onResume();  
  61.         System.out.println("back on!!!!!!!!!!!");  
  62.         initAudioTrack();  
  63.         audioFile = new File(Environment.getExternalStorageDirectory(),"test.wav");  
  64.         System.out.println(audioFile.length());  
  65.         try {  
  66.             fileInputStream = new FileInputStream(audioFile);  
  67.             fileInputStream.skip(0x2c);  
  68.         } catch (Exception e) {  
  69.         }  
  70.   
  71.         writePCMThread = new Thread(new Runnable(){  
  72.             public void run() {  
  73.                 try  
  74.                 {  
  75.                     while(fileInputStream.read(buffer)>=0)  
  76.                     {  
  77.                         System.out.println("write pcm data");  
  78.                         audioTrack.write(buffer, 0, buffer.length);  
  79.                     }  
  80.                 }  
  81.                 catch (Exception e) {  
  82.                     e.printStackTrace();  
  83.                 }  
  84.             }  
  85.         });  
  86.   
  87.     }  
  88.   
  89.     private void initAudioTrack()  
  90.     {  
  91.         int minBufferSize = AudioTrack.getMinBufferSize(0xac44, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);  
  92.         System.out.println("minBufferSize = "+minBufferSize);  
  93.         audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 0xac44,  
  94.         AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT, minBufferSize*2,AudioTrack.MODE_STREAM);  
  95.         audioTrack.setStereoVolume(1.0f, 1.0f);// 设置当前音量大小  
  96.         System.out.println("initAudioTrack over");  
  97.         audioTrack.play();  
  98.     }  
  99.   
  100.     public void onClick(View v)  
  101.     {  
  102.         switch (v.getId()) {  
  103.         case R.id.button1:  
  104.             writePCMThread.start();  
  105.             break;  
  106.         case R.id.button2:  
  107.             break;  
  108.         default:  
  109.             break;  
  110.     }  
  111.   
  112.   
  113.     }  
  114.   
  115.     public void surfaceCreated(SurfaceHolder holder) {  
  116.         System.out.println("surfaceCreated()");  
  117.         this.surfaceHolder = holder;  
  118.     }  
  119.   
  120.     public void surfaceDestroyed(SurfaceHolder holder) {  
  121.     }  
  122.   
  123.     public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  124.         int height) {  
  125.         this.surfaceHolder = holder;  
  126.     }  
  127.   
  128.     public void onActivityResult(int requestCode, int resultCode, Intent data) {  
  129.     }  
  130.   

   转至  : http://blog.csdn.net/ameyume/article/details/7618820

这篇关于MediaPlayer和AudioTrack播放Audio的区别与联系的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/926407

相关文章

Vue和React受控组件的区别小结

《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

Go之errors.New和fmt.Errorf 的区别小结

《Go之errors.New和fmt.Errorf的区别小结》本文主要介绍了Go之errors.New和fmt.Errorf的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考... 目录error的基本用法1. 获取错误信息2. 在条件判断中使用基本区别1.函数签名2.使用场景详细对

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

一文带你迅速搞懂路由器/交换机/光猫三者概念区别

《一文带你迅速搞懂路由器/交换机/光猫三者概念区别》讨论网络设备时,常提及路由器、交换机及光猫等词汇,日常生活、工作中,这些设备至关重要,居家上网、企业内部沟通乃至互联网冲浪皆无法脱离其影响力,本文将... 当谈论网络设备时,我们常常会听到路由器、交换机和光猫这几个名词。它们是构建现代网络基础设施的关键组成

redis和redission分布式锁原理及区别说明

《redis和redission分布式锁原理及区别说明》文章对比了synchronized、乐观锁、Redis分布式锁及Redission锁的原理与区别,指出在集群环境下synchronized失效,... 目录Redis和redission分布式锁原理及区别1、有的同伴想到了synchronized关键字

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

MyBatis中$与#的区别解析

《MyBatis中$与#的区别解析》文章浏览阅读314次,点赞4次,收藏6次。MyBatis使用#{}作为参数占位符时,会创建预处理语句(PreparedStatement),并将参数值作为预处理语句... 目录一、介绍二、sql注入风险实例一、介绍#(井号):MyBATis使用#{}作为参数占位符时,会

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Javaee多线程之进程和线程之间的区别和联系(最新整理)

《Javaee多线程之进程和线程之间的区别和联系(最新整理)》进程是资源分配单位,线程是调度执行单位,共享资源更高效,创建线程五种方式:继承Thread、Runnable接口、匿名类、lambda,r... 目录进程和线程进程线程进程和线程的区别创建线程的五种写法继承Thread,重写run实现Runnab