* Copyright (C) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "napi/native_api.h"
#include "ohaudio/native_audiocapturer.h"
#include <ohaudio/native_audiorenderer.h>
#include <ohaudio/native_audiostreambuilder.h>
#include "ohaudio/native_audio_session_manager.h"
#include <ohaudio/native_audio_resource_manager.h>
#include <chrono>
#include <cstdint>
#include <sstream>
OH_AudioStreamBuilder* builder;
OH_AudioRenderer* audioRenderer;
OH_AudioResourceManager *resMgr;
int32_t g_tokenId;
OH_AudioWorkgroup *grp = nullptr;
OH_AudioRenderer_Callbacks callbacks;
static OH_AudioData_Callback_Result MyOnWriteData_New(
OH_AudioRenderer* renderer,
void* userData,
void* audioData,
int32_t audioDataSize)
{
return AUDIO_DATA_CALLBACK_RESULT_VALID;
}
void MyOnInterruptEvent_New(
OH_AudioRenderer* renderer,
void* userData,
OH_AudioInterrupt_ForceType type,
OH_AudioInterrupt_Hint hint)
{
}
void MyOnError_New(
OH_AudioRenderer* renderer,
void* userData,
OH_AudioStream_Result error)
{
}
int32_t MyOnWriteDataWithMetadata_New(
OH_AudioRenderer* renderer,
void* userData,
void* audioData,
int32_t audioDataSize,
void* metadata,
int32_t metadataSize)
{
return 0;
}
int32_t MyOnWriteData_Legacy(
OH_AudioRenderer* renderer,
void* userData,
void* buffer,
int32_t length)
{
return 0;
}
int32_t MyOnInterruptEvent_Legacy(
OH_AudioRenderer* renderer,
void* userData,
OH_AudioInterrupt_ForceType type,
OH_AudioInterrupt_Hint hint)
{
return 0;
}
int32_t MyOnWriteDataWithMetadata_Legacy(
OH_AudioRenderer* renderer,
void* userData,
void* audioData,
int32_t audioDataSize,
void* metadata,
int32_t metadataSize)
{
return 0;
}
napi_value CreateAudioRender(napi_env env, napi_callback_info info)
{
OH_AudioStreamBuilder_Create(&builder, AUDIOSTREAM_TYPE_RENDERER);
const int SAMPLING_RATE_48K = 48000;
OH_AudioStreamBuilder_SetSamplingRate(builder, SAMPLING_RATE_48K);
const int channelCount = 2;
OH_AudioStreamBuilder_SetChannelCount(builder, channelCount);
OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
OH_AudioRenderer_OnInterruptCallback OnIntereruptCb = MyOnInterruptEvent_New;
OH_AudioStreamBuilder_SetRendererInterruptCallback(builder, OnIntereruptCb, nullptr);
OH_AudioRenderer_OnErrorCallback OnErrorCb = MyOnError_New;
OH_AudioStreamBuilder_SetRendererErrorCallback(builder, OnErrorCb, nullptr);
OH_AudioRenderer_OnWriteDataCallback writeDataCb = MyOnWriteData_New;
OH_AudioStreamBuilder_SetRendererWriteDataCallback(builder, writeDataCb, nullptr);
OH_AudioStream_LatencyMode latencyMode = AUDIOSTREAM_LATENCY_MODE_FAST;
OH_AudioStreamBuilder_SetLatencyMode(builder, latencyMode);
OH_AudioStreamBuilder_SetChannelLayout(builder, CH_LAYOUT_STEREO);
OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_AUDIOVIVID);
OH_AudioRenderer_WriteDataWithMetadataCallback metadataCallback = MyOnWriteDataWithMetadata_New;
OH_AudioStreamBuilder_SetWriteDataWithMetadataCallback(builder, metadataCallback, nullptr);
std::stringstream ss;
ss << "创建播放流成功\n";
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value DestroyAudioRender(napi_env env, napi_callback_info info)
{
std::stringstream ss;
if (builder) {
OH_AudioStreamBuilder_Destroy(builder);
ss << "销毁播放流成功";
}
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value SetVolume(napi_env env, napi_callback_info info)
{
float volume = 0.5f;
OH_AudioRenderer_SetVolume(audioRenderer, volume);
std::stringstream ss;
ss << "设置音量成功\n";
ss << "音量值: " << volume;
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value setLatencyMode(napi_env env, napi_callback_info info)
{
OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST);
std::stringstream ss;
ss << "设置时延模式成功\n";
ss << "模式: FAST";
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value getLatencyMode(napi_env env, napi_callback_info info)
{
OH_AudioStream_Result OH_AudioRenderer_GetLatencyMode
(OH_AudioRenderer *renderer, OH_AudioStream_LatencyMode *latencyMode);
std::stringstream ss;
ss << "获取时延模式成功\n";
ss << "当前模式: ";
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value workgroupcreate(napi_env env, napi_callback_info info)
{
OH_AudioManager_GetAudioResourceManager(&resMgr);
OH_AudioResourceManager_CreateWorkgroup(resMgr, "workgroup", &grp);
OH_AudioWorkgroup_AddCurrentThread(grp, &g_tokenId);
std::stringstream ss;
ss << "创建工作组成功\n";
ss << "工作组名: workgroup\n";
ss << "Token ID: " << g_tokenId;
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value workgroupprocess(napi_env env, napi_callback_info info)
{
constexpr static uint64_t intervalMs = 20;
bool threadShouldRun = true;
while (threadShouldRun) {
auto now = std::chrono::system_clock::now().time_since_epoch();
auto startTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
OH_AudioWorkgroup_Start(grp, startTimeMs, startTimeMs + intervalMs);
threadShouldRun = false;
OH_AudioWorkgroup_Stop(grp);
}
OH_AudioWorkgroup_RemoveThread(grp, g_tokenId);
OH_AudioResourceManager_ReleaseWorkgroup(resMgr, grp);
grp = nullptr;
std::stringstream ss;
ss << "工作组处理完成\n";
ss << "已释放工作组资源";
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value registcallback1(napi_env env, napi_callback_info info)
{
callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData_Legacy;
callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent_Legacy;
callbacks.OH_AudioRenderer_OnStreamEvent = nullptr;
callbacks.OH_AudioRenderer_OnError = nullptr;
std::stringstream ss;
ss << "注册回调函数1成功\n";
ss << "已配置写入数据和中断事件回调";
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value registcallback2(napi_env env, napi_callback_info info)
{
OH_AudioRenderer_Callbacks callbacks = {0};
callbacks.OH_AudioRenderer_OnWriteData = MyOnWriteData_Legacy;
callbacks.OH_AudioRenderer_OnInterruptEvent = MyOnInterruptEvent_Legacy;
std::stringstream ss;
ss << "注册回调函数2成功\n";
ss << "已使用memset初始化并配置回调";
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
napi_value CreateAudioRender02(napi_env env, napi_callback_info info)
{
OH_AudioStream_Type streamType = AUDIOSTREAM_TYPE_RENDERER;
OH_AudioStreamBuilder_Create(&builder, streamType);
const int SAMPLING_RATE_48K = 48000;
OH_AudioStreamBuilder_SetSamplingRate(builder, SAMPLING_RATE_48K);
const int channelCount = 2;
OH_AudioStreamBuilder_SetChannelCount(builder, channelCount);
OH_AudioStreamBuilder_SetSampleFormat(builder, AUDIOSTREAM_SAMPLE_S16LE);
OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_RAW);
OH_AudioStreamBuilder_SetRendererInfo(builder, AUDIOSTREAM_USAGE_MUSIC);
OH_AudioStreamBuilder_SetLatencyMode(builder, AUDIOSTREAM_LATENCY_MODE_FAST);
OH_AudioStreamBuilder_GenerateRenderer(builder, &audioRenderer);
OH_AudioStreamBuilder_SetEncodingType(builder, AUDIOSTREAM_ENCODING_TYPE_AUDIOVIVID);
OH_AudioRenderer_WriteDataWithMetadataCallback metadataCallback = MyOnWriteDataWithMetadata_Legacy;
OH_AudioStreamBuilder_SetWriteDataWithMetadataCallback(builder, metadataCallback, nullptr);
std::stringstream ss;
ss << "创建播放流02成功\n";
ss << "已配置AudioVivid编码和元数据回调";
napi_value retVal;
napi_create_string_utf8(env, ss.str().c_str(), NAPI_AUTO_LENGTH, &retVal);
return retVal;
}
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{
napi_property_descriptor desc[] = {
{"CreateAudioRender", nullptr, CreateAudioRender, nullptr, nullptr, nullptr, napi_default, nullptr},
{"DestroyAudioRender", nullptr, DestroyAudioRender, nullptr, nullptr, nullptr, napi_default, nullptr},
{"SetVolume", nullptr, SetVolume, nullptr, nullptr, nullptr, napi_default, nullptr},
{"setLatencyMode", nullptr, setLatencyMode, nullptr, nullptr, nullptr, napi_default, nullptr},
{"getLatencyMode", nullptr, getLatencyMode, nullptr, nullptr, nullptr, napi_default, nullptr},
{"workgroupcreate", nullptr, workgroupcreate, nullptr, nullptr, nullptr, napi_default, nullptr},
{"workgroupprocess", nullptr, workgroupprocess, nullptr, nullptr, nullptr, napi_default, nullptr},
{"registcallback1", nullptr, registcallback1, nullptr, nullptr, nullptr, napi_default, nullptr},
{"registcallback2", nullptr, registcallback2, nullptr, nullptr, nullptr, napi_default, nullptr},
{"CreateAudioRender02", nullptr, CreateAudioRender02, nullptr, nullptr, nullptr, napi_default, nullptr},
};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
EXTERN_C_END
static napi_module demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = Init,
.nm_modname = "entry",
.nm_priv = ((void *)0),
.reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }