Little SAPI4 and SAPI5 UserLibrary to test

Just starting out? Need help? Post your questions and find answers here.
Esteban1
User
User
Posts: 37
Joined: Sat Jul 16, 2005 4:39 pm
Location: Uruguay

Little SAPI4 and SAPI5 UserLibrary to test

Post by Esteban1 »

I’ve compiled a little UserLibrary for using SAPI4 and/or SAPI5 engines (voices) in my PureBasic programs. It could be useful for someone else. Can anyone give it a try and make some suggestions?
It was tested in Purebasic 3.93 and Windows XP SP2.

You can download it from here:

http://geocities.com/esteban1uy/My_drive.html

Functions:

TTSEnd()
TTSEngCount()
TTSEngMfg()
TTSEngName()
TTSGetPitch()
TTSGetSpeed()
TTSGetVolume()
TTSInit()
TTSPause()
TTSResume()
TTSSAPIVer()
TTSSelect()
TTSSetPitch()
TTSSetSpeed()
TTSSetVolume()
TTSSpeak()
TTSStop()

It also supports some events as AudioStart, AudioStop, and WordPosition.
Some examples included.

PS: Sorry for my English.
ebs
Enthusiast
Enthusiast
Posts: 557
Joined: Fri Apr 25, 2003 11:08 pm

Post by ebs »

Esteban,

I tried your library on Windows XP Home and Professsional. It works great!
I really like the Position callback, so I can tell exactly which word is being pronounced.

Regards,
Eric

P.S. Your English is very good. I did find one mistake in the Help file:
In the "Using Events" section, you refer to "ceros". This should be "zeros" for the numeral 0.
Blade
Enthusiast
Enthusiast
Posts: 362
Joined: Wed Aug 06, 2003 2:49 pm
Location: Venice - Italy, Japan when possible.
Contact:

Post by Blade »

I don't know what's SAPI4, but you lib is very nice!
The quality is much like the one I waas used with the Amiga, but don't know why, the word "hello" is totally incomprensible... (and was the first test I did) :)

Win2000 SP4 here.
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

Esteban,

I just teste your lib which works fine and sounds good.

At the moment I have no suggestions, but will probably come back soon to you.

Right now, just to save some search, can you provide one or some good URLs to download free voices to download ? Or I will probably find otherwise.

Anyway, I have some good reasons to look this stuff further in the purpose to embed utilities and software apps with audible messages.

I appreciate you share this work.

Rgrds
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
Gansta93
Enthusiast
Enthusiast
Posts: 238
Joined: Wed Oct 20, 2004 7:16 pm
Location: The Village
Contact:

Post by Gansta93 »

Hello,

Thank you very much for your lib. :-D
I would like to ask you some informations :
What are the libraries (dll files) used ?
And same thing, do you know where I can find others voices and others languages ?

Thank you again for your lib. :-D

PS : Will you publish the sources? I would be interested.
Be seeing you! :-)

Gansta93
If you speak french, you can visite Le Monde de Gansta93 (Gansta93's World)
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

Esteban,

Right now, I just polished the eventexample.pb sample code. This is just for my own purpose but maybe you will find this interesting to use in the next release of your lib.

As far as I will get new ideas, or receive suggestions, I will improve the code.

It just provides a better GUI management and adds a open / save file feature to feed the editor gadget.

I guess there is no bug inside.

Code: Select all

Enumeration 
  #Menu
  #Menu_Open
  #Menu_Save
  #Menu_Save_As
  #Menu_Quit
  #Menu_Play
  #Menu_Help
  #Menu_Apropos
  #Window_Main
  #Gadget_Editor
  #Gadget_Button_Paste
  #Gadget_Button_Speak
  #Gadget_Button_Stop
  #Gadget_Button_Pause
  #Gadget_Button_Resume
  #Gadget_TrackBar_Speed
  #Gadget_TrackBar_Pitch
  #Gadget_TrackBar_Volume
  #Gadget_ListView_VoicesList
  #Gadget_Text_Speed
  #Gadget_Text_Pitch
  #Gadget_Text_Volume
  #Gadget_Text_VoicesList
  #StatusBar
  #File
EndEnumeration

Procedure Started()
  StatusBarText(#StatusBar, 0, "Speaking", #PB_StatusBar_Center)
EndProcedure

Procedure Ended()
  StatusBarText(#StatusBar, 0, "Not speaking", #PB_StatusBar_Center)
EndProcedure

Procedure Position(Letter.l)
  StatusBarText(#StatusBar, 1, "Position = " + Str(Letter), #PB_StatusBar_Center)
  txtend = SendMessage_(GadgetID(#Gadget_Editor), #EM_FINDWORDBREAK, #WB_RIGHTBREAK, Letter + 1)
  txtstart = SendMessage_(GadgetID(#Gadget_Editor), #EM_FINDWORDBREAK, #WB_MOVEWORDLEFT, Letter + 1)
  range.CHARRANGE
  range\cpMin = txtend
  range\cpMax = txtstart
  SendMessage_(GadgetID(#Gadget_Editor), #EM_EXSETSEL, 0, range)
EndProcedure

;
;
;
  WindowWidth = 480
  WindowHeight = 400
  CurrentDirectory.s = Space(#MAX_PATH)
  GetCurrentDirectory_(#MAX_PATH, @CurrentDirectory)
  CurrentDirectory + "\"
  WindowTitle.s = "PureTTS Reader v0.1"
  FileName.s = ""
  VoiceSpeed = 10 ; (relative scale from 0 to 20, TTS scale from -10 to 10)
  VoicePitch = 10 ; (relative scale from 0 to 20, TTS scale from -10 to 10)
  VoiceVolume = 16 ; (relative scale from 0 to 20, TTS scale from 0 to 100)
  hWnd = OpenWindow(#Window_Main, 0, 0, WindowWidth, WindowHeight, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered, WindowTitle)
  If hWnd
      hBrush = CreateSolidBrush_(#Blue)
      SetClassLong_(hWnd, #GCL_HBRBACKGROUND, hBrush)
      InvalidateRect_(hWnd, #NULL, #TRUE)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Escape, #PB_Shortcut_Escape)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_O | #PB_Shortcut_Control, #Menu_Open)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_S | #PB_Shortcut_Control, #Menu_Save)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Q | #PB_Shortcut_Control, #Menu_Quit)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_F5, #Menu_Play)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_F1, #Menu_Help)
      AddKeyboardShortcut(#Window_Main, #PB_Shortcut_F12, #Menu_Apropos)
      If CreateMenu(#Menu, WindowID(#Window_Main))
          MenuTitle("File")
            MenuItem(#Menu_Open, "&Open")
            MenuItem(#Menu_Save, "&Save")
            MenuItem(#Menu_Save_As, "Save &As")
            MenuItem(#Menu_Quit, "&Quit")
          MenuTitle("Play")
            MenuItem(#Menu_Play, "&Play")
          MenuTitle("Help")
            MenuItem(#Menu_Help, "&Help")
            MenuItem(#Menu_Apropos, "&Apropos")
      EndIf
      If CreateGadgetList(WindowID(#Window_Main))
          EditorGadget(#Gadget_Editor, 5, 5, WindowWidth - 10, 145)
          GadgetToolTip(#Gadget_Editor, "Enter here a multiline text to play")
          AddGadgetItem(#Gadget_Editor, 0, "The quick brown fox jumps over the lazy dog !")
          ButtonGadget(#Gadget_Button_Paste, 10, 160, 50, 25, "Paste")
          ButtonGadget(#Gadget_Button_Speak, 70, 160, 50, 25, "Speak")
          ButtonGadget(#Gadget_Button_Stop, 130, 160, 50, 25, "Stop")
          ButtonGadget(#Gadget_Button_Pause, 190, 160, 50, 25, "Pause")
          ButtonGadget(#Gadget_Button_Resume, 250, 160, 50, 25, "Resume")

          TrackBarGadget(#Gadget_TrackBar_Speed, 55, 200, 360, 20, 0, 20, #PB_TrackBar_Ticks)
          SetGadgetState(#Gadget_TrackBar_Speed, VoiceSpeed)
          GadgetToolTip(#Gadget_TrackBar_Speed, "Display / change the speed level from -10 to 10")

          TrackBarGadget(#Gadget_TrackBar_Pitch, 55, 225, 360, 20, 0, 20, #PB_TrackBar_Ticks)
          SetGadgetState(#Gadget_TrackBar_Pitch, VoicePitch)
          GadgetToolTip(#Gadget_TrackBar_Pitch, "Display / change the pitch level from -10 to 10")

          TrackBarGadget(#Gadget_TrackBar_Volume, 55, 250, 360, 20, 0, 20, #PB_TrackBar_Ticks)
          SetGadgetState(#Gadget_TrackBar_Volume, VoiceVolume)
          GadgetToolTip(#Gadget_TrackBar_Pitch, "Display / change the volume level from 0 to 100")

          ListViewGadget(#Gadget_ListView_VoicesList, 55, 290, WindowWidth - 10 - 50, 60)
          GadgetToolTip(#Gadget_ListView_VoicesList, "Provides the list of available TTS voices")
          TextGadget(#Gadget_Text_Speed, 5, 200, 50, 20, "Speed", #PB_Text_Center)
          TextGadget(#Gadget_Text_Pitch, 5, 225, 50, 20, "Pitch", #PB_Text_Center)
          TextGadget(#Gadget_Text_Volume, 5, 250, 50, 20, "Volume", #PB_Text_Center)
          StringGadget(#Gadget_Text_VoicesList, 5, 290, 50, 60, "Choose" + Chr(13) + Chr(10) + "a voice", #PB_String_Multiline | #PB_String_ReadOnly | #PB_String_BorderLess | #PB_Text_Center)
          GID = GadgetID(#Gadget_Editor)
          dc = GetWindowDC_(GID)
          SendMessage_(GID, #EM_SETTARGETDEVICE, dc, -1)
          ReleaseDC_(GID, dc)
          SendMessage_(GadgetID(#Gadget_Editor), #EM_LIMITTEXT, -1, 0)
      EndIf
      If CreateStatusBar(#StatusBar, WindowID(#Window_Main))
          AddStatusBarField(156)
          AddStatusBarField(156)
      EndIf
      TTSInit(@started(), @ended(), @position())
      voices = TTSEngCount()
      For i = 0 To voices
        AddGadgetItem(#Gadget_ListView_VoicesList, -1, TTSEngName(i))
      Next
      SetGadgetState(#Gadget_ListView_VoicesList, 0)
      TTSSetSpeed(VoiceSpeed - 10)
      TTSSetPitch(VoicePitch - 10)
      TTSSetVolume(VoiceVolume * 5)
      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_CloseWindow
            Quit = #TRUE
          Case #PB_Event_Menu
            Select EventMenuID()
              Case #PB_Shortcut_Escape
                Quit = #TRUE
              Case #Menu_Open 
                FileName = OpenFileRequester("Select a file to open", CurrentDirectory, "Text files|*.txt|All files|*.*", 0)
                If FileName <> ""
                    If ReadFile(#File, FileName)
                        *Buffer = AllocateMemory(Lof())
                        ReadData(*Buffer, Lof())
                        CloseFile(#File)
                        SetGadgetText(#Gadget_Editor, PeekS(*Buffer))
                        FreeMemory(*Buffer)
                    EndIf
                EndIf
              Case #Menu_Save
                If FileName <> ""
                    If MessageRequester("Warning", "Are you sure you want to overwrite " + FileName, #PB_MessageRequester_YesNo) = 6
                        If CreateFile(#File, FileName)
                            WriteString(GetGadgetText(#Gadget_Editor))
                            CloseFile(#File)
                        EndIf
                    EndIf
                EndIf
              Case #Menu_Save_As
                AsFileName.s = SaveFileRequester("Enter a filename to use for saving your speech", CurrentDirectory, "Text files|*.txt|All files|*.*", 0)
                If AsFileName <> ""
                    If CreateFile(#File, AsFileName + ".txt")
                        WriteString(GetGadgetText(#Gadget_Editor))
                        CloseFile(#File)
                    EndIf
                EndIf
              Case #Menu_Quit
                Quit = #TRUE
              Case #Menu_Play
                TTSSpeak(ReplaceString(GetGadgetText(#Gadget_Editor), Chr(13) + Chr(10), " "))
              Case #Menu_Help 
                Help.s = ""
                Help + "Use the simple GUI to play with " + WindowTitle + Chr(13) + Chr(10)
                MessageRequester(WindowTitle + " Help", Help, #PB_MessageRequester_OK)
              Case #Menu_Apropos
                Apropos.s = ""
                Apropos + WindowTitle + Chr(13) + Chr(10)
                Apropos + Chr(13) + Chr(10)
                Apropos + "Designed by Esteban1"
                MessageRequester(WindowTitle + " Apropos", Apropos, #PB_MessageRequester_OK)
            EndSelect
          Case #PB_EventGadget
            Select EventGadgetID()
              Case #Gadget_Button_Paste
                SendMessage_(GadgetID(#Gadget_Editor), #WM_PASTE, 0, 0)
              Case #Gadget_Button_Speak
                TTSSpeak(ReplaceString(GetGadgetText(#Gadget_Editor), Chr(13) + Chr(10), " "))
              Case #Gadget_Button_Stop
                TTSStop()
              Case #Gadget_Button_Pause
                TTSPause()
              Case #Gadget_Button_Resume
                TTSResume()
              Case #Gadget_TrackBar_Speed
                VoiceSpeed = GetGadgetState(#Gadget_TrackBar_Speed)
                TTSSetSpeed(VoiceSpeed - 10)
              Case #Gadget_TrackBar_Pitch
                VoicePitch = GetGadgetState(#Gadget_TrackBar_Pitch)
                TTSSetPitch(VoicePitch - 10)
              Case #Gadget_TrackBar_Volume
                VoiceVolume = GetGadgetState(#Gadget_TrackBar_Volume)
                TTSSetVolume(VoiceVolume * 5)
              Case #Gadget_ListView_VoicesList
                TTSStop()
                TTSSelect(GetGadgetState(#Gadget_ListView_VoicesList))
                TTSSpeak(GetGadgetText(#Gadget_ListView_VoicesList))
                SetGadgetState(#Gadget_TrackBar_Speed, TTSGetSpeed() + 10)
                SetGadgetState(#Gadget_TrackBar_Pitch, TTSGetPitch() + 10)
                SetGadgetState(#Gadget_TrackBar_Volume, TTSGetVolume())
            EndSelect
        EndSelect
      Until Quit
      TTSEnd()
      DeleteObject_(hBrush)
  EndIf
End
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

I finally found a set of Lernout & Hauspie files that self install in \Windows\Lhsp directory.

My question is just now, how to make dll files connect to MS TTS stuff so that new voices will be recognized by using your lib ?

When I launch eventexample, the voice list still only contains Microsoft Sam original voice, but no new instance of L&H.

Rgrds
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
Gansta93
Enthusiast
Enthusiast
Posts: 238
Joined: Wed Oct 20, 2004 7:16 pm
Location: The Village
Contact:

Post by Gansta93 »

Have you found french voices?
I am looking for that, but don't find.
Be seeing you! :-)

Gansta93
If you speak french, you can visite Le Monde de Gansta93 (Gansta93's World)
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

BTW as soon as we will have got a set of voices, the next feature I would like to add would be a wav / mp3 save capability of the program ?!

But right now, I will need some help I guess.
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
Gansta93
Enthusiast
Enthusiast
Posts: 238
Joined: Wed Oct 20, 2004 7:16 pm
Location: The Village
Contact:

Post by Gansta93 »

The link seems to be bad. :oops:
Be seeing you! :-)

Gansta93
If you speak french, you can visite Le Monde de Gansta93 (Gansta93's World)
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

the link works fine from here!

If you can't dl files, just let me know so that I will connect you on a temporary place to get them.
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
Gansta93
Enthusiast
Enthusiast
Posts: 238
Joined: Wed Oct 20, 2004 7:16 pm
Location: The Village
Contact:

Post by Gansta93 »

I've just tryed again, but it still doesn't work. Error number 404 not found. I don't understand.
Be seeing you! :-)

Gansta93
If you speak french, you can visite Le Monde de Gansta93 (Gansta93's World)
fweil
Enthusiast
Enthusiast
Posts: 725
Joined: Thu Apr 22, 2004 5:56 pm
Location: France
Contact:

Post by fweil »

@Gangsta93 : any email to contact U ?
My avatar is a small copy of the 4x1.8m image I created and exposed at 'Le salon international du meuble à Paris' january 2004 in Matt Sindall's 'Shades' designers exhibition. The original laminated print was designed using a 150 dpi printout.
User avatar
GeoTrail
Addict
Addict
Posts: 2794
Joined: Fri Feb 13, 2004 12:45 am
Location: Bergen, Norway
Contact:

Post by GeoTrail »

Does this work independantly of the Microsoft Speech engine?
I Stepped On A Cornflake!!! Now I'm A Cereal Killer!
Post Reply