├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.rst ├── docs ├── Makefile ├── changelog.rst ├── conf.py ├── drivers.rst ├── engine.rst ├── index.rst └── install.rst ├── pyttsx ├── __init__.py ├── driver.py ├── drivers │ ├── __init__.py │ ├── _espeak.py │ ├── dummy.py │ ├── espeak.py │ ├── nsss.py │ └── sapi5.py ├── engine.py └── voice.py ├── setup.py └── tests ├── manual └── run.py └── unit ├── test_all.py ├── test_lifecycle.py ├── test_prop.py ├── test_say.py └── test_setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | build/ 3 | dist/ 4 | pyttsx.egg-info/ 5 | _build/ 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | pyttsx Copyright (c) 2009, 2013 Peter Parente 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include docs * -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ====== 2 | pyttsx 3 | ====== 4 | 5 | Cross-platform Python wrapper for text-to-speech synthesis 6 | 7 | Help Wanted 8 | =========== 9 | 10 | As you can probably tell, I have not had time or in some cases the resources (e.g., specific versions of OSes) to maintain pyttsx very well for some time now. If you are using pyttsx in your day to day work and would like to take over as maintainer of the project, please let me know. 11 | 12 | Quickstart 13 | ========== 14 | 15 | :: 16 | 17 | import pyttsx 18 | engine = pyttsx.init() 19 | engine.say('Greetings!') 20 | engine.say('How are you today?') 21 | engine.runAndWait() 22 | 23 | See http://pyttsx.readthedocs.org/ for documentation of the full API. 24 | 25 | Included drivers 26 | ================ 27 | 28 | * nsss - NSSpeechSynthesizer on Mac OS X 10.5 and higher 29 | * sapi5 - SAPI5 on Windows XP, Windows Vista, and (untested) Windows 7 30 | * espeak - eSpeak on any distro / platform that can host the shared library (e.g., Ubuntu / Fedora Linux) 31 | 32 | Contributing drivers 33 | ==================== 34 | 35 | Email the author if you have wrapped or are interested in wrapping another text-to-speech engine for use with pyttsx. 36 | 37 | Project links 38 | ============= 39 | 40 | * Python Package Index for downloads (http://pypi.python.org/pyttsx) 41 | * GitHub site for source, bugs, and q&a (https://github.com/parente/pyttsx) 42 | * ReadTheDocs for docs (http://pyttsx.readthedocs.org) 43 | 44 | See Also 45 | ======== 46 | 47 | https://github.com/parente/espeakbox - espeak in a 16.5 MB Docker container with a simple REST API 48 | 49 | License 50 | ======= 51 | 52 | Copyright (c) 2009, 2013 Peter Parente 53 | All rights reserved. 54 | 55 | http://creativecommons.org/licenses/BSD/ 56 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | 9 | # Internal variables. 10 | PAPEROPT_a4 = -D latex_paper_size=a4 11 | PAPEROPT_letter = -D latex_paper_size=letter 12 | ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 13 | 14 | .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest 15 | 16 | help: 17 | @echo "Please use \`make ' where is one of" 18 | @echo " html to make standalone HTML files" 19 | @echo " dirhtml to make HTML files named index.html in directories" 20 | @echo " pickle to make pickle files" 21 | @echo " json to make JSON files" 22 | @echo " htmlhelp to make HTML files and a HTML help project" 23 | @echo " qthelp to make HTML files and a qthelp project" 24 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 25 | @echo " changes to make an overview of all changed/added/deprecated items" 26 | @echo " linkcheck to check all external links for integrity" 27 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 28 | 29 | clean: 30 | -rm -rf _build/* 31 | 32 | html: 33 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html 34 | @echo 35 | @echo "Build finished. The HTML pages are in _build/html." 36 | 37 | dirhtml: 38 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml 39 | @echo 40 | @echo "Build finished. The HTML pages are in _build/dirhtml." 41 | 42 | pickle: 43 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle 44 | @echo 45 | @echo "Build finished; now you can process the pickle files." 46 | 47 | json: 48 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json 49 | @echo 50 | @echo "Build finished; now you can process the JSON files." 51 | 52 | htmlhelp: 53 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp 54 | @echo 55 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 56 | ".hhp project file in _build/htmlhelp." 57 | 58 | qthelp: 59 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp 60 | @echo 61 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 62 | ".qhcp project file in _build/qthelp, like this:" 63 | @echo "# qcollectiongenerator _build/qthelp/pyttsx.qhcp" 64 | @echo "To view the help file:" 65 | @echo "# assistant -collectionFile _build/qthelp/pyttsx.qhc" 66 | 67 | latex: 68 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex 69 | @echo 70 | @echo "Build finished; the LaTeX files are in _build/latex." 71 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 72 | "run these through (pdf)latex." 73 | 74 | changes: 75 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes 76 | @echo 77 | @echo "The overview file is in _build/changes." 78 | 79 | linkcheck: 80 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck 81 | @echo 82 | @echo "Link check complete; look for any errors in the above output " \ 83 | "or in _build/linkcheck/output.txt." 84 | 85 | doctest: 86 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest 87 | @echo "Testing of doctests in the sources finished, look at the " \ 88 | "results in _build/doctest/output.txt." 89 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | --------- 3 | 4 | Version 1.2 5 | ~~~~~~~~~~~ 6 | 7 | * Added pip install instructions to doc. 8 | * Fixed voice selection to use VoiceLocaleIdentifier on OS X instead of deprecated VoiceLanguage 9 | 10 | Version 1.1 11 | ~~~~~~~~~~~ 12 | 13 | * Fixed compatibility with pip 14 | * Fixed espeak crash when running on Natty (https://github.com/parente/pyttsx/issues/3) 15 | 16 | Version 1.0 17 | ~~~~~~~~~~~ 18 | 19 | First release -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # pyttsx documentation build configuration file, created by 4 | # sphinx-quickstart on Sun Nov 1 09:40:19 2009. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.append(os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # Add any Sphinx extension module names here, as strings. They can be extensions 24 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 25 | extensions = [] 26 | 27 | # Add any paths that contain templates here, relative to this directory. 28 | templates_path = ['_templates'] 29 | 30 | # The suffix of source filenames. 31 | source_suffix = '.rst' 32 | 33 | # The encoding of source files. 34 | #source_encoding = 'utf-8' 35 | 36 | # The master toctree document. 37 | master_doc = 'index' 38 | 39 | # General information about the project. 40 | project = u'pyttsx' 41 | copyright = u'2009, 2013 Peter Parente' 42 | 43 | # The version info for the project you're documenting, acts as replacement for 44 | # |version| and |release|, also used in various other places throughout the 45 | # built documents. 46 | # 47 | # The short X.Y version. 48 | version = '1.2' 49 | # The full version, including alpha/beta/rc tags. 50 | release = '1.2' 51 | 52 | # The language for content autogenerated by Sphinx. Refer to documentation 53 | # for a list of supported languages. 54 | #language = None 55 | 56 | # There are two options for replacing |today|: either, you set today to some 57 | # non-false value, then it is used: 58 | #today = '' 59 | # Else, today_fmt is used as the format for a strftime call. 60 | #today_fmt = '%B %d, %Y' 61 | 62 | # List of documents that shouldn't be included in the build. 63 | #unused_docs = [] 64 | 65 | # List of directories, relative to source directory, that shouldn't be searched 66 | # for source files. 67 | exclude_trees = ['_build'] 68 | 69 | # The reST default role (used for this markup: `text`) to use for all documents. 70 | #default_role = None 71 | 72 | # If true, '()' will be appended to :func: etc. cross-reference text. 73 | #add_function_parentheses = True 74 | 75 | # If true, the current module name will be prepended to all description 76 | # unit titles (such as .. function::). 77 | #add_module_names = True 78 | 79 | # If true, sectionauthor and moduleauthor directives will be shown in the 80 | # output. They are ignored by default. 81 | #show_authors = False 82 | 83 | # The name of the Pygments (syntax highlighting) style to use. 84 | pygments_style = 'sphinx' 85 | 86 | # A list of ignored prefixes for module index sorting. 87 | #modindex_common_prefix = [] 88 | 89 | 90 | # -- Options for HTML output --------------------------------------------------- 91 | 92 | # The theme to use for HTML and HTML Help pages. Major themes that come with 93 | # Sphinx are currently 'default' and 'sphinxdoc'. 94 | html_theme = 'default' 95 | 96 | # Theme options are theme-specific and customize the look and feel of a theme 97 | # further. For a list of options available for each theme, see the 98 | # documentation. 99 | #html_theme_options = {} 100 | 101 | # Add any paths that contain custom themes here, relative to this directory. 102 | #html_theme_path = [] 103 | 104 | # The name for this set of Sphinx documents. If None, it defaults to 105 | # " v documentation". 106 | #html_title = None 107 | 108 | # A shorter title for the navigation bar. Default is the same as html_title. 109 | #html_short_title = None 110 | 111 | # The name of an image file (relative to this directory) to place at the top 112 | # of the sidebar. 113 | #html_logo = None 114 | 115 | # The name of an image file (within the static path) to use as favicon of the 116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 117 | # pixels large. 118 | #html_favicon = None 119 | 120 | # Add any paths that contain custom static files (such as style sheets) here, 121 | # relative to this directory. They are copied after the builtin static files, 122 | # so a file named "default.css" will overwrite the builtin "default.css". 123 | html_static_path = ['_static'] 124 | 125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 126 | # using the given strftime format. 127 | #html_last_updated_fmt = '%b %d, %Y' 128 | 129 | # If true, SmartyPants will be used to convert quotes and dashes to 130 | # typographically correct entities. 131 | #html_use_smartypants = True 132 | 133 | # Custom sidebar templates, maps document names to template names. 134 | #html_sidebars = {} 135 | 136 | # Additional templates that should be rendered to pages, maps page names to 137 | # template names. 138 | #html_additional_pages = {} 139 | 140 | # If false, no module index is generated. 141 | #html_use_modindex = True 142 | 143 | # If false, no index is generated. 144 | #html_use_index = True 145 | 146 | # If true, the index is split into individual pages for each letter. 147 | #html_split_index = False 148 | 149 | # If true, links to the reST sources are added to the pages. 150 | html_show_sourcelink = False 151 | 152 | # If true, an OpenSearch description file will be output, and all pages will 153 | # contain a tag referring to it. The value of this option must be the 154 | # base URL from which the finished HTML is served. 155 | #html_use_opensearch = '' 156 | 157 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 158 | #html_file_suffix = '' 159 | 160 | # Output file base name for HTML help builder. 161 | htmlhelp_basename = 'pyttsxdoc' 162 | 163 | 164 | # -- Options for LaTeX output -------------------------------------------------- 165 | 166 | # The paper size ('letter' or 'a4'). 167 | #latex_paper_size = 'letter' 168 | 169 | # The font size ('10pt', '11pt' or '12pt'). 170 | #latex_font_size = '10pt' 171 | 172 | # Grouping the document tree into LaTeX files. List of tuples 173 | # (source start file, target name, title, author, documentclass [howto/manual]). 174 | latex_documents = [ 175 | ('index', 'pyttsx.tex', u'pyttsx Documentation', 176 | u'Peter Parente', 'manual'), 177 | ] 178 | 179 | # The name of an image file (relative to this directory) to place at the top of 180 | # the title page. 181 | #latex_logo = None 182 | 183 | # For "manual" documents, if this is true, then toplevel headings are parts, 184 | # not chapters. 185 | #latex_use_parts = False 186 | 187 | # Additional stuff for the LaTeX preamble. 188 | #latex_preamble = '' 189 | 190 | # Documents to append as an appendix to all manuals. 191 | #latex_appendices = [] 192 | 193 | # If false, no module index is generated. 194 | #latex_use_modindex = True 195 | -------------------------------------------------------------------------------- /docs/drivers.rst: -------------------------------------------------------------------------------- 1 | Implementing drivers 2 | -------------------- 3 | 4 | You can implement new drivers for the :mod:`pyttsx.Engine` by: 5 | 6 | #. Creating a Python module with the name of your new driver. 7 | #. Implementing the required driver factory function and class in your module. 8 | #. Using methods on a :class:`pyttsx.driver.DriverProxy` instance provided by the :class:`pyttsx.Engine` to control the event queue and notify applications about events. 9 | 10 | The Driver interface 11 | ~~~~~~~~~~~~~~~~~~~~ 12 | 13 | All drivers must implement the following factory function and driver interface. 14 | 15 | .. module:: pyttsx.drivers 16 | :synopsis: The package containing the available driver implementations 17 | 18 | .. function:: buildDriver(proxy : pyttsx.driver.DriverProxy) -> pyttsx.drivers.DriverDelegate 19 | 20 | Instantiates delegate subclass declared in this module. 21 | 22 | :param proxy: Proxy instance provided by a :class:`pyttsx.Engine` instance. 23 | 24 | .. class:: DriverDelegate 25 | 26 | .. note:: The :class:`DriverDelegate` class is not actually declared in :mod:`pyttsx.drivers` and cannot server as a base class. It is only here for the purpose of documenting the interface all drivers must implement. 27 | 28 | .. method:: __init__(proxy : pyttsx.drivers.DriverProxy, *args, **kwargs) -> None 29 | 30 | Constructor. Must store the proxy reference. 31 | 32 | :param proxy: Proxy instance provided by the :func:`buildDriver` function. 33 | 34 | .. method:: destroy() -> 35 | 36 | Optional. Invoked by the :class:`pyttsx.driver.DriverProxy` when it is being destroyed so this delegate can clean up any synthesizer resources. If not implemented, the proxy proceeds safely. 37 | 38 | .. method:: endLoop() -> None 39 | 40 | Immediately ends a running driver event loop. 41 | 42 | .. method:: getProperty(name : string) -> object 43 | 44 | Immediately gets the named property value. At least those properties listed in the :meth:`pyttsx.Engine.getProperty` documentation must be supported. 45 | 46 | :param name: Name of the property to query. 47 | :return: Value of the property at the time of this invocation. 48 | 49 | .. method:: say(text : unicode, name : string) -> None 50 | 51 | Immediately speaks an utterance. The speech must be output according to the current property values applied at the time of this invocation. Before this method returns, it must invoke :meth:`pyttsx.driver.DriverProxy.setBusy` with value :const:`True` to stall further processing of the command queue until the output completes or is interrupted. 52 | 53 | This method must trigger one and only one `started-utterance` notification when output begins, one `started-word` notification at the start of each word in the utterance, and a `finished-utterance` notification when output completes. 54 | 55 | :param text: Text to speak. 56 | :param name: Name to associate with the utterance. Included in notifications about this utterance. 57 | 58 | .. method:: setProperty(name : string, value : object) -> None 59 | 60 | Immediately sets the named property value. At least those properties listed in the :meth:`pyttsx.Engine.setProperty` documentation must be supported. After setting the property, the driver must invoke :meth:`pyttsx.driver.DriverProxy.setBusy` with value :const:`False` to pump the command queue. 61 | 62 | :param name: Name of the property to change. 63 | :param value: Value to set. 64 | 65 | .. method:: startLoop() 66 | 67 | Immediately starts an event loop. The loop is responsible for sending notifications about utterances and pumping the command queue by using methods on the :class:`pyttsx.driver.DriverProxy` object given to the factory function that created this object. 68 | 69 | .. method:: stop() 70 | 71 | Immediately stops the current utterance output. This method must trigger a `finished-utterance` notification if called during on-going output. It must trigger no notification if there is no ongoing output. 72 | 73 | After stopping the output and sending any required notification, the driver must invoke :meth:`pyttsx.driver.DriverProxy.setBusy` with value :const:`False` to pump the command queue. 74 | 75 | The DriverProxy interface 76 | ~~~~~~~~~~~~~~~~~~~~~~~~~ 77 | 78 | .. module:: pyttsx.driver 79 | :synopsis: The module containing the driver proxy implementation 80 | 81 | The :func:`pyttsx.drivers.buildDriver` factory receives an instance of a :class:`DriverProxy` class and provides it to the :class:`pyttsx.drivers.DriverDelegate` it constructs. The driver delegate can invoke the following public methods on the proxy instance. All other public methods found in the code are reserved for use by an :class:`pyttsx.Engine` instance. 82 | 83 | .. class:: DriverProxy 84 | 85 | .. method:: isBusy() -> bool 86 | 87 | Gets if the proxy is busy and cannot process the next command in the queue or not. 88 | 89 | :return: True means busy, False means idle. 90 | 91 | .. method:: notify(topic : string, **kwargs) -> None 92 | 93 | Fires a notification. 94 | 95 | :param topic: The name of the notification. 96 | :kwargs: Name/value pairs associated with the topic. 97 | 98 | .. method:: setBusy(busy : bool) -> None 99 | 100 | Sets the proxy to busy so it cannot continue to pump the command queue or idle so it can process the next command. 101 | 102 | :param busy: True to set busy, false to set idle -------------------------------------------------------------------------------- /docs/engine.rst: -------------------------------------------------------------------------------- 1 | .. module:: pyttsx 2 | :synopsis: The root pyttsx package defining the engine factory function 3 | 4 | Using pyttsx 5 | ------------ 6 | 7 | An application invokes the :func:`pyttsx.init` factory function to get a reference to a :class:`pyttsx.Engine` instance. During construction, the engine initializes a :class:`pyttsx.driver.DriverProxy` object responsible for loading a speech engine driver implementation from the :mod:`pyttsx.drivers` module. After construction, an application uses the engine object to register and unregister event callbacks; produce and stop speech; get and set speech engine properties; and start and stop event loops. 8 | 9 | The Engine factory 10 | ~~~~~~~~~~~~~~~~~~ 11 | 12 | .. function:: init([driverName : string, debug : bool]) -> pyttsx.Engine 13 | 14 | Gets a reference to an engine instance that will use the given driver. If the requested driver is already in use by another engine instance, that engine is returned. Otherwise, a new engine is created. 15 | 16 | :param driverName: Name of the :mod:`pyttsx.drivers` module to load and use. Defaults to the best available driver for the platform, currently: 17 | 18 | * `sapi5` - SAPI5 on Windows 19 | * `nsss` - NSSpeechSynthesizer on Mac OS X 20 | * `espeak` - eSpeak on every other platform 21 | 22 | :param debug: Enable debug output or not. 23 | :raises ImportError: When the requested driver is not found 24 | :raises RuntimeError: When the driver fails to initialize 25 | 26 | The Engine interface 27 | ~~~~~~~~~~~~~~~~~~~~ 28 | 29 | .. module:: pyttsx.engine 30 | :synopsis: The module containing the engine implementation 31 | 32 | .. class:: Engine 33 | 34 | Provides application access to text-to-speech synthesis. 35 | 36 | .. method:: connect(topic : string, cb : callable) -> dict 37 | 38 | Registers a callback for notifications on the given topic. 39 | 40 | :param topic: Name of the event to subscribe to. 41 | :param cb: Function to invoke when the event fires. 42 | :return: A token that the caller can use to unsubscribe the callback later. 43 | 44 | The following are the valid topics and their callback signatures. 45 | 46 | .. describe:: started-utterance 47 | 48 | Fired when the engine begins speaking an utterance. The associated callback must have the folowing signature. 49 | 50 | .. function:: onStartUtterance(name : string) -> None 51 | 52 | :param name: Name associated with the utterance. 53 | 54 | .. describe:: started-word 55 | 56 | Fired when the engine begins speaking a word. The associated callback must have the folowing signature. 57 | 58 | .. function:: onStartWord(name : string, location : integer, length : integer) 59 | 60 | :param name: Name associated with the utterance. 61 | 62 | .. describe:: finished-utterance 63 | 64 | Fired when the engine finishes speaking an utterance. The associated callback must have the folowing signature. 65 | 66 | .. function:: onFinishUtterance(name : string, completed : bool) -> None 67 | 68 | :param name: Name associated with the utterance. 69 | :param completed: True if the utterance was output in its entirety or not. 70 | 71 | .. describe:: error 72 | 73 | Fired when the engine encounters an error. The associated callback must have the folowing signature. 74 | 75 | .. function:: onError(name : string, exception : Exception) -> None 76 | 77 | :param name: Name associated with the utterance that caused the error. 78 | :param exception: Exception that was raised. 79 | 80 | .. method:: disconnect(token : dict) 81 | 82 | Unregisters a notification callback. 83 | 84 | :param token: Token returned by :meth:`connect` associated with the callback to be disconnected. 85 | 86 | .. method:: endLoop() -> None 87 | 88 | Ends a running event loop. If :meth:`startLoop` was called with `useDriverLoop` set to True, this method stops processing of engine commands and immediately exits the event loop. If it was called with False, this method stops processing of engine commands, but it is up to the caller to end the external event loop it started. 89 | 90 | :raises RuntimeError: When the loop is not running 91 | 92 | .. method:: getProperty(name : string) -> object 93 | 94 | Gets the current value of an engine property. 95 | 96 | :param name: Name of the property to query. 97 | :return: Value of the property at the time of this invocation. 98 | 99 | The following property names are valid for all drivers. 100 | 101 | .. describe:: rate 102 | 103 | Integer speech rate in words per minute. Defaults to 200 word per minute. 104 | 105 | .. describe:: voice 106 | 107 | String identifier of the active voice. 108 | 109 | .. describe:: voices 110 | 111 | List of :class:`pyttsx.voice.Voice` descriptor objects. 112 | 113 | .. describe:: volume 114 | 115 | Floating point volume in the range of 0.0 to 1.0 inclusive. Defaults to 1.0. 116 | 117 | .. method:: isBusy() -> bool 118 | 119 | Gets if the engine is currently busy speaking an utterance or not. 120 | 121 | :return: True if speaking, false if not. 122 | 123 | .. method:: runAndWait() -> None 124 | 125 | Blocks while processing all currently queued commands. Invokes callbacks for engine notifications appropriately. Returns when all commands queued before this call are emptied from the queue. 126 | 127 | .. method:: say(text : unicode, name : string) -> None 128 | 129 | Queues a command to speak an utterance. The speech is output according to the properties set before this command in the queue. 130 | 131 | :param text: Text to speak. 132 | :param name: Name to associate with the utterance. Included in notifications about this utterance. 133 | 134 | .. method:: setProperty(name, value) -> None 135 | 136 | Queues a command to set an engine property. The new property value affects all utterances queued after this command. 137 | 138 | :param name: Name of the property to change. 139 | :param value: Value to set. 140 | 141 | The following property names are valid for all drivers. 142 | 143 | .. describe:: rate 144 | 145 | Integer speech rate in words per minute. 146 | 147 | .. describe:: voice 148 | 149 | String identifier of the active voice. 150 | 151 | .. describe:: volume 152 | 153 | Floating point volume in the range of 0.0 to 1.0 inclusive. 154 | 155 | .. method:: startLoop([useDriverLoop : bool]) -> None 156 | 157 | Starts running an event loop during which queued commands are processed and notifications are fired. 158 | 159 | :param useDriverLoop: True to use the loop provided by the selected driver. False to indicate the caller will enter its own loop after invoking this method. The caller's loop must pump events for the driver in use so that pyttsx notifications are delivered properly (e.g., SAPI5 requires a COM message pump). Defaults to True. 160 | 161 | .. method:: stop() -> None 162 | 163 | Stops the current utterance and clears the command queue. 164 | 165 | The Voice metadata 166 | ~~~~~~~~~~~~~~~~~~ 167 | 168 | .. module:: pyttsx.voice 169 | :synopsis: The module containing the voice structure implementation 170 | 171 | .. class:: Voice 172 | 173 | Contains information about a speech synthesizer voice. 174 | 175 | .. attribute:: age 176 | 177 | Integer age of the voice in years. Defaults to :const:`None` if unknown. 178 | 179 | .. attribute:: gender 180 | 181 | String gender of the voice: `male`, `female`, or `neutral`. Defaults to :const:`None` if unknown. 182 | 183 | .. attribute:: id 184 | 185 | String identifier of the voice. Used to set the active voice via :meth:`pyttsx.engine.Engine.setPropertyValue`. This attribute is always defined. 186 | 187 | .. attribute:: languages 188 | 189 | List of string languages supported by this voice. Defaults to an empty list of unknown. 190 | 191 | .. attribute:: name 192 | 193 | Human readable name of the voice. Defaults to :const:`None` if unknown. 194 | 195 | Examples 196 | ~~~~~~~~ 197 | 198 | Speaking text 199 | ############# 200 | 201 | .. sourcecode:: python 202 | 203 | import pyttsx 204 | engine = pyttsx.init() 205 | engine.say('Sally sells seashells by the seashore.') 206 | engine.say('The quick brown fox jumped over the lazy dog.') 207 | engine.runAndWait() 208 | 209 | Listening for events 210 | #################### 211 | 212 | .. sourcecode:: python 213 | 214 | import pyttsx 215 | def onStart(name): 216 | print 'starting', name 217 | def onWord(name, location, length): 218 | print 'word', name, location, length 219 | def onEnd(name, completed): 220 | print 'finishing', name, completed 221 | engine = pyttsx.init() 222 | engine.connect('started-utterance', onStart) 223 | engine.connect('started-word', onWord) 224 | engine.connect('finished-utterance', onEnd) 225 | engine.say('The quick brown fox jumped over the lazy dog.') 226 | engine.runAndWait() 227 | 228 | Interrupting an utterance 229 | ######################### 230 | 231 | .. sourcecode:: python 232 | 233 | import pyttsx 234 | def onWord(name, location, length): 235 | print 'word', name, location, length 236 | if location > 10: 237 | engine.stop() 238 | engine = pyttsx.init() 239 | engine.connect('started-word', onWord) 240 | engine.say('The quick brown fox jumped over the lazy dog.') 241 | engine.runAndWait() 242 | 243 | Changing voices 244 | ############### 245 | 246 | .. sourcecode:: python 247 | 248 | engine = pyttsx.init() 249 | voices = engine.getProperty('voices') 250 | for voice in voices: 251 | engine.setProperty('voice', voice.id) 252 | engine.say('The quick brown fox jumped over the lazy dog.') 253 | engine.runAndWait() 254 | 255 | Changing speech rate 256 | #################### 257 | 258 | .. sourcecode:: python 259 | 260 | engine = pyttsx.init() 261 | rate = engine.getProperty('rate') 262 | engine.setProperty('rate', rate+50) 263 | engine.say('The quick brown fox jumped over the lazy dog.') 264 | engine.runAndWait() 265 | 266 | Changing volume 267 | ############### 268 | 269 | .. sourcecode:: python 270 | 271 | engine = pyttsx.init() 272 | volume = engine.getProperty('volume') 273 | engine.setProperty('volume', volume-0.25) 274 | engine.say('The quick brown fox jumped over the lazy dog.') 275 | engine.runAndWait() 276 | 277 | Running a driver event loop 278 | ########################### 279 | 280 | .. sourcecode:: python 281 | 282 | engine = pyttsx.init() 283 | def onStart(name): 284 | print 'starting', name 285 | def onWord(name, location, length): 286 | print 'word', name, location, length 287 | def onEnd(name, completed): 288 | print 'finishing', name, completed 289 | if name == 'fox': 290 | engine.say('What a lazy dog!', 'dog') 291 | elif name == 'dog': 292 | engine.endLoop() 293 | engine = pyttsx.init() 294 | engine.connect('started-utterance', onStart) 295 | engine.connect('started-word', onWord) 296 | engine.connect('finished-utterance', onEnd) 297 | engine.say('The quick brown fox jumped over the lazy dog.', 'fox') 298 | engine.startLoop() 299 | 300 | Using an external event loop 301 | ############################ 302 | 303 | .. sourcecode:: python 304 | 305 | engine = pyttsx.init() 306 | engine.say('The quick brown fox jumped over the lazy dog.', 'fox') 307 | engine.startLoop(False) 308 | # engine.iterate() must be called inside externalLoop() 309 | externalLoop() 310 | engine.endLoop() -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ================================== 2 | pyttsx - Text-to-speech x-platform 3 | ================================== 4 | 5 | This documentation describes the pyttsx Python package v |release| and was rendered on |today|. 6 | 7 | .. rubric:: Table of Contents 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | install 13 | engine 14 | drivers 15 | changelog 16 | 17 | .. rubric:: Project Links 18 | 19 | * `Project home page at GitHub`__ 20 | * `Package listing in PyPI`__ 21 | * `Documentation at ReadTheDocs`__ 22 | 23 | __ https://github.com/parente/pyttsx 24 | __ http://pypi.python.org/pypi/pyttsx 25 | __ https://pyttsx.readthedocs.org/ -------------------------------------------------------------------------------- /docs/install.rst: -------------------------------------------------------------------------------- 1 | Installing pyttsx 2 | ----------------- 3 | 4 | Tested versions 5 | ~~~~~~~~~~~~~~~ 6 | 7 | Version |version| of pyttsx includes drivers for the following text-to-speech synthesizers. Only operating systems on which a driver is tested and known to work are listed. The drivers may work on other systems. 8 | 9 | * SAPI5 on Windows XP, Windows Vista, and Windows 7 10 | * NSSpeechSynthesizer on Mac OS X 10.5 (Leopard), 10.6 (Snow Leopard), 10.7 (Lion), and 10.8 (Mountain Lion). 11 | * `espeak`_ on 32-bit Ubuntu Desktop Edition 8.10 (Intrepid), 9.04 (Jaunty), 9.10 (Karmic), and 12.04 (Precise). 12 | 13 | The :func:`pyttsx.init` documentation explains how to select a specific synthesizer by name as well as the default for each platform. 14 | 15 | Using pip to install system-wide 16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | 18 | If you have pip installed, you can use it to install pyttsx in the system site-packages folder. 19 | 20 | On Windows 21 | ########## 22 | 23 | First install the `pywin32-extensions `_ package using its Windows installer. Then use pip to install pyttsx. 24 | 25 | .. code-block:: bash 26 | 27 | $ pip install pyttsx 28 | 29 | On OSX or Linux 30 | ############### 31 | 32 | .. code-block:: bash 33 | 34 | $ sudo pip install pyttsx 35 | 36 | Using pip to install in a virtualenv 37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 38 | 39 | If you have virtualenv_ installed with pip_, you can use pip to install a copy of pyttsx in the virtual environment folder. 40 | 41 | On Windows 42 | ########## 43 | 44 | You'll need to install the `pywin32-extensions `_ package system-wide using its Windows installer. Then you'll need to give your virtualenv access to the system site-packages in order to install pyttsx. 45 | 46 | .. code-block:: bash 47 | 48 | $ virtualenv --system-site-packages myproj 49 | New python executable in myproj/bin/python 50 | Installing setuptools............done. 51 | Installing pip...............done. 52 | $ myproj\Scripts\activate 53 | (myproj)$ pip install pyttsx 54 | 55 | On OSX 56 | ###### 57 | 58 | Unless you wish to compile your own version of pyobjc (a lengthy process), you will need to give your virtualenv access to the system site-packages folder. 59 | 60 | .. code-block:: bash 61 | 62 | $ virtualenv --system-site-packages myproj 63 | New python executable in myproj/bin/python 64 | Installing setuptools............done. 65 | Installing pip...............done. 66 | $ . myproj/bin/activate 67 | (myproj)$ pip install pyttsx 68 | ... 69 | Successfully installed pyttsx 70 | Cleaning up... 71 | 72 | On Linux 73 | ######## 74 | 75 | pyttsx requires no Python dependencies on Linux. You can cut-off the pyttsx virtualenv from the system site-packages. 76 | 77 | code-block:: bash 78 | 79 | $ virtualenv --no-site-packages myproj 80 | New python executable in myproj/bin/python 81 | Installing setuptools............done. 82 | Installing pip...............done. 83 | $ . myproj/bin/activate 84 | (myproj)$ pip install pyttsx 85 | ... 86 | Successfully installed pyttsx 87 | Cleaning up... 88 | 89 | 90 | .. _espeak: http://espeak.sourceforge.net/ 91 | .. _virtualenv: https://pypi.python.org/pypi/virtualenv/1.10.1 92 | .. _pip: https://pypi.python.org/pypi/pip -------------------------------------------------------------------------------- /pyttsx/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | pyttsx package. 3 | 4 | Copyright (c) 2009, 2013 Peter Parente 5 | 6 | Permission to use, copy, modify, and distribute this software for any 7 | purpose with or without fee is hereby granted, provided that the above 8 | copyright notice and this permission notice appear in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | ''' 18 | from __future__ import absolute_import 19 | from .engine import Engine 20 | import weakref 21 | 22 | _activeEngines = weakref.WeakValueDictionary() 23 | 24 | def init(driverName=None, debug=False): 25 | ''' 26 | Constructs a new TTS engine instance or reuses the existing instance for 27 | the driver name. 28 | 29 | @param driverName: Name of the platform specific driver to use. If 30 | None, selects the default driver for the operating system. 31 | @type: str 32 | @param debug: Debugging output enabled or not 33 | @type debug: bool 34 | @return: Engine instance 35 | @rtype: L{engine.Engine} 36 | ''' 37 | try: 38 | eng = _activeEngines[driverName] 39 | except KeyError: 40 | eng = Engine(driverName, debug) 41 | _activeEngines[driverName] = eng 42 | return eng 43 | -------------------------------------------------------------------------------- /pyttsx/driver.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Proxy for drivers. 3 | 4 | Copyright (c) 2009, 2013 Peter Parente 5 | 6 | Permission to use, copy, modify, and distribute this software for any 7 | purpose with or without fee is hereby granted, provided that the above 8 | copyright notice and this permission notice appear in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | ''' 18 | import sys 19 | import traceback 20 | import weakref 21 | import importlib 22 | 23 | class DriverProxy(object): 24 | ''' 25 | Proxy to a driver implementation. 26 | 27 | @ivar _module: Module containing the driver implementation 28 | @type _module: module 29 | @ivar _engine: Reference to the engine that owns the driver 30 | @type _engine: L{engine.Engine} 31 | @ivar _queue: Queue of commands outstanding for the driver 32 | @type _queue: list 33 | @ivar _busy: True when the driver is busy processing a command, False when 34 | not 35 | @type _busy: bool 36 | @ivar _name: Name associated with the current utterance 37 | @type _name: str 38 | @ivar _debug: Debugging output enabled or not 39 | @type _debug: bool 40 | @ivar _iterator: Driver iterator to invoke when in an external run loop 41 | @type _iterator: iterator 42 | ''' 43 | def __init__(self, engine, driverName, debug): 44 | ''' 45 | Constructor. 46 | 47 | @param engine: Reference to the engine that owns the driver 48 | @type engine: L{engine.Engine} 49 | @param driverName: Name of the driver module to use under drivers/ or 50 | None to select the default for the platform 51 | @type driverName: str 52 | @param debug: Debugging output enabled or not 53 | @type debug: bool 54 | ''' 55 | if driverName is None: 56 | # pick default driver for common platforms 57 | if sys.platform == 'darwin': 58 | driverName = 'nsss' 59 | elif sys.platform == 'win32': 60 | driverName = 'sapi5' 61 | else: 62 | driverName = 'espeak' 63 | # import driver module 64 | name = 'pyttsx.drivers.%s' % driverName 65 | self._module = importlib.import_module(name) 66 | # build driver instance 67 | self._driver = self._module.buildDriver(weakref.proxy(self)) 68 | # initialize refs 69 | self._engine = engine 70 | self._queue = [] 71 | self._busy = True 72 | self._name = None 73 | self._iterator = None 74 | self._debug = debug 75 | 76 | def __del__(self): 77 | try: 78 | self._driver.destroy() 79 | except (AttributeError, TypeError): 80 | pass 81 | 82 | def _push(self, mtd, args, name=None): 83 | ''' 84 | Adds a command to the queue. 85 | 86 | @param mtd: Method to invoke to process the command 87 | @type mtd: method 88 | @param args: Arguments to apply when invoking the method 89 | @type args: tuple 90 | @param name: Name associated with the command 91 | @type name: str 92 | ''' 93 | self._queue.append((mtd, args, name)) 94 | self._pump() 95 | 96 | def _pump(self): 97 | ''' 98 | Attempts to process the next command in the queue if one exists and the 99 | driver is not currently busy. 100 | ''' 101 | while (not self._busy) and len(self._queue): 102 | cmd = self._queue.pop(0) 103 | self._name = cmd[2] 104 | try: 105 | cmd[0](*cmd[1]) 106 | except Exception as e: 107 | self.notify('error', exception=e) 108 | if self._debug: traceback.print_exc() 109 | 110 | def notify(self, topic, **kwargs): 111 | ''' 112 | Sends a notification to the engine from the driver. 113 | 114 | @param topic: Notification topic 115 | @type topic: str 116 | @param kwargs: Arbitrary keyword arguments 117 | @type kwargs: dict 118 | ''' 119 | kwargs['name'] = self._name 120 | self._engine._notify(topic, **kwargs) 121 | 122 | def setBusy(self, busy): 123 | ''' 124 | Called by the driver to indicate it is busy. 125 | 126 | @param busy: True when busy, false when idle 127 | @type busy: bool 128 | ''' 129 | self._busy = busy 130 | if not self._busy: 131 | self._pump() 132 | 133 | def isBusy(self): 134 | ''' 135 | @return: True if the driver is busy, false if not 136 | @rtype: bool 137 | ''' 138 | return self._busy 139 | 140 | def say(self, text, name): 141 | ''' 142 | Called by the engine to push a say command onto the queue. 143 | 144 | @param text: Text to speak 145 | @type text: unicode 146 | @param name: Name to associate with the utterance 147 | @type name: str 148 | ''' 149 | self._push(self._driver.say, (text,), name) 150 | 151 | def stop(self): 152 | ''' 153 | Called by the engine to stop the current utterance and clear the queue 154 | of commands. 155 | ''' 156 | # clear queue up to first end loop command 157 | while(True): 158 | try: 159 | mtd, args, name = self._queue[0] 160 | except IndexError: 161 | break 162 | if(mtd == self._engine.endLoop): break 163 | self._queue.pop(0) 164 | self._driver.stop() 165 | 166 | def getProperty(self, name): 167 | ''' 168 | Called by the engine to get a driver property value. 169 | 170 | @param name: Name of the property 171 | @type name: str 172 | @return: Property value 173 | @rtype: object 174 | ''' 175 | return self._driver.getProperty(name) 176 | 177 | def setProperty(self, name, value): 178 | ''' 179 | Called by the engine to set a driver property value. 180 | 181 | @param name: Name of the property 182 | @type name: str 183 | @param value: Property value 184 | @type value: object 185 | ''' 186 | self._push(self._driver.setProperty, (name, value)) 187 | 188 | def runAndWait(self): 189 | ''' 190 | Called by the engine to start an event loop, process all commands in 191 | the queue at the start of the loop, and then exit the loop. 192 | ''' 193 | self._push(self._engine.endLoop, tuple()) 194 | self._driver.startLoop() 195 | 196 | def startLoop(self, useDriverLoop): 197 | ''' 198 | Called by the engine to start an event loop. 199 | ''' 200 | if useDriverLoop: 201 | self._driver.startLoop() 202 | else: 203 | self._iterator = self._driver.iterate() 204 | 205 | def endLoop(self, useDriverLoop): 206 | ''' 207 | Called by the engine to stop an event loop. 208 | ''' 209 | self._queue = [] 210 | self._driver.stop() 211 | if useDriverLoop: 212 | self._driver.endLoop() 213 | else: 214 | self._iterator = None 215 | self.setBusy(True) 216 | 217 | def iterate(self): 218 | ''' 219 | Called by the engine to iterate driver commands and notifications from 220 | within an external event loop. 221 | ''' 222 | try: 223 | next(self._iterator) 224 | except StopIteration: 225 | pass 226 | -------------------------------------------------------------------------------- /pyttsx/drivers/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Speech driver implementations. 3 | 4 | Copyright (c) 2009, 2013 Peter Parente 5 | 6 | Permission to use, copy, modify, and distribute this software for any 7 | purpose with or without fee is hereby granted, provided that the above 8 | copyright notice and this permission notice appear in all copies. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | ''' -------------------------------------------------------------------------------- /pyttsx/drivers/_espeak.py: -------------------------------------------------------------------------------- 1 | '''espeak.py a thin ctypes wrapper for the espeak dll 2 | 3 | Gary Bishop 4 | July 2007 5 | Modified October 2007 for the version 2 interface to espeak and more pythonic interfaces 6 | 7 | Free for any use. 8 | ''' 9 | 10 | from __future__ import print_function 11 | import ctypes 12 | from ctypes import cdll, c_int, c_char_p, c_wchar_p, POINTER, c_short, c_uint, c_long, c_void_p 13 | from ctypes import CFUNCTYPE, byref, Structure, Union, c_wchar, c_ubyte, c_ulong 14 | import time 15 | 16 | def cfunc(name, dll, result, *args): 17 | '''build and apply a ctypes prototype complete with parameter flags''' 18 | atypes = [] 19 | aflags = [] 20 | for arg in args: 21 | atypes.append(arg[1]) 22 | aflags.append((arg[2], arg[0]) + arg[3:]) 23 | return CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags)) 24 | 25 | dll = cdll.LoadLibrary('libespeak.so.1') 26 | 27 | # constants and such from speak_lib.h 28 | 29 | EVENT_LIST_TERMINATED = 0 30 | EVENT_WORD = 1 31 | EVENT_SENTENCE = 2 32 | EVENT_MARK = 3 33 | EVENT_PLAY = 4 34 | EVENT_END = 5 35 | EVENT_MSG_TERMINATED = 6 36 | 37 | class numberORname(Union): 38 | _fields_ = [ 39 | ('number', c_int), 40 | ('name', c_char_p) 41 | ] 42 | 43 | class EVENT(Structure): 44 | _fields_ = [ 45 | ('type', c_int), 46 | ('unique_identifier', c_uint), 47 | ('text_position', c_int), 48 | ('length', c_int), 49 | ('audio_position', c_int), 50 | ('sample', c_int), 51 | ('user_data', c_void_p), 52 | ('id', numberORname) 53 | ] 54 | 55 | AUDIO_OUTPUT_PLAYBACK = 0 56 | AUDIO_OUTPUT_RETRIEVAL = 1 57 | AUDIO_OUTPUT_SYNCHRONOUS = 2 58 | AUDIO_OUTPUT_SYNCH_PLAYBACK = 3 59 | 60 | EE_OK = 0 61 | EE_INTERNAL_ERROR = -1 62 | EE_BUFFER_FULL = 1 63 | EE_NOT_FOUND = 2 64 | 65 | Initialize = cfunc('espeak_Initialize', dll, c_int, 66 | ('output', c_int, 1, AUDIO_OUTPUT_PLAYBACK), 67 | ('bufflength', c_int, 1, 100), 68 | ('path', c_char_p, 1, None), 69 | ('option', c_int, 1, 0)) 70 | Initialize.__doc__ = '''Must be called before any synthesis functions are called. 71 | output: the audio data can either be played by eSpeak or passed back by the SynthCallback function. 72 | buflength: The length in mS of sound buffers passed to the SynthCallback function. 73 | path: The directory which contains the espeak-data directory, or NULL for the default location. 74 | options: bit 0: 1=allow espeakEVENT_PHONEME events. 75 | 76 | Returns: sample rate in Hz, or -1 (EE_INTERNAL_ERROR).''' 77 | 78 | t_espeak_callback = CFUNCTYPE(c_int, POINTER(c_short), c_int, POINTER(EVENT)) 79 | 80 | cSetSynthCallback = cfunc('espeak_SetSynthCallback', dll, None, 81 | ('SynthCallback', t_espeak_callback, 1)) 82 | SynthCallback = None 83 | def SetSynthCallback(cb): 84 | global SynthCallback 85 | SynthCallback = t_espeak_callback(cb) 86 | cSetSynthCallback(SynthCallback) 87 | 88 | SetSynthCallback.__doc__ = '''Must be called before any synthesis functions are called. 89 | This specifies a function in the calling program which is called when a buffer of 90 | speech sound data has been produced. 91 | 92 | 93 | The callback function is of the form: 94 | 95 | int SynthCallback(short *wav, int numsamples, espeak_EVENT *events); 96 | 97 | wav: is the speech sound data which has been produced. 98 | NULL indicates that the synthesis has been completed. 99 | 100 | numsamples: is the number of entries in wav. This number may vary, may be less than 101 | the value implied by the buflength parameter given in espeak_Initialize, and may 102 | sometimes be zero (which does NOT indicate end of synthesis). 103 | 104 | events: an array of espeak_EVENT items which indicate word and sentence events, and 105 | also the occurance if and