在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();

}

Logo

GitCode AI社区是一款由 GitCode 团队打造的智能助手,AI大模型社区、提供国内外头部大模型及数据集服务。

更多推荐