音视频

Android音视频开发(一):音频录制

2019-05-09  本文已影响61人  JYangkai

简介

Android中,如果要录制音频的话有两个选择,一个是MediaRecorder,另一个就是AudioRecord,前者使用简单,后者就相对复杂点

关于MediaRecorder的用法相信大家都比较熟悉,而对于AudioRecord可能要陌生一些,所有我们重点来讲下AudioRecord的用法

声音

在此之前,我们先来了解下关于声音的知识,下面是来自百度百科的介绍

声音(sound)是由物体振动产生的声波。是通过介质空气固体液体)传播并能被人或动物听觉器官所感知的波动现象。最初发出振动(震动)的物体叫声源。声音以的形式振动(震动)传播。声音是声波通过任何物质传播形成的运动。

声音作为一种波,频率在20 Hz~20 kHz之间的声音是可以被人耳识别的。

从上面所述我们得到一个信息:人耳可以听到20 Hz~20 kHz的声音,那么根据奈奎斯特定律,采样率要大于或等于信号中两倍的最高频率,这样才能完整得保留原始信号中的信息

也就是说,要一秒钟采样40k次,才能无失帧得记录原始信息

计算机中记录原始音频,一般是用PCM格式存储,pcm的内容都是byte类型的数组,也就是编码格式

PCM8位

如果是单声道,那么byte数组每一个元素都是一次采样的数据
如果是双声道,那么byte数组就是LRLRLR形式的存储(L代表左耳,R代表右耳)

PCM16位

如果是单声道,那么byte数组每两个元素都是一次采样的数据
如果是双声道,那么byte数组就是L低L高 R低R高 L低L高 R低R高形式的存储(L代表左耳,R代表右耳),低表示低八位,高表示高八位

综上我们得出关于音频的三个参数

创建AudioRecord

private static final int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;//音频来源
private static final int AUDIO_SAMPLE_RATE = 44100;//采样率
private static final int AUDIO_IN_CHANNEL = AudioFormat.CHANNEL_IN_STEREO;//双声道
private static final int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;//编码格式 PCM 16位
private int bufferSizeInBytes = 0;//最小录音缓存
private AudioRecord mAudioRecord;//AudioRecord

public void createDefaultAudio() {
    bufferSizeInBytes = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_IN_CHANNEL, AUDIO_ENCODING);
    mAudioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_IN_CHANNEL, AUDIO_ENCODING, bufferSizeInBytes);
}

我们创建AudioRecord之前还需要获得一个叫做最小缓存bufferSizeInBytes的东西,它可以通过AudioRecord.getMinBufferSize()方法获取,因为我们录音需要不断去读写,所有需要有一个缓存空间,刚好AudioRecord提供给我们现成的方法,我们直接用就可以了。

我们创建成功就可以开始录音了,不过要注意,此时你要检查你的应用是否有录音的权限

录音

mAudioRecord.startRecording();

开启录音后我们还没做任何事,也就没法将录音保存下来,所有我们得开启一个子线程将数据写入文件

开启录音线程

/**
 * 开启录制音频子线程
 */
private void startRecordThread() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            writeDataToFile();
        }
    }).start();
}

/**
 * 将录音内容写入文件
 */
private void writeDataToFile() {
    byte[] audioData = new byte[bufferSizeInBytes];
    FileOutputStream fos = null;
    int readSize = 0;
    try {
        File file = new File("你的文件路径");
        if (file.exists()) {
            file.delete();
        }
        fos = new FileOutputStream("你的文件路径", true);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    while (!isStop) {
        readSize = mAudioRecord.read(audioData, 0, bufferSizeInBytes);
        if (readSize == AudioRecord.ERROR_INVALID_OPERATION || readSize == AudioRecord.ERROR_BAD_VALUE) {
            continue;
        }
        if (fos != null) {
            try {
                fos.write(audioData);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    try {
        if (fos != null) {
            fos.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我们这个线程有一个无线循环的while,在while里我们进行数据的读写,我们可以定义一个boolean变量isStop来控制录音的停止

我们先是新建了一个byte数组
byte[] audioData = new byte[bufferSizeInBytes]
这个数组大小就是之前我们获取到的最小缓存

接着我们打开文件,进行读写,通过mAudioRecord.read()方法不断从AudioRecord中读取数据,然后将其写入文件中,最后在我们停止之后关闭文件的输出流。

停止录音

/**
 * 停止录音
 */
private void stop(){
    mAudioRecord.stop();
    isStop = ture;
}

停止录音就调用AudioRecordstop()方法并将isStop置为ture即可停止录音

最后

以上就是AudioRecord的基本用法,关于音频的更多知识与应用后面会陆续和大家分享,希望大家能够喜欢。

上一篇下一篇

猜你喜欢

热点阅读