Прежде всего: это не дубликат 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.Прошу прощения за любое невежество или глупость, показанную мной в этом посте ...
Обновление
В интересах всех, кто сталкивается с той же проблемой, что и я, видео Франсуа объяснил, что естьошибка в 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;
И, кроме того, если вы хотите воспроизводить звук асинхронно, то вы должны убедиться, что плеер не выходит за рамки!