Speech

#include "libtini/audio.h"

The SSI-263 on the slot-4 card speaks prepared phrases and numbers. tools/speech.py changes text into phonemes on the host. The game identifies phrases by generated names. The audio driver sends one phoneme in each update.

FunctionPurpose
ti_speech_bindSelect the phrase bank
ti_speech_sayQueue a phrase, or interrupt with a phrase
ti_speech_numberQueue a number from 0 to 9999
ti_speech_busyTell if a phrase speaks or waits
ti_speech_stopCancel all speech and power down
ti_speech_voiceSet preset, pitch and rate

Prepare speech

Speech is a part of the audio driver. Set speech in the audio configuration. Start audio. Then bind the bank that tools/speech.py made. Call ti_audio_update frequently. It sends the next phoneme when the chip reports that the last phoneme is complete.

python tools/speech.py speech.json --preview
python tools/speech.py speech.json --output build/my_speech.h --symbol my_speech
#include "my_speech.h"     /* SAY_READY, SAY_GAME_OVER, ... and my_speech */

static ti_audio_config audio = {TI_AUDIO_MOCKINGBOARD, 1, 1, 0, 0};

ti_audio_init(&audio);
ti_speech_bind(&my_speech);
ti_speech_say(SAY_READY, 1);
ti_speech_number(score, 1);         /* "one thousand nine hundred eighty four" */

Music, effects and speech and Data formats describe the phrase file and the vocabulary of the compiler.

Queue and priorities

One phrase speaks, and a maximum of four phrases wait (TI_SPEECH_QUEUE). A priority is 0-127. Of the phrases that wait, the phrase with the highest priority speaks next. Phrases with the same priority keep their order.

To start a phrase immediately, add TI_SPEECH_INTERRUPT (128) to its priority. The new phrase stops the current phrase when its priority is the same or higher. The queue of phrases that wait does not change. A number is one queue item, also when it has several words.

Constants and types

NameValueMeaning
TI_SPEECH_QUEUE4Items that can wait in addition to the item that speaks
TI_SPEECH_INTERRUPT128Priority flag: replace the current phrase

ti_phrase

typedef struct ti_phrase { const uint8_t *data; uint8_t length; } ti_phrase;

One prepared phrase: 1-255 SSI-263 phoneme bytes in near memory. Each phoneme is a separate write to the chip, also when the same phoneme repeats.

ti_speech_bank

typedef struct ti_speech_bank {
    const ti_phrase *phrases;
    uint8_t count;
    const uint8_t *number_ids; /* 0..19, twenty..ninety, hundred, thousand; NULL omits numbers */
} ti_speech_bank;

A bank is a table of phrases. Optionally it also gives the phrase numbers of the thirty number words: zero to nineteen, twenty to ninety, hundred and thousand. tools/speech.py makes the full bank. With --no-numbers, it does not add the number words and sets number_ids to NULL. The driver uses the bank and all its data until the next bind or until audio stops.

Functions

ti_speech_bind

ti_error ti_speech_bind(const ti_speech_bank *bank);

This function checks the bank and makes it the current bank. It cancels the speech in progress. You can also bind a bank before ti_audio_init.

Returns

TI_OK; TI_E_ARGUMENT for a bank, phrase table or number table that the function cannot read, or zero phrases; TI_E_RANGE for an empty phrase, a phrase that the function cannot read, or a number word that is not a phrase of the bank.

ti_speech_say

ti_error ti_speech_say(uint8_t phrase, uint8_t priority);

This function queues phrase number phrase of the bound bank. With TI_SPEECH_INTERRUPT, it starts the phrase immediately. The function returns immediately. The speech continues in ti_audio_update.

Returns

TI_OKThe phrase is in the queue or speaks.
TI_E_RANGENo bank is bound, or the phrase number is not less than the count of the bank.
TI_E_UNAVAILABLEAudio does not run, speech is not enabled, or a speech timeout occurred. After a timeout, speech stays off until audio starts again.
TI_E_BUSYAn interrupt phrase has a lower priority than the phrase that speaks.
TI_E_FULLFour items already wait.

ti_speech_number

ti_error ti_speech_number(uint16_t value, uint8_t priority);

This function queues a number as usual cardinal English, without "and". For example, 1001 is "one thousand one" and 1984 is "one thousand nine hundred eighty four". It joins a maximum of six words into one queue item. This code is a separate archive module. The linker adds it only to programs that call it.

Returns

The same results as ti_speech_say, with these differences: TI_E_STATE when no bank is bound, TI_E_RANGE above 9999, and TI_E_UNAVAILABLE when the bank has no number words.

ti_speech_busy

uint8_t ti_speech_busy(void);

This function returns nonzero while a phrase speaks or waits. A game can use it to skip a minor phrase when a different phrase plays: if (!ti_speech_busy()) ti_speech_say(SAY_POWER, 1);

ti_speech_stop

void ti_speech_stop(void);

This function cancels the current phrase and the waiting phrases, and powers down the SSI-263.

ti_speech_voice

ti_error ti_speech_voice(uint8_t preset, uint8_t pitch, uint8_t rate);

This function cancels the waiting speech and sets the voice. preset 0-2 selects one of three articulation and amplitude settings. pitch is the SSI-263 inflection value. rate 0-15 goes into the rate field of the chip. Audio init sets preset 0, pitch 0x40 and rate 10. The chip stays powered down until the next phrase.

Returns

TI_OK; TI_E_UNAVAILABLE when audio does not run or speech is not enabled; TI_E_ARGUMENT for a preset above 2 or a rate above 15.

How the driver controls the SSI-263

In standalone ONE//e mode, speech needs Appletini firmware F1.3.2 or later. F1.3.2 clocks the two speech engines from the virtual PHI0 in standalone mode. When a speech chip is configured, the driver tries to use it; the configuration does not prove that a chip is present. Show essential messages on the screen as captions too.