package com.dronecontrol.leapcontrol.input.speech; import com.google.common.collect.Sets; import com.google.inject.Inject; import com.dronecontrol.droneapi.components.ThreadComponent; import com.dronecontrol.droneapi.injection.Context; import com.dronecontrol.leapcontrol.input.speech.data.SpeechData; import com.dronecontrol.leapcontrol.input.speech.listeners.SpeechListener; import edu.cmu.sphinx.frontend.util.Microphone; import edu.cmu.sphinx.recognizer.Recognizer; import edu.cmu.sphinx.result.Result; import edu.cmu.sphinx.util.props.ConfigurationManager; import org.apache.log4j.Logger; import java.util.Set; public class SpeechDetector implements Runnable { private static final String CONFIG_FILE_PATH = "command.config.xml"; private static final String RECOGNIZER = "recognizer"; private static final String MICROPHONE = "microphone"; private final Logger logger = Logger.getLogger(SpeechDetector.class); private final ThreadComponent threadComponent; private Set<SpeechListener> speechListeners; private Recognizer recognizer; private Microphone microphone; public static void main(String[] args) { SpeechDetector speechDetector = Context.getBean(SpeechDetector.class); speechDetector.start(); } @Inject public SpeechDetector(ThreadComponent threadComponent) { this.threadComponent = threadComponent; speechListeners = Sets.newHashSet(); initializeDetection(); } private void initializeDetection() { logger.info("Initializing speech detection"); ConfigurationManager configurationManager = new ConfigurationManager(SpeechDetector.class.getResource(CONFIG_FILE_PATH)); recognizer = (Recognizer) configurationManager.lookup(RECOGNIZER); microphone = (Microphone) configurationManager.lookup(MICROPHONE); recognizer.allocate(); } public void start() { logger.info("Starting speech recognition thread"); threadComponent.start(this); } public void stop() { logger.info("Ending speech recognition thread"); threadComponent.stop(); microphone.stopRecording(); recognizer.deallocate(); } @Override public void run() { logger.info("Starting speech recognition"); startMicrophone(); while (!threadComponent.isStopped()) { try { Result result = recognizer.recognize(); if (result != null) { processResult(result); } } catch (RuntimeException e) { // This happens when the recognizer is deallocated (which only happens when the stop() method was called) } } logger.info("Ending speech recognition"); } private void startMicrophone() { if (!microphone.startRecording()) { stop(); throw new IllegalStateException("Cannot start microphone"); } logger.info("Microphone is now listening"); } private void processResult(Result result) { SpeechData speechData = getSpeechData(result); if (speechData == null) { return; } logger.debug(String.format("Recognized speech input '%s'", speechData.getSentence())); for (SpeechListener listener : speechListeners) { listener.onSpeech(speechData); } } private SpeechData getSpeechData(Result result) { String resultText = result.getBestFinalResultNoFiller(); if ("".equals(resultText)) { return null; } return new SpeechData(resultText); } public void addSpeechListener(SpeechListener speechListener) { if (!speechListeners.contains(speechListener)) { speechListeners.add(speechListener); } } public void removeSpeechListener(SpeechListener speechListener) { if (speechListeners.contains(speechListener)) { speechListeners.remove(speechListener); } } }