Озвучивание текстов



Преобразование текста в речь возможно, если в системе установлен пакет функций "Speech API". Синтезирование речи происходит с помощью речевых движков, благо доступ к ним всегда имеется - "Speech API" предоставляет набор специальных функций. Вот мы и попробуем их использовать (создадим программу кодорая будет транслировать текст в речь) - подгружаем к нашему проекту модуль "ActiveX".

Для начала опишем все переменные и константы:

const
//идентификатор класса
SAPI_SpVoice_ClassID:TGUID='{96749377-3391-11D2-9EE3-00C04F797396}';
 
var
//используемый интерфейс
Voice:IDispatch;
//Указатель на параметры движка
DispParams:TDispParams;
Arg:TVariantArg;
//текст который будет транслироваться в речь
Text:WideString;

Теперь переписывай Листинг 1, а я расскажу, что к чему. Перед дальнейшим чтением предлагаю Вам самостоятельно ознакомиться с "COM" или хотя бы иметь представление об этом.
Так вот "CoInitialize(nil)" позволяет потоку нашего приложения войти в подразделение STA (Модель однопотокового подразделения - The Single Threaded Apartment Model), т.е. инициализировать его. Подразделение - это место, где "живет" поток. Поэтому его использование необходимо. Независимо от того, где исполняется объект, клиент обычно создает его и затем получает указатели на необходимые интерфейсы. Для объектов, реализованных сервером "в процессе" или локальным сервером, это можно сделать, вызвав CoCreateInstance, что мы и сделали. Далее проверяем существует ли движок. Потом мы просто производим трансляцию текста.

Листинг1

{$APPTYPE CONSOLE}
//добавляем необходимый модуль
uses Windows,Messages,ActiveX;
 
const
//интерфейс движка
SAPI_SpVoice_ClassID:TGUID='{96749377-3391-11D2-9EE3-00C04F797396}';
 
var
Voice:IDispatch;
//Указатель на параметры движка
DispParams:TDispParams;
Arg:TVariantArg;
//текст который будет транслироваться в речь
Text:WideString;
begin
//строчка для трансляции:"I can talk! I''m alive!"
Text:='<>I can < emph >talk< /emph >! I''m < emph >alive< /emph >!';
 
CoInitialize(nil);
 
//Создание объекта
CoCreateInstance(SAPI_SpVoice_ClassID, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IDispatch, Voice);
 
if Voice=nil then
begin
showmessage('SpeechAPI is not installed.'#10);
Exit;
end;
 
Arg.vt:=VT_BSTR; //binary string
Arg.bstrVal:=PWideChar(Text);
 
DispParams.rgvarg:=@Arg;
DispParams.rgdispidNamedArgs:=nil;
DispParams.cArgs:=1;
DispParams.cNamedArgs:=0;
 
Voice.Invoke(12,GUID_NULL,0,1,DispParams,nil,nil,nil);
end.

Исходя из документации "Microsoft Speech API" можно сказать, что "SAPI" поддерживает управление речевого вывода с помощью параметров. Параметры представленны тегами, которые вставляются непосредственно в читаемую строку. Благодаря таким параметрам мы можем улучшить/изменить трансляцию текста в речь, это достигается с помощью следующих тегов (двойные теги позволяют обрамлять участок текста):

< emph >< /emph > - выделяет фрагмент текста измененным произношением;

< silence msec='60'/ > - вставка паузы (мсек);

< pitch middle='5' >< /pitch > - управляет относительной высотой голоса, изменение от -10 до 10;

< pitch absmiddle='10' >< /spell > - управляет абсолютной высотой голоса, изменение от -10 до 10;

< volume level="50" >< /volume > - управляет громкостью, изменение от 0 до 100;

< spell >< /spell > - позволяет читать обрамленный текст по буквам;

С помощью данных тегов пользователь может "убрать" сухость речевого вывода, ну и вообще на свой манер манипулировать трансляцией по своему вкусу. Теперь попробуем читать файлы. Переписывай Листинг 2 и готовь bat-файл примерно вот такого содержания:


@echo off
rem Russian example =)
speak "" || goto:eof
echo Привет.
speak "<>Pree < pitch middle='-5' >viet< /pitch >."
echo Меня уже замучили.
speak "<>Me < pitch middle='5' >nyah< /pitch > oo theah zah moo chaly"
echo И заставили говорить по-русски.
speak "<>e za stavi < pitch middle='3' >lee< /pitch > gah vah reet po < pitch middle='-3' >roosski< /pitch >."
echo Дураки.
speak "<>doorak < pitch middle='3' >i< /pitch >."

Объясняю, что это нам дает: с помощью команды "speak" мы "передадим" строчку нашей программе, которая будет транслировать ее в речь.

Листинг 2.

{$APPTYPE CONSOLE}
uses Windows,Messages,ActiveX;
 
procedure Write2(const s:string);
asm
push 0
push esp
push [eax-4]
push eax
push STD_OUTPUT_HANDLE
call GetStdHandle
push eax
call WriteFile
end;
 
const
SAPI_SpVoice_ClassID:TGUID='{96749377-3391-11D2-9EE3-00C04F797396}';
 
var
Voice:IDispatch;
DispParams:TDispParams;
Arg:TVariantArg;
Text:WideString;
begin
Text:=paramstr(1);
 
if Text='' then
begin
Write2('Usage: speak "some text"'#10);
Exit;
end;
 
CoInitialize(nil);
 
CoCreateInstance(SAPI_SpVoice_ClassID, nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IDispatch, Voice);
 
if Voice=nil then
begin
Write2('SpeechAPI is not installed.'#10);
Exit;
end;
 
Arg.vt:=VT_BSTR;
Arg.bstrVal:=PWideChar(Text);
 
DispParams.rgvarg:=@Arg;
DispParams.rgdispidNamedArgs:=nil;
DispParams.cArgs:=1;
DispParams.cNamedArgs:=0;
 
Voice.Invoke(12,GUID_NULL,0,1,DispParams,nil,nil,nil);
end.

К данной статье прилагается исходник, в котором есть несколько bat-файлов, а также исходник на assembler'е, которые любезно предоставил "Grom PE". За это ему огромное спасибо!

Советую почитать:

COM - ]]>http://www.hostdir.ru]]> Категория "Программирование"
DCOM - ]]>http://ilyailyahome.chat.ru/dcom.htm]]>

Автор: Jimmy Jonezz