Android 音视频之音频录制

Android提供了两个API用于实现录音功能:AudioRecord、MediaRecorder。

AudioRecord

    AudioRecord与MediaRecorder一样用来录制音频的。相对于MediaRecorder来说,AudioRecorder 录音时直接操纵硬件实时获取音频流数据,可以对录制的数据进行实时的处理,比如降噪,除杂,或者将音频进行实时传输,比如IP电话,对讲功能等操作。同时也可实现暂停功能。
    AudioRecord通过设置不同的采样率,采样位数,声道数,"拉"取不同的音质流,我们可以查看Android官方的API来查看他的初始化方法。
    因为AudioRecord比MediaRecorder更接近底层,录制的音频是PCM格式的,最接近原始声音的音频数据。只能用AudioTraker进行播放,或者可以将PCM数据用算法进行压缩编码后,转换成mp3等格式播放。
    AudioRecord的使用还算简单,没有太多复杂的方法,下面就是代码样例。

    // 音频获取源
    private int audioSource = MediaRecorder.AudioSource.MIC;
    // 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
    private static int sampleRateInHz = 44100;
    // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
    private static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
    // 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
    private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    // 缓冲区字节大小
    private int bufferSizeInBytes = 0;
    private AudioRecord audioRecord;
    // 设置正在录制的状态
    private boolean isRecord = false;
    //AudioName裸音频数据文件
    private static final String AudioName = "/sdcard/love.pcm";//不推荐这么写,可以用Enviroment.

    private void creatAudioRecord() {
        // 获得缓冲区字节大小
        bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz,
                channelConfig, audioFormat);
        // 创建AudioRecord对象
        audioRecord = new AudioRecord(audioSource, sampleRateInHz,
                channelConfig, audioFormat, bufferSizeInBytes);
    }

    public void startRecord() {
        if (!isRecord) {
             // 让录制状态为true
             isRecord = true;
             //开始录制
             audioRecord.startRecording();
             // 开启音频文件写入线程
             new Thread(new AudioRecordThread()).start();
        }
    }

    public void stopRecord() {
        if (audioRecord != null) {
            if (isRecord) {
                //停止文件写入
                isRecord = false;
                //停止录制
                audioRecord.stop();
                //释放资源
                audioRecord.release();
            }
        }
    }

    private class AudioRecordThread implements Runnable {
        @Override
        public void run() {
            //往文件中写入裸数据
            writeDateTOFile();
        }
    }

    /**
     * 这里将数据写入文件,但是并不能播放,因为AudioRecord获得的音频是原始的裸音频,
     * 如果需要播放就必须加入一些格式或者编码的头信息。但是这样的好处就是你可以对音频的 裸数据进行处理,比如你要做一个爱说话的TOM
     * 猫在这里就进行音频的处理,然后重新封装 所以说这样得到的音频比较容易做一些音频的处理。
     */
    private void writeDateTOFile() {
        // new一个byte数组用来存一些字节数据,大小为缓冲区大小
        byte[] audiodata = new byte[bufferSizeInBytes];
        FileOutputStream fos = null;
        int readsize = 0;
        try {
            File file = new File(AudioName);
            if (file.exists()) {
                file.delete();
            }
            fos = new FileOutputStream(file);// 建立一个可存取字节的文件
        } catch (Exception e) {
            e.printStackTrace();
        }
        while (isRecord) {
            readsize = audioRecord.read(audiodata, 0, bufferSizeInBytes);
            if (AudioRecord.ERROR_INVALID_OPERATION != readsize) {
                try {
                    fos.write(audiodata);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        try {
            fos.close();// 关闭写入流
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

下面是Android所支持的音频源:

/**默认声音**/
public static final int DEFAULT = 0;
/**麦克风声音*/
public static final int MIC = 1;
/**通话上行声音*/
public static final int VOICE_UPLINK = 2;
/**通话下行声音*/
public static final int VOICE_DOWNLINK = 3;
/**通话上下行声音*/
public static final int VOICE_CALL = 4;
/**根据摄像头转向选择麦克风*/
public static final int CAMCORDER = 5;
/**对麦克风声音进行声音识别,然后进行录制*/
public static final int VOICE_RECOGNITION = 6;
/**对麦克风中类似ip通话的交流声音进行识别,默认会开启回声消除和自动增益*/
public static final int VOICE_COMMUNICATION = 7;
/**录制系统内置声音*/
public static final int REMOTE_SUBMIX = 8;

MediaRecorder

    MediaRecorder已经集成了录音、编码、压缩等,支持少量的录音音频格式。大部分已经集成,直接调用相关接口即可,代码量小。
    如下面代码样例,录制的m4a文件可以直接播放,并且录制一分钟的音频,只有100KB大小,相对于AudioRecord录制的原始音频,1分钟需要10.34MB的大小,已经被压缩很多了。

// 音频获取源
    private int audioSource = MediaRecorder.AudioSource.MIC;
    // 设置音频采样率,44100是目前的标准,但是某些设备仍然支持22050,16000,11025
    private static int sampleRateInHz = 44100;
    // 设置音频的录制的声道CHANNEL_IN_STEREO为双声道,CHANNEL_CONFIGURATION_MONO为单声道
    private static int channelConfig = AudioFormat.CHANNEL_IN_STEREO;
    // 音频数据格式:PCM 16位每个样本。保证设备支持。PCM 8位每个样本。不一定能得到设备支持。
    private static int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
    private MediaRecorder mRecorder;
    //AudioName裸音频数据文件
    private static final String AudioName = "/sdcard/MRecord.m4a";//不推荐这么写,可以用Enviroment.

    public void startRecord() {
        try {
            // 创建AudioRecord对象
            mRecorder = new MediaRecorder();
            // 设置录音的声音来源
            mRecorder.setAudioSource(audioSource);
            // 设置录制的声音的输出格式(必须在设置声音编码格式之前设置)
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            // 设置声音编码格式
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
            //所有android系统都支持的适中采样的频率
            mRecorder.setAudioSamplingRate(sampleRateInHz);
            File file = new File(AudioName);
            if (file.exists()) {
                file.delete();
            }
            mRecorder.setOutputFile(file.getAbsolutePath());

            mRecorder.prepare();

            // 开始录音
            mRecorder.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void stopRecord() {
        if (mRecorder != null) {
            mRecorder.stop();
            mRecorder.release();//释放资源
            mRecorder = null;
        }
    }

权限申请

注意:由于该程序需要使用系统的麦克风进行录音,因此还需要在清单文件AndroidManifest.xml文件中授权相应的权限:

<!-- 授予该程序向外部存储器写入数据的权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 授予该程序录制声音的权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

github项目地址

未完待更新...

上一篇:Android 音视频之音频编码

有问题的地方请大家帮忙指出,谢谢。
持续更新中...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容