Viewing file: outloud.py (6.16 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# Orca # # Copyright 2005 Google Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # """Outloud voice definitions using ACSS.
This module encapsulates Outloud-specific voice definitions. It maps device-independent ACSS voice definitions into appropriate Outloud voice parameter settings.
"""
__id__ = "$Id: outloud.py,v 1.5 2006/07/31 12:41:30 wwalker Exp $" __author__ = "$Author: wwalker $" __version__ = "$Revision: 1.5 $" __date__ = "$Date: 2006/07/31 12:41:30 $" __copyright__ = "Copyright (c) 2005 Google Inc." __license__ = "LGPL"
_defined_voices = {}
# Map from ACSS dimensions to Outloud settings: def _update_map(table, key, format, settings): """Internal function to update acss->synth mapping.""" table[key] ={} for setting in settings: _table[key][setting[0]] = format % setting[1:]
_table ={} #family codes:
_table['family'] = { 'paul' : " `v1 ", 'male' : " `v1 ", 'harry' : " `v1 `vh65 `vb50 ", 'man' : " `v1 `vh65 `vb50 ", 'dennis' : " `v1 `vb0 ", 'frank' : " `v1 `vr100 ", 'betty' : " `v7 ", 'female' : " `v7 ", 'ursula' : " `v2 ", 'rita' : " `v2 `vr100 ", 'wendy' : " `v2 `vy50 ", 'kit' : " `v3 ", 'child' : " `v3 " } # Average pitch for standard male voice is 65 --this is mapped to # a setting of 5. # Average pitch varies inversely with speaker head size --a child # has a small head and a higher pitched voice. # We change parameter head-size in conjunction with average pitch to # produce a more natural change on the TTS engine.
#male average pitch
_male_ap = [ (0, 0, 90), (1, 13, 81, ), (2, 26, 72), (3, 39, 63), (4, 52, 54, ), (5, 65, 50), (6, 74, 40), (7, 83, 30, ), (8, 87, 26), (9, 92, 21) ]
_update_map(_table, ('male', 'average-pitch'), " `vb%s `vh%s ", _male_ap)
#Harry has a big head --and a lower pitch for the middle setting _man_ap = [ (0, 0, 90), (1, 10, 85, ), (2, 20, 80), (3, 30, 70), (4, 40, 60), (5, 50, 60), (6, 60, 50), (7, 70, 40, ), (8, 80, 30), (9, 90, 20) ]
_update_map(_table,('man', 'average-pitch'), " `vb%s `vh% s",_man_ap) #defalt baseline is average pitch of 81
_female_ap = [ (0, 5, 70), (1, 17, 66), (2, 33, 62), (3, 49, 58), (4, 65, 54, ), (5, 81, 50), (6, 85, 55), (7, 89, 60), (8, 93, 65), (9, 97, 69) ]
_update_map(_table, ('female', 'average-pitch'), " `vb%s `vh% s",_female_ap)
# pitch-range for male:
# Standard pitch range is 30 and is mapped to # a setting of 5. # A value of 0 produces a flat monotone voice --maximum value of 100 # produces a highly animated voice.
_male_pr = [ (0,0), (1,5), (2,15), (3,20), (4,25), (5,30), (6,47), (7,64), (8,81), (9,100) ]
_update_map(_table, ('male', 'pitch-range'), " `vf%s ", _male_pr)
_man_pr = [ (0, 0, ), (1, 5, ), (2, 15), (3, 20), (4, 25, ), (5, 30, ), (6, 47), (7, 64), (8, 81), (9, 100) ]
_update_map(_table, ('man', 'pitch-range'), " `vf%s ", _man_pr)
_female_pr = [ (0, 0, ), (1, 5, ), (2, 15), (3, 20), (4, 25, ), (5, 30, ), (6, 47), (7, 64), (8, 81), (9, 100) ]
_update_map(_table, ('female', 'pitch-range'), " `vf%s ", _female_pr)
# Stress: # On the outloud we map stress to roughness
_male_stress =[ (0, 0), (1, 5), (2, 10), (3, 15), (4, 20, ), (5, 25, ), (6, 30), (7, 35), (8, 40), (9, 45) ]
_update_map(_table, ('male', 'stress'), " `vr%s ", _male_stress)
#Same stress values work for female and man:
_update_map(_table, ('man', 'stress'), " `vr%s ", _male_stress)
_update_map(_table, ('female', 'stress'), " `vr%s ", _male_stress)
#richness
# Smoothness and richness vary inversely. # a maximally smooth voice produces a quieter effect # a rich voice is "bright" in contrast.
_male_richness = [ (0, 0, 60), (1, 4, 78), (2, 8, 80), (3, 12, 84), (4, 16, 88), (5, 20, 92), (6, 24, 93), (7, 28, 95), (8, 32, 97, ), (9, 36, 100) ]
_update_map(_table, ('male', 'richness'), " `vy%s `vv%s " ,_male_richness)
#same settings work for man and female:
_update_map(_table, ('man', 'richness'), " `vy%s `vv%s " , _male_richness)
_update_map(_table, ('female', 'richness'), " `vy%s `vv%s ", _male_richness)
# getrate is here for symmetry with other engines: # In the case of outloud, we dont need to normalize
def getrate(r): return r
def getvoicelist(): return _table['family'].keys()
def getvoice(acss): """Memoized function that returns synthesizer code for specified ACSS setting. Synthesizer code is a tupple of the form (open,close) where open sets the voice, and close resets it."""
name=acss.name() if name in _defined_voices: return _defined_voices[name] _defined_voices[name] =acss2voice(acss) return _defined_voices[name]
def acss2voice(acss): """Return synthesizer code.""" code = "" familyName ='male' if 'family' in acss: familyName = acss['family']['name'] code += _table['family'][familyName] if 'rate' in acss: code += " `vs%s" % int(acss['rate']) voice = "" for d in ['average-pitch', 'pitch-range', 'richness', 'stress']: if d in acss:voice += _table[(familyName, d)][int(acss[d])] if code or voice: code = "%s %s" % (code, voice) return (code, " `v1 ")
|