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

Z
zengyawen 已提交
3
## 简介
4

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

Z
zengyawen 已提交
7
## 开发指导
8 9 10

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

L
liuyuehua1 已提交
11 12 13 14 15 16 17 18
1. 添加头文件

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

Mr-YX's avatar
Mr-YX 已提交
19
2. 使用 **slCreateEngine** 接口创建引擎对象和实例化引擎对象 **engine**
20 21 22 23 24 25 26

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

L
liuyuehua1 已提交
27
3. 获取接口 **SL_IID_ENGINE** 的引擎接口 **engineEngine** 实例
28 29 30 31 32 33

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

Mr-YX's avatar
Mr-YX 已提交
34
4. 配置录音器信息(配置输入源audiosource、输出源audiosink),创建录音对象**pcmCapturerObject**
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

    ```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
    };

54
    // 具体参数需要根据音频文件格式进行适配
55
    SLDataFormat_PCM format_pcm = {
56 57 58 59
        SL_DATAFORMAT_PCM,           // 输入的音频格式
        1,                           // 单声道
        SL_SAMPLINGRATE_44_1,        // 采样率,44100HZ
        SL_PCMSAMPLEFORMAT_FIXED_16, // 音频采样格式,小尾数,带符号的16位整数
60 61 62 63
        0,
        0,
        0
    };
L
liuyuehua1 已提交
64

65 66 67 68 69 70 71 72 73 74 75
    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 已提交
76
5. 获取录音接口**SL_IID_RECORD****recordItf** 接口实例
77
 
Mr-YX's avatar
Mr-YX 已提交
78
    ```c++
79 80 81 82
    SLRecordItf  recordItf;
    (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_RECORD, &recordItf);
    ```   

L
liuyuehua1 已提交
83
6. 获取接口 **SL_IID_OH_BUFFERQUEUE****bufferQueueItf** 实例
84

Mr-YX's avatar
Mr-YX 已提交
85
    ```c++
86 87 88 89
    SLOHBufferQueueItf bufferQueueItf;
    (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
    ```

90
7. 注册 **BufferQueueCallback** 回调
91 92

    ```c++
L
liuyuehua1 已提交
93
    static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
94
    {
L
liuyuehua1 已提交
95
        AUDIO_INFO_LOG("BufferQueueCallback");
96 97 98 99 100 101 102 103 104 105 106 107 108 109
        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;
    }
    
110
    // wavFile_ 需要设置为用户想要录音的文件描述符
L
liuyuehua1 已提交
111
    (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, wavFile_);
112 113
    ```

L
liuyuehua1 已提交
114
8. 开始录音
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

    ```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 已提交
130
                AUDIO_INFO_LOG("CaptureStart, buffer is null or pSize: %{public}lu.", pSize);
131 132 133 134 135 136 137
            }
        }

        return;
    }
    ```

L
liuyuehua1 已提交
138
9. 结束录音
139 140

    ```c++
L
liuyuehua1 已提交
141 142 143 144 145 146 147 148 149 150
    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;
    }  
Mr-YX's avatar
Mr-YX 已提交
151
    ```