« How to checkout Merapi Examples | Main | Flash Catalyst is Public »
Merapi Voice – new AIR/Java example
| By Rich Tretola | June 1, 2009 | |
| 4,853 views |
Ray Camden recently posted about Generating Speech with ColdFusion and Java, so naturally I thought why not do this with AIR and Java via Merapi.
It is so simple to do but also so cool to talk about. So what is involved? Not much really. I simply utilize the same Java classes as Ray had used in his ColdFusion example to generate the speech and pass the text that I would like to hear to Java from AIR via Merapi.
Lets look at the source, Java first.
VoiceRunner.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package merapi.examples.voice; import merapi.Bridge; import merapi.examples.voice.handlers.VoiceHandler;; public class VoiceRunner { //-------------------------------------------------------------------------- // // Static methods // //-------------------------------------------------------------------------- /** * The main method that starts the Bridge and instantiates the VoiceHandler instance. */ public static void main( String[] args ) { Bridge.open(); new VoiceHandler(); } } |
VoiceHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package merapi.examples.voice.handlers; import com.sun.speech.freetts.Voice; import com.sun.speech.freetts.VoiceManager; import merapi.examples.voice.messages.VoiceMessage; import merapi.handlers.MessageHandler; import merapi.messages.IMessage; public class VoiceHandler extends MessageHandler { //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ public VoiceHandler() { super( VoiceMessage.SAY_IT ); } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * Handles the VoiceMessage.SAY_IT message type. */ public void handleMessage( IMessage message ) { if ( message instanceof VoiceMessage ) { VoiceMessage vMessage = ( VoiceMessage ) message; VoiceManager voiceManager = VoiceManager.getInstance(); Voice voice = voiceManager.getVoice("kevin16"); voice.allocate(); voice.speak(vMessage.getText()); } } } |
VoiceMessage.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | package merapi.examples.voice.messages; import merapi.messages.Message; /** * The VoiceMessage class extends Message as an example of a * custom Merapi message. * * @see merapi.messages.Message; */ public class VoiceMessage extends Message { //-------------------------------------------------------------------------- // // Constants // //-------------------------------------------------------------------------- /** * Message type for a SAY_IT message. */ public static final String SAY_IT = "sayIt"; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ public VoiceMessage() { super(); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // text //---------------------------------- /** * A custom data property that contains the text to speak sent from AIR */ public String getText() { return __text; } public void setText( String val ) { __text = val; } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- private String __text = null; } |
Now the AIR application source:
Voice.mxml (main application)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication title="merapi voice" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:merapiproject="http://merapiproject.net/2009" xmlns:messages="merapi.examples.voice.messages.*" verticalCenter="0" width="250" height="275"> <!-- ==== VoiceMessage : The message sent accross the bridge ======================== --> <messages:VoiceMessage id="voiceMessage" text="{sayItText.text}" /> <mx:Script> <![CDATA[ import merapi.messages.IMessage; import merapi.messages.Message; private function sayIt():void{ /* * Call send() method to send the message to Java */ voiceMessage.send(); } ]]> </mx:Script> <mx:Label text="Enter some text below"/> <mx:TextArea id="sayItText" height="150" width="200"> <mx:text>Hello from Merapi, this example was written by Rich Tretola from EverythingFlex dot com</mx:text> </mx:TextArea> <mx:Button click="sayIt()" label="Say It" horizontalCenter="0" y="10"/> </mx:WindowedApplication> |
VoiceMessage.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package merapi.examples.voice.messages { import merapi.messages.Message; [RemoteClass( alias="merapi.examples.voice.messages.VoiceMessage" )] /** * The VoiceMessage class extends Message as an example of a * custom Merapi message. * @author Rich Tretola everythingflex.com twitter @richtretola * @see merapi.messages.Message; */ public class VoiceMessage extends Message { //-------------------------------------------------------------------------- // // Constants // //-------------------------------------------------------------------------- /** * Message type for a Voice message. */ public static const SAY_IT : String = "sayIt"; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. */ public function VoiceMessage() { super( SAY_IT ); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // text //---------------------------------- /** * A custom data property that contains the text to speak */ public var text : String = null; } // end class } // end package |
That is it, 5 total files.
So, what is going on here?
Take a look at VoiceRunner.java and you will notice that when this file is run, a new VoiceHandler is created which sits waiting for messages from AIR.
On the AIR side within the Voice.mxml file, you will notice that an instance of VoiceMessage is created and it’s text property is bound to a TextArea’s text property. When the Say It button is clicked, the VoiceMessage’s send method is called and sends a message to Java via Merapi including the text that will be converted to speech.
The incoming message calls the VoiceHandler’s handleMessage method, where all of the work takes place. Within the handleMessage method you will notice that a new VoiceManager instance is retrieved. A new Voice object is created by calling the VoiceManager’s getVoice method. Finally, the text being passed from AIR is retrieved from the VoiceMessage’s getText method and passed into the Voice’s speak method.
That is all there is to let your AIR applications speak to you.
This example is now available within the merapi-examples repository at http://code.google.com/p/merapi-examples/. For information on how to checkout these applications, please refer to this post.
Topics: Adobe AIR, Artemis/Merapi, Flex | 9 Comments »








June 1st, 2009 at 9:59 am
[...] Flash Builder 4 is Public | EverythingFlex: Flex & AIR on Flex 3 vs Flex 4 State ManagementMerapi Voice – new AIR/Java example | EverythingFlex: Flex & AIR on How to checkout Merapi Examplesjeanphilippe on How to checkout Merapi [...]
June 3rd, 2009 at 7:29 am
[...] a test of this new service I brought up my recent Merapi post within Browserlab and found some errors in my blog that show themselves only in certain [...]
June 7th, 2009 at 5:33 am
Hey Rich,
I’m getting errors. Checked out both project (flex&java) from svn. They both compile but when I hit [say uit] java throws the following:
java.util.zip.ZipException: No such file or directory
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.(ZipFile.java:203)
at java.util.jar.JarFile.(JarFile.java:132)
at java.util.jar.JarFile.(JarFile.java:70)
at sun.net.www.protocol.jar.URLJarFile.(URLJarFile.java:56)
at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:41)
at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:53)
at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:102)
at sun.net.www.protocol.jar.JarURLConnection.getJarFile(JarURLConnection.java:69)
at java.net.JarURLConnection.getManifest(JarURLConnection.java:217)
at java.net.JarURLConnection.getMainAttributes(JarURLConnection.java:269)
at com.sun.speech.freetts.VoiceManager.getDependencyURLs(VoiceManager.java:251)
at com.sun.speech.freetts.VoiceManager.getDependencyURLs(VoiceManager.java:283)
at com.sun.speech.freetts.VoiceManager.getVoiceDirectories(VoiceManager.java:173)
at com.sun.speech.freetts.VoiceManager.getVoices(VoiceManager.java:110)
at com.sun.speech.freetts.VoiceManager.getVoice(VoiceManager.java:502)
at merapi.examples.voice.handlers.VoiceHandler.handleMessage(VoiceHandler.java:67)
at merapi.Bridge.dispatchMessage(Bridge.java:207)
at merapi.BridgeListenerThread.run(BridgeListenerThread.java:108)
I’m I missing a file?
(java 1.5 on osx 10.5.7)
regards
Patrick
Reply to this comment
Rich Tretola Reply:
June 7th, 2009 at 8:18 am
Not sure, I wrote the example on Java 1.5 OS X 10.5.7 and all works fine. I’ll have to look into it.
Reply to this comment
PatrickG Reply:
June 10th, 2009 at 11:48 am
Hey Rich,
I figured it out. The repository is indeed missing some files.
you probably have those jars in your default class path.
I had to add the following jars to the java-project (they can be found in the freetts-1.2.2-bin.zip on sourceforge)
[ http://ovh.dl.sourceforge.net/sourceforge/freetts/freetts-1.2.2-bin.zip
cmu_time_awb.jar
cmu_us_kal.jar
cmudict04.jar
cmulex.jar
cmutimelex.jar
en_us.jar
Now I can hear kevin16 say anything I tell him to,
Although his Dutch pronunciation is kinda poor
Reply to this comment
Rich Tretola Reply:
June 10th, 2009 at 12:55 pm
Nope, my project has only the jars that I checked in:
commons-logging.jar
flex-messaging-common.jar
flex-messaging-core.jar
log4j-1.2.15.jar
merapi-core-0.1.8-beta.jar
spring.jar
tools.jar
June 14th, 2009 at 1:41 pm
[...] have seen Rich Tretola’s blog Everything Flex on text to speech through Merapi and thought it would make sense to do it the other way around. In [...]
June 19th, 2009 at 7:43 pm
Thanks for your well illustrated samples!! I am running into an issue where the Java application does not wait but runs to completion. There are no obvious errors and seems to run okay. I looked at your video posting with regard to the Voice sample – I am also having the same experience with this as well. Any suggestion as to why the Java application thread is not waiting? Thanks
Reply to this comment
September 27th, 2009 at 7:34 am
Hello ,
Very good application !
I had a question if you want to export your application into myappli.air , is it possible to include your java application or you have always to start first your java application and then start myappli.air ?
Because start two application is not good for the final user
thank you for your help
Reply to this comment