Sphinx應用程序編寫


Pocketsphinx API 核心理念

     Pocketsphinx API 被設計是為了減輕編寫語音識別功能應用程序。

  1. 由於使用抽象類,所以在源代碼和二進制文件兼容方面,更能保持穩定。
  2. 因為它完全可重入,所以在同一進程中擁有多個編碼器也不會出現問題。
  3. 在運行時,新的語言模型的接口(在sphinxbase)支持線性多模型插值。
  4. 它能大幅度減少代碼量而且能明顯減少內存消耗。

相關文檔見:http://cmusphinx.sourceforge.net/api/pocketsphinx/

基本用法(hello world

你需要知道幾個關鍵的點如何使用應用程序接口(API):

  1. 命令行通過外部<cmd_ln.h>來解析;
  2. 一切都需要一個ps_decoder_t*作為第一個參數。

為了說明新的接口,我們將通過一個簡單的“hello world”的例子。這個例子為unix源文件和匯編程序。我們將創建一個叫hello_ps.c的C源文件。我們使用如下命令來編譯:

    gcc -o hello_ps hello_ps.c \

    -DMODELDIR=\"`pkg-config --variable=modeldir pocketsphinx`\"

`pkg-config --cflags --libs pocketsphinx sphinxbase`

請注意,編譯錯誤在這里意味着你沒有仔細閱讀教程和不遵循上述安裝指南。例如pocketsphinx需要通過pkg-config系統來正確安裝。為了檢查pocketsphinx正確安裝與否,只要在命令行運行 pkg-config --cflags --libs pocketsphinx sphinxbase 就可以從輸出結果看出。

-I/usr/local/include/sphinxbase  -I/usr/local/include/pocketsphinx 

-L/usr/local/lib -lpocketsphinx -lsphinxbase –lsphinxad

 

pkg-config --variable=modeldir pocketsphinx

顯示結果輸出:/usr/local/share/pocketsphinx/model

 

補充:gcc -o recog recog.c \-DMODELDIR=\"/usr/local/share/pocketsphinx/model\"  -I/usr/local/include/sphinxbase  -I/usr/local/include/pocketsphinx  -L/usr/local/lib -lpocketsphinx -lsphinxbase -lsphinxad

初始化

首先我們需要做的是創建一個配置對象,由於某種原因叫作cmd_ln_t。我們將按如下程序這樣做:

#include <pocketsphinx.h>

 

int main(int argc, char *argv[])

{

        ps_decoder_t *ps;

        cmd_ln_t *config;

 

        config = cmd_ln_init(NULL, ps_args(), TRUE,

                          "-hmm",MODELDIR "/hmm/en_US/ hub4wsj_sc_8k",

                          "-lm", MODELDIR "/lm/en/turtle.DMP",

                          "-dict", MODELDIR "/lm/en/turtle.dic",

                             NULL);

        if (config == NULL)

                return 1;

 

        return 0;

}

 

該cmd_ln_init()功能采用可變數目的空結束NULL的字符串參數。第一個參數是之前要更新的cmd_ln_t *。第二參數是一個數組參數定義—通過調用ps_args()來進行設置。第三個參數是一個標志,告訴參數解析器將是“嚴格”的—如果這是真的,然后重復的參數或未知參數會導致解析失敗。

該MODELDIR宏定義是在GCC命令行中使用pkg-config從PocketSphinx配置中獲得modeldir變量。在windows系統中,你可以簡單的增加一個預處理宏定義到代碼中,像這樣:

          #define MODELDIR "c:/sphinx/model"

(無論你的模型安裝在哪個目錄下),現在,為了初始化解碼器,使用ps_init如下:

ps = ps_init(config);

        if (ps == NULL)

                return 1;

 

解碼文件流

現在現場音頻輸入受到一些特定平台的影響,這將限制我們自已去解碼音頻文件。“turtle”語言模式識別的一個非常簡單的“robot control”語言,其中包括一些諸如“go forward ten meters”的短語。事實上,一個音頻文件包含在PocketSphinx源代碼的句子中。你可以在test/data/goforward.raw中找到。把它復制到當前目錄。如果你想創建自己的版本,需要一個單聲道,小端,無頭16-bit PCM有符號,采樣率為16KHZ的音頻文件。

 

為了這樣做,首先我們打開文件:

        FILE *fh;

 

        fh = fopen("goforward.raw", "rb");

        if (fh == NULL) {

                perror("Failed to open goforward.raw");

                return 1;

        }

然后使用ps_decode_raw()進行解碼:

        rv = ps_decode_raw(ps, fh, "goforward", -1);

        if (rv < 0)

                return 1;

現在,為了假設,我們可以使用ps_get_hyp():

        char const *hyp, *uttid;

        int rv;

        int32 score;

        hyp = ps_get_hyp(ps, &score, &uttid);

        if (hyp == NULL)

                return 1;

        printf("Recognized: %s\n", hyp);

從內存中解碼音頻數據

現在我們將再次解碼相同的文件,但是使用API從內存塊中解碼音頻數據。在這種情況下,首先我們需要使用ps_start_utt()開始說話:

        fseek(fh, 0, SEEK_SET);

        rv = ps_start_utt(ps, "goforward");

        if (rv < 0)

                return 1;

我們將每次從文件中讀取512大小的樣本,使用ps_process_raw()把它們放到解碼器中:

        int16 buf[512];

        while (!feof(fh)) {

            size_t nsamp;

            nsamp = fread(buf, 2, 512, fh);

            rv = ps_process_raw(ps, buf, nsamp, FALSE, FALSE);

        }

然后我們需要使用ps_end_utt()去標記說話的結尾處:

        rv = ps_end_utt(ps);

        if (rv < 0)

                return 1;

以相同精確的方式運行來檢索假設的字符串:

        hyp = ps_get_hyp(ps, &score, &uttid);

        if (hyp == NULL)

                return 1;

        printf("Recognized: %s\n", hyp);

清理

使用ps_free()對對象進行清理,返回使用ps_init()。你不應該釋放配置對象。

代碼清單

 1 #include <pocketsphinx.h>
 2 
 3 int main(int argc, char *argv[])
 4 {
 5     ps_decoder_t *ps;
 6     cmd_ln_t *config;
 7     FILE *fh;
 8     char const *hyp, *uttid;
 9         int16 buf[512];
10     int rv;
11     int32 score;
12 
13     config = cmd_ln_init(NULL, ps_args(), TRUE,
14                  "-hmm", MODELDIR "/hmm/en_US/hub4wsj_sc_8k",
15                  "-lm", MODELDIR "/lm/en/turtle.DMP",
16                  "-dict", MODELDIR "/lm/en/turtle.dic",
17                  NULL);
18     if (config == NULL)
19         return 1;
20     ps = ps_init(config);
21     if (ps == NULL)
22         return 1;
23 
24     fh = fopen("goforward.raw", "rb");
25     if (fh == NULL) {
26         perror("Failed to open goforward.raw");
27         return 1;
28     }
29 
30     rv = ps_decode_raw(ps, fh, "goforward", -1);
31     if (rv < 0)
32         return 1;
33     hyp = ps_get_hyp(ps, &score, &uttid);
34     if (hyp == NULL)
35         return 1;
36     printf("Recognized: %s\n", hyp);
37 
38         fseek(fh, 0, SEEK_SET);
39         rv = ps_start_utt(ps, "goforward");
40     if (rv < 0)
41         return 1;
42         while (!feof(fh)) {
43             size_t nsamp;
44             nsamp = fread(buf, 2, 512, fh);
45             rv = ps_process_raw(ps, buf, nsamp, FALSE, FALSE);
46         }
47         rv = ps_end_utt(ps);
48     if (rv < 0)
49         return 1;
50     hyp = ps_get_hyp(ps, &score, &uttid);
51     if (hyp == NULL)
52         return 1;
53     printf("Recognized: %s\n", hyp);
54 
55     fclose(fh);
56         ps_free(ps);
57     return 0;
58 }

高級用法

對於使用更復雜的老API,有一些明顯的不同地點:

  1. 得到部分和全部假設不再有單獨的功能;
  2. 詞語切分是通過訪問迭代器而不是返回的數組或列表;
  3. 語言模型的轉換是通過外部(<ngram_model.h>)。

首先這些都是簡單的。在這之前,你必須使用uttproc_partial_result()得到部分結果(例如在uttproc_end_utt()前),使用uttproc_result()得到全部結果。現在,ps_get_hyp()能工作在兩種方式下。

對於字的分割,API提供了一個遍歷所有字序列的迭代器對象。這個迭代器對象是一個抽象類,這個抽象類為一些訪問器提供獲取每個字的時間點,分數和(最有趣的)后驗概率。

最后,語言模型切換是完全不同的。解碼器總是與一個語言模型集對象聯系在一起。切換語言模型是通過以下:

  1. 得到一個句柄然后給語言模型集對象:ps_get_lmset()
  2. 選擇一個新的語言模型:ngram_model_set_select()
  3. 告訴解碼器語言模型集已更新:ps_update_lmset()

                                                                                                                                           翻譯於2011年9月21日

參考官網:http://cmusphinx.sourceforge.net/wiki/tuturialpocketsphinx


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM