Page 1 of 1

Speech

Posted: Thu Jun 15, 2017 8:54 pm
by IdeasVacuum
Looking for a text-to-speech library that will work with SB on Andriod. Presumably Google text-to-speech is going to be the answer, anyone dabbled?

Re: Speech

Posted: Sun Jun 18, 2017 7:14 am
by jamirokwai
Have a look at this: https://developer.mozilla.org/en-US/doc ... _synthesis

It says, support in Android is available. I tried on an iPhone - MobileSafari doesn't work for now.

Cheers
J.

Re: Speech

Posted: Sun Jun 18, 2017 1:14 pm
by IdeasVacuum
That's interesting jamirokwai, though the tutorial is aimed at browsers.
Searching for 'speech synthesis' delivers the other end of the scale - tutorials aimed at Android devices:
https://android-developers.googleblog.c ... ch-in.html

So, not sure - for the app I have in mind, which is SmartPhone only, I think it might be better to use a language designed for developing Android Apps.

Re: Speech

Posted: Mon Jun 19, 2017 1:16 pm
by jamirokwai
IdeasVacuum wrote:That's interesting jamirokwai, though the tutorial is aimed at browsers.
Searching for 'speech synthesis' delivers the other end of the scale - tutorials aimed at Android devices:
https://android-developers.googleblog.c ... ch-in.html

So, not sure - for the app I have in mind, which is SmartPhone only, I think it might be better to use a language designed for developing Android Apps.
The page says - although I am not sure, what browser Android phones have -
Chrome for Desktop and Android have supported it since around version 33, without prefixes.
^^

Re: Speech

Posted: Mon Jun 19, 2017 3:48 pm
by Peter
Quick 'n Dirty implementation of speechSynthesis:

SpeechSynthesis-Module:

Code: Select all

EnableExplicit

DeclareModule SpeechSynthesis
  
  EnableExplicit
  
  Global IsInitialized
  
  Declare Init(Callback)
  
  Declare Speak(Text.s, Voice = 0, Rate = 1, Pitch = 1)
  
  Structure sVoices
    Name.s
    Language.s
  EndStructure
  
  Global NewList Voices.sVoices()
  
EndDeclareModule

Module SpeechSynthesis
  
  ! var voices = [];
  
  EnableExplicit
  
  Procedure Init(Callback)
    
    ! function populateVoiceList() {
    
    !   if (typeof speechSynthesis === "undefined") return;
    
    !   voices = speechSynthesis.getVoices();
    
    Protected Name.s
    Protected Language.s
    
    ClearList(Voices())
    
    !   $.each(voices,function(a,b) {
    !     v_name     = b.name;
    !     v_language = b.language;
    
    AddElement(Voices())
    Voices()\Name = Name
    Voices()\Language = Language
    
    !   });
    
    !    v_callback();
    
    ! }
    
    ! populateVoiceList();
    
    ! if ( typeof speechSynthesis !== "undefined" && speechSynthesis.onvoiceschanged !== undefined ) speechSynthesis.onvoiceschanged = populateVoiceList;
    
  EndProcedure  
  
  Procedure Speak(Text.s, Voice = 0, Rate = 1, Pitch = 1)
    
    !  var utterThis = new SpeechSynthesisUtterance(v_text);
    
    !  utterThis.voice = voices[v_voice];
    !  utterThis.pitch = v_pitch;
    !  utterThis.rate  = v_rate;
    
    !  window.speechSynthesis.speak(utterThis);
    
  EndProcedure
  
EndModule
Demo:

Code: Select all

XIncludeFile "SpeechSynthesis.sbi"

#Dialog = 0
#Xml = 0

Runtime Enumeration
  #txtToSpeak
  #cboVoices
  #cmdSpeak
  #trkRate
  #trkPitch
EndEnumeration

Procedure Speak()
  
  Protected TextToSpeak.s = GetGadgetText (#txtToSpeak)
  Protected Voice         = GetGadgetState(#cboVoices)
  Protected Pitch         = GetGadgetState(#trkPitch)
  Protected Rate          = GetGadgetState(#trkRate)
  
  SpeechSynthesis::Speak(TextToSpeak, Voice, Rate, Pitch)
  
EndProcedure


Procedure Main()
  
  Protected XML.s
  
  XML = "<window id='#PB_Any' name='test' text='SpeechSynthesis' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu'>" +
        "  <vbox>" +
        "    <text text='Enter some text in the input below and press the speak-button to hear it. change voices using the dropdown menu.' />" +
        "    <empty />" +
        "    <editor id='#txtToSpeak' text='SpiderBasic is new web client-side programming language based on established BASIC rules.' height='60' flags='#PB_Editor_WordWrap' />" +
        "    <empty />" +
        "    <hbox expand='item:2'>" + 
        "      <text text='Rate:' flags='#PB_Text_VerticalCenter' />" + 
        "      <trackbar id='#trkRate' min='0' max='2' value='1' />" +
        "    </hbox>" + 
        "    <hbox expand='item:2'>" + 
        "      <text text='Pitch:' flags='#PB_Text_VerticalCenter' />" + 
        "      <trackbar id='#trkPitch' min='0' max='2' value='1' />" +
        "    </hbox>" + 
        "    <empty />" +
        "    <hbox expand='item:2'>" + 
        "      <text text='Voice:' flags='#PB_Text_VerticalCenter' />" + 
        "      <combobox id='#cboVoices' height='25' />" +
        "    </hbox>" + 
        "    <empty />" +
        "    <button id='#cmdSpeak' text='Speak!' height='60' />" +
        "  </vbox>" +
        "</window>"
  
  If ParseXML(#Xml, XML) And XMLStatus(#Xml) = #PB_XML_Success
    
    If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
      
      SetWindowTitle(DialogWindow(#Dialog), "SpeechSynthesis: " + Str(ListSize(SpeechSynthesis::Voices())) + " Voices loaded")
      
      ForEach SpeechSynthesis::Voices()
        AddGadgetItem(#cboVoices, -1, SpeechSynthesis::Voices()\Name)
      Next
      
      SetGadgetState(#cboVoices, 0)
      
      BindGadgetEvent(#cmdSpeak, @Speak())
      
      DisableGadget(#trkPitch, #True)
      DisableGadget(#trkRate, #True)
      
    Else  
      Debug "Dialog error: " + DialogError(#Dialog)
    EndIf
  Else
    Debug "XML error: " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
  EndIf
  
EndProcedure

SpeechSynthesis::Init(@Main())
Greetings ... Peter

// Edit 11.04.2024: The code has been changed so that it now also works with Firefox. However, considerably more voices are loaded in the Chrome browser (321 voices) than in Firefox (5 voices).

Re: Speech

Posted: Thu Jun 22, 2017 11:51 pm
by IdeasVacuum
Interesting code Peter but I can't get it to work :cry:

The Demo Window is not displayed? Tried it on Win7 x86 + FireFox and also as an APK. The Debug Window is displayed but it is empty.

Re: Speech

Posted: Fri Jun 23, 2017 6:56 am
by Peter
@IdeasVacuum: can you take a look into the Browser-Console (<F12>)? Perhaps there is an Error-Message?

Greetings ... Peter

Re: Speech

Posted: Fri Jun 23, 2017 10:09 am
by IdeasVacuum
Hi Peter

Nothing at all in the Console - no errors, warnings, info or debug info. Win7x86 + FireFox 54.0

Re: Speech

Posted: Sun Nov 12, 2023 2:43 am
by Quin
Peter wrote: Mon Jun 19, 2017 3:48 pm Quick 'n Dirty implementation of speechSynthesis:

SpeechSynthesis-Module:

Code: Select all

EnableExplicit

DeclareModule SpeechSynthesis
  
  EnableExplicit
  
  Global IsInitialized
  
  Declare Init(Callback)
  
  Declare Speak(Text.s, Voice = 0, Rate = 1, Pitch = 1)
  
  Structure sVoices
    Name.s
    Language.s
  EndStructure
  
  Global NewList Voices.sVoices()
  
EndDeclareModule

Module SpeechSynthesis
  
  ! var voices = [];
  
  EnableExplicit
  
  Procedure Init(Callback)
    
    ! window.speechSynthesis.onvoiceschanged = function() {
    
    If IsInitialized 
      ProcedureReturn
    EndIf
    
    !    voices = window.speechSynthesis.getVoices();
    
    Protected Name.s
    Protected Language.s
    
    ClearList(Voices())
    
    ! $.each(voices,function(a,b) {
    
    !    v_name     = b.name;
    !    v_language = b.language;
    
    AddElement(Voices())
    Voices()\Name = Name
    Voices()\Language = Language
    
    !  });
    
    IsInitialized = #True
    
    !    v_callback();
    ! };
    
  EndProcedure  
  
  Procedure Speak(Text.s, Voice = 0, Rate = 1, Pitch = 1)
    
    !  var utterThis = new SpeechSynthesisUtterance(v_text);
    
    !  utterThis.voice = voices[v_voice];
    !  utterThis.pitch = v_pitch;
    !  utterThis.rate  = v_rate;
    
    !  window.speechSynthesis.speak(utterThis);
    
  EndProcedure
  
EndModule
Demo:

Code: Select all

XIncludeFile "SpeechSynthesis.sbi"

#Dialog = 0
#Xml = 0

Runtime Enumeration
  #txtToSpeak
  #cboVoices
  #cmdSpeak
  #trkRate
  #trkPitch
EndEnumeration

Procedure Speak()
  
  Protected TextToSpeak.s = GetGadgetText (#txtToSpeak)
  Protected Voice         = GetGadgetState(#cboVoices)
  Protected Pitch         = GetGadgetState(#trkPitch)
  Protected Rate          = GetGadgetState(#trkRate)
  
  SpeechSynthesis::Speak(TextToSpeak, Voice, Rate, Pitch)
  
EndProcedure


Procedure Main()
  
  Protected XML.s
  
  XML = "<window id='#PB_Any' name='test' text='Dialog example' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu'>" +
        "  <vbox>" +
        "    <text text='Enter some text in the input below and press the speak-button to hear it. change voices using the dropdown menu.' />" +
        "    <empty />" +
        "    <editor id='#txtToSpeak' text='SpiderBasic is new web client-side programming language based on established BASIC rules.' height='60' flags='#PB_Editor_WordWrap' />" +
        "    <empty />" +
        "    <hbox expand='item:2'>" + 
        "      <text text='Rate:' flags='#PB_Text_VerticalCenter' />" + 
        "      <trackbar id='#trkRate' min='0' max='2' value='1' />" +
        "    </hbox>" + 
        "    <hbox expand='item:2'>" + 
        "      <text text='Pitch:' flags='#PB_Text_VerticalCenter' />" + 
        "      <trackbar id='#trkPitch' min='0' max='2' value='1' />" +
        "    </hbox>" + 
        "    <empty />" +
        "    <hbox expand='item:2'>" + 
        "      <text text='Voice:' flags='#PB_Text_VerticalCenter' />" + 
        "      <combobox id='#cboVoices' height='25' />" +
        "    </hbox>" + 
        "    <empty />" +
        "    <button id='#cmdSpeak' text='Speak!' height='60' />" +
        "  </vbox>" +
        "</window>"
  
  If ParseXML(#Xml, XML) And XMLStatus(#Xml) = #PB_XML_Success
    
    If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
      
      ForEach SpeechSynthesis::Voices()
        AddGadgetItem(#cboVoices, -1, SpeechSynthesis::Voices()\Name)
      Next
      
      SetGadgetState(#cboVoices, 0)
      
      BindGadgetEvent(#cmdSpeak, @Speak())
      
      DisableGadget(#trkPitch, #True)
      DisableGadget(#trkRate, #True)
      
    Else  
      Debug "Dialog error: " + DialogError(#Dialog)
    EndIf
  Else
    Debug "XML error: " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
  EndIf
  
EndProcedure

SpeechSynthesis::Init(@Main())
Greetings ... Peter
Just tested, and this still appears to work for me! Excellent work!