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