瑞芯微Rockchip开发者社区
直播中

挽你何用

9年用户 842经验值
擅长:电源/新能源 MEMS/传感技术
私信 关注
[问答]

请问RNNoise是如何将模型接口并交叉组合到RK3308上的

请问RNNoise是如何将模型接口并交叉组合到RK3308上的?

回帖(1)

刘燕

2022-3-9 15:29:16
  做成接口
  RNNoise已经将推理过程整理成了一个函数(src/denoise.c中的rnnoise_process_frame函数),我们只需要写一个类,其中包含2~3个方法(构造函数、推理函数、析构函数)即可。
  比如我们创建rnnoise_inference.cpp与rnnoise_inference.h文件,构建Rnnoise类,其中包含一个构造函数和一个推理函数:
  rnnoise_inference.h
  #ifndef RNNOISE_INFERENCE
  #define RNNOISE_INFERENCE
  #include “rnnoise.h”
  class Rnnoise{
  private:
  DenoiseState *st;
  public:
  Rnnoise();
  double inference(float *x);
  };
  #endif
  rnnoise_inference.cpp
  #include “rnnoise_inference.h”
  Rnnoise::Rnnoise(){
  st = rnnoise_create(NULL);
  }
  double Rnnoise::inference(float *x){
  double vad_output = 1;
  vad_output = rnnoise_process_frame(this-》st, x, x);
  return vad_output;
  }
  使用方法(主要部分)
  #include “rnnoisevhd.h”
  int main(int argc, char **argv) {
  。..
  float vad = 1.0;
  Rnnoise rnnoise;
  while(1) {
  。..
  vad = rnnoise.inference(x); // x是单帧的音频数据(20ms帧长时就是长度为20*16的数组,读取x的过程可以参考RNNoise的例程)
  。..
  }
  。..
  }
  因为我只需要vad推理的结果,不需要denoise的结果,所以把inference函数写成这样。如果需要denoise后的音频的话对inference函数做微调即可。如果不需要音频,只需要denoise的22个频带增益的话,需要修改一下src/denoise.c中rnnoise_process_frame函数,将最后对音频进行调整的步骤删掉,并且return出22个频带增益。
  交叉编译
  编译出动态链接库
  因为rnnoise原始工程是使用工程根目录下的autogen.sh和configure文件进行编译,所以在运行configure的时候指定host=交叉编译链就好,运行完configure后再make一下,example文件夹中就会生成例程的rnnoise_demo可执行文件。
  但由于我们是要做成接口并且对接口进行交叉编译,并且我不太会改configure文件里的内容,所以我另外写了个CMakeLists.txt(我只会用CMakeLists。。。),单独编译。
  首先在工程根目录运行autogen.sh和configure,--host用于指定交叉编译链(注意不要加后面的“-gcc”或“-g++”),然后make。
  。/autogen.sh
  。/configure --host=aarch64-linux-gnu
  make clean
  make
  然后进入src文件夹, 修改compile.sh,将gcc替换为我们的交叉编译链。
  #!/bin/sh
  aarch64-linux-gnu-gcc -DTRAINING=1 -Wall -W -O3 -g -I.。/include denoise.c kiss_fft.c pitch.c celt_lpc.c rnn.c rnn_data.c -o denoise_training -lm
  然后运行compile.sh
  。/compile.sh
  此时会发现工程根目录下出现了个.lib的隐藏文件夹,其中的librnnoise.so.0我们稍后会用到。
  
  然后在工程根目录下创建一个CMakeLists.txt
  cmake_minimum_required(VERSION 3.10)
  project(aaa)
  set(CMAKE_CXX_FLAGS “${CMAKE_CXX_FLAGS} -std=c++11”)
  set(PATH ${PROJECT_SOURCE_DIR})
  SET(CMAKE_CXX_FLAGS_DEBUG “$ENV{CXXFLAGS} -O3 -Wall -g2 -ggdb”)
  SET(CMAKE_CXX_FLAGS_RELEASE “$ENV{CXXFLAGS}
  SET(CMAKE_BUILD_TYPE ”Debug“)
  message(${PATH})
  #RK3308
  set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
  set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
  set(RNNoise_DIR /home/rua/rnnoise)
  include_directories(${RNNoise_DIR}/examples)
  include_directories(${RNNoise_DIR}/include)
  include_directories(${RNNoise_DIR}/src)
  add_library(rrnoise SHARED ${RNNoise_DIR}/examples/rnnoise_inference.cpp)
  target_link_libraries(rrnoise ${RNNoise_DIR}/.libs/librnnoise.so.0)
  老四连。
  mkdir build
  cd build
  cmake 。.
  make
  build目录下会出现librrnoise.so文件。
  
  我们使用的时候需要用到build文件夹中的librrnoise.so文件,和前面生成的.lib文件夹中的librnnoise.so.0文件。
  使用编译出的动态链接库进行推理
  单独构建一个工程,目录如下
  
  build:编译例程的可执行文件用。
  data:存放测试用的音频文件。
  include:存放一些乱七八糟的.h头文件。
  lib:存放前文说到的两个动态链接库(librrnoise.so、librnnoise.so.0)。
  src:存放例程。
  首先将刚才RNNoise工程中include、src文件夹中所有的.h文件,和我们写的接口的rnnoise_inference.h文件通通复制进这里的include文件夹中。
  接着把librrnoise.so、librnnoise.so.0复制进lib文件夹中。
  然后在src文件夹中创建一个demo.cpp,编写例程代码(此过程省略)。
  最后写CMakeLists.txt并且进行编译。
  cmake_minimum_required(VERSION 3.10)
  project(aaa)
  set(CMAKE_CXX_FLAGS ”${CMAKE_CXX_FLAGS} -std=c++11“)
  set(PATH ${PROJECT_SOURCE_DIR})
  SET(CMAKE_CXX_FLAGS_DEBUG ”$ENV{CXXFLAGS} -O3 -Wall -g2 -ggdb“)
  SET(CMAKE_CXX_FLAGS_RELEASE ”$ENV{CXXFLAGS} -O3 -Wall -fPIC“)
  SET(CMAKE_BUILD_TYPE ”Debug“)
  message(${PATH})
  #RK3308
  set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
  set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
  set(RNNoise_DIR /home/rua/rnnoisevad)
  include_directories(${RNNoise_DIR}/include)
  add_executable(demo ${RNNoise_DIR}/src/demo.cpp)
  target_link_libraries(demo ${RNNoise_DIR}/lib/librrnoise.so)
  编译后在build文件夹中出现可执行文件
  
  随后把该可执行文件、lib文件夹中的两个动态链接库、我们需要处理的音频文件一起扔进板子里。
  
  将两个动态链接库所在的路径添加进查找路径。
  export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/.so
  然后运行可执行文件即可。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分