OpenHarmony NativeC++应用开发speexdsp噪声消除案例
随着5.0的版本的迭代升级,笔者感受到了开源鸿蒙前所未有大的版本更替速度。5.0出现了越来越多的C API可以调用,极大的方便了native c++应用的开发。笔者先将speexdsp噪声消除的案例分享,老规矩,还是开源!!!
开源地址:https://gitee.com/from-north-to-north/OpenHarmony_p7885/tree/3b8ffd1c5223688f0b1e1f011187a6a392b4fcdf/hap/easy_demo/speexdsp
编译好的hap:https://gitee.com/from-north-to-north/OpenHarmony_p7885/blob/3b8ffd1c5223688f0b1e1f011187a6a392b4fcdf/hap/easy_demo/speexdsp/hap/speexdsp.hap
声明:本案例基于 https://gitee.com/harmonyos_samples/audio-native 开源案例的基础上修改,增加speexdsp噪声消除功能
一、speexdsp交叉编译
https://gitcode.com/openharmony-sig/tpc_c_cplusplus/tree/master/community/speexdsp
教程请参考:
https://gitcode.com/openharmony-sig/tpc_c_cplusplus/blob/master/community/openssl_1_1_1w/docs/hap_integrate.md
二、核心实现代码
核心代码:https://gitee.com/from-north-to-north/OpenHarmony_p7885/blob/master/hap/easy_demo/speexdsp/entry/src/main/cpp/AudioRecording.cpp
#include <iostream>
#include <speex/speex_preprocess.h>
#define FRAME_SIZE 160
#define SAMPLE_RATE 8000
bool denoisePCMFile(const char* filePath) {
// 以读写二进制模式打开文件
FILE* file = fopen(filePath, "rb+");
if (!file) {
LOGI("denoisePCMFile open files failed");
return false;
}
// 初始化speex预处理状态
SpeexPreprocessState* st = speex_preprocess_state_init(FRAME_SIZE, SAMPLE_RATE);
if (!st) {
LOGI("denoisePCMFile 无法初始化speex预处理状态");
fclose(file);
return false;
}
// 设置降噪参数
int denoise = 1;
speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &denoise);
short frame[FRAME_SIZE];
size_t readSize;
while ((readSize = fread(frame, sizeof(short), FRAME_SIZE, file)) == FRAME_SIZE) {
// 对帧进行降噪处理
speex_preprocess_run(st, frame);
// 将文件指针移动到当前帧的起始位置
fseek(file, -static_cast<long>(readSize * sizeof(short)), SEEK_CUR);
// 将处理后的帧写回文件
fwrite(frame, sizeof(short), FRAME_SIZE, file);
}
// 释放speex预处理状态
speex_preprocess_state_destroy(st);
// 关闭文件
fclose(file);
LOGI("denoisePCMFile 降噪处理完成,已覆盖原文件");
return true;
}
napi_value DenoisePCMFile(napi_env env, napi_callback_info info) {
if ((nullptr == env) || (nullptr == info)) {
LOGE("GetUptime: env or info is null");
return nullptr;
}
napi_value thisArg;
if (napi_ok != napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr)) {
LOGE("GetUptime: napi_get_cb_info fail");
return nullptr;
}
std::string time ;
const char* filePath = "/data/storage/el2/base/haps/entry/files/oh_test_audio.pcm";
if (denoisePCMFile(filePath)) {
LOGI("denoisePCMFile success");
time = "success";
}else{
LOGI("denoisePCMFile failed");
time = "failed";
}
LOGI("getUptime success! %{public}s", time.c_str());
napi_value res;
napi_create_string_utf8(env, time.c_str(), strlen(time.c_str()), &res);
return res;
}