资料

音频播放AudioTrack之入门篇

配置基本参数

StreamType 音频流类型

最主要的几种STREAM
AudioManager.STREAM_MUSIC:用于音乐播放的音频流。
AudioManager.STREAM_SYSTEM:用于系统声音的音频流。
AudioManager.STREAM_RING:用于电话铃声的音频流。
AudioManager.STREAM_VOICE_CALL:用于电话通话的音频流。
AudioManager.STREAM_ALARM:用于警报的音频流。
AudioManager.STREAM_NOTIFICATION:用于通知的音频流。
AudioManager.STREAM_BLUETOOTH_SCO:用于连接到蓝牙电话时的手机音频流。
AudioManager.STREAM_SYSTEM_ENFORCED:在某些国家实施的系统声音的音频流。
AudioManager.STREAM_DTMF:DTMF音调的音频流。
AudioManager.STREAM_TTS:文本到语音转换(TTS)的音频流。
为什么分那么多种类型,其实原因很简单,比如你在听music的时候接到电话,这个时候music播放肯定会停止,此时你只能听到电话,如果你调节音量的话,这个调节肯定只对电话起作用。当电话打完了,再回到music,你肯定不用再调节音量了。

其实系统将这几种声音的数据分开管理,STREAM参数对AudioTrack来说,它的含义就是告诉系统,我现在想使用的是哪种类型的声音,这样系统就可以对应管理他们了。

MODE模式(static和stream两种)

AudioTrack.MODE_STREAM

STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到AudioTrack中。这个和我们在socket中发送数据一样,应用层从某个地方获取数据,例如通过编解码得到PCM数据,然后write到AudioTrack。这种方式的坏处就是总是在JAVA层和Native层交互,效率损失较大。

AudioTrack.MODE_STATIC

STATIC就是数据一次性交付给接收方。好处是简单高效,只需要进行一次操作就完成了数据的传递;缺点当然也很明显,对于数据量较大的音频回放,显然它是无法胜任的,因而通常只用于播放铃声、系统提醒等对内存小的操作

采样率:mSampleRateInHz

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

通道数目:mChannelConfig

首先得出声道数,目前最多只支持双声道。为什么最多只支持双声道?看下面的源码

  static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {int channelCount = 0;switch(channelConfig) {case AudioFormat.CHANNEL_OUT_MONO:case AudioFormat.CHANNEL_CONFIGURATION_MONO:channelCount = 1;break;case AudioFormat.CHANNEL_OUT_STEREO:case AudioFormat.CHANNEL_CONFIGURATION_STEREO:channelCount = 2;break;default:if (!isMultichannelConfigSupported(channelConfig)) {loge("getMinBufferSize(): Invalid channel configuration.");return ERROR_BAD_VALUE;} else {channelCount = AudioFormat.channelCountFromOutChannelMask(channelConfig);}}.......}

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

  if ((audioFormat !=AudioFormat.ENCODING_PCM_16BIT)  && (audioFormat !=AudioFormat.ENCODING_PCM_8BIT)) {return AudioTrack.ERROR_BAD_VALUE;}

源码

public class AudioTrackManager {private AudioTrack mAudioTrack;private DataInputStream mDis; //播放文件的数据流private Thread mRecordThread;private boolean isStart = false;private volatile static AudioTrackManager mInstance;// 音频流类型private static final int mStreamType = AudioManager.STREAM_MUSIC;// 指定采样率 (MediaRecoder 的采样率通常是8000Hz AAC的通常是44100Hz。 设置采样率为44100,目前为常用的采样率,官方文档表示这个值可以兼容所有的设置)private static final int mSampleRateInHz = 44100;// 指定捕获音频的声道数目。在AudioFormat类中指定用于此的常量private static final int mChannelConfig = AudioFormat.CHANNEL_CONFIGURATION_MONO;//单声道// 指定音频量化位数 ,在AudioFormat类中指定了以下各种可能的常量。通常我们选择ENCODING_PCM_16BIT和ENCODING_PCM_8BIT PCM代表的是脉冲编码调制,它实际上是原始音频样本。// 因此可以设置每个样本的分辨率为16位或者8位,16位将占用更多的空间和处理能力,表示的音频也更加接近真实。private static final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;// 指定缓冲区大小。调用AudioRecord类的getMinBufferSize方法可以获得。private int mMinBufferSize;// STREAM的意思是由用户在应用程序通过write方式把数据一次一次得写到audiotrack中。这个和我们在socket中发送数据一样,// 应用层从某个地方获取数据,例如通过编解码得到PCM数据,然后write到audiotrack。private static final int mMode = AudioTrack.MODE_STREAM;public AudioTrackManager() {initData();}private void initData() {// 根据采样率,采样精度,单双声道得到frame的大小。mMinBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, mChannelConfig, mAudioFormat);// 注意,按照数字音频的知识,这个算出来得失一秒钟的大小.// 创建AudioTrackmAudioTrack = new AudioTrack(mStreamType, mSampleRateInHz, mChannelConfig, mAudioFormat, mMinBufferSize, mMode);}// 获取单例引用public static AudioTrackManager getInstance() {if (mInstance == null) {synchronized (AudioTrackManager.class) {if (mInstance == null) {mInstance = new AudioTrackManager();}}}return mInstance;}// 销毁线程方法private void destroyThread() {try {isStart = false;if (null != mRecordThread && Thread.State.RUNNABLE == mRecordThread.getState()) {try {Thread.sleep(500);mRecordThread.interrupt();} catch (Exception e) {mRecordThread = null;}}mRecordThread = null;} catch (Exception e) {e.printStackTrace();} finally {mRecordThread = null;}}// 启动播放线程private void startThread() {destroyThread();isStart = true;if (mRecordThread == null) {mRecordThread = new Thread(recordRunnable);mRecordThread.start();}}// 播放线程Runnable recordRunnable = new Runnable() {@Overridepublic void run() {try {// 设置线程的优先级android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO);byte[] tempBuffer = new byte[mMinBufferSize];int readCount = 0;while (mDis.available() > 0) {readCount = mDis.read(tempBuffer);if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {continue;}if (readCount != 0 && readCount != -1) {// 判断AudioTrack未初始化,停止播放的时候释放了,状态就为STATE_UNINITIALIZEDif (mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED) {initData();}mAudioTrack.play();mAudioTrack.write(tempBuffer, 0, readCount);}}stopPlay();} catch (Exception e) {e.printStackTrace();}}};// 播放文件private void setPath(String path) throws Exception {File file = new File(path);mDis = new DataInputStream(new FileInputStream(file));}// 设置音频流private void setInputStream(InputStream is) {mDis = new DataInputStream(is);}// 启动播放public void startPlay(InputStream is) {try {// AudioTrack未初始化// if(mAudioTrack.getState() == AudioTrack.STATE_UNINNITIALZED) {//     throw new RuntimeException("The AudioTrack is not uninitialized");// } // AudioRecord.getMiniBufferSize的参数是否支持当前的硬件设备// else if(AudioTrack.ERROR_BAD_VALUE == mMinBufferSize || AudioTrack.ERROR == mMinBufferSize) {//     throw new RuntimeException("AudioTrack unable to getMinBufferSize()");// } else {if (is != null) { // 输入音频输入流setInputStream(is);startThread();}// }} catch (Exception e) {e.printStackTrace();}}// 停止播放public void stopPlay() {try {destroyThread(); //销毁线程if (mAudioTrack != null) {if (mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {mAudioTrack.stop(); // 停止播放}mAudioTrack.release(); // 释放audioTrack资源}if (mDis != null) {mDis.close();}} catch (Exception e) {e.printStackTrace();}}// 暂停播放public void pause() {if (mAudioTrack != null && mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {mAudioTrack.pause();}}
}

音视频之AudioTrack的使用相关推荐

  1. 音视频学习 AudioTrack、OpenSL ES 音频渲染

    前言 在讲解音频渲染之前,需要对音频的基础知识有所了解,所以该篇分为基础概念和AudioTrack 以及 OpenSL ES Demo 实例讲解,这样有助于更好的理解 Android 中音频渲染. 音 ...

  2. audiotrack android,Android 音视频渲染-AudioTrack 播放

    类型 MediaPlayer:原生API中封装最全的 SoundPool:适合播放较短的音频 AudioTrack:底层的音频 API,需要自己解码,只能播放 PCM 裸数据和 WAV AudioTr ...

  3. audiotrack java_Android音视频之AudioTrack播放音频(二)

    前一篇讲了如何录制wav音频文件,本篇就来讲讲如何播放wav文件,这里就是使用AudioTrack来播放音频,确切的说是播放pcm格式数据,使用AudioTrack播放也没什么难度,主要就是将数据写入 ...

  4. 音视频技术开发周刊(第131期)

    每周一期,纵览音视频技术领域的干货和新闻投稿:contribute@livevideostack.com. 架构 Orbital Web App 宣布开源 区块链与视频. 使用 getUserMedi ...

  5. 音视频开发必备基本基础知识(1)

    最近收到了朋友邮寄过来的一本书,刚拿回来就趁机学习了一波音视频开发的知识.现就音视频开发的一些基本知识做一个总结.如下: 1.视频编码 通过特定的压缩技术,将视频格式文件转换成另一种视频格式文件的方法 ...

  6. Android 音视频深入 十一 FFmpeg和AudioTrack播放声音(附源码下载)

    项目地址,求star https://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE% ...

  7. Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  8. 安卓音视频基础:AudioRecord和AudioTrack的简单使用

    在之前的文章安卓实现录音/播放/暂停/继续的功能中介绍了通过MediaRecorder和MediaPlayer实现简单的录音和播放功能,但相比于安卓二次封装后的API,AudioRecord和Audi ...

  9. Android 音视频开发(一) -- 使用AudioRecord 录制PCM(录音);AudioTrack播放音频

    前言,音视频这块,确实比较难入门,本着学习的态度,我这边也跟着 Android 音视频开发入门指南 打怪升级,留下个脚印,大家共勉. 音视频 系列文章 Android 音视频开发(一) – 使用Aud ...

最新文章

  1. pl/sql中的赋值运算符_如何在SQL中使用AND / OR运算符?
  2. 一步怎么测量图片_测量不容易?15套测量仪器实操手册+自动计算表格,自学也可以...
  3. 戴尔R730 安装升级VMware vSphere Hypervisor (ESXi) 6.7
  4. 用vSphere Client去建立虚拟机报MKS的错
  5. Python自动化中的元素定位xpath(二)
  6. static RMQ
  7. 毕业设计-基于Springboot实现仓库管理系统
  8. 如何清理驱动人生的新闻弹窗
  9. js获取某年某月某天是第几周
  10. selenium爬取阿里巴巴国际站
  11. 35、T5L 迪文屏C51开发之音频播放
  12. 大学三年软件工程专业学习感受
  13. CentOS停更;阿里发布全新操作系统(Anolis OS),用后直呼:牛X
  14. Jaden Casing Strings
  15. 如何在高德地图windowInfo弹窗中使用VUE组件
  16. 怎样在苹果电脑上用移动硬盘(使用NTFS格式硬盘)?
  17. 第四次作业——肖祥英
  18. CompletableFuture的正常,异常,timeout和cancel
  19. P2471 [SCOI2007]降雨量(线段树)
  20. 一部全网最全的 JDK 发展历史轨迹图

热门文章

  1. CreateSpecificCulture('zh-cn')和new CultureInfo('zh-cn')的区别
  2. 机器人机械臂运动学——运动学正向解算
  3. WIN10系统安装Ubuntu子系统并在此基础上安装ncl
  4. SAP(Self-Attentive Speaker Embeddings for Text-Independent Speaker Verification)
  5. js将图片转base64两种方法
  6. 【论文阅读】Graphonomy: Universal Human Parsing via Graph Transfer Learning通过图迁移学习进行的通用人体解析
  7. 数组去重方法集锦(一)
  8. 上海有计算机专业的二本大学排名及分数线,上海二本大学排名及分数线
  9. .什么是ECharts
  10. Ubuntu16.04如何安装google chrome浏览器