天天看点

Android 音频 Framework层 音频输入 录音 Java API

上篇文章我们介绍了音频输出(音乐播放),本文将介绍音频的录音即输入,文章中代码坏境Android 4.4

音频输入类:

        MediaRecorder 

        AudioRecord

首先录制音频需要在 AndroidManifest.xml 中加入权限

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

1、MediaRecorder

        MediaRecorder是Android 提供媒体文件录制的类,可以录制视频和音频,我们这主要的是录制音频,下面先看一段录音的代码:

package com.example.framework;

import java.io.File;

import android.app.Activity;
import android.media.MediaRecorder;
import android.media.MediaRecorder.AudioEncoder;
import android.media.MediaRecorder.AudioSource;
import android.media.MediaRecorder.OutputFormat;
import android.os.Bundle;

public class MediaRecorderActivity extends Activity {
	private MediaRecorder mRediaRecorder;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		try {
			String path = new File(getCacheDir(), "audio.mp4").getAbsolutePath();
			mRediaRecorder = new MediaRecorder();
			mRediaRecorder.setAudioChannels(2);
			mRediaRecorder.setAudioSource(AudioSource.MIC);
			mRediaRecorder.setAudioSamplingRate(44100);
			mRediaRecorder.setOutputFormat(OutputFormat.MPEG_4);
			mRediaRecorder.setOutputFile(path);
			mRediaRecorder.setAudioEncoder(AudioEncoder.DEFAULT);
			mRediaRecorder.prepare();
			mRediaRecorder.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (mRediaRecorder != null) {
			mRediaRecorder.stop();
			mRediaRecorder.release();
		}
	}
}
           

参数说明:

AudioChannels 

        声道,Android中取值范围:1或者2,1代表单声道,2代表双声道(立体声)

AudioSource 

        音频源,Android中已经定义好常量,android.media.MediaRecorder.AudioSource 类

public final class AudioSource {
     
        private AudioSource() {}

        /** Default audio source **/
        public static final int DEFAULT = 0;

        /** Microphone audio source */
        public static final int MIC = 1;

        /** Voice call uplink (Tx) audio source */
        public static final int VOICE_UPLINK = 2;

        /** Voice call downlink (Rx) audio source */
        public static final int VOICE_DOWNLINK = 3;

        /** Voice call uplink + downlink audio source */
        public static final int VOICE_CALL = 4;

        /** Microphone audio source with same orientation as camera if available, the main
         *  device microphone otherwise */
        public static final int CAMCORDER = 5;

        public static final int VOICE_RECOGNITION = 6;

        public static final int VOICE_COMMUNICATION = 7;

        public static final int REMOTE_SUBMIX = 8;

}
           

AudioSource.DEFAULT 默认

AudioSource.MIC  麦克风

AudioSource.VOICE_UPLINK  电话上行

AudioSource.VOICE_DOWNLINK 电话下行

AudioSource.VOICE_CALL 电话 上行+下行

AudioSource.CAMCORDER 摄像机

AudioSource.VOICE_RECOGNITION 语音识别

AudioSource.VOICE_COMMUNICATION 语音通信,例如VoIP

AudioSource.REMOTE_SUBMIX 远程声音,例如wifi display

电话录音:AudioSource.VOICE_UPLINK,AudioSource.VOICE_DOWNLINK,AudioSource.VOICE_CALL 需要系统权限

AudioSource.REMOTE_SUBMIX 需要在AndroidManifest中加入

<uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
           

SamplingRate

        采样率,一般取值范围在8000-48000,取值越大声音越好,采样率高文件也会更大

OutputFormat 

        输出格式,Android中已经定义好常量,android.media.MediaRecorder.OutputFormat 类

public final class OutputFormat {
      
        private OutputFormat() {}
        public static final int DEFAULT = 0;
        /** 3GPP media file format*/
        public static final int THREE_GPP = 1;
        /** MPEG4 media file format*/
        public static final int MPEG_4 = 2;

        /** The following formats are audio only .aac or .amr formats */

        /**
         * AMR NB file format
         * @deprecated  Deprecated in favor of MediaRecorder.OutputFormat.AMR_NB
         */
        public static final int RAW_AMR = 3;

        /** AMR NB file format */
        public static final int AMR_NB = 3;

        /** AMR WB file format */
        public static final int AMR_WB = 4;

        /** @hide AAC ADIF file format */
        public static final int AAC_ADIF = 5;

        /** AAC ADTS file format */
        public static final int AAC_ADTS = 6;

        /** @hide Stream over a socket, limited to a single stream */
        public static final int OUTPUT_FORMAT_RTP_AVP = 7;

        /** @hide H.264/AAC data encapsulated in MPEG2/TS */
        public static final int OUTPUT_FORMAT_MPEG2TS = 8;
 }
           

介绍几种常用的格式, @hide 隐藏的,开发中避免使用,新的版本中就可能去掉该格式的支持。

        OutputFormat.THREE_GPP 

                3gp格式

        OutputFormat.MPEG_4 

                mp4格式

        OutputFormat.AMR_NB  

        OutputFormat.AMR_WB 

                AMR_NB和AMR_WB的算法不一样.

        OutputFormat.AAC_ADTS 

                ADTS 全称是(Audio Data Transport Stream) 主要用于音频流传输.

文件格式中并没有看到MP3,Android暂时不支持MP3格式,可以自己录制PCM数据编码成MP3 ,后面我们会介绍PCM数据的录制

OutputFile 

        录音的文件保存路径

AudioEncoder 

        音频编码,编码定义常量类,android.media.MediaRecorder.AudioEncoder

public final class AudioEncoder {
      /* Do not change these values without updating their counterparts
       * in include/media/mediarecorder.h!
       */
        private AudioEncoder() {}
        public static final int DEFAULT = 0;
        /** AMR (Narrowband) audio codec */
        public static final int AMR_NB = 1;
        /** AMR (Wideband) audio codec */
        public static final int AMR_WB = 2;
        /** AAC Low Complexity (AAC-LC) audio codec */
        public static final int AAC = 3;
        /** High Efficiency AAC (HE-AAC) audio codec */
        public static final int HE_AAC = 4;
        /** Enhanced Low Delay AAC (AAC-ELD) audio codec */
        public static final int AAC_ELD = 5;
    }
           

对于不同的文件格式选择不同的编码

        录制MP4或者AAC_ADTS格式时选用编码 AudioEncoder.AAC,AudioEncoder.HE_AAC,AudioEncoder.AAC_ELD

        录制3gp或者amr格式时选用编码 AudioEncoder.AMR_NB,AudioEncoder.AMR_WB 

MediaRecorder录音的主要步骤

        1:设置参数

        2:prepare 准备

        3:start 开始录音

        4:stop 停止录音

        5:release 释放资源

2、AudioRecord

        AudioRecord 低级API,录制的是PCM数据,没有经过压缩,先看Demo

package com.example.framework;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.os.Bundle;

public class AudioRecordActivity extends Activity implements Runnable {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		new Thread(this).start();
	}

	@Override
	public void run() {
		BufferedOutputStream bos = null;
		AudioRecord audioRecord = null;
		try {
			int audioSource = AudioSource.MIC;
			int sampleRateInHz = 44100;
			int channelConfig = AudioFormat.CHANNEL_OUT_STEREO;
			int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
			int bufferSizeInBytes = AudioRecord.getMinBufferSize(sampleRateInHz, channelConfig, audioFormat) * 2;
			audioRecord = new AudioRecord(audioSource, sampleRateInHz, channelConfig, audioFormat, bufferSizeInBytes);
			audioRecord.startRecording();
			bos = new BufferedOutputStream(new FileOutputStream(new File(getCacheDir(), "audio.pcm")));
			byte[] buffer = new byte[bufferSizeInBytes];
			int len = 0;
			while (!isFinishing()) {
				len = audioRecord.read(buffer, 0, bufferSizeInBytes);
 				if (len <= 0) {
					break;
				}
				bos.write(buffer, 0, len);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bos != null) {
				try {
					bos.close();
				} catch (IOException e) {}
			}
			if (audioRecord != null) {
				audioRecord.release();
			}
		}
	}

}
           

上面的代码是录制麦克风的数据,将录制之后的数据写入"audio.pcm" 文件。

AudioRecord 主要参数说明

        audioSource

                和MediaRecorder的一样。

        sampleRateInHz 

                和MediaRecorder的一样。

        channelConfig  

                和MediaRecorder 不一样,AudioFormat.CHANNEL_OUT_STEREO或者AudioFormat.CHANNEL_OUT_STEREO

        audioFormat

                AudioFormat.ENCODING_PCM_8BIT 或者 AudioFormat.ENCODING_PCM_16BIT

        bufferSizeInBytes

                音频缓冲区大小,使用AudioRecord.getMinBufferSize 方法可以获取最小的缓冲区,上面的代码是获取最小的缓冲区乘以2

AudioRecord 的步骤:

        1、设置参数

        2、startRecording 开始录音

        3、read 读取录制的数据

        4、release 释放资源

当我们调用startRecording之后就可以调用read方法从系统中读取音频的PCM数据

read方法的返回值:返回的是读取的数据len,如果大于0读取数据成功,否则读取失败.

总结:MediaRecorder 功能比较强大,录制压缩格式,AudioRecord录制的是PCM数据,在实际开发中两个都有可能用到。