[摘]AudioTrack简单简介之一

Android  2019年3月7日 pm7:24发布6年前 (2019)更新 91es.com站长
76 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.91es.com/  91易搜,为你导航!

版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

余光中:绝色

美丽而善变的巫娘,那月亮翻译是她的特长却把世界译走了样 把太阳的鎔金译成了流银把烈火译成了冰而且带点薄荷的风味 凡尝过的人都说译文是全不可靠但比起原文来呢却更加神秘,更加美 雪是另一位唯美的译者存心把世界译错或者译对,诗人说只因原文本来就...

ThreadPoolExecutor简单记录

前言线程经常用,线程池也用,但在于如何使用,没有记录一下。本文参考别人文章整理。正文使用线程池的好处降低内存资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。在线程池中的线程都是已经被创建好的,我们的任务直接获取一个空闲的线程就能够被执行了提高线程的可管...

冯骥才:青云楼主

青云楼主,海河边一小文人的号。嘛叫小文人?就是在人们嘴边绝对挂不上号,可提起他来差不多还都知道的那类文人。此君脸窄身簿,皮黄肉干,胳膊大腿又细又长,远瞧赛几根竹竿子上凉着的一张豆皮。但人不可貌相,海不可斗量。他能写能画,能刻图章,连托裱的事也行;可行家们说他——手糙了点儿。因故,天津卫的买卖没他写...

Kotlin面对对象简介

前言简单介绍一下Kotlin面对对象简介。记录一下,方便自己查阅。正文类类就是具备某些共同特征的实体的集合,它是一种抽象的数据类型,它是对所具有相同特征实体的抽象。Kotlin中所有类都继承Any类,它是所有类的父类,如果一个类在声明时没有指定父类,则默认父类为Any类无参数和有参...

龙应台:幸福就是……

幸福就是,生活中不必时时恐惧。开店铺的人天亮时打开大门,不会想到是否有政府军或叛军或饥饿的难民来抢劫。走在街上的人不必把背包护在前胸,时时刻刻戒备。睡在屋里的人可以酣睡,不必担心自己一醒来发现屋子已经被拆,家具像破烂一样被丢在街上。到杂货店里买婴儿奶粉的妇人不必想奶粉会不会是假的,婴儿吃了会不会死。...

Android异常之应用已停止运行的日志分析

文章之前写过,重新整理一下。为什么会有应用已停止运行?运行时出现了未捕获的异常,导致程序无法正常运行。如下面,主线程(main)出现致命异常(fatal exception)导致程序无法正常运行。 # main主线程,fatal exception 致命异常 AndroidRuntime...