Linuxové noviny | 07/98 | |||||||
| ||||||||
S modemem jste se jistě již setkali. Asynchronní modem je zařízení, které je schopno přenášet data po telefonní lince nebo po metalickém okruhu (analogová pevná linka). Jistě jste si také všimli, že některé modemy mají někde u své specifikace připsané slovo Voice. A právě o těchto modemech je článek, který právě čtete.
Co je hlasový modem?Jde o zcela běžný modem, určený pro komunikaci nad telefonní linkou. Má rozhraní pro připojení k telefonní síti a rozhraní pro připojení k počítači, obvykle RS--232. Hlasový modem má oproti běžnému modemu schopnost přehrávat do telefonní linky digitální zvukový signál, který dostane z počítače, a naopak počítači předávat digitalizovaný zvuk, který "slyší" v telefonní lince. Většina hlasových modemů má také schopnost tento zvuk do jisté míry analyzovat - například detekovat ticho na lince, vyzváněcí a obsazovací tóny, a také rozpoznávat DTMF (Dual Tone Modulation Frequency) tóny. To je to pípání, které vydává klávesnice všech novějších telefonních přístrojů při vytáčení čísla. Většina hlasových modemů má také vlastní reproduktor a konektor pro připojení sluchátek a mikrofonu.
K čemu je hlasový modem?Asi nejzákladnější a nejjednodušší aplikací hlasového modemu je emulace telefonního záznamníku. Při příchozím volání software rozpozná, jde-li o datové (případně faxové) volání, nebo dovolal-li se člověk. V posledním jmenovaném případě pak do telefonu přehraje zprávu pro volající a umožní uložit hlasový vzkaz.Pokud si ale uvědomíme, že pomocí kláves tónové volby může volající určitým poměrně dobře definovaným způsobem předávat hlasovému modemu informaci, zjistíme, že možnosti jsou daleko větší. Můžeme pak vytvářet i daleko rozsáhlejší aplikace. Jedna z možností je vylepšit náš telefonní záznamník tak, aby po zadání číselného "hesla" pomocí tónové volby umožnil přehrát uložené zprávy nebo změnit zprávu pro volající. Takto se záznamníkem můžeme komunikovat i v případě, že nejsme u svého počítače. V dalším popíšu problém, který jsem řešil pomocí hlasových modemů (a Linuxu, samozřejmě), a dále uvedu prostředky, které jsem k řešení použil.
Přijímací zkouškyStejně jako u všech vysokých škol, konají se i na Fakultě informatiky přijímací zkoušky do prvního ročníku. Celé přijímací řízení končí tím, že uchazeč napíše test, ten někdo opraví (v případě FI ještě tentýž den), přičtou se body za střední školu, různé olympiády a podobně, uchazeči se setřídí podle dosaženého počtu bodů, v určitém místě se udělá čára oddělující přijaté a nepřijaté uchazeče, vytiskne se oznámení o výsledku řízení a rozešle se uchazečům (no, trochu jsem to zjednodušil, ale zhruba to takto probíhá). Uchazeč tedy má několikadenní dobu, po kterou čeká na výsledek zkoušky. Problém je ten, že ne každý uchazeč (nebo jeho rodiče) vydrží čekat až do písemného oznámení. Zaměstnankyně studijního oddělení pak po několik dní nedělají nic jiného, než zodpovídání dotazů na to, jak ten který budoucí génius (:-) dopadl.Rozhodli jsme se, že studijnímu oddělení situaci trochu ulehčíme. Výsledky zveřejňujeme jednak přes WWW, a jednak pomocí hlasových modemů. Uchazeči už u přijímací zkoušky dostanou leták s informací, na jaké telefonní číslo mohou zavolat, a jakým způsobem se tam požadovanou informaci dovědí.
Rozhovor s počítačemCelý systém je řešený tak, že uživatel zavolá na dané číslo, a uslyší toto:
Požadavek na stisk tlačítka nula slouží jednak k tomu, abychom detekovali volající, jejichž telefon nepodporuje tónovou (DTMF) volbu, a jednak proto, že na dalších kódech pak můžeme v budoucnu zavést i jiné služby, než jen sdělování výsledků přijímacích zkoušek. Stiskl-li uchazeč úspěšně tlačítko nula, systém pokračoval dále:
Uchazeč zadal číselný identifikační kód a stiskl tlačítko #. Kódy se uchazeči dověděli při přijímací zkoušce. Kód sestával z šestimístného identifikačního čísla, použitého pro tohoto uchazeče i ve studijní databázi, a tří náhodně vygenerovaných číslic, které sloužily jednak jako heslo, a jednak měly snížit možnost toho, že někdo omylem vyslechne výsledek někoho jiného a vyvodí z toho pro sebe nesprávné závěry. Tlačítko # sloužilo jako ukončovací znak pro sekvenci číslic. Tento způsob zadávání čísla zamezí tomu, že uživatel a systém budou na sebe navzájem čekat, pokud uživatel stiskne o jedno tlačítko méně nebo systém některý tón nerozpozná. Pokud uchazeč zadal chybný kód (například 1234#, systém odpověděl:
Zadal-li uživatel chybný kód (nebo nezadal-li kód) třikrát, systém ukončil spojení. Pokud zadal platný kód, systém jej přečetl a oznamoval výsledky. Několik příkladů zde uvádím:
První příklad ukazuje někoho, kdo ani ke zkoušce nepřišel, druhý je uchazeč na odborné studium, který nebyl přijat, a třetí je uchazeč na učitelství výpočetní technika-fyzika, který byl přijat. Na konci rozhovoru se systém rozloučil a zavěsil:
Později jsme systém ještě modifikovali pro použití k přijímacím zkouškám na Ekonomicko-správní fakultu MU. Tam systém navíc říkal iniciály jmen uchazečů, obory, na které byli přijati a pořadí, na kterém se umístili. Na druhé straně ESF nepožadovala zabezpečení heslem, takže jako vstupní kód sloužilo jen osobní číslo uchazeče.
Použitý hardwareV době prvních testů asi před půl rokem jsme používali počítač s procesorem i486/66, 16MB paměti a asi 250 MB disk. V době konání zkoušek jsme už měli Pentium 90 MHz a 32 MB RAM. Na tomtéž počítači ale neběžely jen hlasové modemy - slouží jako tiskový server, faxový server, jsou na něj přes sériové porty napojeny konzoly nejrůznějších zařízení a vykonává ještě několik dalších služeb. Moje zkušenost je, že na zátěži procesoru této třídy se vůbec neprojevilo, jestli běželo hlasové spojení, nebo ne. A jak uvidíme dále, s efektivitou obslužných programů jsme se nijak neobtěžovali - značná část systému je psána v Perlu. Na kvalitě hlasového spojení se také nijak neprojevila případná zátěž hlasového serveru.V počítači jsou dvě osmiportové sériové karty Cyclades Cyclom 8Yo, každá v ceně zhruba 11 500 Kč. Moje zkušenosti s tímto hardwarem jsou ty nejlepší. Driver pro Linux vypadá stabilně a karty generují poměrně malou zátěž systému. Firma Cyclades dokonce uvádí Linux na prvním místě mezi podporovanými operačními systémy. Narazil jsem jen na jediný problém: driver pro tyto karty nefungoval, pokud byl kompilován překladačem egcs. Tohle se dost těžko detekuje v případě, že jste si egcs nainstalovali někdy před půl rokem a už ani nevíte, že na svém počítači nemáte gcc. Pro hlasové aplikace jsme pořídili šest modemů. Měl jsem se rozhodnout mezi US Robotics Sportster a ZyXEL Omni (s Rockwell chipem). Nakonec to vyhrál Sportster - měl lepší zvuk a fungoval lépe. Jako zajímavost uvedu, že ke Sportsteru dostanete sluchátka, zatímco k ZyXELu Omni výrobce (nebo prodejce?) dává malinkou lahvičku J&B whisky... Modemy jsme napojili na místní telefonní ústřednu, která se ukázala býti jediným slabším článkem systému. Ve špičce totiž vyřizovala až dva hovory za sekundu, což zřejmě bylo víc, než mohla unést. Toto bylo kritické zejména u zkoušek na FI, jejichž výsledky byly zveřejněny ještě tentýž den. A tedy kolem očekávané hodiny zveřejnění byl nápor celkem velký. U zkoušek na ESF situace nebyla tak kritická, protože zveřejnění bylo až skoro týden po vlastních zkouškách, takže se všichni uchazeči nesnažili volat skoro přesně v tutéž hodinu. Propustnost systému je zhruba 150-200 hovorů za hodinu. Průměrný "rozhovor" trval zhruba dvě minuty, což dává okolo 30 hovorů za hodinu na jeden modem.
SoftwareJak se tedy pod Linuxem pracuje s hlasovým modemem? Možností je několik. Mně se nejvíc zalíbil program vgetty. Jde v podstatě o mgetty ftp://ftp.leo.org/pub/comp/os/unix/networking/mgetty/ s vestavěnými hlasovými funkcemi. Tento balík je distribuován v rámci mgetty+sendfax jako další dodatečná aplikace. Protože mgetty je špičkou ve svém oboru, lze očekávat, že ani vgetty na tom nebude špatně. Než přejdu k popisu toho, jak se s vgetty pracuje, uvedu jen, že zbytek systému byl Red Hat Linux 5.0 a jádro 2.0.34.Program vgetty zajišťuje (téměř) jednotný přístup ke hlasovým modemům, takže odlišnosti mezi jednotlivými typy modemů schovává. Program razí myšlenku "jednoduché jednoduše, složité složitěji" - sám obsahuje jednoduchý hlasový záznamník, a pro složitější problémy má podporu skriptů.
Hlasový shellKomunikace vgetty s uživatelskou aplikací probíhá pomocí tzv. hlasového shellu. To je program, jehož jméno můžeme nastavit v konfiguračním souboru voice.conf (na mém Red Hatu byl v adresáři /etc/mgetty+sendfax/). V okamžiku příchozího volání spustí vgetty tento hlasový shell, předá mu v proměnných prostředí svoje PID (používá se pak pro komunikaci), a dále čísla dvou deskriptorů. Tyto deskriptory ukazují na dvě roury, které slouží k obousměrné komunikaci mezi vgetty a hlasovým shellem. Shell pak má možnost jednoduchým znakovým protokolem předávat vgetty svoje příkazy ("přehrej tento soubor", "pípni", "nahrej zvuky, které slyšíš z linky, do tohoto souboru", a tak podobně). Na druhou stranu vgetty předává shellu informace o stavu linky ("Slyším DTMF tón #", "Na lince je ticho", "Slyším obsazovací tón, volající asi zavěsil", atd.). Tento protokol umožňuje implementovat vše potřebné pro hlasové aplikace.
Perl na scéněProgram vgetty obsahuje několik příkladů hlasových shellů - vesměs jde o skripty v Bourne Shellu. Autor píše, že možná někdy bude podporovat i Perl. Protože v Perlu se přece jen píše lépe než v shellu, rozhodl jsem se, že přechod na Perl trochu urychlím. V době vydání tohoto čísla Linuxových novin by již měl být na CPANu ftp://ftp.fi.muni.cz/pub/perl/ dostupný modul Modem::Vgetty, který je výsledkem mé práce. Hlavní kód je již stabilní, momentálně dokončuji drobné detaily jako je například dokumentace.Zmiňovaný modul je objektově orientované, událostně řízené rozhraní k vgetty. Nejjednodušší aplikaci, která přehraje zvukový soubor volajícímu, můžeme napsat třeba takto:
use Modem::Vgetty; my $v = new Modem::Vgetty; $v->play_and_wait('/cesta/soubor.rmd'); exit 0; Je vidět, že se zde používá jakýsi soubor s koncovkou .rmd. Znamená to Raw Modem Data a soubor obsahuje zvuková data přímo pro konkrétní typ modemu. Toto je jediné místo, kde vgetty neskrývá před uživatelem typ modemu a kde aplikace musí tento typ znát. S programem vgetty se dodává i sada konverzních programů se souhrnným názvem pvftools - zavádí portabilní textový zvukový formát PVF (Portable Voice Format), přes který se provádí konverze na jiné formáty. Tento přístup trochu připomíná balík netpbm. Dalším příkladem může být jednoduchý záznamník: volajícímu se přehraje zpráva a má možnost uložit svůj vzkaz.
use Modem::Vgetty; my $v = new Modem::Vgetty; $v->add_handler('BUSY_TONE', 'konec', sub { $v->stop; exit 0; }); $v->enable_events; $v->play_and_wait('/cesta/welcome.rmd'); my $num = 0; $num++ while(-r "/cesta/$num.rmd"); $v->record("/cesta/$num.rmd"); sleep 30; $v->stop; exit 0; Zde už vidíme jednoduché použití událostí. Modul poskytuje několik druhů událostí. Jednou z nich je BUSY_TONE, která vzniká, detekuje-li modem na lince obsazovací tón. To je zejména v případě, kdy volající zavěsil. Program na tuto událost reaguje tak, že ukončí svoji činnost. Řetězec konec zde slouží jen jako identifikace handleru pro danou událost, pokud bychom časem tento handler chtěli zrušit.
Zvuková dataPomocí modulu Modem::Vgetty jsem implementoval celý výše popisovaný hlasový systém. Vzhledem k tomu, že nemám uspokojivě fungující systém pro syntézu řeči, rozhodl jsem se, že celý text namluvím a rozdělím na jednotlivá slova. Myslel jsem si, že pro nasazení v praxi pak bude použit nějaký příjemný ženský hlas, ale nakonec tam zůstal ten můj.
Zvuky jsem vytvářel za pomocí mikrofonu, zvukové karty Gravis Ultrasound MAX a programu snd http://www-ccrma.stanford.edu/CCRMA/Software/snd/snd.html. Tento program umožňuje jak zaznamenávat zvuky, tak poměrně jednoduše tyto zvuky editovat. Tak například jsem do jednoho souboru namluvil všechny možné i nemožné číslovky, a pak jsem je pomocí tohoto programu ukládal po slovech do jednotlivých souborů. Je to nepříliš záživná práce, jak si jistě umíte představit, zejména u tak jednotvárných slov, jako jsou číslovky nebo jednotlivá písmena abecedy. K číslovkám jsem si ještě napsal další modul (bude zřejmě uvolněn jako Cz::Speak nebo Cz::Numbers). Tento modul umožní převést zadané číslo na sekvenci českých slov. Tedy číslo 1234 převede na čtyři řetězce: "tisíc" "dvěstě" "třicet" a "čtyři". Je tam i několik rozšíření - například uživatel může specifikovat rod celého čísla (což se projeví pouze pokud je číslo rovno jedné nebo dvěma), nebo přečíst číslo po trojicích cifer, po dvojicích cifer nebo i po jednotlivých cifrách. Také umí přečíst časový interval a některé další číselné údaje.
Spolupráce s databázíVzhledem k tomu, že na projektu pracovalo více lidí (jednou z částí bylo například zveřejňování výsledků přes WWW), měli jsme jednotné rozhraní: databází byly DBM soubory a rozhraním byl program, který dostal jako parametr identifikační kód uchazeče a vrátil na výstupu informace o neplatném kódu nebo o uchazeči.
ZávěrProkázalo se, že pro podobné účely je vgetty dostatečně mocný prostředek. Systém fungoval téměř bez výpadku a obsloužil řádově tisíc hovorů, při kterých byl zadán správný identifikační kód (což se podařilo volajícím zhruba v 70 procentech volání) v případě zkoušek na FI, a zhruba tři tisíce hovorů v případě ESF. U takovýchto větších akcí se vyplatí mít k dispozici náhradní stroj se stejným softwarem, aby v případě výpadku mohl být systém oživen pouhou výměnou počítače. Toto jsme naštěstí měli, a tak v okamžiku pádu hlasového serveru (dodnes uspokojivě nevysvětleno), kdy došlo k poškození kořenového adresáře a ztrátě více než poloviny souborů na disku, jsme mohli během zhruba hodiny zapojit náhradní počítač a věnovat se restaurování původního počítače ze zálohy (také pravidelně zálohujete, není-liž pravda :-). Na druhé straně tato technologie má své omezení. Asi největším z nich je nutnost manuálního namlouvání hlasových dat do počítače. V případě rozsáhlejších systémů bychom pak narazili na problém, že případné úpravy by musel mluvit tentýž člověk. Kdybychom měli rozumně fungující syntézu řeči, byla by situace trochu jiná. |