Èñïîëüçîâàíèå MS Speech API 4.0 â ïðîãðàììàõ íà FreeBASIC

Äàòà ïóáëèêàöèè:2007
Ïîäåëèòüñÿ â Twitter Ïîäåëèòüñÿ â F******k Ïîäåëèòüñÿ â VKontakte Ïîäåëèòüñÿ â Telegram Ïîäåëèòüñÿ â Mastodon

Ïðåäâàðèòåëüíûå çàìå÷àíèÿ

Ýòà ñòàòüÿ ïðåäíàçíà÷åíà äëÿ òåõ, êòî óæå çíàêîì ñ FreeBASIC è õîòåë áû èñïîëüçîâàòü â ñâîèõ ïðîãðàììàõ òåõíîëîãèè ñèíòåçà ðå÷è, äîñòóïíûå ïîñðåäñòâîì MS SAPI 4. Äëÿ ïîíèìàíèÿ ìàòåðèàëà íåîáõîäèìî çíàòü ÿçûê ïðîãðàììèðîâàíèÿ Áåéñèê, íàçíà÷åíèå äèðåêòèâ êîìïèëÿòîðà FreeBASIC, à òàêæå âëàäåòü áàçîâûìè çíàíèÿìè î òîì, êàê ñîçäàâàòü ïðèëîæåíèÿ â MS Windows. Ïðèâåòñòâóåòñÿ çíàíèå îñíîâ ðàáîòû òåõíîëîãèé COM è OLE àâòîìàòèçàöèè, îäíàêî ýòî òðåáîâàíèå íå ÿâëÿåòñÿ îáÿçàòåëüíûì è îòñóòñòâèå ýòèõ çíàíèé íå äîëæíî ñèëüíî çàòðóäíèòü ïîíèìàíèå ìàòåðèàëà (âåäü ïîëüçóþòñÿ æå ìíîãèå ëþäè ìèêðîâîëíîâîé ïå÷üþ, íå èìåÿ ïðåäñòàâëåíèÿ î ðàáîòå ìàãíåòðîíà).Âïîëíå äîñòàòî÷íî áóäåò âàøåãî îïûòà èñïîëüçîâàíèÿ ôóíêöèè CreateObject() â ñðåäå Visual Basic, Visual Basic for Application èëè ñêðèïòîâîì ÿçûêå VBScript.

Î ÷åì ïîéäåò ðàçãîâîð

Íåñìîòðÿ íà ðÿä íåîñïîðèìûõ äîñòîèíñòâ, ïðèñóùèõ òàêîìó ñðåäñòâó ðàçðàáîòêè ïðîãðàìì, êàê êîìïèëÿòîð FreeBASIC, åñòü îäèí ñóùåñòâåííûé ìîìåíò â ðàáîòå ñ íèì, êîòîðûé ñòàâèò â òóïèê ìíîãèõ ïðîãðàììèñòîâ, ïðèøåäøèõ ê FreeBASIC ïîñëå íåêîòîðîãî îïûòà ïðîãðàììèðîâàíèÿ â ñðåäå Visual Basic. Ýòèì ìîìåíòîì ÿâëÿåòñÿ ðàáîòà ñ ñåðâåðàìè OLE àâòîìàòèçàöèè (OLE Automation). Ïîñêîëüêó êîìïîíåíòû MS Speech API 4 (MS SAPI 4) ðåàëèçîâàíû êàê ñåðâåðû OLE àâòîìàòèçàöèè, òî, âçÿâ èõ â êà÷åñòâå ïðèìåðà, ìû ðàçáåðåìñÿ â òîì, êàê ðàáîòàòü ñ ïîäîáíûìè êîìïîíåíòàìè â ïðîãðàììàõ íà FreeBASIC. Åùå îäíîé ïðè÷èíîé, ïî êîòîðîé â êà÷åñòâå ïðèìåðà âûáðàí íàáîð êîìïîíåíòîâ SAPI 4, ÿâëÿåòñÿ òî îáñòîÿòåëüñòâî, ÷òî ñðåäè ïðèìåðîâ èñõîäíîãî êîäà â êàòàëîãå, ãäå óñòàíîâëåí FreeBASIC, â ïàïêå "examples\disphelper\" îòñóòñòâóþò èìåííî ïðèìåðû ðàáîòû ñ êîìïîíåíòàìè ðå÷åâûõ òåõíîëîãèé (SAPI 4 è SAPI 5).

 ñðåäàõ Visual Basic, VBA è äð., à òàêæå â ñêðèïòîâîì ÿçûêå VBScript ïðîãðàììèñòó äîñòàòî÷íî èñïîëüçîâàòü ôóíêöèþ CreateObject(), ÷òîáû, íè î ÷åì áîëüøå íå çàäóìûâàÿñü, ïîëó÷èòü äîñòóï ê íóæíîìó OLE-ñåðâåðó.  òåðìèíàõ Visual Basic ýòîò OLE-ñåðâåð íàçûâàåòñÿ "îáúåêòîì".  äàëüíåéøåì ïðîãðàììèñò èñïîëüçóåò ïîëó÷åííûé îáúåêò, âûçûâàÿ ìåòîäû (methods) è ïîëó÷àÿ/óñòàíàâëèâàÿ ñâîéñòâà (properties) ýòîãî îáúåêòà. Íà ñòîðîíå OLE-ñåðâåðà ýòîò ìåõàíèçì ïîääåðæèâàåòñÿ ïðè ïîìîùè èíòåðôåéñà IDispatch, íà êîòîðûé âîçëîæåíà îáÿçàííîñòü âûçûâàòü íóæíóþ ôóíêöèþ â ñîîòâåòñòâèè ñ èìåíåì ìåòîäà, êîòîðîå óêàçàë ïðîãðàììèñò â ïðîãðàììå íà Visual Basic. Òàêîé ìåõàíèçì âçàèìîäåéñòâèÿ ïðèêëàäíîé ïðîãðàììû (OLE-êëèåíòà) è ñåðâåðà OLE àâòîìàòèçàöèè íàçûâàåòñÿ "ïîçäíèì" ñâÿçûâàíèåì èç-çà òîãî, ÷òî àäðåñ ôóíêöèè, êîòîðàÿ áóäåò âûçâàíà ïî çàïðîñó ïðèêëàäíîé ïðîãðàììû, îïðåäåëÿåòñÿ íå íà ýòàïå êîìïèëÿöèè ïðîãðàììû, à âî âðåìÿ åå èñïîëíåíèÿ. Ýòîò ìåõàíèçì â ïðîãðàììàõ íà Visual Basic ïîääåðæèâàåòñÿ ñàìîé ñðåäîé ðàçðàáîòêè è áèáëèîòåêàìè, êîòîðûå äîëæíû áûòü âêëþ÷åíû â äèñòðèáóòèâ ñ ïðîãðàììîé.

 îòëè÷èå îò Visual Basic, FreeBASIC ÿâëÿåòñÿ òîëüêî ëèøü êîìïèëÿòîðîì, à íå ñðåäîé ðàçðàáîòêè, ïîýòîìó âñòðîåííûõ ôóíêöèé äëÿ ðàáîòû ñ ñåðâåðàìè OLE àâòîìàòèçàöèè â íåì íå ïðåäóñìîòðåíî. Îäíàêî ýòîò íåäîñòàòîê ìîæíî âîñïîëíèòü, îáðàòèâøèñü ê áèáëèîòåêå Disphelper, êîòîðàÿ ñâîáîäíî ðàñïðîñòðàíÿåòñÿ â îòêðûòîì êîäå è êîòîðàÿ âõîäèò â ñîñòàâ ïàêåòà FreeBASIC. Ïðîãðàììèñòû íà ÿçûêàõ C/C++ ìîãóò áîëåå ïîäðîáíî îçíàêîìèòüñÿ ñ Disphelper íà îôèöèàëüíîì ñàéòå ýòîãî ïðîåêòà (âñå íåîáõîäèìûå ññûëêè ïðèâåäåíû â ñîîòâåòñòâóþùåì ðàçäåëå ýòîé ñòàòüè).

Òàêèì îáðàçîì, äëÿ èñïîëüçîâàíèÿ ñèíòåçà ðå÷è â ïðîãðàììàõ íà FreeBASIC íàì íåîáõîäèìî, âî-ïåðâûõ, îñâîèòü ðàáîòó ñ ôóíêöèÿìè Disphelper, à âî-âòîðûõ, ïîçíàêîìèòüñÿ ñ ìåòîäàìè è ñâîéñòâàìè SAPI 4 è íàó÷èòüñÿ âçàèìîäåéñòâîâàòü ñ íèìè ïðè ïîìîùè Disphelper.

Áûñòðûé ñòàðò

Ïðèâåäåì äâà ôðàãìåíòà ïðîãðàìì íà Visual Basic è FreeBASIC, âûïîëíÿþùèõ ñõîæèå äåéñòâèÿ.

' Visual Basic
SET tts = CreateObject("ActiveVoice.ActiveVoice.1")
tts.Speak ("Hello, world!")

' FreeBASIC dhCreateObject ("ActiveVoice.ActiveVoice.1", NULL, @tts) DHCallMethod (tts, ".Speak(%S)", "Hello, world!")

Åñëè ïðè âçãëÿäå íà ýòè ôðàãìåíòû êîäà Âàì ñòàëî âñå ñîâåðøåííî ïîíÿòíî è Âû ãîðèòå æåëàíèåì ïðèñòóïèòü ê ïðîãðàììèðîâàíèþ, òî Âû ìîæåòå íå ÷èòàòü äàëüøå è äàòü âîëþ ñâîèì æåëàíèÿì. Ìû æå ïîçíàêîìèìñÿ ïîáëèæå ñ âîçìîæíîñòÿìè Disphelper è SAPI 4.

Îñíîâû Disphelper

Áèáëèîòåêà Disphelper ïðåäíàçíà÷åíà äëÿ îáëåã÷åíèÿ ðàáîòû ñ èíòåðôåéñîì IDispatch OLE-êîìïîíåíòîâ . Äëÿ âûçîâà ìåòîäîâ OLE-êîìïîíåíòà èñïîëüçóåòñÿ ñèíòàêñèñ, íàïîìèíàþùèé ñèíòàêñèñ ôóíêöèè printf() ÿçûêà C. Ïðàâèëüíåå áóäåò ñêàçàòü, ÷òî ðå÷ü èäåò íå î ñèíòàêñèñå ñàìîé ôóíêöèè printf(), à î ñèìâîëàõ ñòðîêè ôîðìàòà. Ïðè âûçîâå ôóíêöèé Disphelper èñïîëüçóþòñÿ ïîõîæèå ñîãëàøåíèÿ äëÿ óêàçàíèÿ òèïà àðãóìåíòà, ÷òî è â ôóíêöèè printf().

Âîò íåáîëüøîé ïåðå÷åíü íåêîòîðûõ ñïåöèôèêàöèé àðãóìåíòîâ èç òåõ, ÷òî ïîääåðæèâàåò Disphelper (áîëåå ïîëíûé ñïèñîê ñëåäóåò èçó÷àòü ïî ôàéëó readme.htm, âõîäÿùåì â äèñòðèáóòèâ Disphelper):

  • %d - LONG (INTEGER)
  • %u - ULONG (UINTEGER, DWORD)
  • %e - DOUBLE
  • %b - BOOL
  • %s - LPSTR (óêàçàòåëü íà ñòðîêó îäíîáàéòîâûõ ñèìâîëîâ, STRING PTR, ZSTRING PTR)
  • %S - LPWSTR (óêàçàòåëü íà ñòðîêó èç äâóõáàéòîâûõ ñèìâîëîâ, WSTRING PTR)
  • %o - IDispatch PTR (óêàçàòåëü íà èíòåðôåéñ IDispatch OLE-êîìïîíåíòà)
  • %p - LPVOID (èñïîëüçóåòñÿ äëÿ ïåðåäà÷è äåñêðèïòîðîâ ðàçëè÷íîãî âèäà)

Ïåðå÷èñëèì è îõàðàêòåðèçóåì òå ôóíêöèè Disphelper, êîòîðûå ìû áóäåì èñïîëüçîâàòü â äàëüíåéøåì.

  1. DISPATCH_OBJ() - ìàêðîñ, ñëóæàùèé äëÿ îáúÿâëåíèÿ ïåðåìåííîé òèïà IDispatch PTR.
  2. DHCreateObject () - ñîçäàåò ýêçåìïëÿð OLE-êîìïîíåíòà è óñòàíàâëèâàåò âçàèìîäåéñòâèå ñ èíòåðôåéñîì IDispatch. Äåéñòâèå ýòîé ôóíêöèè ñõîæå ñ äåéñòâèåì ôóíêöèè CreateObject () â Visual Basic.
  3. DHCallMethod() - âûçûâàåò îïðåäåëåííûé ìåòîä (method) OLE-êîìïîíåíòà.
  4. DHPutValue() - ïðèñâàèâàåò çíà÷åíèå îïðåäåëåííîìó ñâîéñòâó (property) OLE-êîìïîíåíòà.
  5. DHGetValue () - ïîëó÷àåò çíà÷åíèå îïðåäåëåííîãî ñâîéñòâà (property) OLE-êîìïîíåíòà.

Íèæå áóäåò ïðèâåäåí èñõîäíûé êîä, äåìîíñòðèðóþùèé èñïîëüçîâàíèå ýòèõ ôóíêöèé. Çäåñü æå ÷óòü ïîäðîáíåå îñòàíîâèìñÿ íà ôóíêöèÿõ DHCallMethod, DHPutValue è DHGetValue. Îïèñàíèíå ïðîòîòèïîâ ýòèõ ôóíêöèé ìîæíî íàéòè â ôàéëå disphelper.bi, êîòîðûé ðàñïîëîæåí â êàòàëîãå êîìïèëÿòîðà FreeBASIC â ïàïêå "inc\disphelper\"..

Ôóíêöèÿ DHCallMethod èìååò ïåðåìåííîå ÷èñëî ïàðàìåòðîâ, çàâèñÿùåå îò êîëè÷åñòâà ïàðàìåòðîâ òîãî ìåòîäà, êîòîðûé íóæíî âûçâàòü. D ëþáîì ñëó÷àå â êà÷åñòâå ïåðâîãî ïàðàìåòðà ïåðåäàåòñÿ ïåðåìåííàÿ òèïà IDispatch PTR (èëè, ïî òåðìèíîëîãèè Visual Basic, îáúåêò), âòîðûì ïàðàìåòðîì ïåðåäàåòñÿ ñòðîêà, ñîäåðæàùàÿ èìÿ âûçûâàåìîãî ìåòîäà ñ òî÷êîé â íà÷àëå è ñïèñêîì ôîðìàòîâ àðãóìåíòîâ. Äàëåå èäóò ñàìè àðãóìåíòû, êîòîðûå áóäóò ïåðåäàíû âûçûâàåìîìó ìåòîäó. Íàïðèìåð, òàê âûãëÿäèò âûçîâ ìåòîäà Method1 ó îáúåêòà Object1, ïðè÷åì ìåòîäó ïåðåäàåòñÿ öåëî÷èñëåííûé àðãóìåíò:

DHCallMethod (Object1, ".Method1(%d)", 100)

Ïîõîæèì îáðàçîì âûçûâàåòñÿ ôóíêöèÿ DHPutValue? òîëüêî âìåñòî ìåòîäà óêàçûâàåòñÿ â âèäå ñòðîêè èìÿ ñâîéñòâà. Íàïðèìåð, òàê âûãëÿäèò ïðèñâàèâàíèå ñâîéñòâó Property1 öåëî÷èñëåííîãî çíà÷åíèÿ:

DHPutValue (Object1, ".Property1=%d", 100)

Íåñêîëüêî èíîé ïîðÿäîê ïàðàìåòðîâ ó ôóíêöèè DHGetValue. Çäåñü ïåðâûì èäåò ñòðîêà ôîðìàòà ïîëó÷àåìîãî çíà÷åíèÿ, çàòåì óêàçàòåëü íà ïåðåìåííóþ, â êîòîðóþ ïîëó÷åííîå çíà÷åíèå áóäåò ñîõðàíåíî, à çàòåì óæå èäåò îáúåêò è ñòðîêà ñ èìåíåì ñâîéñòâà, çíà÷åíèå êîòîðîãî íóæíî ïðî÷èòàòü:

Dim Value As Integer
DHGetValue ("%d", @Value, Object1, ".Property1")

Ôóíêöèè Disphelper âîçâðàùàþò çíà÷åíèå òèïà HRESULT, êîòîðîå ñîäåðæèò êîä çàâåðøåíèÿ îïåðàöèè ñ OLE-êîìïîíåíòîì. Ýòî ìîæåò áûòü êîä óñïåøíîãî çàâåðøåíèÿ èëè êîä îøèáêè. Àíàëèçèðóÿ ýòîò êîä, ìîæíî îïðåäåëèòü ïðè÷èíó âîçíèêíîâåíèÿ îøèáîê. Åñëè óñòàíîâëåí ðåæèì ïåðåõâàòà îøèáîê (íàïðèìåð, â öåëÿõ îòëàäêè), òî â ñëó÷àå îøèáêè íà ýêðàíå ïîÿâèòñÿ ñîîáùåíèå ñ êîäîì âîçâðàòà è òåêñòîâûì îïèñàíèåì åå ïðè÷èíû.

Êîìïîíåíò Direct Speech Synthesis

Ïîäãîòîâêà SAPI 4 ê ðàáîòå

Direct Speech Synthesis - ýòî îäèí èç êîìïîíåíòîâ, âõîäÿùèõ â ñîñòàâ MS SAPI 4. Ýòîò êîìïîíåíò ïðåäíàçíà÷åí äëÿ íåïîñðåäñòâåííîãî ñèíòåçà ðå÷è ïî òåêñòó è ïîçâîëÿåò íå òîëüêî îçâó÷èâàòü òåêñò, íî è óïðàâëÿòü ïàðàìåòðàìè ñèíòåçà ðå÷è. Åñëè Âû èñïîëüçóåòå MS Windows 2000, òî êîìïîíåíòû SAPI 4 âõîäÿò â ñîñòàâ ýòîé îïåðàöèîííîé ñèñòåìû è, ñêîðåå âñåãî, óæå óñòàíîâëåíû íà Âàøåì êîìïüþòåðå. Äëÿ îïåðàöèîííûõ ñèñòåì MS Windows 9x è XP Âàì ïðèäåòñÿ çàãðóçèòü ïîëüçîâàòåëüñêèé äèñòðèáóòèâ SAPI èëè âåñü MS SAPI 4 SDK4. Îäíàêî ïîñëå óñòàíîâêè êîìïîíåíòîâ SAPI 4 Âû ìîæåòå ñòîëêíóòüñÿ ñ ñèòóàöèåé, êîãäà ïðèâåäåííûé íèæå ïðîãðàììíûé êîä íå áóäåò ðàáîòàòü. Åñëè ïðè çàïóñêå îòêîìïèëèðîâàííîé ïðîãðàììû íà ýêðàíå ïîÿâëÿåòñÿ ñîîáùåíèå:

Îøèáêà
Member:  ActiveVoice.ActiveVoice.1 Function:  CreateObject
Error In:  CreateObjectEx
Error:  Íåäîïóñòèìàÿ ñòðîêà ñ óêàçàíèåì êëàññà
Code:  800401f3
Source:  Application

Òî ýòî îçíà÷àåò, ÷òî â ñèñòåìíîì ðååñòðå â ñîîòâåòñòâóþùåì ðàçäåëå íå ñîïîñòàâëåíû ñòðîêîâîå èìÿ êîìïîíåíòà, íàçûâàåìîå ProgId (â íàøåì ñëó÷àå ýòî "ActiveVoice.ActiveVoice.1") è óíèêàëüíûé èäåíòèôèêàòîð êîìïîíåíòà CLSID, ïî êîòîðîìó îïåðàöèîííàÿ ñèñòåìà íàõîäèò íóæíóþ èíôîðìàöèþ äëÿ çàãðóçêè êîìïîíåíòà.

 òàêîì ñëó÷àå íåîáõîäèìî äîïîëíèòü ðååñòð èíôîðìàöèåé âðó÷íóþ. Äëÿ Windows XP íóæíî ñîçäàòü òåêñòîâé ôàéë "activevoice.reg" ñëåäóþùåãî ñîäåðæàíèÿ:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\ActiveVoice.ActiveVoice.1]
@="Direct Speech Synthesis"

[HKEY_CLASSES_ROOT\ActiveVoice.ActiveVoice.1\Clsid]
@="{EEE78591-FE22-11D0-8BEF-0060081841DE}"

Çàòåì â Ïðîâîäíèêå Windows çàïóñòèòü ýòîò ôàéë íà âûïîëíåíèå (íàæàòü êëàâèøó Enter) è ñîãëàñèòüñÿ ñ âíåñåíèåì èçìåíåíèé â ðååñòð. Íà ýòîì ïîäãîòîâêà SAPI 4 ê ðàáîòå çàâåðøåíà.

Åñëè Âû çíàêîìû ñ ôóíêöèÿìè Win32 API, ïðåäíàçíà÷åííûìè äëÿ ðàáîòû ñ ñèñòåìíûì ðååñòðîì, òî, ïðè ðàçðàáîòêå ïîëíîöåííîãî ïðèëîæåíèÿ, ïðîâåðêó è ìîäèôèêàöèþ âûøåîïèñàííîãî êëþ÷à â ñèñòåìíîì ðååñòðå ìîæíî âûïîëíèòü ïðîãðàììíî.

Ñâîéñòâà è ìåòîäû êîìïîíåíòà Direct Speech Synthesis

 ðàìêàõ ýòîé ñòàòüè íàì áóäåò äîñòàòî÷íî èçó÷èòü òå ìåòîäû è ñâîéñòâà, êîòîðûå èñïîëüçóþòñÿ ÷àùå äðóãèõ ïðè ñîçäàíèè ïðèëîæåíèé ñ ïîääåðæêîé ñèíòåçà ðå÷è. Çà áîëåå ïîäðîáíîé èíôîðìàöèåé ñëåäóåò îáðàùàòüñÿ ê äîêóìåíòàöèè, âõîäÿùåé â êîìïëåêò MS SAPI 4 SDK.

Íèæå èìåíà ñâîéñòâ è ìåòîäîâ óêàçûâàþòñÿ ñ òî÷êîé â íà÷àëå, ïîòîìó ÷òî èìåííî â òàêîì âèäå ýòè èìåíà íóæíî ïåðåäàâàòü ôóíêöèÿì Disphelper.

Íà÷íåì ñ ìåòîäîâ:

  • .AudioPause() - ïðèîñòàíàâëèâàåò ñèíòåç ðå÷è.
  • .AudioReset() - ïðåðûâàåò ñèíòåç ðå÷è.
  • .AudioResume() - âîçîáíàâëÿåò ñèíòåç ðå÷è.
  • .Speak(text As String) - îçâó÷èâàåò òåêñò, ïåðåäàííûé â êà÷åñòâå ïàðàìåòðà.
  • .Select(index As Long) - óñòàíàâëèâàåò òåêóùèé ãîëîñ â ñîîòâåòñòâèè ñ íîìåðîì, óêàçàííûì â ïàðàìåòðå.

Òåïåðü ïåðåéäåì ê ñâîéñòâàì, èõ áóäåò íåñêîëüêî áîëüøå:

  • .CountEngines As Long - êîëè÷åñòâî ãîëîñîâ, ïîääåðæèâàåìûõ âñåìè SAPI 4 ñèíòåçàòîðàìè.
  • .CurrentMode As Long - èíäåêñ òåêóùåãî ãîëîñà.
  • .FileName As String - èìÿ ôàéëà â ôîðìàòå wav, êóäà áóäåò çàïèñàíà ñèíòåçèðîâàííàÿ ðå÷ü. Åñëè íå óêàçàíî, òî ðå÷ü áóäåò âîñïðîèçâîäèòüñÿ ÷åðåç çâóêîâóþ êàðòó.
  • .Initialized As Short - óñòàíàâëèâàåòñÿ â 1 äëÿ èíèöèàëèçàöèè êîìïîíåíòà.
  • .Pitch As Long - âûñîòà ñèíòåçèðóåìîé ðå÷è.
  • .ProductName(index As Long) As String - ôèðìåííîå íàçâàíèå ñèíòåçàòîðà ñ óêàçàííûì èíäåêñîì.
  • .Speaker(index As Long) As String - èìÿ ïåðñîíàæà (ãîëîñà) ñ óêàçàííûì èíäåêñîì.
  • .Speaking As Short - åñëè óñòàíîâëåí â1, òî ñèíòåçàòîð çàíÿò ñèíòåçîì ðå÷è; èíà÷å óñòàíîâëåí â 0.
  • .Speed As Long - òåìï ðå÷è.
  • .Tagged As Boolean - óêàçûâàåò ñèíòåçàòîðó íà òî, ÷òî íåîáõîäèìî îáðàáàòûâàòü ñïåöèàëüíûå òåãè ðå÷åâîé ðàçìåòêè, ïîìåùåííûå â òåêñò.

Ãîâîðÿùåå ïðèëîæåíèå íà FreeBASIC

Ïðåæäå âñåãî îòìåòèì íåêîòîðûå îñîáåííîñòè èñïîëüçîâàíèÿ ôóíêöèé Disphelper â ïðîãðàììàõ íà FreeBASIC. Âî-ïåðâûõ, âñå ñòðîêîâûå ïàðàìåòðû ïåðåäàþòñÿ ôóíêöèÿì Disphelper â êîäèðîâêå Unicode. Ïî ýòîé ïðè÷èíå â òåêñòå ïðîãðàììû íåîáõîäèìî óêàçàòü:

#define UNICODE

Âî-âòîðûõ, ñëåäóåò ïîäêëþ÷èòü çàãîëîâî÷íûé ôàéë "disphelper.bi", êîòîðûé âõîäèò â ïàêåò FreeBASIC. Ýòî äåëàåòñÿ äèðåêòèâîé:

#include "disphelper/disphelper.bi"

Â-òðåòüèõ, äëÿ íîðìàëüíîé ðàáîòû Direct Speech Synthesis íåîáõîäèìî ñîçäàòü îêîííîå ïðèëîæåíèå.  êîíñîëüíîì âàðèàíòå ñ ñèíòåçîì ðå÷è ìîãóò âîçíèêíóòü ñëîæíîñòè.

Íèæå ïðèâåäåí èñõîäíûé êîä ïðèëîæåíèÿ Windows, êîòîðîå îòîáðàæàåò íà ýêðàíå äèàëîãîâîå îêíî.  ýòîì îêíå ìîæíî â êîìáèíèðîâàííîì ñïèñêå âûáðàòü ãîëîñ, ââåñòè òåêñò â ïîëå ðåäàêòèðîâàíèÿ è íàæàòü êíîïêó, ÷òîáû ïðåîáðàçîâàòü ââåäåííûé òåêñò â ðå÷ü.

Âåñü ïðîåêò âêëþ÷àåò ïÿòü ôàéëîâ:

  1. speech.bas - èñõîäíûé êîä îñíîâíîé ïðîãðàììû, ðåàëèçóþùåé âûâîä äèàëîãîâîãî îêíà è îáðàáîòêó ñîîáùåíèé.
  2. sapi4.bas - èñõîäíûé êîä áèáëèîòåêè ôóíêöèé, ðåàëèçóþùèõ âçàèìîäåéñòâèå ñ Direct Speech Synthesis ïðè ïîìîùè Disphelper.
  3. sapi4.bi - çàãîëîâî÷íûé ôàéë ñ îáúÿâëåíèÿìè ôóíêöèé sapi4.bas.
  4. resource.bi - çàãîëîâî÷íûé ôàéë ñ èäåíòèôèêàòîðàìè ðåñóðñîâ.
  5. speech.rc - ôàéë îïèñàíèÿ ðåñóðñîâ äèàëîãîâîãî îêíà.

Ïîÿñíèì íàçíà÷åíèå ôàéëà sapi4.bas. Ìîæíî áûëî ïîìåñòèòü âûçîâû ôóíêöèé Disphelper íåïîñðåäñòâåííî â ïðîöåäóðó îáðàáîòêè ñîîáùåíèé äèàëîãîâîãî îêíà. Îäíàêî ìû âûíåñëè ýòè âûçîâû â îòäåëüíóþ áèáëèîòåêó ôóíêöèé sapi4.bas. Ôóíêöèè ýòîé áèáëèîòåêè óñëîâíî ìîæíî íàçâàòü "îáåðòêàìè", òàê êàê îíè êàê áû "îáîðà÷èâàþò" âûçîâû ôóíêöèé Disphelper. Òàêàÿ îðãàíèçàöèÿ èñõîäíîãî êîäà ïîçâîëÿåò íàì ìåíÿòü êîä ôóíêöèé-îáåðòîê, íî ïðè ýòîì íå ìåíÿòü (èëè ïî÷òè íå ìåíÿòü) èñõîäíûé êîä îñíîâíîãî ôàéëà speech.bas.  äàëüíåéøåì, êîãäà áóäåò îáñóæäàòüñÿ ðàáîòà ñ MS SAPI 5 â ïðèëîæåíèÿõ FreeBASIC, ìû âîñïîëüçóåìñÿ ýòîé âîçìîæíîñòüþ, ïîäñòàâèâ âìåñòî sapi4.bas äðóãóþ áèáëèîòåêó, à èìåííî sapi5.bas. Ïîìèìî ýòîãî, Âû ìîæåòå èñïîëüçîâàòü sapi4.bas â äðóãèõ ïðîåêòàõ, ïðè ýòîì âàì íå ïðèäåòñÿ "âûðåçàòü" íóæíûå ôðàãìåíòû êîäà èç îñíîâíîãî ïðèëîæåíèÿ.

Åùå ñëåäóåò îáðàòèòü âíèìàíèå, ÷òî ìû íå ïðèìåíÿåì ìàêðîñ DISPATCH_OBJ(), ïîòîìó ÷òî èñïîëüçóåìûé íàìè îáúåêò (òî åñòü óêàçàòåëü íà èíòåðôåéñ IDispatch OLE-êîìïîíåíòà) ÿâëÿåòñÿ ãëîáàëüíîé ïåðåìåííîé, à ñèíòàêñèñ FreeBASIC íå ïîçâîëÿåò ñîâìåñòèòü óêàçàííûé ìàêðîñ è îáúÿâëåíèå ãëîáàëüíîé ïåðåìåííîé. Ïî óêàçàííîé ïðè÷èíå ìû èñïîëüçóåì êîíñòðóêöèþ:

 
dim SHARED 	  as IDispatch ptr tts = NULL

Ôàéë speech.bas

' Ôàéë speech.bas
' Ïðèìåð èñïîëüçîâàíèÿ SAPI 4 äëÿ ñèíòåçà ðå÷è 
' â ïðîãðàììàõ íà FreeBASIC
'' Êîìïèëèðîâàòü: fbc -s gui speech.rc speech.bas sapi4.bas 
'' 
'' 
option explicit 
#define UNICODE
#include once "windows.bi" 
#include "disphelper/disphelper.bi"

' Çàãîëîâî÷íûé ôàéë ôóíêöèé äëÿ ðàáîòû ñ SAPI 4
#include "sapi4.bi"

' Ôàéë ñ èäåíòèôèêàòîðàìè ðåñóðñîâ
#include "resource.bi"

' Îáúÿâëåíèå äèàëîãîâîé ôóíêöèè
DECLARE FUNCTION DlgProc (byval hwnd as HWND, byval umsg as UINT, byval wparam as WPARAM, byval lparam as LPARAM) as BOOL
             
' Ãëîáàëüíûå ïåðåìåííûå
dim SHARED 	  as IDispatch ptr tts = NULL

' Èíèöèàëèçàöèÿ Disphelper
	dhInitialize( TRUE )

' Ðàçðåøàåì ïåðåõâàò è îòîáðàæåíèå ñîîáùåíèé îá îøèáêàõ
	dhToggleExceptions( TRUE )

' Îòîáðàæàåì äèàëîãîâîå îêíî
  DialogBoxParam( GetModuleHandle( NULL ), cptr( LPCSTR, IDD_DLG1 ), NULL, @DlgProc, NULL ) 

' Îñâîáîæäàåì òî, ÷òî çàíèìàëè
	SAFE_RELEASE( tts)

' Çàâåðøàåì ðàáîòó ñ Disphelper
	dhUninitialize( TRUE )
  end 
' Çäåñü çàêàí÷èâàåòñÿ îñíîâíàÿ ïðîãðàììà

                 ' Ôóíêöèÿ äèàëîãîâîãî îêíà
Function DlgProc (byval hwnd as HWND, byval umsg as UINT, byval wparam as WPARAM, byval lparam as LPARAM) as BOOL
  dim as long id, event
  
  select case uMsg
  case WM_INITDIALOG
' Ïûòàåìñÿ ñîçäàòü Direct Speech Synthesis 
If TRUE <> SAPI4_Initialize(tts) Then
  	EndDialog( hwnd, 0 ) 
Return TRUE
End If

' Çàïîëíÿåì êîìáèíèðîâàííûé ñïèñîê äîñòóïíûìè ãîëîñàìè
SAPI4_GetVoices(tts, GetDlgItem(hWnd, IDC_VOICES_LIST))

' Âûáèðàåì ïåðâûé èç ãîëîñîâ
SAPI4_SelectVoice (tts, 1)

' Óñòàíàâëèâàåì òåìï ðå÷è
SAPI4_SetSpeed (tts, 80)
  case WM_CLOSE
  	EndDialog( hwnd, 0 ) 

  case WM_COMMAND
		id  = loword( wParam )
		event = hiword( wParam )

    select case id
    case IDOK 
' Îçâó÷èâàåì òåêñò
scope
DIM szBuf AS WSTRING * 1024
GetDlgItemText(hWnd, IDC_TEXT_TO_SPEAK, szBuf, 1024)
SAPI4_Speak (tts, @szBuf)
End Scope

case IDCANCEL
    	EndDialog( hwnd, 0 )

case IDC_VOICES_LIST:
' Ðåàãèðóåì íà ñìåíó ãîëîñà
If (event = CBN_SELCHANGE) Then
SAPI4_SelectVoice (tts, SendDlgItemMessage (hWnd, Id, CB_GETCURSEL, 0, 0)+1)
End If
  	end select
    
  case else
  	return FALSE
  
  end select
  
  return TRUE
end function 

Ôàéë sapi4.bas


' Ôàéë sapi4.bas
' Íàáîð ôóíêöèé äëÿ âçàèìîäåéñòâèÿ ñ êîìïîíåíòîì Direct Speech 
' ïðè ïîìîùè ôóíêöèé Disphelper

option explicit 

#define UNICODE
#include once "windows.bi" 
#include "disphelper/disphelper.bi"
' SAPI4_Initialize  ñîçäàåò îáúåêò ActiveVoice.ActiveVoice.1 è èíèöèàëèçèðóåò åãî.
' Âîçâðàò: TRUE, åñëè îøèáîê íå áûëî; FALSE - â ïðîòèâíîì ñëó÷àå.
FUNCTION SAPI4_Initialize (byRef Object As IDispatch PTR) As BOOL
Dim As String ProgId = "ActiveVoice.ActiveVoice.1"
IF FAILED(dhCreateObject (ProgId, NULL, @Object) THEN
RETURN FALSE
END IF
dhPutValue(Object, ".Initialized = %u", 1)
RETURN TRUE
END FUNCTION

' Ïðîöåäóðà SAPI4_GetVoices  çàïîëíÿåò êîìáèíèðîâàííûé ñïèñîê, 
'  äåñêðèïòîð êîòîðîãî ïåðåäàåòñÿ âî âòîðîì ïàðàìåòðå, íàçâàíèÿìè äîñòóïíûõ ãîëîñîâ.
SUB SAPI4_GetVoices (byRef object As IDispatch PTR,byval hCtrl as HWND)
Dim MaxVoice AS INTEGER
Dim szBuf AS WSTRING * 1024
Dim szSpeaker AS WSTRING PTR
Dim szProduct AS WSTRING PTR
Dim i AS INTEGER

SendMessage (hCtrl, CB_RESETCONTENT, 0, 0)
DHGetValue("%d", @MaxVoice, Object, ".CountEngines")
FOR i = 1 TO MaxVoice
DHGetValue("%S", @szSpeaker, Object, ".Speaker(%d)", i)
DHGetValue("%S", @szProduct, Object, ".ProductName (%d)", i)
szBuf = *szSpeaker + ": " +*szProduct
SendMessage (hCtrl, CB_ADDSTRING, 0, @szBuf)
NEXT
SendMessage (hCtrl, CB_SETCURSEL, 0, 0)

			dhFreeString(szSpeaker)
			dhFreeString(szProduct)
END SUB

' Ïðîöåäóðà SAPI4_SelectVoice  óñòàíàâëèâàåò â êà÷åñòâå àêòèâíîãî 
' ãîëîñ ñ óêàçàííûì íîìåðîì.
SUB SAPI4_SelectVoice (byRef Object As IDispatch PTR, byVal Index As INTEGER)
Dim MaxVoice AS INTEGER
DHGetValue("%d", @MaxVoice, Object, ".CountEngines")
IF Index > 0 AND Index <= MaxVoice THEN 
dhCallMethod(Object, ".Select(%u)", Index)
END IF
END SUB

' Ïðîöåäóðà SAPI4_SetSpeed  óñòàíàâëèâàåò òåìï ðå÷è.
' Ïðîâåðêà íà äîïóñòèìîñòü çíà÷åíèÿ òåìïà ðå÷è íå ïðîèçâîäèòñÿ.
SUB SAPI4_SetSpeed (byRef Object As IDispatch PTR, byVal Speed As INTEGER)
dhPutValue(Object, ".Speed=%u", Speed) 
END SUB

' Ïðîöåäóðà SAPI4_Speak  âûçûâàåò ìåòîä, îçâó÷èâàþùèé òåêñò.
SUB SAPI4_Speak (byRef Object As IDispatch PTR, byVal Phrase As WString PTR)
dhCallMethod(Object, ".Speak(%S)", Phrase)
END SUB

Ôàéë sapi4.bi

' Ôàéë sapi4.bi
' Îáúÿâëåíèå ôóíêöèé sapi4.bas
#ifndef __SAPI4_BI__
#define __SAPI4_BI__

DECLARE FUNCTION SAPI4_Initialize (byRef Object As IDispatch PTR) As BOOL
DECLARE SUB SAPI4_GetVoices (byRef Object As IDispatch PTR, byval hCtrl as HWND)
DECLARE SUB SAPI4_SelectVoice (byRef Object As IDispatch PTR, byVal Index As Integer)   
DECLARE SUB SAPI4_SetSpeed (byRef Object As IDispatch PTR, byVal Speed As Integer)
DECLARE SUB SAPI4_Speak (byRef Object As IDispatch PTR, byVal Phrase As WString PTR)
#endif

Ôàéë resource.bi


#ifndef IDC_STATIC 
#define IDC_STATIC -1
#endif
#define IDD_DLG1 1000 
#define IDC_VOICES_LIST	1001
#define IDC_TEXT_TO_SPEAK	1002

Ôàéë speech.rc

#include "resource.bi"

IDD_DLG1 DIALOGEX 0,0,200,100 
CAPTION "Text-to-speech" 
FONT 8,"MS Sans Serif" 
STYLE 0x10CC0000 
EXSTYLE 0x00000080 
BEGIN
	LTEXT "Voice:", IDC_STATIC, 5, 5, 40, 9
	COMBOBOX IDC_VOICES_LIST, 50, 5, 145, 10, WS_TABSTOP| CBS_DROPDOWNLIST | WS_VSCROLL 
	LTEXT "Text to speak:", IDC_STATIC, 5, 5+11, 100, 10
	EDITTEXT IDC_TEXT_TO_SPEAK, 5, 5+22, 190, 10

	 DEFPUSHBUTTON "Speak", IDOK, 120, 5+44, 35, 10 
	PUSHBUTTON  "Çàêðûòü", IDCANCEL, 120+37, 5+44, 35, 10 
END


Ðàñïðîñòðàíåíèå ìàòåðèàëîâ ñàéòà îçíà÷àåò, ÷òî ðàñïðîñòðàíèòåëü ïðèíÿë óñëîâèÿ ëèöåíçèîííîãî ñîãëàøåíèÿ.
Èäåÿ è ðåàëèçàöèÿ: © Âëàäèìèð Äîâûäåíêîâ è Àíàòîëèé Êàìûíèí,  2004-2026