[377375] Enable to generate WAV files by TTS engines
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpVoice.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpVoice.java
index 898ac3c..0436149 100644
--- a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpVoice.java
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/ISpVoice.java
@@ -7,6 +7,7 @@
*
* Contributors:
* Takashi ITOH - initial API and implementation
+ * Kentarou FUKUDA - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.ai.tts.msp.engine;
@@ -40,6 +41,11 @@
return COMUtil.VtblCall(11, address, pAudioOutputAddress);
}
+ public int put_AudioOutputStream(int pAudioOutputStreamAddress) {
+ return COMUtil.VtblCall(13, address, pAudioOutputStreamAddress);
+ }
+
+
public int get_Rate(int pRateAddress) {
return COMUtil.VtblCall(14, address, pRateAddress);
}
diff --git a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/MspVoice.java b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/MspVoice.java
index eba32ea..92c9d98 100644
--- a/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/MspVoice.java
+++ b/plugins/org.eclipse.actf.ai.tts.msp/src/org/eclipse/actf/ai/tts/msp/engine/MspVoice.java
@@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.actf.ai.tts.msp.engine;
+import java.io.File;
+
import org.eclipse.actf.ai.tts.ISAPIEngine;
import org.eclipse.actf.ai.tts.msp.MspPlugin;
import org.eclipse.actf.ai.voice.IVoiceEventListener;
@@ -20,6 +22,8 @@
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.internal.ole.win32.GUID;
+import org.eclipse.swt.internal.ole.win32.IDispatch;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.Variant;
@@ -32,6 +36,9 @@
public static final String ID = "org.eclipse.actf.ai.tts.msp.engine.MspVoice"; //$NON-NLS-1$
public static final String AUDIO_OUTPUT = "org.eclipse.actf.ai.tts.MspVoice.audioOutput"; //$NON-NLS-1$
+ public static final GUID IID_SpFileStream = COMUtil
+ .IIDFromString("{947812B3-2AE1-4644-BA86-9E90DED7EC91}"); //$NON-NLS-1$
+
public ISpVoice dispSpVoice;
private Variant varSapiVoice;
private OleAutomation automation;
@@ -68,7 +75,9 @@
/*
* (non-Javadoc)
*
- * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ * @see
+ * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
+ * .jface.util.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
if (ID.equals(event.getProperty())) {
@@ -83,7 +92,9 @@
/*
* (non-Javadoc)
*
- * @see org.eclipse.actf.ai.tts.ITTSEngine#setEventListener(org.eclipse.actf.ai.voice.IVoiceEventListener)
+ * @see
+ * org.eclipse.actf.ai.tts.ITTSEngine#setEventListener(org.eclipse.actf.
+ * ai.voice.IVoiceEventListener)
*/
public void setEventListener(IVoiceEventListener eventListener) {
spNotifySource.setEventListener(eventListener);
@@ -100,8 +111,7 @@
firstFlag |= SVSFPurgeBeforeSpeak;
}
if (index >= 0) {
- speak(
- "<BOOKMARK mark=\"" + index + "\"/>", firstFlag | SVSFPersistXML); //$NON-NLS-1$ //$NON-NLS-2$
+ speak("<BOOKMARK mark=\"" + index + "\"/>", firstFlag | SVSFPersistXML); //$NON-NLS-1$ //$NON-NLS-2$
speak(text, SVSFlagsAsync);
speak("<BOOKMARK mark=\"-1\"/>", SVSFlagsAsync | SVSFPersistXML); //$NON-NLS-1$
} else {
@@ -366,11 +376,11 @@
* @see org.eclipse.actf.ai.tts.ITTSEngine#setGender(java.lang.String)
*/
public void setGender(String gender) {
- //TODO
- if(GENDER_MALE.equalsIgnoreCase(gender)){
-// setVoiceName("name=Microsoft Mike");
- }else if(GENDER_FEMALE.equalsIgnoreCase(gender)){
-// setVoiceName("name=Microsoft Mary");
+ // TODO
+ if (GENDER_MALE.equalsIgnoreCase(gender)) {
+ // setVoiceName("name=Microsoft Mike");
+ } else if (GENDER_FEMALE.equalsIgnoreCase(gender)) {
+ // setVoiceName("name=Microsoft Mary");
}
}
@@ -386,4 +396,64 @@
public boolean isDisposed() {
return isDisposed;
}
+
+ @Override
+ public boolean canSpeakToFile() {
+ return true;
+ }
+
+ @Override
+ public boolean speakToFile(String text, File file) {
+ int pv = COMUtil.createDispatch(IID_SpFileStream);
+ OleAutomation autoSpFileStream = null;
+ boolean speakToFileResult = false;
+
+ if (file == null || (file.exists() && !file.canWrite())) {
+ return false;
+ }
+
+ Variant varSpFileStream = new Variant(new IDispatch(pv));
+ try {
+ autoSpFileStream = varSpFileStream.getAutomation();
+
+ // AllowAudioOutputFormatChangesOnNextSet
+ // System.out.println(automation.getProperty(7).getBoolean());
+
+ // format
+ // System.out.println(autoSpFileStream.getProperty(1).getAutomation().setProperty(1,new
+ // Variant(6)));
+
+ // open 100 close 101
+ String tmpS = file.toURI().toString();
+ if (tmpS.startsWith("file:/")) {
+ tmpS = tmpS.substring(6);
+ }
+
+ autoSpFileStream.invoke(100, new Variant[] { new Variant(tmpS),
+ new Variant(3), new Variant(false) });
+
+ dispSpVoice.put_AudioOutputStream(pv);
+
+ char[] data = (text + "\0").toCharArray(); //$NON-NLS-1$
+ int bstrText = MemoryUtil.SysAllocString(data);
+
+ try {
+ dispSpVoice.Speak(bstrText, 0);
+ } finally {
+ MemoryUtil.SysFreeString(bstrText);
+ }
+ autoSpFileStream.invoke(101);
+ autoSpFileStream.dispose();
+ autoSpFileStream = null;
+ speakToFileResult = true;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ if (autoSpFileStream != null) {
+ autoSpFileStream.dispose();
+ autoSpFileStream = null;
+ }
+ }
+ return speakToFileResult;
+ }
}
diff --git a/plugins/org.eclipse.actf.ai.tts.protalker/src/org/eclipse/actf/ai/tts/protalker/engine/ProTalker.java b/plugins/org.eclipse.actf.ai.tts.protalker/src/org/eclipse/actf/ai/tts/protalker/engine/ProTalker.java
index 75fa699..00d6a7a 100644
--- a/plugins/org.eclipse.actf.ai.tts.protalker/src/org/eclipse/actf/ai/tts/protalker/engine/ProTalker.java
+++ b/plugins/org.eclipse.actf.ai.tts.protalker/src/org/eclipse/actf/ai/tts/protalker/engine/ProTalker.java
@@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.actf.ai.tts.protalker.engine;
+import java.io.File;
+
import org.eclipse.actf.ai.tts.ITTSEngine;
import org.eclipse.actf.ai.tts.protalker.ProTalkerPlugin;
import org.eclipse.actf.ai.voice.IVoiceEventListener;
@@ -39,7 +41,9 @@
/*
* (non-Javadoc)
*
- * @see org.eclipse.actf.ai.tts.ITTSEngine#setEventListener(org.eclipse.actf.ai.voice.IVoiceEventListener)
+ * @see
+ * org.eclipse.actf.ai.tts.ITTSEngine#setEventListener(org.eclipse.actf.
+ * ai.voice.IVoiceEventListener)
*/
public void setEventListener(IVoiceEventListener eventListener) {
engine.addIndexListener(eventListener);
@@ -48,7 +52,9 @@
/*
* (non-Javadoc)
*
- * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ * @see
+ * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
+ * .jface.util.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
if (ID.equals(event.getProperty())) {
@@ -164,4 +170,12 @@
public boolean isDisposed() {
return isDisposed;
}
+
+ public boolean canSpeakToFile() {
+ return false;
+ }
+
+ public boolean speakToFile(String text, File file) {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/ISpVoice.java b/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/ISpVoice.java
index 5609cca..db9851f 100644
--- a/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/ISpVoice.java
+++ b/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/ISpVoice.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007 IBM Corporation and Others
+ * Copyright (c) 2007, 2012 IBM Corporation and Others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,6 +7,7 @@
*
* Contributors:
* Takashi ITOH - initial API and implementation
+ * Kentarou FUKUDA - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.ai.tts.sapi.engine;
@@ -40,6 +41,11 @@
return COMUtil.VtblCall(11, address, pAudioOutputAddress);
}
+ public int put_AudioOutputStream(int pAudioOutputStreamAddress) {
+ return COMUtil.VtblCall(13, address, pAudioOutputStreamAddress);
+ }
+
+
public int get_Rate(int pRateAddress) {
return COMUtil.VtblCall(14, address, pRateAddress);
}
diff --git a/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/SapiVoice.java b/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/SapiVoice.java
index bd996bc..a08eebe 100644
--- a/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/SapiVoice.java
+++ b/plugins/org.eclipse.actf.ai.tts.sapi/src/org/eclipse/actf/ai/tts/sapi/engine/SapiVoice.java
@@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.actf.ai.tts.sapi.engine;
+import java.io.File;
+
import org.eclipse.actf.ai.tts.ISAPIEngine;
import org.eclipse.actf.ai.tts.sapi.SAPIPlugin;
import org.eclipse.actf.ai.voice.IVoiceEventListener;
@@ -20,6 +22,8 @@
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.internal.ole.win32.GUID;
+import org.eclipse.swt.internal.ole.win32.IDispatch;
import org.eclipse.swt.ole.win32.OLE;
import org.eclipse.swt.ole.win32.OleAutomation;
import org.eclipse.swt.ole.win32.Variant;
@@ -32,6 +36,9 @@
public static final String ID = "org.eclipse.actf.ai.tts.sapi.engine.SapiVoice"; //$NON-NLS-1$
public static final String AUDIO_OUTPUT = "org.eclipse.actf.ai.tts.SapiVoice.audioOutput"; //$NON-NLS-1$
+ public static final GUID IID_SpFileStream = COMUtil
+ .IIDFromString("{947812B3-2AE1-4644-BA86-9E90DED7EC91}"); //$NON-NLS-1$
+
public ISpVoice dispSpVoice;
private Variant varSapiVoice;
private OleAutomation automation;
@@ -68,7 +75,9 @@
/*
* (non-Javadoc)
*
- * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+ * @see
+ * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
+ * .jface.util.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
if (ID.equals(event.getProperty())) {
@@ -83,7 +92,9 @@
/*
* (non-Javadoc)
*
- * @see org.eclipse.actf.ai.tts.ITTSEngine#setEventListener(org.eclipse.actf.ai.voice.IVoiceEventListener)
+ * @see
+ * org.eclipse.actf.ai.tts.ITTSEngine#setEventListener(org.eclipse.actf.
+ * ai.voice.IVoiceEventListener)
*/
public void setEventListener(IVoiceEventListener eventListener) {
spNotifySource.setEventListener(eventListener);
@@ -100,8 +111,7 @@
firstFlag |= SVSFPurgeBeforeSpeak;
}
if (index >= 0) {
- speak(
- "<BOOKMARK mark=\"" + index + "\"/>", firstFlag | SVSFPersistXML); //$NON-NLS-1$ //$NON-NLS-2$
+ speak("<BOOKMARK mark=\"" + index + "\"/>", firstFlag | SVSFPersistXML); //$NON-NLS-1$ //$NON-NLS-2$
speak(text, SVSFlagsAsync);
speak("<BOOKMARK mark=\"-1\"/>", SVSFlagsAsync | SVSFPersistXML); //$NON-NLS-1$
} else {
@@ -366,11 +376,11 @@
* @see org.eclipse.actf.ai.tts.ITTSEngine#setGender(java.lang.String)
*/
public void setGender(String gender) {
- //TODO
- if(GENDER_MALE.equalsIgnoreCase(gender)){
+ // TODO
+ if (GENDER_MALE.equalsIgnoreCase(gender)) {
setVoiceName("name=Microsoft Mike");
- }else if(GENDER_FEMALE.equalsIgnoreCase(gender)){
- setVoiceName("name=Microsoft Mary");
+ } else if (GENDER_FEMALE.equalsIgnoreCase(gender)) {
+ setVoiceName("name=Microsoft Mary");
}
}
@@ -386,4 +396,64 @@
public boolean isDisposed() {
return isDisposed;
}
+
+ @Override
+ public boolean canSpeakToFile() {
+ return true;
+ }
+
+ @Override
+ public boolean speakToFile(String text, File file) {
+ int pv = COMUtil.createDispatch(IID_SpFileStream);
+ OleAutomation autoSpFileStream = null;
+ boolean speakToFileResult = false;
+
+ if (file == null || (file.exists() && !file.canWrite())) {
+ return false;
+ }
+
+ Variant varSpFileStream = new Variant(new IDispatch(pv));
+ try {
+ autoSpFileStream = varSpFileStream.getAutomation();
+
+ // AllowAudioOutputFormatChangesOnNextSet
+ // System.out.println(automation.getProperty(7).getBoolean());
+
+ // format
+ // System.out.println(autoSpFileStream.getProperty(1).getAutomation().setProperty(1,new
+ // Variant(6)));
+
+ // open 100 close 101
+ String tmpS = file.toURI().toString();
+ if (tmpS.startsWith("file:/")) {
+ tmpS = tmpS.substring(6);
+ }
+
+ autoSpFileStream.invoke(100, new Variant[] { new Variant(tmpS),
+ new Variant(3), new Variant(false) });
+
+ dispSpVoice.put_AudioOutputStream(pv);
+
+ char[] data = (text + "\0").toCharArray(); //$NON-NLS-1$
+ int bstrText = MemoryUtil.SysAllocString(data);
+
+ try {
+ dispSpVoice.Speak(bstrText, 0);
+ } finally {
+ MemoryUtil.SysFreeString(bstrText);
+ }
+ autoSpFileStream.invoke(101);
+ autoSpFileStream.dispose();
+ autoSpFileStream = null;
+ speakToFileResult = true;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ if (autoSpFileStream != null) {
+ autoSpFileStream.dispose();
+ autoSpFileStream = null;
+ }
+ }
+ return speakToFileResult;
+ }
}
diff --git a/plugins/org.eclipse.actf.ai.voice/src/org/eclipse/actf/ai/tts/ITTSEngine.java b/plugins/org.eclipse.actf.ai.voice/src/org/eclipse/actf/ai/tts/ITTSEngine.java
index 2bf6688..08387e0 100644
--- a/plugins/org.eclipse.actf.ai.voice/src/org/eclipse/actf/ai/tts/ITTSEngine.java
+++ b/plugins/org.eclipse.actf.ai.voice/src/org/eclipse/actf/ai/tts/ITTSEngine.java
@@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.actf.ai.tts;
+import java.io.File;
+
import org.eclipse.actf.ai.voice.IVoice;
import org.eclipse.actf.ai.voice.IVoiceEventListener;
@@ -118,4 +120,26 @@
* available
*/
public boolean isAvailable();
+
+ /**
+ * Returns <code>true</code> if TTS engine supports to speak text into WAV
+ * file, and <code>false</code> otherwise.
+ *
+ * @return <code>true</code> if TTS engine supports to speak text into WAV
+ * file, and <code>false</code> otherwise.
+ */
+ public boolean canSpeakToFile();
+
+ /**
+ * Speak the contents of a text string into WAV file
+ *
+ * @param text
+ * text string to be spoken
+ * @param file
+ * target File to write WAV data.
+ * @return <code>true</code> if WAV file is successfully generated, and
+ * <code>false</code> otherwise.
+ */
+ public boolean speakToFile(String text, File file);
+
}