Android 音頻錄製(三)-OpenSL ES

Android 系統爲我們提供了三種錄製音頻的方式

  1. MediaRecord( Java API)
  2. AudioRecord( Java API)
  3. OpenSL ES( Native API)

上兩節說了 MediaRecordAudioRecord,他們都是應用層提供的 Java Api。這節呢就來說下 native 層爲我們提供的相關 api。

什麼是 OpenSL ES

先來看下 OpenSL ES 官方文檔 是怎麼介紹的。

This library allows you to use C or C++ to implement high-performance, low-latency audio, whether you are writing a synthesizer, digital audio workstation, karaoke, game, or other real-time app.
The OpenSL ES™ standard exposes audio features similar to those in the MediaPlayer and MediaRecorder APIs in the Android Java framework. OpenSL ES provides a C language interface as well as C++ bindings, allowing you to call the API from code written in either language.

這兩段話的大致意思就是。我這個庫在音頻處理方面老牛逼了,性能高不說,延時還短的不要不要的。而且使用方法和 MediaPlayerMeidaRecord 基本上差別不大,唯一的要求就是得會 C 或者 C艹 呀。

OpenSL ES 在哪

要進行 NDK 開發就必須得先集成相應環境,正如需要 Android SDK 一樣。同樣需要 Android NDK,如果已經科學上網,則直接在 Android StudioSDk Manager 中直接下載即可

在這裏插入圖片描述

下載完成後新建項目時就會看到有一個 Native C++ 的選項,創建出來的項目是一個 Native 版本的 Hello Word。

在這裏插入圖片描述

OpenSL ES 錄製

OpenSL ES 錄製音頻有如下相關流程

  1. 創建接口對象

    void createEngine() {
        SLresult result;
    
        result = slCreateEngine(&engineObj, 0, nullptr, 0, nullptr, nullptr);
        assert(result == SL_RESULT_SUCCESS);
        (void) result;
    
        result = (*engineObj)->Realize(engineObj, SL_BOOLEAN_FALSE);
        assert(SL_RESULT_SUCCESS == result);
        (void) result;
    
        result = (*engineObj)->GetInterface(engineObj, SL_IID_ENGINE, &engine);
        assert(SL_RESULT_SUCCESS == result);
        (void) result;
    
        const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
        const SLboolean req[1] = {SL_BOOLEAN_FALSE};
        // outputMixObj 用於輸出聲音數據
        (*engine)->CreateOutputMix(engine, &outputMixObj, 1, ids, req);
    
        result = (*outputMixObj)->Realize(outputMixObj, SL_BOOLEAN_FALSE);
        assert(SL_RESULT_SUCCESS == result);
        (void) result;
    }
    
  2. 創建錄音器

    result = (*mAudioEngine->engine)->CreateAudioRecorder(mAudioEngine->engine, &mRecorderObj,
            &audioSrc, &audioSink, 1, id, req);
    if (SL_RESULT_SUCCESS != result) {
        return false;
    }
    
    result = (*mRecorderObj)->Realize(mRecorderObj, SL_BOOLEAN_FALSE);
    if (SL_RESULT_SUCCESS != result) {
        return false;
    }
    
  3. 設置緩衝隊列和回調函數

    result = (*mBufferQueue)->RegisterCallback(mBufferQueue, recorderCallback, this);
    
  4. 設置錄音狀態,開始錄製

    bool AudioRecorder::start() {
        if (!mIsInitialized) {
            if (!initRecorder()) {
                return false;
            }
            mIsInitialized = true;
        }
    
        SLresult result;
    
        result = (*mRecorder)->SetRecordState(mRecorder, SL_RECORDSTATE_STOPPED);
        if (SL_RESULT_SUCCESS != result) {
            return false;
        }
    
        result = (*mBufferQueue)->Clear(mBufferQueue);
        if (SL_RESULT_SUCCESS != result) {
            return false;
        }
    
        // enqueue an empty buffer to be filled by the recorder
        // (for streaming recording, we would enqueue at least 2 empty buffers to start things off)
        result = (*mBufferQueue)->Enqueue(mBufferQueue, mBuffers[mIndex], mBufSize * sizeof(short));
        if (SL_RESULT_SUCCESS != result) {
            return false;
        }
    
        // 開始錄製
        result = (*mRecorder)->SetRecordState(mRecorder, SL_RECORDSTATE_RECORDING);
        if (SL_RESULT_SUCCESS != result) {
            return false;
        }
    
        mIsRecording = true;
        LOGI("start recording...");
    
        return true;
    }
    

最後附上 完整源碼

相關推薦

音頻基礎知識

Android 音頻錄製-MeidaRecord

Android 音頻錄製-AudioRecord

Android 音頻錄製-OpenSL ES

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章