【问题标题】:Can't access microphone while running Dialog demo in sphinx4 5prealpha在 sphinx4 5prealpha 中运行对话框演示时无法访问麦克风
【发布时间】:2015-03-18 11:45:47
【问题描述】:

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

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

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

该错误说明有关 16 khz 和通道为单声道的问题。很明显它是关于采样的。并且还提到了麦克风。

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

:

问题是 HelloWorld 和对话框演示在 sphinx4 1.06 beta 中运行良好,但在我尝试了最新版本后,它给出了以下错误:

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

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

【问题讨论】:

  • @NikolayShmyrev 声卡是科胜讯 SmartAudio HD
  • 好的,对不起,这是 sphinx4 中的一个错误,识别器无法正确释放资源,Windows java 不允许第二次打开麦克风。
  • 我们跟踪器中的相关问题sourceforge.net/p/cmusphinx/bugs/412
  • 我会在未来几天内尝试修复它
  • @NikolayShmyrev 演示一次都没成功.....

标签: java cmusphinx sphinx4


【解决方案1】:

如果您修改 SpeechSourceProvider 以返回一个常量麦克风引用,它不会尝试创建多个麦克风引用,这是问题的根源。

public class SpeechSourceProvider {
    private static final Microphone mic = new Microphone(16000, 16, true, false);

    Microphone getMicrophone() {
        return mic;
    }
}

这里的问题是,您不希望多个线程尝试访问单个资源,但对于演示,识别器会根据需要停止和启动,这样它们就不会全部竞争麦克风。

【讨论】:

  • 这对我也有用。截至 2019 年,我刚刚克隆了 github 存储库并遇到了同样的问题。
【解决方案2】:

正如 Nickolay 在源伪造论坛 (here) 中解释的那样,麦克风资源需要由当前使用它的识别器释放,以便另一个识别器能够使用麦克风。在修复 API 的同时,我对 sphinx API 中的某些类进行了以下更改作为临时解决方法。这可能不是最好的解决方案,在提出更好的解决方案之前猜测,这会起作用。


我创建了一个名为MicrophoneExtention的类,其源代码与Microphone类相同,并添加了以下方法:

公共无效closeLine(){ line.close(); }

类似LiveSpeechRecognizerExtention类,源代码为LiveSpeechRecognizer类,做了如下改动:

  • 使用我定义的 MicrohphoneExtention 类:
    private final MicroPhoneExtention microphone;
  • 在构造函数内部,
    microphone =new MicrophoneExtention(16000, 16, true, false);
  • 并添加以下方法:
公共无效closeRecognitionLine(){ 麦克风.closeLine(); }



最后我编辑了DialogDemo的主要方法。

配置配置 = 新配置(); configuration.setAcousticModelPath(ACOUSTIC_MODEL); configuration.setDictionaryPath(DICTIONARY_PATH); configuration.setGrammarPath(GRAMMAR_PATH); 配置.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

【讨论】:

  • 我遵循了您的修改,当我现在运行时,我收到此错误:“java.lang.IllegalStateException: Expected state READY actual state DEALLOCATED at edu.cmu.sphinx.recognizer.Recognizer.checkState(Recognizer .java:134)"
  • 我不确定问题可能出在哪里,我的工作正常,调用堆栈上有什么?如果我没看错,识别器的解码器会抛出异常,而不是行。
  • 线程“主”java.lang.IllegalStateException 中的异常:edu.cmu 的 edu.cmu.sphinx.recognizer.Recognizer.checkState(Recognizer.java:134) 的预期状态 READY 实际状态 DEALLOCATED。 sphinx.recognizer.Recognizer.recognize(Recognizer.java:103) at edu.cmu.sphinx.recognizer.Recognizer.recognize(Recognizer.java:122) at edu.cmu.sphinx.api.AbstractSpeechRecognizer.getResult(AbstractSpeechRecognizer.java: 63) 在 edu.cmu.sphinx.demo.dialog.DialogDemo.main(DialogDemo.java:153)
  • 这是我得到的控制台输出
  • 确保语句的顺序正确。 1.停止识别 2.关闭线路 3.重新分配识别器 4.开始识别。 .........正如我所说,这对我来说很好..
【解决方案3】:

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;
}
}

【讨论】:

    【解决方案4】:

    对我来说,有了这个改变,问题是只要我停留在 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 和另一个录音任务重复使用麦克风

    【讨论】:

      猜你喜欢
      • 2014-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多