Announcement

Collapse
No announcement yet.

Object Code for Study - Set Speech Rate

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Object Code for Study - Set Speech Rate

    I was playing with some SAPI code and ran across two different approaches to coding an Object, where the task was to set the speed of the speaking voice. Not having any particular skills with Objects, I just thought the two approaches were interesting and worthy of taking a closer look because it will teach me something about using Objects.

    This must be the millionth time I've told myself I want to code more with Objects. The list of reasons, and code I want to explore, just keeps building up!

    This is a side-by-side comparison of the two coding approaches. I find it useful in viewing the differences between the two. The actual code listings are further down the post.

    Click image for larger version  Name:	pb_2056.jpg Views:	1 Size:	129.1 KB ID:	771624
    Code:
    'Compilable Example:
    #Compiler PBWin 10
    #Compile Exe
    #Dim All
    %Unicode=1
    #Include "Win32API.inc"
    %IDC_Slow = 500
    %IDC_Fast = 501
    
    Global hDlg As Dword, vRes, vTxt As Variant, oSp As Dispatch
    
    Function PBMain() As Long
       Dialog Default Font "Tahoma", 12, 1
       Dialog New Pixels, 0, "SAPI, Test Code",300,300,200,75, %WS_OverlappedWindow To hDlg
       Control Add Button, hDlg, %IDC_Slow,"Slow", 10,10,75,25
       Control Add Button, hDlg, %IDC_Fast,"Fast", 100,10,75,25
       Dialog Show Modal hDlg Call DlgProc
    End Function
    
    CallBack Function DlgProc() As Long
       Local vRate As Long
       Select Case Cb.Msg
          Case %WM_InitDialog
             vTxt = "Hello from Gary Beene"
             osp = NewCom "SAPI.SpVoice"
          Case %WM_Command
             Select Case Cb.Ctl
                Case %IDC_Slow
                   vRate = -3
                   Object Let osp.Rate() = vRate
                   Object Call osp.Speak(vTxt) To vRes
                Case %IDC_Fast
                   vRate = +3
                   Object Let osp.Rate() = vRate
                   Object Call osp.Speak(vTxt) To VRes
             End Select
       End Select
    End Function
    Code:
    'Compilable Example:
    #Compile Exe
    #Dim All
    %Unicode=1
    #Include "Win32API.inc"
    #Include "Sapi.inc"
    %IDC_Fast   = 501
    %IDC_Slow   = 502
    
    Global hDlg As Dword, psp As ISpVoice, wText As WString
    
    Function PBMain() As Long
       Dialog Default Font "Tahoma", 12, 1
       Dialog New Pixels, 0, "SAPI Test Code",300,300,300,75, %WS_OverlappedWindow To hDlg
       Control Add Button, hDlg, %IDC_Slow,"Slow", 10,10,75,20
       Control Add Button, hDlg, %IDC_Fast,"Fast", 100,10,75,20
       Dialog Show Modal hDlg Call DlgProc
    End Function
    
    CallBack Function DlgProc() As Long
       Select Case Cb.Msg
          Case %WM_InitDialog
             wText = "Hello from Gary Beene"
             pSp = NewCom "SAPI.SpVoice"
          Case %WM_Command
             Select Case Cb.Ctl
                Case %IDC_Slow
                   psp.SetRate -3
                   pSp.Speak(ByVal StrPtr(wText), %SPF_Async, ByVal %Null)
                Case %IDC_Fast
                   psp.SetRate +3
                   pSp.Speak(ByVal StrPtr(wText), %SPF_Async, ByVal %Null)
             End Select
       End Select
    End Function

  • #2
    Well, pooh. The image doesn't load full size, making the code harder to read. Not sure how to fix that.

    Comment


    • #3
      Hi Gary,

      The code samples both create the same object.
      That is a "SAPI.SpVoice" COM object.

      The code on the left uses old functional style access where the one on the right uses more conventional object access.

      All windows COM objects will provide an hResult to let you know how well your code worked.
      The PB code on the left passes this into vRes.
      The code on the right still provides the hResult but you would need to use the PB OBJRESULT keyword to get at it.

      The code on the right is more readable and in keeping with COM object coding standards.


      For using something as general as speech, you would normally create a global object and not create one each time in a Dlg procedure.
      Wrapping the object so you can use syntax like " Speak "Hello" " is also a good idea.

      Hope this helps.
      I Know its late from the post but just spotted it while looking for an answer to a powerthread issue.

      Regards,
      Neil

      Kind regards,
      Neil

      http://www.BASICProgramming.info

      Comment


      • #4
        Gary was comparing the slower DISPATCH versus a DIRECT interface.

        You should always use the simpler and faster DIRECT interface where it is available.

        Comment


        • #5
          You are mistaken.


          If you mean comparing the difference between late and early binding then NO he is not doing that.

          He would need an INTERFACE IDBIND definition in there somewhere.


          The 2 differences between the 2 apps are merely syntactic and where the OBJResult goes.
          Both do lookups through the vTable.


          Gary is not interested in speed as he is creating a new object each time in a dialog function and there are no TIX or TIMER statements anywhere.
          He is also relying on PB helping the programmer by deleting the object as it goes out of scope.

          If as a programmer you know the object you are using you should be using EARLY binding.

          Kind regards,
          Neil

          http://www.BASICProgramming.info

          Comment


          • #6
            Originally posted by Neil Prichard View Post
            You are mistaken.

            If you mean comparing the difference between late and early binding then NO he is not doing that.
            I am not mistaken and I don't mean that. I meant what I said. Let me amplify it slightly
            Gary was comparing the old, slower, more cumbersome DISPATCH interface versus the newer, more efficient DIRECT interface.

            In the first/left code Gary is using "oSp As Dispatch" (Dispatch Interface)
            in the second/right code he is using "psp As ISpVoice" (Direct Interface)


            The 2 differences between the 2 apps are merely syntactic and where the OBJResult goes.
            Both do lookups through the vTable.
            They differences are not merely syntactic, They are very different ways of working with the object and its parameters ( variant! )

            To quote Bob Zale in Help:
            "Prior versions of PowerBASIC introduced client COM services, which were accessible through the COM DISPATCH interface. While the DISPATCH interface is very flexible and easy-to-use, that very flexibility adds a level of overhead which is unacceptable for many applications. This version of PowerBASIC adds the capability to create and access COM objects through a DIRECT INTERFACE or a DISPATCH INTERFACE."

            and

            DIRECT INTERFACE: This is the most efficient form of interface. When you call a particular METHOD or PROPERTY, the compiler simply performs an indirect jump to the correct entry point listed in the virtual function table (VFT or VTBL). This is just as fast as calling a standard Sub or Function, and is the default access method used by PowerBASIC.

            · DISPATCH INTERFACE: This is a slow form of interface, originally introduced as a part of Microsoft Visual Basic. When you use DISPATCH, the compiler actually passes the name of the METHOD you wish to execute as a text string. The parameters can also be passed in the same way. The object must then look up the names, and decide which METHOD to execute, and which parameters to use, based upon the text strings provided. This is a very slow process. Many scripting languages still use DISPATCH as their sole method of operation, so continued support is necessary.



            Comment

            Working...
            X