Search code examples
javakeypresskeylistenersphinx4

KeyListener isShiftDown() is reading shift is down when not


So I'm building a sphinx-4 program that will only listen when you hold down the shift button. This is so that I can prevent errors and only have it listen to me when I'm holding down the shift button. When I release the shift button, I want the program to wait until I hold it down again. The Program will then fully exit when ctrl-c is pressed. I'm doing this using a keylistener.

The problem I'm running into is that the program does start listening after I press the shift button, however it won't stop listening when I release it. I'm not sure what is wrong with my code. Here is what I have in my MKeyListener class I've created:

public class MKeyListener implements KeyListener {
    static ConfigurationManager cm;


    @Override
    public void keyTyped(KeyEvent e) {
        // TODO Auto-generated method stub
        System.out.println("Please hold down the shift button to have Sphinx listen.");
    }

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub



        if (e.getKeyCode() == KeyEvent.VK_SHIFT)
        {
            Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
            recognizer.allocate();
            // start the microphone or exit if the programm if this is not possible
            Microphone microphone = (Microphone) cm.lookup("microphone");
            if (!microphone.startRecording()) {
                System.out.println("Cannot start microphone.");
                recognizer.deallocate();
                System.exit(1);
            }

            System.out.println("Say: (Good morning | Hello) ( Bhiksha | Evandro | Paul | Philip | Rita | Will )");

            // loop the recognition until the programm exits.
            Boolean var = e.isShiftDown();
            while (var == true) {

                System.out.println("Start speaking. Press Ctrl-C to quit.\n");

                Result result = recognizer.recognize();

                if (result != null) {
                    String resultText = result.getBestFinalResultNoFiller();
                    System.out.println("You said: " + resultText + '\n');
                } else {
                    System.out.println("I can't hear what you said.\n");
                }
                var = e.isShiftDown();
                System.out.println(var);
            }
            recognizer.deallocate();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
        if (e.getKeyCode() == KeyEvent.VK_SHIFT)
        {
        Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
        recognizer.deallocate();
    }

Here is my main class I'm running:

public class HelloWorld extends MKeyListener implements KeyListener{

public static void main(String[] args) throws Exception {
    JTextField textField = new JTextField();
    textField.addKeyListener(new MKeyListener());
    JFrame jframe = new JFrame();
    jframe.add(textField);
    jframe.setSize(400, 350);
    jframe.setVisible(true);

    if (args.length > 0) {
        cm = new ConfigurationManager(args[0]);
    } else {
        cm = new ConfigurationManager(HelloWorld.class.getResource("helloworld.config.xml"));
    }



}

What am I doing wrong here?


Solution

  • Your approach seems very expensive. You are attempting to do things which seem both unnecessary and possibly problematic to do - though I am not an expert on Sphinx4

    I have written an application which did exactly the same thing (except it listened for space instead of shift). My approach was completely different and, I think, pretty lightweight.

    config.xml:

    <component name="keyPressedSpeechClassifier"
               type="package.KeyPressedSpeechClassifier">
    </component>
    
    <component name="epFrontEnd" type="edu.cmu.sphinx.frontend.FrontEnd">
        <propertylist name="pipeline">
            <item>microphone</item>
            <item>speechClassifier</item>
            <item>keyPressedSpeechClassifier</item>
            <item>speechMarker</item>
            <item>nonSpeechDataFilter</item>
            <item>premphasizer</item>
            <item>windower</item>
            <item>fft</item>
            <item>melFilterBank</item>
            <item>dct</item>
            <item>liveCMN</item>
            <item>featureExtraction</item>
        </propertylist>
      </component>
    

    KeyPressedSpeechClassifier:

    public class KeyPressedSpeechClassifier extends BaseDataProcessor {
    
        static KeyPressedSpeechClassifier _instance;
        public static KeyPressedSpeechClassifier getInstance() {return _instance;}
    
        LinkedList<Data> queue;
    
        volatile boolean isRecognitionEnabled = false;
    
        public KeyPressedSpeechClassifier() {
            queue = new LinkedList<Data>();
            _instance = this;
            System.out.println("KeyPressedSpeechClassifier created");
        }
    
        @Override
        public Data getData() throws DataProcessingException {
            Data data = getPredecessor().getData();
            if (data instanceof DoubleData) {
                DoubleData dd = (DoubleData) data;
                queue.push(new SpeechClassifiedData(dd, isRecognitionEnabled));
            } else if (data instanceof SpeechClassifiedData) {
                ((SpeechClassifiedData) data).setSpeech(isRecognitionEnabled);
                queue.push(data);
            } else {
                queue.push(data);
            }
            if (queue.isEmpty()) {
                return null;
            } else {
                return queue.pop();
            }
        }
    
        public void setRecognitionEnabled(boolean enabled) {
            this.isRecognitionEnabled = enabled;
        }
    }