音频处理分享

长音频播放声音分为MediaPlayer和AudioTrack两种方案的。MediaPlayer可以播放多种格式的声音文件,例如MP3,WAV,OGG,AAC,MIDI等。然而AudioTrack只能播放PCM数据流。当然两者之间还是有紧密的联系,MediaPlayer在播放音频时,在framework层还是会创建AudioTrack,把解码后的PCM数流传递给AudioTrack,最后由AudioFlinger进行混音,传递音频给硬件播放出来。利用AudioTrack播放只是跳过Mediaplayer的解码部分而已。

短音效播放声音目前使用SoundPool方案,SoundPool 是 Android 提供的一个API类,用来播放简短的音频,使用简单但功能相对强大。只需花很少的气力,就可以完成音频的播放、暂停、恢复及停止等操作。从名字上也可以看出,它是一个“pool”,我们可以加载多个音频资源到内存,进行管理与播放,比如控制同时播放流的最大数目。加载资源到内存是需要花费少许时间的,因此我们需要监听加载资源完毕的事件,在加载完毕后才能进行播放,以免发生不可预期的错误。

以上均是GPU处理的硬编解码方案。

1、MediaPlayer

使用注意点:

1、使用MediaPlayer的setDataSource设置raw资源需要转化成Uri:

Uri setDataSourceuri = Uri.parse("android.resource://com.klzz.vipthink.pad/" + resId);

2、prepare()的调用可能需要很长时间执行,因为它可能涉及到获取和解码媒体数据。因此,就像任何需要很长时间才能执行的方法一样,永远不要从应用程序的UI线程调用它。这样做会导致UI挂起,直到方法返回,这是一种非常糟糕的用户体验,并可能导致ANR(应用程序没有响应)错误。

准备数据并且响应UI的时间阈值是100ms。所以prepareAsync()可以解决以上问题。

3、可以通过调用start()、pause()和seekTo()等方法在start、pause()和PlaybackCompleted状态之间切换。但是,调用stop()时,资源已经释放,此时不适合调用start(),需要重新加载数据。

2、AudioTrack

作用:AudioTrack是管理和播放单一音频资源的类。AudioTrack仅仅能播放已经解码的PCM流,用于PCM音频流的回放。

AudioTrack实现PCM音频播放五步走

1、配置基本参数

  • StreamType音频流类型,系统将几种声音的数据分开管理,STREAM参数对AudioTrack来说,它的含义就是告诉系统,我现在想使用的是音乐播放还是系统播放还是电话铃声等等,方便系统对应管理。

  • MODE模式(static和stream两种)。stream一边加载编解码一边播放,优点可处理大音频,缺点是效率低;static是一次性加载,缺点是不适用大音频。

  • 采样率 (MediaRecoder 的采样率通常是8000Hz AAC的通常是44100Hz。 设置采样率为44100,目前为常用的采样率,官方文档表示这个值可以兼容所有的设置)

  • 通道数目:最大为双声道。

  • 频量化位数:mAudioFormat(只支持8bit和16bit两种。)

2、获取最小缓冲区大小

3、创建AudioTrack对象

4、获取PCM数据,转成DataInputStream

  • 第一种加载PCM的路径获取到PCM文件
  • 第二种通过ffmpeg软编码转码其他类型的文件变为PCM数据
  • 第三种通过MediaCodec硬编码转化PCM数据

5、开启/停止播放

3、SoundPool

作用:播放一些短时间且可以重复重叠的音效,是一个多轨道播放的音效音频工具类。

注意事项:
1、pause()、resume()和stop()是针对播放流操作的,传递的是play()返回的streamID ;
2、play()中的priority参数,只在同时播放的流的数量超过了预先设定的最大数量是起作用,管理器将自动终止优先级低的播放流。如果存在多个同样优先级的流,再进一步根据其创建事件来处理,新创建的流的年龄是最小的,将被终止;
3、同时播放多个音频,通过play()函数,成功则返回非0的streamID;
4、当设置为无限循环时,需要手动调用stop()来终止播放;
5、播放流的优先级(play()中的priority参数),只在同时播放数超过设定的最大数时起作用;
6、程序中不用考虑(play触发的)播放流的生命周期,无效的soundID/streamID不会导致程序错误。
无论如何,程序退出时,手动终止播放并释放资源是必要的。

7、soundID是使用在play方法上的并返回streamID,streamID是使用在stop方法上的,用于指定暂停指定音效。

开发中曾遇到过播放长语音(文件大小1M以上)不全,播放语音解码损坏的问题。

你可能感兴趣的:(音频处理分享)