在sphinx4 5prealpha中运行Dialog演示时无法访问麦克风

时间:2015-03-18 11:45:48

标签: java cmusphinx sphinx4

我正在尝试运行sphinx 4 pre aplha的对话框演示,但它会出错。

我正在创建一个实时语音应用程序。

我使用maven导入了项目,并在堆栈溢出时遵循本指南:https://stackoverflow.com/a/25963020/2653162

错误说明有关16 khz和通道为单声道的问题。很明显它是关于抽样的东西。关于麦克风也是如此。

我看了如何将麦克风设置更改为16 khz和16 bit但是在Windows 7中没有这样的选项

 Only Options available in win 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

无法弄清楚如何解决问题。

4 个答案:

答案 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类,并进行了以下更改:

  • 使用我定义的MicrohphoneExtention类:
    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了