Last active
March 4, 2016 06:23
-
-
Save NigelThorne/8446065 to your computer and use it in GitHub Desktop.
AutoHotKey_L script to TTS the currently selected text.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'sinatra' | |
| require 'win32ole' | |
| Sinatra::Application.reset! | |
| class MySinatraApp < Sinatra::Base | |
| set :port, 7732 #SPEAK | |
| @@is_paused = false | |
| module SpeechVoiceSpeakFlags | |
| #SpVoice Flags | |
| SVSFDefault = 0 | |
| SVSFlagsAsync = 1 | |
| SVSFPurgeBeforeSpeak = 2 | |
| SVSFIsFilename = 4 | |
| SVSFIsXML = 8 | |
| SVSFIsNotXML = 16 | |
| SVSFPersistXML = 32 | |
| #Normalizer Flags | |
| SVSFNLPSpeakPunc = 64 | |
| #Masks | |
| SVSFNLPMask = 64 | |
| SVSFVoiceMask = 127 | |
| SVSFUnusedFlags = -128 | |
| end | |
| @@queue ||= [] | |
| get '/' do | |
| """<html><body> | |
| <script src=\"https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js\"></script> | |
| <script> | |
| function post(link) { | |
| var xhttp = new XMLHttpRequest(); | |
| xhttp.open(\"POST\", link , true); | |
| xhttp.send(); | |
| } | |
| </script> | |
| <form id='sayform' action='./say' method='post'>What should I say?: <input name='text' type='text'></input></form></br> | |
| <button type='button' onclick=\"post('./pause')\">Pause</button> | |
| <button type='button' onclick=\"post('./resume')\">Resume</button> | |
| <button type='button' onclick=\"post('./stop')\">Stop</button> | |
| <button type='button' onclick=\"post('./toggle')\">Pause/Resume</button> | |
| <script> | |
| $('#sayform').submit(function(e){ | |
| e.preventDefault(); | |
| $.ajax({ | |
| url:'./say', | |
| type:'post', | |
| data:$('#sayform').serialize(), | |
| success:function(){ | |
| $('#sayform input').val(\"\"); | |
| } | |
| }); | |
| }); | |
| </script> | |
| </body></html>""" | |
| end | |
| post '/say' do | |
| @@is_paused = false | |
| voice.Speak(params["text"], SpeechVoiceSpeakFlags::SVSFlagsAsync) | |
| return "ok" | |
| end | |
| post '/say_to_file' do | |
| @@is_paused = false | |
| out= voice.AudioOutputStream | |
| temp_file = "c:\\temp\\output.wav" | |
| rm_file(temp_file) | |
| fs = WIN32OLE.new('SAPI.SpFileStream') | |
| fs.Open(temp_file, 3, true) | |
| puts "file open" | |
| format_ex = WIN32OLE.new('SAPI.SpWaveFormatEx') | |
| voice.AudioOutputStream = fs | |
| voice.AudioOutputStream.Format.Type = 39 # SAFT48kHz16BitStereo = 39 | |
| puts "stream set" | |
| voice.Speak(params["text"], SpeechVoiceSpeakFlags::SVSFPurgeBeforeSpeak) | |
| puts "text spoken: #{params["text"]}" | |
| fs.Close() | |
| voice.AudioOutputStream = out | |
| puts "stream reset" | |
| return "ok #{temp_file}" | |
| end | |
| post'/pause' do | |
| voice.Pause | |
| @@is_paused = true | |
| return "ok" | |
| end | |
| post'/stop' do | |
| voice.Speak("", SpeechVoiceSpeakFlags::SVSFPurgeBeforeSpeak) | |
| @@is_paused = false | |
| return "ok" | |
| end | |
| post '/resume' do | |
| voice.Resume | |
| @@is_paused = false | |
| return "ok" | |
| end | |
| post '/toggle' do | |
| if (@@is_paused) | |
| @@is_paused = false | |
| voice.Resume | |
| else | |
| @@is_paused = true | |
| voice.Pause | |
| end | |
| return "ok" | |
| end | |
| get '/status' do | |
| voice.Speak("status") | |
| return "COM Object: #{@@voice.nil?}" | |
| end | |
| def voice | |
| begin | |
| @@voice.IsUISupported(nil) if(@@voice != nil) | |
| rescue | |
| @@voice = nil | |
| end | |
| @@voice ||= WIN32OLE.new('SAPI.SpVoice') | |
| end | |
| def rm_file(file) | |
| File.delete(file) if File.exist?(file) | |
| end | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # config.ru | |
| require 'rubygems' | |
| require 'sinatra' | |
| require 'rack/reloader' | |
| require './app' | |
| set :environment, :development | |
| use Rack::Reloader, 0 if development? | |
| run Sinatra::Application |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| source "http://rubygems.org" | |
| gem "eventmachine", "1.0.8" | |
| gem "thin" | |
| gem "win32-service" | |
| gem "sinatra" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| GEM | |
| remote: http://rubygems.org/ | |
| specs: | |
| daemons (1.2.3) | |
| eventmachine (1.0.8) | |
| ffi (1.9.10-x86-mingw32) | |
| rack (1.6.4) | |
| rack-protection (1.5.3) | |
| rack | |
| sinatra (1.4.6) | |
| rack (~> 1.4) | |
| rack-protection (~> 1.4) | |
| tilt (>= 1.3, < 3) | |
| thin (1.6.4) | |
| daemons (~> 1.0, >= 1.0.9) | |
| eventmachine (~> 1.0, >= 1.0.4) | |
| rack (~> 1.0) | |
| tilt (2.0.1) | |
| win32-service (0.8.7) | |
| ffi | |
| PLATFORMS | |
| x86-mingw32 | |
| DEPENDENCIES | |
| eventmachine (= 1.0.8) | |
| sinatra | |
| thin | |
| win32-service |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require "./say" | |
| pause |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'rubygems' | |
| require 'win32/service' | |
| include Win32 | |
| SERVICE_NAME = 'ruby_tts_service' | |
| # delete the service | |
| # NOTE: if the services applet is up during this operation, the service won't be removed from that ui | |
| # unitil you close and reopen it (it gets marked for deletion) | |
| #Service.delete(SERVICE_NAME) | |
| #path = File.expand_path(File.dirname(__FILE__)).gsub('/','\\') | |
| # Create a new service | |
| Service.create({ | |
| :service_name => SERVICE_NAME, | |
| :host => nil, | |
| :service_type => Service::WIN32_OWN_PROCESS, | |
| :description => 'A tts web service', | |
| :start_type => Service::AUTO_START, | |
| :error_control => Service::ERROR_NORMAL, | |
| :binary_path_name => "\"#{`where ruby`.chomp}\" -C \"#{`echo %cd%`.chomp}\" windows_service.rb", | |
| :load_order_group => 'Network', | |
| :dependencies => nil, | |
| :display_name => SERVICE_NAME | |
| }) | |
| Service.start(SERVICE_NAME) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # encoding: utf-8 | |
| #!/usr/bin/env ruby | |
| begin | |
| SUBSTITUTIONS = { | |
| # TODO: Read urls correctly... http://aumel-constash.vsl.com.au:7990/projects/BOND/repos/bddmanagement as http aumel-constash dot vsl dot com dot au, port 7990, projects, BOND, repos, bdd Management | |
| /UCASE([0-9]+)/ => "yous case \\1", | |
| /\b\.Net\b/ => " dot net ", | |
| "/" => "-n-", | |
| /\bgit\b/i => " gitt ", | |
| /\bLBS\b/ => " Leica Biosystems ", | |
| 'no.' => "no .", | |
| 'XP' => 'ex-pea', | |
| 'APIs' => 'A P eyes', | |
| 'GOTO' => 'Go Too', | |
| ' AND ' => ' , and ', | |
| ' WHEN ' => ' , when ', | |
| ' THEN ' => ' , then ', | |
| /plugin/ => "plug in", | |
| # 'WIP' => '"Work In Progress"', | |
| 'IMO' => '"In My Opinion"', | |
| /[A-Z][A-Z][A-Z][A-Z]+((?=[^A-Za-z])|(?!.))/ => lambda{|x|x.downcase}, #All caps becomes word | |
| "\u0092" => "'", | |
| /n[^a-z0-9\s]t/ => 'n\'t', | |
| /[®«]/ => "", # don't read trademark sign | |
| / A / => "'a'", | |
| /PMs/ => "pee-emms", | |
| /RESTful/ => "restful", | |
| /Actionee/i => "Action-e", | |
| /Leica/i => "Liker", | |
| /Axeda/i => "Exceedar", | |
| /\.exe(?=[^a-z])/i => " executable ", | |
| /\.txt(?=[^a-z])/i => " text file ", | |
| /rebranded/ => "re-branded", | |
| /App(?=[\s\.])/ => " application ", | |
| 'GUI' => " gooee ", | |
| /localhost/ => "local host", | |
| /tear/ => "tair", | |
| /(?<word>[A-Z][a-z]*)(?=[A-Z ,\.;:\t\/])/ => "'\\k<word>' ", # CamelCaseWords should be split by spaces | |
| /((?<!.)|(?<=\n))(?<line>[\?\-]\t[^\n]*)\n/m => "\n\\k<line>.\n", # dot points becomes sentences. | |
| /\.dll/ => " Deelle el", | |
| '\\' => ' slash ', | |
| 'default' => 'deefault', | |
| '×' => 'times', | |
| 'disconnect' => 'dis-connect', | |
| 'btw' => 'by the way', | |
| 'vagaries' => 'vaigeries', | |
| 'verbalised' => 'verbaleyesed', | |
| '(s)' => 's', | |
| 'BOND-III' => 'BOND3', | |
| ' is.' => ' is .', | |
| 'Telerik' => 'Tellerrick', | |
| 'reading and writing' => ' banana and <phoneme alphabet="x-cmu" ph="T AH0 M EY1 T OW0">writing</phoneme>', | |
| } | |
| # gitt | |
| #Hi, I'm Fred. The time is currently <say-as format="dmy" interpret-as="date">01/02/1960</say-as> | |
| require 'cgi' | |
| #def to_speakxml(text) | |
| # text.gsub!(/\r?\n/, " ") | |
| # expression = Regexp.union(SUBSTITUTIONS.keys) | |
| # begin | |
| # <<-eos | |
| # <?xml version="1.0" encoding="UTF-8"?> | |
| # <speak xmlns="http://www.w3.org/2001/10/synthesis" version="1.0" xml:lang="en-UK"> | |
| # <voice xml:lang="en-UK"> | |
| # #{SUBSTITUTIONS.reduce(text){ |o, (r,s)| | |
| # s.is_a?(Proc) ? o.gsub(r, &s) : o.gsub(r, s) | |
| # } | |
| # } | |
| # </voice> | |
| # </speak> | |
| # eos | |
| # rescue => e | |
| # e.to_s | |
| # end | |
| #end | |
| def to_speakxml(text) | |
| text.gsub!(/\r?\n/, " ") | |
| expression = Regexp.union(SUBSTITUTIONS.keys) | |
| begin | |
| <<-eos | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <vxml version = "2.1"> | |
| <form id="F_1"> | |
| <block> | |
| #{SUBSTITUTIONS.reduce(text){ |o, (r,s)| | |
| s.is_a?(Proc) ? o.gsub(r, &s) : o.gsub(r, s) | |
| } | |
| } | |
| </block> | |
| </form> | |
| </vxml> | |
| eos | |
| rescue => e | |
| e.to_s | |
| end | |
| end | |
| if(__FILE__ == $0) | |
| ARGF.set_encoding(Encoding::UTF_8) | |
| puts to_speakxml(ARGF.read) | |
| end | |
| rescue => e | |
| puts e.to_s | |
| end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # encoding: utf-8 | |
| require 'win32ole' | |
| require "./say" | |
| begin | |
| text = File.read('c:\\temp\\tmp_ahk_tts_clip.txt') | |
| # ARGF.set_encoding(Encoding::UTF_8) | |
| # text = ARGF.read(); | |
| data = text.bytes.to_a.pack("U*") | |
| require_relative 'rephrase' | |
| if data == "" | |
| toggle | |
| else | |
| text = to_speakxml(data) | |
| File.write('C:\\temp\\tmp_ahk_clip_out.txt',text) | |
| say text | |
| end | |
| rescue => e | |
| text = e.message | |
| text = "empty message" if text.empty? | |
| WIN32OLE.new('SAPI.SpVoice').Speak(text) | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require "./say" | |
| resume |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require './app.rb' | |
| MySinatraApp.run! :host => 'localhost', :port => 7732, :server => 'thin' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'uri' | |
| require 'net/http' | |
| def say(text) | |
| post("say", 'text' => text) | |
| end | |
| def toggle() | |
| post("toggle", 'text' => '') | |
| end | |
| def pause() | |
| post("pause", 'text' => '') | |
| end | |
| def resume() | |
| post("resume", 'text' => '') | |
| end | |
| def stop() | |
| post("stop", 'text' => '') | |
| end | |
| def post(act, body) | |
| uri = URI.parse("http://localhost:7732/#{act}") | |
| response = Net::HTTP.post_form(uri, body) | |
| end | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require "./say" | |
| stop |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| address: localhost | |
| port: 7732 | |
| servers: 1 | |
| max_conns: 10 | |
| max_persistent_conns: 2 | |
| timeout: 30 | |
| environment: production | |
| pid: tmp/pids/thin-production.pid | |
| log: log/thin-production.log | |
| daemonize: true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ;;;;;;;;;;;;;;;;;;;;TTS;;;;;;;;;;;;;;;;;;;;;; | |
| #^D:: ; Win + Ctrl + D | |
| ClipSaved := ClipboardAll | |
| Clipboard = ; Start off empty to allow ClipWait to detect when the text has arrived. | |
| Send ^c | |
| ClipWait, 0.1 ; Wait for the clipboard to contain text. | |
| FileDelete , c:\temp\tmp_ahk_tts_clip.txt | |
| FileAppend , %Clipboard% , c:\temp\tmp_ahk_tts_clip.txt | |
| Gui, Add, Button, gPause, &Pause | |
| Gui, Add, Button, gResume ys, &Resume | |
| Gui, Add, Button, gStop ys, &Stop | |
| Gui, Show,, TTS | |
| Run, %comspec% /c "".\rephrase_runner.rb" c:\temp\tmp_ahk_tts_clip.txt" ,,;Hide | |
| Clipboard := ClipSaved | |
| ClipSaved = ; Free the memory | |
| Return | |
| Stop: | |
| Run, %comspec% /c "".\stop.rb"" ,,;Hide | |
| Gui, Cancel | |
| Return | |
| Pause: | |
| Run, %comspec% /c "".\pause.rb"" ,,;Hide | |
| Return | |
| Resume: | |
| Run, %comspec% /c "".\resume.rb"" ,,;Hide | |
| Return |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This runs a simple sinatra app as a service | |
| LOG_FILE = 'C:\\sinatra_daemon.log' | |
| require 'rubygems' | |
| require 'sinatra/base' | |
| require './app' | |
| #begin | |
| require 'win32/daemon' | |
| include Win32 | |
| $stdout.reopen("thin-server.log", "w") | |
| $stdout.sync = true | |
| $stderr.reopen($stdout) | |
| class TestDaemon < Daemon | |
| def service_main | |
| log 'started' | |
| MySinatraApp.run! :host => 'localhost', :port => 7732, :server => 'thin' | |
| while running? | |
| log 'running' | |
| sleep 10 | |
| end | |
| end | |
| def service_stop | |
| log 'ended' | |
| exit! | |
| end | |
| def log(text) | |
| File.open('log.txt', 'a') { |f| f.puts "#{Time.now}: #{text}" } | |
| end | |
| end | |
| TestDaemon.mainloop | |
| #rescue Exception => err | |
| #File.open(LOG_FILE,'a+'){ |f| f.puts " ***Daemon failure #{Time.now} err=#{err} " } | |
| #raise | |
| #end |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Added index web page so you can Pause/Say/Stop/Resume from there if you like.