一、AuidoTrack 使用步骤
1、获取最小缓存区大小
使用 AudioTrack 的静态成员,获取音频缓存区最小尺寸:
static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat)
- sampleRateInHz:音频采样率,常用的采样率有 8k、16k、44.1K、48k;
- channelConfig:声道配置,常用配置有 CHANNEL_IN_MONO (单声道)、CHANNEL_IN_STEREO (立体声);
- audioFormat:采样精度,支持的精度有:ENCODING_PCM_8BIT (8 位量化精度)、ENCODING_PCM_16BIT (16位量化精度);
2、创建 AudoTrack 对象
AudioTraker 构造函数如下:
public AudioTrack(int streamType, int sampleRateInHz, int channelConfig, int audioFormat,
int bufferSizeInBytes, int mode)
streamType : 音频流类型,可选的参数如下:
- AudioSystem.STREAM_VOICE_CALL:通话;
- AudioSystem.STREAM_SYSTEM:系统;
- AudioSystem.STREAM_RING:铃音;
- AudioSystem.STREAM_MUSIC:音乐;
- AudioSystem.STREAM_ALARM:闹铃;
- AudioSystem.STREAM_NOTIFICATION:通知;
sampleRateInHz:参考 getMinBufferSize;
channelConfig:参考 getMinBufferSize;
audioFormat:参考 getMinBufferSize;
bufferSizeInBytes:缓冲区大小,上一步骤获取的值;
mode:支持另种模式 MODE_STATIC (一次写入全部音频数据)、MODE_STREAM (边播放边写入数据);
3、启动播放
调用 AudioTrack 的 play 函数启动音频播放。
public void play()
4、写入音频数据
一般会启动一个线程,通过 write 函数循环往 AudioTrack 中写入音频数据。
public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes)
5、停止播放
调用 stop 停止播放,release 释放资源。
public void stop()
public void release()
二、使用范例
package com.huangchao.testaudio;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import static android.os.Process.*;
public class AudioTrackUtils {
private static final int mStreamType = AudioManager.STREAM_MUSIC;
private static final int mSampleRateInHz = 44100;
private static final int mChannelConfig = AudioFormat.CHANNEL_IN_STEREO;
private static final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
private static int mMode = AudioTrack.MODE_STREAM;
private AudioTrack mAudioTrack;
private DataInputStream mDis;
private Thread mPlayThread;
private boolean isStart = false;
private int mMinBufferSize;
private volatile static AudioTrackUtils mInstance;
Runnable recordRunnable = new Runnable() {
@Override
public void run() {
try {
setThreadPriority(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) {
if (mAudioTrack.getState() == mAudioTrack.STATE_UNINITIALIZED) {
initData();
}
mAudioTrack.play();
mAudioTrack.write(tempBuffer, 0, readCount);
}
}
stopPlay();
} catch (Exception e) {
e.printStackTrace();
}
}
};
public AudioTrackUtils() {
initData();
}
private void initData() {
mMinBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, mChannelConfig, mAudioFormat);
mAudioTrack = new AudioTrack(mStreamType, mSampleRateInHz, mChannelConfig,
mAudioFormat, mMinBufferSize, mMode);
}
public static AudioTrackUtils getInstance() {
if (mInstance == null) {
synchronized (AudioTrackUtils.class) {
if (mInstance == null) {
mInstance = new AudioTrackUtils();
}
}
}
return mInstance;
}
private void destroyThread() {
try {
isStart = false;
if (null != mPlayThread && Thread.State.RUNNABLE == mPlayThread.getState()) {
try {
Thread.sleep(500);
mPlayThread.interrupt();
} catch (Exception e) {
mPlayThread = null;
}
}
mPlayThread = null;
} catch (Exception e) {
e.printStackTrace();
} finally {
mPlayThread = null;
}
}
private void startThread() {
destroyThread();
isStart = true;
if (mPlayThread == null) {
mPlayThread = new Thread(recordRunnable);
mPlayThread.start();
}
}
private void setPath(String path) throws Exception {
File file = new File(path);
mDis = new DataInputStream(new FileInputStream(file));
}
public void startPlay(String path) {
try {
if (isStart) {
return;
}
setPath(path);
startThread();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopPlay() {
try {
destroyThread();
if (mAudioTrack != null) {
if (mAudioTrack.getState() == AudioRecord.STATE_INITIALIZED) {
mAudioTrack.stop();
}
if (mAudioTrack != null) {
mAudioTrack.release();
}
}
if (mDis != null) {
mDis.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
版权声明:本文为shijiheike原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。