Programovanie

Hovoriace Java!

Prečo by ste chceli, aby vaše aplikácie hovorili? Pre začiatok je to zábava a vhodná pre zábavné aplikácie, ako sú hry. A je tu aj vážnejšia stránka prístupnosti. Nemyslím tu len na tých, ktorí sú prirodzene znevýhodnení pri používaní vizuálneho rozhrania, ale aj na situácie, keď je nemožné - alebo dokonca nezákonné - odtrhnúť zrak od toho, čo robíte.

Nedávno som pracoval s niektorými technológiami na získavanie informácií HTML a XML z webu [pozri „Prístup k najväčšej databáze na svete s pripojením Web DataBase“ (JavaWorld, Marca 2001)]. Napadlo mi, že by som mohol túto prácu a tento nápad spojiť, aby som vytvoril hovoriaci webový prehliadač. Takýto prehliadač by sa ukázal byť užitočný na počúvanie úryvkov informácií z vašich obľúbených stránok - napríklad nadpisov správ - rovnako ako počúvanie rádia, keď idete so psom alebo šoférujete do práce. Samozrejme, so súčasnou technológiou by ste museli so sebou nosiť prenosný počítač s pripojeným mobilným telefónom, ale tento nepraktický scenár by sa mohol v blízkej budúcnosti zmeniť s príchodom inteligentných telefónov s podporou jazyka Java, ako je Nokia 9210 (9290 v USA).

Z krátkodobého hľadiska bude možno užitočnejšia čítačka e-mailov, ktorá je možná aj vďaka rozhraniu JavaMail API. Táto aplikácia by pravidelne kontrolovala vašu doručenú poštu a vašu pozornosť by priťahoval hlas odnikiaľ hlásajúci „Máte novú poštu, chcete, aby som vám ju prečítal?“ V podobnom duchu zvážte hovoriacu pripomienku - spojenú s vašou aplikáciou denníka -, ktorá kričí „Nezabudnite na stretnutie so šéfom o 10 minút!“

Za predpokladu, že ste týmto myšlienkam predaní alebo máte nejaké dobré nápady, pôjdeme ďalej. Začnem tým, ako ukážem, ako dať dodaný súbor zip do práce, aby ste mohli okamžite začať pracovať a preskočiť podrobnosti implementácie, ak si myslíte, že je to príliš tvrdá práca.

Vyskúšajte motor reči

Ak chcete použiť modul reči, musíte do svojho CLASSPATH zahrnúť súbor jw-0817-javatalk.zip a spustiť com.lotontech.speech.Talker triedy z príkazového riadku alebo z programu Java.

Ak ho chcete spustiť z príkazového riadku, zadajte:

java com.lotontech.speech.Talker "h | e | l | oo" 

Ak ho chcete spustiť z programu Java, jednoducho vložte dva riadky kódu:

com.lotontech.speech.Talker talker = nový com.lotontech.speech.Talker (); talker.sayPhoneWord ("h | e | l | oo"); 

V tomto bode by vás asi zaujímalo, aký formát má formát „h | e | l | oo“ reťazec, ktorý zadáte na príkazovom riadku alebo zadáte do sayPhoneWord (...) metóda. Nechaj ma vysvetliť.

Rečový modul pracuje tak, že zreťazí krátke zvukové vzorky, ktoré predstavujú najmenšie jednotky ľudskej - v tomto prípade anglickej - reči. Tie zvukové ukážky, tzv alofóny, sú označené jedno-, dvoj- alebo trojpísmenovým identifikátorom. Niektoré identifikátory sú zrejmé a iné nie tak zrejmé, ako vidíte z fonetického vyjadrenia slova „ahoj“.

  • h - znie tak, ako by ste čakali
  • e - znie tak, ako by ste čakali
  • l - znie to, ako by ste čakali, ale všimnite si, že som zredukoval dvojité „l“ na jediné
  • oo - je zvuk pre „ahoj“, nie pre „robota“ a nie pre „príliš“

Tu je zoznam dostupných alofónov:

  • a - ako v kat
  • b - ako v kabíne
  • c - ako v kat
  • d - ako v bodke
  • e - ako v stávke
  • f - ako v žabke
  • g - ako v žabke
  • h - ako v ošípanej
  • i - ako u ošípanej
  • j - ako v prípravku
  • k - ako v súdku
  • l - ako v nohe
  • m - ako v met
  • n - ako na začiatku
  • o - ako v nie
  • p - ako v hrnci
  • r - ako v hnilobe
  • s - ako v sat
  • t - ako v sat
  • u - ako sa uvádza
  • v - ako v mať
  • w - ako na mokro
  • r - ako doteraz
  • z - ako v zoo
  • aa - ako vo falošnom
  • ay - ako v sene
  • ee - ako u včely
  • ii - ako na vysokej
  • oo - ako v chode
  • bb - variácia b s rôznym dôrazom
  • dd - variácia d s rôznym dôrazom
  • ggg - variácia g s rôznym dôrazom
  • hh - variácia h s rôznym dôrazom
  • ll - variácia l s rôznym dôrazom
  • nn - variácia n s rôznym dôrazom
  • rr - variácia r s rôznym dôrazom
  • tt - variácia t s rôznym dôrazom
  • rr - variácia y s rôznym dôrazom
  • ar - ako v aute
  • aer - ako v starostlivosti
  • ch - ako v ktorom
  • ck - ako pri kontrole
  • ucho - ako v pive
  • ehm - ako neskôr
  • omyl - ako v neskoršom (dlhší zvuk)
  • ng - ako pri kŕmení
  • alebo - ako v zákone
  • ou - ako v zoo
  • ouu - ako v zoo (dlhší zvuk)
  • ow - ako u kravy
  • oy - ako u chlapca
  • š - ako v zatvorenom stave
  • th - ako vo veci
  • dth - ako v tomto
  • uh - variácia u
  • wh - ako kde
  • zh - ako v ázijčine

V ľudskej reči sa výška slova zvyšuje a klesá v ktorejkoľvek hovorenej vete. Táto intonácia robí prejav prirodzenejším, emotívnejším a umožňuje odlíšiť otázky od výrokov. Ak ste niekedy počuli syntetický hlas Stephena Hawkinga, pochopili ste, o čom hovorím. Zvážte tieto dve vety:

  • Je to falošné - f | aa | k
  • Je to falošné? - f | AA | k

Ako ste už asi uhádli, spôsob, ako zvýšiť intonáciu, je používať veľké písmená. S tým musíte trochu experimentovať a naznačujem, že by ste sa mali sústrediť na dlhé samohlásky.

To je všetko, čo potrebujete vedieť o používaní softvéru, ale ak vás zaujíma, čo sa deje pod kapotou, čítajte ďalej.

Implementujte rečový modul

Rečový modul vyžaduje implementáciu iba jednej triedy so štyrmi metódami. Využíva Java Sound API zahrnuté v J2SE 1.3. Nebudem poskytovať komplexný návod k Java Sound API, ale naučíte sa príkladom. Zistíte, že toho nie je veľa, a komentáre vám povedia, čo potrebujete vedieť.

Tu je základná definícia Hovorca trieda:

balík com.lotontech.speech; import javax.sound.sampled. *; import java.io. *; import java.util. *; import java.net. *; hovorca verejnej triedy {private SourceDataLine line = null; } 

Ak bežíte Hovorca z príkazového riadku, hlavný(...) ako vstupný bod bude slúžiť nižšie uvedená metóda. Trvá prvý argument príkazového riadku, ak existuje, a odovzdá ho sayPhoneWord (...) metóda:

/ * * Táto metóda hovorí fonetickým slovom uvedeným v príkazovom riadku. * / public static void main (String args []) {Talker player = new Talker (); if (args.length> 0) player.sayPhoneWord (args [0]); System.exit (0); } 

The sayPhoneWord (...) metóda sa volá hlavný(...) vyššie, alebo sa dá zavolať priamo z vašej Java aplikácie alebo appletu podporovaného doplnkom. Vyzerá to komplikovanejšie, ako je. V zásade ide iba o krok slovom allophones - oddelené znakom „|"symboly vo vstupnom texte - a prehráva ich jeden po druhom cez zvukový výstupný kanál. Aby to znelo prirodzenejšie, spojím koniec každej zvukovej vzorky so začiatkom nasledujúcej:

/ * * Táto metóda hovorí daným fonetickým slovom. * / public void sayPhoneWord (reťazcové slovo) {// - Nastaviť fiktívne bajtové pole pre predchádzajúci zvuk - byte [] previousSound = null; // - Rozdelenie vstupného reťazca na samostatné alofóny - StringTokenizer st = nový StringTokenizer (slovo, "|", nepravda); while (st.hasMoreTokens ()) {// - Vytvorte názov súboru pre allophone - String thisPhoneFile = st.nextToken (); thisPhoneFile = "/ allophones /" + thisPhoneFile + ". au"; // - Získať údaje zo súboru - byte [] thisSound = getSound (thisPhoneFile); if (previousSound! = null) {// - Zlúčiť predchádzajúci alofón s týmto, ak môžeme - int mergeCount = 0; if (previousSound.length> = 500 && thisSound.length> = 500) mergeCount = 500; pre (int i = 0; i

Na konci sayPhoneWord (), uvidíte, že to volá prehrať zvuk(...) na výstup jednotlivej zvukovej vzorky (alofón) a táto zavolá vypustiť(...) na vypláchnutie zvukového kanálu. Tu je kód pre prehrať zvuk(...):

/ * * Táto metóda prehráva zvukovú ukážku. * / private void playSound (byte [] data) {if (data.length> 0) line.write (data, 0, data.length); } 

A pre vypustiť(...):

/ * * Táto metóda vyprázdni zvukový kanál. * / private void drain () {if (line! = null) line.drain (); skúsiť {Thread.sleep (100);} chytiť (výnimka e) {}} 

Ak sa teraz pozriete späť na sayPhoneWord (...) uvidíte, že existuje jedna metóda, ktorú som ešte nepokryl: getSound (...).

getSound (...) načíta vopred nahranú zvukovú vzorku zo súboru au ako dáta bajtov. Keď poviem súbor, mám na mysli zdroj, ktorý sa nachádza v dodanom súbore zip. Rozlišujem to tým, že spôsob, akým sa zmocníte zdroja JAR - pomocou getResource (...) metóda - postupuje sa odlišne od spôsobu, akým sa zmocníte súboru, čo nie je zjavná skutočnosť.

Pre podrobný prehľad čítania údajov, konverzie zvukového formátu a vytvárania inštancií zvukového výstupného riadku (prečo to nazývajú SourceDataLine, Neviem) a po zostavení bajtových údajov vás odkazujem na nasledujúce komentáre v kóde:

/ * * Táto metóda načíta súbor pre jeden alofón a * skonštruuje bajtový vektor. * / private byte [] getSound (String fileName) {try {URL url = Talker.class.getResource (fileName); Stream AudioInputStream = AudioSystem.getAudioInputStream (url); Formát audioformátu = stream.getFormat (); // - Prevod zvuku ALAW / ULAW na PCM na prehrávanie - if ((format.getEncoding () == AudioFormat.Encoding.ULAW) || (format.getEncoding () == AudioFormat.Encoding.ALAW)) { AudioFormat tmpFormat = nový AudioFormat (AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate (), format.getSampleSizeInBits () * 2, format.getChannels (), format.getFrameSize () * 2, format.getFrameRate (), true); stream = AudioSystem.getAudioInputStream (tmpFormat, stream); format = tmpFormat; } DataLine.Info info = nový DataLine.Info (Clip.class, format, ((int) stream.getFrameLength () * format.getFrameSize ())); if (line == null) {// - Výstupný riadok ešte nie je inštancovaný - // - Nájdeme vhodný druh riadku? - DataLine.Info outInfo = nový DataLine.Info (SourceDataLine.class, formát); if (! AudioSystem.isLineSupported (outInfo)) {System.out.println ("Priradenie riadku" + outInfo + "nie je podporované."); vyvolať novú výnimku („Zhoda s riadkom“ + outInfo + „nie je podporovaná.“); } // - Otvorte zdrojový dátový riadok (výstupný riadok) - line = (SourceDataLine) AudioSystem.getLine (outInfo); line.open (formát, 50000); line.start (); } // - Niektoré výpočty veľkosti - int frameSizeInBytes = format.getFrameSize (); int bufferLengthInFrames = line.getBufferSize () / 8; int bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes; byte [] data = new byte [bufferLengthInBytes]; // - Prečítajte si dátové bajty a spočítajte ich - int numBytesRead = 0; if ((numBytesRead = stream.read (data))! = -1) {int numBytesRemaining = numBytesRead; } // - Skráťte bajtové pole na správnu veľkosť - byte [] newData = nový bajt [numBytesRead]; pre (int i = 0; i

Takže, to je všetko. Syntetik reči v asi 150 riadkoch kódu vrátane komentárov. Nie je to však ešte celkom na konci.

Prevod textu na reč

Fonetické zadávanie slov by sa mohlo zdať trochu zdĺhavé, takže ak chcete vytvoriť niektorú z príkladov aplikácií, ktoré som navrhol v úvode, chcete ako vstup poskytnúť obyčajný text.

Po preskúmaní problému som v súbore zip uviedol experimentálnu triedu prevodu textu na reč. Keď ho spustíte, výstup vám poskytne prehľad o tom, čo robí.

Prevodník textu na reč môžete spustiť pomocou príkazu, ako je tento:

java com.lotontech.speech.Converter "ahoj" 

To, čo uvidíte ako výstup, vyzerá asi takto:

ahoj -> h | e | l | oo tam -> dth | aer 

Alebo čo tak spustiť to ako:

java com.lotontech.speech.Converter "Rád čítam JavaWorld" 

vidieť (a počuť) toto:

i -> ii like -> l | ii | k to -> t | ouu read -> r | ee | a | d java -> j | a | v | a world -> w | err | l | d 

Ak vás zaujíma, ako to funguje, môžem vám povedať, že môj prístup je dosť jednoduchý a pozostáva zo súboru pravidiel nahradenia textu, ktoré sa používajú v určitom poradí. Tu je niekoľko príkladov pravidiel, ktoré by ste možno chceli mentálne uplatniť, aby ste v prípade slov „mravec“, „chceli“, „hľadali“, „nechcene“ a „jedinečne“:

  1. Nahradiť „* unique *“ za „| y | ou | n | ee | k |“
  2. Nahradiť „* chcieť *“ výrazom „| w | o | n | t |“
  3. Nahradiť „* a *“ výrazom „| a |“
  4. Nahradiť „* e *“ výrazom „| e |“
  5. Nahradiť „* d *“ výrazom „| d |“
  6. Nahradiť „* n *“ výrazom „| n |“
  7. Nahradiť „* u *“ výrazom „| u |“
  8. Nahradiť „* t *“ výrazom „| t |“

Pre „nežiaduce“ bude postupnosť takto:

nežiaduceun [| w | o | n | t |] vyd (pravidlo 2) [| u |] [| n |] [| w | o | n | t |] [| e |] [| d |] (pravidlá 4, 5, 6, 7) u | n | w | o | n | t | e | d (s odstránenými prebytočnými znakmi) 

Mali by ste vidieť, ako slová obsahujúce písmená zvyknutý bude hovorené iným spôsobom ako slová obsahujúce písmená mravec. Mali by ste tiež vidieť, ako sa pravidlo zvláštnych prípadov týka celého slova jedinečný má prednosť pred ostatnými pravidlami, aby sa toto slovo hovorilo ako y | ou ... radšej než u | n ....

$config[zx-auto] not found$config[zx-overlay] not found