#!/usr/bin/tclsh # Keywords: Emacspeak, ViaVoice Outloud , TCL # {{{ LCD Entry: # LCD Archive Entry: # emacspeak| T. V. Raman |raman@cs.cornell.edu # A speech interface to Emacs | # $Date$ | # $Revision$ | # Location undetermined # # }}} # {{{ Copyright: #Copyright (C) 1995 -- 2001, T. V. Raman #All Rights Reserved # # This file is not part of GNU Emacs, but the same permissions apply. # # GNU Emacs is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # GNU Emacs is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Emacs; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. # }}} # {{{source common code #package require Tclx set wd [file dirname $argv0] source $wd/tts-lib.tcl # }}} # {{{ procedures proc version {} { q "This is [ttsVersion]" d } proc tts_set_punctuations {mode} { global tts set tts(punctuations) $mode return "" } proc tts_set_speech_rate {rate} { global tts set factor $tts(char_factor) set tts(speech_rate) $rate synth "`vs$rate " return "" } proc tts_set_character_scale {factor} { global tts set tts(say_rate) [round \ [expr $tts(speech_rate) * $factor ]] set tts(char_factor) $factor return "" } proc tts_say {text} { global tts s set r $tts(speech_rate) set prefix "`v1 `vs$r " regsub -all {\[\*\]} $text { `p1 } text synth " $prefix $text" return "" } #formerly called tts_letter proc l {text} { global tts set r $tts(speech_rate) set prefix "`v1 `vs$r " if {[regexp {[A-Z]} $text]} { set prefix "$prefix `vb80" } set tts(not_stopped) 1 synth "$prefix `ts2 $text`ts0" return "" } #formerly called tts_speak proc d {} { speech_task } proc tts_resume {} { resume return "" } proc tts_pause {} { pause return "" } #formerly called tts_stop proc s {} { global tts if {$tts(not_stopped)==1} { set tts(not_stopped) 0 stop queue_clear } else { puts stderr StopNoOp } } #formerly called tts_tone #produce tones via midi proc t {{pitch 440} {duration 50}} { global tts queue if {$tts(midi)} { set inst 9 set len .1 set note [expr $pitch / 10] n $inst $note $len return "" } } proc sh {{duration 50}} { global tts queue set silence "`p$duration " set queue($tts(q_tail)) [list t $silence] incr tts(q_tail) return "" } proc tts_split_caps {flag} { global tts set tts(split_caps) $flag return "" } proc tts_capitalize {flag} { global tts set tts(capitalize) $flag return "" } proc tts_allcaps_beep {flag} { global tts set tts(allcaps_beep) $flag return "" } proc tts_reset {} { global tts synth -reset queue_clear synth "Resetting engine to factory defaults." } proc r {rate} { global queue tts set queue($tts(q_tail)) [list s "`vs $rate "] incr tts(q_tail) return "" } # }}} # {{{ speech task proc trackIndex {index} { global tts set tts(last_index) $index } proc speech_task {} { global queue tts set tts(last_index) 0 set tts(not_stopped) 1 set r $tts(speech_rate) set length [queue_length] set prefix "`v1 `vs$r " loop index 0 $length { set event [queue_remove] set event_type [lindex $event 0] switch -exact -- $event_type { s { set text [clean [lindex $event 1]] say " $prefix $text" } n { if {$tts(midi)} { lvarpop event eval note $event } } } } synth " " return "" } # }}} # {{{clean #preprocess element before sending it out: proc clean {element} { global queue tts if {[string match all $tts(punctuations)] } { regsub -all -- {\*} $element \ { star } element regsub -all -- {-} $element \ { dash } element regsub -all -- {;} $element \ { semicolen } element regsub -all -- {\(} $element \ { left paren } element regsub -all -- {\)} $element \ { right paren } element regsub -all -- {@} $element \ { at } element regsub -all {[.,!?;:+=/'\"@$%&_*()]} $element \ { `00 \0 `p10 } element } else { regsub -all {[*%&()\"]} $element {} element regsub -all {([0-9a-zA-Z])([@!;/:()=\#,.\"])+([0-9a-zA-Z])} $element \ {\1 `p5 \3} element regsub -all {``} $element { `ar } element regsub -all {''} $element { `af } element regsub -all {' } $element { `p1 } element regsub -all -- {--} $element { `p10 } element regsub -all -- {-} $element { `p1 } element } if {$tts(capitalize) } { regsub -all {[A-Z]} $element {`ar`p10 & } element } if {$tts(split_caps) } { if {$tts(allcaps_beep)} { set tone "" set abbrev_tone "" } else { set tone "" set abbrev_tone "" } set allcaps [regexp {[^a-zA-Z0-9]?([A-Z][A-Z0-9]+)[^a-zA-Z0-9]} $element full match ] while {$allcaps } { if {[string length $match] <=3} { set abbrev " $abbrev_tone$match" regsub -all {[A-Z]} $abbrev {& `p1 } abbrev regsub -all A $abbrev {[ey]} abbrev regsub $match $element $abbrev element } else { regsub $match $element "$tone[string tolower $match]" element } set allcaps [regexp {[^a-zA-Z0-9]([A-Z][A-Z0-9]+)[^a-zA-Z0-9]} $element full match ] } regsub -all {[A-Z]} $element { `p1 &} element regsub -all {([^ -_A-Z])([A-Z][a-zA-Z]* )} $element\ {\1 `p1 \2 } element regsub -all {([^ -_A-Z])([A-Z])} $element\ {\1 `p1 \2} element } return $element } # }}} # {{{ Initialize and set state. #do not die if you see a control-c signal ignore {sigint} #initialize outloud tts_initialize set tts(speech_rate) 75 notes_initialize set servers [file dirname $argv0] set tclTTS $servers/linux-outloud #set ECIINI unless already set if {![info exists env(ECIINI)] || ![file exists $env(ECIINI)] } { set env(ECIINI) $tclTTS/eci.ini } load $tclTTS/tcleci.so synth {`v1 Via IBM Via Voice, `vb55 `vh55 `ar this `p20, is Eamakspeak! } #Start the main command loop: commandloop # }}} # {{{ Emacs local variables ### Local variables: ### major-mode: tcl-mode ### voice-lock-mode: t ### folded-file: t ### End: # }}}