opensles-capture.md 4.7 KB
Newer Older
L
liuyuehua1 已提交
1
# OpenSL ES音频录制开发指导
2 3 4

## 场景介绍

L
liuyuehua1 已提交
5 6
开发者可以通过本文了解到在**OpenHarmony**如何使用**OpenSL ES**进行录音相关操作;当前仅实现了部分[**OpenSL ES**接口]  
(https://gitee.com/openharmony/third_party_opensles/blob/master/api/1.0.1/OpenSLES.h),未实现接口调用后会返回**SL_RESULT_FEATURE_UNSUPPORTED**
7 8 9 10 11 12 13

 

## 开发步骤

以下步骤描述了在**OpenHarmony**如何使用 **OpenSL ES** 开发音频录音功能:

L
liuyuehua1 已提交
14 15 16 17 18 19 20 21 22
1. 添加头文件

    ```c++
    #include <OpenSLES.h>
    #include <OpenSLES_OpenHarmony.h>
    #include <OpenSLES_Platform.h>
    ```

2. 使用 **slCreateEngine** 接口创建引擎对象和实例化引擎对象 **engine**
23 24 25 26 27 28 29 30 31

    ```c++
    SLObjectItf engineObject = nullptr;
    slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
    (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
    ```

    

L
liuyuehua1 已提交
32
3. 获取接口 **SL_IID_ENGINE** 的引擎接口 **engineEngine** 实例
33 34 35 36 37 38 39 40

    ```c++
    SLEngineItf engineItf = nullptr;
    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineItf);
    ```

    

L
liuyuehua1 已提交
41
4. 配置录音器信息(配置输入源audiosource、输出源audiosink),创建录音对象**pcmCapturerObject**
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

    ```c++
    SLDataLocator_IODevice io_device = {
        SL_DATALOCATOR_IODEVICE,
        SL_IODEVICE_AUDIOINPUT,
        SL_DEFAULTDEVICEID_AUDIOINPUT,
        NULL
    };

    SLDataSource audioSource = {
        &io_device,
        NULL
    };

    SLDataLocator_BufferQueue buffer_queue = {
        SL_DATALOCATOR_BUFFERQUEUE,
        3
    };

    //具体参数需要根据音频文件格式进行适配
    SLDataFormat_PCM format_pcm = {
        SL_DATAFORMAT_PCM,
        OHOS::AudioStandard::AudioChannel::MONO,
        OHOS::AudioStandard::AudioSamplingRate::SAMPLE_RATE_44100,
        OHOS::AudioStandard::AudioSampleFormat::SAMPLE_S16LE,
        0,
        0,
        0
    };
L
liuyuehua1 已提交
71

72 73 74 75 76 77 78 79 80 81 82
    SLDataSink audioSink = {
        &buffer_queue,
        &format_pcm
    };
    
    SLObjectItf pcmCapturerObject = nullptr;
    result = (*engineItf)->CreateAudioRecorder(engineItf, &pcmCapturerObject,
        &audioSource, &audioSink, 0, nullptr, nullptr);
    (*pcmCapturerObject)->Realize(pcmCapturerObject, SL_BOOLEAN_FALSE);
    ```

L
liuyuehua1 已提交
83
5. 获取录音接口**SL_IID_RECORD****recordItf** 接口实例
84 85 86 87 88 89
 
    ```
    SLRecordItf  recordItf;
    (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_RECORD, &recordItf);
    ```   

L
liuyuehua1 已提交
90
6. 获取接口 **SL_IID_OH_BUFFERQUEUE****bufferQueueItf** 实例
91 92 93 94 95 96 97 98

    ```
    SLOHBufferQueueItf bufferQueueItf;
    (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
    ```

    

L
liuyuehua1 已提交
99
7. 注册 **BuqqerQueueCallback** 回调
100 101

    ```c++
L
liuyuehua1 已提交
102
    static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
103
    {
L
liuyuehua1 已提交
104
        AUDIO_INFO_LOG("BufferQueueCallback");
105 106 107 108 109 110 111 112 113 114 115 116 117 118
        FILE *wavFile = (FILE *)pContext;
        if (wavFile != nullptr) {
            SLuint8 *buffer = nullptr;
            SLuint32 pSize = 0;
            (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
            if (buffer != nullptr) {
                fwrite(buffer, 1, pSize, wavFile);
                (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
            } 
        }

        return;
    }
    
L
liuyuehua1 已提交
119
    //wavFile_ 需要设置为用户想要录音的文件描述符
L
liuyuehua1 已提交
120
    (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, wavFile_);
121 122 123
    ```


L
liuyuehua1 已提交
124
8. 开始录音
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

    ```c++
    static void CaptureStart(SLRecordItf recordItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile)
    {
        AUDIO_INFO_LOG("CaptureStart");
        (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING);
        if (wavFile != nullptr) {
            SLuint8* buffer = nullptr;
            SLuint32 pSize = 0;
            (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
            if (buffer != nullptr) {
                AUDIO_INFO_LOG("CaptureStart, enqueue buffer length: %{public}lu.", pSize);
                fwrite(buffer, 1, pSize, wavFile);
                (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, pSize);
            } else {
L
liuyuehua1 已提交
140
                AUDIO_INFO_LOG("CaptureStart, buffer is null or pSize: %{public}lu.", pSize);
141 142 143 144 145 146 147 148
            }
        }

        return;
    }
    ```


L
liuyuehua1 已提交
149
9. 结束录音
150 151

    ```c++
L
liuyuehua1 已提交
152 153 154 155 156 157 158 159 160 161
    static void CaptureStop(SLRecordItf recordItf)
    {
        AUDIO_INFO_LOG("Enter CaptureStop");
        fflush(wavFile_);
        (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED);
        (*pcmCapturerObject)->Destroy(pcmCapturerObject);
        fclose(wavFile_);
        wavFile_ = nullptr;
        return;
    }  
162
    ```