Не удается получить доступ к микрофону во время запуска демонстрации Dialog в sphinx4 5prealpha

Я пытаюсь запустить диалоговое демо sphinx 4 pre aplha, но оно выдает ошибки.

Я создаю приложение для живой речи.

Я импортировал проект с помощью maven и следовал этому руководству по переполнению стека: /questions/43161008/cmu-sphinx-4-5-pre-alpha-rukovodstvo-po-ustanovke/43161012#43161012

Ошибка говорит о проблемах, касающихся 16 кГц и канала, являющегося моно. Так ясно, что о материале отбора проб. И это тоже говорит о микрофоне.

Я смотрел, как изменить настройки микрофона на 16 кГц и 16 бит, но в Windows 7 такой опции нет

:Только опции, доступные в 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

Не могу понять, что делать, чтобы решить проблему.

3 ответа

Если вы измените SpeechSourceProvider чтобы вернуть постоянную ссылку на микрофон, он не будет пытаться создать несколько ссылок на микрофон, что является источником проблемы.

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

    Microphone getMicrophone() {
        return mic;
    }
}

Проблема здесь в том, что вы не хотите, чтобы несколько потоков пытались получить доступ к одному ресурсу, но для демонстрации распознаватели останавливаются и запускаются по мере необходимости, так что они не все конкурируют за микрофон.

Как объясняет Николай на форуме кузницы источников ( здесь), ресурс микрофона должен быть освобожден распознавателем, использующим его в настоящее время, чтобы другой распознаватель мог использовать микрофон. Пока 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.setAcousticModelPath(ACOUSTIC_MODEL);
    configuration.setDictionaryPath(DICTIONARY_PATH);
    configuration.setGrammarPath(GRAMMAR_PATH);
    configuration.setUseGrammar(истина);

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

Ответ 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;
}
}

Для меня с этим изменением проблема заключалась в том, что пока я оставался в контексте cmusphinx, было хорошо, что линию можно использовать повторно много раз. Но если я начну повторно использовать микрофон для другой работы (например, для записи), он будет недоступен!
Я вижу, что поток был открыт в классе Microphone, но никогда не закрывался!

Итак, сначала я перехожу в класс 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 и другой задачи записи.

Другие вопросы по тегам