by Richard Russell, November 2015

The program below illustrates the use of the speak sub; it is compatible with both LB and LBB. Note that it is necessary to declare speechInit as global:

   ' LB speech synthesis without a helper DLL! 
   ' by Richard Russell, 26-Mar-2012 
 
   open "ole32.dll" for dll as #ole32 
   calldll #ole32, "CoInitialize", 0 as long, r as long 
   global speechInit 
   do 
     read phrase$ 
     print phrase$ 
     call speak phrase$ 
   loop until phrase$ = "" 
   calldll #ole32, "CoUninitialize", r as long 
   close #ole32 
   end 
 
   data "This is a demonstration of speech synthesis" 
   data "using Liberty BASIC code without a helper DLL" 
   data "" 
 
   ' Text-to-speech subroutine, using the SAPI5 speech engine, by Richard Russell 
 
   sub speak text$ 
 
   if speechInit = 0 then 
     struct clsid, a as long, b as long, c as long, d as long 
     clsid.a.struct = hexdec("96749377") : clsid.b.struct = hexdec("11D23391") 
     clsid.c.struct = hexdec("C000E39E") : clsid.d.struct = hexdec("9673794F") 
 
     struct iid, a as long, b as long, c as long, d as long 
     iid.a.struct = hexdec("6C44DF74") : iid.b.struct = hexdec("499272B9") 
     iid.c.struct = hexdec("99EFECA1") : iid.d.struct = hexdec("D422046E") 
 
     struct voice, v as long 
     struct temp, v as long 
     calldll #ole32, "CoCreateInstance", clsid as struct, 0 as long, 5 as long, _ 
                                         iid as struct, voice as struct, r as long 
     if voice.v.struct = 0 then notice "SAPI5 is not available" : end 
     speechInit = 1 
   end if 
 
   length = len(text$)+1 
   wtext$ = space$(length*2) 
   calldll #kernel32, "MultiByteToWideChar", 0 as long, 0 as long, text$ as ptr, _ 
                      -1 as long, wtext$ as ptr, length as ulong, r as long 
 
   pvoice = voice.v.struct 
   temp.struct = pvoice 
   pspeak = temp.v.struct + 80 
   temp.struct = pspeak 
   speak = temp.v.struct 
   temp.struct = pvoice 
 
   calldll #user32, "CallWindowProcA", speak as long, pvoice as long, _ 
                    wtext$ as ptr, 0 as long, 0 as long, r as long 
   end sub
The default voice is used; it may be a male or female voice depending on the version of Windows. If you prefer to specify the gender (assuming both a male and a female voice are installed, which may not always be the case) you can insert 'tags' in the string to achieve that:
   data "<voice optional='gender=female'>This is a demonstration of speech synthesis</voice>"
   data "<voice optional='gender=male'>using Liberty BASIC code without a helper DLL</voice>"
   data ""
It is also possible to control the speed and the volume in a similar way:
   data "<rate absspeed = '4'>This is a demonstration of speech synthesis</rate>"
   data "<volume level = '50'>using Liberty BASIC code without a helper DLL</voice>"
   data ""
The speed should be specified as a value between -10 and +10, and the volume as a value between 0 and 100.

This alternative format for the tags may also be used:
   data "<rate absspeed = '4'/>This is a demonstration of speech synthesis"
   data "<volume level = '50'/>using Liberty BASIC code without a helper DLL"
   data ""

If you want to select a specific SAPI5 voice (and you know it is installed on your PC) you can do that as follows:
   data "<voice required='name=IVONA 2 Brian OEM'>This is a demonstration of speech synthesis</voice>"
In this case the voice selected is Ivona Brian (a British English male voice) which can be purchased from http://www.textaloud.com/