Difference between revisions of "SAPI"

From Free Pascal wiki
Jump to navigationJump to search
(→‎Windows alternatives: Mentioned linux/osx; removed duplicate code)
(Moved non-Windows content to new Speech Synthesis meta page; fixed syntax highlighting)
(9 intermediate revisions by 7 users not shown)
Line 1: Line 1:
== What is it ==
+
== SAPI ==
 +
 
 
SAPI stands for Speech Application Programming Interface, a Microsoft Windows API used to perform text-to-speech (TTS).
 
SAPI stands for Speech Application Programming Interface, a Microsoft Windows API used to perform text-to-speech (TTS).
  
== Use with FreePascal ==
+
=== Use with Free Pascal ===
Lazarus/FreePascal can use this interface to perform TTS.
+
 
 +
Lazarus / Free Pascal can use this interface to perform TTS.
 
Source: forum post: [http://lazarus.freepascal.org/index.php/topic,17852.0]
 
Source: forum post: [http://lazarus.freepascal.org/index.php/topic,17852.0]
  
 
On Windows Vista and above, you will run in trouble with the FPU interrupt mask (see [http://stackoverflow.com/questions/3032739/delphi-sapi-text-to-speech]). The code dealing with SavedCW is meant to work around this.
 
On Windows Vista and above, you will run in trouble with the FPU interrupt mask (see [http://stackoverflow.com/questions/3032739/delphi-sapi-text-to-speech]). The code dealing with SavedCW is meant to work around this.
<syntaxhighlight>
+
 
 +
<syntaxhighlight lang="pascal">
 
uses
 
uses
 
   ...,comobj;
 
   ...,comobj;
Line 25: Line 28:
 
   end;
 
   end;
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 
For the options available with SpVoice.Speak and other SpVoice methods see http://msdn.microsoft.com/en-us/library/ms723609(v=vs.85).aspx.
 
For the options available with SpVoice.Speak and other SpVoice methods see http://msdn.microsoft.com/en-us/library/ms723609(v=vs.85).aspx.
: '''WARNING''' The Ole object created in above snippet will be destroyed automatically when the SpVoice variant goes out of scope. For larger texts the use of the asynchronous mode allows to keep your application reactive while speak is running. In that case it is especially important to control carefully the lifetime of the object and store it in a global or class variable. Destroying the object while speak is still running can cause crashes.  
+
 
 +
{{Warning|The OLE object created in above snippet will be destroyed automatically when the SpVoice variant goes out of scope. For larger texts the use of the asynchronous mode allows to keep your application reactive while speak is running. In that case it is especially important to control carefully the lifetime of the object and store it in a global or class variable. Destroying the object while speak is still running can cause crashes.}}
 +
 
 +
 
 
Changing the FPU interrupt mask can be done at any moment before loading the ole object and if your application is not using any floating point arithmetic there is no need to reset the FPU interrupt mask to its original value.
 
Changing the FPU interrupt mask can be done at any moment before loading the ole object and if your application is not using any floating point arithmetic there is no need to reset the FPU interrupt mask to its original value.
  
== Windows, Linux, OSX alternatives ==
+
=== Assigning text to a variable. A WideString must used ===
An alternative on Windows is to use [[espeak]]. eSpeak has 11 voices, (7 male and 4 female) and is cross platform supporting Windows, Mac and Linux. It also has many [[espeak#Using eSpeak command line|command line parameters]] which can be used to further improve the speech. When coding, an eSpeak installation can be used and a [[espeak#Preparing to use eSpeak|stand-alone option]] is available as well.
 
  
For a code example, please see the [[espeak]] article.
+
<syntaxhighlight lang="pascal">
 +
File:procedure TForm1.Button1Click(Sender: TObject);
 +
Var
 +
  SpVoice1: Variant;
 +
  VoiceString: WideString; // WideString must be used to assign variable for speech to function, can be Global.
 +
begin
 +
  SpVoice1 := CreateOleObject('SAPI.SpVoice'); // Can be assigned in form.create
 +
  VoiceString := Button1.Caption;              // variable assignment
 +
  SpVoice1.Speak(VoiceString,0);
 +
end;       
 +
</syntaxhighlight>
  
== Linux/Unix alternatives ==
+
Thank you nsunny from 2013 post.
On Linux/Unix, there are some command line Text To Speech engines, that may also offer access via APIs. An example is the festival engine.
 
  
See [[Linux_Programming_Tips#Perform_text-to-speech_.28TTS.29_or_how_to_let_my_computer_speak]]
+
== Alternatives ==
  
== OSX alternatives ==
+
See the [[Speech Synthesis]] article.
OSX has system wide text to speech functionality built in: VoiceOver. See [[LCL_Accessibility#Mac_OS_X_VoiceOver]]
 
See here for code for using the '''say''' command to perform TTS: [http://lazarus.freepascal.org/index.php/topic,18903.msg107254.html#msg107254]
 
  
 
[[Category:FPC]]
 
[[Category:FPC]]
 
[[Category:Lazarus]]
 
[[Category:Lazarus]]
 +
[[Category:Windows]]
 
[[Category:Tutorials]]
 
[[Category:Tutorials]]
 +
[[Category:Speech synthesis]]

Revision as of 01:16, 19 December 2019

SAPI

SAPI stands for Speech Application Programming Interface, a Microsoft Windows API used to perform text-to-speech (TTS).

Use with Free Pascal

Lazarus / Free Pascal can use this interface to perform TTS. Source: forum post: [1]

On Windows Vista and above, you will run in trouble with the FPU interrupt mask (see [2]). The code dealing with SavedCW is meant to work around this.

uses
  ...,comobj;
var
  SavedCW: Word;
  SpVoice: Variant;
begin
  SpVoice := CreateOleObject('SAPI.SpVoice');
  // Change FPU interrupt mask to avoid SIGFPE exceptions
  SavedCW := Get8087CW;
  try
    Set8087CW(SavedCW or $4);
    SpVoice.Speak('hi', 0);
  finally
    // Restore FPU mask
    Set8087CW(SavedCW);
  end;

For the options available with SpVoice.Speak and other SpVoice methods see http://msdn.microsoft.com/en-us/library/ms723609(v=vs.85).aspx.

Warning-icon.png

Warning: The OLE object created in above snippet will be destroyed automatically when the SpVoice variant goes out of scope. For larger texts the use of the asynchronous mode allows to keep your application reactive while speak is running. In that case it is especially important to control carefully the lifetime of the object and store it in a global or class variable. Destroying the object while speak is still running can cause crashes.


Changing the FPU interrupt mask can be done at any moment before loading the ole object and if your application is not using any floating point arithmetic there is no need to reset the FPU interrupt mask to its original value.

Assigning text to a variable. A WideString must used

File:procedure TForm1.Button1Click(Sender: TObject);
Var
  SpVoice1: Variant;
  VoiceString: WideString; // WideString must be used to assign variable for speech to function, can be Global.
begin
  SpVoice1 := CreateOleObject('SAPI.SpVoice'); // Can be assigned in form.create
  VoiceString := Button1.Caption;              // variable assignment 
  SpVoice1.Speak(VoiceString,0);
end;

Thank you nsunny from 2013 post.

Alternatives

See the Speech Synthesis article.