[摘]AudioTrack简单简介之一

Android  2019年3月7日 pm7:24发布6年前 (2019)更新 城堡大人
110 0 0

1.1、什么是PCM

脉冲编码调制(Pulse Code Modulation,PCM),它的作用是把一个时间连续,取值连续的模拟信号变换成时间离散,取值离散的数字信号后在信道中传输。脉冲编码调制就是对模拟信号先抽样,再对样值幅度量化,编码的过程。

pcm是一个通信上的概念,脉冲编码调制,是编码。wav是媒体概念,体现的是封装。wav文件可以封装pcm编码信息,也可以封装其他编码格式,例如mp3等

从手机麦克风采集的数据就是pcm原始数据。

1.2、AudioTrck

首先它可以直接播放pcm音频数据,但是不能播放其它的格式如MP3,AAC,WAV等,不过更加上层的API如MediaPlay却可以播放这些格式,但是同时MediaPlay也失去了对底层数据流的一些操作,如AudioTrack可以控制每一帧数据,可以自己转化任意格式,自由性比较强大,而MediaPlay却不行。

AudioTrack播放有两种模式:

MODE_STREAM:

在这种模式下,需要先play,然后通过write一次次把音频数据写到AudioTrack中(我在试验中可以先write再play,可能是数据太小了的原因)。每次都需要把数据从用户提供的Buffer中拷贝到AudioTrack内部的Buffer中,这在一定程度上会使引入延时。

适用于大多数的场景,将audio buffers从java层传递到native层即返回。

如果audio buffers占用内存多,应该使用MODE_STREAM。

比如播放时间很长的声音文件,

比如音频文件使用高采样率,

比如动态的处理audio buffer等

MODE_STATIC:

这种模式下,需要先write,再play.。先把所有数据通过一次write调用传递到AudioTrack中的内部缓冲区,后续就不必再传递数据了。但它也有一个缺点,就是一次write的数据不能太多,否则系统无法分配足够的内存来存储全部数据。

一次性将全部的音频资源从java传递到native层,这种方式延迟低,但也有局限性。

音频文件短且占用内存小。

适用于短促的游戏音效,并且对播放延迟真的有很高要求。

PS:以上两种模式比对摘抄如下文章

1.3、介绍

在看播放之前,先来了解一下AudioTrack是如何构造出来的。

在AudioTrack构造函数中,会接触到AudioManager.STREAM_MUSIC这个参数。

Android将系统的声音streamType分为好几种流类型,下面是几个常见的:

  1. STREAM_ALARM:警告声
  2. STREAM_MUSIC:音乐声,例如music等
  3. STREAM_RING:铃声
  4. STREAM_SYSTEM:系统声音,例如低电提示音,锁屏音等
  5. STREAM_VOCIE_CALL:通话声

注意:上面这些类型的划分和音频数据本身并没有关系。例如MUSIC和RING类型都可以是某首MP3歌曲。另外,声音流类型的选择没有固定的标准,例如,铃声预览中的铃声可以设置为MUSIC类型。音频流类型的划分和Audio系统对音频的管理策略有关。(也就是播放时调用的哪种流格式而已,Android对不同流格式处理的有些不同而已

构造有多种:

下面两种对于低版本api可以用:

1.  AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes, int mode)

2.  AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,int bufferSizeInBytes, int mode, int sessionId)

streamType(音频流类型AudioManager.STREAM_XXX),sampleRateInHz(采样率,不同音频的采样率不一样,比如可以16000,也可以说44100),channelConfig(通道数目,目前最多只支持双声道),audioFormat(音频量化位数,只支持8bit和16bit,也就是AudioFormat.ENCODING_PCM_8BIT和AudioFormat.ENCODING_PCM_16BIT),bufferSizeInBytes(取决于采样率、声道数和采样深度三个属性),mode(仅支持MODE_STREAM和MODE_STATIC,上面有介绍)

sessionId:音频会话的ID AudioTrack必须附加。AudioManager.AUDIO_SESSION_ID_GENERATE if the session isn't known at construction time。就是说在创建的时候不知道会话可以传入这个值AudioManager.AUDIO_SESSION_ID_GENERATE 。

文档中也给出了提示:https://developer.android.google.cn/reference/android/media/AudioTrack.html#AudioTrack(int,%20int,%20int,%20int,%20int,%20int)

This constructor was deprecated in API level 26.use AudioTrack.Builder or AudioTrack(AudioAttributes, AudioFormat, int, int, int) to specify the AudioAttributes instead of the stream type which is only for volume control.

另外一种:

3. AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,int mode, int sessionId)

后面三个int参数就不用介绍了,上面有,介绍前两个参数(not null)。

format实例描述将通过此AudioTrack播放的数据的格式。见AudioFormat.Builder用于配置音频格式参数,如编码数据格式、通道和采样率,就是将之前的api的三个参数(数据格式,通道,采样率)合为一体,很容易理解。

attributes则是对之前的api的streamType的 一个改进,具体请查阅AudioAttributes 。

 

本文摘抄《Android-音视频(3):用AudioTrack播放音频PCM》、《音频播放AudioTrack之入门篇》和《AudioTrack中MODE_STATIC和MODE_STREAM的差异》自己整理得出。不懂的可访问相关链接。

后面还有一篇关于如何使用,谢谢。

 

https://www.biumall.com/  笔友城堡,为你导航!

版权声明 1、 本站名称: 笔友城堡
2、 本站网址: https://www.biumall.com/
3、 本站部分文章来源于网络,仅供学习与参考,如有侵权,请留言

暂无评论

暂无评论...

随机推荐

JNI静态注册

前言之前其实写过,代码不见了,为了走一下流程,重新简单的写了一个。PS:设计NDK环境配置这里不介绍哈正文静态注册先由Java得到本地方法的声明,然后再通过JNI实现该声明方法。优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低缺点: 当需...

JNI动态注册封装C语言版

前言在上一篇《JNI调用Java方法》的动态注册并调用Java方法,上次也说了可以把公共部分封装一下。说干就干,今天就把上次代码封装一下。正文我这不介绍完整的动态注册,有需要可以看《JNI动态注册》。这里只是个人流水账。Hello.javapackage com.biumall.dyn...

[摘]对于Fragment的一些理解

Fragment为何要用Fragment是Android 3.0 (Honeycomb)被引入的。主要目的是为了给大屏幕(如平板电脑)上更加动态和灵活的UI设计提供支持。由于平板电脑的屏幕比手机的屏幕大很多,因此可用于组合和交换的UI组件的空间更大,利用Fragment实现此类设计的时,就无需管...

朱自清:背影

那年冬天,祖母死了,父亲的差使也交卸了,正是祸不单行的日子。我从北京到徐州打算跟着父亲奔丧回家。到徐州见着父亲,看见满院狼藉的东西,又想起祖母,不禁簌簌地流下眼泪。父亲说:“事已如此,不必难过,好在天无绝人之路!”回家变卖典质,父亲还了亏空;又借钱办了丧事。这些日子,家中光景很是惨淡,一半为了丧事...

gcc编译器相关介绍

前言简单记录gcc编译器相关内容正文gcc (GNU Compiler)是GNC推出的多平台编译器,可以将C语言、C++源程序编译成可以执行的文件。gcc支持后缀.c C语言源代码.h 程序所包含的头文件.i 已经预处理过的C源代码文件.s 汇编语言源代码文件.o 编译后的目标...

Android取消和开启提示音

前言如果系统设置[声音]选项中关闭了[触摸提示音],则所有的View都没有提示音。开启系统设置[触摸提示音]基础上,View或ViewGroup设置setOnTouchListener()或者setOnLongClickListener()都是没有提示音的。开启系统设置[触摸提示音]基础上...