android AudioRecord音频录制AudioTrack音频播放,pcm转wav

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34272093/article/details/81703096
package com.example.administrator.speech;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Environment;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class AudioRecordManager {

    //播放状态 status
    private boolean isRecording = false;
    //音频输入麦克风
    private static final int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;
    //录音对象
    private AudioRecord record = null;
    //缓冲区
    private int bufferSize = 0;
    //采样率
    private final static int AUDIO_SAMPLE_RATE_IN_HZ = 16000;
    //单声道
    private final static int AUDIO_CHANNEL_CONFIG = AudioFormat.CHANNEL_CONFIGURATION_MONO;
    //音频格式
    private final static int AUTIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

    private static final String TAG = "AudioRecordManager";
    private Context context;
    //音频播放
    private AudioTrack track;
    private FileInputStream fileInputStream;
    //pcm file wav file
    private File file,pcmFile,wavFile;
    //Thread
    private Thread recordThread = null;
    private ArrayList<byte[]> inBuffer = new ArrayList<>();

    //构造方法
    public AudioRecordManager(Context context) {
        this.context = context;
        bufferSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE_IN_HZ, AUDIO_CHANNEL_CONFIG, AUTIO_ENCODING);
        record = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE_IN_HZ, AUDIO_CHANNEL_CONFIG, AUTIO_ENCODING, bufferSize);
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
            file = new File(Environment.getExternalStorageDirectory().getPath()+"/WAV/");
            if (file.exists()){
                file.delete();
            }
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        pcmFile = new File(file, "test.pcm");
        wavFile = new File(file, "test.wav");
        Log.d("----->wavFile=",wavFile.getAbsolutePath());
        if (wavFile.exists()){
            wavFile.delete();
        }


    }


    //创建录音对象
    public void createAudio(String fileName, int audioSource, int sampleRateInHz, int channelConfig, int encoding) {
        bufferSize = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, encoding);
        record = new AudioRecord(audioSource, sampleRateInHz, channelConfig, encoding, bufferSize);
//        this.fileName = fileName;
    }

//    //创建默认的录音对象
//    public void createDefaultAudio(String fileName) {
//        bufferSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE_IN_HZ, AUDIO_CHANNEL_CONFIG, AUTIO_ENCODING);
//        record = new AudioRecord(AUDIO_INPUT,AUDIO_SAMPLE_RATE_IN_HZ, AUDIO_CHANNEL_CONFIG, AUTIO_ENCODING,bufferSize);
//        rawFile = fileName+".raw";
//        wavFile = fileName+".wav";
//        startRecord();
//    }

    /**
     * 开始录音
     */
    public void startRecord() {
        record.startRecording();
        isRecording = true;
        recordThread = new Thread(new AudioRecordThread());
        recordThread.start();
    }

    public void stopRecord() {
        isRecording = false;
        inBuffer.clear();
    }

    public void clearRecord() {
        if (record != null) {
            record.stop();
            record.release();
            record = null;
        }
        try {
            recordThread.join();

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    class AudioRecordThread implements Runnable {
        @Override
        public void run() {
            writeDataToFile();
            pcmToWav(pcmFile.getAbsolutePath(),wavFile.getAbsolutePath());
        }
    }

    private void writeDataToFile() {
        try {
            byte[] audioData = new byte[bufferSize];
            FileOutputStream outputStream = null;
            int readSize;

            if (pcmFile.exists()) pcmFile.delete();
            outputStream = new FileOutputStream(pcmFile);
            while (isRecording) {
                readSize = record.read(audioData, 0, bufferSize);
                synchronized (inBuffer) {
                    inBuffer.add(audioData.clone());
                }
                if (AudioRecord.ERROR_INVALID_OPERATION != readSize) {
                    outputStream.write(audioData);
                }
            }
            outputStream.flush();
            outputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * pcm 转换成wav
     **/
    private void pcmToWav(String pcmFile,String wavFile){
        FileInputStream in;
        FileOutputStream out;
        long totalAudioLen;
        long totalDataLen;
        long longSampleRate = AUDIO_SAMPLE_RATE_IN_HZ;
        int channels = 1;
        long byteRate = 16 * AUDIO_SAMPLE_RATE_IN_HZ * channels / 8;
        byte[] data = new byte[bufferSize];
        try {
            in = new FileInputStream(pcmFile);
            out = new FileOutputStream(wavFile);
            totalAudioLen = in.getChannel().size();
            totalDataLen = totalAudioLen + 36;
            WriteWaveFileHeader(out, totalAudioLen, totalDataLen, longSampleRate, channels, byteRate);
            while (in.read(data) != -1) {
                out.write(data);
            }
            in.close();
            out.close();
        }catch (IOException e) {
            e.printStackTrace();
        }


    }
    private byte[] WriteWaveFileHeader(FileOutputStream out, long totalAudioLen,
                                       long totalDataLen, long longSampleRate, int channels,
                                       long byteRate) throws IOException {
        byte[] header = new byte[44];
        header[0] = 'R';
        header[1] = 'I';
        header[2] = 'F';
        header[3] = 'F';
        header[4] = (byte) (totalDataLen & 0xff);
        header[5] = (byte) ((totalDataLen >> 8) & 0xff);
        header[6] = (byte) ((totalDataLen >> 16) & 0xff);
        header[7] = (byte) ((totalDataLen >> 24) & 0xff);
        header[8] = 'W';
        header[9] = 'A';
        header[10] = 'V';
        header[11] = 'E';
        header[12] = 'f'; // 'fmt ' chunk
        header[13] = 'm';
        header[14] = 't';
        header[15] = ' ';
        header[16] = 16; // 4 bytes: size of 'fmt ' chunk
        header[17] = 0;
        header[18] = 0;
        header[19] = 0;
        header[20] = 1; // format = 1
        header[21] = 0;
        header[22] = (byte) channels;
        header[23] = 0;
        header[24] = (byte) (longSampleRate & 0xff);
        header[25] = (byte) ((longSampleRate >> 8) & 0xff);
        header[26] = (byte) ((longSampleRate >> 16) & 0xff);
        header[27] = (byte) ((longSampleRate >> 24) & 0xff);
        header[28] = (byte) (byteRate & 0xff);
        header[29] = (byte) ((byteRate >> 8) & 0xff);
        header[30] = (byte) ((byteRate >> 16) & 0xff);
        header[31] = (byte) ((byteRate >> 24) & 0xff);
        header[32] = (byte) (1 * 16 / 8); // block align
        header[33] = 0;
        header[34] = 16; // bits per sample
        header[35] = 0;
        header[36] = 'd';
        header[37] = 'a';
        header[38] = 't';
        header[39] = 'a';
        header[40] = (byte) (totalAudioLen & 0xff);
        header[41] = (byte) ((totalAudioLen >> 8) & 0xff);
        header[42] = (byte) ((totalAudioLen >> 16) & 0xff);
        header[43] = (byte) ((totalAudioLen >> 24) & 0xff);
        out.write(header, 0, 44);
        return header;
    }

    /**
     * 结束录制
     */
    /**
     * 播放
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void playRecord() {
        final int minBufferSize = AudioTrack.getMinBufferSize(AUDIO_SAMPLE_RATE_IN_HZ, AUDIO_CHANNEL_CONFIG, AUTIO_ENCODING);
        track = new AudioTrack(new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .build(),
                new AudioFormat.Builder()
                .setSampleRate(AUDIO_SAMPLE_RATE_IN_HZ)
                .setEncoding(AUTIO_ENCODING)
                .setChannelMask(AUDIO_CHANNEL_CONFIG)
                .build(),
                minBufferSize,
                AudioTrack.MODE_STREAM,
                AudioManager.AUDIO_SESSION_ID_GENERATE
        );
        track.play();
        File file = new File(Environment.getExternalStorageDirectory().getPath()+"/WAV/", "test.pcm");
        try {
            fileInputStream = new FileInputStream(file);
            new Thread(new Runnable() {
               @Override
               public void run() {
                   byte[] tempBuffer = new byte[minBufferSize];
                   int lenght = 0;
                   try {
                       lenght = fileInputStream.available();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
                   boolean is= lenght>0?true:false;
                   while (is) {
                       int readCount = 0;
                       try {
                           readCount = fileInputStream.read(tempBuffer);
                       } catch (IOException e) {
                           e.printStackTrace();
                       }
                       if (readCount == AudioTrack.ERROR_INVALID_OPERATION ||
                               readCount == AudioTrack.ERROR_BAD_VALUE) {
                           continue;
                       }
                       if (readCount != 0 && readCount != -1) {
                           track.write(tempBuffer, 0, readCount);
                       }
                   }

               }
           }).start();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }


    }
}

猜你喜欢

转载自blog.csdn.net/qq_34272093/article/details/81703096