<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),并且会处理单词和发音之间偶尔出现的超过两个空格的情况。