11 Speech

The TI-99/4A had, back in the day, perhaps the greatest speech capabilities of any of the plethora of "home computers" that were so prevalent during the early 1980s. Coupled with the Solid State Speech Synthesizer it was pretty much unbeatable.

If you have a speech synth connected, you can take advantage of it in TurboForth. Unlike languages such as Extended Basic (which also offered speech synthesizer access) your program can continue to execute while the speech synthesizer is talking.

11.1 Types of Speech

Streaming of raw (Linear Predictive Coded) data directly into the speech synthesizer, allowing any word to be spoken in any voice (provided you have the data)

TurboForth supports both methods.

11.2 Speaking Words from the Speech Synthesizer Vocabulary

The word SAY is used in TurboForth to speak words from the speech synth's built-in vocabulary. The stack signature for SAY is as follows:

SAY ( address count -- )

As can be inferred from the above stack signature, SAY actually expects an address of a list of data (address), and the number of items in that list (count). The word DATA can be used in TurboForth to build lists.

Example

Let's try an example. Let's make the speech synthesizer say "I LIKE FORTH":

: ILF DATA 3 $3793 $3F2F $2D19 SAY ;

Here, we have set up a data list consisting of three values. These values are the addresses of the words in the synthesizer vocabulary:

"I" - address 0x3793

"LIKE" - address 0x3F2F

"FORTH" - address 0x2D19

At run-time (when execute the word ILF) DATA pushes the address of the start of its data-list, and the number of items in the list (the count) to the stack, which is exactly what SAY expects.

If you run the above example (just type it in, then type ILF) you'll hear the speech synthesizer tell you in its rather gruff deep male voice that it likes Forth!

*Note: If you are running TurboForth in a PC based emulator, then the best emulators to use for speech are MESS and Win994A. Classic99 is not currently recommended for speech.

11.3 Speaking Using LPC Data

If you have the LPC data, or the means to create it, you can make the synthesizer say anything you like. The technique is exactly the same: Use DATA to define the list of bytes to send, and then use the word STREAM to stream the data into the speech synthesizer in the background.

Example

Here is an example which says "Forth is Awesome!"

It is taken from Block 2 of the TurboForth companion disk, which contains a number of demo's and utilities, all in source code form.

When using DATA with long streams of bytes (anything that is more than 80 characters in length) then the source code should be entered via a disk block. If you have the companion disk, you can try the above demo by typing 2 LOAD

11.4 Background Speech

Interfacing with the speech synthesizer is non-trivial. Care must be taken to give the speech synthesizer time to executes its commands, and the input FIFO must not be allowed to overflow, otherwise garbage/garbled speech is the result. The words SAY and STREAM use interrupts to 'drip feed' the speech synthesizer with data. However, it should be noted that interrupts are only breifly enabled and then disabled again in TurboForth during the operation of words that accesses video memory. Consequently, for speech to function properly it some type of video access should occur regularly. The reason it is possible to execute speech words from the command line is that the cursor is flashing, which causes the VDP interrupts to fire, which gives the speech driver an opportunity to execute and service the speech synth. In practice, this is isn't a big problem, as speech tends to be used in games, where reads/writes to the video memory are of quite a high frequency, thus giving the speech driver plenty of opportunities to execute. The alternative would be to enable interrupts all the time, however this would have the un-desirable side-effect of slowing down the main execution thread (your Forth program).

11.5 Determining Speech Synthesizer Status

It is possible to poll the speech synthesizer and see if it is busy (talking). Simply use the word TALKING?

TALKING? ( -- true/false)

As can be seen, TALKING? returns either true or false. True means the speech synthesizer is busy (talking). This word should be used when you need to send successive speech phrases to the synthesizer; as you will want to ensure that one phrase has finished before the next one starts:

Example

The following program says "I like Green", then it says "I like Red". In between the two phrases, it waits to allow the first phrase to finish before starting the next one.

Note that WAIT, as discussed above in 11.4, access video memory (it does a read from VDP memory address 0 and then simply drops the result, as it is not needed. This gives the VDP interrupts a chance to executes, which in turn allows the speech driver to run, which feeds the data to the synthesizer.

The loop in WAIT simply checks the synthesizer by calling TALKING? and loops until False is returned by TALKING?. The word NOT in the loop simply inverts the result returned by TALKING?, since UNTIL loops until the result passed to it is true. Since we want the loop to exit on a false, we invert the result returned by TALKING?.

An alternative, (though slightly slower) version would be:

: WAIT BEGIN 0 V@ DROP TALKING? FALSE = UNTIL ;

Where, as can be seen, the loop repeats 'until false'. I.e. Until TALKING returns false. Here, the result from TALKING? is compared to FALSE using the word = (i.e. is the result returned from TALKING? equal to FALSE).

11.6 Determining if Speech is Supported

It is not necessary for your Forth program to determine if the speech synthesizer is fitted to the machine. In the event that the speech sythesizer is not fitted, the speech driver aborts and returns immediately. Therefore your Forth code can simply assume that speech is available and the system will take care of the rest.