导航:首页 > 操作系统 > androidaudio的播放

androidaudio的播放

发布时间:2023-09-10 16:03:55

A. android音视频【十二】使用OpenSLES和AudioTrack进行播放PCM

本节我们学习下如何播放pcm数据,在Android中有两种方法:一种是使用java层的 AudioTrack 方法,一种是使用底层的 OpenSLES 直接在 jni 层调用系统的 OpenSLES的c方法 实现。

两种使用场景不一样:
AudioTrack 一般用于 比如本地播放一个pcm文件/流,又或者播放解码后的音频的pcm流,API较简单。
OpenSLES 一般用于一些播放器中开发中,比如音频/视频播放器,声音/音频的播放采用的OpenSLES,一是播放器一般是c/c++实现,便于直接在c层调用OpenSLES的API,二也是如果用AudioTrack进行播放,务必会带来java和jni层的反射调用的开销,API较复杂。

可以根据业务自行决定来进行选择。

AudioTrack的方式使用较简单,直接在java层。

指定采样率,采样位数,声道数进行创建。

其中44100是采样率, AudioFormat.CHANNEL_OUT_STEREO 为双声道,还有 CHANNEL_OUT_MONO 单声道。 AudioFormat.ENCODING_PCM_16BIT 为采样位数16位,还有 ENCODING_PCM_8BIT 8位。 minBufferSize 是播放器缓冲的大小,也是根据采样率和采样位数,声道数 进行获取,只有满足最小的buffer才去操作底层进程播放。

最后一个参数mode。可以指定的值有 AudioTrack.MODE_STREAM 和 AudioTrack.MODE_STATIC 。

MODE_STREAM 适用于大多数的场景,比如动态的处理audio buffer,或者播放很长的音频文件,它是将audio buffers从java层传递到native层。音频播放时音频数据从Java流式传输到native层的创建模式。

MODE_STATIC 适用场景,比如播放很短的音频,它是一次性将全部的音频资源从java传递到native层。音频数据在音频开始播放前仅从Java传输到native层的创建模式。

是的,就这么一个方法。注意此方法是同步方法,是个耗时方法,一般是开启一个线程循环调用 write 方法进行写入。
注意在调用 write 方法前需要调用 audioTrack.play() 方法开始播放。

因为是pcm裸数据,无法像mediaplayer一样提供了API。所以需要自己处理下。可以利用 getPlaybackHeadPosition 方法。

getPlaybackHeadPosition() 的意思是返回以帧为单位表示的播放头位置
getPlaybackRate() 的意思是返回以Hz为单位返回当前播放采样率。

所以当前播放时间可以通过如下方式获取

OpenSLES:(Open Sound Library for Embedded Systems).
OpenSLES是跨平台是针对嵌入式系统精心优化的硬件音频加速API。使用OpenSLES进行音频播放的好处是可以不依赖第三方。比如一些音频或者视频播放器中都是用OpenSLES进行播放解码后的pcm的,这样免去了和java层的交互。

在Android中使用OpenSLES首先需要把Android 系统提供的so链接到外面自己的so。在CMakeLists.txt脚本中添加链接库OpenSLES。库的名字可以在 类似如下目录中

需要去掉lib

然后导入头文件即可使用了OpenSLES提供的底层方法了。

创建&使用的步骤大致分为:

一个 SLObjectItf 里面可能包含了多个Interface,获取Interface通过 GetInterface 方法,而 GetInterface 方法的地2个参数 SLInterfaceID 参数来指定到的需要获取Object里面的那个Interface。比如通过指定 SL_IID_ENGINE 的类型来获取 SLEngineItf 。我们可以通过 SLEngineItf 去创建各种Object,例如播放器、录音器、混音器的Object,然后在用这些Object去获取各种Interface去实现各种功能。

如上所说,SLEngineItf可以创建混音器的Object。

在创建播放器前需要创建音频的配置信息(比如采样率,声道数,每个采样的位数等)

开始播放后会不断的回调这个 pcmBufferCallBack 函数将音频数据压入队列
(*pcmBufferQueue)->RegisterCallback(pcmBufferQueue, pcmBufferCallBack, this);

如果想要暂停播放参数直接设置为SL_PLAYSTATE_PAUSED,若暂停后继续播放设置参数为SL_PLAYSTATE_PLAYING即可。若想要停止播放参数设置为SL_PLAYSTATE_STOPPED即可。

首先获取播放器的用于控制音量的接口SLVolumeItf pcmVolumePlay

然后动态设置

首先也是获取播放器的用于控制音量的接口SLMuteSoloItf pcmMutePlay

然后动态设置

看起来控制还是蛮简单的哈。先熟悉这么多,OpenSLES还是蛮强大的。

https://github.com/ta893115871/PCMPlay

B. Android播放简短音频-SoulPool

前言

最近新接触的项目中有一个业务功能是语音播报,所以有接触到了SoulPool这个类,写个文章记录一下~

如果项目业务功能中需要播放简短的音频的话,可以使用SoundPool 。SoundPool 是 Android 提供的一个API类,用来播放简短音频的,使用起来简单并且功能强大。

SoundPool 除了可以完成音频的播放、暂停、恢复及停止的操作外,还可以调节左右声道的音量值、调整播放的语速、设置播放的优先级以及播放的次数等等。

创建SoulPool

SoundPool 的创建方式在Android 5.0 以前是直接使用SoundPool 的构建方法即可,在Android5.0之后,则是使用Builder模式来创建。为了更好的兼容性,我们可以判断一下api版本进行对应的创建。

Android5.0之前SoundPool 的构造函数有三个参数分别是maxStreams、streamType和srcQuality。

maxStreams:同时播放流的最大数量,当播放的流大于此设置值时,则会选择性停止优先级较低的流;

streamType:流类型,例如STREAM_MUSIC、STREAM_ALARM、STREAM_NOTIFICATION等;

srcQuality:采样率转换器质量,很少用得上,默认设置0即可;

Android5.0 之后,使用Builder模式进行构造,可以设置多个参数。我这里放两张源码截图,如果需要详细了解的,可以自己点进去追踪一下~

SoundPool.Builder中setMaxStreams和之前Android5.0SoundPool的构造函数maxStreams参数相同。SoundPool.Builder中setAudioAttributes用来设置audio 属性,此值要么不设,要么设置不为null的值,否则会导致异常产生。

音频资源的加载与播放

首先我们要进行音频资源的加载,加载成功之后,才能进行播放。加载音频,我们可以使用SoulPool实例中的load方法。

加载音频资源时异步执行的,此过程需要时间,所以我们可以使用SoulPool中的OnLoadCompleteListener接口进行监听,其中的onLoadComplete方法则是在音频资源加载完成后调用。

我们还可以通过SoulPool中的unload方法,卸载之前加载过的资源。

其实,只要我们点进去SoulPool类中,就能看见它提供的所有方法了,如上图。

音频播放,我们是使用到了SoulPool实例中的play方法,该方法要传比较多的参数,分别是soundID、leftVolume、rightVolume、priority、loop和rate,它们分别代表的意思是:

soundID:是SoulPool加载资源load方法返回的值,指向某个已加载的音频资源;

leftVolume和rightVolume:分别代表左声道和右声道的值,设置范围在0f ~ 1f;

priority:则是流的优先级;

loop:是循环播放的次数, 例如-1是表示无限循环;

rate:则是播放的速率 ,1是正常速率,如果设置2则表示2倍速率;

play方法返回的streamID,若返回0则播放失败,其它值都代表播放成功。

图中方法还有pause、resume、stop分别代表暂停音播放、恢复音频播放和停止音频播放。SoulPool提供的方法,源码中都有,这里就不一一细说了。记得!一定要释放资源(release)

注意事项

1.SoulPool并不是什么格式的音频资源都支持的,MP3这些常见的格式当然是支持的,如果有别的格式的音频可以自己测试一下;

2.SoulPool是Android为了播放简短音频提供的api,所以尽量不要播放时间过长的音频;

3.设置播放流的优先级的问题,如果同时播放的活动流的数目超过设置的maxStreams时,会根据优先级来停止优先级较低的流;如果有多个具有相同低优先级的流,它将选择要停止的最旧流,并且该流不再有效;如果要播放的流的优先级最低,则会播放失败。

4.加载音频资源的数量限制也注意一下,别加载过多。

                                2021年9月15日程序猿小钟带着【播放简短音频类-SoulPool】到此一游~

C. android 5.0怎么设置音乐从听筒播放

5.0 之前 可以用AudioManager.setMode来设置phone state 来达到切换听筒的目的,但是5.0之后非系统应用没有这个权限了。发现微信依然可以切换,研究了下底层设备切换发现是如下操作的:
1.播放音频流类型要设置为AudioManager.STREAM_VOICE_CALL
2.在播放前调用AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION,AudioSystem.FORCE_NONE);
这个调用需要 在AndroidManifest.xml中添加 android.permission.MODIFY_AUDIO_SETTINGS 权限
并且AudioSystem这个类是隐藏类,在Android 公开API中没有,所以需要用反射调用,或者自己编译出一个framework.jar包,放到工程里,不过这样有可能兼容性不是很好。

阅读全文

与androidaudio的播放相关的资料

热点内容
压缩气管阀门 浏览:457
pdf推文 浏览:353
69程序员 浏览:577
阿里云服务器镜像如何迁移到腾讯 浏览:979
安卓如何显示日期在状态栏 浏览:803
cadsplt这个命令用不了 浏览:463
安卓夸克怎么取消监管 浏览:662
pdf怎么裁剪图片 浏览:436
黑上宏命令 浏览:644
mac解压压缩包有密码 浏览:704
命令与征服知乎 浏览:561
小时代pdf 浏览:221
化工设备第三版答案pdf 浏览:465
防火卷帘控制器单片机程序 浏览:16
rdlcpdf 浏览:109
链表实现快速排序python 浏览:590
php输出命令 浏览:987
d站app叫什么名字 浏览:172
oppor系列如何解除应用加密 浏览:602
程序员那么可爱姜逸城初恋 浏览:501