#
# Sistema de reconhecimento de fala. Idioma português brasileiro.
# Mostra um menu de opções e cola o resultado no aplicativo em uso.
# Feito para windows (testado no Windows Seven). Licença: Domínio público.
# (c) 2011 Sony Fermino dos Santos - http://gigawiki.com/sony/
# Fornecido sem quaisquer garantias e responsabilidades.
# Use por sua conta e risco.
# Veja instruções de uso em http://gigawiki.com/sony/reconhecimento-de-fala
#
# Este é meu primeiro trabalho em Ruby.
#
# Parte destes comentários foi redigida verbalmente com este programa.
puts "Iniciando reconhecimento de fala!"
require 'thread'
# codificação utf8 <-> iso_8859-1
# inspirado em http://forum.rubyonbr.org/forums/1/topics/507 (by Ronie Uliana)
class String
def utf8_decode
array_utf8 = self.unpack('U*')
array_enc = []
array_utf8.each do |num|
if num <= 0xFF
array_enc << num
else
array_enc.concat "&\#\#{num};".unpack('C*')
end
end
array_enc.pack('C*')
end
def utf8_decode!
self.replace(self.utf8_decode)
end
def utf8_encode
self.unpack('C*').pack('U*')
end
def utf8_encode!
self.replace(self.utf8_encode)
end
end
def ignora(motivo, opcoes)
# loga motivo
puts "\nIgnorando: #{motivo}\nOpcoes:"
opcoes.each {|o| puts " '#{o}'"}
end
# abre comunicação com o Julius
puts "Abrindo comunicacao com o Julius..."
f = IO.popen("julius.bat -C opcoes.jconf 2>nul:", "r+")
# ignora primeira frase (que é vazia), enquanto espera o Julius ficar pronto
f.readpartial(4096)
# thread para ler o Julius em paralelo, enquanto a principal aguarda todas as opções.
lin = ''
mutex = Mutex.new # mutex p/ lin
termina = false
thread = Thread.new do
while not termina
linha = f.readpartial(4096)
mutex.synchronize do
lin += linha
end
end
end
at_exit do
# fecha a outra thread e o pipe.
print "\nTerminando... "
termina = true
f.write "Termina\n"
f.close
puts "Ok!"
end
while true
print "\nAguardando frase... "
linhas = linha = ''
# espera chegarem as opções do Julius
while true
mutex.synchronize do
linha = lin
lin = ''
end
if linha != ''
# estão chegando linhas
linhas += linha
sleep 0.01
next
elsif linhas == ''
# ainda não veio nada
sleep 0.2
next
else
# acabaram de vir as linhas!
break
end
end
print "Ok!"
# separa as frases candidatas
opcoes = linhas.scan(/sentence\d+.(.*)/).collect!{|e| e[0]}
# ignora a respiração
opcoes.each {|s| s.strip!; s.utf8_decode!}
if opcoes.include? 'há um ano'
ignora 'respiracao', opcoes
next
end
# monta um menu com as opções, e cola o resultado na aplicação corrente
# monta opções de comando
op_cmd = ''
tamanho = 0
opcoes.each do |opcao|
if !opcao.empty?
# tira espaços repetidos
opcao.squeeze!(' ')
op_cmd += " \"#{opcao}\""
tamanho += opcao.length
end
end
# na escolha da frase pode haver ruídos
# se o tamanho total for pequeno, ignora.
if tamanho < 50
ignora "tamanho insuficiente: " + tamanho.to_s, opcoes
next
end
# mostra a primeira opção para identificar o texto
puts " - " + opcoes[0]
# monta comando do menu
# comando se o autohotkey estiver instalado (no vista):
# comando = "\"c:\program Files\AutoHotkey\AutoHotkey.exe\" menu.ahk " + op_cmd
# comando para uso com menu.exe:
comando = "menu " + op_cmd
# executa o comando
print "Lancando o menu... "
system(comando)
puts "Ok!"
end