kaldi真正的核心原始碼,都是c++寫成的,這個結論可以從如下兩點得以確認:
(1)在kaldi的原始碼kaldi/src
目錄下,能看到很多擴充套件名為.cc
的源程式,這是linux下c++原始碼;
(2)在原始碼中,比如kaldi\src\featbin\compute-mfcc-feats.cc
,可以看到static_cast
和std::string
這樣的**,這是c++特有的語法。
但是我們是怎麼使用kaldi的呢,是直接呼叫這些c++程式?
有過kaldi使用經驗的人都知道,kaldi的使用,並不是直接寫c++/python程式來呼叫c++原始碼/動態鏈結庫。而是通過寫shell程式,來使用kaldi提供的各項功能(比如提取音訊的mfcc特徵)。
那問題就來了,我們寫的shell程式,是怎麼呼叫這些c++程式的呢? 下面我們就以kaldi中的經典入門例子kaldi/egs/yesno/s5
為例,分析其中的關鍵原始碼,從而回答這個問題。
首先,我們進入kaldi/egs/yesno/s5
目錄,執行其中的run.sh
,看一下例程執行的結果。
# feature extraction
for x in train_yesno test_yesno; do
steps/make_mfcc.sh --nj 1 data/$x exp/make_mfcc/$x mfcc
steps/compute_cmvn_stats.sh data/$x exp/make_mfcc/$x mfcc
utils/fix_data_dir.sh data/$x
done
可以看到,提取mfcc特徵,是呼叫了steps/make_mfcc.sh
。
繼續看檔案steps/make_mfcc.sh
,其中大部分**都在做檔案目錄配置,引數配置,但能看到如下**段:
$cmd job=1:$nj $logdir/make_mfcc_$.job.log \
extract-segments scp,p:$scp $logdir/segments.job ark:- \| \
compute-mfcc-feats $vtln_opts --verbose=2 --config=$mfcc_config ark:- ark:- \| \
copy-feats --compress=$compress $write_num_frames_opt ark:- \
ark,scp:$mfccdir/raw_mfcc_$name.job.ark,$mfccdir/raw_mfcc_$name.job.scp \
|| exit 1;
其中cmd
為run.pl
,這是perl程式。在kaldi/egs/yesno/s5/utils/run.pl
開啟這個檔案,可以看到其用法描述如下:
@ar** < 2 && die "usage: run.pl log-file command-line arguments...";
可以看到,command-line就是具體的執行命令。所以,extract-segments
,compute-mfcc-feats
和copy-feats
就是該shell/perl呼叫的最終命令。
以compute-mfcc-feats
為例進行分析。首先,可以肯定這不是linux自帶的命令。用如下cmd搜尋一下看它在什麼位置,並檢視其屬性:
kaldi# find . -name compute-mfcc-feats
./src/featbin/compute-mfcc-feats
kaldi# ll -h src/featbin/compute-mfcc-feats
-rwxr-xr-x 1 root root 2.3m apr 29 21:39 src/featbin/compute-mfcc-feats*
可以看到compute-mfcc-feats
就是可執行檔案。如果這個檔案是用kaldi的c++原始碼編譯出來的,那它應該在makefile裡有描述。用如下命令搜出內容中含有compute-mfcc-feats
的所有檔案:
kaldi# grep -rnw . -e "compute-mfcc-feats"
./src/featbin/.depend.mk:7225:compute-mfcc-feats.o: compute-mfcc-feats.cc /usr/include/stdc-predef.h \
./src/featbin/makefile:10: compute-fbank-feats compute-kaldi-pitch-feats compute-mfcc-feats \
./src/featbin/compute-mfcc-feats.cc:1:// featbin/compute-mfcc-feats.cc
./src/featbin/compute-mfcc-feats.cc:31: "usage: compute-mfcc-feats [options...] \n";
可見,在src/featbin/makefile
中,確實寫到了compute-mfcc-feats
。開啟這個makefile檔案,可以看到,上文command-line中的三個命令,都是由這個makefile描述來生成的:
binfiles =
compute-mfcc-feats \
extract-segments \
copy-feats \
在這個makefile所在的目錄下,還能找到compute-mfcc-feats.cc
,這就是抽取mfcc特徵的c++**。可以看到compute-mfcc-feats
命令的引數解析過程,都是在改c++**中實現的。
以kaldi中提取mfcc特徵的功能為例,通過分析該過程原始碼(shell/perl/c++),發現了kaldi中shell呼叫c++原始碼的過程:c++編譯為可執行檔案,shell中呼叫這個可執行檔案。
如果你想改動kaldi的某些過程(比如mfcc提取過程),需要修改其c++原始碼,而不是shell。
如果你想為kaldi新增新的功能,需要寫好c++和makefile,生成可執行檔案,再通過shell來呼叫這個可執行檔案。
QT Creator 中C 呼叫python程式
在專案的.pro檔案中加入pyhon的標頭檔案路徑和庫路徑 includepath c python python36 include libs lc python python36 libs lpython36 當然路徑要換成自己的路徑 其中libs lc python python36 libs...
協程中呼叫阻塞函式
from concurrent.futures import threadpoolexecutor from tornado import gen threadpool threadpoolexecutor 2 def mysleep count import time for i in range...
Linux C中呼叫shell命令
很多時候我們需要在我們所編寫的c程式當中,呼叫一行命令,在命令列執行的命令,比如ifconfig,ls,或者是其他需要的命令如mpirun machinefile host np mpi並行程式 等等,這就要求我們能夠在linux下呼叫shell命令。linux的c就為我們提供了乙個可以呼叫shel...