隨著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 8000bool 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;
}