Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[function] Easy Text to speech


  • Please log in to reply
43 replies to this topic
daveclark
  • Members
  • 7 posts
  • Last active: Aug 01 2015 12:26 PM
  • Joined: 26 Dec 2011
Thank you for your reply.

I'm aware that memory usage will increase (in my case, using a more sofisticated SAPI voice, it will go up to 28000 K).

The thing is that, even after 10 min saying nothing, the memory consumption will continue to be this very same 28000 K.

Isn't there a way to clear the memory and then create the voice all again?

I think you have already got it by now, but I'm not closing the application after the speaking is finished.

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
You could recreate SAPI voice on each hotkey press, which is inefficient but will lower memory consumption in a periods when voice is saying nothing.
F1::
oVoice := ComObjCreate("SAPI.SpVoice")	; or use TTS_CreateVoice()
oVoice.Speak("Automate almost anything by sending keystrokes and mouse clicks.",0x0)	; or use TTS()
oVoice := ""
return
or you could use timer which will delete object if Speak method wasn't called for a specified amount of time.

daveclark
  • Members
  • 7 posts
  • Last active: Aug 01 2015 12:26 PM
  • Joined: 26 Dec 2011
I had already done that and didn't have any success at all.

Now I've realized the problem is with the voice I'm using, NeoSpeech Bridget TTS voice. All the other SAPI voices function as they should: when I set
oVoice := ""
the memory consumption lowers.

Thank you!

  • Guests
  • Last active:
  • Joined: --
I got a message box when run running.
it reports error: 0x8004503A -

Source: (null)
Description: (null)
HelpFile: (null)
HelpContext: 0

Specifically: GetAttribute

Line#
213: }
214: Else
214: if command = GetVoices
215: {
216: param1 := (param1 = "") ? "
" : param1
217: Loop,oVoice.GetVoices.Count
218: {
---> 219: Name := oVoice.GetVoices.Item(A_Index-1).GetAttribute("Name")
220: VoiceList .= Name param1
221: }
222: Return,RTrim(VoiceList,param1)
223: }
224: Else
224: if command = GetStatus
225: {

Continue running the script?

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
Run this code
MsgBox % ComObjCreate("SAPI.SpVoice").GetVoices.Count
and post result here.

ikaros
  • Members
  • 9 posts
  • Last active: Apr 04 2012 12:45 PM
  • Joined: 29 Feb 2012
Lol great!!

NoreW
  • Members
  • 1 posts
  • Last active: Mar 23 2012 11:28 PM
  • Joined: 21 Mar 2012
Hi, thanks for sharing this.
Is there any way to read this?
<pron sym="h eh 1 l ow & w er 1 l d"> hello world </pron>
Pronunciation tag not allowed? I've got 0x80045003 error :(

Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009
Hmm, when I run this:
String = <pron sym="h eh 1 l ow & w er 1 l d"> hello world </pron>
oVoice := ComObjCreate("SAPI.SpVoice")
oVoice.Speak(String,0x8)   ; SVSFIsXML = 0x8
return
I get the same error as you :( - 0x80045003 error - SPERR_UNSUPPORTED_FORMAT - The caller has specified an unsupported format. :?:

Other examples from XML TTS Tutorial work... example;
String = <spell>These words should be spelled out.</spell>
oVoice := ComObjCreate("SAPI.SpVoice")
oVoice.Speak(String,0x8)   ; SVSFIsXML = 0x8
return


jk4837
  • Members
  • 2 posts
  • Last active: Aug 21 2013 09:31 PM
  • Joined: 18 Aug 2013

Thanks for sharing!

 

How can I change output voice format to "48kHz16bitStereo" ?

 



Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009

Take a look at example below - it will say What a nice day! first using 8kHz8BitMono and than 48kHz16BitStereo format. wink.png

;===Auto-execute========================================================================
oVoice := ComObjCreate("SAPI.SpVoice")

SetOutputVoiceFormat(oVoice, 4)			; SAFT8kHz8BitMono :=4
oVoice.Speak("What a nice day!",0x0)

SetOutputVoiceFormat(oVoice, 39)		; SAFT48kHz16BitStereo := 39
oVoice.Speak("What a nice day!",0x0)
ExitApp


;===Functions===========================================================================
SetOutputVoiceFormat(oVoice, AudioOutputStreamFormatType) {
	oVoice.AllowAudioOutputFormatChangesOnNextSet:=0
	oVoice.AudioOutputStream.Format.Type:=AudioOutputStreamFormatType
	oVoice.AudioOutputStream:=oVoice.AudioOutputStream
	oVoice.AllowAudioOutputFormatChangesOnNextSet:=1
}

My Website • Recommended: AutoHotkey Unicode 32-bit • Join DropBox, Copy


jk4837
  • Members
  • 2 posts
  • Last active: Aug 21 2013 09:31 PM
  • Joined: 18 Aug 2013

Thank you very much!  It works!!!   grin.png

 

 

Take a look at example below - it will say What a nice day! first using 8kHz8BitMono and than 48kHz16BitStereo format. wink.png

;===Auto-execute========================================================================
oVoice := ComObjCreate("SAPI.SpVoice")

SetOutputVoiceFormat(oVoice, 4)			; SAFT8kHz8BitMono :=4
oVoice.Speak("What a nice day!",0x0)

SetOutputVoiceFormat(oVoice, 39)		; SAFT48kHz16BitStereo := 39
oVoice.Speak("What a nice day!",0x0)
ExitApp


;===Functions===========================================================================
SetOutputVoiceFormat(oVoice, AudioOutputStreamFormatType) {
	oVoice.AllowAudioOutputFormatChangesOnNextSet:=0
	oVoice.AudioOutputStream.Format.Type:=AudioOutputStreamFormatType
	oVoice.AudioOutputStream:=oVoice.AudioOutputStream
	oVoice.AllowAudioOutputFormatChangesOnNextSet:=1
}


daorc
  • Members
  • 177 posts
  • Last active:
  • Joined: 18 Oct 2006

Hi,

 

Is anyone else having trouble with this on Windows 10?  My machine has been using this script for ages with no problems.  But wince the update to Win10 it often only reads the first few sounds or first few words of selected text before stopping.  Is anyone else getting this, or have any idea what the issue may be?

 

I'm using the exact copy-and-pasted code from here:

https://autohotkey.c...ch/#entry372022

And "Example 1" that's directly below it.

 

So my code is:

 

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

Voice := ComObjCreate("SAPI.SpVoice")
return

F1::TTS(Voice, "ToggleSpeak", gst())    ; select some text and press F1


gst() { ; GetSelectedText by Learning one
    IsClipEmpty := (Clipboard = "") ? 1 : 0
    if !IsClipEmpty {
        ClipboardBackup := ClipboardAll
        While !(Clipboard = "") {
            Clipboard =
            Sleep, 10
        }
    }
    Send, ^c
    ClipWait, 0.1
    ToReturn := Clipboard, Clipboard := ClipboardBackup
    if !IsClipEmpty
    ClipWait, 0.5, 1
    Return ToReturn
}

TTS(oVoice, command, param1="", param2="") {        ; by Learning one. For AHK_L. Thanks: jballi, Sean, Frankie.
    ; AHK forum location:    www.autohotkey.com/forum/topic57773.html
    ; Read more:            msdn.microsoft.com/en-us/library/ms723602(v=VS.85).aspx, www.autohotkey.com/forum/topic45471.html, www.autohotkey.com/forum/topic83162.html
    static CommandList := "ToggleSpeak,Speak,SpeakWait,Pause,Stop,SetRate,SetVolume,SetPitch,SetVoice,GetVoices,GetStatus,GetCount,SpeakToFile"
    if command not in %CommandList%
    {
        MsgBox, 16, TTS() error, "%command%" is not valid command.
        return
    }
    if command = ToggleSpeak    ; speak or stop speaking
    {
        Status := oVoice.Status.RunningState
        if Status = 1    ; finished
        oVoice.Speak(param1,0x1)    ; speak asynchronously
        Else if Status = 0    ; paused
        {
            oVoice.Resume
            oVoice.Speak("",0x1|0x2)    ; stop
            oVoice.Speak(param1,0x1)    ; speak asynchronously
        }
        Else if Status = 2    ; reading
        oVoice.Speak("",0x1|0x2)    ; stop
    }
    Else if command = Speak        ; speak asynchronously
    {
        Status := oVoice.Status.RunningState
        if Status = 0    ; paused
        oVoice.Resume
        oVoice.Speak("",0x1|0x2)    ; stop
        oVoice.Speak(param1,0x1)    ; speak asynchronously
    }
    Else if command = SpeakWait        ; speak synchronously
    {
        Status := oVoice.Status.RunningState
        if Status = 0    ; paused
        oVoice.Resume
        oVoice.Speak("",0x1|0x2)    ; stop
        oVoice.Speak(param1,0x0)    ; speak synchronously
    }
    Else if command = Pause    ; Pause toggle
    {
        Status := oVoice.Status.RunningState
        if Status = 0    ; paused
        oVoice.Resume
        else if Status = 2    ; reading
        oVoice.Pause
    }
    Else if command = Stop
    {
        Status := oVoice.Status.RunningState
        if Status = 0    ; paused
        oVoice.Resume
        oVoice.Speak("",0x1|0x2)    ; stop
    }
    Else if command = SetRate
        oVoice.Rate := param1        ; rate (reading speed): param1 from -10 to 10. 0 is default.
    Else if command = SetVolume
        oVoice.Volume := param1        ; volume (reading loudness): param1 from 0 to 100. 100 is default
    Else if command = SetPitch                ; http://msdn.microsoft.com/en-us/library/ms717077(v=vs.85).aspx
        oVoice.Speak("<pitch absmiddle = '" param1 "'/>",0x20)    ; pitch : param1 from -10 to 10. 0 is default.
    Else if command = SetVoice
    {
        Loop, % oVoice.GetVoices.Count
        {
            Name := oVoice.GetVoices.Item(A_Index-1).GetAttribute("Name")    ; 0 based
            If (Name = param1)
            {
                DoesVoiceExist := 1
                break
            }
        }
        if !DoesVoiceExist
        {
            MsgBox,64,, Voice "%param1%" does not exist.
            return
        }
        While !(oVoice.Status.RunningState = 1)
        Sleep, 20
        oVoice.Voice := oVoice.GetVoices("Name=" param1).Item(0) ; set voice to param1
    }
    Else if command = GetVoices
    {
        param1 := (param1 = "") ? "`n" : param1        ; param1 as delimiter
        Loop, % oVoice.GetVoices.Count
        {
            Name := oVoice.GetVoices.Item(A_Index-1).GetAttribute("Name")    ; 0 based
            VoiceList .= Name param1
        }
        Return RTrim(VoiceList,param1)
    }
    Else if command = GetStatus
    {
        Status := oVoice.Status.RunningState
        if Status = 0 ; paused
        Return "paused"
        Else if Status = 1 ; finished
        Return "finished"
        Else if Status = 2 ; reading
        Return "reading"
    }
    Else if command = GetCount
        return oVoice.GetVoices.Count
    Else if command = SpeakToFile    ; param1 = TextToSpeak, param2 = OutputFilePath
    {
        oldAOS := oVoice.AudioOutputStream
        oldAAOFCONS := oVoice.AllowAudioOutputFormatChangesOnNextSet
        oVoice.AllowAudioOutputFormatChangesOnNextSet := 1    
        
        SpStream := ComObjCreate("SAPI.SpFileStream")
        FileDelete, % param2    ; OutputFilePath
        SpStream.Open(param2, 3)
        oVoice.AudioOutputStream := SpStream
        TTS(oVoice, "SpeakWait", param1)
        SpStream.Close()
        oVoice.AudioOutputStream := oldAOS
        oVoice.AllowAudioOutputFormatChangesOnNextSet := oldAAOFCONS
    }
}    
TTS_CreateVoice(VoiceName="", VoiceRate="", VoiceVolume="", VoicePitch="") {        ; by Learning one. For AHK_L.
    oVoice := ComObjCreate("SAPI.SpVoice")
    if !(VoiceName = "")
        TTS(oVoice, "SetVoice", VoiceName)
    if VoiceRate between -10 and 10
        oVoice.Rate := VoiceRate        ; rate (reading speed): from -10 to 10. 0 is default.
    if VoiceVolume between 0 and 100
        oVoice.Volume := VoiceVolume    ; volume (reading loudness): from 0 to 100. 100 is default
    if VoicePitch between -10 and 10
        TTS(oVoice, "SetPitch", VoicePitch)    ; pitch: from -10 to 10. 0 is default.
    return oVoice
}


Learning one
  • Members
  • 1483 posts
  • Last active: Jan 02 2016 02:30 PM
  • Joined: 04 Apr 2009

I recently upgraded to Windows 10 and it works without problems...


My Website • Recommended: AutoHotkey Unicode 32-bit • Join DropBox, Copy


daorc
  • Members
  • 177 posts
  • Last active:
  • Joined: 18 Oct 2006

Thanks for checking, Learning one!  It only seems to fail once every couple of weeks.  I've changed from using "ToggleSpeak" to "Speak" and not failed again yet.  I wonder though if it's some compatibility issue with another text-to-speech program (I have various different ones running at different times).  I will let you know if the change I just mentioned fixes it ...