Create a Flash Speech Synthesizer - Phonetic Speech Synthesizer
(Page 4 of 5 )
Fonetikally Speeking
Importing some allophones into Flash was a breeze. I used Adobe Audition (a sound-editing application) to:
- Remove any silent spaces at the beginning and end of each sample
- Reduce any clicks at the start and end of the samples (using fade in or fade out if necessary)
- Normalize the samples (so that all samples are at the same volume and power level)
- Optimize the samples for web use
I ended up with a library of synthesized voice samples, each of which I gave a name and linkage identifier that were both identical to the spoken allophone, as shown in Figure 7-2. For those not prepared to go through the same process, you can download speech_final.fla, complete with allophone sounds already imported, from this book’s web site.

Figure 7-2. The Library, showing the sound files used for the allophones
The old 8-bit speech synthesizers did not convert conventional spelling to phonetic text. For example, to pronounce the word “knowledge,” you had to ask the speech synthesizer to pronounce the phonetic equivalent, such as “nnolej” or something similar. To test my premise that Flash can be made to talk, I limited myself to writing a phonetic speech synthesizer. If you want to make a name for yourself, I’d welcome any code that converts from conventional spelling to phonetic spelling. (You might begin with technical linguistics papers you can find on the Web!)
So I tacked some string handling onto the simple sound code shown previously to create something that could take a raw allophone-based string and convert it to a simple sound queue serviced by an onSoundComplete( ) callback function:
makePhrase = function () {
if (soundCount < soundMax){
soundCount++;
speech.attachSound(aPhones[soundCount]);
speech.start();
} else {
delete speech.onSoundComplete;
}
};
function say (phrase) {
var i = j= 0;
aPhones = new Array();
for (i = 0; i < phrase.length; i++) {
if (phrase.charAt(i) != "|") {
aPhones[j] += phrase.charAt(i);
if (phrase.charAt(i) == " ") {
aphones[j] = "space";
}
}else {
j++;
}
}
speech.attachSound(aPhones[0]);
speech.start();
speech.onSoundComplete = makePhrase;
soundCount = 0;
soundMax = j-1;
}
function SoundInit () {
speech = new Sound(this);
}
soundInit();
say("h|e|ll|oo| | | | | |h|ow| |ar| |y|ouu| | | | |tt|u|d|ay|");
stop();
Unfortunately, some of the allophone sound names are too similar to differentiate between them easily. For example, “ooo” could be written as “o o o”, “o oo”, or “oo o” and each variation would sound different. Instead, I used the | character as an allophone separator. The pure programmer in me would have renamed the allophones to “o1” and “o2” so the problem never occurs, but the designer in me overturned this decision because it makes manually creating the phonetic text string easier and more intuitive—“y|oo” makes more sense than “y|o2.”
Assuming we just wanted to say “hello,” the code works as follows. The first line sets the ball rolling. It sends our text to be spoken as a phonetically spelled string argument to the say( ) function:
say("h|e|ll|oo|");
The say( ) function creates a new array, which overwrites any existing array of the same name, so we don’t need to clear data from previous function calls. Following our example through, the array of allophones is:
aPhones[0] = "h"
aPhones[1] = "e"
aPhones[2]= "ll"
aPhones[3]= "oo"
We then attach the first sound, “h”, to our Sound instance and use onSoundComplete events to sequentially attach “e”, “ll”, and “oo” in turn as each allophone completes. This is taken care of via the makePhrase( ) function, which attaches the next sound file in our allophone sequence,aPhones, until all the entries in the array are sounded. Simple, eh? It works in a cool retro Speak & Spell digitized voice. Have a listen to speech_final.fla.
As a final hack-within-a-hack, note that I have used only one Sound instance, rather than one per sound file, which results in longer code full of too manyforloops. Using one Sound instance is possible because you can useSound.attach Sound( ) as many times as you like, and it is also fast, so you can do it on the fly. This has two very cool side effects for the advanced Flash sound programmer:
- You need to set up only one onSoundComplete callback rather than having to create one per Sound instance.
- Flash has eight sound channels, but you cannot normally access the separate channels. Flash assigns the channels behind the scenes, but this is not always desirable if you are creating complex scripted sound control. Instead, you can create eightSoundinstances (channel0tochannel7),and then reassign the sounds to be played dynamically to each viaSound.attachSound( ).This gives you your eightSoundinstances in a way that relates directly to the eight sound channels.
 | If you've enjoyed what you've seen here, or to get more information, click on the "Buy the book!" graphic. Pick up a copy today!
Visit the O'Reilly Network http://www.oreillynet.com for more online content. |
Next: Final Thoughts >>
More Flash Articles
More By O'Reilly Media