在Android屏幕镜像三:AudioRecorder 录制PCM中
实现了声音的录制,接下来实现保存声音数据并在本机通过AudioTack
播放。
一、保存音频数据
private String audioPath = "sdcard/mc_audio.pcm";
private OutputStream mAudioStream;
AudioCapture.OnAudioCaptureCallback mAudioCallback = new AudioCapture.OnAudioCaptureCallback() {
@Override
public void onCaptureAudioCallback(byte[] buf) {
writeAudio(buf);
}
};
private void writeAudio(byte[] bytes) {
if (mAudioStream == null) {
File audioFile = new File(audioPath);
if (audioFile.exists()) {
audioFile.delete();
}
try {
audioFile.createNewFile();
mAudioStream = new FileOutputStream(audioFile);
} catch (Exception e) {
Log.w(TAG, e);
}
}
try {
mAudioStream.write(bytes);
} catch (Exception e) {
Log.w(TAG, e);
}
}
private void stopWriteAudio() {
if (mAudioStream != null) {
try {
mAudioStream.flush();
mAudioStream.close();
} catch (Exception e) {
Log.w(TAG, e);
}
mAudioStream = null;
}
}
二、读取音频数据并播放
音频文件读取,由于声音没有帧的概念,所以每次只需要读取一定数量的数据即可
public class PCMFileReader extends Thread {
private final static String TAG = "PCMFileReader";
private PCMDecoder mDecoder;
//文件路径
private String path;
public PCMFileReader(String path) {
this.path = path;
}
public void setDecoder(PCMDecoder decoder) {
mDecoder = decoder;
}
@Override
public void run() {
super.run();
File file = new File(path);
if (!file.exists()) {
return;
}
try {
FileInputStream inputStream = new FileInputStream(file);
while (inputStream.available() > 0) {
byte[] frame = new byte[1920];
int length = inputStream.read(frame);
//Log.i(TAG, "read " + length);
onFrame(frame, 0, length);
}
} catch (Exception e) {
Log.w(TAG, e);
}
}
private void onFrame(byte[] frame, int offset, int length) {
if (mDecoder == null) {
return;
}
mDecoder.decode(frame, offset, length);
}
}
AudioTrack播放,注意AudioTack的参数设置与采集音频数据的参数保持一致
public class PCMDecoder {
private final static String TAG = "PCMDecoder";
private AudioTrack mAudioTack;
//音频流类型
private static final int mStreamType = AudioManager.STREAM_MUSIC;
private static final int mSampleRateInHz = 48000;
private static final int mChannelConfig = AudioFormat.CHANNEL_IN_STEREO;
private static final int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;
private int mMinBufferSize;
private static int mMode = AudioTrack.MODE_STREAM;
public PCMDecoder() {
init();
}
private void init() {
mMinBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHz, mChannelConfig, mAudioFormat);
mAudioTack = new AudioTrack(mStreamType, mSampleRateInHz, mChannelConfig,
mAudioFormat, mMinBufferSize * 2, mMode);
}
public void decode(byte[] frame, int offset, int length) {
Log.i(TAG, "decode " + length);
mAudioTack.play();
mAudioTack.write(frame, offset, length);
}
public void stop(){
mAudioTack.stop();
}
}
播放声音
if (mAudioDecoder == null) {
mAudioDecoder = new PCMDecoder();
}
if (mAudioThread == null) {
mAudioThread = new PCMFileReader(audioPath);
mAudioThread.setDecoder(mAudioDecoder);
mAudioThread.start();
}
网友评论