PBToolboxAI v3 ← Site

speechout — n_pbt_speechout #

← Riferimento dei componenti · Sommario della guida

Lettura ad alta voce: l'applicazione legge un testo frase per frase e ti dice a che punto è. Nessun servizio di terze parti, nessuna chiave API — la sintesi è quella della postazione.

▶ Vederlo dal vivo — Applicazione dimostrativa, riquadro Speech out: l'anteprima, il codice che la produce e questa pagina, fianco a fianco.


In breve #

Oggetto non visualen_pbt_speechout
Serve aFar sentire un testo: accessibilità, mani occupate, una notifica che nessuno guarda
PrincipioTu dai il testo; il componente lo divide in frasi e ti dice quale sta leggendo
DipendenzaLa sintesi vocale della postazione — nessun servizio di terze parti, nessuna chiave API

Avvio rapido #

// once, when the window opens
inv_voice.of_open()

// then, wherever you need it
inv_voice.is_lang = inv_voice.LANG_FR_FR
inv_voice.of_speak("Bonjour. Votre commande est expediee.")

Non visuale: il cablaggio degli eventi #

Una voce non ha nulla da mostrare. Il componente quindi non disegna niente: nessuna barra di riproduzione da sistemare, nessuno spazio tolto a ciò che serve.

E per questo non devi collegare nulla: un oggetto non visuale non ha finestra, quindi niente campanello, ma il componente preleva da solo i suoi eventi sul loop PowerBuilder finché la voce è aperta e li solleva sull'oggetto. Scrivi solo i gestori ue_* (nessun ricevitore, nessun timer).

// Just speak -- the ue_* events arrive on their own :
inv_voice.of_speak("Good morning. Your order has shipped.")
// the ue_sentence / ue_word / ue_stopped events arrive on their own

Seguire la lettura nel TUO testo #

ue_sentence porta l'indice e il testo della frase in lettura. Da lì viene l'evidenziazione — nel tuo mle_, nella tua datawindow o nel tuo statictext: tu sai dov'è il tuo testo, noi mai.

Esiste anche il percorso inverso: of_speak_from() riprende da una frase precisa, cosa che si collega al clic su un paragrafo. I numeri vengono da ue_sentence, quindi indicano sempre ciò che è stato davvero letto.

Il taglio è quello del componente, non il tuo: of_sentence_count() restituisce il suo conteggio. Non ricontare dalla tua parte, i due divergerebbero.


Ciò che la postazione sa davvero dire #

of_languages() restituisce le lingue che questa postazione sa effettivamente pronunciare, senza duplicati. È la domanda che si pone un utente: non «quali voci esistono», ma «c'è la mia lingua».

of_voices() scende di un gradino e nomina le voci stesse. Entrambi gli elenchi vengono dalla macchina, non da noi: non scrivere mai un nome fisso nel codice.

Il riconoscimento vocale non ha un equivalente, e non è una dimenticanza: il riconoscimento non porta alcun elenco delle lingue che accetta.

Senza alcun componente da parte tua, gnv_utils.of_speech_languages(as_tags[]) dà lo stesso elenco — la DLL interroga una voce nascosta, poi la elimina: è ciò che una finestra chiede prima che la voce esista, quale lingua proporre, in quale leggere. La chiamata è sincrona e può richiedere fino a due secondi la prima volta: l'elenco delle voci arriva tardi, e la chiamata lo aspetta. E gnv_utils.of_speech_voices(as_names[], as_langs[]) dà le voci stesse con la loro lingua, per proporre «Hortense» o «Julie» anziché un tag; gnv_utils.of_locale_name(as_tag) dà a un tag il suo nome leggibile — «francese (Francia)» per fr-FR.

string ls_tags[]

if inv_voice.of_languages(ls_tags) > 0 then inv_voice.is_lang = ls_tags[1]

Proprietà #

ProprietàTipoPredefinitoRuolo
is_langstringen-USLingua letta, in BCP-47 (costanti LANG_*). Decide quale voce viene scelta — finché is_voice è vuota, poiché un nome di voce fissa la propria lingua. Senza una voce per quella lingua la postazione legge con quella che ha, e ue_voice_fallback le nomina entrambe
is_textstring""Il testo da leggere. Il componente lo taglia in frasi; tre tag dicono COME leggere un pezzo: [pause=500], [spell]…[/spell], [say-as=digits]…[/say-as] (vedi sotto)
is_voicestring""Nome della voce, preso da of_voices(). Vuoto = la prima che parla is_lang
ii_rateinteger100Velocità, in PER CENTO di quella normale (da 10 a 400). Cambiata durante la lettura, vale dalla frase successiva
ii_pitchinteger100Altezza della voce, in PER CENTO dell'altezza normale (da 0 a 200)
ii_volumeinteger100Volume in percento (0 muto a 100), la scala del lettore video
il_timeout_mslong300000Durata massima di una lettura SINCRONA: cinque minuti. Oltre, of_speak_sync rende -4 e la lettura viene interrotta (is_last_error dice perché)
is_last_errorstring""Perché l'ultimo of_speak_sync ha reso -4: voce non creata, motore in errore, tempo scaduto

Metodi #

MetodoRuolo
of_open ( )Crea la voce. Facoltativo — of_speak lo fa — ma chiamarlo all'apertura della finestra paga il costo una volta, lontano dalla prima frase. Restituisce un numero positivo quando la voce esiste, 0 o meno se non ha potuto essere creata
of_is_open ( )Vero una volta creata la voce
of_speak ( string as_text )Imposta il testo e lo legge, dalla prima frase. Senza argomento, rilegge is_text. Restituisce 0 una volta inviato, -1 se la voce non ha potuto essere creata
of_speak_from ( long al_index )Riprende la lettura da una frase precisa. Restituisce 0 una volta inviato, -1 se la voce non ha potuto essere creata
of_pause ( )Sospende la lettura dov'è. Restituisce 0 una volta inviato, -1 se la voce non ha potuto essere creata
of_resume ( )Riprende da dove of_pause si era fermato. Restituisce 0 una volta inviato, -1 se la voce non ha potuto essere creata
of_stop ( )Ferma la lettura; of_speak riparte dalla prima frase
of_is_speaking ( )Vero finché una frase viene letta — una lettura in pausa conta ancora. Chiesto al componente, mai una copia scaduta
of_sentence_count ( )Restituisce quante frasi il componente ha ricavato dal testo
of_count ( ) → integerQuante frasi il componente ha ricavato dal testo — lo stesso numero che rende of_sentence_count. La libreria pone questa domanda sotto un solo nome ovunque
of_voices ( ref string as_names[] )Riempie l'array con le voci installate su questa postazione e ne restituisce il numero
of_languages ( ref string as_tags[] )Riempie l'array con le lingue che questa postazione sa pronunciare, senza duplicati, e ne restituisce il numero
of_voice_used ( )La voce che il componente consegnerà davvero al motore — non sempre quella chiesta da is_lang: una postazione porta le voci che qualcuno vi ha installato e nessun'altra. Vuoto = il componente non ne impone alcuna, e il motore prende la sua, quella della lingua di sistema. Nominarla sarebbe indovinare. ue_error lo dice al momento di leggere; questo si legge prima
of_speak_sync ( { string as_text } )Legge e ATTENDE la fine: la riga seguente gira dopo l'ultima frase, la finestra continua a dipingersi. Rende 0 alla fine, -4 in caso di errore o tempo scaduto (is_last_error)
of_enqueue ( string as_text )Mette un testo in CODA: letto subito se la voce è libera, dopo la lettura in corso altrimenti, senza mai tagliarla. Rende 0, -1 se la voce non ha potuto essere creata
of_clear_queue ( )Dimentica i testi in attesa, senza tagliare quello in lettura. Rende 0, -1 se la voce non ha potuto essere creata
of_queue_count ( )Rende il numero di testi ancora in attesa (quello in lettura non è contato)
of_add_replacement ( string as_from, string as_to )Una regola di pronuncia: ogni parola INTERA as_from è letta as_to (PB → PowerBuilder). Applicata prima dei tag, conservata dall'oggetto. Rende 0, -5 se as_from è vuoto
of_clear_replacements ( )Svuota il dizionario. Rende 0
of_replacement_count ( )Rende il numero di regole del dizionario
of_pick_voice ( string as_lang, string as_gender )Sceglie una voce INSTALLATA per una lingua e, se esiste, un genere (GENDER_FEMALE, GENDER_MALE, GENDER_ANY): lingua esatta, poi la sua famiglia. La mette in is_voice e la rende; vuoto se nessuna voce parla quella lingua
of_duration ( )Rende la durata STIMATA della lettura, in millisecondi (parole al minuto alla velocità richiesta, pause comprese): per una barra di avanzamento, non per un cronometro. Il ritmo IMPARA la voce: ogni frase letta fino in fondo misura quello reale, ricordato per voce su questa postazione
of_position ( )Rende la posizione stimata della lettura, in millisecondi, affinata dalle parole che il motore riporta; 0 quando nulla si legge
of_progress ( )Rende l'avanzamento stimato, da 0 a 100
of_spoken_text ( )Le frasi COME la voce le riceve, una per riga (dizionario applicato, tag risolti): il testo da mostrare per seguire parola per parola
of_process_events ( )Svuota gli eventi in attesa e li solleva su questo oggetto. Il pump interno del componente lo chiama per te finché la voce è aperta — non lo chiami mai
of_close ( )Libera la voce, fermando prima ciò che stava dicendo. Il distruttore lo chiama
of_reset ( )Riporta tutte le proprietà al valore iniziale

Eventi #

EventoScatta quando
ue_started (string as_lang)La lettura comincia; as_lang ricorda in quale lingua
ue_stopped ( )L'ultima frase è finita, oppure è stato chiamato of_stop
ue_paused ( )La lettura è sospesa
ue_resumed ( )La lettura riparte
ue_sentence (long al_index, string as_text)Per ogni frase, con il suo rango e il suo testo: così si segue la lettura altrove nella finestra
ue_error (string as_message)La postazione non ha alcun motore o alcuna voce, o la voce fallisce. Una voce semplicemente ASSENTE non è un errore: è ue_voice_fallback
ue_voices_ready (long al_count)Il motore ha riempito l'elenco delle voci — arriva tardi; of_voices, of_languages, of_voice_used e of_pick_voice lo attendono da soli (2,5 s al massimo), questo evento dice solo QUANDO è arrivato; al_count dice quante ne ha la postazione
ue_word (long al_index, long al_start, long al_length)La PAROLA in corso nella frase al_index: Mid(frase, al_start, al_length). Quando il motore riporta le parole (la maggior parte delle voci Windows)
ue_queue_done ( )L'ultimo testo della coda (of_enqueue) è letto
ue_voice_fallback (string as_wanted, string as_used)La voce o la lingua richiesta non è su questa postazione; as_used nomina quella che legge al suo posto. Un'informazione, non un errore: la lettura continua

Pronuncia: pause, compitazione, dizionario #

WebView2 non ha SSML. Il testo porta quindi tre tag suoi, risolti prima del taglio in frasi, e un dizionario di parole intere applicato prima di essi. Un tag sconosciuto è letto così com'è.

TagEffetto
[pause=500]Un silenzio di 500 ms (10 s al massimo). La pausa termina la frase in corso
[spell]ABC12[/spell]Ogni carattere detto uno per uno: «A, B, C, 1, 2»
[say-as=digits]4152[/say-as]Le cifre una per una, non «quattromilacentocinquantadue»
[say-as=characters]…[/say-as]Come [spell]
// The dictionary : whole words, in the order added, case-sensitive
inv_voice.of_add_replacement("PB", "PowerBuilder")
inv_voice.of_add_replacement("Mme", "Madame")
inv_voice.of_add_replacement("4152", "[say-as=digits]4152[/say-as]")   // a rule may add a tag

inv_voice.of_speak("Mme Durand, PB order 4152 [pause=600] code [spell]PBT[/spell].")

Coda, lettura sincrona, avanzamento #


Esempi #

Leggere una notifica #

inv_voice.of_speak("Order 4152 has been shipped. It arrives on Thursday.")

Evidenziare la frase in corso #

// in ue_sentence, on the nonvisual object
st_read.text = as_text

// and a click on a paragraph resumes from it
inv_voice.of_speak_from(2)

Scegliere la voce e la velocità #

string ls_voices[]

if inv_voice.of_voices(ls_voices) > 0 then inv_voice.is_voice = ls_voices[1]
inv_voice.ii_rate = 75
inv_voice.of_speak()

Annunciare senza tagliare: la coda #

// Each event of the application is queued : all of them are heard, in order
inv_voice.of_enqueue("Order 4152 has been shipped.")
inv_voice.of_enqueue("Order 4153 is ready.")
// ue_queue_done fires after the last one

Evidenziare la parola in corso #

// in ue_sentence : keep the sentence
is_sentence = as_text

// in ue_word : the word is Mid(is_sentence, al_start, al_length)
st_read.text = Left(is_sentence, al_start - 1) + "[" + Mid(is_sentence, al_start, al_length) + "]" + Mid(is_sentence, al_start + al_length)

Una voce per lingua e genere, poi leggere aspettando la fine #

inv_voice.of_pick_voice(n_pbt_speechout.LANG_FR_FR, n_pbt_speechout.GENDER_FEMALE)
if inv_voice.of_speak_sync("Please confirm the order.") = 0 then
	li_answer = MessageBox("Order", "Confirm ?", Question!, YesNo!)
end if

Buone pratiche #


← Riferimento dei componenti · Sommario della guida