android核心技术与最佳实践笔记(三)

第七章  深入解析android网络编程
        第九章  android多媒体编程
9.1  音频处理
 
       上述为google为开发者提供的音频开发框架, 在应用层,开发者可以调用MediaPlayer,  MediaRecorder,  SoundPool 等进行音频的播放记录以及游戏的特效音制作等。 在框架层,AudioFlinger,  AudioPolicyManager,  AudioSerivce  AudioHardwareInterface构成了对音频控制的基本骨架。框架层本身包括java,C++两部分,并通过JNI 进行通信,其中对服务的调用是基于C/S框架实现的。内核层提供不同音频设备的驱动和ALSA框架等。音频本身的播放涉及的多媒体引擎是 Stagefright。
       AudioPolicyService 所负责的工作在早期版本中是在AudioFlinger中实现的。随着场景的复杂化,Google 将关于音频设备的连接状态,音频的并发策略,音量的处理等工作放置到   AudioPolicyService 中,而 AudioFlinger更侧重于音频流的控制  AudioHardwareInterface则是对不同设备产商的音频设备的驱动与框架层的适配接口,为框架层提供一个与驱动通信的统一接口
       下面对音频播放,音频录制,音频管理,音效处理等几个方面进行介绍:
 9.1.1  音频播放
     根据播放方式的不同,android为应用层提供了多个播放接口,如MediaPlayer,  SoundPool ,  AudioTrack ,  AsyncPlayer,  JetPlayer, ToneGenerator 等, 他们适用于不同的场景。
  1.  基于MediaPlayer 播放
      功能强大,对音频视频都支持,为保证播放期间系统正常工作,需要设置   android.permission.WAKE_LOCK权限
        MediaPlayer支持的音频格式包括 AAC, AMR,  FLAC  MP3  MIDI,  OGG,  PCM等。
      在原生层 MediaPlayer 由状态机控制,其状态机如下图:
            
          注意: 当调用reset()方法时,MediaPlayer会返回到MEDIA_PLAYER_IDLE状态,除了图中所示的状态外,MediaPlayer还存在一个出错的状态,即 Media_Player_STATE_ERROR。监听出错的监听器为 MediaPlayer.OnErrorListener。
        对于背景音乐,将MediaPlayer封装在Service中即可实现。
        MediaPlayer支持元数据,音频文件,音频流等形式的源数据的播放。
  (1)播放元数据
        所谓 元数据即 raw 文件夹下的资源文件,调用方法如下: 
               mMediaPlayer = MediaPlayer.create( this,  R.raw.test.cbr );
               mMediaPlayer.start();
  (2)播放音频文件
       对于本地文件,其数据源可通过 Uri 来表示,在开始播放前需要设置播放类型并加载缓冲,实例如下:
               Uri  myUri = ... ;
               MediaPlayer  mediaPlayer = new  MediaPlayer();
               mediaPlayer.setAudioStreamType( AudioManager.STREAM_MUSIC );
               mediaPlayer.setDataSource( getApplicationContext(),  myUri );
               mediaPlayer.prepare(); //加载缓冲
               mediaPlayer.start();
  (3)播放流
       MediaPlayer 支持基于网络的流播放,其支持的协议包括 RSTP,  HTTP渐进流,  HTTP生活流等。在网络播放和本地文件播放略有不同,实例如下:
              String  url =  "http://zhangmenshiting.baidu.com/****.mp3";
              MediaPlayer  mediaPlayer = new MediaPlayer();
              mediaPlayer.setAudioStreamType( AudioManager.STREAM_MUSIC );
              mediaPlayer.setDataSource( url );
              mediaPlayer.prepareAsync();
              ..................     mediaPlayer.start();
         考虑到网络情况的发杂性,以及获取数据和解码的时间比较长,不推荐在播放流时通过  prepare() 方法加载缓冲,尤其不能再UI主线程中调用。应通过 prepareAsync() 方法将缓冲的工作放置在非UI主线程中进行,当准备完成时,MediaPlayer通过 MediaPlayer.OnPreparedListener 监听器可以监听到该时间。设置方法如下:
             mMediaPlayer.setOnpreparedListener( mPreparedListener );
        通常在准备工作完成后开始进行播放。监听器处理加载缓冲结束的消息的方法:
             MediaPlayer.OnPreparedListener  mPreparedListener = new MediaPlayer.onPreparedListener(){
                     public  void  onPrepared( MediaPlayer mp ){
                              mediaPlayer.start();
                     }
             }
       当播放结束时,通过MediaPlayer.OnCompletionListener 可以监听到播放结束的消息,实例如下:
             mMediaPlayer.setOnCompletionListenr( new  MediaPlayer.OnCompletionListener(){
                      public  void  onCompletion( MediaPlayer  mediaPlayer ){
                      }
             } );
 2.  基于SoundPool 播放
        SoundPool 能够播放音频流的组合音,这对游戏应用很有用,其对应的JNI接口为 android_media_SoundPool.cpp
         SoundPool 可通过APK包中的资源文件或文件系统中的文件将音频资源加载到内存中。在底层实现上,SoundPool 通过媒体播放服务(MediaPlaybackService)可以将音频资源解码为一个 16位的单声道或立体声的 PCM流,使应用避免了再回放过程中进行解码造成的延迟。
       除了回放过程中延迟小的优点外,SoundPool 还能够对一定数量的音频流进行同时播放。当要播放的音频流数量超过 SoundPool 所设置的最大值时,SoundPool 将会停止已播放的一条低优先级的音频流。SoundPool 对最大音频流数量的设置(默认为32),可避免CPU过载。
       对游戏等应用而言,MediaPlayer会使性能减低。在android中,专门提供了SoundPool 类来执行此类音频播放,SoundPool 类占用的CPU资源较少,反应较快。
       与其他音频播放类相比,SoundPool 类可自行设置音频播放时的品质,音量,播放速率等,并可管理多个音频流,每个流均拥有自己独立的ID,对单个音频流的管理均是通过其ID 来进行的。 SoundPool 类使用的场景包括应用程序中的音效。
       SoundPool 组合音频流的实例如下:
              int  srcQulity = 100;
              mSoundPool = new SoundPool( SOUNDPOOL_STREAMS,  AudioManager.STREAM_MUSIC, srcQuality );//创建SoundPool对象
              //架子音频流
              int  sampleId1 = mSoundPool.load( mContext,  R.raw.a_4,  PRIORITY );
              AssetFileDescriptor  afd = mContext.getResources().openRawResourceFd( R.raw.c_sharp_5 ) ;
              int  smapleId2 = mSoundPool.load( afd,  PRIORITY );
              FileDescriptor  fd = afd.getFileDescriptor();
              long  offset = afd.getStartOffset();
              long  length = afd.getLength();
              int  sampleId3;
              sampleId3 = mSoundPool.load( fd,  offset,  length,  PRIORITY );
              String  path = mFile.getAbsolutePath();
              int  sampleId4;
              sampleId4 = mSoundPool.load( path,  PRIORITY );
              mSoundPool.unload( sampleId4 );
     通过 SoundPool 播放某音频流的方法如下:
              float  leftVolume = SILENT;
              float  rightVolume = LOUD;
              int  priority = 1;
              int  loop = 0 ;
              int  rate = 1f;
              int  streamID = mSoundPool.play( sampleID,  leftVolume,  rightVolume, priority, loop, rate );
3. 基于AudioTrack播放
        AudioTrack主要用于管理单个音频,这是一个较底层的音频播放方法。在构建AudioTrack时,需要明确流类型,采样率,通道配置,音频格式,缓冲大小,播放模式等参数。
        AudioTrack 支持 STREAM_VOICE_CALL,  STREAM_SYSTEM,  STREAM_RING,  STREAM_MUSIC 和 STREAM_ALARM等流类型。
        AudioTrack支持 44100Hz  , 22050Hz,  11025Hz等采样率。
        AudioTrack支持单声道(CHANNEL_OUT_MONO)和立体声(CHANNEL_OUT_STEREO)两种声道。
        AudioTrack支持 ENCODING_PCM_16BIT 和 ENCODING_PCM_8BIT 两种编码格式。
        AudioTrack支持静态模式(Static  Mode)和流模式(Streaming Mode)两种播放模式。静态模式由于没有从java层向原生层传递数据造成的延迟,因此时延很小。当然,受限于音频缓冲的大小,静态模式常在游戏场景中用于播放时长很短的音频资源。当音频流较大不足以在音频缓冲证一些写入时,可采用流模式。AudioTrack的应用实例如下:
              track = new 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值