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();//开始

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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

1
2
public native void start() throws IllegalStateException;
public native void stop() throws IllegalStateException;

1.3.frameworks\base\media\jni\android_media_MediaCodec.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 开始录音
 *
 * @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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/**
 * 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();
}

  

 

posted @   CrushGirl  阅读(259)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示