|
Предварительные замечанияЭта статья предназначена для тех, кто уже знаком с 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):
Перечислим и охарактеризуем те функции Disphelper, которые мы будем использовать в дальнейшем.
Ниже будет приведен исходный код, демонстрирующий использование этих функций. Здесь же чуть подробнее остановимся на функциях 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. Начнем с методов:
Теперь перейдем к свойствам, их будет несколько больше:
Говорящее приложение на FreeBASICПрежде всего отметим некоторые особенности использования функций Disphelper в программах на FreeBASIC. Во-первых, все строковые параметры передаются функциям Disphelper в кодировке Unicode. По этой причине в тексте программы необходимо указать: #define UNICODE Во-вторых, следует подключить заголовочный файл "disphelper.bi", который входит в пакет FreeBASIC. Это делается директивой: #include "disphelper/disphelper.bi" В-третьих, для нормальной работы Direct Speech Synthesis необходимо создать оконное приложение. В консольном варианте с синтезом речи могут возникнуть сложности. Ниже приведен исходный код приложения Windows, которое отображает на экране диалоговое окно. В этом окне можно в комбинированном списке выбрать голос, ввести текст в поле редактирования и нажать кнопку, чтобы преобразовать введенный текст в речь. Весь проект включает пять файлов:
Поясним назначение файла 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-2025 |
Социальные сети