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