https://blog.csdn.net/ronaldo4511/article/details/89155457
AudioTrack:用于输出音频数据,它有两种数据加载模式
MODE_STREAM:以流的形式持续把音频数据写到AudioTrack内部的Buffer中
MODE_STATIC:在play之前只需要把所有数据通过一次write调用传递到AudioTrack中的内部缓冲区
示例代码
import android.Manifest;
import android.annotation.SuppressLint;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class AudioTrackActivity extends AppCompatActivity {
// 采样率
// 44100是目前的标准,但是某些设备仍然支持22050,16000,11025
// 采样频率一般共分为22.05KHz、44.1KHz、48KHz三个等级
private final static int AUDIO_SAMPLE_RATE = 16000;
// 音频通道 单声道
private final static int AUDIO_CHANNEL = AudioFormat.CHANNEL_OUT_MONO;
// 音频格式:PCM编码
private final static int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
// 音频格式:PCM编码
private final static int AUDIO_TRACK_TYPE_STREAM = AudioTrack.MODE_STREAM;
/**
* 需要申请的运行时权限
*/
private String[] permissions = new String[]{
Manifest.permission.RECORD_AUDIO,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private static final int MY_PERMISSIONS_REQUEST = 1001;
private final String pcmFileName = Environment.getExternalStorageDirectory() + "/Download/record.pcm";
private AudioTrack audioTrack;
private byte[] audioData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_audio_track);
ActivityCompat.requestPermissions(this, permissions, MY_PERMISSIONS_REQUEST);
findViewById(R.id.staticStart).setOnClickListener(v -> staticStart());
findViewById(R.id.streamStart).setOnClickListener(v -> streamStart());
findViewById(R.id.stop).setOnClickListener(v -> stop());
}
@SuppressLint("StaticFieldLeak")
private void staticStart(){
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
InputStream in = new FileInputStream(new File(pcmFileName));
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (int b; (b = in.read()) != -1; ) {
out.write(b);
}
audioData = out.toByteArray();
} finally {
in.close();
}
} catch (IOException e) {
}
return null;
}
@Override
protected void onPostExecute(Void v) {
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, AUDIO_SAMPLE_RATE,
AUDIO_CHANNEL, AUDIO_ENCODING, audioData.length, AUDIO_TRACK_TYPE_STREAM);
audioTrack.write(audioData, 0, audioData.length);
audioTrack.play();
}
}.execute();
}
private void stop(){
if (null != audioTrack) {
audioTrack.stop();
audioTrack.release();
audioTrack = null;
}
}
private void streamStart(){
final int minBufferSize = AudioTrack.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING);
audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, AUDIO_SAMPLE_RATE,
AUDIO_CHANNEL, AUDIO_ENCODING, minBufferSize, AUDIO_TRACK_TYPE_STREAM);
audioTrack.play();
File file = new File(pcmFileName);
new Thread(() -> {
try {
FileInputStream fileInputStream = new FileInputStream(file);
byte[] tempBuffer = new byte[minBufferSize];
while (fileInputStream.available() > 0) {
int readCount = fileInputStream.read(tempBuffer);
if (readCount == AudioTrack.ERROR_INVALID_OPERATION ||
readCount == AudioTrack.ERROR_BAD_VALUE) {
continue;
}
if (readCount != 0 && readCount != -1) {
audioTrack.write(tempBuffer, 0, readCount);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}