美文网首页
Android屏幕镜像四:AudioTrack播放PCM

Android屏幕镜像四:AudioTrack播放PCM

作者: DON_1007 | 来源:发表于2019-12-11 17:21 被阅读0次

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

相关文章

网友评论

      本文标题:Android屏幕镜像四:AudioTrack播放PCM

      本文链接:https://www.haomeiwen.com/subject/apwdgctx.html