Android5.1 录音机 MediaRecorder、微信 AudioRecord
Android提供了两个对象用于录音的实现:MediaRecorder 和AudioRecord
1.MediaRecorder:录制的音频文件是经过压缩后的,需要设置编码器 并且录制的音频文件可以用系统自带的Music播放器播放 MediaRecorder已经集成了录音、编码、压缩等,并支持少量的录音音频格式,但是这也是他的缺点,支持的格式过少并且无法实时处理音频数据
2.AudioRecord:主要实现对音频实时处理以及边录边播功能,相对MediaRecorder比较专业,输出是PCM语音数据 如果保存成音频文件,是不能够被播放器播放的,所以必须先写代码实现数据编码以及压缩
一.录音机
1.1.packages\apps\SoundRecorder\src\com\android\soundrecorder\Recorder.java
mRecorder.prepare(); //准备
mRecorder.start();//开始
public void startRecording(int outputfileformat, int recordingType,String extension, Context context) { stop(); if (mSampleFile == null) { String myExtension = extension + TEMP_SUFFIX; File sampleDir = Environment.getExternalStorageDirectory(); if (!sampleDir.canWrite()) // Workaround for broken sdcard support on the device. sampleDir = new File("/sdcard/sdcard"); String sampleDirPath = null; if (sampleDir != null) { sampleDirPath = sampleDir.getAbsolutePath() + File.separator + RECORD_FOLDER; } if (sampleDirPath != null) { sampleDir = new File(sampleDirPath); } if (sampleDir != null && !sampleDir.exists()) { if (!sampleDir.mkdirs()) { Log.i(TAG, "<startRecording> make dirs fail"); } } try { if (null != sampleDir) { Log.i(TAG, "SR sampleDir is:" + sampleDir.toString()); } SimpleDateFormat simpleDateFormat = new SimpleDateFormat( "yyyyMMddHHmmss"); String time = simpleDateFormat.format(new Date(System .currentTimeMillis())); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(SAMPLE_PREFIX).append("_"+time) .append(myExtension); String name = stringBuilder.toString(); mSampleFile = new File(sampleDir, name); boolean result = mSampleFile.createNewFile(); if (result) { Log.i(TAG, "creat file success"); } } catch (IOException e) { setError(SDCARD_ACCESS_ERROR); return; } } mRecorder = new MediaRecorder(); mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mRecorder.setOutputFormat(outputfileformat); mRecorder.setOutputFile(mSampleFile.getAbsolutePath()); mRecorder.setAudioSamplingRate(mSamplingRate);
1.2.frameworks\base\media\java\android\media\MediaRecorder.java
public native void start() throws IllegalStateException; public native void stop() throws IllegalStateException;
1.3.frameworks\base\media\jni\android_media_MediaCodec.cpp
static void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) { ALOGV("android_media_MediaCodec_start"); sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL) { throwExceptionAsNecessary(env, INVALID_OPERATION); return; } status_t err = codec->start(); throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed"); } static void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) { ALOGV("android_media_MediaCodec_stop"); sp<JMediaCodec> codec = getMediaCodec(env, thiz); if (codec == NULL) { throwExceptionAsNecessary(env, INVALID_OPERATION); return; } status_t err = codec->stop(); throwExceptionAsNecessary(env, err); }
二.微信
2.1.AudioRecord
/** * 开始录音 * * @param listener 音频流的监听 */ public void startRecord(final RecordStreamListener listener) { if (status == Status.STATUS_NO_READY || TextUtils.isEmpty(fileName)) { throw new IllegalStateException("录音尚未初始化,请检查是否禁止了录音权限~"); } if (status == Status.STATUS_START) { throw new IllegalStateException("正在录音"); } Log.d("AudioRecorder", "===startRecord===" + audioRecord.getState()); audioRecord.startRecording(); new Thread(new Runnable() { @Override public void run() { writeDataTOFile(listener); } }).start(); }
2.2.frameworks\base\media\java\android\media\AudioRecord.java
/** * Starts recording from the AudioRecord instance. * @throws IllegalStateException */ public void startRecording() throws IllegalStateException { if (mState != STATE_INITIALIZED) { throw new IllegalStateException("startRecording() called on an " + "uninitialized AudioRecord."); } // start recording synchronized(mRecordingStateLock) { if (native_start(MediaSyncEvent.SYNC_EVENT_NONE, 0) == SUCCESS) { handleFullVolumeRec(true); mRecordingState = RECORDSTATE_RECORDING; } mFileObserver.startWatching(); } } /** * Starts recording from the AudioRecord instance when the specified synchronization event * occurs on the specified audio session. * @throws IllegalStateException * @param syncEvent event that triggers the capture. * @see MediaSyncEvent */ public void startRecording(MediaSyncEvent syncEvent) throws IllegalStateException { if (mState != STATE_INITIALIZED) { throw new IllegalStateException("startRecording() called on an " + "uninitialized AudioRecord."); } // start recording synchronized(mRecordingStateLock) { if (native_start(syncEvent.getType(), syncEvent.getAudioSessionId()) == SUCCESS) { handleFullVolumeRec(true); mRecordingState = RECORDSTATE_RECORDING; } } mFileObserver.startWatching(); }