On 6/14/06, Adam S. [email protected] wrote:
Here’s my attempt:
Here’s a quick version that is closer to having speech synth. It’s not
a real synthesiser, but if you can provide the corresponding ogg files
it can look for certain phrases and play them. The result should sound
a bit better than a real synthesiser since the sections will be spoken
fairly naturally. Only 53 files to record!
Well maybe the strings you use could be made a bit more similar to
shorten the list a bit 
Les
$CheerThreshold = 6 #decrease to get more random encouragement
$LongThreshold = 120 #minimum time to be considered a “long” run
class SpeechSynth
def initialize
@known = [“minutes left in this phase”,
“you are done, rest now.”,
“until the next activity”,
“OK, you can walk now”,
“seconds more to walk”,
“seconds more to run”,
“to go and there are”,
“OK, you can run now”,
“You are almost done”,
“are you ready, go!”,
“get ready to walk”,
“get ready to run”,
“short run left”,
“in this phase”,
“to exercise”,
“Keep it up!”,
“to exersize”,
“Way to go!”,
“of walking”,
“short runs”,
“minute and”,
“There are”,
“Good job!”,
“long runs”,
“of runing”,
“You have”,
“walk for”,
“long run”,
“minutes”,
“seconds”,
“to walk”,
“run for”,
“to run”,
“walks”,
“left”,
“only”,
“more”,
“for”,
“and”,
“60”,
“30”,
“15”,
“18”,
“55”,
“7”,
“6”,
“5”,
“9”,
“3”,
“2”,
“1”,
“8”,
“4”]
end
def playFile(fileName)
puts "PLAY: '" +fileName + "'"
#on linux this can be:
#`play #{filename}`
end
def known(searchPhrase)
@known.each do |phrase|
return $~[1] if searchPhrase =~ /^(#{phrase}).*/i
end
puts "UNKNOWN PHRASE: #{searchPhrase}"
return nil
end
def say(sentence)
while sentence.length > 0
knownPhrase = known(sentence)
if knownPhrase
playFile(knownPhrase + ".ogg")
sentence = sentence[knownPhrase.length+1..-1]
sentence = "" if !sentence
else
sentence = ""
end
sentence.strip!
end
end
end
class Phase
attr_reader :action, :seconds
def initialize action, time
@action = action.downcase
@seconds = time.to_i
end
end
class Coach
def initialize filename
@synth = SpeechSynth.new
File.open(filename) {|f|
@rawdata = f.read.split(“\n”)
}
@duration = 0
@runs = @longs = @walks = 0
@encouragometer = 0
@step = [30,15,10,5,5]
end
def coach
build_timeline
say summarize(2)
say start_prompt
@time = Time.now
@target_time = @time
while (phase = @phases.shift)
update_summary phase
narrate_phase phase
if @phases.size > 0
say transition(@phases[0].action)
say summarize(rand(2))
end
end
say finish_line
end
def narrate_phase phase
say what_to_do_for(phase)
@target_time += phase.seconds
delta = (@target_time - Time.now).to_i
stepidx = 0
while (delta > 0)
stepidx+=1 if delta < @step[stepidx]+1
wait_time = delta%@step[stepidx]
wait_time += @step[stepidx] if wait_time <= 0
wait(wait_time)
delta = (@target_time - Time.now).to_i
encourage_maybe
say whats_left(phase.action,delta) if delta > 0
end
end
def update_summary phase
@duration -= phase.seconds
@runs -= 1 if phase.action == ‘run’
@longs -= 1 if phase.action == ‘run’ and phase.seconds >=
$LongThreshold
@walks -= 1 if phase.action == ‘walk’
end
def build_timeline
@phases = @rawdata.map {|command|
p = Phase.new(*command.split)
@duration += p.seconds
@runs += 1 if p.action == ‘run’
@longs += 1 if p.action == ‘run’ and p.seconds >= $LongThreshold
@walks += 1 if p.action == ‘walk’
p
}
end
def say s
@synth.say(s)
end
def wait n
if $DEBUG
puts “…waiting #{n} seconds…”
@target_time -= n
else
$stdout.flush
sleep(n)
end
end
def encourage_maybe
@encouragometer += rand(3)
if (@encouragometer > $CheerThreshold)
say cheer
@encouragometer = 0
end
end
def timesay secs
secs = secs.to_i
s = “”
if secs > 60
min = secs/60
secs -= min*60
s += “#{min} minute”
s += ‘s’ if min > 1
s += ’ and ’ if secs > 0
end
if secs > 0
s += “#{secs} second”
s += ‘s’ if secs > 1
end
s
end
All the phrases should be below this line, not mixed up in the logic
def what_to_do_for phase
s = “#{phase.action} for #{timesay(phase.seconds)} \n”
#s += “You are almost done” if @phases.size == 1
s
end
def whats_left act, time
timestr = timesay(time)
s = [
“You have #{timestr} more to #{act}”,
“#{act} for #{timestr} more”,
“only #{timestr} left of #{act}ing”,
“You have #{timestr} more to #{act}”,
“#{timestr} left in this phase”,
“There are #{timestr} until the next activity”
]
s[rand(s.size)]
end
def start_prompt
“are you ready, go!”
end
def transition next_act
s = [“OK, you can #{next_act} now”,
“get ready to #{next_act}”]
s[rand(s.size)]
end
def finish_line
“you are done, rest now.”
end
def cheer
c = [“Keep it up!”, “Way to go!”, “Good Job!”]
c[rand(c.size)]
end
def summarize degree
shorts = @runs - @longs
s = “you have #{timesay(@duration)}”
if degree > 0
if degree > 1
s+= " for "
else
s+= " to go and there are " if @runs > 0
end
s+=“#{@longs} long run” if @longs > 0
s+=“s” if @longs > 1
s+=" and" if @longs > 0 and shorts > 0 and degree <=1
s+=" #{shorts} short run" if shorts > 0
s+=“s” if shorts > 1
if degree >1
s+=" and" if @longs+shorts > 0
s+=" #{@walks} walk" if @walks > 0
s+=“s” if @walks > 1
else
s+=" left"
end
else
s+= " left to exercise"
end
s
end
end
Coach.new(ARGV[0]||“week3.txt”).coach