AudioTrack用来播放音频的原始数据PCM。MediaPlayer把音频解码后的数据交给AudioTrack来播放。

我们看下AudioTrack的构造函数

  public AudioTrack(AudioAttributes attributes, AudioFormat format, int bufferSizeInBytes,int mode, int sessionId)throws IllegalArgumentException {this(attributes, format, bufferSizeInBytes, mode, sessionId, false /*offload*/,ENCAPSULATION_MODE_NONE, null /* tunerConfiguration */);}

AudioAttributes attributes  

        AudioAttributes audioAttributes = (new AudioAttributes.Builder()).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();

设置当前要播放什么内容的数据

我们看源码包括下面一下信息

public final class AudioAttributes implements Parcelable {private final static String TAG = "AudioAttributes";/*** Content type value to use when the content type is unknown, or other than the ones defined.*/public final static int CONTENT_TYPE_UNKNOWN = 0;/*** Content type value to use when the content type is speech.*/public final static int CONTENT_TYPE_SPEECH = 1;/*** Content type value to use when the content type is music.*/public final static int CONTENT_TYPE_MUSIC = 2;/*** Content type value to use when the content type is a soundtrack, typically accompanying* a movie or TV program.*/public final static int CONTENT_TYPE_MOVIE = 3;/*** Content type value to use when the content type is a sound used to accompany a user* action, such as a beep or sound effect expressing a key click, or event, such as the* type of a sound for a bonus being received in a game. These sounds are mostly synthesized* or short Foley sounds.*/public final static int CONTENT_TYPE_SONIFICATION = 4;

包括了 演讲 电影 音乐等类型。我们这里选择

CONTENT_TYPE_MUSIC

 AudioFormat format

 AudioFormat.Builder builder = new AudioFormat.Builder();builder.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO).setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(44100);AudioFormat audioFormat = builder.build();

设置声道掩码,比如采集音视频我们设置了AudioFormat.CHANNEL_IN_STEREO,那么播放的时候要设置成AudioFormat.CHANNEL_OUT_STEREO

设置编码格式AudioFormat.ENCODING_PCM_16BIT 每个采样大小是2个字节

设置采样率 44100

builder还提供了setChannelIndexMask方法,setChannelIndexMask和setChannelMask是互斥的。

setChannelIndexMask
Added in API level 23
AudioFormat.Builder setChannelIndexMask (int channelIndexMask)
设置频道索引掩码。 通道索引掩码指定帧中的音频采样与编号的端点通道的关联。 信道索引掩码中的第i位对应于第i个端点信道。 例如,具有四个通道的端点被表示为索引掩码位0至3.这个位置掩码解释的这个setChannelMask(int) 。AudioTrack和AudioRecord支持通道索引掩码。 如果指定了通道索引掩码,则使用该掩码,否则使用由setChannelMask指定的通道位置掩码。 对于AudioTrack和AudioRecord ,如果指定了通道索引掩码,则不需要通道位置掩码。
int bufferSizeInBytes
     *   See {@link #getMinBufferSize(int, int, int)} to determine the estimated minimum buffer size*   for an AudioTrack instance in streaming mode.

注释中写道对于流模式AudioTrack getMinBufferSize

int mode

@param mode streaming or static buffer. See {@link #MODE_STATIC} and {@link #MODE_STREAM}.

MODE_STATIC 一次把数据传进来

MODE_STREAM 传很多次数据

int sessionId 会话id
AudioManager.AUDIO_SESSION_ID_GENERATE

AudioManager.generateAudioSessionId()

开始播放

 Runnable recordRunnable = new Runnable() {@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overridepublic void run() {try {//设置线程的优先级android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);byte[] tempBuffer = new byte[buffersize];int readCount = 0;while (inputStream.available() > 0) {readCount= inputStream.read(tempBuffer);if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {continue;}if (readCount != 0 && readCount != -1) {//一边播放一边写入语音数据//判断AudioTrack未初始化,停止播放的时候释放了,状态就为STATE_UNINITIALIZEDif(mAudioTrack.getState() == mAudioTrack.STATE_UNINITIALIZED){init();}mAudioTrack.play();mAudioTrack.write(tempBuffer, 0, readCount);}}stopPlay();//播放完就停止播放} catch (Exception e) {e.printStackTrace();}}};

停止播放

 public void stopPlay() {try {if (mAudioTrack != null) {if (mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {//初始化成功mAudioTrack.stop();//停止播放}if (mAudioTrack != null) {mAudioTrack.release();//释放audioTrack资源}}if (inputStream != null) {inputStream.close();//关闭数据输入流}} catch (Exception e) {e.printStackTrace();}}

完整代码

package com.yuanxuzhen.androidmedia.audio;import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.os.Build;
import android.provider.MediaStore;
import android.util.Log;import androidx.annotation.RequiresApi;import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class AudioTrackManager {private static volatile AudioTrackManager instance;private AudioTrack mAudioTrack;private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;private int buffersize;private ExecutorService executorService;private DataInputStream inputStream;private AudioTrackManager() {init();}public static AudioTrackManager getInstance() {if (instance == null) {synchronized (AudioTrackManager.class) {if (instance == null) {instance = new AudioTrackManager();}}}return instance;}@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)private void init() {executorService = Executors.newCachedThreadPool();AudioFormat.Builder builder = new AudioFormat.Builder();builder.setChannelMask(AudioFormat.CHANNEL_OUT_STEREO).setEncoding(AudioFormat.ENCODING_PCM_16BIT).setSampleRate(44100);AudioFormat audioFormat = builder.build();buffersize = AudioTrack.getMinBufferSize(44100,AudioFormat.CHANNEL_OUT_STEREO,AudioFormat.ENCODING_PCM_16BIT);Log.e("yuanAudioTrack", "init buffersize=" + buffersize);AudioAttributes audioAttributes = (new AudioAttributes.Builder()).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build();mAudioTrack = new AudioTrack(audioAttributes,audioFormat,buffersize,AudioTrack.MODE_STREAM,AudioManager.AUDIO_SESSION_ID_GENERATE);}/*** 播放线程*/Runnable recordRunnable = new Runnable() {@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overridepublic void run() {try {//设置线程的优先级android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);byte[] tempBuffer = new byte[buffersize];int readCount = 0;while (inputStream.available() > 0) {readCount= inputStream.read(tempBuffer);if (readCount == AudioTrack.ERROR_INVALID_OPERATION || readCount == AudioTrack.ERROR_BAD_VALUE) {continue;}if (readCount != 0 && readCount != -1) {//一边播放一边写入语音数据//判断AudioTrack未初始化,停止播放的时候释放了,状态就为STATE_UNINITIALIZEDif(mAudioTrack.getState() == mAudioTrack.STATE_UNINITIALIZED){init();}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);inputStream = new DataInputStream(new FileInputStream(file));}public void stopPlay() {try {if (mAudioTrack != null) {if (mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {//初始化成功mAudioTrack.stop();//停止播放}if (mAudioTrack != null) {mAudioTrack.release();//释放audioTrack资源}}if (inputStream != null) {inputStream.close();//关闭数据输入流}} catch (Exception e) {e.printStackTrace();}}public void startPlay(String path) {try {setPath(path);executorService.execute(recordRunnable);} catch (Exception e) {e.printStackTrace();}}}

gitee地址

https://gitee.com/creat151/android-media.git

AudioTrack使用相关推荐

  1. android audiotrack使用问题:listener不回调的原因

    部分人使用audiotrack,有可能会发现audiotrack的回调方法不回调,其实很多情况下是这样子的: 一般的音频数据源会起一个线程获取,一般新起的线程都没有looper,而audiotrack ...

  2. android audiotrack权限,Android中AudioRecord和AudioTrack的使用注意

    AudioRecord需要至少 这项录音权限.有时候在AndroidManifest.xml中加进去后,有些手机系统仍然没有授予该权限.需要到手机的设置中的权限管理,把这项权限打开.没权限就会闪退.如 ...

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

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

  4. android音频系统之AudioTrack的使用

    今天,简单讲讲  AudioTrack的使用. 1.Android AudioTrack简介 在android中播放声音可以用MediaPlayer和AudioTrack两种方案的,但是两种方案是 ...

  5. WebRTC 的 AudioSource/AudioTrack

    按照 WebRTC 的设计,AudioSource 是一个音频源,它可以向外提供 PCM 音频帧数据,比如麦克风录制可以提供 PCM 音频帧数据,它应该是一个 AudioSource.然而在 WebR ...

  6. ktm390蓝牙连接安卓_蓝牙音乐AudioTrack Session ID的获取

    当今这个音视频无处不在的时代,音频跟踪会话ID(AudioTrack Session ID)是个很重要的参数,可以用来实现音频相关的一些特效.接下来的内容我们就探究如何在安卓蓝牙系统中获取该id. 熟 ...

  7. Android之 AudioTrack学习

    AudioTrack主要是用来播放声音的,AudioTrack贯穿了JAVA层,JNI层和Native层. AudioTrack JAVA层: framework\base\media\java\an ...

  8. Andorid之MediaPlayer和AudioTrack播放Audio的区别与联系

    播放声音可以用MediaPlayer和AudioTrack,两者都提供了java API供应用开发者使用.虽然都可以播放声音,但两者还是有很大的区别的. 其中最大的区别是MediaPlayer可以播放 ...

  9. android 使用 audiorecord 和 audiotrack 实现实时录音播放

    基本思路就是用 audiorecord不断得到音频数据,然后使用audiotrack 播放 //得到音频 package com.ysg.audiotest;import java.io.IOExce ...

  10. AudioTrack 播放PCM音频数据

    AudioTrack 可以用来播放PCM数据,上一篇博客我讲了AudioRecord可以录制PCM数据 AudioTrack实例可以在两种模式下运行:静态或流式传输. 在Streaming模式下,应用 ...

最新文章

  1. SAP MM初阶之事务代码MIGO界面批次拆分最多输入15行?
  2. 【华为出品】智能体白皮书2020(附全文下载)
  3. 2021年第十六届全国大学生智能汽车竞赛赛道铺设规范
  4. slf4j 使用方法---个人总结
  5. 什么是xmlschema
  6. datetimepicker弹出窗在iframe中部分遮挡_美军下一代班组武器项目,NGSW中的小秘密,你了解多少?...
  7. 电脑知识:电脑无法开机解决方案,赶紧收藏吧!
  8. LCS(2021牛客多校4)
  9. 【python】Macbook的Anaconda查看、创建和管理python环境
  10. 50元打造双网卡负载均衡服务器
  11. 寻宝处理器的引人入胜之旅——《大话处理器》新书出炉
  12. Dubbo自定义日志拦截器 1
  13. println()函数输出int类型返回值错误的问题
  14. Herev Falciani推出新的加密货币和区块链项目
  15. 【面经】深度学习算法岗(京东)
  16. 单链表插入时间复杂度分析
  17. HDLBits在线练习题之Exams/ece241 2014 q7b
  18. ecshop二次开发手册【基本结构】
  19. Unity UGUI Inputfield 回车submit 按下Enter回车完成
  20. Android开发使用Glide获取图片背景色淡绿色解决办法

热门文章

  1. 光伏发电站并网点反孤岛保护装置——安科瑞 严新亚
  2. 电路——电阻电路的一般分析方法
  3. Java 锁机机制——浅析 Synchronized
  4. 两台电脑共享一个音响方法
  5. 【智能无线小车系列十一】利用GPS 模块定位我的小车
  6. 【深度之眼吴恩达机器学习第四期】笔记(五)
  7. 从0到1优雅实现沉浸式状态栏
  8. 单片机AT指令操作GA6-B短信模块连接阿里云MQTT服务器(双向通信)
  9. 2022-2028年中国考前英语培训行业市场现状调查及投资商机预测报告
  10. 七种分布式系统的解决方案,一次性讲给你听!