Speech API
в Delphi
А сейчас мы познакомимся
с программированием речи в Delphi. Хотите чтобы Делфи заговорил - читайте
эту страницу!
Нудеюсь, что вы
уже установили пакет функций Speech API и хотя бы один речевой движок.
Если нет - то милости просим на Насосную станцию.
Речевые движки - это те модули, которые синтезируют речь. Для доступа
к ним нужно использовать специальные функции, которые описаны в наборе
функций Speech API. Поэтому для того, чтобы написать минимальную программу
умеющую говорить, нужны эти два компонента. Сначала мы попробуем написать
как раз эту программу-минимум а потом заставим персонаж MS Agent заговорить.
То есть постараемся совместить технологию MSAgent и SpeechAPI. Тогда
агент станет еще более приятным.
Ну, а для того чтобы
всем эти заняться нам потребуется полезный модулек speech.pas,
в котором объявлены полезные константы, типы, функции и интрефейсы.
Не забудьте подключить его в разделе uses
главного модуля приложения.
Попытаемся создать
программу, где мы будем вводить текст для чтения в редакторе, выбирать
движок для чтения в ComboBox'е и пару кнопок для чтения, паузы и остановки.
Объявим в секции
private нужные
для работы переменные:
private
{ Private declarations }
fITTSCentral: ITTSCentral; {Центральный интерфейс,
через который производятся все действия с речью}
fIAMM: IAudioMultimediaDevice;
{Интерфейс для связи с аудиоустройством}
aTTSEnum: ITTSEnum;
{Интерфейс для перебора движков}
fpModeInfo: PTTSModeInfo;
{Указатель на параметры движка}
Во ходе создания
главной формы приложения нам нужно проверить установленные движки в
системе, и их названия поместить в ComboBox. Это мы и сделаем:
procedure TForm1.FormCreate(Sender: TObject);
var
NumFound : DWord;
ModeInfo : TTSModeInfo;
begin
try
{Инициализация аудиоустройства}
CoCreateInstance(CLSID_MMAudioDest, Nil, CLSCTX_ALL,
IID_IAudioMultiMediaDevice, fIAMM);
except
end;
{Создание перечисляемого объекта для перебора всех движков в системе
с помощью интерфейса ITTSEnum}
CoCreateInstance(CLSID_TTSEnumerator, Nil, CLSCTX_ALL,
IID_ITTSEnum, aTTSEnum);
aTTSEnum.Reset;//Сбрасываем на первый
aTTSEnum.Next(1, ModeInfo, @NumFound); {Получаем первый движок}
While NumFound > 0 do
begin
ComboBox1.Items.Add(String(ModeInfo.szModeName));
aTTSEnum.Next(1, ModeInfo, @NumFound); {Получаем остальные}
end;
end;
В этом коде происходит
создания экземпляров COM объектов класса CLSID_MMAudioDest
и CLSID_TTSEnumerator.
Для этого используется метод CoCreateInstance
из библиотеки COM. Он создает экземпляр объекта на основании нужного
класса CLSID(Class Identifier) и идентификатора интерфейса IID(Interface
Identifier). В первом случае мы образуем объект для связи с аудио устройством,
во втором создаем экземпляр TTS, перечисляемого класса для перебора
всех речевых синтезаторов, установленных в системе. После этого экземпляры
классов окажутся соответственно в fIAMM
и в aTTSEnum. После этого
начинаем перебирать движки, узнавать их имена и добавлять в ComboBox'ы.
Кстате, не забудьте объвить в разделе uses
модуль
activex.pas, иначе Delphi будет ругаться насчет процедуры
CoCreateInstance,
и модуль ComObj.pas,
иначе после выполнения процедуры CoCreateInstance
переменная aTTSEnum
будет оставаться равна nil,
а значит программа будет обваливаться на следующей строке.
Теперь если вы запустите
программку, то в списке ComboBox'а увидите названия всех движков, установленных
у вас в системе:

Естественно,
что пока наша программка не умеет говорить, но зато знает необходимую
инфу о речевых устройствах.
Теперь
займемся загрузкой речевых синтезаторов для чтения текста. Поэтому пропишем
событие изменения движка в ComboBox'е:
procedure TForm1.ComboBox1Change(Sender: TObject);
var
NumFound: DWord;
ModeInfo : TTSModeInfo;{Для хранения информации о текущем движке}
begin
try
CoCreateInstance(CLSID_MMAudioDest, nil, CLSCTX_ALL,
IID_IAudioMultiMediaDevice, fIAMM);
CoCreateInstance(CLSID_TTSEnumerator, nil, CLSCTX_ALL,
IID_ITTSEnum, aTTSEnum);
aTTSEnum.Reset;
{Перескакиваем на нужный движок}
Form1.aTTSEnum.skip(ComboBox1.ItemIndex);
aTTSEnum.Next(1, ModeInfo, @NumFound);
if assigned(fpModeInfo) then
{если fpModeInfo не равен nil}
dispose(fpModeInfo);
new(fpModeInfo);
fpModeInfo^:=ModeInfo;
{загружаем движок по его GUID}
aTTSEnum.Select(fpModeInfo^.gModeID, fITTSCentral, IUnknown(fIAMM));
except
end;
end;
Ну и все, теперь
следует сказать, что "механизм чтения" приводится в действие
следующим образом:
procedure TForm1.SpeakClick(Sender: TObject);
var
SData: TSData;
BufRich: string;
begin
if not assigned(fITTSCentral) then
begin
ShowMessage('Не выбран движок!');
exit;
end;
BufRich:='Это текст!'; {Этот текст будет прочитан}
SData.dwSize := length(BufRich) + 1;
SData.pData := pChar(BufRich);
try
fITTSCentral.TextData(CHARSET_TEXT, 0, SData, nil, IID_ITTSBufNotifySink);
except
end;
end;
Подставляйте в BufRich
все что угодно, содержание этой строки и будет синтезироваться в речь!
Для полного счастья
не хватает приостановки чтения, то есть паузы, и полной остановки. Так
вот осуществить это можно с помощью следующих методов:
...
fITTSCentral.AudioPause; {Пауза в чтении}
fITTSCentral.AudioResume; {Восстановление чтения после паузы}
fITTSCentral.AudioReset; {Полная остановка чтения}
...
Остальные процедуры
на кнопочки чтения, паузы и стоп, думаю, вы сами нафантазируете,
а чтобы получить полный исходный текст проекта воспользуйтесь
ссылочкой в конце страницы. Это пока все! Собираюсь в ближайшее
время рассказать о том как работать с другими атрибутами чтения,
такими как скорость, тон, громкость и т.д. Но это потом, а пока
то ,что есть! Заходите ко мне на страничку почаще!
Скачать
простейшую программу чтения текстов(~226Кб)