Sphinx4 won't recognize full speech if .wav file duration is long - java

We are doing a project which user's answers are saved as .wav files and evaluated after. We have created grammars for each and every question. There are two questions we are having a recognition problem. Problems are probably the same since user must speak approximately 7-8 seconds for both of these questions.
This is the grammar file that we are using for one of the questions;
#JSGF V1.0;grammar Question8; public <Question8> = ( one hundred | ninety three | eighty six | seventy nine | seventy two | sixty five) * ;
Here, user must count numbers backwards by 7s. It recognizes fine if I speak too fast. When I speak slowly, for instance after saying "one hundred" and wait for 1 second and carry on until sixty five like this, it will only recognize one hundred and it won't recognize other words.
Two main parts are responsible for these processes:
The class that we created for microphone;
public final class SpeechRecorder {
static Configuration configuration = new Configuration();
static Microphone mic = new Microphone(16000, 16, 1, true, true, false, 10, true, "average", 0, "default", 6400);
public static void startMic() {
mic.initialize();
mic.startRecording();
mic.getAudioFormat();
mic.getUtterance();
System.out.println("Audio Format is" + mic.getAudioFormat());
}
public static void stopMic(String questionName) {
mic.stopRecording();
Utterance u = mic.getUtterance();
try {
u.save("Resources/Answers/" + questionName + ".wav", AudioFileFormat.Type.WAVE);
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getAnswersOfSpeech(String question) throws IOException {
Evaluation.disableLogMessages();
configuration.setAcousticModelPath("resource:/edu/cmu/sphinx/models/en-us/en-us");
configuration.setDictionaryPath("resource:/edu/cmu/sphinx/models/en-us/cmudict-en-us.dict");
configuration.setGrammarPath("resource:/Grammer");
configuration.setGrammarName(question);
configuration.setUseGrammar(true);
StreamSpeechRecognizer recognizer = new StreamSpeechRecognizer(configuration);
recognizer.startRecognition(new FileInputStream("Resources/Answers/" + question + ".wav"));
SpeechResult Result = recognizer.getResult();
String speechWords = Result.getHypothesis();
return speechWords;
}
public static String getSavedAnswer(int question) {
return User.getAnswers(question);
}
}
This is where we save user's answer as .wav files into our resources.
btn_microphone.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
click++;
if (click % 2 == 1) {
SpeechRecorder.startMic();
btn_microphone.setIcon(new ImageIcon("Resources/Images/record.png"));
} else {
SpeechRecorder.stopMic("Question" + Integer.toString(question));
btn_Next.setVisible(true);
btn_microphone.setIcon(new ImageIcon("Resources/Images/microphone.png"));
lbl_speechAnswer.setVisible(true);
try {
userAnswer = SpeechRecorder.getAnswersOfSpeech("Question" + Integer.toString(question));
} catch (IOException e1) {
e1.printStackTrace();
}
if (userAnswer.equals("")) {
lbl_speechAnswer.setText(
"<html>No answer was given, click on microphone button to record again</html>");
} else {
lbl_speechAnswer.setText("<html>Your answer is " + userAnswer
+ ", click on microphone button to record again</html>");
}
}
}
});
I don't how can we overcome this problem. I would be so grateful if anyone could help me.

You need a loop as in transcriber demo:
while ((result = recognizer.getResult()) != null) {
System.out.format("Hypothesis: %s\n", result.getHypothesis());
}
recognizer.stopRecognition();

Related

JFugue converts midi file incorrectly

(using jfugue 5.0.9) I wanted to convert .mid to .txt (staccato), and later to .mid again, to confirm conversions worked. Both .mid (original and converted) should be equal ideally, but the converted (midi -> staccato -> midi) file has weird delayed notes, and one enlargened note duration. JFugue probably struggles because the midi is a human, hyper-sensible recording. Is there any way to fix this?
Heres the 3 files https://drive.google.com/drive/folders/1DepX0lCqNaIRCoHRfGwBRsO1xRFCbCpl?usp=sharing
And here are the 2 methods used:
public static Pattern convMidToStac(String fileName, boolean makeAFile) {
Pattern p = new Pattern();
// Convert midi file to a JFugue Staccato pattern.
try {
p = MidiFileManager.loadPatternFromMidi(new File("D:/eclipse-workspace/MidiReader/" + fileName + ".mid"));
if (makeAFile) {
makeFile(fileName, p.toString());
}
return p;
} catch (Exception e) {
System.out.println("An error occurred.");
e.printStackTrace();
return null;
}
}
public static void convStacToMid(String fileName) {
Pattern p = new Pattern();
try {
p = MidiFileManager.loadPatternFromMidi(new File("D:/eclipse-workspace/MidiReader/" + fileName + ".mid"));
File filePath = new File("D:/eclipse-workspace/MidiReader/" + fileName + "MIDI.mid");
MidiFileManager.savePatternToMidi(p, filePath);
} catch (Exception e) {
e.printStackTrace();
}
}

TimerTask stops running after midnight

I have a small part of the program that has a timer to take a picture using a usb webcamera through the command line (fswebcam) every 15 minutes.
The code is like this:
public static final String HOME_DIR = System.getProperty("user.home") + "/";
public static final String PGP_DIR = HOME_DIR + "PGP/";
public static final String COLLECTION_DATA_DIR = PGP_DIR + "collectionData/";
public static final String SENSOR_CALIBRATION_DATA = PGP_DIR + "sensorCalibration/";
public static final String PICTURE_DIR = PGP_DIR + "pictures/";
public static final String ALARM_DIR = PGP_DIR + "alarms/";
private class PictureTakerTask extends TimerTask{
Timer t;
public void start(){
if(t != null){
t.cancel();
t.purge();
t = null;
this.cancel();
}
t = new Timer(true);
t.scheduleAtFixedRate(this, 0, 1000 * 60 * 15); //takes a picture every 15 minutes
}
public void stop(){
if(running) return;
if(t != null){
t.cancel();
t.purge();
t = null;
}
this.cancel();
}
#Override
public void run() {
String filename = getPictureFilename();
if(filename == null) return;
Process p;
try {
CommIO.printLog("Taking a picture");
String file;
light.setGreenPWM(80);
p = Runtime.getRuntime().exec("fswebcam -r 1920x1080 --no-banner -S 1 " + filename);
p.waitFor();
System.out.println ("picture taken with exit value: " + p.exitValue());
p.destroy();
light.setGreenPWM(0);
} catch (Exception e) {
e.printStackTrace();
light.setGreenPWM(0);
}
}
private String getPictureFilename(){
//make folder if it doesn't exist already
SimpleDateFormat justDate = new SimpleDateFormat("MM-dd-yy");
String date = justDate.format(new Date());
String s = PICTURE_DIR + date + "/";
File picDir = new File(s);
if(!picDir.exists()){
if(picDir.mkdir()){
Alert alert = new Alert(AlertType.ERROR, "Couldn't make picture directory: " + s, ButtonType.OK);
}
}
//find an unused filename
String picFileName = s + "plant_01.jpg";
File tempFile = new File(picFileName);
int i = 1;
while (tempFile.exists()) { //finds the next nonexistent name for data spreadsheet
String num = i < 10 ? "0" + i : "" + i;
picFileName = s + "plant_" + num + ".jpg";
i++;
tempFile = new File(picFileName);
if(i > 10000) break;
}
return picFileName;
}
}
The thread starts and works fine, until midnight exactly. It will fail to take pictures the next day. I can't figure out for the life of me why it stops. If I stop and restart the task it will work fine again. If I even take a picture through the terminal outside the program it will work fine again. It just will quit taking pictures by the next day. It even creates the next day's folder, just no pictures. No error messages (that I can find).
Does anybody have any ideas or experience with this? Before you say it, no I can't use motion or Cron because I need to be synchronized with the "light" object in the run() function.
Answering my own question. Simple mistake, actually:
if(picDir.mkdir()){
Alert alert = new Alert(AlertType.ERROR, "Couldn't make picture directory: " + s, ButtonType.OK);
}
Forgot the negation of condition. I usually run the program more than once in a day to check other changes, so it makes the folder on the first time, crashes the thread, and runs fine the next couple times I start the program. But when the next day comes around, it makes an Alert and throws a tantrum because it's not on the FX thread. It was difficult to notice because I forgot to actually even show the Alert.
I love java-fx, but it can be so finicky sometimes. Fixed by adding negation, and putting the alert into a Platform.runLater Runnable.
You could try and set the time to 12:00:01am at 11:59:59pm. I'm not sure if that would fix it. A while loop could work.

JavaFX concurrency freezing ui

i am looking into JavaFX now, specifically into concurrency. As my homework i decided to do an app, of which one of the functions is to read text file. For reference i used core java bonus chapter which is not in the book but available on website of horstmann (v1ch13fx.uitask.TaskDemo) and after finishing i tried it out and encountered an issue - the whole UI freezes together with reading the file, can be between few seconds and few minutes. Unless what i learned was not correct and just nonsense, shouldn't doing the reading on separate thread from UI prevent this from happening?
Can anyone who unedrstands this better have a look and tell me whether there is some problem with the code itself (tried same task with the app written by horstmann and same issue appears though) and advise me of any ways i could deal with this issue?
No matter what i do issue is the same, second day im at it now looking for sources online. Is it an issue with the code itself, or the concept of the task? And in the end this runs on damn powerful machine, which makes the headache even bigger.
public static void read(Stage stage, TextArea textArea, Label status, MenuItem open, MenuItem clear) {
if(task != null) return;
FileChooser chooser = new FileChooser();
chooser.setInitialDirectory(new File(".."));
chooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("Text files", "*.txt"));
File file = chooser.showOpenDialog(stage);
if(file == null) return;
textArea.clear();
task = new Task<>() {
public Integer call() {
int lines = 0;
try(BufferedReader br = new BufferedReader(new FileReader(file))) {
while(br.readLine() != null) {
String line = br.readLine();
Platform.runLater(() -> textArea.appendText(line + " \n"));
lines++;
updateMessage(lines + " lines read.");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return lines;
}
};
execute.execute(task);`enter code here`
Joop Eggen is correct. Your runLater calls are happening so fast, they are clogging up the JavaFX event queue, so JavaFX has no chance to do its normal painting and input handling.
A simple workaround is putting Thread.sleep(20); in your loop.
A better workaround, which won’t slow down your reading of the file, is to make your own buffer, and limit how often you update the TextArea:
task = new Task<>() {
public Integer call() {
int lines = 0;
Collection<String> linesBuffer = new ArrayList<>(100_000);
long timeOfLastAppend = System.nanoTime();
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
linesBuffer.add(line);
// Do not update the TextArea more than 10 times per second
// (that is, every 100 million nanoseconds).
long time = System.nanoTime();
if (time - timeOfLastAppend >= 100_000_000L) {
timeOfLastAppend = time;
String text = String.join(" \n", linesBuffer) + " \n";
Platform.runLater(() -> textArea.appendText(text));
linesBuffer.clear();
}
lines++;
updateMessage(lines + " lines read.");
}
if (!linesBuffer.isEmpty()) {
String text = String.join(" \n", linesBuffer) + " \n";
Platform.runLater(() -> textArea.appendText(text));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return lines;
}
};

How to detect out of vocabulary word in CMU Sphinx

I am having a problem with the Sphinx voice recognition library for Java. I am using it to get input and handle it. In the grammar file , I wrote like this:
#JSGF V1.0;
grammar hello;
public <sentence> = (play | pause | next | previous);
My grammar is simple , just includes 4 words : "play" , "pause" , "next" , "previous". I have used Sphinx to detect them sucessfully . But I want my app to show a message like : "Unrecognized word" when I speak some words that do not belong to the grammar. Currently, For example, if I speak to the microphone a not belong to the grammar like :"stop" , it still show up the word that it detects that it is the nearest result.
My code is like this :
public class SphinxDemo {
static int i = 1;
static String resultText;
public static void main(String[] args) {
try {
URL url;
if (args.length > 0) {
url = new File(args[0]).toURI().toURL();
} else {
url = SphinxDemo.class.getResource("helloworld.config.xml");
}
System.out.println("Loading...");
ConfigurationManager cm = new ConfigurationManager(url);
Recognizer recognizer = (Recognizer) cm.lookup("recognizer");
Microphone microphone = (Microphone) cm.lookup("microphone");
/* allocate the resource necessary for the recognizer */
recognizer.allocate();
/* the microphone will keep recording until the program exits */
if (microphone.startRecording()) {
System.out
.println("Say: play|pause|previous|next");
while (true) {
System.out
.println("Start speaking. Press Ctrl-C to quit.\n");
Result result = recognizer.recognize();
if (result != null) {
System.out.println("Enter your choise" + "\n");
resultText = result.getBestFinalResultNoFiller();
System.out.println("You said: " + resultText + "\n");
}
if(!(resultText.equalsIgnoreCase("play") || resultText.equalsIgnoreCase("previous") || resultText.equalsIgnoreCase("pause")||resultText.equalsIgnoreCase("next"))){
System.out.println("Unrecognized word\n");
}
}
} else {
System.out.println("Cannot start microphone.");
recognizer.deallocate();
System.exit(1);
}
} catch (IOException e) {
System.err.println("Problem when loading SphinxDemo: " + e);
e.printStackTrace();
} catch (PropertyException e) {
System.err.println("Problem configuring SphinxDemo: " + e);
e.printStackTrace();
} catch (InstantiationException e) {
System.err.println("Problem creating SphinxDemo: " + e);
e.printStackTrace();
}
}
}
I have tried to add something like this to detect unrecognized word but it does not work:
if(!(resultText.equalsIgnoreCase("play") || resultText.equalsIgnoreCase("previous") || resultText.equalsIgnoreCase("pause")||resultText.equalsIgnoreCase("next"))){
System.out.println("Unrecognized word\n");
}
If you use latest cmusphinx, it will return <unk> when word is not in the grammar.

Java - <identifier> expecter error

I was writing a java tool that toggles wether a game mod is active (specifically, the game is Dwarf Fortress, and the mod is DFHack) and the program is nearly done. However, I cant seem to get the variables right that tell the program how to check if the mod is active or not.
I got this status file containing a single character, being 1 for active and 0 for inactive.
This is the code (By the way, if it is needed: I checked the name of the file and it matches the class declaration).
package nl.dirkkok.dfhacktoggle;
/*
* DFHacktoggle
* 28-12-2013 # 2:02 PM
*
* This program will disable DFHack if it is enabled, and enable it if it is disabled.
*
* Using this tool is at your own risk. If you send me an email complaining about this program doing anything you dont want, then I will laugh at you, and tell you that you cant read. :)
*
* Created by Dirk Kok <d.kok.2000#gmail.com>. This tool is my property, but I do not claim rights of neither Dwarf Fortress nor DFHack.
*/
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.IOException;
import java.nio.file.NoSuchFileException;
public class Dfhacktoggle {
private static Path statusfile = "dfhack-status";
private boolean dfhack = false;
private byte[] fileArray = new byte[1];
private byte[] active = new byte[1];
private byte[] inactive = new byte[1];
private file dfhacksdl = "SDLdfhack.dll";
private file vanillasdl = "SDLreal.dll";
private file sdl = "SDL.dll";
active[] <byte> = 1;
inactive[] <byte> = 0;
public static void main(String[] args) {
try {
fileArray = Files.readAllBytes(file);
if (fileArray[0] == 1) {
p("DFHack is active. Deactivating...");
try {
if (vanillasdl.exists()) throw new java.io.IOException("File exists");
sdl.renameTo(dfhacksdl);
vanillasdl.renameTo(sdl);
Files.write(statusfile, inactive, WRITE);
} catch (IOException x) {
errp("DFHack could not be deactivated. Reinstalling the program will solve this.");
errp("Detailed info:");
errp("IOException: " + x);
} catch (NoSuchFileException x) {
errp("Status file could not be found. Reinstalling the program will solve this.");
errp("Detailed info:");
errp("NoSuchFileException: " + x);
}
} else if (fileArray[0] == 0) {
p("DFHack is inactive. Activating...");
try {
if(vanillasdl.exists()) throw new java.io.IOException("File exists");
sdl.renameTo(vanillasdl);
dfhacksdl.renameTo(sdl);
Files.write(statusfile, active, WRITE);
} catch (IOException x) {
errp("Status could not be checked. Reinstalling the program will solve this.");
errp("Detailed info:");
errp("IOException: " + x);
} catch (NoSuchFileException x) {
errp("Status file could not be found. Reinstalling the program will solve this.");
errp("Detailed info:");
errp("NoSuchFileException: " + x);
}
} else {
errp("DFHack's status could not be checked. Reinstalling the program will solve this.");
}
} catch (IOException x) {
errp("Status could not be checked. Reinstalling the program will solve this.");
errp("Detailed info:");
errp(x);
}
}
public void p(String txt) {
System.out.println(txt);
}
public void errp(String txt) {
System.err.println(txt);
}
}
The compiler returns this:
F:\Dfhack-swap>javac Dfhacktoggle.java
Dfhacktoggle:29: error: <identifier> expected
active[] <byte> = 1;
^
Dfhacktoggle:30: error: <identifier> expected
inactive[] <byte> = 0;
^
Your syntax is wrong there's no active[] <byte> = 1; in Java
If you want to assign it a value You can do it in this way
active[0] = 1;
inactive[0] = 0;
But there's no need for array to use it as a boolean you can just define it as a byte
byte active= 1;
byte inactive= 0;

Categories

Resources