- presentazione del sito
- Registrazione
- Eventi, mostre, convegni ed iniziative segnalate dalle aziende
- Recensioni ed articoli
- Le Mailing Lists
- La rivista Pc Ciechi
- Wiki
- Chi siamo
- Donazioni
- Un progetto degno di nota: Wintalbra
- Come navigare in questo sito
- rss
- Bancomat Accessibili sul territorio nazionale
- Contattaci
- I sostenitori di SpazioAusili
sintesi:indicazioni per la creazione di un dizionario specifico
adriano barbieri su uiciechi.it, 2009-01.
Ogni sintesi vocale può gestire la punteggiatura, ma non sempre allo stesso modo; è importante quindi sapere come poter interagire rispettando il loro
modus operandi.
Ed ora, un po' di pubblicità
:La punteggiatura serve a creare una pausa più o meno lunga, durante la lettura di un testo, il punto fermo è quello più delicato. Infatti, se è seguito
da almeno uno spazio, si trovi a fine riga, o inserito in un acronimo del tipo "s.p.a.", la sintesi vocale si comporterà in modo diverso a seconda dei
casi; in effetti non sempre il punto fermo indica una pausa.
Per far sì che la pausa venga rispettata occorre che il punto fermo sia seguito da almeno uno spazio, o sia a fine riga e seguito da il carattere di ritorno
a capo.
Queste condizioni sono sufficienti per alcune sintesi vocali, mentre per altre come e-speak, non bastano, occorre che anche l'iniziale che segue sia maiuscola;
ma non solo; che prima del punto fermo vi siano almeno due caratteri.
Quest'ultima condizione è comune a molte sintesi vocali, se ne avete più d'una, provate questi semplici test:
a. b. (due minuscole separate da punto e spazio)
a.b. (due minuscole separate da un punto).
A. B. (due maiuscole separate da punto e spazio).
A.B. (due maiuscole separate da un punto).
a.b.c. (tre minuscole separate da un punto).
A.B.C. (tre maiuscole come sopra).
a. b. c. (tre minuscole separate da un punto più uno spazio).
A. B. C. (tre maiuscole come sopra).
ab. c. (due minuscole e una minuscola separata da un punto più uno spazio).
ab. C. (due minuscole e una maiuscola separata come sopra).
AB. C. (due maiuscole e una maiuscola separata come sopra).
Noterete che ogni sintesi interagirà inserendo le pause in modi diversi come ho spiegato sopra.
E-Speak richiede almeno due caratteri prima del punto, uno spazio, e una lettera maiuscola, quindi, è neccessario creare un dizionario ad hoc, che permetta
di conservare il formato dell'iniziale di ogni parola e nei limiti del possibile anche tutto il resto di quest'ultima.
Prima occorre, però, spiegare alcune problematiche, perchè capendo il loro meccanismo saremo in grado di aggirarle.
Prendiamo ancora ad esempio il nome Sophia. Il metodo per processare e successivamente correggere il nome Sophia, in Sophìa, con l'ultima "ì" accentata
al posto della "i" normale, potrebbe essere così:
"SOPHIA|[sS]ophia(\W)", parola in sostituzione "sophìa\1".
Questo approccio è funzionale solamente nel matching, però non permette di preservare l'iniziale corretta, ma si limita a correggere la parola, utilizzando
una forma minuscola e fissa nella parola in sostituzione, compresa l'iniziale "s".
Test. sophia, con iniziale minuscola.
Test. Sophia, con iniziale maiuscola.
Se si prova le due righe di test appena descritte utilizzando una sintesi della Loquendo, si potrà notare che la pausa che precede il nome "Sophia" verrà
rispettata a prescindere dalla iniziale della parola.
Cosa diversa se si provasse con Silvia della Nuance Real Speak, o con e-speak di Nvda.
La soluzione di usare sistematicamente tutte le iniziali delle parole nel campo di sostituzione in maiuscolo avrebbe degli ulteriori inconvenienti.
Nota bene, dalla snapshot 2493 sono stati apportati alcuni cambiamenti:
Il file di configurazione nvda.ini e SpeechDicts sono ora salvati nella cartella "dati applicazioni" dell'utente,questo, se nvda viene installato tramite
la versione installer.
La modifica è stata neccessaria per Vista e anche altri sistemi multiutente, in modo che ogni utente potrà avere nvda con la propria configurazione individuale.
Il dizionario di default.dic non essendo più presente la cartella SpeechDicts nei pacchetti di Nvda, è stato incorporato e renominato con "Builtin.dic".
Ad ogni aggiornamento dello ScreenReader non ci sarà più pericolo di sovrascrittura, ma il dizionario di default è comunque sempre a disposizione all'utente,,
mantiene la priorità sui "specifici", ed è secondario al "Builtin".
Inserendo una regex come questa:
# guaina. "GUAINA|[gG]uaina(\W)", e in sostituzione "Guàina\1".
La quale si limita a sostituire l'iniziale con una analoga maiuscola e la prima "a", con la "à accentata".
L'iniziale fissa maiuscola consente il rispetto della pausa con sintesi come silvia, ed e-speak ; ma la parola "Guaina", è contenuta ad esempio anche nella
parola "Sguaina", "Inguaina", "Sguainala", eccetera.
Incontrando tale parola, notare l'iniziale "s" maiuscola, la nostra regex la correggerebbe sostituendo "guaina" in "Guàina".
La correzione formerebbe una parola così: "SGuàina", notare le prime due lettere "SG" maiuscole.
Come mai la s risulta "staccata"?
Questa interferenza è generata dal dizionario "builtin.dic" di Nvda, la seguente regex ne è la causa:
#Break away a word starting with a capital from a fully uppercase word
"([A-Z])([A-Z][a-z]) \1 \2 1 1".
Come si può notare per chi mastica inglese, la regex si incarica di staccare quelle parole composte da una completamente maiuscola seguita da un'altra
con l'iniziale maiuscola, come ad esempio: "WORDPad", "FIREFox", "OPENOffice", eccetera.
L'uso di un'iniziale fissa maiuscola limita la versatilità delle Regex; la Regex builtin ci obbligherebbe a inserire una nuova voce al nostro dizionario
per la parola "Sguaina", dovendo inserire alla sua sinistra anche il metacarattere "\b" (barra rovesciata diagonale b) per evitare un conflitto tra le
due, e limitando il più possibile ogni contatto di ulteriori parole, così:
# Guaina. "(\b)(GUAINA|[gG]uaina)(\W)", e in sostituzione "\1Guàina\3".
il problema però si può aggirare sfruttando la capacità di memorizzazione dei gruppi tra parentesi tonde, e l'aiuto di una classe; salviamo quindi l'iniziale
di "guaina", in questo modo: "([gG])".
La classe "[gG]" permette di scegliere uno dei due caratteri predefiniti, mentre il gruppo serve a memorizzarlo. Il contenuto memorizzato lo si può richiamare
nel campo della parola in sostituzione con "\1" (barra diagonale rovesciata uno), come nell'esempio che segue:
"([gG])UAINA|uaina(\W)", parola in sostituzione "\1uàina\2".
Abbiamo fatto sì che l'iniziale della nostra parola sia variabile e non più costante; se si incapperà nuovamente nella parola "Sguaina", la nostra Regex
si adatterà al resto della parola in sostituzione, ottenendo "Sguàina", notare che sta volta di maiuscola c'è rimasta solo la "S". Abbiamo così aggirato
un problema, ma non sarà l'unico, vediamo perchè.
La nostra regex funziona bene solo se incontra una parola nella forma in minuscolo, anche se in realtà è in grado di riconoscere la parola nei due formati;
il motivo è che abbiamo lasciato una parte fissa in minuscolo nel campo di sostituzione. Ecco come viene rielaborata la parola incontrata nei due formati:
Guàina. (in minuscolo; la prima "à" accentata ci salva). SGuàina. (in maiuscolo; sta volta no, perchè?).
Per l'ennesima volta il dizionario "Builtin", è la causa di questo secondo problema:
#break up words that use a capital letter to denote another word "([a-z])([A-Z]) \1 \2 1 1".
Analogamente alla precedente, questa si occupa di "staccare" le parole, quelle però che hanno l'iniziale maiuscola da quelle in minuscolo che la precedono,
come WinFax, WordPad, AdrianoBarbieri, eccetera.
È un'altra regex utile, ma limitante perchè impedisce l'uso di regex più complesse, preposte a processare più ricorrenze di una stessa parola, come ad
esempio questa:
# Leggici/mi/ti/la/le/li/lo. "([lL])EGGI|eggi([cCmMtT][iI]|[lL].)(\W)", voce in sostituzione "\1èggi\2\3".
Che può processare le seguenti varianti:
eggici
leggimi
leggiti
leggila
leggile
leggili
leggilo
La regex mette la giusta iniziale nel gruppo uno, e sostituisce la prima vocale "e", con la "è accentata", aggiungendo il valore processato nei gruppi
due e tre, sfruttando una parte fissa in minuscolo della parola "ggi", ottenendo una cosa del genere:
leggimi = lèggimi; tutto in minuscolo va bene.
LEGGIMI = LèggiMI; in maiuscolo, la "MI" alla fine viene staccata dal resto della parola in minuscolo a causa della Regex del dizionario "builtin" di Nvda.
Ovviamente l'effetto è ancora più pronunciato con parole più lunghe.
Quelle "due" ci attaccano da due fronti, ed hanno sempre la priorità sui nostri dizionari. Non vogliamo e non conviene eliminarle, perché, dopotutto, hanno
la loro utilità.
Una soluzione è di aggirare queste due regex "builtin" sfruttando il loro "tallone d'Achille", le vocali accentate, che per nostra fortuna non vengono
considerate, per ora!
Sfruttando appieno i "gruppi" che permettono di memorizzare il risultato di un processo in esso contenuto, per salvare e recuperare l'iniziale, ma anche
altre parti di una parola, combinati opportunamente con le vocali accentate, ecco più o meno come sarà la nostra nuova Regex:
"([lL])[eE](GGI|ggi)([cCmMtT][iI]|[lL].)(\W)", voce in sostituzione "\1è\2\3\4".
Qui, ogni singolo gruppo processa e memorizza la parte di parola ad esso assegnata, escludendo l'unica classe esterna ai gruppi, i quali, richiamati, come
pezzi di un puzzle si occupano di aggiungere le varie parti che completano la nostra parola, mantenendo il formato dell'originale. In tal modo le ricorrenze
di prima vengono convertite così:
leggimi = lèggimi. (in minuscolo).
Leggimi = Lèggimi. (iniziale maiuscola e resto minuscolo).
LEGGIMI = LèGGIMI. (tutto maiuscolo).
E così via per le altre ricorrenze precedentemente elencate. Tutta la parola viene preservata e ricomposta nella sua forma originale, a parte la vocale
nella classe "[eE]", che nel nostro caso viene sostituita dalla "è accentata".
Nel tentativo di rendere più chiara possibile la comprensione della sintassi delle Regex, non ho usato una forma "nidificata" che solitamente preferisco
adottare, altrimenti ecco come sarebbe stata:
"([lL])[eE]((GGI|ggi)([cCmMtT][iI]|[lL].)\W)", voce in sostituzione "\1è\2".
La forma nidificata la trovo più comoda nel caso di modifica. Vi ricordo che i "gruppi" vanno contati da sinistra verso destra, e nei gruppi nidificati
ha priorità il primo gruppo più esterno che ne contiene; negli esempiche seguono userò una classe vuota indicante la vocale da accentare, e nel campo di
sostituzione userò un punto esclamativo per indicarne il punto d'inserimento:
"(1)[](2)(3)" = "\1!\2\3".
"(1(2))[](3)" = "\1!\3".
"(1(2)(3))[](4)(5)" = "\1!\4\5".
"(1(2))[](3(4)(5)(6))" = "\1!\3".
La struttura della nostra nuova Regex si adatterebbe a quasi tutte le sintesi vocali, ma E-speak ha un ulteriore problema, non vocalizza allo stesso modo
le vocali accentate, c'è una lieve differenza di inflessione da una minuscola a una maiuscola. Quindi, non è sempre possibile sfruttare le Regex a struttura
"multipla" che processano la parola nei due formati maiuscolo/minuscolo.
Con E-Speak occorrono due Regex, una per ogni formato della parola; questo, almeno per quelle espressioni regolari preposte a gestire più ricorrenze di
una stessa parola.
Per ognuna occorre usare una vocale maiuscola o minuscola a seconda del formato da processare, quindi partendo dall'esempio dell'ultima Regex, ecco come
deve essere convertita nel formato esteso:
# Leggici/mi/ti/la/e/i/o minuscolo.
"([lL])e(ggi)([cmt]i|l.)(\W)", voce in sostituzione "\1è\2\3\4".
# Leggici/mi/ti/la/e/i/o, maiuscolo.
"(L)E(GGI)([CMT]I|L.)(\W)", voce in sostituzione "\1È\2\3\4".
Ecco la stessa coppia di Espressioni regolari ma nella versione nidificata:
# Leggici/mi/ti/la/e/i/o, minuscolo.
([lL])e(ggi([cmt]i|l.)\W)", voce in sostituzione "\1è\2".
# Leggici/mi/ti/la/e/i/o, maiuscolo.
(L)E(GGI([CMT]I|L.)\W)", voce in sostituzione "\1È\2".
Questo sistema a doppia Regex si può evitarlo nelle parole uniche che non hanno ricorrenze come ad esempio "Sophia":
"([sS])(OPHIA|ophia)(\W)", voce in sostituzione "\1ophìa\3".
In ogni caso, qualsiasi metodo si adotti, bisogna sempre stare attenti ai possibili conflitti tra Regex con parole che potrebero essere contenute all'interno
di altre. In tal caso si deve fare in modo di "chiudere" queste regex utilizzando il giusto metacarattere escaped, nella maggior parte dei casi si può
usare "\b" (barra diagonale rovesciata b minuscola) all'inizio, mentre alla fine "\W" (barra diagonale rovesciata W maiuscola) alla fine dell'espressione
regolare; in alcuni casi la "\b" può essere anche usata alla fine in combinazione con una classe che neghi, ad esempio, anche le vocali: "(\b[^ÀÈÉÌÒÓÙàèéìòóù])".
Le vocali accentate "filtrano", quindi l'uso dei soli metacaratteri escaped a volte va affiancato alla negazione sistematica delle vocali accentate, prendete
ad esempio questa parola: "url". Essa è contenuta anche in "urlo", o "urlò", o "urlìo", e tante altre.
Chiudere questa parola con "\W" funziona bene con "urlo", ma non con "urlò", o urlìo". Le ultime due parole, infatti, hanno una vocale accentata che nessun
metacarattere può escludere; quello più efficace è "\b", ma anche questo lascia filtrare le vocali accentate. Ma con una classe di negazione come "[^ÀÈÉÌÒÓÙàèéìòóù]"
di rinforzo si può.
# Url.
"\b[uU])([rR])([lL])(\b[^àèéìòóùÁÉÈÍÒÓÚ])", voce in sostituzione "\1 \2 \3\4".
Per essere sicuro che una nuova Regex inserita nel mio dizionario, funzioni senza conflitti, aggiungo temporaneamente un", ok" al termine della stringa
di sostituzione.
Può succedere benissimo che la nuova Regex non funzioni, non perchè sbagliata, ma perchè un'altra molto simile "non chiusa" interviene prima perchè essendo
più in cima ne assume la priorità.
In tal caso se quest'ultima la si "chiude", o la si sposta subito sotto, tutto funziona. Tenetelo sempre in mente.
Ecco un valido motivo del perchè il modulo dizionario non ordini alfabeticamente le voci in modo automatico, come ad esempio invecee fa Jaws che al momento
non usa le Regex.
La cosa che invece manca è un campo di ricerca e la possibilità di inserire una voce nel punto desiderato, mentre attualmente il modulo si limita ad "accodare"
le nuove immissioni, obbligando a sistemare manualmente i conflitti con un editor esterno come il blocco note, che purtroppo non è affidabile con files
molto grossi.
Ecco perchè io uso NotePad++.
********
Per ulteriori spiegazioni, scrivere a: Adriano Barbieri.