SAPI : change Voice

Re: SAPI : change Voice

Postby Danielmaximiliano » Sat Feb 10, 2024 10:38 pm

hello Jimmy

Jimmy wrote:hi,
Code: Select all  Expand view  RUN
  oSpVoice:EventInterests := SVEAllEvents + SVEAudioLevel

but how to get Event to call Function like in MSDN Sample ?
https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms723593(v=vs.85)


I am reading and reading about how to know that the "Word" event has happened, just for now I am interested in the phoneme or word
applying
Code: Select all  Expand view  RUN
oNarrator                := CreateObject( "Sapi.SPVoice" , "WithEvents" )
oNarrator:EventInterests := SVEPhoneme
oNarrator:Speak( Main.RichEdit_1.VALUE, SVSFlagsAsync)
While ..
...
end

When sending the text to the TTS engine it should know if that event happened but I can't find a way to know yet since there is no real example of how it works.
Danielmaximiliano
 
Posts: 24
Joined: Tue Mar 20, 2012 11:06 pm

Re: SAPI : change Voice

Postby Antonio Linares » Sun Feb 11, 2024 9:05 am

Dear Jimmy,

Those are the different events info!

Please post here the exact code you are using and I will help you to process them
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42113
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: SAPI : change Voice

Postby Antonio Linares » Sun Feb 11, 2024 9:33 am

Never mind, I got the events working here! :-D

Now lets analize them...
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42113
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Re: SAPI : change Voice

Postby Antonio Linares » Sun Feb 11, 2024 9:40 am

Simply add this line at the top:

static aEvents := {}

and then use this:

oVoice:__hSink = __axRegisterHandler( oVoice:__hObj, { | ... | AAdd( aEvents, { ... } ) } )

Finally, after the dialog, do:

XBrowser( aEvents )
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42113
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: SAPI : change Voice

Postby Antonio Linares » Sun Feb 11, 2024 9:42 am

IMO the reason why we were not getting the events was that we were not using a window/dialog in the example

As soon as we have tested it with a dialog, the events arrive! :-D
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42113
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: SAPI : change Voice

Postby Jimmy » Sun Feb 11, 2024 10:10 am

hi,

i "think" we need a RTF Control to use
Code: Select all  Expand view  RUN
  oGetText:SetSel({StreamPosition , StreamPosition + Length})
   oGetText:SetFocus()

to get this Effect ( not perfect ) using HMG Syntax and RTF
Image
a Get / MGet will highlight hole Control when get Focus

but i do not know how to change *.RC from EDITTEXT into RTF (?)
who can help me please
greeting,
Jimmy
User avatar
Jimmy
 
Posts: 1732
Joined: Thu Sep 05, 2019 5:32 am
Location: Hamburg, Germany

Re: SAPI : change Voice

Postby Antonio Linares » Sun Feb 11, 2024 10:34 am

Dear Jimmy,

Can you share the RC for your example ? In case you are using a RC file...

My mistake: the difference with events is NOT a handle of a window. The difference is to play in ASYNC mode !!!

oVoice:Speak( "harbour and xharbour", 1 ) // that 1 uses Async mode and thus events arrive to us !!!
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42113
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: SAPI : change Voice

Postby Enrico Maria Giordano » Sun Feb 11, 2024 10:53 am

Can I see a working sample, please?
User avatar
Enrico Maria Giordano
 
Posts: 8718
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia

Re: SAPI : change Voice

Postby Antonio Linares » Sun Feb 11, 2024 11:58 am

Dear Enrico,

Here you have it:
Code: Select all  Expand view  RUN
#include "FiveWin.ch"

static aEvents := {}

function Main()

    local oVoice := TOleAuto():New( "Sapi.SPVoice" )
   
    oVoice:__hSink = __axRegisterHandler( oVoice:__hObj, { | ... | AAdd( aEvents, { ... } ) } )
 
    oVoice:Speak( "hello my friend", 1 )  // 1 means asynch so events can arrive. Instead of 1, 3 can be used to cancel what is being said and start again in asynch mode
    MsgInfo( "waiting" ) // we wait and process windows messages so events can arrive

    XBrowser( aEvents )
 
 return nil
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42113
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: SAPI : change Voice

Postby Antonio Linares » Sun Feb 11, 2024 12:04 pm

Events and meanings:

1 --> Start
3 --> An OLE object is received, probably self OLE object ?
5 --> Word, 4th param is position, 5th param is length
6 --> ???
7 --> Sentence, 4th param is position, 5th param is length
8 --> ???
2 --> End

https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms723587(v=vs.85)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42113
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Re: SAPI : change Voice

Postby Danielmaximiliano » Sun Feb 11, 2024 11:24 pm

Jimmy wrote: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

mi solunción
Code: Select all  Expand view  RUN
Function ChangeVoice()  //cambiar voz desde un doble click sobre la lista de narradores
local nGrid   := Main.List_1.Value
local cName := aAvoice [ nGrid , 1 ]
Local oVoice
 /* oNarrator:voice   := oNarrator:GetVoices():Item( nGrid - 1)  // Fumciona
    oNarrator:Speak( "Narrador " + cName, SVSFlagsAsync )          */

  For Each oVoice In oNarrator:GetVoices()                      
     If (oVoice:GetDescription(0) == Main.List_1.item(Main.List_1.Value))
      oNarrator:voice := oVoice        
      oNarrator:Speak( "Narrador " + cName, SVSFlagsAsync )
     endif
  Next 

RETURN 
Danielmaximiliano
 
Posts: 24
Joined: Tue Mar 20, 2012 11:06 pm

Re: SAPI : change Voice

Postby Danielmaximiliano » Mon Feb 12, 2024 3:09 am

Hola Jimmy :
Leyendo creo que se necesita la propiedad "Status" https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms723612(v=vs.85)
pero no consigo descifrar bien el uso aqui https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms722534(v=vs.85)
Code: Select all  Expand view  RUN
Function Play()
local  nStreamNumber , nStreamPosition , nCharacterPosition, nLength , ISpeechVoiceStatus
 oNarrator:EventInterests := SVEPhoneme
 
 oNarrator:Speak( Main.RichEdit_1.VALUE, SVSFlagsAsync)
 ISpeechVoiceStatus := oNarrator:Status  
     
      DO WHILE .not. ISpeechVoiceStatus:RunningState == SRSEDone
               
               nCharacterPosition := ISpeechVoiceStatus:InputWordPosition
               nLength            := ISpeechVoiceStatus:InputWordLength
               Main.RichEditBox_1.CaretPos     := nCharacterPosition
               Main.RichEdit_1.SelectRange     := { nCharacterPosition, nLength }
               
      ENDDO
 
Return


el codigo para iluminar el tenxto del control Richtedit deberia ser parecido a esto en VBA
Code: Select all  Expand view  RUN
   V.Speak "this is stream number<bookmark mark='2two'/> two.", SVSFlagsAsync + SVSFIsXML
    List1.AddItem "LastStreamNumberQueued is " & V.Status.LastStreamNumberQueued
    DoEvents

    Do
        V.WaitUntilDone (500) 'Wait for 0.5 second so we won't get too many outputs

        List1.AddItem ""
        List1.AddItem "LastStreamNumberQueued is " & V.Status.LastStreamNumberQueued
        List1.AddItem "CurrentStreamNumber is " & V.Status.CurrentStreamNumber
        List1.AddItem "InputSentenceLength is " & V.Status.InputSentenceLength
        List1.AddItem "InputSentencePosition is " & V.Status.InputSentencePosition
        List1.AddItem "InputWordLength is " & V.Status.InputWordLength
        List1.AddItem "InputWordPosition is " & V.Status.InputWordPosition
        List1.AddItem "RunningState is " & V.Status.RunningState
        List1.AddItem "LastBookmark is " & V.Status.LastBookmark
        List1.AddItem "LastBookmarkId is " & V.Status.LastBookmarkId
        List1.AddItem "VisemeId is " & V.Status.VisemeId
        List1.AddItem "PhonemeId is " & V.Status.PhonemeId
        List1.AddItem "LastHResult is " & V.Status.LastHResult
        DoEvents

    Loop Until V.Status.RunningState = SRSEDone 'Exit when voice stops
Danielmaximiliano
 
Posts: 24
Joined: Tue Mar 20, 2012 11:06 pm

Re: SAPI : change Voice

Postby Jimmy » Mon Feb 12, 2024 6:02 am

hi Antonio,
Antonio Linares wrote:Events and meanings:

1 --> Start
3 --> An OLE object is received, probably self OLE object ?
5 --> Word, 4th param is position, 5th param is length
6 --> ???
7 --> Sentence, 4th param is position, 5th param is length
8 --> ???
2 --> End

thx for your List f Event meaning, now it work (almost) perfect
Code: Select all  Expand view  RUN

  oSpVoice:__hSink := __axRegisterHandler( oSpVoice:__hObj, { | a,b,c,d,e | OnEvent( a,b,c,d,e ) } )


FUNCTION OnEvent()
LOCAL iMax  := PCOUNT()
LOCAL i
LOCAL aPara := ARRAY(5)

   FOR i := 1 TO iMax
     aPara[i] := PValue( i ) ) )
   NEXT

   DO CASE
     CASE aPara[1] = 2
         OffSet := aPara[3]
         oSpVoice_Word(aPara[2],aPara[3],0, 0)
      CASE aPara[1] = 5
         oSpVoice_Word(aPara[2],aPara[3],aPara[4], aPara[5])
   ENDCASE
RETURN NIL

PROCEDURE oSpVoice_Word(StreamNumber, StreamPosition , CharacterPosition , Length )
   oGetText:SetSel({CharacterPosition , CharacterPosition + Length})
   oGetText:SetFocus()
   SYSRefresh()
RETURN

but as i say : it need a RTF in *.RC to show highlight Word
greeting,
Jimmy
User avatar
Jimmy
 
Posts: 1732
Joined: Thu Sep 05, 2019 5:32 am
Location: Hamburg, Germany

PreviousNext

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: RSalazarU and 46 guests