我正在尝试运行sphinx 4 pre aplha的对话框演示,但它会出错。
我正在创建一个实时语音应用程序。
我使用maven导入了项目,并在堆栈溢出时遵循本指南:https://stackoverflow.com/a/25963020/2653162
错误说明有关16 khz和通道为单声道的问题。很明显它是关于抽样的东西。关于麦克风也是如此。
我看了如何将麦克风设置更改为16 khz和16 bit但是在Windows 7中没有这样的选项
:
问题是HelloWorld和对话框演示在sphinx4 1.06测试版中运行良好但在我尝试了最新版本之后它会出现以下错误:
Exception in thread "main" java.lang.IllegalStateException: javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 16000.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian not supported.
at edu.cmu.sphinx.api.Microphone.<init>(Microphone.java:38)
at edu.cmu.sphinx.api.SpeechSourceProvider.getMicrophone(SpeechSourceProvider.java:18)
at edu.cmu.sphinx.api.LiveSpeechRecognizer.<init>(LiveSpeechRecognizer.java:34)
at edu.cmu.sphinx.demo.dialog.Dialog.main(Dialog.java:145)
Caused by: javax.sound.sampled.LineUnavailableException: line with format PCM_SIGNED 16000.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian not supported.
at com.sun.media.sound.DirectAudioDevice$DirectDL.implOpen(DirectAudioDevice.java:513)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:121)
at com.sun.media.sound.AbstractDataLine.open(AbstractDataLine.java:413)
at edu.cmu.sphinx.api.Microphone.<init>(Microphone.java:36)
... 3 more
无法弄清楚如何解决问题。
答案 0 :(得分:5)
如果您修改<c:if test="${not empty param.error}">
<h1>TEST</h1>
</c:if>
以返回固定麦克风参考,则不会尝试创建多个麦克风参考,这是问题的根源。
SpeechSourceProvider
这里的问题是您不希望多个线程尝试访问单个资源,但是对于演示,识别器会根据需要停止并启动,这样他们就不会竞争麦克风
答案 1 :(得分:1)
正如Nickolay在source forge论坛(here)中解释的那样,麦克风资源需要由当前使用它的识别器释放,以便能够使用麦克风。在修复API时,我对sphinx API中的某些类进行了以下更改,作为临时解决方法。这可能不是最好的解决方案,在提出更好的解决方案之前猜测,这将有效。
我创建了一个名为MicrophoneExtention
的类,其源代码与Microphone
类相同,并添加了以下方法:
public void closeLine(){ line.close(); }
类似于LiveSpeechRecognizerExtention
类,源代码为LiveSpeechRecognizer
类,并进行了以下更改:
private final MicroPhoneExtention microphone;
microphone =new MicrophoneExtention(16000, 16, true, false);
public void closeRecognitionLine(){ microphone.closeLine(); }
最后,我编辑了DialogDemo
的主要方法。
Configuration configuration = new Configuration();
configuration.setAcousticModelPath(ACOUSTIC_MODEL);
configuration.setDictionaryPath(DICTIONARY_PATH);
configuration.setGrammarPath(GRAMMAR_PATH);
configuration.setUseGrammar(true);
configuration.setGrammarName("dialog");
LiveSpeechRecognizerExtention recognizer =
new LiveSpeechRecognizerExtention(configuration);
Recognizer.startRecognition(true);
while (true) {
System.out.println("Choose menu item:");
System.out.println("Example: go to the bank account");
System.out.println("Example: exit the program");
System.out.println("Example: weather forecast");
System.out.println("Example: digits\n");
String utterance = recognizer.getResult().getHypothesis();
if (utterance.startsWith("exit"))
break;
if (utterance.equals("digits")) {
recognizer.stopRecognition();
recognizer.closeRecognitionLine();
configuration.setGrammarName("digits.grxml");
recognizer=new LiveSpeechRecognizerExtention(configuration);
recognizeDigits(recognizer);
recognizer.closeRecognitionLine();
configuration.setGrammarName("dialog");
recognizer=new LiveSpeechRecognizerExtention(configuration);
recognizer.startRecognition(true);
}
if (utterance.equals("bank account")) {
recognizer.stopRecognition();
recognizerBankAccount(Recognizer);
recognizer.startRecognition(true);
}
if (utterance.endsWith("weather forecast")) {
recognizer.stopRecognition();
recognizer.closeRecognitionLine();
configuration.setUseGrammar(false);
configuration.setLanguageModelPath(LANGUAGE_MODEL);
recognizer=new LiveSpeechRecognizerExtention(configuration);
recognizeWeather(recognizer);
recognizer.closeRecognitionLine();
configuration.setUseGrammar(true);
configuration.setGrammarName("dialog");
recognizer=new LiveSpeechRecognizerExtention(configuration);
recognizer.startRecognition(true);
}
}
Recognizer.stopRecognition();
显然DialogDemo
中的方法签名需要改变......
希望这可以帮助...
最后,我不确定我所做的事情是否合法。如果我做错了什么,请善意地指出我的错误:D
答案 2 :(得分:0)
aetherwalker的答案对我有用 - 更详细地说,我用我自己的实现覆盖了以下文件,其中我只改变了使用过的SpeechSourceProvider:
第一个是AbstractSpeechRecognizer:
public class MaxAbstractSpeechRecognizer {
protected final Context context;
protected final Recognizer recognizer;
protected ClusteredDensityFileData clusters;
protected final MaxSpeechSourceProvider speechSourceProvider;
/**
* Constructs recognizer object using provided configuration.
* @param configuration initial configuration
* @throws IOException if IO went wrong
*/
public MaxAbstractSpeechRecognizer(Configuration configuration)
throws IOException
{
this(new Context(configuration));
}
protected MaxAbstractSpeechRecognizer(Context context) throws IOException {
this.context = context;
recognizer = context.getInstance(Recognizer.class);
speechSourceProvider = new MaxSpeechSourceProvider();
} .......................
然后是LiveSpeechRecognizer:
public class MaxLiveSpeechRecognizer extends MaxAbstractSpeechRecognizer {
private final Microphone microphone;
/**
* Constructs new live recognition object.
*
* @param configuration common configuration
* @throws IOException if model IO went wrong
*/
public MaxLiveSpeechRecognizer(Configuration configuration) throws IOException
{
super(configuration);
microphone = speechSourceProvider.getMicrophone();
context.getInstance(StreamDataSource.class)
.setInputStream(microphone.getStream());
}......................
最后但并非最不重要的是SpeechSourceProvider:
import edu.cmu.sphinx.api.Microphone;
public class MaxSpeechSourceProvider {
private static final Microphone mic = new Microphone(16000, 16, true, false);
Microphone getMicrophone() {
return mic;
}
}
答案 3 :(得分:0)
对我来说,问题在于只要我停留在cmusphinx的上下文中,这条线可以多次重复使用就很好了。但是,如果我开始将麦克风重新用于其他工作(例如录音),则该麦克风不可用!
我看到该流在“麦克风”类中处于打开状态,但从未关闭!
因此,我首先在类Microphone
中将以下属性从静态更改为动态:
private TargetDataLine line;
private InputStream inputStream;
在我更改了stopRecording方法以在行之前关闭流之后
/**
* close the stream and line
*/
public void stopRecording() {
if (inputStream != null )
try {
inputStream.close();
} catch (IOException e) {
throw new IllegalStateException(e);
}
line.stop();
}
现在,无需做任何更改(SpeechSourceProvider类是原始的),我就可以为cmupsphinx和其他录制任务重用mic了