Android音视频笔记(一)音频录制

529 阅读1分钟

一、音频录制AudioRecord

AudioRecord录制的输出格式为PCM,这种格式不能直接播放,但是Android原生也提供了AudioTrack,这使得我们可以在软件内部实现录制播放功能。

首先添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

以下是AudioRecord的参数配置。

int frequency = 48000;//采样率
int channelConfig = AudioFormat.CHANNEL_IN_MONO;//声道配置
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;//音频格式
File audioFile;
​
//开始录制
void record() throws IOException {
    //如果文件已存在则删除
    if (audioFile.exists()) audioFile.delete();
    audioFile.createNewFile();
​
    FileOutputStream fos = new FileOutputStream(audioFile);//字节输出流
    BufferedOutputStream bos = new BufferedOutputStream(fos);//字节缓冲输出流
    DataOutputStream dos = new DataOutputStream(bos);
​
    //计算最小缓冲区
    int bufferSize = AudioRecord.getMinBufferSize(frequency, channelConfig, audioFormat);
    short[] buffer = new short[bufferSize];
    if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
        judgeNeedRequestMicPermission();
        return;
    }
    AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, frequency, channelConfig, audioFormat, bufferSize);
    //开始录制
    audioRecord.startRecording();
    recording = true;
    new Thread(new Runnable() {
        @Override
        public void run() {
            while(recording){
                System.out.println(recording);
                int bufferRead = audioRecord.read(buffer, 0, bufferSize);
                for(int i=0; i<bufferRead; i++){
                    try {
                        dos.writeShort(buffer[i]);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            System.out.println(audioFile);
            audioRecord.stop();
            audioRecord.release();
​
            try {
                dos.close();
                bos.close();
                fos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }).start();
}

recording为false时结束录制,可以自定义一个按钮修改。

二、音频播放AudioTrack

AudioTrack的配置与AudioRecord基本一致,唯一要注意的是把声道配置改成 AudioFormat.CHANNEL_OUT_MONO。

void play(int frq) throws IOException{
    int length = (int)audioFile.length()/2;
    if(!audioFile.exists() || length==0) {
        Toast.makeText(getBaseContext(), "音频文件不存在或为空", Toast.LENGTH_SHORT).show();
        return;
    }
    short[] data = new short[length];
    FileInputStream fis = new FileInputStream(audioFile);
    BufferedInputStream bis = new BufferedInputStream(fis);
    DataInputStream dis = new DataInputStream(bis);
    int i=0;
    while(dis.available()>0) {
        data[i] = dis.readShort();
        i++;
    }
    dis.close();
    bis.close();
    fis.close();
​
    AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, frq,  AudioFormat.CHANNEL_OUT_MONO, audioFormat, length*2, AudioTrack.MODE_STREAM);
    audioTrack.play();
    audioTrack.write(data, 0, length);
    audioTrack.stop();
    //audioTrack.release();       // 不能马上release,因为write后是异步播放,此时还刚开始播放,release就不播放了
}

总结

其实也没什么好总结的,本文展示的只是基本用法,AudioRecord能实现很多强大的功能,比如边录边播、语音通话等。以上内容只是对大佬们的拙劣模仿罢了,如果各位有什么其他见解,欢迎在评论区探讨。