0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用OpenHarmonyNDK移植三方库Speexdsp

OpenHarmony开发经验 来源:OpenHarmony开发经验 作者:OpenHarmony开发经验 2023-05-16 10:18 次阅读
  • 大家好,我是一名即将本科毕业的OpenHarmony开发者,去年暑假利用了两个月时间移植了一个语音处理的三方库Speexdsp到OpenHarmony标准系统。主要为其编写了build.gn使其加入了OpenHarmony编译体系(基于ninja和gn),Speexdsp在linux下是使用构建工具configure、makefile构建的。移植的难点并不在于.c和.h以及cflags、idflags的分析,而在于重新熟悉一套编译构建体系,而且当时可参考的资料并不太多。
  • 笔者最近为Speexdsp编写了CMakeLists.txt,使用OpenHarmony的NDK工具编译出来so动态库和可执行文件,并且成功在开发板上运行,现将经验分享如下:

speexdsp移植完毕已提交至openhamrony sig仓库:https://gitee.com/openharmony-sig/contest/tree/master/2022_OpenHarmony_thirdparty/speexdsp

(笔者也没想到会继续续写三方库方面的文章,学无止境,希望能够帮助更多人了解OpenHarmony,加入OpenHarmony生态)


  • NDK (原生开发套件) 是一套工具,使开发者能够在 OpenHarmony hap应用中使用 C/C++ 代码。它提供了一系列的工具可以帮助开发者快速的开发C/C++的动态库、静态库和可执行文件。
  • OpenHarmony 应用开发的Native C++开发方式就要依赖NDK。NDK被包含在OpenHarmony SDK中。可以在DevEco Studio使用 NDK 将 C/C ++ 代码编译到so库中,然后使用 DevEco Studio 的构建插件hvigor-ohos-plugin将so库打包到 Hap 中。ArkTS代码随后可以通过NAPI框架调用SO库中的函数。
  • 深开鸿郭岳峰老师开发的OCRDemo就通过NAPI调用了C++的三方库Tesseract的能力,而这个库本身还依赖leptonica、libjpeg、libpng、libtiff等C/C ++ 等四方库。如果重新编写build.gn移植到OpenHarmony,工作量巨大。

1. 编写build.gn与编写CMakeLists.txt移植到OpenHarmony两者的区别

  • 1、编译环境不同,编译工具
    • 编写build.gn方式,编译环境是在OpenHarmony源码中,编译时使用到的是源码中的编译工具。
    • 编写CMakeLists.txt的移植方式实际上是Native C++应用开发方式的一种,并且NDK是SDK的一部分,编译so时候实际上使用的是NDK的编译工具。
  • 2、so安装的地方不一样
    • 编写build.gn方式,三方库编译出来的so和测试用例可以打包进入OpenHarmony固件中。
    • 编写CMakeLists.txt方式,编译出来的实际上会被打包进入hap应用中,hap再安装到OpenHarmony操作系统上完成三方库so能力的调用。
  • 3、编写CMakeLists.txt比编写build.gn更容易
    • build.gn总有各种各样的编译器标志要加入以消除编译报错,开发者学习成本比较高
    • CMakeLists.txt方式开发者则相对熟悉,对于原生库就是camke构建的三方库,只需要对原生库已有的CMakeLists.txt做少量修改,比如删除与其他操作系统有关的部分(笔者说的就是AOSP)。

2. 使用OpenHarmony的NDK工具移植Speexdsp到Speexdsp

  • 在windows端的IDE上调用NDK
    • 创建Native C++工程,但是先不写NAPI和ArkTS的部分,先为C/C ++的三方库编写CMakeLists.txt(如果三方库本身就是cmake构建的,但也要对CMakeLists.txt进行少量的修改,详细请参考该样例 https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/FA/OCRDemo)。 然后编译hap应用来调用SDK中的NDK工具。

3. 创建Native C++工程使用SDK中的NDK工具

创建Native C++工程参考:三方库移植之NAPI开发[3]通过IDE开发NAPI工程

  • 1、打开IDE Deveco Studio,创建一个Native C++工程。

    image.png

  • 2、SDK选择API9,model选择Stage。新建的Native C++工程有一个默认的hello world教程

    image.png

3.1 将Speexdsp加入Native C++工程,在库中编写顶层CMakeLists.txt生成动态库

  • 1、将speexdsp源码移动到Native C++工程entry\\src\\main\\cpp目录,cpp目录专门用于存放C/C ++代码。

    image.png

  • 2、删除Speexdsp中无关的代码让代码结构简洁。Speexdsp中有一些无关的代码,例如和win32、macO上运行的有关代码,甚至还有塞班系统symbian上的代码。(不管了先删除,不知道Speexdsp的开源协议允不允许笔者这样做,但是看着乱乱的目录结构,笔者希望这样让自身的思路清晰一些。)

    image.png

# 目录结构说明
cpp
├─include               # .h文件
├─libspeexdsp           # .c文件
│   └─CMakeLists.txt    # 笔者编写的用来生成可执行文件库的CMakeLists.txt
├─BUILD.gn              # 笔者之前写的BUILD.gn,现在拿来参考写CMakeLists.txt
├─CMakeLists.txt        # 笔者编写的用来生成动态库的CMakeLists.txt
├─config.h              # Speexdsp原生库在linux下编译构建生成的配置文件
├─speexdsp_api.txt      # Speexdsp的api列表
└─speedsp_tested_api.txt
  • 3、编写顶层在CMakeLists.txt生成动态库

    image.png

# CMake的最小版本要求
cmake_minimum_required(VERSION 3.4.1)

# 脚本中set是将普通变量、缓存变量或者环境变量设置为指定的值。
# 从CMake v3.1开始,可以CMAKE_CXX_STANDARD变量设置C++标准
set(CMAKE_CXX_STANDARD 11)

# 项目名称
project(speexdsp)

# 添加cflags信息
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-implicit-function-declaration")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-sign")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-c99-extensions")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable")

# cflags信息
# 这个命令是针对所有类型编译器的,也就是说这里添加的选项会在所有的编译器中运用,比如-std=c++11是针对C++的编译器参数,也会被运用在C语言编译器中
# 通过在CMakeLists.txt文件中添加add_compile_options命令可以起到添加参数的作用
add_compile_options(-g -O2  -fvisibility=hidden -Wno-implicit-function-declaration -Wno-pointer-sign -Wno-c99-extensions -Wno-unused-variable)



# 头文件
set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")

# 设定编译宏 -D
add_definitions(-DHAVE_CONFIG_H)

############################################################
# 创建so动态库

# 源文件
# CMAKE_CURRENT_SOURCE_DIR指的CMakeLists.txt当前所在的目录
set(SHARED_LIB_SRC "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/preprocess.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/jitter.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/mdf.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/fftwrap.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/filterbank.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/resample.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/buffer.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/scal.c"
                   "${CMAKE_CURRENT_SOURCE_DIR}/libspeexdsp/smallft.c")

add_library(speexdsp SHARED ${SHARED_LIB_SRC})
target_include_directories(speexdsp PRIVATE ${INCLUDE_DIR})

############################################################

# 链接数学库-lm
# 如果为所有target统一指定编译时要链接的库用LINK_LIBRARIES
# 为每个target单独指定编译时要链接的库用TARGET_LINK_LIBRARIES
link_libraries(-lm)
target_link_libraries(speexdsp PUBLIC m)

# 使用add_subdirectory()将子目录添加到构建
add_subdirectory(libspeexdsp)

3.2 在库中编写底层CMakeLists.txt生成可执行文件,用来验证so库是否运行正常

  • 在.c源文件目录添加CMakeLists.txt用来编译出可执行文件,用来验证使用NDK移植三方库到OpenHarmony标准系统是否成功。如下:

屏幕截图 20230316 220059.png

cmake_minimum_required(VERSION 3.4.1)
project(test)

#生成执行二进制文件,生成testdenoise测试用例
ADD_EXECUTABLE(testdenoise testdenoise.c)
# 将二进制文件链接到生成的动态库
TARGET_LINK_LIBRARIES(testdenoise PUBLIC speexdsp)
# 将二进制文件链接的库文件
link_libraries(-lm)
# 添加编译器标志
add_compile_options(-g -O2  -fvisibility=hidden)

# 生成testecho测试用例
ADD_EXECUTABLE(testecho testecho.c)
TARGET_LINK_LIBRARIES(testecho PUBLIC speexdsp)
link_libraries(-lm)
add_compile_options(-g -O2  -fvisibility=hidden)

# 生成testjitter测试用例
ADD_EXECUTABLE(testjitter testjitter.c)
TARGET_LINK_LIBRARIES(testjitter PUBLIC speexdsp)
link_libraries(-lm)
add_compile_options(-g -O2  -fvisibility=hidden)

# 生成testresample测试用例
ADD_EXECUTABLE(testresample testresample.c)
TARGET_LINK_LIBRARIES(testresample PUBLIC speexdsp)
link_libraries(-lm)
add_compile_options(-g -O2  -fvisibility=hidden)

# 生成testresample2测试用例
ADD_EXECUTABLE(testresample2 testresample2.c)
TARGET_LINK_LIBRARIES(testresample2 PUBLIC speexdsp)
link_libraries(-lm)
add_compile_options(-g -O2  -fvisibility=hidden)

3.3 在库外的CMakeLists.txt中添加代码使能speexdsp编译

  • 1、 新建的Native C++工程是有一个默认的Hello World模板的,在entry\\src\\main\\cpp目录下有一个CMakeLists.txt,需要在其中添加代码使能speexdsp编译

    屏幕截图 20230317 104050.png

在entry\\src\\main\\cpp\\CMakeLists.txt中主要做两件事情

# 添加子目录speexdsp
add_subdirectory(speexdsp)

# 添加链接libspeexdsp.so动态库
# 把动态库libentry.so链接到动态库libspeexdsp.so
target_link_libraries(entry PUBLIC libace_napi.z.so speexdsp)
  • 2、如果不添加代码,则speexdsp的动态库和可执行用例编译不出来

3.4 执行编译命令编译动态库和测试用例

  • 1、在IDE上方工具栏选择编译hap进行so和测试用例的编译

    image.png

  • 2、编译结果在entry\\build\\default\\intermediates\\cmake\\default\\obj目录下

    屏幕截图 20230317 224016.png

├─arm64-v8a  
│      libc++_shared.so
│      libentry.so
│      libspeexdsp.so
│      testdenoise
│      testecho
│      testjitter
│      testresample
│      testresample2
│
└─armeabi-v7a
        libc++_shared.so
        libentry.so
        libspeexdsp.so
        testdenoise
        testecho
        testjitter
        testresample
        testresample2
  • 3、为什么会IDE中的NDK会编译出64位和32位的动态库和可执行文件呢?因为OpenHarmony操作系统有32位和64位,这样是为了hap能在不同位数的OpenHarmony版本上运行。

3.5 根据32位和64位的OpenHarmony版本推送相应的so和可执行文件到开发板上

如何分辨开发板上OpenHarmony版本是64位还是32位?和linux的方式是一样。用getconf WORD_BITgetconf LONG_BIT获得word和long的位数。64位系统中分别得到32和64。32位系统中分别得到32和32。

  • 1、笔者开发板上烧录的是32位的OpenHarmony Beta5版本

    image.png

    • 因此需要将Native C++工程目录下的entry\\build\\default\\intermediates\\cmake\\default\\obj\\armeabi-v7a中的libspeexdsp.so和testdenoise、testecho、testjitter、testresample、testresample2推送到设备端的data目录

      image.png

  • 2、通过与ohos版本匹配的hdc_std工具,将编译生成的库以及测试用的可执行文件推送到开发板的data目录

    image.png

hdc_std shell mount -o remount,rw /	    ## 重新加载系统为可读写
hdc_std file send testdenoise /data         ## 推送可执行文件testdenoise到data目录
hdc_std file send libspeexdsp /data         ## 推送libspeexsdp.so到data目录
  • 3、执行testdenoise可执行文件(其它测试用例的执行请参考 移植speexdsp到OpenHarmony标准系统⑤
    • 通过分析testdenoise.c源码,执行测试程序时需要指定一份输入的不为空的8000Hz的input.pcm音频,并且需要指定一份空的输出的output.pcm音频。rk3568上运行,执行语句如下:
./testdenoise < input.pcm > output.pcm

image.png

  • 4、测试结果:对比输入的input.pcm和输出的outpu.pcm的波形图和声谱图,噪声已经被消除。pc端和rk3568开发板运行testdenoise可执行程序效果一致。可执行文件运行成功,使用OpenHarmonyNDK移植三方库Speexdsp成功

    image.png

知识点附送

1、AIP8的应用如何更改为API9支持64位版本

1.1 API8只支持32位,API9支持32位和64位。

  • 以该PR https://gitee.com/openharmony/applications_app_samples/pulls/759 学习将api8应用适配适配Arm64

  • 1、修改build-profile.json5 ,将compileSdkVersioncompatibleSdkVersion属性由8改为9

    • compileSdkVersion指定OpenHarmony应用/服务编译时的SDK版本

    • compatibleSdkVersion指定OpenHarmony应用/服务兼容的最低SDK版本

      image.png

  • 2、修改entry/build-profile.json5,abi添加64位arm64-v8a

    • abiFilters用于设置本机的ABI编译环境

      image.png

  • 3、修改entry/src/main/config.json,设备类型改为默认

    image.png

  • 4、这个pr改动了XComponent/entry/src/main/cpp/common/plugin_common.h文件,plugin_common.h文件和hilog调试的功能有关。

2、编译构建子系统如何增加编译构建arm64选择

以该issue https://gitee.com/openharmony/build/issues/I53E9I 来学习

  • 分别在hb工具和build.sh脚本添加--target-cpu选项

电源服务子系统支持64位

https://gitee.com/openharmony/powermgr_power_manager/issues/I55094

graphic子系统适配64位编译

https://gitee.com/openharmony/graphic_graphic_2d/issues/I53720

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 移植
    +关注

    关注

    1

    文章

    376

    浏览量

    28089
  • 编译
    +关注

    关注

    0

    文章

    647

    浏览量

    32758
  • OpenHarmony
    +关注

    关注

    25

    文章

    3628

    浏览量

    16027
收藏 人收藏

    评论

    相关推荐

    三方移植OpenHarmony过程

    战码先锋,PR征集令(以下简称“战码先锋”)第二期正如火如荼地进行中,涉及OpenAtom OpenHarmony(以下简称“OpenHarmony”)主干仓、SIG仓、三方,共计1
    的头像 发表于 09-22 10:11 2549次阅读

    【润和软件DAYU200开发板体验】移植speexdspOpenHarmony标准系统⑤

    看下去的耐心,分享将以连载的方式进行。感谢润和软件提供的硬件支持。 下期预告:OAT开源扫描和三方上仓基本要求 本期为 移植speexdspOp
    的头像 发表于 10-12 10:09 1568次阅读
    【润和软件DAYU200开发板体验】<b class='flag-5'>移植</b><b class='flag-5'>speexdsp</b>到<b class='flag-5'>OpenHarmony</b>标准系统⑤

    【润和软件DAYU200开发板体验】移植speexdspOpenHarmony标准系统④

    看下去的耐心,分享将以连载的方式进行。 下期预告:speexdsp功能分析和功能测试 本期为 移植speexdspOpenHarmony标准系统 的第④期,主要内容如下: @ toc
    的头像 发表于 10-12 10:11 1814次阅读
    【润和软件DAYU200开发板体验】<b class='flag-5'>移植</b><b class='flag-5'>speexdsp</b>到<b class='flag-5'>OpenHarmony</b>标准系统④

    快速移植OpenHarmony三方芯片平台的方法

    移植概述本文面向希望将OpenHarmony移植三方芯片平台硬件的开发者,介绍一种借助三方芯片平台自带Linux内核的现有能力,快速
    发表于 04-12 11:08

    4步成功将三方——speexdsp移植OpenHarmony

    4步成功将三方——speexdsp移植OpenHarmony战码先锋,PR征集令(以下简称“战码先锋”)第二期正如火如荼地进行中,涉及O
    发表于 09-27 12:02

    OpenHarmony三方适配指南

    本文以OpenHarmony-3.2-Beta4上适配modbus编译动态为例。获取三方使用之前要做好代码溯源,确认可用的版本,开源许可和发布方式等。通过正确的路径获取源码,可以是
    发表于 04-07 09:12

    OpenAtom OpenHarmony 三方创建发布及安全隐私检测

    OpenAtom OpenHarmony三方(以下简称“三方”或“包”),是经过验证可在OpenHa
    发表于 11-13 17:27

    openharmony三方组件适配移植的多选列表功能教程

    项目介绍 项目名称:drag-select-recyclerview 所属系列:openharmony的第三方组件适配移植 功能:drag-select-recyclerview是一个简单的多选列表
    发表于 03-30 10:48 1次下载

    openharmony三方组件适配移植的股价图表

    项目介绍 项目名称:ikvStockChart 所属系列:openharmony的第三方组件适配移植 功能:ikvStockChart一个简单的openharmony图表
    发表于 04-01 09:30 2次下载

    openharmony三方组件适配移植的okhttp教程案例

    项目介绍 项目名称:okhttp 所属系列:openharmony的第三方组件适配移植 功能:PUT,DELETE,POST,GET等请求、文件的上传下载、加载图片(内部会图片大小自动压缩)、支持
    发表于 04-12 09:25 4次下载

    openharmony三方组件适配移植的数据组件

    项目介绍 项目名称:DBFlow 所属系列:openharmony的第三方组件适配移植 功能:DBFlow是一个快速、高效、功能丰富数据组件 项目
    发表于 04-13 09:56 2次下载

    总结移植三方OpenHarmony的经验

    三方主要是基于标准 Linux 系统的 c/c++ 开源,所以三方移植工作,首先是在标准
    的头像 发表于 05-07 15:52 5943次阅读

    移植speexdspOpenHarmony标准系统②

    由于想要分享的内容较多,为避免读者姥爷们失去看下去的耐心,分享将以连载的方式进行。 第一期请点击查看《移植speexdspOpenHarmony标准系统① 》,本期为移植
    的头像 发表于 11-30 09:10 853次阅读

    移植speexdspOpenHarmony标准系统的第③

    ://gitee.com/openharmony-sig/contest/tree/master/2022_OpenHarmony_thirdparty/speexdsp 四、将三方
    的头像 发表于 12-01 12:35 1095次阅读

    鸿蒙三方适配指南

    本文以 OpenHarmony-3.2-Beta4 上适配 modbus 编译动态为例。 获取三方 使用之前要做好代码溯源,确认可用的版本,开源许可和发布方式等。 通过正确的路径获
    的头像 发表于 02-14 09:33 3257次阅读