Module dectalk
[hide private]
[frames] | no frames]

Source Code for Module dectalk

  1  """Dectalk voice definitions using ACSS. 
  2   
  3  This module encapsulates Dectalk-specific voice definitions.  It 
  4  maps device-independent ACSS voice definitions into appropriate 
  5  Dectalk voice parameter settings. 
  6   
  7  """ 
  8   
  9  __id__ = "$Id: dectalk.py 3535 2005-11-17 14:32:59Z raman $" 
 10  __author__ = "$Author: raman $" 
 11  __version__ = "$Revision: 3535 $" 
 12  __date__ = "$Date: 2005-11-17 06:32:59 -0800 (Thu, 17 Nov 2005) $" 
 13  __copyright__ = "Copyright (c) 2005 T. V. Raman" 
 14  __license__ = "LGPL" 
 15   
 16  _defined_voices = {} 
 17   
 18  # Map from ACSS dimensions to Dectalk settings: 
 19   
 20  _table ={} 
 21  #family codes: 
 22   
 23  _table['family'] = { 
 24      'male' : ' :np ', 
 25      'paul' :  ':np', 
 26      'man' :  ':nh', 
 27      'man' : ' :nh ', 
 28      'dennis' :  ':nd', 
 29      'frank' :  ':nf', 
 30      'betty' :  ':nb', 
 31      'female' : ' :nb ', 
 32      'ursula' :  ':nu', 
 33      'wendy' :  ':nw', 
 34      'rita' :  ':nr', 
 35      'kid' :  ':nk', 
 36      'child' : ' :nk ' 
 37      } 
 38   
 39  # average-pitch : 
 40  # Average pitch for standard male voice is 122hz --this is mapped to 
 41  # a setting of 5. 
 42  # Average pitch varies inversely with speaker head size --a child 
 43  # has a small head and a higher pitched voice. 
 44  # We change parameter head-size in conjunction with average pitch to 
 45  # produce a more natural change on the Dectalk. 
 46   
 47  #male average pitch 
 48   
49 -def _update_map(table, key, format, settings):
50 """Internal function to update acss->synth mapping.""" 51 table[key] ={} 52 for setting in settings: 53 _table[key][setting[0]] = format % setting[1:]
54 55 _male_ap = [ 56 (0, 96, 115), 57 (1, 101, 112), 58 (2, 108, 109), 59 (3, 112, 106), 60 (4, 118, 103, ), 61 (5, 122, 100), 62 (6, 128, 98), 63 (7, 134, 96), 64 (8, 140, 94), 65 (9, 147, 91)] 66 67 _update_map(_table, ('male', 'average-pitch'), 68 " ap %s hs %s ", _male_ap) 69 70 #Man has a big head --and a lower pitch for the middle setting 71 _man_ap = [ 72 (0, 50, 125), 73 (1, 59, 123), 74 (2, 68, 121), 75 (3, 77, 120), 76 (4, 83, 118, ), 77 (5, 89, 115), 78 (6, 95, 112), 79 (7, 110, 105), 80 (8, 125, 100), 81 (9, 140, 95) 82 ] 83 84 _update_map(_table,('man', 'average-pitch'), 85 " ap %s hs %s ",_man_ap) 86 87 _female_ap = [ 88 (0, 160, 115), 89 (1, 170, 112), 90 (2, 181, 109), 91 (3, 192, 106), 92 (4, 200, 103, ), 93 (5, 208, 100), 94 (6, 219, 98), 95 (7, 225, 96), 96 (8, 240, 94), 97 (9, 260, 91) 98 ] 99 100 _update_map(_table, ('female', 'average-pitch'), 101 " ap %s hs %s ",_female_ap) 102 103 # pitch-range for male: 104 105 # Standard pitch range is 100 and is mapped to 106 # a setting of 5. 107 # A value of 0 produces a flat monotone voice --maximum value of 250 108 # produces a highly animated voice. 109 # Additionally, we also set the assertiveness of the voice so the 110 # voice is less assertive at lower pitch ranges. 111 112 _male_pr = [ 113 (0, 0, 0), 114 (1, 20, 10), 115 (2, 40, 20), 116 (3, 60, 30), 117 (4, 80, 40, ), 118 (5, 100, 50, ), 119 (6, 137, 60), 120 (7, 174, 70), 121 (8, 211, 80), 122 (9, 250, 100), 123 ] 124 125 _update_map(_table, ('male', 'pitch-range'), 126 " pr %s as %s ", _male_pr) 127 128 _man_pr = [ 129 (0, 0, 0), 130 (1, 16, 20), 131 (2, 32, 40), 132 (3, 48, 60), 133 (4, 64, 80, ), 134 (5, 80, 100, ), 135 (6, 137, 100), 136 (7, 174, 100), 137 (8, 211, 100), 138 (9, 250, 100) 139 ] 140 141 _update_map(_table, ('man', 'pitch-range'), 142 " pr %s as %s ", _man_pr) 143 144 _female_pr = [ 145 (0, 0, 0), 146 (1, 50, 10), 147 (2, 80, 20), 148 (3, 100, 25), 149 (4, 110, 30, ), 150 (5, 140, 35), 151 (6, 165, 57), 152 (7, 190, 75), 153 (8, 220, 87), 154 (9, 250, 100) 155 ] 156 157 _update_map(_table, ('female', 'pitch-range'), 158 " pr %s as %s ", _female_pr) 159 160 # Stress: 161 162 # On the Dectalk we vary four parameters 163 # The hat rise which controls the overall shape of the F0 contour 164 # for sentence level intonation and stress, 165 # The stress rise that controls the level of stress on stressed 166 # syllables, 167 # the baseline fall for paragraph level intonation 168 # and the quickness --a parameter that controls whether the final 169 # frequency targets are completely achieved in the phonetic transitions. 170 171 172 _male_stress =[ 173 (0, 0, 0, 0, 0), 174 (1, 3, 6, 20, 3), 175 (2, 6, 12, 40, 6), 176 (3, 9, 18, 60, 9, ), 177 (4, 12, 24, 80, 14), 178 (5, 18, 32, 100, 18), 179 (6, 34, 50, 100, 20), 180 (7, 48, 65, 100, 35), 181 (8, 63, 82, 100, 60), 182 (9, 80, 90, 100, 40) 183 ] 184 185 _update_map(_table, ('male', 'stress'), 186 " hr %s sr %s qu %s bf %s ", _male_stress) 187 188 _man_stress = [ 189 (0, 0, 0, 0, 0), 190 (1, 4, 6, 2, 2, ), 191 (2, 8, 12, 4, 4, ), 192 (3, 12, 18, 6, 6, ), 193 (4, 16, 24, 8, 8, ), 194 (5, 20, 30, 10, 9), 195 (6, 40, 48, 32, 16), 196 (7, 60, 66, 54, 22), 197 (8, 80, 78, 77, 34), 198 (9, 100, 100, 100, 40) 199 ] 200 201 202 _update_map(_table, ('man', 'stress'), 203 " hr %s sr %s qu %s bf %s ", _man_stress) 204 205 _female_stress = [ 206 (0, 1, 1, 0, 0), 207 (1, 3, 4, 11, 0), 208 (2, 5, 8, 22, 0), 209 (3, 8, 12, 33, 0, ), 210 (4, 11, 16, 44, 0), 211 (5, 14, 20, 55, 0), 212 (6, 35, 40, 65, 10), 213 (7, 56, 80, 75, 20), 214 (8, 77, 90, 85, 30), 215 (9, 100, 100, 100, 40) 216 217 ] 218 219 _update_map(_table, ('female', 'stress'), 220 " hr %s sr %s qu %s bf %s ", _female_stress) 221 222 #richness 223 224 # Smoothness and richness vary inversely. 225 # a maximally smooth voice produces a quieter effect 226 # a rich voice is "bright" in contrast. 227 228 229 _male_richness = [ 230 (0, 0, 100), 231 (1, 14, 80), 232 (2, 28, 60), 233 (3, 42, 40), 234 (4, 56, 30), 235 (5, 70, 28), 236 (6, 60, 24 ), 237 (7, 70, 16), 238 (8, 80, 8), 239 (9, 100, 0) 240 ] 241 242 _update_map(_table, ('male', 'richness'), 243 " ri %s sm %s " ,_male_richness) 244 245 _man_richness = [ 246 (0, 100, 0), 247 (1, 96, 3), 248 (2, 93, 6), 249 (3, 90, 9), 250 (4, 88, 11), 251 (5, 86, 12), 252 (6, 60, 24, ), 253 (7, 40, 44), 254 (8, 20, 65), 255 (9, 0, 70) 256 ] 257 258 _update_map(_table, ('man', 'richness'), 259 " ri %s sm %s " , _man_richness) 260 261 _female_richness = [ 262 (0, 0, 100), 263 (1, 8, 76), 264 (2, 16, 52), 265 (3, 24,28), 266 (4, 32, 10), 267 (5, 40, 4), 268 (6, 50, 3), 269 (7, 65, 3), 270 (8, 80, 2), 271 (9, 100, 0) 272 ] 273 274 _update_map(_table, ('female', 'richness'), 275 " ri %s sm %s ", _female_richness)
276 -def getrate(r): return 180 + 4*r
277
278 -def getvoicelist(): return _table['family'].keys()
279
280 -def getvoice(acss):
281 """Memoized function that returns synthesizer code for 282 specified ACSS setting. 283 Synthesizer code is a tupple of the form (open,close) 284 where open sets the voice, and close resets it.""" 285 286 name=acss.name() 287 if name in _defined_voices: return _defined_voices[name] 288 _defined_voices[name] =acss2voice(acss) 289 return _defined_voices[name]
290
291 -def acss2voice(acss):
292 """Return synthesizer code.""" 293 code = "" 294 family ='male' 295 if 'family'in acss: 296 family = acss['family'] 297 code += _table['family'][family] 298 if 'rate' in acss: code += " :ra %s" % getrate(acss['rate']) 299 if 'punctuations' in acss: code += " :punc %s" %acss['punctuations'] 300 voice = "" 301 dv = "" 302 for d in ['average-pitch', 'pitch-range', 303 'richness', 'stress']: 304 if d in acss:voice += _table[(family, d)][acss[d]] 305 if voice: dv = " :dv %s" % voice 306 if code or voice: code = "[%s %s]" % (code, dv) 307 return (code, " [:np] ")
308