音视频开发进阶指南(第四章)-AudioTrack播放PCM

简介: 笔记

使用AudioTrack播放PCM


为什么只播放PCM不播放Mp3呢?因为AudioTrack是基础API,没有解码功能,而MediaPlayer是有解码功能的。所以要播放Mp3,还需要自行添加解码功能,把Mp3解码为PCM再播放。

只要做好两件事情:

  1. AudioTrack的初始化参数的含义
  2. AudioTrack的播放流程:play->write->stop


1. 初始化AudioTrack

//获取最小缓冲区大小
 int minBufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE,    //采样率
         AudioFormat.CHANNEL_OUT_STEREO, //双声道
         AudioFormat.ENCODING_PCM_16BIT  //采样格式
 );
 //初始化AudioTrack对象
 AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,   //媒体类型
         SAMPLE_RATE,  //采样率
         AudioFormat.CHANNEL_IN_STEREO, //双声道
         AudioFormat.ENCODING_PCM_16BIT, //采样格式
         minBufferSize,  //缓冲区大小
         AudioTrack.MODE_STREAM  //流式加载
 );

参数详解:

  • 参数一:streamType
    Android手机上提供了多重音频管理策略(例如按一下手机侧面音量键,会出现多个音量管理,这其实就是不同音频策略的音频控制展示),当系统有多个进程需要播放音频的时候,管理策略会决定最终的呈现效果,该参数的可选值将以常量的形式定义在类AudioManager中,主要包括以下内容:

public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_
public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
public static final int STREAM_RING = AudioSystem.STREAM_RING;
public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;
  • 参数二:sampleRateInHz
    采样率,即播放的音频每秒钟会有多少次采样,可选用的采样频率列表为:8000、16000、22050、24000、32000、44100、48000等,要根据播放的PCM的采样率来决定初始化AudioTrack时的具体值,否则可能导致声音变快或者变慢
  • 参数三:channelConfig
    声道数(通道数)配置,可选值以常量形式配置在类AudioFormat中,常用的是CHANNEL_IN_MONO(输入单声道),CHANNEL_IN_STEREO(输入双声道)。(因为现在大多数手机的麦克风都是伪立体声采集,为了性能考虑,建议使用单声道进行音频采集,而转变为立体声的过程可以在声音的特效处理阶段来完成)。
  • 参数四:audioFormat
    该参数是用来配置数据位宽,表示了采样精度,可选值以常量的形式定义在类AudioFormat中,分别为ENCODING_PCM_16BIT和ENCODING_PCM_8BIT,注意,前者是可以兼容安卓所有手机的。
  • 参数五:bufferSizeInBytes
    它配置的是AudioTrack内部缓冲区的大小,AudioTrack类提供了一个静态方法getMinBufferSize来帮忙开发者确定缓冲区的大小,在实际开发中,强烈建议使用该方法,而不是自己手动计算。
  • 参数六:mode
    AudioTrack提供了两种播放模式,可选的值以常量的形式定义在类AudioTrack中,分别为:
  1. MODE_STREAM 按照一定的时间间隔不间断地定入音频数据,理论上它可以应用于任何音频播放的场景
  2. MODE_STATIC 需要一次性将所有的数据都写入播放缓冲区中,简单高效,通常用于播放铃声、系统提醒的音频片段。


2. 启动播放

//先启动播放
audioTrack.play();

3. write音频数据

//分配缓冲区
byte[] buffer = new byte[minBufferSize * 3];
is = getAssets().open(pcmFilePath);
dis = new DataInputStream(is);
int readCount = 0;
while (dis.available() > 0) {
    //读取PCM
    readCount = dis.read(buffer);
    Log.d(MainActivity.class.getSimpleName(), "readCount=" + readCount);
    if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {
        continue;
    }
    if (readCount != 0 && readCount != -1) {
        //写入AudioTrack
        audioTrack.write(buffer, 0, readCount);
    }
}
...
audioTrack.stop();


目录
相关文章
|
数据可视化 IDE 编译器
Open CASCADE之v7.4.0源码编译与可视化调试,使用VS2017+32位编译器(1)
Open CASCADE之v7.4.0源码编译与可视化调试,使用VS2017+32位编译器
1947 0
Open CASCADE之v7.4.0源码编译与可视化调试,使用VS2017+32位编译器(1)
|
数据格式
51单片机--红外遥控
51单片机--红外遥控
1068 10
|
8月前
|
XML 前端开发 C#
C#编程实践:解析HTML文档并执行元素匹配
通过上述步骤,可以在C#中有效地解析HTML文档并执行元素匹配。HtmlAgilityPack提供了一个强大而灵活的工具集,可以处理各种HTML解析任务。
356 19
|
开发工具 git
|
编解码 调度 Android开发
Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置
Android音频框架之一 详解audioPolicy流程及HAL驱动加载与配置
2243 0
|
XML 存储 测试技术
Android系统 添加动态控制SystemUI状态栏、导航栏和下拉菜单
Android系统 添加动态控制SystemUI状态栏、导航栏和下拉菜单
3786 2
SeLinux 权限配置技巧
SeLinux 权限配置技巧
562 2
锁屏组件新能力实现问题之在Activity中锁屏状态下显示悬浮窗的实现如何解决
锁屏组件新能力实现问题之在Activity中锁屏状态下显示悬浮窗的实现如何解决
447 0
|
存储 IDE KVM
不想用了PVE了怎么办?那就迁移到VMware呗!
不想用了PVE了怎么办?那就迁移到VMware呗!
|
XML Shell Android开发
android12.0(S) DeviceOwner 应用默认授权(MDM 权限)
android12.0(S) DeviceOwner 应用默认授权(MDM 权限)
2179 0