1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <bits/alltypes.h>
17 #include <cstdint>
18 #include <cstdio>
19 #include <cstring>
20 #include <net/if.h>
21 #include <thread>
22 #include <chrono>
23 #include <sys/stat.h>
24 #include <linux/quota.h>
25 #include "napi/native_api.h"
26 #include "ohaudio/native_audiocapturer.h"
27 #include "ohaudio/native_audiorenderer.h"
28 #include "ohaudio/native_audiostreambuilder.h"
29 #include "ohaudio/native_audiostream_base.h"
30 #include "hilog/log.h"
31
32 const int GLOBAL_RESMGR = 0xFF00;
33
34 namespace AudioTestConstants {
35 constexpr int32_t FIRST_ARG_IDX = 1;
36 constexpr int32_t SECOND_ARG_IDX = 2;
37 constexpr int32_t THIRD_ARG_IDX = 3;
38 constexpr int32_t RECODER_TIME = 10000;
39 constexpr int32_t COUNTDOWN_INTERVAL = 1000;
40 constexpr int32_t CONVERT_RATE = 1000;
41 constexpr int32_t WAIT_INTERVAL = 1000;
42 } // namespace AudioTestConstants
43
44 static std::string g_filePath = "/data/storage/el2/base/haps/entry/files/oh_test_audio.pcm";
45
46 FILE *g_file = nullptr;
47 bool g_readEnd = false;
48 bool g_rendererLowLatency = false;
49 int32_t g_samplingRate = 48000;
50 int32_t g_channelCount = 2;
51 int32_t g_latencyMode = 1;
52
53 static OH_AudioStream_Result ret;
54 static OH_AudioCapturer_Callbacks callbacks;
55 static OH_AudioRenderer_Callbacks rendererCallbacks;
56 static OH_AudioCapturer *audioCapturer;
57 static OH_AudioRenderer *audioRenderer;
58 static OH_AudioStreamBuilder *builder;
59 static OH_AudioStreamBuilder *rendererBuilder;
60
GetRendererState(napi_env env,napi_callback_info info)61 static napi_value GetRendererState(napi_env env, napi_callback_info info)
62 {
63 OH_AudioStream_State state;
64 OH_AudioRenderer_GetCurrentState(audioRenderer, &state);
65 napi_value sum;
66 napi_create_int32(env, state, &sum);
67
68 return sum;
69 }
70
GetFileState(napi_env env,napi_callback_info info)71 static napi_value GetFileState(napi_env env, napi_callback_info info)
72 {
73 napi_value sum;
74 napi_create_int32(env, g_readEnd, &sum);
75
76 return sum;
77 }
78
GetFramesWritten(napi_env env,napi_callback_info info)79 static napi_value GetFramesWritten(napi_env env, napi_callback_info info)
80 {
81 napi_value sum;
82 int64_t frames;
83 OH_AudioRenderer_GetFramesWritten(audioRenderer, &frames);
84 napi_create_int64(env, frames, &sum);
85
86 return sum;
87 }
88
GetFileSize(napi_env env,napi_callback_info info)89 static napi_value GetFileSize(napi_env env, napi_callback_info info)
90 {
91 struct stat statbuf;
92 stat(g_filePath.c_str(), &statbuf);
93 napi_value sum;
94 int64_t fileSize = statbuf.st_size;
95 napi_create_int64(env, fileSize, &sum);
96 return sum;
97 }
98
AudioCapturerOnReadData(OH_AudioCapturer * capturer,void * userData,void * buffer,int32_t bufferLen)99 static int32_t AudioCapturerOnReadData(OH_AudioCapturer *capturer, void *userData, void *buffer, int32_t bufferLen)
100 {
101 size_t count = 1;
102 if (fwrite(buffer, bufferLen, count, g_file) != count) {
103 printf("buffer fwrite err");
104 }
105 return 0;
106 }
107
AudioRendererOnWriteData(OH_AudioRenderer * capturer,void * userData,void * buffer,int32_t bufferLen)108 static int32_t AudioRendererOnWriteData(OH_AudioRenderer *capturer, void *userData, void *buffer, int32_t bufferLen)
109 {
110 size_t readCount = fread(buffer, bufferLen, 1, g_file);
111 if (!readCount) {
112 if (ferror(g_file)) {
113 printf("Error reading myfile");
114 } else if (feof(g_file)) {
115 OH_AudioRenderer_Stop(audioRenderer);
116 OH_AudioRenderer_Release(audioRenderer);
117 OH_AudioStreamBuilder_Destroy(rendererBuilder);
118 fclose(g_file);
119 g_file = fopen(g_filePath.c_str(), "rb");
120 // 1. create builder
121
122 OH_AudioStream_Type type = AUDIOSTREAM_TYPE_RENDERER;
123 OH_AudioStreamBuilder_Create(&rendererBuilder, type);
124 // 2. set params and callbacks
125
126 OH_AudioStreamBuilder_SetSamplingRate(rendererBuilder, g_samplingRate);
127 OH_AudioStreamBuilder_SetChannelCount(rendererBuilder, g_channelCount);
128 if (g_rendererLowLatency) {
129 OH_AudioStreamBuilder_SetLatencyMode(rendererBuilder, (OH_AudioStream_LatencyMode)g_latencyMode);
130 }
131 rendererCallbacks.OH_AudioRenderer_OnWriteData = AudioRendererOnWriteData;
132 OH_AudioStreamBuilder_SetRendererCallback(rendererBuilder, rendererCallbacks, nullptr);
133 // 3. create OH_AudioRenderer
134
135 OH_AudioStreamBuilder_GenerateRenderer(rendererBuilder, &audioRenderer);
136 g_readEnd = true;
137 }
138 }
139 return 0;
140 }
141
AudioCapturerLowLatencyInit(napi_env env,napi_callback_info info)142 static napi_value AudioCapturerLowLatencyInit(napi_env env, napi_callback_info info)
143 {
144 if (audioCapturer) {
145 OH_AudioCapturer_Release(audioCapturer);
146 OH_AudioStreamBuilder_Destroy(builder);
147 fclose(g_file);
148 g_file = nullptr;
149 audioCapturer = nullptr;
150 builder = nullptr;
151 }
152 g_file = fopen(g_filePath.c_str(), "wb");
153 // 1. create builder
154
155 OH_AudioStream_Type type = AUDIOSTREAM_TYPE_CAPTURER;
156 OH_AudioStreamBuilder_Create(&builder, type);
157 // 2. set params and callbacks
158
159 OH_AudioStreamBuilder_SetSamplingRate(builder, g_samplingRate);
160 OH_AudioStreamBuilder_SetChannelCount(builder, g_channelCount);
161 OH_AudioStreamBuilder_SetLatencyMode(builder, (OH_AudioStream_LatencyMode)g_latencyMode);
162
163 callbacks.OH_AudioCapturer_OnReadData = AudioCapturerOnReadData;
164 OH_AudioStreamBuilder_SetCapturerCallback(builder, callbacks, nullptr);
165
166 // 3. create OH_AudioCapturer
167
168 OH_AudioStreamBuilder_GenerateCapturer(builder, &audioCapturer);
169 return nullptr;
170 }
171
AudioCapturerInit(napi_env env,napi_callback_info info)172 static napi_value AudioCapturerInit(napi_env env, napi_callback_info info)
173 {
174 if (audioCapturer) {
175 OH_AudioCapturer_Release(audioCapturer);
176 OH_AudioStreamBuilder_Destroy(builder);
177 fclose(g_file);
178 g_file = nullptr;
179 audioCapturer = nullptr;
180 builder = nullptr;
181 }
182 g_file = fopen(g_filePath.c_str(), "wb");
183 // create builder
184
185 OH_AudioStream_Type type = AUDIOSTREAM_TYPE_CAPTURER;
186 OH_AudioStreamBuilder_Create(&builder, type);
187
188 // set params and callbacks
189
190 OH_AudioStreamBuilder_SetSamplingRate(builder, g_samplingRate);
191 OH_AudioStreamBuilder_SetChannelCount(builder, g_channelCount);
192
193 callbacks.OH_AudioCapturer_OnReadData = AudioCapturerOnReadData;
194 OH_AudioStreamBuilder_SetCapturerCallback(builder, callbacks, nullptr);
195
196 // create OH_AudioCapturer
197
198 OH_AudioStreamBuilder_GenerateCapturer(builder, &audioCapturer);
199 return nullptr;
200 }
201
202
AudioCapturerStart(napi_env env,napi_callback_info info)203 static napi_value AudioCapturerStart(napi_env env, napi_callback_info info)
204 {
205 // start
206
207 OH_AudioCapturer_Start(audioCapturer);
208 return nullptr;
209 }
210
AudioCapturerPause(napi_env env,napi_callback_info info)211 static napi_value AudioCapturerPause(napi_env env, napi_callback_info info)
212 {
213 OH_AudioCapturer_Pause(audioCapturer);
214 return nullptr;
215 }
216
AudioCapturerStop(napi_env env,napi_callback_info info)217 static napi_value AudioCapturerStop(napi_env env, napi_callback_info info)
218 {
219 OH_AudioCapturer_Stop(audioCapturer);
220 return nullptr;
221 }
222
AudioCapturerRelease(napi_env env,napi_callback_info info)223 static napi_value AudioCapturerRelease(napi_env env, napi_callback_info info)
224 {
225 if (audioCapturer) {
226 OH_AudioCapturer_Release(audioCapturer);
227 OH_AudioStreamBuilder_Destroy(builder);
228 audioCapturer = nullptr;
229 builder = nullptr;
230 }
231 return nullptr;
232 }
233
CloseFile(napi_env env,napi_callback_info info)234 static napi_value CloseFile(napi_env env, napi_callback_info info)
235 {
236 if (g_file) {
237 fclose(g_file);
238 g_file = nullptr;
239 }
240 return nullptr;
241 }
242
AudioRendererLowLatencyInit(napi_env env,napi_callback_info info)243 static napi_value AudioRendererLowLatencyInit(napi_env env, napi_callback_info info)
244 {
245 if (audioRenderer) {
246 OH_AudioRenderer_Release(audioRenderer);
247 OH_AudioStreamBuilder_Destroy(rendererBuilder);
248 fclose(g_file);
249 g_file = nullptr;
250 audioRenderer = nullptr;
251 rendererBuilder = nullptr;
252 }
253 g_file = fopen(g_filePath.c_str(), "rb");
254 if (g_file == nullptr) {
255 return 0;
256 }
257 // create builder
258
259 OH_AudioStream_Type type = AUDIOSTREAM_TYPE_RENDERER;
260 OH_AudioStreamBuilder_Create(&rendererBuilder, type);
261
262 // set params and callbacks
263
264 OH_AudioStreamBuilder_SetSamplingRate(rendererBuilder, g_samplingRate);
265 OH_AudioStreamBuilder_SetChannelCount(rendererBuilder, g_channelCount);
266 OH_AudioStreamBuilder_SetLatencyMode(builder, (OH_AudioStream_LatencyMode)g_latencyMode);
267
268 rendererCallbacks.OH_AudioRenderer_OnWriteData = AudioRendererOnWriteData;
269 OH_AudioStreamBuilder_SetRendererCallback(rendererBuilder, rendererCallbacks, nullptr);
270
271 // create OH_AudioRenderer
272
273 OH_AudioStreamBuilder_GenerateRenderer(rendererBuilder, &audioRenderer);
274 g_readEnd = false;
275 g_rendererLowLatency = true;
276 return nullptr;
277 }
278
AudioRendererInit(napi_env env,napi_callback_info info)279 static napi_value AudioRendererInit(napi_env env, napi_callback_info info)
280 {
281 if (audioRenderer) {
282 OH_AudioRenderer_Release(audioRenderer);
283 OH_AudioStreamBuilder_Destroy(rendererBuilder);
284 fclose(g_file);
285 g_file = nullptr;
286 audioRenderer = nullptr;
287 rendererBuilder = nullptr;
288 }
289 g_file = fopen(g_filePath.c_str(), "rb");
290 if (g_file == nullptr) {
291 return 0;
292 }
293 // create builder
294
295 OH_AudioStream_Type type = AUDIOSTREAM_TYPE_RENDERER;
296 OH_AudioStreamBuilder_Create(&rendererBuilder, type);
297
298 // set params and callbacks
299
300 OH_AudioStreamBuilder_SetSamplingRate(rendererBuilder, g_samplingRate);
301 OH_AudioStreamBuilder_SetChannelCount(rendererBuilder, g_channelCount);
302
303 rendererCallbacks.OH_AudioRenderer_OnWriteData = AudioRendererOnWriteData;
304 OH_AudioStreamBuilder_SetRendererCallback(rendererBuilder, rendererCallbacks, nullptr);
305
306 // create OH_AudioRenderer
307
308 OH_AudioStreamBuilder_GenerateRenderer(rendererBuilder, &audioRenderer);
309 g_readEnd = false;
310 g_rendererLowLatency = false;
311 return nullptr;
312 }
313
314
AudioRendererStart(napi_env env,napi_callback_info info)315 static napi_value AudioRendererStart(napi_env env, napi_callback_info info)
316 {
317 g_readEnd = false;
318 // start
319
320 OH_AudioRenderer_Start(audioRenderer);
321 return nullptr;
322 }
323
AudioRendererPause(napi_env env,napi_callback_info info)324 static napi_value AudioRendererPause(napi_env env, napi_callback_info info)
325 {
326 g_readEnd = false;
327 OH_AudioRenderer_Pause(audioRenderer);
328 return nullptr;
329 }
330
AudioRendererStop(napi_env env,napi_callback_info info)331 static napi_value AudioRendererStop(napi_env env, napi_callback_info info)
332 {
333 g_readEnd = false;
334 OH_AudioRenderer_Stop(audioRenderer);
335 return nullptr;
336 }
337
AudioRendererRelease(napi_env env,napi_callback_info info)338 static napi_value AudioRendererRelease(napi_env env, napi_callback_info info)
339 {
340 if (audioRenderer) {
341 OH_AudioRenderer_Release(audioRenderer);
342 OH_AudioStreamBuilder_Destroy(rendererBuilder);
343 audioRenderer = nullptr;
344 rendererBuilder = nullptr;
345 }
346 return nullptr;
347 }
348
349
Init(napi_env env,napi_value exports)350 EXTERN_C_START static napi_value Init(napi_env env, napi_value exports)
351 {
352 napi_property_descriptor desc[] = {
353 {"closeFile", nullptr, CloseFile, nullptr, nullptr, nullptr, napi_default, nullptr},
354 {"audioCapturerLowLatencyInit", nullptr, AudioCapturerLowLatencyInit, nullptr, nullptr, nullptr, napi_default,
355 nullptr},
356 {"audioCapturerInit", nullptr, AudioCapturerInit, nullptr, nullptr, nullptr, napi_default, nullptr},
357 {"audioCapturerStart", nullptr, AudioCapturerStart, nullptr, nullptr, nullptr, napi_default, nullptr},
358 {"audioCapturerPause", nullptr, AudioCapturerPause, nullptr, nullptr, nullptr, napi_default, nullptr},
359 {"audioCapturerRelease", nullptr, AudioCapturerRelease, nullptr, nullptr, nullptr, napi_default, nullptr},
360 {"audioCapturerStop", nullptr, AudioCapturerStop, nullptr, nullptr, nullptr, napi_default, nullptr},
361 {"audioRendererLowLatencyInit", nullptr, AudioRendererLowLatencyInit, nullptr, nullptr, nullptr, napi_default,
362 nullptr},
363 {"audioRendererInit", nullptr, AudioRendererInit, nullptr, nullptr, nullptr, napi_default, nullptr},
364 {"audioRendererStart", nullptr, AudioRendererStart, nullptr, nullptr, nullptr, napi_default, nullptr},
365 {"audioRendererPause", nullptr, AudioRendererPause, nullptr, nullptr, nullptr, napi_default, nullptr},
366 {"audioRendererRelease", nullptr, AudioRendererRelease, nullptr, nullptr, nullptr, napi_default, nullptr},
367 {"getRendererState", nullptr, GetRendererState, nullptr, nullptr, nullptr, napi_default, nullptr},
368 {"getFileSize", nullptr, GetFileSize, nullptr, nullptr, nullptr, napi_default, nullptr},
369 {"getFramesWritten", nullptr, GetFramesWritten, nullptr, nullptr, nullptr, napi_default, nullptr},
370 {"getFileState", nullptr, GetFileState, nullptr, nullptr, nullptr, napi_default, nullptr},
371 {"audioRendererStop", nullptr, AudioRendererStop, nullptr, nullptr, nullptr, napi_default, nullptr}};
372 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
373 return exports;
374 }
375 EXTERN_C_END
376
377 static napi_module demoModule = {
378 .nm_version = 1,
379 .nm_flags = 0,
380 .nm_filename = nullptr,
381 .nm_register_func = Init,
382 .nm_modname = "entry",
383 .nm_priv = ((void *)0),
384 .reserved = {0},
385 };
386
RegisterEntryModule(void)387 extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
388 {
389 napi_module_register(&demoModule);
390 }
391