Page 1 of 5

SAPI : change Voice

PostPosted: Tue Jan 23, 2024 5:58 am
by Jimmy
hi.

i try to change "Voice" of Sapi.SPVoice

"Voice"is a Property of SPVoice and use ISpeechObjectTokens object as Parameter

ISpeechObjectTokens object just have Method Item and Property COUNT
Image
---

but when i try
Code: Select all  Expand view
  oVoices:Voice  := oVoices:GetVoices():Item(cnVar -1)

i got Error
Error description: (DOS Error -2147352573) WINOLE/1006 Argument error: _VOICE
Args:
[ 1] = O
-2147352573 : "Member not found."

i also try SetVoice()
Error description: (DOS Error -2147352570) WINOLE/1009 No exported method: SETVOICE
-2147352570 : "Unknown name."

but it seem me another Interface ...

Question : do i need to CoCreateInstance those Interface :?:

Re: SAPI : change Voice

PostPosted: Wed Jan 24, 2024 9:11 am
by Antonio Linares
Dear Jimmy,

asking chatgpt for help:
Code: Select all  Expand view
#include <windows.h>
#include <sapi.h>

int main() {
    CoInitialize(NULL);

    ISpVoice *pVoice = NULL;
    HRESULT hr = CoCreateInstance(&CLSID_SpVoice, NULL, CLSCTX_ALL, &IID_ISpVoice, (void**)&pVoice);

    if (SUCCEEDED(hr)) {
        // Get the list of available voices
        ISpObjectTokenCategory *pCategory = NULL;
        hr = CoCreateInstance(&CLSID_SpObjectTokenCategory, NULL, CLSCTX_ALL, &IID_ISpObjectTokenCategory, (void**)&pCategory);

        if (SUCCEEDED(hr)) {
            hr = pCategory->SetId(SPCAT_VOICES, FALSE);

            if (SUCCEEDED(hr)) {
                IEnumSpObjectTokens *pEnum = NULL;
                hr = pCategory->EnumTokens(NULL, NULL, &pEnum);

                if (SUCCEEDED(hr)) {
                    // Change the voice - replace "Microsoft David Desktop - English (United States)" with the desired voice
                    const wchar_t *desiredVoice = L"Microsoft David Desktop - English (United States)";
                    ISpObjectToken *pVoiceToken = NULL;

                    while (pEnum->Next(1, &pVoiceToken, NULL) == S_OK) {
                        WCHAR *voiceDescription;
                        if (SUCCEEDED(pVoiceToken->GetDescription(&voiceDescription))) {
                            if (wcscmp(voiceDescription, desiredVoice) == 0) {
                                // Set the voice
                                hr = pVoice->SetVoice(pVoiceToken);
                                wprintf(L"Voice changed to: %s\n", desiredVoice);
                                break;
                            }
                            CoTaskMemFree(voiceDescription);
                        }
                        pVoiceToken->Release();
                    }
                    pEnum->Release();
                }
            }
            pCategory->Release();
        }

        // Speak something with the new voice
        if (SUCCEEDED(hr)) {
            pVoice->Speak(L"Hello, I am using a different voice now.", 0, NULL);
        }

        pVoice->Release();
    }

    CoUninitialize();

    return 0;
}
 

Re: SAPI : change Voice

PostPosted: Wed Jan 24, 2024 11:49 am
by Jimmy
hi Antonio,

thx for help and "C"-CODE from ChatGPT

now i have to find out how to use that "C" CODE with harbour as HB_FUNC()

---

i wonder that i real need CoCreateInstance() under harbort and Xbase++ as VB did work without "extra" CODE
you can see it in this Video
https://www.youtube.com/watch?v=klAAoeuuu_c

---

there is a free 3-PP Solution : DispHelper
Speech.C
Code: Select all  Expand view
  ...
       dhPutRef(tts, L".Voice = %o", spVoice);

DispHelper :
https://disphelper.sourceforge.net/
https://github.com/DrYak/disphelper

Re: SAPI : change Voice

PostPosted: Thu Jan 25, 2024 4:24 am
by Jimmy
hi,

i try to use CODE from ChatGPT as HB_FUNC() but i got Errors
C:\hmg.3.4.4\0\SAPI>..\..\build SapiVoice.hbp
Harbour 3.2.0dev (r1703241902)
Copyright (c) 1999-2016, http://harbour-project.org/
HB_FUNC.PRG: In function 'HB_FUN_GETZIRA':
HB_FUNC.PRG:20:31: error: 'ISpObjectTokenCategory {aka struct ISpObjectTokenCategory}' has no member named 'SetId'
HB_FUNC.PRG:24:35: error: 'ISpObjectTokenCategory {aka struct ISpObjectTokenCategory}' has no member named 'EnumTokens'
HB_FUNC.PRG:31:37: error: 'IEnumSpObjectTokens {aka struct IEnumSpObjectTokens}' has no member named 'Next'
In file included from C:/hmg.3.4.4/mingw/i686-w64-mingw32/include/winbase.h:2377:0,
from C:/hmg.3.4.4/mingw/i686-w64-mingw32/include/windows.h:70,
from HB_FUNC.PRG:3:
HB_FUNC.PRG:33:54: error: 'ISpObjectToken {aka struct ISpObjectToken}' has no member named 'GetDescription'
HB_FUNC.PRG:36:48: error: 'ISpVoice {aka struct ISpVoice}' has no member named 'SetVoice'
HB_FUNC.PRG:42:40: error: 'ISpObjectToken {aka struct ISpObjectToken}' has no member named 'Release'
HB_FUNC.PRG:44:30: error: 'IEnumSpObjectTokens {aka struct IEnumSpObjectTokens}' has no member named 'Release'
HB_FUNC.PRG:47:26: error: 'ISpObjectTokenCategory {aka struct ISpObjectTokenCategory}' has no member named 'Release'
HB_FUNC.PRG:52:23: error: 'ISpVoice {aka struct ISpVoice}' has no member named 'Speak'
HB_FUNC.PRG:55:19: error: 'ISpVoice {aka struct ISpVoice}' has no member named 'Release'
HB_FUNC.PRG:60:16: warning: 'return' with a value, in function returning void
hbmk2[SapiVoice]: Error: Running C/C++ compiler. 1
gcc.exe -c -O3 -march=i586 -mtune=pentiumpro -fomit-frame-pointer -W -Wall -pipe -IC:/hmg.3.4.4/harbour/include -IC:/hm
g.3.4.4/0/SAPI -IC:/hmg.3.4.4/include R:/Temp/hbmk_9tofgt.dir/Main.c R:/Temp/hbmk_9tofgt.dir/HB_FUNC.c R:/Temp/hbmk_5vro
0l.c

the Error are in Lines which have "->" (Alias ?) in Line of CODE
need more help please as i´m not a "C"-Programmer and don´t understand Errors

Re: SAPI : change Voice

PostPosted: Fri Jan 26, 2024 7:13 am
by Antonio Linares
Dear Jimmy,

It seems as a bug in Harbour TOleAuto as this code should work:

oVoice:voice = oVoice:GetVoices():Item( 1 )

Re: SAPI : change Voice

PostPosted: Fri Jan 26, 2024 8:47 am
by Jimmy
hi Antonio,

thx for the Idea.

Result is same like using Property "Voice"
Error description: (DOS Error -2147352573) WINOLE/1007 Argument error: VOICE
Args:
[ 1] = O

Stack Calls
===========
Called from: => TOLEAUTO:VOICE( 0 )
Called from: main.prg => CHANGEVOICE( 125 )
Called from: main.prg => (b)MAIN( 43

Re: SAPI : change Voice

PostPosted: Fri Jan 26, 2024 10:01 am
by Antonio Linares
It seems as a bug in Harbour TOleAuto

Re: SAPI : change Voice

PostPosted: Fri Jan 26, 2024 4:51 pm
by Antonio Linares
Dear Jimmy,

I keep a github repo that allows to run Harbour from Visual Studio in debug mode:
https://github.com/FiveTechSoft/harbour_app_msvc64_sources

I have been debugging the Harbour code and it seems as when we try to assign oVoice:Voice if fails though it admits "Voice" as a valid message

Its strange, but we have been unable to find a way to solve it for now...

Re: SAPI : change Voice

PostPosted: Fri Jan 26, 2024 7:10 pm
by Otto
Dear Antonio,
Sometimes I would also be interested in a debugger.
Can you perhaps create a screenshot video showing how Harbour runs in debug mode, what you see, and how to install it?


Best regards,
Otto

Re: SAPI : change Voice

PostPosted: Fri Jan 26, 2024 7:20 pm
by Antonio Linares
Dear Otto,

this is not a high level Harbour debugger

It is a low level debugger to see the Harbour virtual machine running and be able to debug C code. You get it when you install (free) Visual Studio Community

1. Install Visual Studio Community
2. git clone https://github.com/FiveTechSoft/harbour_app_msvc64_sources
3. double click on the SLN file

It is to review Harbour internals, etc. not for high level use

https://github.com/FiveTechSoft/screenshots/blob/master/visual_studio_debugger.png?raw=true

Image

Re: SAPI : change Voice

PostPosted: Sun Jan 28, 2024 6:19 am
by Antonio Linares
Dear Jimmy,

Fixed! :-)

Effectively it was a Harbour bug. Now it is working fine.

Do you build Harbour yourself or do you prefer me to send it to you ? For what C compiler ?

The fix:
in harbour/contrib/hbwin/olecore.c

HB_FUNC( WIN_OLEAUTO___ONERROR )
...
Code: Select all  Expand view
        if ((HB_ISBYREF(1)) || HB_ISARRAY(1))
             lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_( pDisp ) dispid, HB_ID_REF( IID_NULL ),
                                                   LOCALE_USER_DEFAULT,
                                                   DISPATCH_PROPERTYPUTREF, &dispparam,
                                                   NULL, &excep, &uiArgErr );
         else
             lOleError = HB_VTBL( pDisp )->Invoke( HB_THIS_(pDisp) dispid, HB_ID_REF( IID_NULL ),
                                                   LOCALE_USER_DEFAULT,
                                                   DISPATCH_PROPERTYPUT, &dispparam,
                                                   NULL, &excep, &uiArgErr );

Re: SAPI : change Voice

PostPosted: Sun Jan 28, 2024 6:38 am
by Jimmy
hi Antonio,

this is a GREAT News

can you please send me a Link for download fixed Harbour Version to use with BCC7 32 Bit, thx

Re: SAPI : change Voice

PostPosted: Sun Jan 28, 2024 6:41 am
by Antonio Linares
https://github.com/FiveTechSoft/harbour_and_xharbour_builds/blob/master/hbwin.lib

Please test it and let me know if it works fine for you :-)

The bug and the fix have been reported to the Harbour devel group so it should be included in the Harbour official repo very soon!

Re: SAPI : change Voice

PostPosted: Sun Jan 28, 2024 8:58 am
by Jimmy
hi Antonio,

i have follow Link and download File
than i rename old Folder and unpack file harbour_bcc770_32_20231117.zip into c:\harbour

when now try to build my Fivewin Project i got
Turbo Incremental Link 6.70 Copyright (c) 1997-2014 Embarcadero Technologies, Inc.
Error: Unresolved external '___get_std_stream' referenced from C:\HARBOUR\LIB\WIN\BCC\HBVMMT.LIB|fm
Error: Unable to perform link

---

i do have copy hbwin.lib into c:\Harbour\lib\win\bcc afterwards but get same Error
what i´m doing wrong :?:

Re: SAPI : change Voice

PostPosted: Sun Jan 28, 2024 9:49 am
by Enrico Maria Giordano
Please try with HBVM.LIB instead of HBVMMT.LIB.