我以 Sphinx4 HelloWorld 为例,制作了自己的语法文件,其中包含“什么是病毒”或“什么是应用软件”之类的句子,简单的 JSGF 内容,我确实分别标记了每个句子,如下所示:
public <0> = What is number twelve |
What is twelve;
public <1> = What is the title bar;
public <2> = What is control |
What is the control key;
没有 n-gram,因为我不完全理解它,我不确定它是否适用于这样一个简单的例子(或者我认为它不适用)。无论如何,代码只是 HelloWorld.java 的复制粘贴,并且识别效果很好,我会说它大约 90% 准确。
现在我把这段代码放到一个 Runnable 中,启动了一个新线程,突然间识别率非常可怕,大约为 10%(十分之一是正确的)。
显然,我直接在应用程序中使用我的麦克风(内置笔记本电脑麦克风)捕捉声音,并且我看到了一些建议,即声音应该根据我使用的字典(这是标准 WSJ_8gau_13dCep_16k_40mel_130Hz_6800Hz)重新采样,所以我的第一个问题是:内置的mic.startRecording() 方法可以做到吗?- 这个问题的原因是在主线程上运行的HelloWorld似乎不需要重新采样?
我的第二个问题是我认为多线程会显着降低性能是否正确?如果是的话,有没有办法在不对代码进行大修的情况下解决这个问题?
为了记录,我问是因为我正在使用 SWT 和 Sphinx4 在 Java 中编写一个简单的类似 Jeopardy 的语音识别游戏,主应用程序在主线程上运行,而识别在另一个线程上运行。我目前使用 ZipCity 示例识别听众的方式,但即使它在主线程上运行,它的效果也很糟糕,所以我将跳到更简单的识别方式,这就是我进行 HelloWorld 测试的原因。
编辑:我忘了提到我通常在错误的准确性示例中得到空的结果文本
这是代码,尽管它与示例中的完全相同:
好的工作之一:
public class main_class {
public static void main(String[] args) {
ConfigurationManager cm;
cm = new ConfigurationManager(main_class.class.getResource("/jsapi_pr/res/sapi.config.xml"));
Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
recognizer.allocate();
// start the microphone or exit if the program if this is not possible
Microphone microphone = (Microphone) cm.lookup("microphone");
if (!microphone.startRecording()) {
System.out.println("Cannot start microphone.");
recognizer.deallocate();
System.exit(1);
}
// loop the recognition until the program exits.
while (true) {
System.out.println(recognizer.getState());
Result result = recognizer.recognize();
if (result != null) {
String resultText = result.getBestFinalResultNoFiller();
if(!resultText.isEmpty()) {
System.out.println("You said: " + resultText + '\n');
}
} else {
System.out.println("I can't hear what you said.\n");
}
}
}
工作不好的一个:
public class main_class {
public static void main(String[] args) {
runnable_test test = new runnable_test();
test.begin();
}
}
public class runnable_test implements Runnable {
@Override
public void run() {
ConfigurationManager cm;
cm = new ConfigurationManager(main_class.class.getResource("/jsapi_pr/res/sapi.config.xml"));
Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
recognizer.allocate();
// start the microphone or exit if the program if this is not possible
Microphone microphone = (Microphone) cm.lookup("microphone");
if (!microphone.startRecording()) {
System.out.println("Cannot start microphone.");
recognizer.deallocate();
System.exit(1);
}
// loop the recognition until the program exits.
while (true) {
System.out.println(recognizer.getState());
Result result = recognizer.recognize();
if (result != null) {
String resultText = result.getBestFinalResultNoFiller();
if(!resultText.isEmpty()) {
System.out.println("You said: " + resultText + '\n');
}
} else {
System.out.println("I can't hear what you said.\n");
}
}
}
public void begin() {
Thread thread = new Thread(this);
thread.start();
}
}
我会尽快尝试发布一些结果,但正如所说的第一个工作正常,第二个通常会触发 resultText.isEmpty(),即使它“识别”某些东西,它通常也是错误的。
EDIT2:我提高了麦克风的性能和音量,而且效果更好,但我仍然无法理解为什么会发生这种情况,因为正如我所说,在主线程中运行时,没有提高麦克风的结果仍然非常好。
主应用程序的性能也好得多,从 12 比 2 提高到 12 比 6。