zoukankan      html  css  js  c++  java
  • 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播放音乐的示例,音乐文件是从数据库中取出的。

    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. }  
        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

    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.   
    131. }  
    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等。

  • 相关阅读:
    html基础进阶笔记
    程序员的自我提升
    过滤思路
    for循环
    jeesite在生成主子表代码的时候在eclipse里面没有子表代码
    java学习笔记2
    人性的弱点
    java学习笔记
    Percona Toolkit 安装使用
    mysql 中查询当天、本周,本月,上一个月的数据
  • 原文地址:https://www.cnblogs.com/rosepotato/p/3338607.html
Copyright © 2011-2022 走看看