android 传输pcm pc播放,Android屏幕镜像四:AudioTrack播放PCM

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

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值