Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2023-06

Microsoft SAPI on Freepascal

33 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

James Richters

I am trying to get Microsoft speech synthesis to work with Freepascal. I am trying to follow the guide here:

I don't know what I am doing wrong. SAPI is working on my system, because the TTSApp Demo that comes with the
Microsoft Speech SDK works fine.

Here is my test program:

{$mode objfpc}

uses
CRT, Windows, SysUtils, ComObj, Variants, OLEServer, Classes, ActiveX, ShellApi;

var
  SavedCW: Word;
  SpVoice: Variant;
  MyWideString: WideString;
begin
  CoInitialize(nil);
  SpVoice := CreateOleObject('SAPI.SpVoice');
  // Change FPU interrupt mask to avoid SIGFPE exceptions
  MyWideString := WideString('Hello, the time is ' + TimeToStr(Now));
  Writeln(MyWideString);
  SavedCW := Get8087CW;
  try
    Set8087CW(SavedCW or $4);
    SpVoice.Speak(MyWideString, 0);
  finally
    // Restore FPU mask
    Set8087CW(SavedCW);
  end;
  Writeln('Press Any Key');
  ReadKey;
  CoUninitialize;
end.
Whenever my program gets to:
SpVoice.Speak(MyWideString, 0);
Even if I hardcode something like:
SpVoice.Speak('Hello', 0);

I always get:
Running "i:\programming\TTS.exe "
Hello, the time is 8:41:27
An unhandled exception occurred at $0041FC90:
EOleError: Variant does not reference an automation object $0041FC90
$00424DAD
$0040BB31
$00401A8A main, line 21 of i:\programming\TTS.pas

I don't really understand what this means, and I can't find a complete sample program that I can just compile and run. I feel I must be missing something but I don't know what it is.

Any help is greatly appreciated!

James

Reply by email

James Richters
to James Richters

Ooops forgot the link:
https://wiki.lazarus.freepascal.org/SAPI

Earlier message 69 lines
From: fpc-pascal On Behalf Of James Richters via fpc-pascal Sent: Sunday, June 25, 2023 8:52 AM To: 'FPC-Pascal users discussions' Cc: James Richters Subject: [fpc-pascal] Microsoft SAPI on Freepascal I am trying to get Microsoft speech synthesis to work with Freepascal. I am trying to follow the guide here: I don't know what I am doing wrong. SAPI is working on my system, because the TTSApp Demo that comes with the Microsoft Speech SDK works fine. Here is my test program: {$mode objfpc} uses CRT, Windows, SysUtils, ComObj, Variants, OLEServer, Classes, ActiveX, ShellApi; var SavedCW: Word; SpVoice: Variant; MyWideString: WideString; begin CoInitialize(nil); SpVoice := CreateOleObject('SAPI.SpVoice'); // Change FPU interrupt mask to avoid SIGFPE exceptions MyWideString := WideString('Hello, the time is ' + TimeToStr(Now)); Writeln(MyWideString); SavedCW := Get8087CW; try Set8087CW(SavedCW or $4); SpVoice.Speak(MyWideString, 0); finally // Restore FPU mask Set8087CW(SavedCW); end; Writeln('Press Any Key'); ReadKey; CoUninitialize; end. Whenever my program gets to: SpVoice.Speak(MyWideString, 0); Even if I hardcode something like: SpVoice.Speak('Hello', 0); I always get: Running "i:\programming\TTS.exe " Hello, the time is 8:41:27 An unhandled exception occurred at $0041FC90: EOleError: Variant does not reference an automation object $0041FC90 $00424DAD $0040BB31 $00401A8A main, line 21 of i:\programming\TTS.pas I don't really understand what this means, and I can't find a complete sample program that I can just compile and run. I feel I must be missing something but I don't know what it is. Any help is greatly appreciated! James

Reply by email

Rafael Picanço

Hi James,

I am not familiar with variants and Ole objects, sorry about that. I found some people using code with Ole objects and it that seems to work, can you chack if it applies to your case?

https://stackoverflow.com/questions/17970573/using-word-ole-in-lazarus-freepascal

Best,
R

Show quoted text 149 lines
Send fpc-pascal mailing list submissions to To subscribe or unsubscribe via the World Wide Web, visit https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal or, via email, send a message with subject or body 'help' to You can reach the person managing the list at When replying, please edit your Subject line so it is more specific than "Re: Contents of fpc-pascal digest..." Today's Topics: 1. Re: Microsoft SAPI on Freepascal (Rafael Pican?o) 2. Re: SDL2 Event Registration (and case statements) (Rafael Pican?o) 3. Re: Microsoft SAPI on Freepascal (Rafael Pican?o) 4. Re: Microsoft SAPI on Freepascal (James Richters) ---------------------------------------------------------------------- Message: 1 Date: Sun, 25 Jun 2023 13:33:24 -0300 From: Rafael Pican?o To: Subject: Re: [fpc-pascal] Microsoft SAPI on Freepascal Message-ID: <CAGpuCi712ve6bRsXdVn=y7cFTuMSWSw4K2ewe65yu1F= > Content-Type: text/plain; charset="utf-8" Hi James, > SpVoice : Variant; > SpVoice := CreateOleObject('SAPI.SpVoice') The Free Pascal Variant type does not handle interfaces by default. Take a look: https://wiki.freepascal.org/Variant Best, R -------------- next part -------------- An HTML attachment was scrubbed... URL: < http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20230625/ae39a571/attachment-0001.htm > ------------------------------ Message: 2 Date: Sun, 25 Jun 2023 13:42:00 -0300 From: Rafael Pican?o To: Subject: Re: [fpc-pascal] SDL2 Event Registration (and case statements) Message-ID: <CAGpuCi4Dq6PkNs=xz3Vsy=ppwNVe-BdSad8oTVg=+ > Content-Type: text/plain; charset="utf-8" Thanks Guilhermo, Just to clarify, I do have a limited number of events. Lets say, 2 events. So, using the SDL_RegisterEvents function, is it possible to define these two new events as normal constants so they will be known at compile time and will make Free Pascal case statements happy? Best, R -------------- next part -------------- An HTML attachment was scrubbed... URL: < http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20230625/c9a4b1e9/attachment-0001.htm > ------------------------------ Message: 3 Date: Sun, 25 Jun 2023 13:52:17 -0300 From: Rafael Pican?o To: Subject: Re: [fpc-pascal] Microsoft SAPI on Freepascal Message-ID: < > Content-Type: text/plain; charset="utf-8" Hi James, Sorry, I missed the following reference: "Remark Dispatch interface support for variants is currently broken in the compiler." (https://www.freepascal.org/docs-html/ref/refsu20.html) Best, R > -------------- next part -------------- An HTML attachment was scrubbed... URL: < http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20230625/08ee32d3/attachment-0001.htm > ------------------------------ Message: 4 Date: Sun, 25 Jun 2023 13:24:46 -0400 From: "James Richters" To: , "'FPC-Pascal users discussions'" Subject: Re: [fpc-pascal] Microsoft SAPI on Freepascal Message-ID: Content-Type: text/plain; charset="utf-8" So it?s broken? It seems like the link you provided is trying to show a workaround, but I don?t know how I could apply that. >"Remark Dispatch interface support for variants is currently broken in the compiler." (https://www.freepascal.org/docs-html/ref/refsu20.html) -------------- next part -------------- An HTML attachment was scrubbed... URL: < http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20230625/c33bf375/attachment.htm > ------------------------------ Subject: Digest Footer _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal ------------------------------ End of fpc-pascal Digest, Vol 228, Issue 30 *******************************************

Reply by email

James Richters
to Rafael Picanço

I gave up on doing it directly, it seems SO convoluted to do with FPC with the COM unit and all this stuff I just don’t understand, and it’s SO simple to do with a VBS script in just 3 lines and it just works! (it would only be 2 lines if I didn’t want Microsoft Zira)

So I decided to do this in the most ridiculous way possible.. but after 3 days of trying to get send something directly to SAPI with FPC , I’m done with it, and getting this to work was super easy.

Computers are fast enough that I don’t need to waste my time tying to figure this out, just have FPC write out a VBS script, and run it with Process.Execute problem solved!

Here it is, maybe it will help someone else struggling to get something so simple to work:

{$mode objfpc}
Program Zira;
Uses
   SysUtils, Classes, Process;
Procedure Zira(ZiraZtring: AnsiString);
Var
   ScriptText: TStringList;
   Process: TProcess;
Begin
   ScriptText := TStringList.Create;
   ScriptText.Add('Set objVoice = CreateObject("SAPI.SpVoice")');
   ScriptText.Add('Set objVoice.Voice = objVoice.GetVoices().Item(1)');
   ScriptText.Add('objVoice.Speak "' + ZiraZtring + '"');
   ScriptText.SaveToFile('ZiraScript.vbs');
   Process := TProcess.Create(nil);
   Process.Executable := 'WScript.exe';
   Process.Parameters.Add('ZiraScript.vbs');
   Process.Execute;
   Process.WaitOnExit;
   ScriptText.Free;
   DeleteFile('ZiraScript.vbs');
End;
Begin
   Zira('Hello World');
End.
Earlier message 14 lines
From: fpc-pascal On Behalf Of Rafael Picanço via fpc-pascal Sent: Sunday, June 25, 2023 2:17 PM To: Cc: Rafael Picanço Subject: Re: [fpc-pascal] Microsoft SAPI on Freepascal Hi James, I am not familiar with variants and Ole objects, sorry about that. I found some people using code with Ole objects and it that seems to work, can you chack if it applies to your case? https://stackoverflow.com/questions/17970573/using-word-ole-in-lazarus-freepascal Best, R

Reply by email

Michael Van Canneyt
to James Richters
James Richters wrote
I gave up on doing it directly, it seems SO convoluted to do with FPC with the COM unit and all this stuff I just don’t understand, and it’s SO simple to do with a VBS script in just 3 lines and it just works! (it would only be 2 lines if I didn’t want Microsoft Zira)

I don't know what people advised you, but what you want to do needs 3 lines of code only:

I created a lazarus application, dropped a button and in the onclick I call speak('hello'). It just works.

uses comobj; procedure speak(s : string); var v : olevariant; begin v:=CreateOleObject('SAPI.SpVoice'); v.Voice:=v.GetVoices().Item(1); v.Speak(s); end; {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); begin speak('hello'); end; -- No need to write a script, call tprocess etc. You can do everything right in fpc as simple as this. Michael.

Reply by email

Rik van Kekem
to James Richters: I gave up on doing it directly, it seems SO convoluted to do with FPC with the COM unit…

Op 25-06-2023 om 22:46 schreef James Richters via fpc-pascal:

I gave up on doing it directly, it seems SO convoluted to do with FPC with the COM unit and all this stuff I just don’t understand, and it’s SO simple to do with a VBS script in just 3 lines and it just works!(it would only be 2 lines if I didn’t want Microsoft Zira)

You didn't mention the version of FPC/Lazarus you were using.

I had a simple example which worked for me (but your example also directly worked for me in trunk).

program Project1;
{$mode objfpc}{$H+}
uses
   Classes, ComObj;
var
   Voice: olevariant;
begin
   Voice := CreateOLEObject('SAPI.SpVoice');
   Voice.Speak('I am speaking.', 0);
   Voice.Speak('I am also speaking.', 0);
end.

I didn't even have the problem with any EZeroDivide exception.

Grtz, Rik van Kekem

Reply by email

Unknown author
to Michael Van Canneyt: I don't know what people advised you, but what you want to do needs 3 lines of code only:…

Does the form code do something different than the command line? When I try to run this code, I get an unhandled exception error.

Any idea how to fix?

Michael Van Canneyt wrote 50 lines
On Sun, 25 Jun 2023, James Richters via fpc-pascal wrote: > I gave up on doing it directly, it seems SO convoluted to do with FPC > with the COM unit and all this stuff I just don’t understand, > and it’s SO simple to do with a VBS script in just 3 lines and it > just works!  (it would only be 2 lines if I didn’t want Microsoft Zira) I don't know what people advised you, but what you want to do needs 3 lines of code only: I created a lazarus application, dropped a button and in the onclick I call speak('hello'). It just works. -- uses comobj; procedure speak(s : string); var   v : olevariant; begin   v:=CreateOleObject('SAPI.SpVoice');   v.Voice:=v.GetVoices().Item(1);   v.Speak(s); end; {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject); begin   speak('hello'); end; -- No need to write a script, call tprocess etc. You can do everything right in fpc as simple as this. Michael. _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to Marco van de Voort: I have to change that to (0) to get it to work. Might depend on configuration?
Marco van de Voort wrote 7 lines
On 26-6-2023 15:54, Michael Van Canneyt via fpc-pascal wrote: > >   v.Voice:=v.GetVoices().Item(1); > I have to change that to (0) to get it to work. Might depend on configuration?

Probably the number of voices installed in the system determines this.

I simply took OP's code, I assume he has 2 voices installed as I do...

Michael.

Reply by email

Unknown author
to Rik van Kekem: Op 25-06-2023 om 22:46 schreef James Richters via fpc-pascal: You didn't mention the…

Thank you, this one works for me with a command line compile.  I compared the two programs, and the line that asks for the voices is the culprit.

I'll have to do some digging to see why that line breaks the runtime execution.

But at least I can make it work now.  I'd always used powerbasic when I needed to work with com objects, good to know I can do the same thing in fpc now.

Rik van Kekem wrote 32 lines
Op 25-06-2023 om 22:46 schreef James Richters via fpc-pascal: > I gave up on doing it directly, it seems SO convoluted to do with FPC > with the COM unit and all this stuff I just don’t understand, > and it’s SO simple to do with a VBS script in just 3 lines and it > just works!(it would only be 2 lines if I didn’t want Microsoft Zira) You didn't mention the version of FPC/Lazarus you were using. I had a simple example which worked for me (but your example also directly worked for me in trunk). program Project1; {$mode objfpc}{$H+} uses   Classes, ComObj; var   Voice: olevariant; begin   Voice := CreateOLEObject('SAPI.SpVoice');   Voice.Speak('I am speaking.', 0);   Voice.Speak('I am also speaking.', 0); end. I didn't even have the problem with any EZeroDivide exception. -- Grtz, Rik van Kekem _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Michael Van Canneyt
to Unknown author
Travis Siegel wrote 6 lines
Thank you, this one works for me with a command line compile.  I compared the two programs, and the line that asks for the voices is the culprit. I'll have to do some digging to see why that line breaks the runtime execution.

Try changing the selected voice to 0 instead of 1.

Michael.

Reply by email

James Richters
to Michael Van Canneyt: I don't know what people advised you, but what you want to do needs 3 lines of code only:…

I was trying to figure this out on my own.. I went to: https://wiki.freepascal.org/SAPI

that is where I got my advice.
I took the top example code from the link and made it into the following program:

{$Mode OBJFPC}
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;
end.

It fails with

Running "i:\programming\gcode\mill\sapi.exe "
An unhandled exception occurred at $004143F0:
EOleError: Variant does not reference an automation object $004143F0
$0041950D
$0040B9A1
$00401931 main, line 13 of I:/Programming/Gcode/Mill/SAPI.pas

I don't have Lazarus, just FPC. I have been going nuts trying to track down this unhandled exception.

I tried to make your example into a FPC program without Lazarus: {$mode objfpc}{$H+}
uses

  comobj;

var

  SavedCW: Word;
  v: OleVariant;

begin

   v:=CreateOleObject('SAPI.SpVoice');
   v.Speak('Hello');

End.
I get:
Running "i:\programming\gcode\mill\sapi.exe "
An unhandled exception occurred at $00414370:
EOleError: Variant does not reference an automation object $00414370
$0041948D
$0040B941
$004018DF main, line 9 of i:/programming/gcode/mill/sapi.pas

I have tried to trace through with F7 I get a message that "Program generated a signal 291... " and then the IDE terminates

I still do not have an example I can compile and run from the FPC IDE (without Lazarus)

I don't know what people advised you, but what you want to do needs 3 lines of code only:

Reply by email

Michael Van Canneyt
to James Richters
James Richters wrote 20 lines
I tried to make your example into a FPC program without Lazarus: {$mode objfpc}{$H+} uses comobj; var SavedCW: Word; v: OleVariant; begin v:=CreateOleObject('SAPI.SpVoice'); v.Speak('Hello'); End. I get: Running "i:\programming\gcode\mill\sapi.exe " An unhandled exception occurred at $00414370: EOleError: Variant does not reference an automation object $00414370 $0041948D $0040B941 $004018DF main, line 9 of i:/programming/gcode/mill/sapi.pas

I suspect COM is not properly initialized, and that Lazarus does this for you. (it needs com for some components on windows)

So, try adding unit windows to the uses clause and add

CoInitialize(nil);

as the first statement of your program.

Michael.

Reply by email

Michael Van Canneyt
to Michael Van Canneyt
Michael Van Canneyt wrote 30 lines
On Mon, 26 Jun 2023, James Richters wrote: > > I tried to make your example into a FPC program without Lazarus: > {$mode objfpc}{$H+} > uses > comobj; > var > SavedCW: Word; > v: OleVariant; > begin > v:=CreateOleObject('SAPI.SpVoice'); > v.Speak('Hello'); > End. > I get: > Running "i:\programming\gcode\mill\sapi.exe " > An unhandled exception occurred at $00414370: > EOleError: Variant does not reference an automation object > $00414370 > $0041948D > $0040B941 > $004018DF main, line 9 of i:/programming/gcode/mill/sapi.pas I suspect COM is not properly initialized, and that Lazarus does this for you. (it needs com for some components on windows) So, try adding unit windows to the uses clause and add

That should be unit activex instead of unit windows.

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt: I suspect COM is not properly initialized, and that Lazarus does this for you. (it needs…
Michael Van Canneyt wrote 12 lines
I suspect COM is not properly initialized, and that Lazarus does this for you. (it needs com for some components on windows) So, try adding unit windows to the uses clause and add CoInitialize(nil); as the first statement of your program.

(afaik 3.2.2's comobj does this automatically, in older version YMMV).

Reply by email

Michael Van Canneyt
to Marco van de Voort
Marco van de Voort wrote 15 lines
On 26-6-2023 20:26, Michael Van Canneyt via fpc-pascal wrote: > > I suspect COM is not properly initialized, and that Lazarus does this for > you. > (it needs com for some components on windows) > > So, try adding unit windows to the uses clause and add > > CoInitialize(nil); > > as the first statement of your program. > > (afaik 3.2.2's comobj does this automatically, in older version YMMV).

Well, I checked prior to sending my answer. If it does this, it's well hidden. There seems to be some hook for it, though.

Michael.

Reply by email

Unknown author
to Michael Van Canneyt: Try changing the selected voice to 0 instead of 1. Michael.
Michael Van Canneyt wrote
Try changing the selected voice to 0 instead of 1.

Yeah, already tried that, didn't help any. *grumble*

Because I use a screen reader, I have multiple sapi voices installed, (though I rarely use them), but I haven't played with the code enough just yet to see why it fails when it tries to select one, when not selecting one works just fine <shrug>

It's important enough, I'll try to figure it out, but if it fails, it's not a real issue, since the default voice is fine with me anyway.

On the screen reader, I actually use the espeak engine, so I don't use the sapi voices under normal circumstances anyhow, but it would be useful to know how to switch voices, perhaps I could add a read out loud functionality to my epub reader.  Some folks seem to like that sort of thing.

Reply by email

Unknown author
to Michael Van Canneyt: I suspect COM is not properly initialized, and that Lazarus does this for you. (it needs…
Michael Van Canneyt wrote 35 lines
On Mon, 26 Jun 2023, James Richters wrote: > > I tried to make your example into a FPC program without Lazarus: > {$mode objfpc}{$H+} > uses >  comobj; > var >  SavedCW: Word; >  v: OleVariant; > begin >   v:=CreateOleObject('SAPI.SpVoice'); >   v.Speak('Hello'); > End. > I get: > Running "i:\programming\gcode\mill\sapi.exe " > An unhandled exception occurred at $00414370: > EOleError: Variant does not reference an automation object >  $00414370 >  $0041948D >  $0040B941 >  $004018DF  main,  line 9 of i:/programming/gcode/mill/sapi.pas I suspect COM is not properly initialized, and that Lazarus does this for you. (it needs com for some components on windows) So, try adding unit windows to the uses clause and add CoInitialize(nil); as the first statement of your program.

Not version I got working using just fpc (I don't use lazarus, or even a gui (in most cases) I've not figured out how to generate accessible guis from a pascal program.  When I need a GUI, I'll either use java (and tell it to use grid layout so I don't have to mess with placement), or I'll use powerbasic, and generate the GUI separate from the program using their tools, then just drop the code in where it's needed to make the GUI code work.  It uses DDT methods to generate the GUI, and that works just fine with screen readers.  I don't know how to do that with FPC, so I generally don't use it when a GUI is required.

But, back to the point.

For me, the code:

program voice;
uses
comobj;
procedure speak(s : string);
var
v : olevariant;
begin
v:=CreateOleObject('SAPI.SpVoice');
v.Speak(s);
end;
begin
speak('Hello.');
end.

It's not a whole lot different from the one posted above, but it might help point to the issue.

For me, the line

v.Voice:=v.GetVoices().Item(0);

(or any other number) causes a similar but different error from the one received from the original poster in his code, so it could be, (but likely isn't) related.

Reply by email

James Richters
to Marco van de Voort: (afaik 3.2.2's comobj does this automatically, in older version YMMV).

I appreciate the help with this. I'm still confused. In my original post, I already had CoInitialize, CoUninitialize; and Unit ComOBJ, Unit Windows and Unit ActiveX I was still getting EOleError: Variant does not reference an automation object.

Do I need to do all this Change FPU stuff?

I'm sure I'm doing something wrong but I still can't get it to work. Here's my original program. I wasn't even trying to change the voice yet. What do I need to do to this to make it work?

James

{$mode objfpc}

uses
CRT, Windows, SysUtils, ComObj, Variants, OLEServer, Classes, ActiveX, ShellApi;

var
  SavedCW: Word;
  SpVoice: Variant;
  MyWideString: WideString;
begin
  CoInitialize(nil);
  SpVoice := CreateOleObject('SAPI.SpVoice');
  MyWideString := WideString('Hello, the time is ' + TimeToStr(Now));
  Writeln(MyWideString);
  // Change FPU interrupt mask to avoid SIGFPE exceptions
  SavedCW := Get8087CW;
  try
    Set8087CW(SavedCW or $4);
    SpVoice.Speak(MyWideString, 0);
  finally
    // Restore FPU mask
    Set8087CW(SavedCW);
  end;
  Writeln('Press Any Key');
  ReadKey;
  CoUninitialize;
end.

Reply by email

James Richters
to Unknown author: Not version I got working using just fpc (I don't use lazarus, or even a gui (in most…

When I run the code below I get:
An unhandled exception occurred at $004143C0:
■ Free Pascal IDE Version 1.0.12 [2022/02/07]
■ Compiler Version 3.3.1-10077-gc8403ad49e
■ GDB Version GNU gdb (GDB) 7.2
Running "i:\programming\sapi.exe "
EOleError: Variant does not reference an automation object $004143C0
$004194DD
$0040B991
$0040193B SPEAK, line 13 of i:/programmingl/sapi.pas $00401962 main, line 17 of i:/programming/sapi.pas

program voice;
uses
comobj;
procedure speak(s : string);
var
v : olevariant;
begin
v:=CreateOleObject('SAPI.SpVoice');
v.Speak(s);
end;
begin
speak('Hello.');
end.

Reply by email

Unknown author
to James Richters: When I run the code below I get: An unhandled exception occurred at $004143C0: ■ Free…

Hmm, ok, apparently something changed in the way FPC handles objects between 3.31 and 3.20 (the version I'm using).

Thought I had 3.22, but <shrug>.

I guess it could be a sapi version difference too, but I don't know how to check that.

James Richters wrote 31 lines
When I run the code below I get: An unhandled exception occurred at $004143C0: ■ Free Pascal IDE Version 1.0.12 [2022/02/07] ■ Compiler Version 3.3.1-10077-gc8403ad49e ■ GDB Version GNU gdb (GDB) 7.2 Running "i:\programming\sapi.exe " EOleError: Variant does not reference an automation object $004143C0 $004194DD $0040B991 $0040193B SPEAK, line 13 of i:/programmingl/sapi.pas $00401962 main, line 17 of i:/programming/sapi.pas program voice; uses comobj; procedure speak(s : string); var v : olevariant; begin v:=CreateOleObject('SAPI.SpVoice'); v.Speak(s); end; begin speak('Hello.'); end.

Reply by email

Unknown author
to James Richters: I appreciate the help with this. I'm still confused. In my original post, I already had…

Also, for what it's worth, your code works fine on fpc 3.20.

James Richters wrote 45 lines
I appreciate the help with this. I'm still confused. In my original post, I already had CoInitialize, CoUninitialize; and Unit ComOBJ, Unit Windows and Unit ActiveX I was still getting EOleError: Variant does not reference an automation object. Do I need to do all this Change FPU stuff? I'm sure I'm doing something wrong but I still can't get it to work. Here's my original program. I wasn't even trying to change the voice yet. What do I need to do to this to make it work? James {$mode objfpc} uses CRT, Windows, SysUtils, ComObj, Variants, OLEServer, Classes, ActiveX, ShellApi; var SavedCW: Word; SpVoice: Variant; MyWideString: WideString; begin CoInitialize(nil); SpVoice := CreateOleObject('SAPI.SpVoice'); MyWideString := WideString('Hello, the time is ' + TimeToStr(Now)); Writeln(MyWideString); // Change FPU interrupt mask to avoid SIGFPE exceptions SavedCW := Get8087CW; try Set8087CW(SavedCW or $4); SpVoice.Speak(MyWideString, 0); finally // Restore FPU mask Set8087CW(SavedCW); end; Writeln('Press Any Key'); ReadKey; CoUninitialize; end. _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Steve Litt
to Rik van Kekem: Op 25-06-2023 om 22:46 schreef James Richters via fpc-pascal: You didn't mention the…

Rik van Kekem via fpc-pascal said on Mon, 26 Jun 2023 16:12:06 +0200

Show quoted text 11 lines
program Project1; {$mode objfpc}{$H+} uses   Classes, ComObj; var   Voice: olevariant; begin   Voice := CreateOLEObject('SAPI.SpVoice');   Voice.Speak('I am speaking.', 0);   Voice.Speak('I am also speaking.', 0); end.

Where does one get ComObj? On my box this errored out with:

speak.pas(4,12) Fatal: Can't find unit ComObj used by Project1

By the way, when pasting the Classes, ComObj line from your email and compiling, I got an error about a bad character. To get past it I had to re-type the command on a new line and then delete the pasted one.

Thanks,

SteveT

Steve Litt
Autumn 2022 featured book: Thriving in Tough Times http://www.troubleshooters.com/bookstore/thrive.htm

Reply by email

Steve Litt
to Steve Litt

Steve Litt via fpc-pascal said on Mon, 26 Jun 2023 22:26:17 -0400

Where does one get ComObj? On my box this errored out with:

I went off half cocked. I'm using Linux. Is ComObj even available on Linux? Would you expect Voice := CreateOLEObject('SAPI.SpVoice') and Voice.Speak('I am speaking.', 0) to work on Linux? I know soundon and soundoff don't work with Linux.

Thanks,

SteveT

Steve Litt
Autumn 2022 featured book: Thriving in Tough Times http://www.troubleshooters.com/bookstore/thrive.htm

Reply by email

Michael Van Canneyt
to Steve Litt
Steve Litt wrote 8 lines
Steve Litt via fpc-pascal said on Mon, 26 Jun 2023 22:26:17 -0400 > Where does one get ComObj? On my box this errored out with: I went off half cocked. I'm using Linux. Is ComObj even available on Linux? Would you expect Voice := CreateOLEObject('SAPI.SpVoice') and Voice.Speak('I am speaking.', 0) to work on Linux? I know soundon and soundoff don't work with Linux.

comobj and everything COM related is windows specific. So this will never work on linux.

The technology that comes closest on Linux is DBUS.

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt: Well, I checked prior to sending my answer. If it does this, it's well hidden. There…
Michael Van Canneyt wrote
 (afaik 3.2.2's comobj does this automatically, in older version YMMV). Well, I checked prior to sending my answer. If it does this, it's well hidden. There seems to be some hook for it, though.

It hooks initproc into a linked list fashion which is called at the end of FPC_INITIALIZEUNITS, which is a way to put it last/late in the init sequence.

Reply by email

James Richters
to James Richters: Well that's worth a lot, it may be indicating a bug in 3.3.1? I guess I need to get on…

I changed to Compiler Version 3.3.1-12875-gadf843196a which is what FPCUPDeluxe installed when I installed Trunk and now it runs just fine. So I guess there was a bug in 3.3.1-10077-gc8403ad49e that was fixed already. I was so convinced that I was doing something wrong I didn't even think to try another version.

Because I use a screen reader, I have multiple sapi voices installed,

(though I rarely use them), but I haven't played with the code enough just yet to see why it fails when it tries to select one, when not selecting one works just fine <shrug>

Here's a sample program that now works on the updated 3.3.1, I guess it should work on 3.2 as well. It lists all available voices and lets you choose one. Maybe that would let you select another voice?

{$Mode OBJFPC}
program VoiceSelection;
uses
  ComObj;
var
  v: OleVariant;
  selectedVoiceIndex: Integer;
  voiceName: string;
  speechText: string;
begin
  v := CreateOleObject('SAPI.SpVoice');
  Writeln('Available Voices:');
  for selectedVoiceIndex := 0 to v.GetVoices.Count - 1 do
  begin
    voiceName := v.GetVoices.Item(selectedVoiceIndex).GetDescription;
    Writeln('Voice ', selectedVoiceIndex + 1, ': ', voiceName);
  end;
  Writeln;
  Writeln('Enter the index of the voice you want to use:');
  Readln(selectedVoiceIndex);
  if (selectedVoiceIndex < 1) or (selectedVoiceIndex > v.GetVoices.Count)
then
  begin
    Writeln('Invalid voice index.');
    Exit;
  end;
  voiceName := v.GetVoices.Item(selectedVoiceIndex - 1).GetDescription;
  v.Voice := v.GetVoices.Item(selectedVoiceIndex - 1);
  Writeln('Selected Voice: ', voiceName);
  speechText := 'Hello World, this is ' + voiceName;
  Writeln('Speech Text: ', speechText);
  v.Speak(speechText);
end.

James

Reply by email