Java TTS (Text To Speech) speech.properties file - java

I'm working on a PC asistant, which means it should recognize my voice and give feedback or do things, the feedback should be a computer generated voice.
I know there's a way inside Java itself to achieve this, using javax.speech for example. This voice isn't really of good quality, but it's doesn't require all kinds of libraries and it should be easy to use. I currently have this prototype code:
public static void speech(String text) {
if(text.trim() == "")
return;
String voiceName = "kevin16";
try {
SynthesizerModeDesc desc = new SynthesizerModeDesc(null, "general", Locale.US, null, null);
Synthesizer synth = Central.createSynthesizer(desc);
synth.allocate();
synth.resume();
desc = (SynthesizerModeDesc) synth.getEngineModeDesc();
Voice[] voices = desc.getVoices();
Voice voice = null;
for(Voice entry : voices) {
if(entry.getName().equals(voiceName)) {
voice = entry;
break;
}
}
synth.getSynthesizerProperties().setVoice(voice);
synth.speakPlainText(text, null);
synth.waitEngineState(Synthesizer.QUEUE_EMPTY);
synth.deallocate();
} catch(Exception ex) {
String message = " missing speech.properties in " + System.getProperty("user.home") + "\n";
System.out.println("" + ex);
System.out.println(message);
ex.printStackTrace();
}
}
From: converting text to speech java code
When I execute the code it causes an error, that's because the file speech.properties is not found, it should be in my users directory. The problem is that I don't know where to get this file from, or what should be in this file, could anyone help me?
Also, it would be great if anyone could send me a link to a good speech tutorial, I searched the web but it's hard to find!

I could fix your example with just a few changes.
First, I Added these lines in the beggining of your try-catch block:
System.setProperty("FreeTTSSynthEngineCentral", "com.sun.speech.freetts.jsapi.FreeTTSEngineCentral");
System.setProperty("freetts.voices", "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory");
Central.registerEngineCentral("com.sun.speech.freetts.jsapi.FreeTTSEngineCentral");
These lines bypass the need for that pesky speech.properties file.
Second, the voice name is "kevin16", not "kelvin16".
Third, I moved the synth.resume() to after the synth.getSynthesizerProperties().setVoice(voice) line. This is because it can't start talking anything without a predefined voice.
Forth, your if(text.trim() == "") is bad because comparing Strings using == is not a good idea.
Here is the resulting code:
public static void speech(String text) {
if (text == null || text.trim().isEmpty()) return;
String voiceName = "kevin16";
try {
System.setProperty("FreeTTSSynthEngineCentral", "com.sun.speech.freetts.jsapi.FreeTTSEngineCentral");
System.setProperty("freetts.voices", "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory");
Central.registerEngineCentral("com.sun.speech.freetts.jsapi.FreeTTSEngineCentral");
SynthesizerModeDesc desc = new SynthesizerModeDesc(null, "general", Locale.US, null, null);
Synthesizer synth = Central.createSynthesizer(desc);
synth.allocate();
desc = (SynthesizerModeDesc) synth.getEngineModeDesc();
Voice[] voices = desc.getVoices();
Voice voice = null;
for (Voice entry : voices) {
if(entry.getName().equals(voiceName)) {
voice = entry;
break;
}
}
synth.getSynthesizerProperties().setVoice(voice);
synth.resume();
synth.speakPlainText(text, null);
synth.waitEngineState(Synthesizer.QUEUE_EMPTY);
synth.deallocate();
} catch(Exception ex) {
String message = " missing speech.properties in " + System.getProperty("user.home") + "\n";
System.out.println("" + ex);
System.out.println(message);
ex.printStackTrace();
}
}

Related

App Intent Problem | Your app contains an Intent Redirection vulnerability

I got this message after updating app in play console. I am sharing code of a method where the error is, as suggested by Google. I never updated this part of the code and it never showed any problem before. I am not sure why it is showing me an error. Do I need to update the way of saving a file? I hope to find a solution here.
public void saveDocument(ScannedDocument scannedDocument) {
Mat doc = (scannedDocument.processed != null) ? scannedDocument.processed : scannedDocument.original;
Intent intent = getIntent();
String fileName;
boolean isIntent = false;
Uri fileUri = null;
if (intent.getAction().equals("android.media.action.IMAGE_CAPTURE")) {
fileUri = ((Uri) intent.getParcelableExtra(MediaStore.EXTRA_OUTPUT));
Log.d(TAG, "intent uri: " + fileUri.toString());
try {
fileName = File.createTempFile("onsFile", ".jpg", this.getCacheDir()).getPath();
} catch (IOException e) {
e.printStackTrace();
return;
}
isIntent = true;
} else {
String folderName = mSharedPref.getString("storage_folder", FOLDER_NAME);
File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString()
+ "/" + folderName);
if (!folder.exists()) {
folder.mkdirs();
Log.d(TAG, "wrote: created folder " + folder.getPath());
}
fileName = folder.getAbsolutePath()
+ "/DOC-"
+ new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date())
+ ".jpg";
}
Mat endDoc = new Mat(Double.valueOf(doc.size().width).intValue(),
Double.valueOf(doc.size().height).intValue(), CvType.CV_8UC4);
Core.flip(doc.t(), endDoc, 1);
Imgcodecs.imwrite(fileName, endDoc);
endDoc.release();
try {
ExifInterface exif = new ExifInterface(fileName);
exif.setAttribute("UserComment", "Generated");
String nowFormatted = mDateFormat.format(new Date().getTime());
exif.setAttribute(ExifInterface.TAG_DATETIME, nowFormatted);
exif.setAttribute(ExifInterface.TAG_DATETIME_DIGITIZED, nowFormatted);
// exif.setAttribute("Software", "OpenNoteScanner " + BuildConfig.VERSION_NAME + "");
exif.saveAttributes();
} catch (IOException e) {
e.printStackTrace();
}
if (isIntent) {
InputStream inputStream = null;
OutputStream realOutputStream = null;
try {
inputStream = new FileInputStream(fileName);
realOutputStream = this.getContentResolver().openOutputStream(fileUri);
// Transfer bytes from in to out
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) > 0) {
realOutputStream.write(buffer, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
try {
inputStream.close();
realOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
animateDocument(fileName, scannedDocument);
Log.d(TAG, "wrote: " + fileName);
if (isIntent) {
new File(fileName).delete();
setResult(RESULT_OK, intent);
finish();
} else {
addImageToGallery(fileName, this);
}
refreshCamera();
}
Google has a page on Mitigating Intent Redirection vulnerabilities that you should read carefully.
The short version is that the vulnerability could potentially1 be exploited by a malicious app to allow it to access private app components or files.
The document explains three possible ways to mitigate this vulnerability. Unfortunately, there is not enough context to be sure which of the three is most appropriate for your app. However, the first one is straightforward:
"If the affected app component does not need to receive Intents from other apps then you can make that app component private by setting `android:exported="false" in your Manifest."
I never updated this part of the code and it never showed any problem before.
That could mean that this is a relatively new kind of Android vulnerability, or that Google's methodology for detecting it has become more rigorous since last time you published your app.
Do I need to update the way of saving a file?
Possibly yes. Or possibly one of the mitigations will be sufficient.
I hope to find a solution here.
There are some possible solutions in the Google document I linked to.
1 - It is moot if it is actually possible to exploit the vulnerability in your app. The point is that Google Play Store's scanning / analysis / testing methodology has found what they believe to be a problem. Their goal is to protect Play Store users.

Javamail : Setting timeout for folder.search

I have been using Javamail (version 1.6.4) for a while now, mostly for event listening, mail parsing and copy/delete mails (from Exchnage using IMAPS). Lately i was asked to use sub-folders for a business usecase. When moving mail from the Inbox folder to a sub-folder the UID changes so i'm using folder.search() in order to find the new UID. This works most of the times but sometimes the search goes indefnitley (or its duration is very long) which may lag the entire application.
Is there a way to set a timeout (or other way to throw an exception if it runs too long) for folder.search()?
I understood that imap search is done on the server side but i just wanted to validate. this is an example of how i send search to the server (we can assume subject is unique for this discussion):
private static String findMailIdBySubject(String mailbox, String srcFolder, String subject) {
Folder srcFolderObj = null;
boolean wasConnectionEstablished = connectToMail(mailbox);
if (!wasConnectionEstablished) {
return null;
}
// get mailboxStore object
MailboxStore mailboxStore = MailBoxStoreList.getMailStoreByMailBox(mailbox);
try {
// Open inbox folder to get messages metadata
srcFolderObj = mailboxStore.getStore().getFolder(srcFolder);
srcFolderObj.open(Folder.READ_WRITE);
// create search Term
SearchTerm term = new SearchTerm() {
private static final long serialVersionUID = 7L;
#Override
public boolean match(Message message) {
try {
String mailSubject = message.getSubject();
if (mailSubject == null) {
mailSubject = "";
}
if (mailSubject.equals(subject)) {
return true;
}
} catch (MessagingException ex) {
log.error("Failed to search for mail with mailbox: " + mailbox + " in folder: " + srcFolder
+ " subject: " + subject + " Error: " + ExceptionUtils.getStackTrace(ex));
}
return false;
}
};
// search for the relevant message
Message[] messages = srcFolderObj.search(term);
UIDFolder uf = (UIDFolder) srcFolderObj;
return String.valueOf(uf.getUID(messages[0]));
} catch (Exception e) {
log.error("Subject: Failed to find id of mail in mailbox " + mailbox + " in folder " + srcFolder
+ " , Error: " + ExceptionUtils.getStackTrace(e));
return null;
} finally {
try {
if (srcFolderObj != null && srcFolderObj.isOpen()) {
srcFolderObj.close();
}
} catch (Exception e) {
}
}
}
i also tried to replace SearchTerm override with the following but performance was the same:
SearchTerm searchTerm = new SubjectTerm(subject);
Thanks in advance!

IO Exception Error When Trying to Read a Text File

I am trying to read a text file which contains strings (separated by commas) of airport information. However, when I try to read the file, it throws and IOException. Here is the code:
public ArrayList<ArrayList<String>> createAirportLibrary() {
ArrayList<ArrayList<String>> airportLibrary = new ArrayList<>();
String[] line;
BufferedReader reader = null;
try {
// import the text file
File airportsFile = new File("C:\\Users\\cjkei\\AndroidStudioProjects\\TravelTime\\app\\libs\\airports.txt");
// read the first line of the file
reader = new BufferedReader(new FileReader(airportsFile));
line = reader.readLine().split(",");
// loop through each line of file and add each airport to the library
while (line != null) {
int i = 0;
ArrayList<String> thisAirport = new ArrayList<>();
while (i < line.length){
if (line[i] instanceof String){
thisAirport.add(line[i]);
}
else {
airportLibrary.add(thisAirport);
thisAirport.clear();
}
i++;
}
line = reader.readLine().split(",");
}
}
catch (IOException e) {
Context context = this;
String text = "error reading file";
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
}
finally {
try {
if (reader != null) {
reader.close();
}
}
catch (IOException e) {
Context context = this;
String text = "could not close reader";
int duration = Toast.LENGTH_SHORT;
Toast.makeText(context, text, duration).show();
}
}
return airportLibrary;
}
I tried to debug step by step, but right after the onCreate call, it shows
this.
You might want to try the function Files.lines. It returns a Stream<String> you can then iterate over the stream.
Stream<String> stream = Files.lines(Paths.get(fileName))
stream.forEach(this::doSomethingWithLine);
private void doSomethingWithLine(String line) {
// actually do something
}
The picture you added does not show any exception information, but it does make clear where the error is coming from:
You are confusing two environments, and trying to open a file that does not exist.
The code in your example is for an Android app, but the file path is for a file on a Windows PC.
There is no "C drive" on Android devices, and you can not have Android code read a file from your PC, even if you run it on an emulator running on said PC.
If you look carefully at the full exception message, you will see that the problem is "File not found".
To do this, you can do something like this:
Toast.makeText(context, "Exception: " + e.toString(), Toast.LENGTH_SHORT).show();
or batter yet, since you are on Android, use the logging utility:
Log.e("MY_APP", "Exception: " + e.toString());
e.printStackTrace();
If you want the file to be part of your app and read it on the Android device, put it under assets folder in your project and use:
context.getAssets().open("MyFile.txt");
https://developer.android.com/reference/android/content/res/Resources

Global cursor in Dropbox API v2

I use dropbox /delta endpoint to track changes inside Dropbox.
More precisely, the following piece of code allow me to track changes in "/superfolder" recursively (I'm using here DbxClientV1):
List<String> listOfResults = new ArrayList<String>();
String path = "/superfolder";
String cursor = null;
while (true) {
DbxDelta<DbxEntry> deltaWithPathPrefix = client.getDeltaWithPathPrefix(cursor, path);
cursor = deltaWithPathPrefix.cursor;
if (deltaWithPathPrefix.reset) {
System.out.println("Reset!");
}
for (DbxDelta.Entry entry : deltaWithPathPrefix.entries) {
if (entry.metadata == null) {
System.out.println("Deleted: " + entry.lcPath);
listOfResults.add(entry.lcPath);
} else {
System.out.println("Added or modified: " + entry.lcPath);
}
}
if (!deltaWithPathPrefix.hasMore) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Logger.getLogger(MainSearchV1.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Now, I've switched to DbxClientV2 client. To track changes on dropbox I use client.files.listFolder() in the following form:
TreeMap<String, Metadata> children = new TreeMap<String, Metadata>();
Files.ListFolderResult result;
String cursor = null;
while (true) {
if (cursor == null) {
result = client.files.listFolder("/superfolder");
} else {
result = client.files.listFolderContinue(cursor);
}
cursor = result.cursor;
for (Metadata md : result.entries) {
if (md instanceof DeletedMetadata) {
children.remove(md.pathLower);
System.out.println("Deleted: " + md.pathLower);
} else {
children.put(md.pathLower, md);
System.out.println("State: " + md.pathLower);
System.out.println(md.toString());
}
}
if (!result.hasMore) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
Regretably, I've discovered that I can only track changes only of "superfolder" folder.
Is there a way to get a "global cursor" that tracks changes recursively in Dropbox API v2?
The Java SDK uses the builder pattern for pretty much all calls with multiple optional arguments. If I understand your question correctly, I think you're looking for this:
result = client.files.listFolderBuilder("/superfolder")
.recursive(true)
.start();
EDIT: You asked about a "global" cursor. I think you actually meant recursive, but in case you really meant global, you can pass an empty string ("") as a path to represent the root.

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.

Categories

Resources