home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / python-support / gnome-orca / orca / dectalk.py < prev    next >
Encoding:
Python Source  |  2009-04-13  |  14.6 KB  |  564 lines

  1. # Orca
  2. #
  3. # Copyright 2005-2008 Google Inc.
  4. #
  5. # This library is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU Library General Public
  7. # License as published by the Free Software Foundation; either
  8. # version 2 of the License, or (at your option) any later version.
  9. #
  10. # This library is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. # Library General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU Library General Public
  16. # License along with this library; if not, write to the
  17. # Free Software Foundation, Inc., Franklin Street, Fifth Floor,
  18. # Boston MA  02110-1301 USA.
  19. #
  20. """Dectalk voice definitions using ACSS.
  21.  
  22. This module encapsulates Dectalk-specific voice definitions.  It
  23. maps device-independent ACSS voice definitions into appropriate
  24. Dectalk voice parameter settings.
  25.  
  26. """
  27.  
  28. __id__ = "$Id: dectalk.py 4281 2008-10-08 22:05:56Z wwalker $"
  29. __author__ = "T. V. Raman"
  30. __version__ = "$Revision: 4281 $"
  31. __date__ = "$Date: 2008-10-08 18:05:56 -0400 (Wed, 08 Oct 2008) $"
  32. __copyright__ = "Copyright (c) 2005-2008 Google Inc."
  33. __license__ = "LGPL"
  34.  
  35. import chnames
  36.  
  37. # Handling of special characters
  38. #
  39. # Emacspeak uses Tcl syntax to communicate with its speech servers.  It
  40. # embraces text in curly braces, so that at least {, }, and \ must be quoted
  41. # when sending text to speech server.  But individual speech engines have
  42. # their own special characters in addition to those of Tcl.  Dectalk
  43. # perceives speech parameters enclosed in square brackets, and Emacspeak
  44. # exploits this to transmit speech settings to Dectalk.  Thus we must quote
  45. # [ and ] too.
  46.  
  47. def makeSpecialCharMap():
  48.     """Returns list of pairs mapping characters which are special for
  49.     Dectalk speech server to their replacements.
  50.     """
  51.     chars = r'{\}[]'
  52.     return [(ch, ' '+chnames.getCharacterName(ch)+' ') for ch in chars]
  53.  
  54.  
  55. # Speech parameters
  56.  
  57. _defined_voices = {}
  58.  
  59. # Map from ACSS dimensions to Dectalk settings:
  60.  
  61. _table = {}
  62. #family codes:
  63.  
  64. _table['family'] = {
  65.     'male' : ' :np ',
  66.     'paul' :  ':np',
  67.     'man' :  ':nh',
  68.     'harry' : ' :nh ',
  69.     'dennis' :  ':nd',
  70.     'frank' :  ':nf',
  71.     'betty' :  ':nb',
  72.     'female' : ' :nb ',
  73.     'ursula' :  ':nu',
  74.     'wendy' :  ':nw',
  75.     'rita' :  ':nr',
  76.     'kid' :  ':nk',
  77.     'child' : ' :nk '
  78.     }
  79.  
  80. # average-pitch :
  81. # Average pitch for standard male voice is 122hz --this is mapped to
  82. # a setting of 5.
  83. # Average pitch varies inversely with speaker head size --a child
  84. # has a small head and a higher pitched voice.
  85. # We change parameter head-size in conjunction with average pitch to
  86. # produce a more natural change on the Dectalk.
  87.  
  88. #male average pitch
  89.  
  90. def _update_map(table, key, format,  settings):
  91.     """Internal function to update acss->synth mapping."""
  92.     table[key] = {}
  93.     for setting  in  settings:
  94.         _table[key][setting[0]] = format % setting[1:]
  95.  
  96. _male_ap = [
  97.     (0, 96, 115),
  98.     (1, 101, 112),
  99.     (2, 108, 109),
  100.     (3, 112, 106),
  101.     (4, 118, 103),
  102.     (5, 122, 100),
  103.     (6, 128, 98),
  104.     (7, 134, 96),
  105.     (8, 140, 94),
  106.     (9, 147, 91)
  107.     ]
  108.  
  109. _update_map(_table, ('male', 'average-pitch'),
  110.             " ap %s hs %s ",  _male_ap)
  111. _update_map(_table, ('paul', 'average-pitch'),
  112.             " ap %s hs %s ",  _male_ap)
  113.  
  114. #Man  has a big head --and a lower pitch for the middle setting
  115. _man_ap = [
  116.     (0, 50, 125),
  117.     (1, 59, 123),
  118.     (2, 68, 121),
  119.     (3, 77, 120),
  120.     (4, 83, 118),
  121.     (5, 89, 115),
  122.     (6, 95, 112),
  123.     (7, 110, 105),
  124.     (8, 125, 100),
  125.     (9, 140, 95)
  126.     ]
  127.  
  128. _update_map(_table, ('man', 'average-pitch'),
  129.             " ap %s hs %s ",_man_ap)
  130. _update_map(_table, ('harry', 'average-pitch'),
  131.             " ap %s hs %s ",_man_ap)
  132.  
  133. _female_ap = [
  134.     (0, 160, 115),
  135.     (1, 170, 112),
  136.     (2, 181, 109),
  137.     (3, 192, 106),
  138.     (4, 200, 103),
  139.     (5, 208, 100),
  140.     (6, 219, 98),
  141.     (7, 225, 96),
  142.     (8, 240, 94),
  143.     (9, 260, 91)
  144.     ]
  145.  
  146. _update_map(_table, ('female', 'average-pitch'),
  147.             " ap %s hs %s ",_female_ap)
  148. _update_map(_table, ('betty', 'average-pitch'),
  149.             " ap %s hs %s ",_female_ap)
  150.  
  151. # The default DECtalk values for the pitch of the other voices seem
  152. # to be as follows:
  153. # Frank = 155, Dennis = 110, Ursula = 240, Rita = 106, Wendy = 200
  154. # Kit = Child = 306
  155. # Therefore, follow TV Raman's lead:
  156.  
  157. _frank_ap = [
  158.     (0, 129, 115),
  159.     (1, 134, 112),
  160.     (2, 141, 109),
  161.     (3, 145, 106),
  162.     (4, 151, 103),
  163.     (5, 155, 100),
  164.     (6, 159, 98),
  165.     (7, 165, 96),
  166.     (8, 171, 94),
  167.     (9, 178, 91)
  168.     ]
  169.  
  170. _update_map(_table, ('frank', 'average-pitch'),
  171.             " ap %s hs %s ",  _frank_ap)
  172.  
  173. _dennis_ap = [
  174.     (0, 84, 115),
  175.     (1, 89, 112),
  176.     (2, 96, 109),
  177.     (3, 100, 106),
  178.     (4, 106, 103),
  179.     (5, 110, 100),
  180.     (6, 116, 98),
  181.     (7, 122, 96),
  182.     (8, 128, 94),
  183.     (9, 135, 91)
  184.     ]
  185.  
  186. _update_map(_table, ('dennis', 'average-pitch'),
  187.             " ap %s hs %s ",  _dennis_ap)
  188.  
  189. _ursula_ap = [
  190.     (0, 196, 115),
  191.     (1, 206, 112),
  192.     (2, 215, 109),
  193.     (3, 224, 106),
  194.     (4, 232, 103),
  195.     (5, 240, 100),
  196.     (6, 251, 98),
  197.     (7, 265, 96),
  198.     (8, 280, 94),
  199.     (9, 300, 91)
  200.     ]
  201.  
  202. _update_map(_table, ('ursula', 'average-pitch'),
  203.             " ap %s hs %s ",  _ursula_ap)
  204.  
  205. _rita_ap = [
  206.     (0, 62, 115),
  207.     (1, 72, 112),
  208.     (2, 81, 109),
  209.     (3, 90, 106),
  210.     (4, 98, 103),
  211.     (5, 106, 100),
  212.     (6, 117, 98),
  213.     (7, 131, 96),
  214.     (8, 146, 94),
  215.     (9, 166, 91)
  216.     ]
  217.  
  218. _update_map(_table, ('rita', 'average-pitch'),
  219.             " ap %s hs %s ",  _rita_ap)
  220.  
  221. # For some reason, Wendy at a high pitch causes the
  222. # synthesizer to click and eventually make a feedback sound!
  223. # It doesn't seem to be the result of the pitch.
  224. # Keeping head size constant for higher pitch seems to eliminate
  225. # the problem.
  226.  
  227. _wendy_ap = [
  228.     (0, 156, 115),
  229.     (1, 166, 112),
  230.     (2, 175, 109),
  231.     (3, 184, 106),
  232.     (4, 192, 103),
  233.     (5, 200, 100),
  234.     (6, 211, 100),
  235.     (7, 225, 100),
  236.     (8, 240, 100),
  237.     (9, 260, 100)
  238.     ]
  239.  
  240. _update_map(_table, ('wendy', 'average-pitch'),
  241.             " ap %s hs %s ",  _wendy_ap)
  242.  
  243. # Kit/Child can't have the traditional adult head size
  244. # Setting the largest head size is the smallest adult
  245. # female head size.
  246.  
  247. _child_ap = [
  248.     (0, 256, 91),
  249.     (1, 266, 89),
  250.     (2, 276, 87),
  251.     (3, 286, 85),
  252.     (4, 296, 83),
  253.     (5, 306, 81),
  254.     (6, 316, 79),
  255.     (7, 326, 77),
  256.     (8, 336, 75),
  257.     (9, 346, 73)
  258.     ]
  259.  
  260. _update_map(_table, ('child', 'average-pitch'),
  261.             " ap %s hs %s ",  _child_ap)
  262. _update_map(_table, ('kit', 'average-pitch'),
  263.             " ap %s hs %s ",  _child_ap)
  264.  
  265. # pitch-range for male:
  266.  
  267. #  Standard pitch range is 100 and is  mapped to
  268. # a setting of 5.
  269. # A value of 0 produces a flat monotone voice --maximum value of 250
  270. # produces a highly animated voice.
  271. # Additionally, we also set the assertiveness of the voice so the
  272. # voice is less assertive at lower pitch ranges.
  273.  
  274. _male_pr = [
  275.     (0, 0, 0),
  276.     (1, 20, 10),
  277.     (2, 40, 20),
  278.     (3, 60, 30),
  279.     (4, 80, 40, ),
  280.     (5, 100, 50, ),
  281.     (6, 137, 60),
  282.     (7, 174, 70),
  283.     (8, 211, 80),
  284.     (9, 250, 100),
  285.     ]
  286.  
  287. _update_map(_table, ('male', 'pitch-range'),
  288.             " pr %s as %s ", _male_pr)
  289. _update_map(_table, ('paul', 'pitch-range'),
  290.             " pr %s as %s ", _male_pr)
  291.  
  292. # For now, assume that standard pitch range is reasonably
  293. # consistent for all male voices with the execption of harry
  294.  
  295. _update_map(_table, ('frank', 'pitch-range'),
  296.             " pr %s as %s ", _male_pr)
  297. _update_map(_table, ('dennis', 'pitch-range'),
  298.             " pr %s as %s ", _male_pr)
  299.  
  300.  
  301. _man_pr = [
  302.     (0, 0, 0),
  303.     (1, 16, 20),
  304.     (2, 32, 40),
  305.     (3, 48, 60),
  306.     (4, 64, 80, ),
  307.     (5, 80, 100, ),
  308.     (6, 137, 100),
  309.     (7, 174, 100),
  310.     (8, 211, 100),
  311.     (9, 250, 100)
  312.     ]
  313.  
  314. _update_map(_table, ('man', 'pitch-range'),
  315.             " pr %s as %s ", _man_pr)
  316. _update_map(_table, ('harry', 'pitch-range'),
  317.             " pr %s as %s ", _man_pr)
  318.  
  319. _female_pr = [
  320.     (0, 0, 0),
  321.     (1, 50, 10),
  322.     (2, 80, 20),
  323.     (3, 100, 25),
  324.     (4, 110, 30, ),
  325.     (5, 140, 35),
  326.     (6, 165, 57),
  327.     (7, 190, 75),
  328.     (8, 220, 87),
  329.     (9, 250, 100)
  330.     ]
  331.  
  332. _update_map(_table, ('female', 'pitch-range'),
  333.             " pr %s as %s ", _female_pr)
  334. _update_map(_table, ('betty', 'pitch-range'),
  335.             " pr %s as %s ", _female_pr)
  336.  
  337. # For now, assume that standard pitch range is reasonably
  338. # consistent for all female voices, including kit
  339.  
  340. _update_map(_table, ('ursula', 'pitch-range'),
  341.             " pr %s as %s ", _female_pr)
  342. _update_map(_table, ('rita', 'pitch-range'),
  343.             " pr %s as %s ", _female_pr)
  344. _update_map(_table, ('wendy', 'pitch-range'),
  345.             " pr %s as %s ", _female_pr)
  346. _update_map(_table, ('kit', 'pitch-range'),
  347.             " pr %s as %s ", _female_pr)
  348. _update_map(_table, ('child', 'pitch-range'),
  349.             " pr %s as %s ", _female_pr)
  350.  
  351. # Stress:
  352.  
  353. # On the Dectalk we vary four parameters
  354. # The hat rise which controls the overall shape of the F0 contour
  355. # for sentence level intonation and stress,
  356. # The stress rise that controls the level of stress on stressed
  357. # syllables,
  358. # the baseline fall for paragraph level intonation
  359. # and the quickness --a parameter that controls whether the final
  360. # frequency targets are completely achieved in the phonetic transitions.
  361.  
  362. _male_stress = [
  363.     (0, 0, 0, 0, 0),
  364.     (1, 3, 6, 20, 3),
  365.     (2, 6, 12, 40, 6),
  366.     (3, 9, 18, 60, 9, ),
  367.     (4, 12, 24, 80, 14),
  368.     (5, 18, 32, 100, 18),
  369.     (6, 34, 50, 100, 20),
  370.     (7, 48, 65, 100, 35),
  371.     (8, 63, 82, 100, 60),
  372.     (9, 80, 90, 100, 40)
  373. ]
  374.  
  375. _update_map(_table, ('male', 'stress'),
  376.             " hr %s sr %s qu %s bf %s ", _male_stress)
  377. _update_map(_table, ('paul', 'stress'),
  378.             " hr %s sr %s qu %s bf %s ", _male_stress)
  379.  
  380. # For now, grabbing these values for all males but Harry
  381.  
  382. _update_map(_table, ('frank', 'stress'),
  383.             " hr %s sr %s qu %s bf %s ", _male_stress)
  384. _update_map(_table, ('dennis', 'stress'),
  385.             " hr %s sr %s qu %s bf %s ", _male_stress)
  386.  
  387.  
  388. _man_stress = [
  389.     (0, 0, 0, 0, 0),
  390.     (1, 4, 6, 2, 2),
  391.     (2, 8, 12, 4, 4),
  392.     (3, 12, 18, 6, 6),
  393.     (4, 16, 24, 8, 8),
  394.     (5, 20, 30, 10, 9),
  395.     (6, 40, 48, 32, 16),
  396.     (7, 60, 66, 54, 22),
  397.     (8, 80, 78, 77, 34),
  398.     (9, 100, 100, 100, 40)
  399.     ]
  400.  
  401. _update_map(_table, ('man', 'stress'),
  402.             " hr %s sr %s qu %s bf %s ", _man_stress)
  403. _update_map(_table, ('harry', 'stress'),
  404.             " hr %s sr %s qu %s bf %s ", _man_stress)
  405.  
  406. _female_stress = [
  407.     (0, 1, 1, 0, 0),
  408.     (1, 3, 4, 11, 0),
  409.     (2, 5, 8, 22, 0),
  410.     (3, 8, 12, 33, 0),
  411.     (4, 11, 16, 44, 0),
  412.     (5, 14, 20, 55, 0),
  413.     (6, 35, 40, 65, 10),
  414.     (7, 56, 80, 75, 20),
  415.     (8, 77, 90, 85, 30),
  416.     (9, 100, 100, 100, 40)
  417.     ]
  418.  
  419. _update_map(_table, ('female', 'stress'),
  420.             " hr %s sr %s qu %s bf %s ", _female_stress)
  421. _update_map(_table, ('betty', 'stress'),
  422.             " hr %s sr %s qu %s bf %s ", _female_stress)
  423.  
  424. # For now, grabbing these values for all females including kit
  425.  
  426. _update_map(_table, ('ursula', 'stress'),
  427.             " hr %s sr %s qu %s bf %s ", _female_stress)
  428. _update_map(_table, ('rita', 'stress'),
  429.             " hr %s sr %s qu %s bf %s ", _female_stress)
  430. _update_map(_table, ('wendy', 'stress'),
  431.             " hr %s sr %s qu %s bf %s ", _female_stress)
  432. _update_map(_table, ('kit', 'stress'),
  433.             " hr %s sr %s qu %s bf %s ", _female_stress)
  434. _update_map(_table, ('child', 'stress'),
  435.             " hr %s sr %s qu %s bf %s ", _female_stress)
  436.  
  437. #richness
  438.  
  439. # Smoothness and richness vary inversely.
  440. # a  maximally smooth voice produces a quieter effect
  441. # a rich voice is "bright" in contrast.
  442.  
  443. _male_richness = [
  444.     (0, 0, 100),
  445.     (1, 14, 80),
  446.     (2, 28, 60),
  447.     (3, 42, 40),
  448.     (4, 56, 30),
  449.     (5, 70, 28),
  450.     (6, 60, 24 ),
  451.     (7, 70, 16),
  452.     (8, 80, 8),
  453.     (9, 100, 0)
  454.     ]
  455.  
  456. _update_map(_table, ('male', 'richness'),
  457.             " ri %s sm %s " ,_male_richness)
  458. _update_map(_table, ('paul', 'richness'),
  459.             " ri %s sm %s " ,_male_richness)
  460.  
  461. # For now, grabbing these values for all males but Harry
  462.  
  463. _update_map(_table, ('frank', 'richness'),
  464.             " ri %s sm %s " ,_male_richness)
  465. _update_map(_table, ('dennis', 'richness'),
  466.             " ri %s sm %s " ,_male_richness)
  467.  
  468. _man_richness = [
  469.     (0, 100, 0),
  470.     (1, 96, 3),
  471.     (2, 93, 6),
  472.     (3, 90, 9),
  473.     (4, 88, 11),
  474.     (5, 86, 12),
  475.     (6, 60, 24, ),
  476.     (7, 40, 44),
  477.     (8, 20, 65),
  478.     (9, 0, 70)
  479.     ]
  480.  
  481. _update_map(_table, ('man', 'richness'),
  482.             " ri %s sm %s " , _man_richness)
  483. _update_map(_table, ('harry', 'richness'),
  484.             " ri %s sm %s " , _man_richness)
  485.  
  486. _female_richness = [
  487.     (0, 0, 100),
  488.     (1, 8, 76),
  489.     (2, 16, 52),
  490.     (3, 24,28),
  491.     (4, 32, 10),
  492.     (5, 40, 4),
  493.     (6, 50, 3),
  494.     (7, 65, 3),
  495.     (8, 80,  2),
  496.     (9, 100, 0)
  497.     ]
  498.  
  499. _update_map(_table, ('female', 'richness'),
  500.             " ri %s sm %s ", _female_richness)
  501. _update_map(_table, ('betty', 'richness'),
  502.             " ri %s sm %s ", _female_richness)
  503.  
  504. # For now, grabbing these values for all females including kit
  505.  
  506. _update_map(_table, ('ursula', 'richness'),
  507.             " ri %s sm %s ", _female_richness)
  508. _update_map(_table, ('rita', 'richness'),
  509.             " ri %s sm %s ", _female_richness)
  510. _update_map(_table, ('wendy', 'richness'),
  511.             " ri %s sm %s ", _female_richness)
  512. _update_map(_table, ('kit', 'richness'),
  513.             " ri %s sm %s ", _female_richness)
  514. _update_map(_table, ('child', 'richness'),
  515.             " ri %s sm %s ", _female_richness)
  516.  
  517.  
  518. def getrate(r):
  519.     return int(180 + 4*r)
  520.  
  521. def getvolume(v):
  522.     return int(10*v)
  523.  
  524. def getvoicelist(): 
  525.     return _table['family'].keys()
  526.  
  527. def getvoice(acss):
  528.     """Memoized function that returns  synthesizer code for
  529.     specified  ACSS setting.
  530.     Synthesizer code is a tupple of the form (open,close)
  531.     where open sets the voice, and close resets it."""
  532.     name = acss.name()
  533.     if name in _defined_voices:
  534.         return _defined_voices[name]
  535.     _defined_voices[name] = acss2voice(acss)
  536.     return _defined_voices[name]
  537.  
  538. def acss2voice(acss):
  539.     """Return synthesizer code."""
  540.     code = ""
  541.     familyName = 'male'
  542.     if 'family' in acss:
  543.         familyName = acss['family']['name']
  544.         if familyName in _table['family']:
  545.             code += _table['family'][familyName]
  546.     if 'rate' in acss:
  547.         code += " :ra %s" % getrate(acss['rate'])
  548.     if 'punctuations' in acss:
  549.         code += " :punc %s" % acss['punctuations']
  550.     if 'gain' in acss:
  551.         code += " :volume set %s" % getvolume(acss['gain'])
  552.     voice = ""
  553.     dv = ""
  554.     for d in ['average-pitch', 'pitch-range',
  555.               'richness', 'stress']:
  556.         if d in acss:
  557.             if (familyName, d) in _table:
  558.                 voice += _table[(familyName, d)][int(acss[d])]
  559.     if voice:
  560.         dv = " :dv %s" % voice
  561.     if code or voice:
  562.         code = "[%s  %s]" % (code, dv)
  563.     return (code, " [:np] ")
  564.