【起因】
眼馋稚晖君的pico语音助手。想着以后做毕设可能用到语音识别或至少可以增加项目实践经历。然后就动手去学习使用百度语音的SDK,然后逛着逛着百度发现了一个好玩的东西——kaldi,一款非常流行的开源语音识别AI工具。如果把它在自己的板子上搭起来,实现本地化的智能语音识别,好像有点牛逼的样子。(这位少年后面几天不太好过)。
然后就撸起袖子开始动手。移植过程花费一两天时间,有之前移植Bluez的经历在,移植过程的问题解决得还算顺利。结果将交叉编译好的代码放到imx6ull上测试运行时,状况百出,被卡了一个星期。。。但经过重重障碍,最后测试成功的那一刻,少年特别特别兴奋。
言归正传,先展示测试成功的效果图片:
声明一下环境:
【虚拟机系统】:ubuntu 16,arm交叉编译工具链
【硬件平台与准备】:I.MX6ULL开发板,一张SD卡(至少32G)
【项目代价】:头发与电脑硬盘(kaldi编译后有十几个G)
【安装kaldi依赖】
先参照kaldi目录下tools下的INSTALL,检查系统环境下的依赖:
extras/check_dependencies.sh #检查依赖
一般用sudo apt install xxx可以解决
【MKL安装】
有点波折:(cd-rom源引发的)
运行extras/install_mkl.sh时,报错;
E: Failed to fetch cdrom://Ubuntu 16.04.6 LTS _Xenial Xerus_ - Release amd64
解决:remove the CD-ROM (or or original installation media) from the sources.list
将/etc/apt/source.list中的cdrom条目注释,sudo apt-get update。
又报错:E: Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /va
解决:
sudo pkill -KILL appstreamcli
wget -P /tmp https://launchpad.net/ubuntu/+archive/primary/+files/appstream_0.9.4-1ubuntu1_amd64.deb https://launchpad.net/ubuntu/+archive/primary/+files/libappstream3_0.9.4-1ubuntu1_amd64.deb
sudo dpkg -i /tmp/appstream_0.9.4-1ubuntu1_amd64.deb /tmp/libappstream3_0.9.4-1ubuntu1_amd64.deb
【编译OpenBlas】
git下载命令:
git clone https://github.com/xianyi/OpenBLAS.git
基础线性代数子程序库
cd ./OpenBLAS
make TARGET=ARMV7 HOSTCC=gcc BINARY=32 CC=arm-linux-gnueabihf-gcc FC=arm-linux-gnueabihf-gfortran
make PREFIX=./install/ install
生成的库在目录OpenBLAS/install/下
【编译clapack】
clapack下载
版本:clapack-3.1.1.1
①cp make.inc.example make.inc,因为clapack的所有Makefile都是调用make.inc来配置编译环境的。
修改make.inc以下选项:
CC = arm-linux-gnueabihf-gcc
LOADER = arm-linux-gnueabihf-gcc
ARCH = arm-linux-gnueabihf-ar
RANLIB = arm-linux-gnueabihf-gcc-ranlib
BLASLIB = ../../libblas.a
LAPACKLIB = libclapack.a
②到BLAS/SRC下make,编译生成libblas.a静态库(生成的静态库在clapack的根目录下)
③到SRC下make,编译生成libclapack.a静态库
报错找不到xxx.o,实际原因是INSTALL下的文件还没有编译!
解决:
将SRC下的xx.o拷贝到INSTALL下。
或想办法先编译INSTALL下的文件。
拷贝libclapack.a,并重命令为liblapack.a:cp libclapack.a liblapack.a
③编译生成libf2c.a静态库
cd ./F2CLIBS/libf2c/
修改文件夹下的makefile文件:
注释该两行:
# ld -r -x -o $*.xxx $*.o
# mv $*.xxx $*.o
注释或修改如下几行:
libf2c.a: $(OFILES)
# ar r libf2c.a $?
# -ranlib libf2c.a
arm-linux-gnueabihf-ar r libf2c.a $?
arm-linux-gnueabihf-ranlib libf2c.a
注释如下部分中的两行:
arith.h: arithchk.c
$(CC) $(CFLAGS) -DNO_FPINIT arithchk.c -lm ||\
$(CC) -DNO_LONG_LONG $(CFLAGS) -DNO_FPINIT arithchk.c -lm
#./a.out >arith.h
#rm -f a.out arithchk.o
另外:删除所有关于uninit的部分,比如uninit.o uninit.c,大概有3处。
make
有如上输出表明编译成功,将F2CLIBS下的静态库拷贝到clapack根目录下
【编译Alsa】
clapack下载
版本:alsa-lib-1.1.7
配置:
CC=arm-linux-gnueabihf-gcc ./configure --enable-shared --prefix=/xxx/alsa-lib-1.1.7/install/ --host=arm-linux-gnueabihf
【编译portaudio】
版本:pa_stable_v190600_20161030
位置:解压到kaldi/tools目录下
配置:
CC=arm-linux-gnueabihf-gcc ./configure --enable-static --host=arm-linux-gnueabihf
输出结果中有"ALSA…no",则做以下操作需要修改makefile,手动添加alsa支持。
①CFLAGS中 -DSIZEOF_LONG的值修改为8,添加头文件搜索路径
-I/home/zhou/kaldi_asr/alsa-lib-1.1.7/build/include
②OTHER_OBJS中添加src/hostapi/alsa/pa_linux_alsa.o和src/common/pa_ringbuffer.o
③在如下位置添加第4和第5行的内容
for include in $(INCLUDES); do \
$(INSTALL_DATA) -m 644 $(top_srcdir)/include/$$include $(DESTDIR)$(includedir)/$$include; \
done
$(INSTALL_DATA) -m 644 $(top_srcdir)/src/common/pa_ringbuffer.h $(DESTDIR)$(includedir)/$$include;
$(INSTALL_DATA) -m 644 $(top_srcdir)/src/common/pa_memorybarrier.h $(DESTDIR)$(includedir)/$$include;
$(INSTALL) -d $(DESTDIR)$(libdir)/pkgconfig
④修改如下内容
INCLUDES = portaudio.h pa_linux_alsa.h
LDFLAGS = -L/home/zhou/kaldi_asr/alsa-lib-1.2.2/build/lib
LIBS = -lm -lpthread /home/zhou/kaldi_asr/alsa-lib-1.2.2/build/lib/libasound.so
CXX = arm-linux-gnueabihf-g++
AR = arm-linux-gnueabihf-ar
make
make PREFIX=pwd/install install
【编译openfst】
版本:openfst-1.6.7
位置:放到kaldi/tools下进行配置和编译
CXX=arm-linux-gnueabihf-g++ ./configure --prefix=`pwd` --enable-static --enable-shared --enable-ngram-fsts --host=arm-linux-gnueabihf LIBS="-ldl"
make,有报错:
arm-linux-gnueabihf-g++: internal compiler error: Killed (program cc1plus)
原因是机器内存不足,需要使用swap分区
(df -h 查看系统磁盘,没有可用的swap分区)
解决:
#创建临时swap分区
sudo dd if=/dev/zero of=/home/swap bs=64M count=16
sudo mkswap /home/swap
sudo swapon /home/swap
#重新执行编译
make
#关闭和删除临时分区
sudo swapoff /home/swap
sudo rm /home/swap
最后安装make install
和建立软链接:ln -s openfst-1.6.7 openfst
注意:其它比较新的版本对交叉编译的支持性不好。可能会报错,如
error: cannot run test program while cross compiling
交叉编译configure时候经常使用 --host
选项,但是在configure中有很多的测试程序是不可以在HOST上运行的,此时就有可能出现如上错误。
这个错误的解决的方式:根据提示定位configure中的内容,然后修改。可能需要①指定使用cache,或②按照报错提示去注释或修改configure文件。
【编译kaldi】
github repo:https://github.com/kaldi-asr/kaldi
准备:
①将lacpack根目录下生成的几个静态库拷贝到OpenBLAS/build/lib:cp clapack/*.a /OpenBLAS/build/lib
②进入src下,修改configure,注释如下内容
# If more than one library specified, or a conflict has been recorded above
# already, then add all deduced libraries as conflicting options (not all may
# be conflicting sensu stricto, but let the user deal with it).
#if [[ ${#mathlibs[@]} -gt 1 || $incompat ]]; then
# for libpfx in "${mathlibs[@]}"; do
# # Handle --mkl-libdir out of common pattern.
# [[ $libpfx == mkl && $MKLLIBDIR ]] && incompat+=(--mkl-libdir=)
# # All other switches follow the pattern --$libpfx-root.
# incompat+=(--$(lcase $libpfx)-root=)
# done
# failure "Incompatible configuration switches: ${incompat[@]}"
#fi
配置:
CXX=arm-linux-gnueabihf-g++ AR=arm-linux-gnueabihf-ar AS=arm-linux-gnueabihf-as RANLIB=arm-linux-gnuebihf-ranlib ./configure --static --use-cuda=no --openblas-root=/home/zhou/kaldi_asr/OpenBLAS/build --clapack-root=/home/zhou/kaldi_asr/OpenBLAS/build
修改kaldi.mk:
a. 增加修改工作如下,确保依赖的头文件和静态库的路径正确
b. 删除-msse和-msse2参数
c. 从OpenBLAS/lapack-netlib/LAPACKE/include拷贝如下几个文件到OpenBLAS/build/include
最后编译src下的文件,可能要半个小时左右
make depend -j4
make
0s… FAIL matrix-lib-test when cross-compiling
原因分析:
https://github.com/kaldi-asr/kaldi/issues/4137
some libraries have tests that run while building. Which is a problem if you’re cross-compiling. I assume the issue is that the tests fail because it’s built for a different architecture and the build system is trying to run it on the host.
解决:注释src/matrix/Makefile中的TESTFILES,即不进行测试。
【编译online解码器】
onlinebin现已停止维护,编译kaldi时默认编译online2bin工具集。但onlinebin比较简单,没有一大堆参数,可以用来测试。
修改src下online和onlinebin的Makefile文件
将其中的-lasound替换为/home/zhou/kaldi_asr/alsa-lib-1.2.2/build/lib/libasound.so
在onlinebin下make编译
编译后会生成解码器的两个可执行文件:online-gmm-decode-faster 和 online-wav-gmm-decode-faster。
【移植到开发板】
将整个kaldi拷贝到根文件系统,
将数据堂训练好的模型放到egs下
最后在开发板中进行测试工作(真正的坎):让kali在Linux开发板上运行起来~(测试运行篇)
交叉编译过程参考:
-
kaldi嵌入式平台的移植及实现:https://blog.csdn.net/cj1989111/article/details/84320162
-
树莓派上搭建(交叉编译):https://blog.csdn.net/qq_36707695/article/details/103224236