kaldi中SHELL呼叫C 程式過程原始碼分析

2021-09-25 00:23:16 字數 3336 閱讀 4192

kaldi真正的核心原始碼,都是c++寫成的,這個結論可以從如下兩點得以確認:

(1)在kaldi的原始碼kaldi/src目錄下,能看到很多擴充套件名為.cc的源程式,這是linux下c++原始碼;

(2)在原始碼中,比如kaldi\src\featbin\compute-mfcc-feats.cc,可以看到static_caststd::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;

其中cmdrun.pl,這是perl程式。在kaldi/egs/yesno/s5/utils/run.pl開啟這個檔案,可以看到其用法描述如下:

@ar** < 2 && die "usage: run.pl log-file command-line arguments...";
可以看到,command-line就是具體的執行命令。所以,extract-segmentscompute-mfcc-featscopy-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...