zoukankan      html  css  js  c++  java
  • Android 音频播放——AudioTrack直接播PCM、MediaPlayer播媒体文件可以是audio

    http://blog.csdn.net/java_android_c/article/details/52678265

    Android平台播放音频的方式一般有3种。1.利用系统内置的应用程序播放音频    2.利用AudioTrack播放原始音频   3.使用MediaPlayer播放。此3种音频播放方式,以第三种MediaPlayer播放这种方式使用的最多,必须掌握!

    一、使用系统内置的程序。

    Google想的“周到”,一般都给我们提供了一些内置程序,然而这些内置程序的UI效果,那真是感人啊!一般内置程序,我们就是看看而已。

    [java] view plain copy
     
    1. Intent intent=new Intent(Intent.ACTION_VIEW);  
    2. intent.setDataAndType(url,type); //eg:intent.setDataAndType(url,“audio/mp3”);  url音频文件路径  
    3. startActivity(intent);  


    二、使用AudioTrack播放音频:只能播放原始的PCM数据,通过callback函数一直写入HW。实际上MediaPlayer也是通过AudioTrack来播放音频的

     在NuPlayer有一个mAudioSink,实际是AudioOutput类型,内部有一个AudioTrack,用来播放解码后的PCM数据

    AudioTrack只能用来播放原始音频(PCM)

    [java] view plain copy
     
    1. //播放音频(PCM)  
    2.     public void play()  
    3.     {     
    4.         DataInputStream dis=null;  
    5.         try {  
    6.              //从音频文件中读取声音  
    7.              dis=new DataInputStream(new BufferedInputStream(new FileInputStream(recordingFile)));  
    8.             } catch (FileNotFoundException e) {  
    9.               e.printStackTrace();  
    10.             }  
    11.         //最小缓存区  
    12.         int bufferSizeInBytes=AudioTrack.getMinBufferSize(sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT);  
    13.         //创建AudioTrack对象   依次传入 :流类型、采样率(与采集的要一致)、音频通道(采集是IN 播放时OUT)、量化位数、最小缓冲区、模式  
    14.         player=new AudioTrack(AudioManager.STREAM_MUSIC,sampleRateInHz,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_16BIT, bufferSizeInBytes, AudioTrack.MODE_STREAM);  
    15.           
    16.         byte[] data =new byte [bufferSizeInBytes];  
    17.         player.play();//开始播放  
    18.         while(true)  
    19.         {  
    20.             int i=0;  
    21.             try {  
    22.                 while(dis.available()>0&&i<data.length)  
    23.                 {  
    24.                   data[i]=dis.readByte();//录音时write Byte 那么读取时就该为readByte要相互对应  
    25.                   i++;  
    26.                 }  
    27.             } catch (IOException e) {  
    28.                 // TODO Auto-generated catch block  
    29.                 e.printStackTrace();  
    30.             }  
    31.             player.write(data,0,data.length);  
    32.               
    33.             if(i!=bufferSizeInBytes) //表示读取完了  
    34.             {  
    35.                 player.stop();//停止播放  
    36.                 player.release();//释放资源  
    37.                 break;  
    38.             }  
    39.         }  
    40.           
    41.     }  

    这里是播放PCM的关键代码,完整Demo在本文的末尾会给出相应的链接!主要是从文件中读取数据到数组中,然后写到AudiotTrack之中,然后AudioTrack就会将其播放,利i!=bufferSizeInBytes 判断其读取完了(文件的末尾)。

    三、使用MediaPlayer进行音频播放。——这个是播放多媒体的,包括audio和 video

    MediaPlayer是很强大的一个Android系统内置的类,它不仅可以播放音频同时还可以播放视频。最常见的方法有:

    start()开始播放        pause()暂停播放    stop()停止播放       prepareAsync() /prepare()  开始准备     

    getCurrentPosition() 当前播放的位置         getDuration()文件总的时长      seekTo (int position)定位播放

    示例代码 演示利用MediaPlayer和Seekbar进行音频 的播放 、暂停、拖动快进播放等 。效果如图:(具体完整代码在备注里面可下载MediaPlayerDemo)

    布局文件:

    [html] view plain copy
     
    1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    2.     xmlns:tools="http://schemas.android.com/tools"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     android:background="@drawable/background"  
    6.     tools:context="${relativePackage}.${activityClass}" >  
    7.   
    8.     <TextView   
    9.         android:layout_width="wrap_content"  
    10.         android:layout_height="wrap_content"  
    11.         android:text="天空之城主题曲(宫崎骏)"  
    12.         android:textColor="#F8F8F8"  
    13.         android:textSize="18sp"  
    14.         android:ellipsize="marquee"  
    15.         android:layout_centerInParent="true"  
    16.         />  
    17.       
    18.     <LinearLayout   
    19.         android:layout_width="match_parent"  
    20.         android:layout_height="wrap_content"  
    21.         android:layout_marginLeft="5dp"  
    22.         android:layout_marginRight="5dp"  
    23.         android:layout_marginBottom="5dp"  
    24.         android:layout_above="@+id/bottom"  
    25.         android:gravity="center_vertical"  
    26.         >  
    27.      
    28.     <TextView  
    29.         android:id="@+id/left"  
    30.         android:layout_width="wrap_content"  
    31.         android:layout_height="wrap_content"  
    32.         android:text="00:00"  
    33.         android:textColor="#F8F8F8"  
    34.         />  
    35.       
    36.     <SeekBar   
    37.         android:id="@+id/seek"  
    38.         android:layout_width="match_parent"  
    39.         android:layout_height="wrap_content"  
    40.         android:layout_weight="1"  
    41.         android:enabled="false"  
    42.         />  
    43.      
    44.     <TextView  
    45.         android:id="@+id/right"  
    46.         android:layout_width="wrap_content"  
    47.         android:layout_height="wrap_content"  
    48.         android:text="00:00"  
    49.         android:textColor="#F8F8F8"  
    50.         />  
    51.       
    52.     </LinearLayout>  
    53.       
    54.     <LinearLayout  
    55.         android:id="@+id/bottom"  
    56.         android:layout_width="match_parent"  
    57.         android:layout_height="wrap_content"  
    58.         android:layout_alignParentBottom="true"  
    59.         android:layout_marginBottom="5dp"  
    60.         android:orientation="horizontal" >  
    61.           
    62.         <Button  
    63.             android:id="@+id/start"   
    64.             android:layout_width="0dp"  
    65.             android:layout_height="wrap_content"  
    66.             android:layout_weight="1"  
    67.             android:text="播放"  
    68.             android:textColor="#F8F8F8"  
    69.             android:textSize="14sp"  
    70.             android:enabled="false"  
    71.             />  
    72.           
    73.         <Button  
    74.             android:id="@+id/stop"   
    75.             android:layout_width="0dp"  
    76.             android:layout_height="wrap_content"  
    77.             android:layout_weight="1"  
    78.             android:text="暂停"  
    79.             android:textSize="14sp"  
    80.             android:textColor="#F8F8F8"  
    81.             android:enabled="false"  
    82.             />  
    83.           
    84.     </LinearLayout>  
    85.       
    86. </RelativeLayout>  

    初始化MediaPlayer

    [java] view plain copy
     
    1.       mAssetManager=getAssets();  
    2. try {  
    3.     afd=mAssetManager.openFd("sky.mp3");// 创建天空之城的AssetFileDescriptor文件  
    4.     } catch (IOException e) {  
    5.     e.printStackTrace();  
    6.     Log.e(TAG,"创建AssetFileDescriptor 异常 ,请查看根福是否存在");  
    7. }  
    8. mMediaPlayer=new MediaPlayer();  
    9. try {  
    10.     //设置播放源 ,当然还有其他的重载方法 eg:setDataSource(String path) path可以使网络路径也可以是本地路径,网络的记得加权限  
    11.     mMediaPlayer.setDataSource(afd.getFileDescriptor());   
    12. catch (Exception e) {  
    13.     e.printStackTrace();  
    14.     Log.e(TAG,"设置播放源异常" );  
    15. }  
    16. mMediaPlayer.prepareAsync(); //MediaPlayer 开始准备  异步的, 还有prepare()这个是同步的  

    MediaPlayer设置相应的监听器

    [java] view plain copy
     
    1. seek.setMax(100);//设置长度100  
    2. seek.setOnSeekBarChangeListener(this);//设置Seekbar的滑动监听器  
    3. mMediaPlayer.setOnPreparedListener(this);//设置准备就绪监听  
    4. mMediaPlayer.setOnCompletionListener(this);//设置播放完成  
    [java] view plain copy
     
    1. //结束滑动时     
    2. @Override  
    3. public void onStopTrackingTouch(SeekBar seekBar) {  
    4.       int a=(int)((sum/100.0)*(seekBar.getProgress()));  
    5.       mMediaPlayer.seekTo(a); //seekTo方法接收的单位是:毫秒  
    6.       handler.sendEmptyMessage(START); //更新seekBar  
    7. }  
    [java] view plain copy
     
    1. @Override  
    2. public void onPrepared(MediaPlayer mp) {  
    3.        //准备就绪完成  
    4.         start.setEnabled(true);  
    5.         stop.setEnabled(true);  
    6.         seek.setEnabled(true);  
    7.         sum=mMediaPlayer.getDuration();  
    8.         right.setText(FormatTime(sum/1000));  }  
    [java] view plain copy
     
    1. //播放完成  
    2. @Override  
    3. public void onCompletion(MediaPlayer mp) {  
    4.     start.setText("播放");  
    5.     seek.setProgress(0);  
    6.     mMediaPlayer.seekTo(0);  
    7. }  

    Handler 更新SeekBar的状态:

    [java] view plain copy
     
    1. private Handler handler=new Handler()  
    2.    {  
    3.     @Override  
    4.     public void handleMessage(Message msg) {  
    5.         switch (msg.what) {  
    6.             case 1:{  
    7.                 int current=mMediaPlayer.getCurrentPosition();// 得到数值的单位是毫秒  
    8.                 int prass=(int)(current/(sum*1.0)*100);  
    9.                 left.setText(FormatTime(current/1000));  
    10.                 seek.setProgress(prass);  
    11.                 if(!pause)  
    12.                 {  
    13.                   handler.sendEmptyMessageDelayed(1,1000);//1 秒后继续更新  
    14.                 }  
    15.                 break;  
    16.             }  
    17.               
    18.             case 0:{  
    19.                 //停止更新  
    20.                 pause=true;  
    21.                 break;  
    22.             }  
    23.         default:  
    24.             break;  
    25.         }  
    26.     }  
    27.       
    28.    };  

    1.比较容易让人混淆的是pause方法和stop方法的区别:2个方法都可以让音频停止。

    调用Pause方法后想再次听见声音直接调用start方法之后即可。调用stop方法停止音频之后,再次调用start方法之后不会播放,要先调用prepareAsync或者prepare方法,之后在public void onPrepared(MediaPlayer mp)回调方法里面调用start方法才会播放。

    2.start方法要在准备就绪,即在public void onPrepared(MediaPlayer mp)里面回调。

    3.不使用MediaPlayer时记得stop,然后release 释放相关的资源。(本例在Activity的OnDestroy方法中调用的)

    下图是MediaPlayer状态及方法流程图:

    四、备注:

    AudioTrack播放PCMDemo  如果对Demo中音频采集不熟悉,可以查阅 Android 音频采集

    MediaPlayerDemo(利用MediaPlayer播放音频)

  • 相关阅读:
    MySQL中的事务
    MySQL中的锁
    MySQL查询更新所有满足条件的数据
    MySQL存储引擎
    MySQL架构
    MySQL中存储json格式数据
    Java反射破坏单例模式
    合唱队(华为OJ)
    Java实现生产者消费者问题
    Spring IOC + AOP 的实现
  • 原文地址:https://www.cnblogs.com/stnlcd/p/7151438.html
Copyright © 2011-2022 走看看