Announcement

Collapse
No announcement yet.

How do I convert Text to Speech in PowerBASIC?

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

  • #21
    Hi,

    I would like to use "SAPI 4.0" text-to-speech engine from Microsoft;
    I know "SAPI 4.0" is pretty old, but it comes with various text-to-speech engines languages :

    - American English
    - British English
    - Dutch
    - French
    - German
    - Italian
    - Japaneses
    - Korean
    - Portugeese (Brazil)
    - Russian
    - Spanish

    Does anyone has make it work with PowerBASIC ?

    link for user : http://www.microsoft.com/MSAGENT/downloads/user.asp#tts

    link for developer http://www.microsoft.com/msagent/dow.../developer.asp

    Thank you for your help.
    Jean-Pierre

    ------------------
    Jean-Pierre LEROY
    Cholet - France



    [This message has been edited by Jean-Pierre LEROY (edited February 15, 2006).]
    Jean-Pierre LEROY

    Comment


    • #22
      You can change the voice and voice speed in the control panel.
      Speech Properties/Text To Speech


      ------------------

      Comment


      • #23
        Whats the min size of SAPI componants that need to be shipped
        with my app?



        ------------------
        Kind Regards
        Mike

        Comment


        • #24
          Mike,
          for use on WinXP, there are no components required, the basic speech stuff is part of the operating system.

          Paul.


          ------------------

          Comment


          • #25
            Hi,

            I try the code supply by Jose, but it doesn't seem to work with the old "SAPI 4.0" text-to-speech engine from Microsoft.

            "SAPI 4.0" is pretty old, but it comes with various text-to-speech engines languages (see my previous reply in this thread).

            Any chance to get it work with PowerBASIC ?

            Thank you for your help.
            Jean-Pierre LEROY

            ------------------
            Jean-Pierre LEROY
            Cholet - France

            [This message has been edited by Jean-Pierre LEROY (edited April 07, 2006).]
            Jean-Pierre LEROY

            Comment


            • #26
              SAPI 4.0 should have a different ProgID. Use the COM browser to get it.
              Also check if the names of the methods are the same or different.

              Forum: http://www.jose.it-berater.org/smfforum/index.php

              Comment


              • #27
                Thank you José for your reply.

                From the Microsoft Agent version 2.0 I get these information.

                To use a particular speech engine in your code, use the Agent API to set the engine. For speech input engines, use SRModeID, specifying the mode ID for the engine. However, note that the engine must be installed. To determine if the engine is present, you can query SRModeID. The engine must match the character's LanguageID setting. For example, you cannot set SRModeID to a German speech recognition engine mode ID for a character whose LanguageID is French.

                Voice Mode IDs
                Microsoft Speech Recognition Engine v4.0 {D8905400-B5C8-11D0-B968020AFDB1B9C}


                Check and set the character's LanguageID and SRModeID in your code before you attempt to define grammar for the voice parameters of Command objects your application. Also consider checking the browser or system language so you can be certain to match your users' configuration. The engine may fail if you attempt to define a grammar for a language that the engine does not match.
                A character set for text-to-speech (TTS) output can be compiled with a default speech output engine's mode ID preference. When the character is loaded, if the engine is installed and matches the character's LanguageID, Agent will attempt to load that mode ID for speech output. If the engine is not present or has a different LanguageID, Agent will attempt to load the first mode ID it finds that matches the character's LanguageID, but still sets the character's compiled speed and pitch setting.
                Note that since all Microsoft Agent supplied characters are compiled to use the Lernout & Hauspie TruVoice American English engine as the default speech output engine, the characters' speed and pitch setting are tuned for this language and engine. Therefore when using other TTS engines or engines of other languages the characters may not speak at the optimal pitch or speed. Although your application or Web page cannot write the Pitch and Speed property values, you can include Pit (pitch) and Spd (speed) tags in your output text that will temporarily change the pitch and speed for a particular utterance. However, using the Pit and Spd tags will not change the Pitch and Speed properties. See Programming the Microsoft Agent Control and the Microsoft Agent Speech Output Tags for details.
                You also need to install the SAPI 4.0a runtime binaries (SPCHAPI.exe) when using other SAPI-compliant TTS engines than the L&H TruVoice American English engine with the Microsoft Agent supplied characters so that the engines are enumerated properly. To download and install the SAPI runtime binaries, go to the Microsoft Agent Download page, or from your Web page, include the following Object tag to automatically install the component:
                Code:
                <OBJECT width=0 height=0
                CLASSID="CLSID:0C7F3F20-8BAB-11d2-9432-00C04F8EF48F"
                CODEBASE="#VERSION=4,0,0,0">
                </OBJECT>
                What the difference between the ProgID and the CLSID ?
                I'm sorry to ask such question; I'm not familiar with COM programming.

                Thank you.
                ------------------
                Jean-Pierre LEROY
                Cholet - France

                [This message has been edited by Jean-Pierre LEROY (edited April 07, 2006).]
                Jean-Pierre LEROY

                Comment


                • #28
                  A ProgID (Program Identifier) is an alphanumeric string associated with
                  a ClsID (Class Identifier). See the PROGID$ keyword in the PB Help File.
                  To get a ProgID from the ClsID that you have posted use
                  a$ = PROGID$("{0C7F3F20-8BAB-11d2-9432-00C04F8EF48F}").

                  However, your quote talks about choosing an speech engine to be used by
                  Microsoft Agent, not about to use SAPI 4.0 directly.

                  Run the COM browser, search for something like Microsoft Speech Engine 4.0
                  and generate the interface declarations.
                  Forum: http://www.jose.it-berater.org/smfforum/index.php

                  Comment


                  • #29
                    Jose,
                    Resurrecting this thread ... I tried out your code in post #5 to stop SAPI but could not get it to work. The text reads until it is complete, even if I do press the button. Did I interpret your post correctly?

                    Code:
                    'Compilable Example:
                    #Compiler PBWin 10
                    #Compile Exe
                    #Dim All
                    
                    %IDC_Stop = 500
                    %Unicode=1
                    #Include "Win32API.inc"
                    Global hDlg, hThread As Dword, StopTalking As Long, sText As String
                    
                    Function PBMain() As Long
                       Dialog New Pixels, 0, "Stop SAPI Test",300,300,300,200, %WS_OverlappedWindow To hDlg
                       Control Add Button, hDlg, %IDC_Stop,"Stop", 50,10,100,20
                       Dialog Show Modal hDlg Call DlgProc
                    End Function
                    
                    CallBack Function DlgProc() As Long
                       Select Case Cb.Msg
                          Case %WM_InitDialog
                             sText = "Now is the time for all good men to read this sentence and head to the enlistment center to help their country fight for justice!"
                             Thread Create ReadText(0) To hThread
                             Thread Close hThread To hThread
                          Case %WM_Command
                             Select Case Cb.Ctl
                                Case %IDC_Stop
                                   StopTalking = 1
                             End Select
                       End Select
                    End Function
                    
                    Thread Function ReadText (ByVal X As Long) As Long
                       Local vRes, vTxt, vTime As Variant, oSp As Dispatch
                       Let oSp = NewCom "SAPI.SpVoice"
                       If IsFalse IsObject(oSp) Then Exit Function
                       vTxt = sText
                       Object Call oSp.Speak(vTxt) To vRes
                    
                       vTime = 10 As Long   ' Check every 10 milliseconds
                       Do
                          Object Call oSp.WaitUntilDone(vTime) To vRes
                          If Variant#(vRes) Then Exit Do  ' Exit if finished
                          If IsTrue StopTalking Then Exit Do
                       Loop
                    End Function

                    Comment


                    • #30
                      Using Object Call oSp.Speak(vTxt) To vRes uses the default action, that is to do the task synchronously.

                      Change it to

                      Code:
                      DIM vFlag AS VARIANT
                      vFlag = 1 AS LONG ' %SVSFlagsAsync
                      Object Call oSp.Speak(vTxt, vFlag) To vRes
                      to run it asynchronously.
                      Forum: http://www.jose.it-berater.org/smfforum/index.php

                      Comment


                      • #31
                        Howdy, Jose!

                        Yep - that does the trick. Thanks!

                        Comment


                        • #32
                          When I went looking in the forum on the topic (stopping the voice), I was surprised to find that every example used the vTime=-1 option. I expected to find a dozen folks wanting to know how to stop the text once it was started. So either everyone else figured it out but me, or no one uses SAPI all that much!

                          Comment


                          • #33
                            > When I went looking in the forum on the topic (stopping the voice), I was surprised to find that every example used the vTime=-1 option.

                            In fact, WaitUntilDone is not called if you have called Speak in the default synchronously mode, because "When synchronous speech is used in an application, the application's execution is blocked while the voice speaks, and the user is effectively locked out. This may be acceptable for simple applications, or those with no graphical user interface (GUI), but when sophisticated user interaction is intended, asynchronous speaking will generally be more appropriate. The WaitUntilDone and SpeakCompleteEvent methods can be used to block an application's forward progress while allowing user interaction with the mouse or keyboard."

                            > I expected to find a dozen folks wanting to know how to stop the text once it was started. So either everyone else figured it out but me, or no one uses SAPI all that much!

                            Sapi is a COM technology, and COM is evil
                            Forum: http://www.jose.it-berater.org/smfforum/index.php

                            Comment


                            • #34
                              I downloaded the SAPI5 SDK to get one useful tool, TTSApp.exe which saves speech as a wav file. Convert it to MP3 and you can use it in video. There are a couple of useful voices in Win 10, the earlier ones were very poor. Opened the exe and tweaked the size of the dialog to make it easier to use and it more or less does the job if either wav or MP3 sound is what you are after.

                              Here is a test piece I posted on Youtube that uses the Win10 Zira voice.

                              https://www.youtube.com/watch?v=aC3AzuWfIBc
                              hutch at movsd dot com
                              The MASM Forum

                              www.masm32.com

                              Comment


                              • #35
                                Steve,
                                Nice video. I need to go try out the new voices ... as time permits. There's no end of cool thing to do in this world.

                                Comment


                                • #36
                                  With Jose's stop solution in it ...


                                  Code:
                                  'Compilable Example:
                                  #Compiler PBWin 10
                                  #Compile Exe
                                  #Dim All
                                  
                                  %IDC_Start   = 500
                                  %IDC_TextBox = 501
                                  %IDC_Stop    = 502
                                  
                                  %Unicode=1
                                  #Include "Win32API.inc"
                                  Global hDlg, hThread As Dword, StopTalking As Long, sText As String
                                  
                                  Function PBMain() As Long
                                     Local style&
                                     style& = %WS_TabStop Or _
                                              %WS_Border Or  _
                                              %ES_Left Or    _
                                              %ES_WantReturn Or _      '<--- optional, needed for manual editing
                                              %ES_MultiLine
                                     Dialog New Pixels, 0, "SAPI Test",300,300,300,200, %WS_OverlappedWindow To hDlg
                                     Control Add Button, hDlg, %IDC_Start,"Start", 10,10,100,20
                                     Control Add Button, hDlg, %IDC_Stop,"Stop", 120,10,100,20
                                     Control Add TextBox, hDlg, %IDC_TextBox, "", 10,50,220,200, style&
                                     Dialog Show Modal hDlg Call DlgProc
                                  End Function
                                  
                                  CallBack Function DlgProc() As Long
                                     Local w,h As Long
                                     Select Case Cb.Msg
                                        Case %WM_InitDialog
                                           sText$ = "Now is the time for all good men to read"
                                           sText$ += " this sentence and head to the enlistment"
                                           sText$ += " center to help their country fight for justice!"
                                           Control Set Text hDlg, %IDC_TextBox, sText$
                                        Case %WM_Size
                                           Dialog Get Client hDlg To w,h
                                           Control Set Size hDlg, %IDC_Textbox, w-20,h-60
                                        Case %WM_Command
                                           Select Case Cb.Ctl
                                              Case %IDC_Start
                                                 Thread Create ReadText(0) To hThread
                                                 Thread Close hThread To hThread
                                              Case %IDC_Stop
                                                 StopTalking = 1
                                           End Select
                                     End Select
                                  End Function
                                  
                                  Thread Function ReadText (ByVal X As Long) As Long
                                     Local vFlag, vRes, vTxt, vTime As Variant, oSp As Dispatch
                                     Let oSp = NewCom "SAPI.SpVoice"
                                     If IsFalse IsObject(oSp) Then Exit Function
                                  
                                     vTxt = sText
                                     vFlag = 1
                                     Object Call oSp.Speak(vTxt,vFlag) To vRes
                                  
                                     vTime = 10 As Long   ' Check every 10 milliseconds
                                     Do
                                        Object Call oSp.WaitUntilDone(vTime) To vRes
                                        If Variant#(vRes) Then Exit Do  ' Exit if finished
                                        If IsTrue StopTalking Then Exit Do
                                     Loop
                                  End Function

                                  Comment


                                  • #37
                                    Jose!

                                    I was thinking that it would be cool to highlight each word as it is spoken Looking at MSDN it seems that we can set the events SAPI sends to the calling application - particularly the SPEI_TTS_BOUNDARY event, which provides information about the word being spoken.

                                    Have you published an example of how to access that SAPI event? I don't see anything here on the forums about it.

                                    With the boundary information in hand, it would be easy enough to highlight the corresponding text in the textbox.
                                    Last edited by Gary Beene; 17 Jul 2017, 10:45 AM.

                                    Comment


                                    • #38
                                      Hey Gary,

                                      Using José's indications, you may also put stuff like

                                      [Code to get volume from a control]
                                      Object Call oSp.SetVolume(vVolume) 'Volume from zero to 100

                                      [Code to get rate from a control]
                                      Object Call oSp.SetRate(vRate) 'Talking speed from -10 to 10

                                      in the LOOP to gain even more control over the speak process...

                                      Pierre

                                      Comment


                                      • #39
                                        Yep, Pierre, more fun waiting to be had

                                        Comment


                                        • #40
                                          This is an example using the low-level ISpVoice interface.

                                          Code:
                                          ' ########################################################################################
                                          ' Microsoft Windows
                                          ' Contents: SAPI example
                                          ' Compilers: PBWIN 10+, PBCC 6+
                                          ' Headers: Windows API headers III
                                          ' Copyright (c) 2017 José Roca. Freeware. Use at your own risk.
                                          ' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
                                          ' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
                                          ' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
                                          ' ########################################################################################
                                          #COMPILE EXE
                                          #DIM ALL
                                          %UNICODE = 1
                                          
                                          ' // Include files for external files
                                          #INCLUDE ONCE "CWindow.inc"   ' // CWindow class
                                          #INCLUDE ONCE "Sapi.inc"
                                          
                                          %IDC_START = 1001
                                          %IDC_STOP = 1002
                                          %MSG_SAPI_EVENT = %WM_USER + 1   ' --> change me
                                          
                                          GLOBAL pSp AS ISpVoice, wText AS WSTRING
                                          
                                          ' ========================================================================================
                                          ' Main
                                          ' ========================================================================================
                                          FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG
                                          
                                             ' // Set process DPI aware
                                             AfxSetProcessDPIAware
                                          
                                             ' // Create an instance of the class
                                             LOCAL pWindow AS IWindow
                                             pWindow = CLASS "CWindow"
                                             IF ISNOTHING(pWindow) THEN EXIT FUNCTION
                                          
                                             ' // Create the main window
                                             ' // Note: CW_USEDEFAULT is used as the default value When passing 0's as the width and height
                                             pWindow.CreateWindow(%NULL, "SAPI example", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
                                             ' // Set the client size
                                             pWindow.SetClientSize 500, 320
                                             ' // Center the window
                                             pWindow.CenterWindow
                                          
                                             ' // Add the buttons
                                             pWindow.AddButton(pWindow.hwnd, %IDC_START, "&Start", 250, 250, 75, 23)
                                             pWindow.AddButton(pWindow.hwnd, %IDC_STOP, "&Stop", 350, 250, 75, 23)
                                          
                                             ' // Create an instance of the SpVoice object
                                             pSp = NewCom "SAPI.SpVoice"
                                             pSp.SetInterest(SPFEI(%SPEI_WORD_BOUNDARY), SPFEI(%SPEI_WORD_BOUNDARY))
                                             pSp.SetNotifyWindowMessage(pWindow.hwnd, %MSG_SAPI_EVENT, 0, 0)
                                          
                                             ' // Default message pump (you can replace it with your own)
                                             FUNCTION = pWindow.DoEvents(nCmdShow)
                                          
                                          END FUNCTION
                                          ' ========================================================================================
                                          
                                          ' ========================================================================================
                                          ' Main callback function.
                                          ' ========================================================================================
                                          FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
                                          
                                             ' // Process window mesages
                                             SELECT CASE uMsg
                                          
                                                CASE %WM_COMMAND
                                                   SELECT CASE LO(WORD, wParam)
                                                      CASE %IDCANCEL
                                                         ' // If the Escape key has been pressed...
                                                         IF HI(WORD, wParam) = %BN_CLICKED THEN
                                                            ' // ... close the application by sending a WM_CLOSE message
                                                            SendMessage hwnd, %WM_CLOSE, 0, 0
                                                            EXIT FUNCTION
                                                         END IF
                                          
                                                      CASE %IDC_START
                                                         wText = "Now is the time for all good men to read"
                                                         wText += " this sentence and head to the enlistment"
                                                         wText += " center to help their country fight for justice!"
                                                         pSp.Speak(BYVAL STRPTR(wText), %SPF_ASYNC, BYVAL %NULL)
                                                         EXIT FUNCTION
                                          
                                                      CASE %IDC_STOP
                                                         wText = ""
                                                         pSp.Speak(BYVAL STRPTR(wText), %SVSFPurgeBeforeSpeak, BYVAL %NULL)
                                                         EXIT FUNCTION
                                          
                                                   END SELECT
                                          
                                                CASE %WM_DESTROY
                                                   pSp = NOTHING
                                                   ' // End the application
                                                   PostQuitMessage 0
                                                   EXIT FUNCTION
                                          
                                                CASE %MSG_SAPI_EVENT
                                                   OutputDebugStringW "MSG_SAPI_EVENT"
                                                   DIM eventItem AS SPEVENT, eventStatus AS SPVOICESTATUS, nStart AS DWORD, nEnd AS DWORD
                                                   DO
                                                      IF pSp.GetEvents(1, eventItem, BYVAL %NULL) <> %S_OK THEN EXIT DO
                                                      IF eventItem.eEventId = %SPEI_WORD_BOUNDARY THEN
                                                         pSp.GetStatus(eventStatus, BYVAL %NULL)
                                                         nStart = eventStatus.ulInputWordPos
                                                         nEnd = eventStatus.ulInputWordLen
                                                         OutputDebugStringW "Start: " & STR$(nStart) & " - Len: " & STR$(nEnd)
                                                      END IF
                                                   LOOP
                                          
                                             END SELECT
                                          
                                             ' // Pass unprocessed messages to Windows
                                             FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)
                                          
                                          END FUNCTION
                                          ' ========================================================================================
                                          Last edited by José Roca; 18 Jul 2017, 03:45 PM.
                                          Forum: http://www.jose.it-berater.org/smfforum/index.php

                                          Comment

                                          Working...
                                          X