La classe SpeechSynthesizer del .NET Framework 3.0 (di cui ho già parlato in questo post) consente di redirezionare l'output del Text-To-Speech su varie destinazioni, ovvero l'uscita audio del PC (default), un file WAV oppure un generico Stream. Sfruttando quest'ultimo, è possibile realizzare uno Speech Server minimale in grado di fornire funzionalità di Text-To-Speech anche a sistemi che non hanno la potenza adatta per gestire un motore di TTS oppure che non dispongono di una sua implementazione (come nel caso dei Pocket PC con il .NET Compact Framework 2.0).
L'idea è semplice: sul server è in esecuzione un servizio che accetta le connessioni dai vari client, quindi legge la stringa che si vuole venga pronunciata, crea uno stream contenente il "parlato" e lo restituisce indietro. In tal modo, quest'ultimo non deve fare altro che riprodurre lo stream (che è semplicemente uno stream WAV) per ottenere l'effetto del Text-To-Speech. Il cuore dello Speech server è il seguente:
1 using(MemoryStream ms = new MemoryStream())
2 {
3 //Legge la stringa dalla connessione TCP.
4 //...
5
6 //Genera il Text-To-Speech.
7 using (SpeechSynthesizer ss = new SpeechSynthesizer())
8 {
9 ss.SelectVoice("ScanSoft Silvia_Dri40_16kHz");
10 ss.SetOutputToWaveStream(ms);
11 ss.Speak(text);
12 }
13
14 //Converte lo stream in array di byte e lo invia al client.
15 //...
16 }
In particolare, la riga 10 redireziona l'output del Text-To-Speech su un MemoryStream, che poi viene convertito in byte e rispedito al mittente. Naturalmente è possibile tutta una serie di ottimizzazioni: ad esempio, si può comprimere l'array di byte prima di inviarlo al client, in modo da limitare la quantità di dati che passano sulla rete e riducerre così il tempo di risposta.