• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# OpenSL ES音频录制开发指导
2
3## 简介
4
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
7## 开发指导
8
9以下步骤描述了在**OpenHarmony**如何使用 **OpenSL ES** 开发音频录音功能:
10
111. 添加头文件
12
13    ```c++
14    #include <OpenSLES.h>
15    #include <OpenSLES_OpenHarmony.h>
16    #include <OpenSLES_Platform.h>
17    ```
18
192. 使用 **slCreateEngine** 接口创建引擎对象和实例化引擎对象 **engine**
20
21    ```c++
22    SLObjectItf engineObject = nullptr;
23    slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
24    (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
25    ```
26
273. 获取接口 **SL_IID_ENGINE** 的引擎接口 **engineEngine** 实例
28
29    ```c++
30    SLEngineItf engineItf = nullptr;
31    result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineItf);
32    ```
33
344. 配置录音器信息(配置输入源audiosource、输出源audiosink),创建录音对象**pcmCapturerObject**
35
36    ```c++
37    SLDataLocator_IODevice io_device = {
38        SL_DATALOCATOR_IODEVICE,
39        SL_IODEVICE_AUDIOINPUT,
40        SL_DEFAULTDEVICEID_AUDIOINPUT,
41        NULL
42    };
43
44    SLDataSource audioSource = {
45        &io_device,
46        NULL
47    };
48
49    SLDataLocator_BufferQueue buffer_queue = {
50        SL_DATALOCATOR_BUFFERQUEUE,
51        3
52    };
53
54    // 具体参数需要根据音频文件格式进行适配
55    SLDataFormat_PCM format_pcm = {
56        SL_DATAFORMAT_PCM,           // 输入的音频格式
57        1,                           // 单声道
58        SL_SAMPLINGRATE_44_1,        // 采样率,44100HZ
59        SL_PCMSAMPLEFORMAT_FIXED_16, // 音频采样格式,小尾数,带符号的16位整数
60        0,
61        0,
62        0
63    };
64
65
66    SLDataSink audioSink = {
67        &buffer_queue,
68        &format_pcm
69    };
70
71    SLObjectItf pcmCapturerObject = nullptr;
72    result = (*engineItf)->CreateAudioRecorder(engineItf, &pcmCapturerObject,
73        &audioSource, &audioSink, 0, nullptr, nullptr);
74    (*pcmCapturerObject)->Realize(pcmCapturerObject, SL_BOOLEAN_FALSE);
75    ```
76
775. 获取录音接口**SL_IID_RECORD** 的 **recordItf** 接口实例
78
79    ```c++
80    SLRecordItf  recordItf;
81    (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_RECORD, &recordItf);
82    ```
83
846. 获取接口 **SL_IID_OH_BUFFERQUEUE** 的 **bufferQueueItf** 实例
85
86    ```c++
87    SLOHBufferQueueItf bufferQueueItf;
88    (*pcmCapturerObject)->GetInterface(pcmCapturerObject, SL_IID_OH_BUFFERQUEUE, &bufferQueueItf);
89    ```
90
917. 注册 **BufferQueueCallback** 回调
92
93    ```c++
94    static void BufferQueueCallback(SLOHBufferQueueItf bufferQueueItf, void *pContext, SLuint32 size)
95    {
96        AUDIO_INFO_LOG("BufferQueueCallback");
97        FILE *wavFile = (FILE *)pContext;
98        if (wavFile != nullptr) {
99            SLuint8 *buffer = nullptr;
100            SLuint32 pSize = 0;
101            (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
102            if (buffer != nullptr) {
103                fwrite(buffer, 1, pSize, wavFile);
104                (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, size);
105            }
106        }
107
108        return;
109    }
110
111    // wavFile_ 需要设置为用户想要录音的文件描述符
112    (*bufferQueueItf)->RegisterCallback(bufferQueueItf, BufferQueueCallback, wavFile_);
113    ```
114
1158. 开始录音
116
117    ```c++
118    static void CaptureStart(SLRecordItf recordItf, SLOHBufferQueueItf bufferQueueItf, FILE *wavFile)
119    {
120        AUDIO_INFO_LOG("CaptureStart");
121        (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_RECORDING);
122        if (wavFile != nullptr) {
123            SLuint8* buffer = nullptr;
124            SLuint32 pSize = 0;
125            (*bufferQueueItf)->GetBuffer(bufferQueueItf, &buffer, pSize);
126            if (buffer != nullptr) {
127                AUDIO_INFO_LOG("CaptureStart, enqueue buffer length: %{public}lu.", pSize);
128                fwrite(buffer, 1, pSize, wavFile);
129                (*bufferQueueItf)->Enqueue(bufferQueueItf, buffer, pSize);
130            } else {
131                AUDIO_INFO_LOG("CaptureStart, buffer is null or pSize: %{public}lu.", pSize);
132            }
133        }
134
135        return;
136    }
137    ```
138
1399. 结束录音
140
141    ```c++
142    static void CaptureStop(SLRecordItf recordItf)
143    {
144        AUDIO_INFO_LOG("Enter CaptureStop");
145        fflush(wavFile_);
146        (*recordItf)->SetRecordState(recordItf, SL_RECORDSTATE_STOPPED);
147        (*pcmCapturerObject)->Destroy(pcmCapturerObject);
148        fclose(wavFile_);
149        wavFile_ = nullptr;
150        return;
151    }
152    ```