Skip to content

Commit ffa6951

Browse files
committed
Updated GSpeech API for better accuracy and code cleanup.
1 parent 5cb7291 commit ffa6951

File tree

5 files changed

+67
-93
lines changed

5 files changed

+67
-93
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/bin
22
.classpath
33
.project
4+
.settings
45
/target

src/main/java/com/darkprograms/speech/recognizer/GSpeechDuplex.java

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import javax.sound.sampled.LineUnavailableException;
2020
import javax.sound.sampled.TargetDataLine;
2121

22-
import com.darkprograms.speech.util.ChunkedOutputStream;
2322
import com.darkprograms.speech.util.StringUtil;
2423

2524
//TODO Add a better logging system to GSpeechDuplex
@@ -109,6 +108,8 @@ public void recognize(File flacFile, int sampleRate) throws IOException{
109108
recognize(mapFileIn(flacFile), sampleRate);
110109
}
111110

111+
112+
112113
/**
113114
* Send a byte[] to the URL with a specified sampleRate.
114115
* NOTE: The byte[] should contain no more than 15 seconds of audio.
@@ -119,7 +120,6 @@ public void recognize(File flacFile, int sampleRate) throws IOException{
119120
public void recognize(byte[] data, int sampleRate){
120121

121122
if(data.length >= MAX_SIZE){//Temporary Chunking. Does not allow for Google to gather context.
122-
System.out.println("Chunking the audio into smaller parts...");
123123
byte[][] dataArray = chunkAudio(data);
124124
for(byte[]array: dataArray){
125125
recognize(array, sampleRate);
@@ -162,9 +162,10 @@ public void recognize(TargetDataLine tl, AudioFormat af) throws IOException, Lin
162162
final String API_UP_URL = GOOGLE_DUPLEX_SPEECH_BASE +
163163
"up?lang=" + language + "&lm=dictation&client=chromium&pair=" + PAIR +
164164
"&key=" + API_KEY + "&continuous=true&interim=true"; //Tells Google to constantly monitor the stream;
165-
165+
166166
//Opens downChannel
167167
this.downChannel(API_DOWN_URL);
168+
168169
//Opens upChannel
169170
this.upChannel(API_UP_URL, tl, af);
170171
}
@@ -191,15 +192,16 @@ public void run() {
191192
Scanner inStream = openHttpsConnection(url);
192193
if(inStream == null){
193194
//ERROR HAS OCCURED
195+
System.out.println("Error has occured");
196+
return;
194197
}
195-
while(inStream.hasNextLine()){
196-
String response = inStream.nextLine();
198+
String response;
199+
while(inStream.hasNext() && (response = inStream.nextLine()) != null){
197200
if(response.length()>17){//Prevents blank responses from Firing
198201
GoogleResponse gr = new GoogleResponse();
199202
parseResponse(response, gr);
200203
fireResponseEvent(gr);
201204
}
202-
203205
}
204206
inStream.close();
205207
System.out.println("Finished write on down stream...");
@@ -233,7 +235,7 @@ public void run() {
233235
* @param af The AudioFormat to stream with.
234236
* @throws LineUnavailableException If cannot open or stream the TargetDataLine.
235237
*/
236-
private void upChannel(String urlStr, TargetDataLine tl, AudioFormat af) throws LineUnavailableException{
238+
private void upChannel(String urlStr, TargetDataLine tl, AudioFormat af) throws IOException, LineUnavailableException{
237239
final String murl = urlStr;
238240
final TargetDataLine mtl = tl;
239241
final AudioFormat maf = af;
@@ -243,9 +245,8 @@ private void upChannel(String urlStr, TargetDataLine tl, AudioFormat af) throws
243245
}
244246
new Thread ("Upstream Thread") {
245247
public void run() {
246-
openHttpsPostConnection(murl, mtl, maf);
248+
openHttpsPostConnection(murl, mtl, (int)maf.getSampleRate());
247249
}
248-
249250
}.start();
250251

251252
}
@@ -258,8 +259,6 @@ public void run() {
258259
private Scanner openHttpsConnection(String urlStr) {
259260
int resCode = -1;
260261
try {
261-
262-
263262
URL url = new URL(urlStr);
264263
URLConnection urlConn = url.openConnection();
265264
if (!(urlConn instanceof HttpsURLConnection)) {
@@ -270,7 +269,6 @@ private Scanner openHttpsConnection(String urlStr) {
270269
// TIMEOUT is required
271270
httpConn.setInstanceFollowRedirects(true);
272271
httpConn.setRequestMethod("GET");
273-
274272
httpConn.connect();
275273
resCode = httpConn.getResponseCode();
276274
if (resCode == HttpsURLConnection.HTTP_OK) {
@@ -293,49 +291,53 @@ private Scanner openHttpsConnection(String urlStr) {
293291
* @param mtl The TargetDataLine you want to post data from. <b>Note should be open</b>
294292
* @param maf The AudioFormat of the data you want to post
295293
*/
296-
private void openHttpsPostConnection(final String murl,
297-
final TargetDataLine mtl, final AudioFormat maf) {
294+
private void openHttpsPostConnection(String murl, TargetDataLine mtl, int sampleRate) {
298295
URL url;
299296
try {
300297
url = new URL(murl);
301298
URLConnection urlConn = url.openConnection();
302299
if (!(urlConn instanceof HttpsURLConnection)) {
303300
throw new IOException ("URL is not an Https URL");
304301
}
302+
305303
HttpsURLConnection httpConn = (HttpsURLConnection)urlConn;
306304
httpConn.setAllowUserInteraction(false);
307305
httpConn.setInstanceFollowRedirects(true);
308306
httpConn.setRequestMethod("POST");
309307
httpConn.setDoOutput(true);
310308
httpConn.setChunkedStreamingMode(0);
311309
httpConn.setRequestProperty("Transfer-Encoding", "chunked");
312-
httpConn.setRequestProperty("Content-Type", "audio/x-flac; rate=" + (int)maf.getSampleRate());
310+
httpConn.setRequestProperty("Content-Type", "audio/x-flac; rate=" + sampleRate);
313311
// also worked with ("Content-Type", "audio/amr; rate=8000");
314312
httpConn.connect();
315-
313+
316314
// this opens a connection, then sends POST & headers.
317-
OutputStream out = httpConn.getOutputStream();
315+
final OutputStream out = httpConn.getOutputStream();
318316
//Note : if the audio is more than 15 seconds
319317
// dont write it to UrlConnInputStream all in one block as this sample does.
320318
// Rather, segment the byteArray and on intermittently, sleeping thread
321319
// supply bytes to the urlConn Stream at a rate that approaches
322320
// the bitrate ( =30K per sec. in this instance ).
323321
System.out.println("Starting to write data to output...");
324-
AudioInputStream ais = new AudioInputStream(mtl);
325-
ChunkedOutputStream os = new ChunkedOutputStream(out);
326-
AudioSystem.write(ais, FLACFileWriter.FLAC, os);
327-
out.write(FINAL_CHUNK);
328-
System.out.println("IO WRITE DONE");
329-
out.close();
322+
final AudioInputStream ais = new AudioInputStream(mtl);;
323+
AudioSystem.write(ais, FLACFileWriter.FLAC, out);
324+
//Output Stream is automatically closed
330325
// do you need the trailer?
331326
// NOW you can look at the status.
332-
int resCode = httpConn.getResponseCode();
327+
328+
//Diagonostic Code.
329+
/*int resCode = httpConn.getResponseCode();
333330
if (resCode / 100 != 2) {
334331
System.out.println("ERROR");
335332
}
336-
}catch(Exception ex){
333+
Scanner scanner = new Scanner(httpConn.getInputStream());
334+
while(scanner.hasNextLine()){
335+
System.out.println("UPSTREAM READS:" + scanner.nextLine());
336+
}
337+
scanner.close();*/
338+
System.out.println("Upstream Closed...");
339+
}catch(IOException ex){
337340
ex.printStackTrace();
338-
339341
}
340342
}
341343

@@ -369,34 +371,32 @@ private Scanner openHttpsPostConnection(String urlStr, byte[][] data, int sample
369371
httpConn.setRequestProperty("Content-Type", "audio/x-flac; rate=" + sampleRate);
370372
// also worked with ("Content-Type", "audio/amr; rate=8000");
371373
httpConn.connect();
372-
373-
// this opens a connection, then sends POST & headers.
374-
out = httpConn.getOutputStream();
375-
//Note : if the audio is more than 15 seconds
376-
// dont write it to UrlConnInputStream all in one block as this sample does.
377-
// Rather, segment the byteArray and on intermittently, sleeping thread
378-
// supply bytes to the urlConn Stream at a rate that approaches
379-
// the bitrate ( =30K per sec. in this instance ).
380-
System.out.println("Starting to write");
381-
for(byte[] dataArray: mextrad){
382-
out.write(dataArray); // one big block supplied instantly to the underlying chunker wont work for duration > 15 s.
383-
try {
384-
Thread.sleep(1000);//Delays the Audio so Google thinks its a mic.
385-
} catch (InterruptedException e) {
386-
e.printStackTrace();
387-
}
388-
}
389-
out.write(FINAL_CHUNK);
390-
System.out.println("IO WRITE DONE");
391-
// do you need the trailer?
392-
// NOW you can look at the status.
393-
resCode = httpConn.getResponseCode();
394-
if (resCode / 100 != 2) {
395-
System.out.println("ERROR");
374+
// this opens a connection, then sends POST & headers.
375+
out = httpConn.getOutputStream();
376+
//Note : if the audio is more than 15 seconds
377+
// dont write it to UrlConnInputStream all in one block as this sample does.
378+
// Rather, segment the byteArray and on intermittently, sleeping thread
379+
// supply bytes to the urlConn Stream at a rate that approaches
380+
// the bitrate ( =30K per sec. in this instance ).
381+
System.out.println("Starting to write");
382+
for(byte[] dataArray: mextrad){
383+
out.write(dataArray); // one big block supplied instantly to the underlying chunker wont work for duration > 15 s.
384+
try {
385+
Thread.sleep(1000);//Delays the Audio so Google thinks its a mic.
386+
} catch (InterruptedException e) {
387+
e.printStackTrace();
396388
}
397-
389+
}
390+
out.write(FINAL_CHUNK);
391+
System.out.println("IO WRITE DONE");
392+
// do you need the trailer?
393+
// NOW you can look at the status.
394+
resCode = httpConn.getResponseCode();
395+
if (resCode / 100 != 2) {
396+
System.out.println("ERROR");
397+
}
398398
if (resCode == HttpsURLConnection.HTTP_OK) {
399-
return new Scanner(httpConn.getInputStream());
399+
return new Scanner(httpConn.getInputStream(), "UTF-8");
400400
}
401401
else{
402402
System.out.println("HELP: " + resCode);

src/main/java/com/darkprograms/speech/recognizer/Recognizer.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import java.nio.charset.Charset;
88

99
import org.json.*;
10-
import com.darkprograms.speech.util.StringUtil;
1110

1211
/***************************************************************
1312
* Class that submits FLAC audio and retrieves recognized text
@@ -124,12 +123,6 @@ public String toString(){
124123
private boolean profanityFilter = true;
125124
private String language = null;
126125
private String apikey = null;
127-
128-
/**
129-
* Constructor
130-
*/
131-
private Recognizer() {
132-
}
133126

134127
/**
135128
* Constructor

src/main/java/com/darkprograms/speech/synthesiser/Synthesiser.java

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ public class Synthesiser {
5454
/**
5555
* Constructor
5656
*/
57-
@Deprecated
5857
public Synthesiser() {
5958
languageCode = "auto";
6059
}
@@ -96,16 +95,14 @@ public InputStream getMP3Data(String synthText) throws IOException{
9695
String languageCode = this.languageCode;//Ensures retention of language settings if set to auto
9796

9897
if(languageCode == null || languageCode.equals("") || languageCode.equalsIgnoreCase("auto")){
99-
try{
100-
languageCode = detectLanguage(synthText);//Detects language
101-
if(languageCode == null){
102-
languageCode = "en-us";//Reverts to Default Language if it can't detect it.
103-
//Throw an error message here eventually
104-
}
105-
}
106-
catch(Exception ex){
107-
ex.printStackTrace();
98+
languageCode = detectLanguage(synthText);//Detects language
99+
/* NOTE: Detect language relies on an entirely seperate endpoint.
100+
* If the GoogleTranslate API stops working, do not use the auto parameter
101+
* and switch to something else or a best guess.
102+
*/
103+
if(languageCode == null){
108104
languageCode = "en-us";//Reverts to Default Language if it can't detect it.
105+
//Throw an error message here eventually
109106
}
110107
}
111108

@@ -137,7 +134,8 @@ public InputStream getMP3Data(String synthText) throws IOException{
137134
URLConnection urlConn = url.openConnection(); //Open connection
138135

139136
//Adding header for user agent is required
140-
urlConn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0");
137+
urlConn.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) "
138+
+ "Gecko/20100101 Firefox/4.0");
141139

142140
return urlConn.getInputStream();
143141
}
@@ -201,7 +199,8 @@ private List<String> parseString(String input, List<String> fragments){
201199
fragments.add(input.substring(0,100));//In case you sent gibberish to Google.
202200
return parseString(input.substring(100), fragments);
203201
}else{
204-
fragments.add(input.substring(0,lastWord));//Otherwise, adds the last word to the list for recursion.
202+
fragments.add(input.substring(0,lastWord));
203+
//Otherwise, adds the last word to the list for recursion.
205204
return parseString(input.substring(lastWord), fragments);
206205
}
207206
}
@@ -269,15 +268,5 @@ public InputStream call() throws IOException{
269268
return getMP3Data(synthText);
270269
}
271270
}
272-
273-
public static void main(String[] args){
274-
Synthesiser synth = new Synthesiser("en-US");
275-
try {
276-
synth.getMP3Data("Hello, this is a test");
277-
} catch (IOException e) {
278-
// TODO Auto-generated catch block
279-
e.printStackTrace();
280-
}
281-
}
282271
}
283272

src/main/java/com/darkprograms/speech/translator/GoogleTranslate.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
import java.net.URLConnection;
88
import java.net.URLEncoder;
99
import java.nio.charset.Charset;
10-
import java.text.ParseException;
11-
import java.text.SimpleDateFormat;
1210
import java.util.ArrayList;
1311
import java.util.Date;
1412
import java.util.List;
@@ -217,16 +215,9 @@ private static boolean containsLettersOnly(String text){
217215
* This function generates the b parameter for translation acting as the seed for the hashing algorithm.
218216
*/
219217
private static int generateB() {
220-
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy", Locale.US);
221-
222-
Date start;
223-
Date now;
224-
try {
225-
start = sdf.parse("01/01/1970");
226-
now = new Date();
227-
} catch (ParseException e) {
228-
return 402890;
229-
}
218+
Date start = new Date(0L); //Unix Epoch
219+
Date now = new Date();
220+
230221
long diff = now.getTime() - start.getTime();
231222
long hours = diff / (60 * 60 * 1000) % 24;
232223
long days = diff / (24 * 60 * 60 * 1000);

0 commit comments

Comments
 (0)