美文网首页
语音开发初识(AudioRecord、AudioTrack的使用

语音开发初识(AudioRecord、AudioTrack的使用

作者: Ford_ | 来源:发表于2019-06-01 18:24 被阅读0次

最近在做语音相关的开发如Siri 智能音箱等都会经过下图的流程:


image.png

1.RecordManager类 对录音功能进行封装

public class RecordManager {
    private final static String TAG = "RecordManager";
    private static RecordManager mInstance;
    // 音频获取源
    private int audioSource = MediaRecorder.AudioSource.VOICE_COMMUNICATION;
    // 设置音频采样率
    private int sampleRateInHz = 48000;
    // 设置音频的录制的声道 CHANNEL_IN_STEREO为双声道
    private int channelConfig = AudioFormat.CHANNEL_IN_MONO;
    // 音频数据格式:PCM 16位每个样本
    private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    // 缓冲区字节大小
    private int bufferSizeInBytes = 0;
    private AudioRecord audioRecord;
    // 设置正在录制的状态
    private boolean isRecord = false;
    private static String sdFilePath = Environment.getExternalStorageDirectory().getPath() + "/RecordPcm/";
    private File pcmFile;

    private RecordManager() {
    }

    public static RecordManager getInstance() {
        if (mInstance == null) {
            synchronized (RecordManager.class) {
                if (mInstance == null) {
                    mInstance = new RecordManager();
                }
            }
        }
        return mInstance;
    }
 /**
     * 初始化AudioRecord
     */

    public void init() {
        bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat);
        audioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);
    }

    /**
     * 停止录制
     */
    public void stopRecord() {
        if (audioRecord != null) {
            Log.d(TAG, "Record Close...");
            isRecord = false;//停止文件写入
            audioRecord.stop();
            audioRecord.release();//释放资源
            audioRecord = null;
        }
    }
/**
     * 开始录制
     */
    public void startRecord() {
        if (isRecord) {
            Log.e(TAG, "正在录制中....." + audioRecord.getState());
            return;
        }
        if (audioRecord == null) {
            init();
        }
        if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
            Log.e(TAG, "AudioRecord创建失败" + audioRecord.getState());
            return;
        }
        isRecord = true;
        pcmFile = createFile(System.currentTimeMillis() + "abc.pcm");
        audioRecord.startRecording();
        // 开启音频文件写入线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                byte[] audioData = new byte[bufferSizeInBytes];
                FileOutputStream fos = null;
                try {
                    fos = new FileOutputStream(pcmFile.getAbsoluteFile());
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
                int readSize;
                while (isRecord == true) {
                    readSize = audioRecord.read(audioData, 0, bufferSizeInBytes);
                    if (AudioRecord.ERROR_INVALID_OPERATION != readSize) {
                        try {
                            fos.write(audioData);
                            Log.v(TAG, "readSize:" + readSize);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private File createFile(String name) {
        File file = new File(sdFilePath);
        if (!file.exists()) {
            file.mkdirs();
        }
        String filePath = sdFilePath + name;
        File objFile = new File(filePath);
        if (!objFile.exists()) {
            try {
                objFile.createNewFile();
                return objFile;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return objFile;
    }


二、TrackManager 封装了pcm播放的功能

 final private static String TAG = "TrackManager";
    private static TrackManager mInstance;
    private AudioTrack mAudioTrack;
    private int mOutChannelConfig = AudioFormat.CHANNEL_OUT_MONO;//播放声道
    private int mTrackBufferSize;
    private int mSampleRateInHZ = 48000; //采样率
    private int mAudioFormat = AudioFormat.ENCODING_PCM_16BIT;  //位数
    private static String sdFilePath = Environment.getExternalStorageDirectory().getPath() + "/RecordPcm/";
    private File file;
    private volatile boolean isLife;

    private TrackManager() {
    }

    public static TrackManager getInstance() {
        if (mInstance == null) {
            synchronized (TrackManager.class) {
                mInstance = new TrackManager();
            }
        }
        return mInstance;
    }

    /**
     * 初始化AudioTrack
     */
    private void init() {
        mTrackBufferSize = AudioTrack.getMinBufferSize(mSampleRateInHZ, mOutChannelConfig, mAudioFormat);// 获得音频缓冲区大小
        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, mSampleRateInHZ, mOutChannelConfig, mAudioFormat, mTrackBufferSize, AudioTrack.MODE_STREAM);
    }
 /**
     * 开始播放 pcm文件
     */
    public void startTrack() {
        if (isLife) {
            Log.d(TAG, "正在播放...");
            return;
        }
        if (mAudioTrack == null) {
            init();
        }
        isLife = true;
        new Thread((new Runnable() {
            @Override
            public void run() {
                byte[] tempBuffer = new byte[mTrackBufferSize];
                FileInputStream fileInputStream;
                File folder = new File(sdFilePath);
                if (!folder.isDirectory()) {
                    return;
                }
                for (File folderFile : folder.listFiles()) {
                    Log.e(TAG, "STATUS:" + mAudioTrack.getState());
                    if (!isLife) {
                        return;
                    }
                    String folderName = folderFile.getName();
                    file = new File(sdFilePath, folderName);
                    Log.d(TAG, "path:" + sdFilePath + "  -folderName:" + folderName);
                    if (!file.exists()) {
                        continue;
                    }
                    try {
                        mAudioTrack.play();
                        fileInputStream = new FileInputStream(file);
                        while (fileInputStream.available() > 0) {
                            int readCount = fileInputStream.read(tempBuffer);
                            if (readCount == AudioTrack.ERROR_INVALID_OPERATION ||
                                    readCount == AudioTrack.ERROR_BAD_VALUE) {
                                continue;
                            }
                            Log.v(TAG, "readCount:" + readCount);
                            if (readCount != 0 && readCount != -1) {
                                mAudioTrack.write(tempBuffer, 0, readCount);
                            }
                        }
                        fileInputStream.close();
                        try {
                            Thread.sleep(300);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                stopTrack();
            }
        })).start();
    }

    /**
     * 停止播放
     */
    public void stopTrack() {
        Log.d(TAG, "stopTrack");
        if (mAudioTrack != null) {
            isLife = false;
            mAudioTrack.stop();
        }
    }

MainActivity

 public void onClick(View v) {
        int id = v.getId();
        switch (id) {
            case R.id.btn_start_record:
                RecordManager.getInstance().startRecord();
                break;
            case R.id.btn_stop_record:
                RecordManager.getInstance().stopRecord();
                break;
            case R.id.btn_start_track:
                TrackManager.getInstance().startTrack();
                break;
            case R.id.btn_stop_track:
                TrackManager.getInstance().stopTrack();
                break;
        }
abcd.jpg

github:代码查看地址

相关文章

网友评论

      本文标题:语音开发初识(AudioRecord、AudioTrack的使用

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