#!/usr/bin/tcl # Keywords: Emacspeak, Software Dectalk , 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. # ATTENTION # This is not the original program # Updated for test by G.Casse (2003-03-13) # # }}} # {{{source common code set wd [file dirname $argv0] source $wd/tts-lib.tcl set rate_old 0 # }}} # {{{ procedures 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 set tts(say_rate) [round \ [expr $rate * $factor ]] 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 synth "\[:sa w]$text\013" return "" } #formerly called tts_letter proc l {text} { global tts set r $tts(speech_rate) set f $tts(say_rate) #synth "\[:say letter]$text\[:say clause]" synth " $text " return "" } #formerly called tts_speak proc d {} { speech_task } proc tts_resume {} { resume return "" } proc tts_repeat {} { global tts queue_rewind if {[queue_empty?]} { synth {No speech to repeat.} set tts(not_stopped) 1 } else { speech_task } return "" } proc tts_pause {} { pause return "" } #formerly called tts_stop proc s {} { stop queue_clear } #formerly called tts_tone #produce tones via midi proc t {{pitch 440} {duration 50}} { global tts queue set tone "\[:to $pitch $duration\]" set queue($tts(q_tail)) [list t $tone] incr tts(q_tail) 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 "\[_] " #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 {[:phoneme arpabet speak on ] [:pu s ] [:sa c] Via Software DecTalk, This, is Eamakspeak! } } proc r {rate} { global queue tts set queue($tts(q_tail)) [list s "\[:rate $rate] "] incr tts(q_tail) return "" } # }}} # {{{ speech task proc speech_task {} { global queue tts rate_old set mode $tts(punctuations) set r $tts(speech_rate) set length [queue_length] say "\[_]\[:sa c]\[:np]\[:ra $r]\[:pu $mode]" if {$rate_old != $r } { say "\[:ra $r]" set rate_old $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 "\[:i r 1]$text\013" } t { set text [lindex $event 1] say "\[:np] $text " } a { set sound [lindex $event 1] say "\[:play $sound]" } n { if {$tts(midi)} { lvarpop event catch {eval note $event} err } } } } synth " " return "" } # }}} # {{{clean #preprocess element before sending it out: proc clean {element} { global queue tts if {[string match all $tts(punctuations)] } { regsub -all {\#} $element \ { pound } element regsub -all {\*} $element \ { star } element regsub -all {[%&;()$+=/]} $element { \0 } element regsub -all {\.,} $element \ { dot comma [_,] } element regsub -all {\.\.\.} $element \ { dot dot dot } element regsub -all {\.\.} $element \ { dot dot } element regsub -all {([a-zA-Z])\.([a-zA-Z])} $element \ {\1 dot \2} element regsub -all {[0-9]+} $element { & } element } else { regsub -all {\.,} $element \ {[_,]} element regsub -all {([0-9a-zA-Z])([\"!;/:()=])+([0-9a-zA-z])} $element \ {\1 \2 \3} element regsub -all {([a-zA-Z])(,)+([a-zA-z])} $element \ {\1 \2 \3} element regsub -all {([a-zA-Z])(\.)([a-zA-z])} $element \ {\1[*]dot[*]\3} element regsub -all {``} $element {[_<1>/]} element regsub -all {''} $element {[_<1>\\]} element regsub -all { '} $element {[_']} element regsub -all {' } $element {[_']} element regsub -all -- {--} $element { [_,]} element regsub -all -- {-} $element { } element } if {$tts(capitalize) } { regsub -all {[A-Z]} $element {[_ :to 440 10]&} element } if {$tts(split_caps) } { if {$tts(allcaps_beep)} { set tone {[_:to 660 10]} set abbrev_tone ":to 660 10" } 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 {&[*]} 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 {[_<5>]&} element regsub -all {([^ -_A-Z])([A-Z][a-zA-Z]* )} $element\ {\1[_<1>]\2[,] } element regsub -all {([^ -_A-Z])([A-Z])} $element\ {\1[_<1>]\2} element } return $element } # }}} # {{{ Initialize and set state. #do not die if you see a control-c signal ignore {sigint} #initialize Dectalk tts_initialize set tts(speech_rate) 225 set tts(say_rate) [round \ [expr $tts(speech_rate) * $tts(char_factor)]] notes_initialize set tclTTS $env(EMACSPEAK_DIR)/servers/software-dtk load $tclTTS/tcldtk.so synth {[:phoneme arpabet speak on ] [:pu s ] [:sa c] [:np] Via Software DecTalk, This, 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: # }}} commandloop