=====Asynchronous speech===== //by Richard Russell, October 2016//\\ \\ The supplied example program **SPEAK.BBC** outputs the speech synchronously, that is **PROCspeak()** does not return to the caller until the speech output is complete. That will often be what is wanted, but in some circumstances you may wish to get on with doing something else while a phrase is being spoken. The programs below illustrate how that may be achieved; the first uses the **ActiveX** (COM automation) approach used in SPEAK.BBC and the second uses direct calls to the **SAPI5 COM objects**. ===== ActiveX method ===== The **PROCspeakasync()** routine returns immediately and the **FNisspeaking()** function allows the current status to be polled so you can discover when the speech is finished. The parameter ''3'' passed to the **Speak** method is a combination of SVSFlagsAsync (1) and SVSFPurgeBeforeSpeak (2). If you want to 'queue' multiple phrases change the parameter to ''1'' and move the 'waiting' loop to just before the **PROC_releaseobject()**: REM. Text-to-speech demonstration program using COMLIB REM. R.T.Russell, 24-Apr-2007 INSTALL @lib$+"COMLIBA" ON ERROR PROC_comexit : PRINT 'REPORT$ : END ON CLOSE PROC_comexit : QUIT PROC_cominit Pitch% = 0 Speed% = 0 Voice$ = "" tts% = FN_createobject("Sapi.SpVoice") REPEAT READ phrase$ PRINT phrase$ PROCspeakasync(tts%,phrase$,Pitch%,Speed%,Voice$) REPEAT WAIT 100 PRINT "Waiting..." UNTIL NOT FNisspeaking(tts%) UNTIL phrase$ = "" PROC_releaseobject(tts%) PROC_comexit END DATA "BBC BASIC for Windows is an advanced implementation of BBC BASIC for Microsoft Windows," DATA "providing the programmer with a familiar language but with a modern interface." DATA "It combines the simplicity of BASIC with the sophistication of a structured language," DATA "allowing you to write utilities and games, use sound and graphics, perform calculations" DATA "and create complete Windows applications." DATA "In short, using BBC BASIC you will be able to make your PC do what you want it to." DATA DEF PROCspeakasync(tts%,phrase$,pitch%,speed%,voice$) LOCAL qual$ qual$ = "" IF voice$<>"" qual$ += "" PROC_callmethod(tts%, "Speak("""+qual$+phrase$+""",3)") ENDPROC DEF FNisspeaking(tts%) = FN_getvaluestr(tts%,"Status.RunningState") <> "1" ===== COM object method ===== The **PROC_voice_speak()** routine returns immediately and the **FN_voice_status()** function allows the current status to be polled so you can discover when the speech is finished: REM. Text-to-speech demonstration program: asynchronous REM. Richard Russell, 18-Apr-2012 SPF_ASYNC = 1 SPRS_DONE = 1 ON ERROR SYS `CoUninitialize` : PRINT 'REPORT$ : END ON CLOSE SYS `CoUninitialize` : QUIT SYS "LoadLibrary","OLE32.DLL" TO O% SYS "GetProcAddress",O%,"CoInitialize" TO `CoInitialize` SYS "GetProcAddress",O%,"CoUninitialize" TO `CoUninitialize` SYS "GetProcAddress",O%,"CoCreateInstance" TO `CoCreateInstance` SYS `CoInitialize`,0 voice% = FN_voice_create REPEAT READ phrase$ PRINT phrase$ PROC_voice_speak(voice%, phrase$) REPEAT WAIT 100 PRINT "Waiting..." UNTIL FN_voice_status(voice%) = SPRS_DONE UNTIL phrase$ = "" PROC_voice_free(voice%) SYS `CoUninitialize` END DATA "BBC BASIC for Windows is an advanced implementation of BBC BASIC for Microsoft Windows," DATA "providing the programmer with a familiar language but with a modern interface." DATA "It combines the simplicity of BASIC with the sophistication of a structured language," DATA "allowing you to write utilities and games, use sound and graphics, perform calculations" DATA "and create complete Windows applications." DATA "In short, using BBC BASIC you will be able to make your PC do what you want it to." DATA DEF FN_voice_create LOCAL C%, I%, V% DIM C% LOCAL 15, I% LOCAL 15 C%!0 = &96749377 : C%!4 = &11D23391 : C%!8 = &C000E39E : C%!12 = &9673794F I%!0 = &6C44DF74 : I%!4 = &499272B9 : I%!8 = &99EFECA1 : I%!12 = &D422046E SYS `CoCreateInstance`, C%, 0, 5, I%, ^V% IF V%=0 ERROR 100, "SAPI5 not available" = V% DEF PROC_voice_speak(V%, M$) LOCAL M% DIM M% LOCAL 2*LENM$+1 SYS "MultiByteToWideChar", 0, 0, M$, -1, M%, LENM$+1 SYS !(!V%+80), V%, M%, SPF_ASYNC, 0 ENDPROC DEF FN_voice_status(V%) LOCAL spvs{} DIM spvs{ulCurrentStream%, ulLastStreamQueued%, hrLastResult%, dwRunningState%, \ \ ulInputWordPos%, ulInputWordLen%, ulInputSentPos%, ulInputSentLen%, \ \ lBookmarkId%, PhonemeId%, VisemeId%, dwReserved1%, dwReserved2%} SYS !(!V%+88), V%, spvs{}, 0 = spvs.dwRunningState% DEF PROC_voice_free(V%) SYS !(!V%+8), V% ENDPROC