В первую очередь: это не дубликат Delphi и SAPI. У меня есть определенная проблема с "SAPI в Delphi" предмет.
Я использовал превосходное руководство Библиотеки типов Импорта в Delphi 2009 для получения компонента TSpVoice в палитре элементов. Это работает отлично. С
var
SpVoice: TSpVoice;
Я могу записать
SpVoice.Speak('This is an example.', 1);
получить асинхронный аудиовыход.
Первый вопрос
Согласно документации, я смог бы записать
SpVoice.Speak('This is an example.', 0);
для получения синхронного аудиовыхода но вместо этого я получаю исключение EZeroDivide. Почему это?
Второй вопрос
Но что еще более важно, я хотел бы смочь создать объект SpVoice динамично (я думаю, что это называют к "позднему - связывают" объект SpVoice), частично потому что только очень небольшая часть всех сессий моего приложения будет использовать его, и частично потому что я не хочу принимать существование сервера SAPI в системе конечного пользователя.
С этой целью я попробовал
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: Variant;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SpVoice.Speak('this is a test', 0);
end;
который, по-видимому, не делает ничего вообще! (Замена 0 с 1 дает мне исключение EZeroDivide.)
Отказ от ответственности
Я довольно плохо знаком с автоматизацией COM/OLE. Я сожалею о любом незнании или глупости, показанной мной в этом сообщении...
В пользу всех встречающихся с той же проблемой, как я сделал, видео François объяснило, что существует ошибка в SAPI/Windows (некоторая несовместимость где-нибудь), который заставляет следующий код повысить исключение EZeroDivide:
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: variant;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SpVoice.Speak('This is a text.');
end;
Решение, как представлено видео, состоит в том, чтобы изменить управляющее слово FPU:
procedure TForm1.FormClick(Sender: TObject);
var
SpVoice: variant;
SavedCW: Word;
begin
SpVoice := CreateOleObject('SAPI.SpVoice');
SavedCW := Get8087CW;
Set8087CW(SavedCW or $4);
SpVoice.Speak('This is a text.');
Set8087CW(SavedCW);
end;
И, кроме того, если Вы хотите играть звук асинхронно, затем необходимо удостовериться, что плеер не выходит из объема!
Возможно, вам будет интересно увидеть этот сеанс CodeRage 4 на «Включение речи в приложениях Delphi (zip)» Вы получите инструкции, которые ищете ... (и я предполагаю, что вы используете Vista или +, так как нулевое деление не происходило в XP)