<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
有一個驚人的單詞和發音信息文件在卡內基·梅隆大學.超過 10 萬個單詞和變體。來自他們的網站:“它的條目對於語音識別和合成特別有用,因為它具有從單詞到它們在 ARPAbet 音素集中的發音的映射,ARPAbet 音素集是英語發音的標準。 當前音素集包含 39 個音素,元音帶有詞彙重音標記”。文件中的典型行如下所示
跑道 R AH1 N AH0 R AW2 ND
該文件易於使用;每行以單個換行符結尾,單詞與數據用兩個空格分隔,每個數據項由一個空格分隔。數據項在另一個文件中描述,該文件具有如下條目
Phoneme Example Translation ------- ------- ----------- AA odd AA D AE at AE T AH hut HH AH T AO ought AO Tfor 39 phonemes.
這是將 100K+ 單詞加載到關聯數組中的一些 JSL。
source = Load Text File( "$DESKTOP/grammar/cmudict-0.7b",charset("windows-1252") );symbols = Load Text File( "$DESKTOP/grammar/cmudict-0.7b.symbols" );symlist = Words( symbols, "\!n" );symPat = symlist; // make a copySubstitute Into( symPat, Expr( {} ), Expr( Pat Altern() ) ); // convert list to alternation patternsympat = Eval( sympat ); // build the pattern, oncelineEnding = "\!n";commentLine = ";" + Pat Break( lineEnding ) + lineEnding;dataLine = Pat Break( " " ) >> word + " " + Pat Repeat( " " + symPat ) >> pronounce[word] + lineEnding;pronounce = Associative Array();rc = Pat Match( source, Pat Pos( 0 ) + Pat Repeat( (dataLine | commentLine) + Pat Fence() ) + Pat R Pos( 0 ) );if( rc, Show( pronounce["ELEPHANTS"] ), print("failed"));pronounce["ELEPHANTS"] = " EH1 L AH0 F AH0 NT S";
第 1 行和第 2 行將下載的文件從桌面上的文件夾加載到 JSL 字符串中。這個巨大的文件有像上面的 RUNAROUND 例子那樣的條目。這個小文件的每一行都有一個音素。這些符號被加載到第 3 行的列表中。words() 函數使用換行符將文本拆分為單個單詞的列表。symlist 保存單詞,並在第 4 行在 sympat 中製作了一個副本。
在第 5 行,SubstituteInto() 操作逗號分隔字符串的 JSL 列表表達式,將其轉換為對 Pat Altern() 的 JSL 函數調用,其中包含逗號分隔字符串列表。第 6 行評估 Pat Altern() 函數,生成實際模式值。這大致相當於以某種方式構造這個 JSL 並對其進行評估:
sympat = "AA" | "AA0" | ... | "Z" | "ZH"; // 39 phonemes in all
操縱表達式是一個高級主題,並且可能非常有用。
第 7 行將一個簡單的換行符字符串分配給 JSL 變量。讀取變量名比轉義序列更容易。第 8 行描述了註釋行在大文件中的樣子。這是第 8 行將跳過的註釋塊:
;;; # CMUdict -- Major Version: 0.07;;; # ========================================================================;;; # Copyright (C) 1993-2015 Carnegie Mellon University. All rights reserved.;;; # Redistribution and use in source and binary forms, with or without;;; # modification, are permitted provided that the following conditions;;; # are met:;;; # 1. Redistributions of source code must retain the above copyright;;; # notice, this list of conditions and the following disclaimer.;;; # The contents of this file are deemed to be source code.;;; # 2. Redistributions in binary form must reproduce the above copyright;;; # notice, this list of conditions and the following disclaimer in;;; # the documentation and/or other materials provided with the;;; # distribution.;;; # This work was supported in part by funding from the Defense Advanced;;; # Research Projects Agency, the Office of Naval Research and the National;;; # Science Foundation of the United States of America, and by member;;; # companies of the Carnegie Mellon Sphinx Speech Consortium. We acknowledge;;; # the contributions of many volunteers to the expansion and improvement of;;; # this dictionary.;;; # THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND;;; # ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,;;; # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR;;; # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY;;; # NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,;;; # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT;;; # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,;;; # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY;;; # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT;;; # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE;;; # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
第 9 行描述了大文件中的數據行。第 9 行做了很多工作,又來了
dataLine = Pat Break( " " ) >> word + " " + Pat Repeat( " " + symPat ) >> pronounce[word] + lineEnding;
PatBreak() 將文本匹配到空白並將文本存儲在單詞.單詞後有兩個空格;其中一個在 patRepeat 之前匹配,其中一個在 patRepeat 第一次運行其模式時匹配。patRepeat 模式使用 symPat 來驗證每個音素;如果出現錯誤的音素,PatMatch 將失敗,並且只會加載關聯數組字典的一部分。
patRepeat 是貪婪的,會盡可能地吞噬空白和 symPat。當它到達 lineEnding 時,它不能再繼續,>> 立即賦值運算符將重複的匹配存儲到 pronounce[word] 中。魔法!用於索引pronounce的word的值是剛匹配的值!剛剛創建了一個字典條目!
第 10 行創建字典,一個關聯數組。在第9行定義好pattern後創建即可;該模式直到下一行才會運行。
pronounce = 關聯數組();
第 11 行:
rc = Pat Match( source, Pat Pos( 0 ) + Pat Repeat( (dataLine | commentLine) + Pat Fence() ) + Pat R Pos( 0 ) );
使用 PatPos 和 PatRpos 來確保匹配整個字符串。介於兩者之間的是另一個 PatRepeat,它一遍又一遍地解析數據行或註釋行 10 萬次以上。PatFence 是一種優化,告訴模式匹配器不要保存回溯信息。如果模式失敗,接近尾聲,回溯將允許匹配器備份並嘗試不同的選擇。對於這個文件,那將毫無意義,而且保存所有回溯信息所需的內存會很大。PatFence 提示加快了速度。
發音[“斑馬”]
" Z IY1 BR AH0"
發音[“AARDVARK”]
“ AA1 RDV AA2 R K”
發音[“SUPERCALIFRAGILISTICEXPEALIDOSHUS”]
“ S UW2 P ER0 K AE2 L AH0 FR AE1 JH AH0 L IH2 ST IH0 K EH2 KSP IY0 AE2 L AH0 D OW1 SH AH0 S”
根據您下載 CMU 數據的位置,行尾和間距可能會很亂。 以下應該更好地處理它。
source = Load Text File( "z:/cmudict-0.7b.txt",charset("windows-1252") );
symbols = Load Text File( "z:/cmudict-0.7b.symbols.txt" );
symlist = Words( symbols, "\!n" );
symPat = symlist; // make a copy
Substitute Into( symPat, Expr( {} ), Expr( Pat Altern() ) ); // convert list to alternation pattern
sympat = Eval( sympat ); // build the pattern, once
lineEnding = "\!n\!r";
commentLine = ";;;" + Pat Break( lineEnding ) + patspan(lineEnding);
dataLine = Pat Break( " " ) >> word + " " + Pat Repeat( patspan(" ") + symPat ) >> pronounce[word] + patspan(lineEnding);
pronounce = Associative Array();
rc = Pat Match( source, Pat Pos( 0 ) + Pat Repeat( (dataLine | commentLine ) + Pat Fence() ) + Pat R Pos( 0 ) );
if( rc, Show( pronounce["ELEPHANTS"] ), print("failed"));它應該更健壯一些,因為它會處理行尾的許多 CR 和 LF 組合(不僅僅是 LF),並且會處理單詞和發音之間偶爾出現的超過兩個空格的情況。