festival-freebsoft-utils-0.10/0000755000175000017500000000000011075611374014511 5ustar pdmpdmfestival-freebsoft-utils-0.10/ANNOUNCE0000644000175000017500000000352611075611374015650 0ustar pdmpdmfestival-freebsoft-utils 0.10 released ===================================== The Free(b)soft project is pleased to announce festival-freebsoft-utils 0.10. * What is festival-freebsoft-utils? festival-freebsoft-utils is a collection of Festival utilities that enhance Festival with some useful features. They provide all what is needed for interaction with Speech Dispatcher. Key festival-freebsoft-utils features are: - Generalized concept of input events. festival-freebsoft-utils allows not only plain text synthesis, but also combining it with sounds. Additionally, mechanism of logical events mapped to other events is provided. - Substitution of events for given words. - High-level voice selection mechanism and setting of basic prosodic parameters. - Spelling mode. - Capital letter signalization. - Punctuation modes, for explicit reading or not reading punctuation characters. - Incremental synthesis of texts and events. - Speech Dispatcher support. - Rudimentary SSML support. - Enhancing the Festival extension language with some functions commonly used in Lisp. Support for wrapping already defined Festival functions by your own code. - Everything is written in the extension language, no patching of the Festival C++ sources is needed. * What is new in version 0.10? - Speech Dispatcher support works again with recent versions of libc/iconv. - TMPDIR environment variable is honored even when the related Festival bug is present. - Bug fixes. * Where to get it? You can get the distribution tarball of the released version from http://www.freebsoft.org/pub/projects/festival-freebsoft-utils/festival-freebsoft-utils-0.10.tar.gz . The home page of the project is http://www.freebsoft.org/festival-freebsoft-utils . Local Variables: fill-column: 72 End: festival-freebsoft-utils-0.10/COPYING0000644000175000017500000004313311075611374015550 0ustar pdmpdm GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. festival-freebsoft-utils-0.10/Makefile0000644000175000017500000000413511075611374016154 0ustar pdmpdm# Makefile for festival-freebsoft-utils # Copyright (C) 2004, 2006, 2007, 2008 Brailcom, o.p.s. # # Author: Milan Zamazal # # COPYRIGHT NOTICE # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. PROJECT := festival-freebsoft-utils VERSION := 0.10 DISTDIR := festival-freebsoft-utils-$(VERSION) TARBALL := $(DISTDIR).tar DOCDIR := doc .PHONY: all install install-strip uninstall clean distclean mostlyclean \ maintainer-clean TAGS info dvi dist check all: info install: install-strip: $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install uninstall: mostlyclean: clean: mostlyclean rm -rf $(DISTDIR) $(TARBALL)* rm -f doc/*.info doc/*.ps doc/*.pdf doc/*.html doc/*.dvi distclean: clean maintainer-clean: distclean TAGS: info: $(DOCDIR)/$(PROJECT).info %.info: %.texi cd $(DOCDIR) && makeinfo $(PROJECT).texi pdf: $(DOCDIR)/$(PROJECT).pdf %.pdf: %.texi cd $(DOCDIR) && texi2pdf $(PROJECT).texi dvi: $(DOCDIR)/$(PROJECT).dvi %.dvi: %.texi cd $(DOCDIR) && texi2dvi $(PROJECT).texi ps: $(DOCDIR)/$(PROJECT).ps %.ps: %.texi dvi cd $(DOCDIR) && dvips $(PROJECT).dvi html: $(DOCDIR)/$(PROJECT).html %.html: %.texi cd $(DOCDIR) && \ makeinfo --html --no-split $(PROJECT).texi doc-all: info pdf ps dvi html dist: clean info mkdir $(DISTDIR) chmod 755 $(DISTDIR) install -m 644 [A-Z]* *.scm $(DISTDIR) mkdir -m 755 $(DISTDIR)/doc install -m 644 doc/*.texi doc/*.info* $(DISTDIR)/doc/ tar cvf $(TARBALL) $(DISTDIR) gzip -9 $(TARBALL) check: festival-freebsoft-utils-0.10/NEWS0000644000175000017500000000746011075611374015217 0ustar pdmpdmUser-visible changes to festival-freebsoft-utils: * Changes in festival-freebsoft-utils 0.10 ** Speech Dispatcher support updated for new libc/iconv. Due to a change in iconv Speech Dispatcher support has stopped to work. This release fixes the problem. ** TMPDIR environment variable honored. There is a bug in the current released version of Edinburgh Speech Tools resulting in ignoring temporary directory setting in TMPDIR environment variable. festival-freebsoft-utils now contains workaround of this bug. ** Bug fixes. * Changes in festival-freebsoft-utils 0.9 ** Character recoding improvements. Recoding of characters from UTF-8 to 8-bit codings is more kind to extra characters, not present in the target coding. New variable `recode-special-utf8-translations' allows to define custom mapping of extra characters. ** New function `string-replace'. ** Bug fixes. * Changes in festival-freebsoft-utils 0.8 ** New features required by Speech Dispatcher 0.6.4. ** Additional language codes for available Festival voices. ** Bug fixes in SSML support. * Changes in festival-freebsoft-utils 0.7 ** Better support of the general intonation method. It is generally possible to change basic prosodic parameters of voices that use general intonation method. ** New languages supported. Bug fixes and improvements that make Finnish, French and Italian voices work with festival-freebsoft-utils. ** New utility functions `butlast' and `abs'. ** Use iconv instead of recode. Iconv is more stable and better maintained recoding utility than recode. * Changes in festival-freebsoft-utils 0.6 ** Manual licensed under both GFDL and GPL. * Changes in festival-freebsoft-utils 0.5 ** SSML mode rewritten. Major cleanup of the mode. SSML interaction with Speech Dispatcher improved. Additionally spelling support was added, while SSML prosody settings remained unimplemented on the synthesis level in this version. ** New utility functions `min' and `max'. * Changes in festival-freebsoft-utils 0.4 No user visible changes, just bug fixes. * Changes in festival-freebsoft-utils 0.3 ** New module fileio.scm. ** New module recode.scm. ** Changes of the Speech Dispatcher interface. The Speech Dispatcher interface was changed to be compatible with Speech Dispatcher 0.5 and is not compatible with older Speech Dispatcher versions. * Changes in festival-freebsoft-utils 0.2 ** Speech Dispatcher rate and pitch setting changed. Now the Speech Dispatcher to Festival pitch/rate value mapping is smooth and pitch is set relatively to the default pitch of current voice. ** Event handling mechanism was reworked. Event handling was redesigned to produce better results and to be cleaner and more robust. ** Voice and language selection mechanism was generalized and simplified. There are new language-codes and voice-select-defaults variables that replace the old speechd-* voice and language selection variables. ** New functions for unified setting of prosodic parameters. With their help, you can change basic prosodic parameters like pitch, rate or volume easily. ** There is new option for disabling initial pauses in synthesized samples. See the variable inhibit-initial-pauses. ** Utterance chunking implemented in SIOD. It is now possible to perform utterance chunking not only in tts_file, but in any extension function. ** Synthesized events can be returned in multiple wave forms. See the manual entry of the multiple.scm module for description why this can be useful. The Speech Dispatcher interface was enhanced this way too. ** Rudimentary SSML support. ** New utility functions. See documentation of the util.scm and wave.scm files for the complete list of available utility functions. ** SoX is required. The SoX sound processing tool is now required for most of the functionality. Local variables: mode: outline end: festival-freebsoft-utils-0.10/README0000644000175000017500000000310311075611374015366 0ustar pdmpdmfestival-freebsoft-utils is a collection of Festival utilities that enhance Festival with some useful features. They provide all what is needed for interaction with Speech Dispatcher. Key festival-freebsoft-utils features are: - Generalized concept of input events. festival-freebsoft-utils allows not only plain text synthesis, but also combining it with sounds. Additionally, mechanism of logical events mapped to other events is provided. - Substitution of events for given words. - High-level voice selection mechanism and setting of basic prosodic parameters. - Spelling mode. - Capital letter signalization. - Punctuation modes, for explicit reading or not reading punctuation characters. - Incremental synthesis of texts and events. - Speech Dispatcher support. - Rudimentary SSML support. - Enhancing the Festival extension language with some functions commonly used in Lisp. Support for wrapping already defined Festival functions by your own code. - Everything is written in the extension language, no patching of the Festival C++ sources is needed. All the functionality is under development. Some things could be done in a better way, any help is welcome. You can contact us on the mailing list speechd@freebsoft.org. REQUIREMENTS - Festival 1.4.3. - SoX. - iconv. INSTALLATION - Copy all the *.scm files to a directory contained in the Festival's load-path. (Type `load-path' in Festival to view the directory list.) USAGE Look at the festival-freebsoft-utils manual in festival-freebsoft-utils.info. -- Milan Zamazal festival-freebsoft-utils-0.10/cap-signalization.scm0000644000175000017500000000514611075611374020637 0ustar pdmpdm;;; Capital character signalization ;; Copyright (C) 2003, 2004, 2006 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'util) (require 'oo) (defvar cap-signalization-mode nil) (define-wrapper (token_to_words token name) cap-signalization (if cap-signalization-mode (let ((ttw* (lambda (token name) (append (if (string-matches name "^[A-ZÁÈÏÉÌÍÒÓØ©«ÚÙÝ®].*") ;; token_to_words allows only strings and ;; symbols as feature values, so we have to use ;; capital-event, to be transformed later (list '((name "") (capital-event "") (event-stick-to next)))) ((next-func) token name))))) (if (string-matches name "^..*[A-ZÁÈÏÉÌÍÒÓØ©«ÚÙÝ®].*") (let ((i 1)) (while (not (string-matches (substring name i 1) "^[A-ZÁÈÏÉÌÍÒÓØ©«ÚÙÝ®].*")) (set! i (+ i 1))) (append (ttw* token (substring name 0 i)) (token_to_words token (substring name i (- (length name) i)) (next-func)))) (ttw* token name))) ((next-func) token name))) (Param.wrap Token_Method cap-signalization (lambda (utt) (apply* (next-value) (list utt)) (do-relation-items (w utt Word) (if (item.has_feat w 'capital-event) (add-event utt w '(logical capital) nil))) utt)) (define (set-cap-signalization-mode mode) "(set-cap-signalization-mode MODE) Enable or disable capital letter signalization mode. If MODE is non-nil, enable the mode, otherwise disable it." (oo-ensure-function-wrapped 'token_to_words) (set! cap-signalization-mode mode)) (provide 'cap-signalization) festival-freebsoft-utils-0.10/events.scm0000644000175000017500000003046711075611374016533 0ustar pdmpdm;;; Support of miscellaneous kinds of speech events ;; Copyright (C) 2003, 2004, 2005, 2006 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'cap-signalization) (require 'punctuation) (require 'ssml-mode) (require 'util) (require 'wave) (require 'word-mapping) ;;; Configuration variables (defvar sound-icon-directory "/usr/share/sounds/sound-icons" "Directory where sound icons are placed by default.") (defvar logical-event-mapping '((capital sound "capital") (empty-text sound "empty-text") (start sound "start") (prompt sound "prompt") (message sound "message") (finish sound "finish") (beginning-of-line sound "beginning-of-line") (end-of-line sound "end-of-line")) "Alist mapping logical sound events to any events. Each element of the alist is of the form (LOGICAL-EVENT EVENT-TYPE EVENT-VALUE), where LOGICAL-EVENT is the symbol naming the event to transform, EVENT-TYPE is the symbol naming the type of the transformed event and EVENT-VALUE is the corresponding transformed event value. The following event types are supported: `logical' -- just this event type again, the value is a symbol naming the event `text' -- plain text (the event value) to be synthesized `sound' -- a WAV file to be played, the value is a string naming the file; either as an absolute pathname starting with the slash character or a pathname relative to `sound-icon-directory' `key' -- a key event, the value is a string naming the key `character' -- a character event, the value is a string naming the character ") (defvar key-event-mapping '(("control_i" text "tab") ("control_m" text "enter") ("control_[" text "escape") ("f1" text "f 1") ("f2" text "f 2") ("f3" text "f 3") ("f4" text "f 4") ("f5" text "f 5") ("f6" text "f 6") ("f7" text "f 7") ("f8" text "f 8") ("f9" text "f 9") ("f10" text "f 10") ("f11" text "f 11") ("f12" text "f 12")) "Alist mapping key events to any events. The form of the alist is the same as in `logical-event-mapping', except LOGICAL-EVENT is replaced by a string naming the key.") (defvar character-event-mapping '(("\000" text "control space") ("\001" text "control a") ("\002" text "control b") ("\003" text "control c") ("\004" text "control d") ("\005" text "control e") ("\006" text "control f") ("\007" text "control g") ("\010" text "control h") ("\t" text "tab") ("\n" text "newline") ("\013" text "control k") ("\014" text "control l") ("\r" text "control m") ("\016" text "control n") ("\017" text "control o") ("\020" text "control p") ("\021" text "control q") ("\022" text "control r") ("\023" text "control s") ("\024" text "control t") ("\025" text "control u") ("\026" text "control v") ("\027" text "control w") ("\030" text "control x") ("\031" text "control y") ("\032" text "control z") ("\0240" text "hard space")) "Alist mapping character events to any events. The form of the alist is the same as in `logical-event-mapping', except LOGICAL-EVENT is replaced by a string naming the character.") (defvar event-mappings (list (list 'logical logical-event-mapping) (list 'key key-event-mapping) (list 'character character-event-mapping)) "Alist mapping event types to new events. Each element of the alist is of the form (EVENT-TYPE EVENT-MAPPING), where EVENT-TYPE is one of the symbols `logical', `text', `sound', `key', `character', and EVENT-MAPPING is the of the same form as `logical-event-mapping'.") (defvar event-debug nil) ;;; Internal functions (define (event-print object) (if event-debug (if (and (symbol-bound? 'server_log_file) (eq (typeof server_log_file) 'string)) (unwind-protect (let ((f (fopen (string-append server_log_file "-e") "a"))) (format f "%l\n" object) (fclose f)) (print object)) (print object)))) (defmac (event-with-mode form) (let ((mode-name (nth 0 (nth 1 form))) (mode-value (nth 1 (nth 1 form))) (body (nth_cdr 2 form))) (let ((mode-var (intern (string-append mode-name "-mode"))) (mode-func (intern (string-append "set-" mode-name "-mode")))) `(let ((,mode-name ,mode-var)) (,mode-func ,mode-value) (unwind-protect* (begin ,@body) (,mode-func ,mode-name)))))) (define (event-find-seg-1 utt word placement) (cond ((not word) (list ((if (eq? placement 'after) utt.relation.first utt.relation.last) utt 'Segment) placement)) ((not (string-equal (item.feat word "R:SylStructure.daughter1.daughter1.name") 0)) (let ((d (if (eq placement 'after) item.daughtern item.daughter1))) (list (d (d (item.relation word 'SylStructure))) placement))) (t (event-find-seg-1 utt ((if (eq? placement 'after) item.prev item.next) word) placement)))) (define (event-find-seg utt word placement) (if (utt.relation.items utt 'Segment) (if (eq? placement 'after) (event-find-seg-1 utt (item.next word) 'before) (event-find-seg-1 utt (item.prev word) 'after)) (begin (utt.relation.append utt 'Segment (list (caar (cdar (PhoneSet.description '(silences)))))) (list (utt.relation.first utt 'Segment) placement)))) (define (event-eat-utt utt wave-eater) (utt.relation.create utt 'Event) (do-relation-items (w utt Word) (let* ((events '()) (get-events (lambda (item) (let ((events* (item-events utt item))) (when events* (set! events (append (mapcar (lambda (e) (list (first e) (if (string-equal (second e) 'prev) 'before 'after))) events*) events))))))) (get-events w) (let ((token (item.parent (item.relation w 'Token)))) (if (and token (or (not (item.next w)) (not (equal? token (item.parent (item.relation (item.next w) 'Token)))))) (while token (get-events token) (set! token (item.next token)) (when (and token (item.daughters token)) (set! token nil))))) (mapcar (lambda (event-direction) (let* ((event (first event-direction)) (direction (second event-direction)) (seg-placement (event-find-seg utt w direction)) (seg (first seg-placement)) (placement (second seg-placement)) (event* (utt.relation.append utt 'Event `(event ((event ,event) (event-placement ,placement) (end ,(item.feat seg 'end)) (pend ,(item.feat seg "R:Segment.p.end"))))))) (item.set_feat seg 'event event*))) (reverse events)))) (let ((w (utt.wave utt))) (if (utt.relation.items utt 'Event) (let ((last-break 0.0)) (do-relation-items (event utt Event) (let ((break (if (string-equal (item.feat event 'event-placement) 'after) (item.feat event 'end) (or (item.feat event 'pend) 0.0))) (event* (item.feat event 'event))) (wave-eater (wave-subwave w last-break break)) (event-synth-plain (first event*) (second event*) wave-eater) (set! last-break break))) (wave-eater (wave-subwave w last-break (item.feat (utt.relation.last utt 'Segment) 'end)))) (wave-eater w))) utt) (define (event-synth-text text wave-eater) (unless (string-equal text "") (event-eat-utt (SynthText text) wave-eater))) (define (event-synth-ssml value wave-eater) (ssml-parse value) (let ((utt (ssml-next-chunk)) (last-utt nil)) (while utt (set! last-utt utt) (unless (symbol? utt) (utt.synth utt) (event-eat-utt utt wave-eater)) (set! utt (ssml-next-chunk))) last-utt)) (define (event-synth-key value wave-eater) (let ((text (string-append value))) (while (string-matches text ".*_.*") (aset text (length (string-before text "_")) 32)) (event-synth-text text wave-eater))) (define (event-synth-character value wave-eater) (event-synth-text value wave-eater)) (define (event-synth-sound value wave-eater) (let ((utt (wave-import-utt (if (string-matches value "^/.*") value (string-append sound-icon-directory "/" value))))) (wave-eater (utt.wave utt)) (when (string-matches value "^.*\.delete-after-play$") (delete-file value)) utt)) (define (event-synth-plain type value wave-eater) (cond ((eq? type 'text) (event-synth-text value wave-eater)) ((eq? type 'ssml) (event-synth-ssml value wave-eater)) ((eq? type 'sound) (event-synth-sound value wave-eater)) ((eq? type 'mark) (wave-eater (intern value))) (t (let ((transformed (cdr (assoc value (cadr (assq type (langvar 'event-mappings))))))) (cond (transformed (event-synth-1 (first transformed) (second transformed) wave-eater)) ((or (eq? type 'key) (eq? type 'character)) (event-with-mode (punctuation 'all) (event-with-mode (cap-signalization t) ((if (eq? type 'key) event-synth-key event-synth-character) value wave-eater)))) ((eq? type 'logical) (event-synth-text (if (string-matches value "^_.*") "" value) wave-eater)) (t (error "Event description not found" (cons type value)))))))) (define (event-synth-1 type value wave-eater) (event-print (list 'event event-debug type value)) (if (and (eq? type 'logical) (string-matches value "^_.*")) (cond ((string-matches value "^_debug_on.*") (set! event-debug (string-after value '_debug_on)) (set_backtrace t) (event-print value)) ((string-matches value "^_debug_off.*") (set! event-debug nil) (set_backtrace nil) (event-print value)))) (event-synth-plain type value wave-eater)) ;;; External functions (define (event-synth type value) (let* ((waves '()) (utt (event-synth-1 type value (lambda (w) (set! waves (cons w waves)))))) (if (<= (length waves) 1) utt (wave-utt (wave-concat (reverse waves)))))) (define (event-play type value) (utt.play (event-synth type value))) (define (set-event-mapping! type value new-type new-value) (set! event-mappings (assoc-set event-mappings type (assoc-set (cadr (assoc type event-mappings)) value (list new-type new-value))))) (define (item-events utt item) (mapcar (lambda (event) (list (nth 1 event) (nth 3 event))) (remove-if (lambda (annotation) (not (eq? (car annotation) 'event))) (get-annotations utt item)))) (define (add-event utt item event stick-to) (add-annotation utt item (list 'event event 'event-stick-to stick-to))) ;;; Announce (provide 'events) festival-freebsoft-utils-0.10/fileio.scm0000644000175000017500000000545711075611374016477 0ustar pdmpdm;;; File input/output utilities ;; Copyright (C) 2004 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'util) (defmac (with-open-file form) (let* ((spec (nth 1 form)) (body (nth_cdr 2 form)) (var (nth 0 spec)) (filename (nth 1 spec)) (how (or (nth 2 spec) "r"))) `(let ((,var (fopen ,filename ,how))) (unwind-protect* (begin ,@body) (fclose ,var))))) (defmac (with-temp-file-data form) (let* ((spec (nth 1 form)) (body (nth_cdr 2 form)) (filename (nth 0 spec)) (data (nth 1 spec))) `(with-temp-file ,filename (write-file ,filename ,data) ,@body))) (define (write-file filename string) (with-open-file (f filename "w") (fwrite (if (symbol? string) (format nil "%s" string) string) f))) (define (read-file filename) (with-open-file (f filename) (let* ((strings '()) (buffer (format nil "%1024s" "")) (buflen (length buffer)) (n 0) (reading t)) (while reading (set! n (fread buffer f)) (if n (begin (push (substring buffer 0 n) strings) (when (< n buflen) (set! reading nil))) (set! reading nil))) (apply string-append (reverse strings))))) (define (make-read-line-state) (list "")) (define (read-line file state) (let* ((text (car state)) (line (and text (string-before text "\n")))) (cond ((not text) nil) ((equal? line "") (let* ((buffer (format nil "%256s" "")) (n (fread buffer file))) (cond ((and (not n) (eqv? text "")) (set! line nil) (set! text nil)) ((not n) (set! line text) (set! text nil)) (t (set! text (string-append text (substring buffer 0 n))) (let ((state* (list text))) (set! line (read-line file state*)) (set! text (car state*))))))) (t (set! text (string-after text "\n")))) (set-car! state text) line)) (provide 'fileio) festival-freebsoft-utils-0.10/multiwave.scm0000644000175000017500000000477611075611374017250 0ustar pdmpdm;;; Generating multiple waves from a single event ;; Copyright (C) 2004 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'events) (require 'ssml-mode) (require 'tokenize) (require 'util) (defvar multi-waiting-waves nil) (defvar multi-waiting-text nil) (defvar multi-ssml-processing nil) (define (multi-add-wave wave) (set! multi-waiting-waves (append multi-waiting-waves (list wave)))) (define (multi-event-synth type value) (event-synth-1 type value multi-add-wave)) (define (multi-synth-current-text) (let ((new-text (second (next-chunk multi-waiting-text)))) (multi-event-synth 'text (substring multi-waiting-text 0 (- (length multi-waiting-text) (length new-text)))) (set! multi-waiting-text new-text))) ;; External functions (define (multi-clear) (set! multi-waiting-waves '()) (set! multi-waiting-text "") (set! multi-ssml-processing nil)) (define (multi-synth type value) (multi-clear) (cond ((eq? type 'text) (set! multi-waiting-text value)) ((eq? type 'ssml) (ssml-parse value) (set! multi-ssml-processing t)) (t (multi-event-synth type value)))) (define (multi-next) (cond (multi-waiting-waves (let ((wave (car multi-waiting-waves))) (set! multi-waiting-waves (cdr multi-waiting-waves)) wave)) (multi-ssml-processing (let ((utt (ssml-next-chunk))) (cond ((symbol? utt) utt) (utt (utt.synth utt) (event-eat-utt utt multi-add-wave) (multi-next)) (t (set! multi-ssml-processing nil))))) ((not (equal? multi-waiting-text "")) (multi-synth-current-text) (multi-next)) (t nil))) (provide 'multiwave) festival-freebsoft-utils-0.10/nopauses.scm0000644000175000017500000000252111075611374017052 0ustar pdmpdm;;; Inhibition of initial pauses ;; Copyright (C) 2004 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'oo) (require 'util) (defvar inhibit-initial-pauses nil "If non-nil, inhibit initial pauses in words.") (define-wrapper (insert_initial_pause utt) nopauses (unless inhibit-initial-pauses ((next-func) utt))) (define (nopauses-insert-initial-pause utt) (when inhibit-initial-pauses ((oo-unwrapped 'insert_initial_pause) utt) (item.set_feat (utt.relation.first utt 'Segment) 'end 0.0)) utt) (add-hook after_analysis_hooks nopauses-insert-initial-pause) (provide 'pause-util) festival-freebsoft-utils-0.10/oo.scm0000644000175000017500000001273011075611374015635 0ustar pdmpdm;;; Support of some object oriented features for Festival ;; Copyright (C) 2004 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'util) ;;; General wrapping mechanism (define (oo-first-wrapper-func wrappers) (cdar wrappers)) (define (oo-wrapper-func wrappers name) (cdr (assoc name wrappers))) (define (oo-next-wrapper-func wrappers name) (cond ((null? wrappers) nil) ((equal? (car (first wrappers)) name) (cdr (second wrappers))) (t (oo-next-wrapper-func (cdr wrappers) name)))) (define (oo-set-wrapper-func! wrappers-var name function) (let* ((wrappers (symbol-value wrappers-var)) (spec (assoc name wrappers))) (if spec (set-cdr! spec function) (set-symbol-value! wrappers-var (cons (cons name function) (symbol-value wrappers-var)))) nil)) (define (oo-wrapped-var funcname) (intern (string-append funcname "!shadow"))) (define (oo-wrappers-var funcname) (intern (string-append funcname "!wrappers"))) (define (oo-gen-wrapper wrappers-var) (lambda args (apply (oo-first-wrapper-func (symbol-value wrappers-var)) args))) (define (oo-ensure-function-wrapped funcname) (let ((shadow (oo-wrapped-var funcname))) (when (or (not (boundp shadow)) (not (eq (symbol-value funcname) (symbol-value shadow)))) (let ((wrapper (oo-gen-wrapper (oo-wrappers-var funcname))) (wrappers-var (oo-wrappers-var funcname))) (oo-set-wrapper-func! wrappers-var nil (symbol-value funcname)) (set-symbol-value! funcname wrapper) (set-symbol-value! shadow wrapper))))) (define (oo-unwrapped funcname) (let ((wrappers-var (oo-wrappers-var funcname))) (if (boundp wrappers-var) (cdar (last (symbol-value wrappers-var))) (symbol-value funcname)))) (defmac (define-wrapper form) ;; (define-wrapper (FUNCTION ARG ...) WRAPPER-NAME . BODY) (let ((func (car (cadr form))) (args (cdr (cadr form))) (name (car (cddr form))) (body (cdr (cddr form)))) (let ((wrappers-var (oo-wrappers-var func))) (unless (boundp wrappers-var) (set-symbol-value! wrappers-var (list (cons nil (symbol-value func)))) (oo-ensure-function-wrapped func)) `(oo-set-wrapper-func! (quote ,wrappers-var) (quote ,name) (lambda ,args (let ((next-func (lambda () (oo-next-wrapper-func ,wrappers-var (quote ,name))))) ,@body)))))) ;;; Parameter wrapping (define (oo-param-wrappers-var param-name) (when (consp param-name) (set! param-name (car param-name))) (intern (string-append param-name "!P!wrappers"))) (define oo-Param.get-wrapper-enabled t) (define-wrapper (Param.get name) Param.get-wrapper (let ((wrappers-var (oo-param-wrappers-var name))) (if (and (boundp wrappers-var) oo-Param.get-wrapper-enabled) ((oo-first-wrapper-func (symbol-value wrappers-var))) ((next-func) name)))) (defmac (Param.wrap form) ;; (Param.wrap PARAM-NAME WRAPPER-NAME . BODY) (let* ((param-name (nth 1 form)) (wrapper-name (nth 2 form)) (body (nth_cdr 3 form)) (wrappers-var (oo-param-wrappers-var param-name))) (unless (boundp wrappers-var) (set-symbol-value! wrappers-var (list (cons nil (lambda () (set! oo-Param.get-wrapper-enabled nil) (unwind-protect* (Param.get param-name) (set! oo-Param.get-wrapper-enabled t))))))) `(oo-set-wrapper-func! (quote ,wrappers-var) (quote ,wrapper-name) (lambda () (let ((next-value (lambda () ((oo-next-wrapper-func ,wrappers-var (quote ,wrapper-name)))))) ,@body))))) ;;; Variables (defvar oo-glet-stack '()) (define (oo-push-let-value var) (push (cons var (symbol-value var)) oo-glet-stack)) (define (oo-pop-let-value var) (cond ((null oo-glet-stack) (error "No restore value on the variable stack")) ((not (eq? (caar oo-glet-stack) var)) (error "Variable stack mismatch")) (t (cdr (pop oo-glet-stack))))) (defmac (glet* form) (let ((bindings (nth 1 form)) (body (nth_cdr 2 form))) (if bindings (let* ((spec (car bindings)) (var (car spec)) (value (cadr spec))) `(begin (oo-push-let-value (quote ,var)) (unwind-protect* (begin (set! ,var ,value) (glet* ,(cdr bindings) ,@body)) (set! ,var (oo-pop-let-value (quote ,var)))))) `(begin ,@body)))) ;;; Announce (provide 'oo) festival-freebsoft-utils-0.10/prosody-param.scm0000644000175000017500000002141111075611374020011 0ustar pdmpdm;;; Changing prosody parameters ;; Copyright (C) 2004, 2006, 2008 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'util) (defvar prosody-testing-word "babebibobub") ;;; Prosody parameter accessors (define (prosody-get-pitch) ;; This is now easy thing, there are many intonation methods in Festival, ;; more methods can be added and the Int_Target_Method parameter can be ;; wrapped (cond ((prosody-general-method?) (or (avalue-get 'f0_mean int_general_params) (prosody-general-pitch))) ((prosody-lr-method?) (avalue-get 'target_f0_mean int_lr_params)) ((prosody-simple-method?) (avalue-get 'f0_mean int_simple_params)))) (define (prosody-set-pitch value) (cond ((prosody-general-method?) (if (avalue-get 'f0_mean int_general_params) (set! int_general_params (assoc-set int_general_params 'f0_mean (list value))) (prosody-set-general-pitch value))) ((prosody-lr-method?) (set! int_lr_params (assoc-set int_lr_params 'target_f0_mean (list value)))) ((prosody-simple-method?) (set! int_simple_params (assoc-set int_simple_params 'f0_mean (list value)))))) (define (prosody-get-pitch-range) (cond ((prosody-general-method?) (or (avalue-get 'f0_std int_general_params) (prosody-general-pitch-range))) ((prosody-lr-method?) (avalue-get 'target_f0_std int_lr_params)) ((prosody-simple-method?) (avalue-get 'f0_mean int_simple_params)))) (define (prosody-set-pitch-range value) (cond ((prosody-general-method?) (if (avalue-get 'f0_std int_general_params) (set! int_general_params (assoc-set int_general_params 'f0_std (list value))) (prosody-set-general-pitch-range value))) ((prosody-lr-method?) (set! int_lr_params (assoc-set int_lr_params 'target_f0_std (list value)))) ((prosody-simple-method?) (set! int_simple_params (assoc-set int_simple_params 'f0_std (list value)))))) (defvar prosody-volume 1) (define (prosody-get-volume) prosody-volume) (define (prosody-set-volume value) (add-hook after_synth_hooks prosody-adjust-volume t) (set! prosody-volume value)) (define (prosody-get-rate) (/ 1 (Param.get 'Duration_Stretch))) (define (prosody-set-rate value) (Param.set 'Duration_Stretch (/ 1 value))) ;;; Internal utilities (defvar prosody-parameters '()) (define (prosody-change-parameter value get-func set-func min max) (let* ((old-value (get-func)) (new-value (if (eq? (typeof value) 'closure) (value old-value) value))) (cond ((> new-value max) (set! new-value max)) ((< new-value min) (set! new-value min))) (set-func new-value) old-value)) (define (prosody-adjust-volume utt) (utt.wave.rescale utt prosody-volume)) ;;; Internal utilities -- general intonation method handling (defvar prosody-voice-f0-alist '()) ; items: (VOICE PITCH RANGE) (defvar prosody-voice-pitch-factor '()) ; (CURRENT-VOICE PITCH RANGE) (defmac (define-prosody-method-test form) (let* ((method-name (nth 1 form)) (method-function-name (intern (string-append "Int_Targets_" method-name))) (function-name (intern (string-append "prosody-" (downcase method-name) "-method?")))) `(define (,function-name) (let ((int-method (Param.get 'Int_Target_Method))) (or (eq? int-method ,method-function-name) (equal? int-method (quote ,method-function-name)) (equal? (Param.get 'Int_Method) ,method-name)))))) (define-prosody-method-test "General") (define-prosody-method-test "LR") (define-prosody-method-test "Simple") (define (prosody-general-base-f0) (or (second (assoc current-voice prosody-voice-f0-alist)) (let ((orig-targ-func (avalue-get 'targ_func int_general_params)) (pitch-list '())) (avalue-set! 'targ_func int_general_params (lambda (utt syl) (let ((result (orig-targ-func utt syl))) (set! pitch-list (append pitch-list (mapcar cadr result))) result))) (unwind-protect* (SynthText prosody-testing-word) (avalue-set! 'targ_func int_general_params orig-targ-func)) (set! pitch-list (or (butlast (cdr pitch-list)) '(100))) (let* ((n (length pitch-list)) (pitch (/ (apply + pitch-list) n)) (range (/ (apply + (mapcar (lambda (p) (abs (- p pitch))) pitch-list)) n))) (set! prosody-voice-f0-alist (assoc-set prosody-voice-f0-alist current-voice (list pitch range))) pitch)))) (define (prosody-general-f0-range) (prosody-general-base-f0) (third (assoc current-voice prosody-voice-f0-alist))) (define (prosody-general-pitch) (* (prosody-general-base-f0) (prosody-current-voice-pitch-factor))) (define (prosody-general-pitch-range) (* (prosody-general-f0-range) (prosody-current-voice-pitch-range-factor))) (define (prosody-current-voice-pitch-factor) (when (or (null? prosody-voice-pitch-factor) (not (equal? current-voice (first prosody-voice-pitch-factor)))) (set! prosody-voice-pitch-factor (list current-voice 1 1))) (second prosody-voice-pitch-factor)) (define (prosody-current-voice-pitch-range-factor) (prosody-current-voice-pitch-factor) ; ensure the factor is defined (third prosody-voice-pitch-factor)) (define (prosody-ensure-targ-func-wrapped) (unless (assoc 'prosody-wrapper-enabled int_general_params) (prosody-general-base-f0) ; store original base f0 (let ((orig-func (avalue-get 'targ_func int_general_params))) (avalue-set! 'targ_func int_general_params (lambda (utt syl) (prosody-change-general-pitch utt syl orig-func))) (set! int_general_params (cons '(prosody-wrapper-enabled t) int_general_params))))) (define (prosody-set-general-pitch freq) (prosody-ensure-targ-func-wrapped) (set! prosody-voice-pitch-factor (list current-voice (/ freq (prosody-general-base-f0)) (or (third prosody-voice-pitch-factor) 1)))) (define (prosody-set-general-pitch-range range) (prosody-ensure-targ-func-wrapped) (set! prosody-voice-pitch-factor (list current-voice (or (second prosody-voice-pitch-factor) 1) (/ range (prosody-general-f0-range))))) (define (prosody-change-general-pitch utt syl next-func) (let ((base-pitch (prosody-general-base-f0)) (pitch-factor (prosody-current-voice-pitch-factor)) (range-factor (prosody-current-voice-pitch-range-factor))) (mapcar (lambda (spec) (cons (first spec) (cons (* pitch-factor (+ base-pitch (* range-factor (- (second spec) base-pitch)))) (cddr spec)))) (next-func utt syl)))) ;;; Exported functions (define (prosody-shifted-value shift) (lambda (x) (+ shift x))) (define (prosody-relative-value coef) (lambda (x) (* coef x))) (define (set-pitch pitch) ;; Hz or a function (prosody-change-parameter pitch prosody-get-pitch prosody-set-pitch 50 500)) (define (set-pitch-range pitch-range) ;; mean-in-% or a function (prosody-change-parameter pitch-range prosody-get-pitch-range prosody-set-pitch-range 0 100)) (define (set-volume volume) ;; 0..1 or a function (prosody-change-parameter volume prosody-get-volume prosody-set-volume 0 1)) (define (set-rate rate) ;; 0+..1..inf- or a function (prosody-change-parameter rate prosody-get-rate prosody-set-rate 0.1 10)) (define (change-prosody function param) (prog1 (function param) (set! prosody-parameters (assoc-set prosody-parameters function param)))) (define (restore-prosody) (let ((parameters prosody-parameters)) (while parameters ((caar parameters) (cdar parameters)) (set! parameters (cdr parameters))))) (define (reset-prosody) (set! prosody-parameters '())) (provide 'prosody-param) festival-freebsoft-utils-0.10/punctuation.scm0000644000175000017500000001412511075611374017571 0ustar pdmpdm;;; Punctuation modes ;; Copyright (C) 2003, 2004, 2005, 2006, 2008 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'oo) (require 'word-mapping) (defvar punctuation-mode 'default) (defvar punctuation-chars "[- !\"#$%&'()*+,./\\\\^_`:;<=>?@{|}~]") (defvar punctuation-chars-2 "[][]") (defvar punctuation-punc-languages '(english britishenglish americanenglish)) ;; Default English voice doesn't have defined pronunciation of punctuation ;; characters (defvar punctuation-pronunciation '(("." "dot") ("," "comma") (";" "semicolon") (":" "colon") ("!" "exclamation" "mark") ("?" "question" "mark") ("-" "dash") ("'" "right" "quote") ("`" "left" "quote") ("\"" "double" "quote") ("(" "left" "parenthesis") (")" "right" "parenthesis") ("{" "left" "brace") ("}" "right" "brace"))) (define (punctuation-character string) (or (string-matches string punctuation-chars) (string-matches string punctuation-chars-2))) (define (punctuation-split-token token name ttw) ;; We must be careful not to discard whole token here. It may contain ;; annotations such as index marks and they would be discarded together with ;; the token. (let ((words (punctuation-split-token* token name ttw))) (or words (ttw token (if (eq punctuation-mode 'all) "" " "))))) (define (punctuation-split-token* token name ttw) (cond ;; No punctuation ((and (not (string-matches name (string-append ".*" punctuation-chars ".*"))) (not (string-matches name (string-append ".*" punctuation-chars-2 ".*")))) (ttw token name)) ;; Punctuation at start ((punctuation-character (substring name 0 1)) (append (if (eq? punctuation-mode 'all) (ttw token (substring name 0 1))) (punctuation-split-token token (substring name 1 (- (length name) 1)) ttw))) ;; Punctuation inside (t (let ((i 1)) (while (not (punctuation-character (substring name i 1))) (set! i (+ i 1))) (append (ttw token (substring name 0 i)) (punctuation-split-token token (substring name i (- (length name) i)) ttw)))))) (define-wrapper (token_to_words token name) punctuation (if (eq? punctuation-mode 'default) ((next-func) token name) (punctuation-split-token token name (next-func)))) (define (punctuation-process-words utt) (cond ((eq? punctuation-mode 'all) (if (member (intern (Param.get 'Language)) punctuation-punc-languages) ;; Standard English lexicon has no notion of punctuation pronounciation (do-relation-items (w utt Word) (let ((trans (assoc (item.name w) punctuation-pronunciation))) (if (and trans (not (word-mapping-of w))) (begin (item.set_name w (car (cdr trans))) (set! trans (cdr (cdr trans))) (while trans (let ((i (item.insert w (list (car trans))))) (item.append_daughter (item.parent (item.relation w 'Token)) i)) (set! trans (cdr trans))))))) ;; We assume other languages don't insert punctuation words themselves (do-relation-items (w utt Word) (let* ((w* (item.relation w 'Token)) (token (item.parent w*))) (when (and (not (item.prev w*)) (item.has_feat token 'prepunctuation)) (dolist (p (reverse (symbolexplode (item.feat token 'prepunctuation)))) (let ((i (item.insert w `(,p ((name ,p))) 'before))) (item.prepend_daughter token i)))) (when (and (not (item.next w*)) (item.has_feat token 'punc)) (dolist (p (reverse (symbolexplode (item.feat token 'punc)))) (let ((i (item.insert w `(,p ((name ,p)))))) (item.append_daughter token i)))))))) ;; Delete punctuation when punctuation-mode is none ;; (We actually don't delete the words as this might discard annotations ;; such as index marks. So we just make the word names empty.) ((eq punctuation-mode 'none) (do-relation-top-items (token utt Token) (if (punctuation-character (item.name token)) (dolist (w (mapcar (lambda (i) (item.relation i 'Word)) (item.daughters token))) (if w (item.set_feat w 'name ""))))) (do-relation-top-items (w utt Word) (if (punctuation-character (item.name w)) (item.set_feat w 'name ""))))) utt) (Param.wrap Token_Method punctuation (lambda (utt) (apply* (next-value) (list utt)) (punctuation-process-words utt))) (Param.wrap Word_Method punctuation ;; This is here to avoid deletion of punctuation in standard functions (lambda (utt) (if (eq? punctuation-mode 'all) (do-relation-items (w utt Word) (if (string-matches (item.feat w 'pos) "f?punc") (item.set_feat w 'pos 'allpunc)))) (apply* (next-value) (list utt)))) (define (set-punctuation-mode mode) (or (member mode '(default all none)) (error "Unknown punctuation mode" mode)) (oo-ensure-function-wrapped 'token_to_words) (set! punctuation-mode mode)) (provide 'punctuation) festival-freebsoft-utils-0.10/recode.scm0000644000175000017500000000322611075611374016461 0ustar pdmpdm;;; Character set conversions ;; Copyright (C) 2004, 2005, 2006, 2008 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'fileio) (define (recode string from to) (if (string-equal string "") string (with-temp-file-data (tmpfile string) (with-temp-file out-tmpfile (system (format nil "iconv -c -f %s -t %s//TRANSLIT -o %s %s" from to out-tmpfile tmpfile)) (read-file out-tmpfile))))) (defvar recode-special-utf8-translations '(("​" " "))) (define (recode-utf8->current string) (let ((translations recode-special-utf8-translations)) (while translations (let ((translation (car translations))) (set! string (string-replace string (car translation) (cadr translation)))) (set! translations (cdr translations)))) (let ((coding (current-voice-coding))) (if (eq? coding 'utf-8) string (recode string 'utf-8 coding)))) (provide 'recode) festival-freebsoft-utils-0.10/speech-dispatcher.scm0000644000175000017500000001676211075611374020624 0ustar pdmpdm;;; Speech Dispatcher interface ;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'cap-signalization) (require 'events) (require 'multiwave) (require 'prosody-param) (require 'punctuation) (require 'spell-mode) (require 'ssml-mode) (require 'util) (require 'voice-select) (defvar speechd-base-pitch nil) (defvar speechd-spelling nil) (define (speechd-set-lang-voice lang voice) (let* ((voice* (downcase voice)) (name (or voice t)) (gender (cond ((string-matches voice* ".*female.*") 'female) ((string-matches voice* ".*male.*") 'male) (t t))) (age (if (string-matches voice* "child.*") 8 40)) (variant (if (string-matches voice* ".*[0-9]") (substring voice* (- (length voice*) 1) 1) t))) (if (eq? lang t) (begin (voice.select name) (set! voice-select-current-defaults (mapcar (lambda (item) (if (eq? (car item) 'name) (list 'name name) item)) voice-select-defaults))) (select-voice* lang gender age variant name)) (set! speechd-base-pitch (prosody-get-pitch)) (restore-prosody) (current-voice-coding))) (define (speechd-send-to-client wave) (if (or (symbol? wave) (not wave)) wave (let ((file-type (Param.get 'Wavefiletype))) (Param.set 'Wavefiletype 'nist) (unwind-protect* (utt.send.wave.client wave) (Param.set 'Wavefiletype file-type))))) (define (speechd-maybe-send-to-client wave) (unless speechd-multi-mode (speechd-send-to-client wave))) (define (speechd-event-synth type value) ((if speechd-multi-mode multi-synth event-synth) type value)) (define (speechd-refresh-modes) (set-punctuation-mode punctuation-mode) (set-cap-signalization-mode cap-signalization-mode)) (define-wrapper (ssml-change-voice . args) speechd-ssml-change-voice (let ((result (apply (next-func) args))) (speechd-refresh-modes) result)) ;;; Commands (defvar speechd-multi-mode nil) (define (speechd-enable-multi-mode mode) "(speechd-set-punctuation-mode MODE) Enable (if MODE is non-nil) or disable (if MODE is nil) sending multiple synthesized wave forms." (set! speechd-multi-mode mode)) (define (speechd-next*) (unless speechd-multi-mode (error "Not in multi mode")) (let ((wave (if speechd-spelling (begin (spell_init_func) (unwind-protect (prog1 (multi-next) (spell_exit_func)) (spell_exit_func))) (multi-next)))) (cond ((symbol? wave) wave) (wave (wave-utt wave)) (t nil)))) (define (speechd-next) "(speechd-next) Return next synthesized wave form." (let ((utt (speechd-next*))) (when utt (speechd-send-to-client utt)))) (define (speechd-speak* text) (set! speechd-spelling nil) (speechd-event-synth 'text (recode-utf8->current text))) (define (speechd-speak text) "(speechd-speak TEXT) Speak TEXT." (speechd-maybe-send-to-client (speechd-speak* text))) (define (speechd-speak-ssml* ssml-text) (set! speechd-spelling nil) (oo-ensure-function-wrapped 'ssml-change-voice) (speechd-event-synth 'ssml ssml-text)) (define (speechd-speak-ssml ssml-text) "(speechd-speak-ssml SSML-TEXT) Speak SSML-TEXT." (speechd-maybe-send-to-client (speechd-speak-ssml* ssml-text))) (define (speechd-spell* ssml-text) (oo-ensure-function-wrapped 'ssml-change-voice) (set! speechd-spelling t) (spell_init_func) (unwind-protect (prog1 (speechd-event-synth 'ssml ssml-text) (spell_exit_func)) (spell_exit_func))) (define (speechd-spell text) "(speechd-spell SSML-TEXT) Spell SSML-TEXT." (speechd-maybe-send-to-client (speechd-spell* text))) (define (speechd-sound-icon* name) (set! speechd-spelling nil) (speechd-event-synth 'logical name)) (define (speechd-sound-icon name) "(speechd-sound-icon NAME) Play the sound or text bound to the sound icon named by the symbol NAME." (speechd-maybe-send-to-client (speechd-sound-icon* name))) (define (speechd-character* character) (set! speechd-spelling nil) (speechd-event-synth 'character (recode-utf8->current character))) (define (speechd-character character) "(speechd-character CHARACTER) Speak CHARACTER, represented by a string." (speechd-maybe-send-to-client (speechd-character* character))) (define (speechd-key* key) (set! speechd-spelling nil) (speechd-event-synth 'key (recode-utf8->current key))) (define (speechd-key key) "(speechd-key KEY) Speak KEY, represented by a string." (speechd-maybe-send-to-client (speechd-key* key))) (define (speechd-set-language language) "(speechd-set-language language) Set current language to LANGUAGE, where LANGUAGE is the language ISO code, given as a two-letter string." (speechd-set-lang-voice language "male1")) (define (speechd-set-punctuation-mode mode) "(speechd-set-punctuation-mode MODE) Set punctuation mode to MODE, which is one of the symbols `all' (read all punctuation characters), `none' (don't read any punctuation characters) or `some' (default reading of punctuation characters)." (if (eq? mode 'some) (set! mode 'default)) (set-punctuation-mode mode)) (define (speechd-set-voice voice) "(speechd-set-voice VOICE) Set voice, which is one of the Speech Dispatcher voice strings." (speechd-set-lang-voice nil voice)) (define (speechd-set-festival-voice name) (speechd-set-lang-voice t name)) (define (speechd-set-rate rate) "(speechd-set-rate RATE) Set speech RATE, which must be a number in the range -100..100." ;; Stretch the rate to the interval 0.5..2 in such a way, that: ;; f(-100) = 0.5 ; f(0) = 1 ; f(100) = 2 (change-prosody set-rate (pow 2 (/ rate 100.0)))) (define (speechd-set-pitch pitch) "(speechd-set-pitch PITCH) Set speech PITCH, which must be a number in the range -100..100." ;; Stretch the pitch to the interval 0.5*P..2*P, where P is the default pitch ;; of the voice, in such a way, that: ;; f(-100) = 0.5*P ; f(0) = P ; f(100) = 2*P (unless speechd-base-pitch (set! speechd-base-pitch (prosody-get-pitch))) (let ((relative-pitch (pow 2 (/ pitch 100.0)))) (change-prosody set-pitch (* relative-pitch speechd-base-pitch)))) (define (speechd-set-capital-character-recognition-mode mode) "(speechd-set-capital-character-recognition-mode MODE) Enable (if MODE is non-nil) or disable (if MODE is nil) capital character recognition mode." (set-cap-signalization-mode mode)) (define (speechd-list-voices) "(speechd-list-voices) Return the list of the voice names (represented by strings) available for the current language." (current-language-voices)) festival-freebsoft-utils-0.10/spell-mode.scm0000644000175000017500000000347211075611374017264 0ustar pdmpdm;;; Spelling mode ;; Copyright (C) 2003, 2004 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'util) (defvar spell-orig-token.singlecharsymbols nil) (defvar spell-orig-pos-method nil) (defvar spell-mode nil) (define (spell-pos utt) (do-relation-items (w utt Word) (item.set_feat w 'pos 'sym)) utt) (define (spell_init_func) (set! spell-orig-token.singlecharsymbols token.singlecharsymbols) (set! token.singlecharsymbols "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ") (set! spell-orig-pos-method (Param.get 'POS_Method)) (Param.set 'POS_Method spell-pos) (set! spell-mode t)) (define (spell_exit_func) (set! token.singlecharsymbols spell-orig-token.singlecharsymbols) (Param.set 'POS_Method spell-orig-pos-method) (set! spell-mode nil)) (set! tts_text_modes (cons (list 'spell (list (list 'init_func spell_init_func) (list 'exit_func spell_exit_func))) tts_text_modes)) (provide 'spell-mode) festival-freebsoft-utils-0.10/ssml-mode.scm0000644000175000017500000005502411075611374017123 0ustar pdmpdm;;; Speech Synthesis Markup Language 1.0 support ;; Copyright (C) 2004, 2005, 2006, 2008 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ;; speak: supported ;; lexicon: ignored (no reasonable specification of the element) ;; meta: ignored (no reasonable use here known) ;; metadata: ignored (no reasonable use here known) ;; p: supported ;; s: supported ;; say-as: trivially rendered (attribute values undefined in the standard); ;; special value detail="spell" ;; phoneme: unsupported ;; sub: supported ;; voice: supported, but prosody not yet retained (TODO) ;; emphasis: not properly supported (TODO) ;; break: partially supported (TODO) ;; prosody: partially supported (TODO) ;; audio: supported (TODO more complicated alternative text may fail to render) ;; mark: supported ;; desc: ignored (no reasonable use here known) (require 'duration) (require_module 'rxp) (require 'prosody-param) (require 'recode) (require 'spell-mode) (require 'tokenize) (require 'util) (require 'voice-select) ;;; User configurable features (defvar ssml-break-values '((none 0.0) (x-weak 0.01) (weak 0.05) (medium 0.1) (strong 0.2) (x-strong 0.5))) (defvar ssml-pitch-values '((x-low 70) (low 100) (medium 130) (high 170) (x-high 220) (default 130))) (defvar ssml-range-values '((x-low 0) (low 2) (medium 5) (high 10) (x-high 20) (default 5))) (defvar ssml-rate-values '((x-slow 0.5) (slow 0.7) (medium 1.0) (fast 1.5) (x-fast 2.0) (default 1.0))) (defvar ssml-volume-values '((silent 0) (x-soft 0.2) (soft 0.4) (medium 0.6) (loud 0.8) (x-loud 1.0) (default 1.0))) ;;; Auxiliary functions (defvar ssml-base-uri nil) (define (ssml-attval attlist att) (let ((attval (car (xxml_attval att attlist)))) (if attval (recode-utf8->current (string-append attval))))) (define (ssml-attval-time attlist att) (let ((time (string-before (ssml-attval attlist 'time) "s"))) (and time (not (equal? time "")) (let ((ms-time (string-before time "m"))) (if (equal? ms-time "") (read-from-string time) (* (read-from-string ms-time) 0.001)))))) (define (ssml-val-complex value alist) (cond ((string-matches value "[a-z].*") (cadr (assoc_string value alist))) ((or (string-matches value "[0-9]+\\(\\.\\([0-9]+\\)?\\)?") (string-matches value "\\.[0-9]+")) (read-from-string value)) (t (when (string-matches value "\\+.*") (set! value (string-after value "+"))) (cond ((string-matches value ".*%$") `(prosody-relative-value ,(+ 1 (* (read-from-string (string-before value "%")) 0.01)))) ((string-matches value ".*st$") `(prosody-relative-value ,(pow 2 (/ (read-from-string (string-before value "st")) 12)))) ((string-matches value ".*Hz$") `(prosody-shifted-value ,(read-from-string (string-before value "Hz")))) (t `(prosody-shifted-value ,(read-from-string value))))))) (define (ssml-attval-complex attlist att alist) (ssml-val-complex (ssml-attval attlist att) alist)) (define (ssml-current-voice) current-voice) (define (ssml-change-voice lang-code gender age variant name) (prog1 (select-voice* lang-code gender age variant name) (restore-prosody))) (define (ssml-change-language attlist) (let ((lang (ssml-attval attlist 'xml:lang))) (when lang (ssml-change-voice lang nil nil nil nil)))) (define (ssml-change-prosody utt prosody) (ssml-set-feature utt 'ssml-prosody prosody)) (define (ssml-process-prosody utt) (let* ((item (ssml-find-feature utt 'ssml-prosody)) (prosody (ssml-get-feature item 'ssml-prosody))) (while item (set! item (item.next item)) (when item (dolist (p prosody) (ssml-set-feature* utt item 'prosody p)))))) (define (ssml-get-url url tmpfile) (get_url (cond ((string-matches url "[a-z]+://.*") url) (ssml-base-uri (path-append ssml-base-uri url)) (t (string-append "file:" url))) tmpfile)) (define (ssml-set-feature* utt item feature value) (add-annotation utt item (list feature value))) (define (ssml-set-feature utt feature value) (ssml-set-feature* utt (ssml-last-token utt) feature value)) (define (ssml-feature-1 value) (second (first value))) (define (ssml-get-feature utt item feature) (remove-if (lambda (a) (not (eq? (car a) feature))) (get-annotations utt item))) (define (ssml-get-feature-1 utt item feature) (ssml-feature-1 (ssml-get-feature utt item feature))) (define (ssml-has-feature utt item feature) (ssml-get-feature utt item feature)) (define (ssml-find-feature utt feature) (let ((item (utt.relation.last utt 'Token))) (while (and item (not (ssml-has-feature utt item feature))) (set! item (item.prev item))) item)) (define (ssml-find-feature-value utt feature) (let ((item (ssml-find-feature utt feature))) (and item (ssml-get-feature utt item feature)))) (define (ssml-find-feature-value-1 utt feature) (ssml-feature-1 (ssml-find-feature-value utt feature))) (define (ssml-spread-feature utt starting-feature feature value) (let ((item (ssml-find-feature utt starting-feature))) (while item (set! item (item.next item)) (when item (ssml-set-feature* utt item feature value))))) (define (ssml-delete-feature utt item feature) (set-annotations utt item (remove-if (lambda (a) (not (eq? (car a) feature))) (get-annotations utt item)))) (define (ssml-delete-items-from-feature utt feature) (let ((item (utt.relation.last utt 'Token)) (value nil)) (while (not value) (set! value (ssml-get-feature utt item feature)) (unless value (let ((prev-item (item.prev item))) (item.delete item) (set! item prev-item)))) value)) (define (ssml-utt-text utt) (let* ((last-token (and utt (utt.relation.last utt 'Token))) (token last-token) (token-list nil)) (when last-token (while (and token (not (eq? (ssml-get-feature-1 utt token 'ssml-tag) 'noticed))) (push (item.name token) token-list) (set! token (item.prev token))) (ssml-set-feature* utt last-token 'ssml-tag 'noticed)) (apply string-append token-list))) (define (ssml-append-text utt text) (while (not (string-equal text "")) (set! text (get-token utt text)))) (define (ssml-last-token utt) (or (utt.relation.last utt 'Token) (token-utterance-append utt "" "" "" "" 'Token))) ;;; Synthesis handlers ;; Breaks: Ensure they are present wherever needed. (define-wrapper (Classic_Pauses utt) ssml-classic-pauses (do-relation-top-items (token utt Token) (when (ssml-has-feature utt token 'ssml-break) (let ((token* token)) (while (and token* (not (item.daughtern token*))) (set! token* (item.prev token*))) (when token* (item.set_feat (item.daughtern token*) 'pbreak "B"))))) ((next-func) utt)) ;; Breaks: Adjust silence durations. (define-wrapper (Duration utt) ssml-duration ((next-func) utt) (let ((token (utt.relation utt 'Token))) (if (and token (ssml-has-feature utt token 'ssml-break)) (let ((length (apply + (mapcar second (ssml-get-feature utt token 'ssml-break)))) (starting-token token)) (set! token (item.next token)) (while (and token (not (item.daughtern token))) (when (ssml-has-feature utt token 'ssml-break) (set! length (+ length (apply + (mapcar second(ssml-get-feature utt token 'ssml-break)))))) (set! token (item.next token))) (while (and starting-token (and (not item.daughtern starting-token))) (set! starting-token (item.prev starting-token))) (when starting-token (let* ((seg find_last_seg (item.daughtern starting-token)) (silence (and seg (item.next seg)))) (when silence ;; The final step remains unimplemented for now. ;; We should adjust features of all the following segments here. (sslm-set-feature utt silence 'ssml-duration length))))) (set! token (item.next token)))) utt) ;;; Markup handlers (define (ssml.speak.start attlist utt) (set! ssml-base-uri (ssml-attval attlist 'xml:base)) (ssml-change-voice nil nil nil nil nil) nil) (define (ssml.speak.end attlist utt) nil) (define (ssml.lexicon attlist utt) nil) (define (ssml.meta attlist utt) nil) (define (ssml.metadata.start attlist utt) nil) (define (ssml.metadata.end attlist utt) nil) (define (ssml.p.start attlist utt) nil) (define (ssml.p.end attlist utt) nil) (define (ssml.s.start attlist utt) nil) (define (ssml.s.end attlist utt) nil) (define (ssml.say-as.start attlist utt) (if (string-equal (ssml-attval attlist 'detail) "spell") (begin (ssml-set-feature utt 'ssml-say-as 'spell) (spell_init_func)) (ssml-set-feature utt 'ssml-say-as 'dummy))) (define (ssml.say-as.end attlist utt) (let* ((item (ssml-find-feature utt 'ssml-say-as)) (value (ssml-get-feature-1 utt item 'ssml-say-as))) (ssml-delete-feature utt item 'ssml-say-as) (when (string-equal value 'spell) (unless (string-equal (ssml-find-feature-value-1 utt 'ssml-say-as) 'spell) (spell_exit_func)))) nil) (define (ssml.phoneme.start attlist utt) nil) (define (ssml.phoneme.end attlist utt) nil) (define (ssml.sub.start attlist utt) (let ((text (format nil "%s" (ssml-attval attlist 'alias)))) (ssml-set-feature utt 'ssml-sub text)) nil) (define (ssml.sub.end attlist utt) (ssml-append-text utt (ssml-feature-1 (ssml-delete-items-from-feature utt 'ssml-sub)))) (define (ssml.voice.start attlist utt) (apply ssml-change-voice (mapcar (lambda (att) (ssml-attval attlist att)) '(xml:lang gender age variant name)))) (define (ssml.voice.end attlist utt) nil) (define (ssml.break attlist utt) ;; TODO: Process the assigned time breaks in pause and duration processing (let* ((strength (or (ssml-attval attlist 'strength) 'medium)) (time (string-before (ssml-attval attlist 'time) "s")) (length (if (and time (not (equal? time ""))) (let ((ms-time (string-before time "m"))) (if (equal? ms-time "") (read-from-string time) (* (read-from-string ms-time) 0.001))) (cadr (assoc_string strength ssml-break-values))))) (when length (ssml-set-feature utt 'ssml-break length))) nil) (define (ssml.emphasis.start attlist utt) (ssml-change-prosody utt `((pitch ,(prosody-relative-value 1.1)) (rate ,(prosody-relative-value 0.8)))) nil) (define (ssml.emphasis.end attlist utt) (ssml-process-prosody utt) nil) (define (ssml.prosody.start attlist utt) (let* ((pitch (ssml-attval-complex attlist 'pitch ssml-pitch-values)) (contour (ssml-attval attlist 'contour)) (range (ssml-attval-complex attlist 'range ssml-range-values)) (rate (ssml-attval-complex attlist 'rate ssml-rate-values)) (duration (ssml-attval-time attlist 'duration)) (volume (ssml-attval-complex attlist 'volume ssml-volume-values)) (prosody '()) (set-param (lambda (id value) (push (list id value) prosody)))) (when volume (set-param 'volume volume)) (cond (duration ;; TODO: implement ) (rate (set-param 'rate rate))) (if contour (let ((values '())) (while (not (string-equal contour "")) (let* ((pair (string-after (string-before contour ")") "(")) (time (string-before pair "%")) (value (string-before (string-after pair ",") ")"))) (push (cons time (ssml-val-complex value nil)) values)) (set! contour (string-after contour ")"))) ; TODO: implement ; (set-param 'contour (reverse values)) ) (begin (when pitch (set-param 'pitch pitch)) (when range (set-param 'pitch-range range)))) (ssml-change-prosody utt prosody)) nil) (define (ssml.prosody.end attlist utt) (ssml-process-prosody utt) nil) (define (ssml.audio.start attlist utt) (ssml-set-feature utt 'ssml-audio-uri (ssml-attval attlist 'src)) nil) (define (ssml.audio.end attlist utt) (dolist (uri (mapcar second (ssml-find-feature-value utt 'ssml-audio-uri))) (let ((tmpfile (make-temp-filename "ssml-audio-%s.delete-after-play")) (sound-available nil)) (unwind-protect (begin (ssml-get-url uri tmpfile) (set! sound-available t)) (delete-file tmpfile)) (when sound-available (add-event utt (ssml-last-token utt) (list 'sound tmpfile) nil)))) (ssml-delete-items-from-feature utt 'ssml-audio-uri) nil) (define (ssml.audio attlist utt) (ssml.audio.start attlist utt) (ssml.audio.end attlist utt)) (define (ssml.mark attlist utt) (add-event utt (ssml-last-token utt) (list 'mark (ssml-attval attlist 'name)) nil) nil) (define (ssml.desc.start attlist utt) nil) (define (ssml.desc.end attlist utt) nil) (define (ssml.cdata attlist utt) ;; Dummy element representing just text. nil) ;;; Setup (defvar ssml-xxml-elements.orig nil) (defvar ssml-eou_tree.orig nil) (defvar ssml-tags '("speak" "lexicon" "meta" "metadata" "p" "s" "say-as" "phoneme" "sub" "voice" "emphasis" "break" "prosody" "audio" "mark" "desc")) (defvar ssml-parsed nil) (defvar ssml-elements (apply append (mapcar (lambda (elt) (list `(,(format nil "(%s" elt) (ATTLIST UTT) (push (list (quote ,(intern (format nil "ssml.%s.start" elt))) ATTLIST (ssml-utt-text UTT)) ssml-parsed) nil) `(,(format nil ")%s" elt) (ATTLIST UTT) (push (list (quote ,(intern (format nil "ssml.%s.end" elt))) ATTLIST (ssml-utt-text UTT)) ssml-parsed) nil) `(,(format nil "%s" elt) (ATTLIST UTT) (push (list (quote ,(intern (format nil "ssml.%s" elt))) ATTLIST (ssml-utt-text UTT)) ssml-parsed) nil))) ssml-tags))) (define (ssml_init_func) (set! ssml-xxml-elements.orig xxml_elements) (set! xxml_elements ssml-elements) (set! ssml-eou_tree.orig eou_tree) (set! eou_tree '((0))) (set! ssml-voices (list current-voice)) ;; reset-voice used to be called here, but it's not much useful and it resets ;; current speechd settings, which is not what we want. ) (define (ssml_exit_func) (voice.select (car (last ssml-voices))) (set! xxml_elements ssml-xxml-elements.orig) (set! eou_tree ssml-eou_tree.orig)) (set! tts_text_modes (cons (list 'ssml (list (list 'init_func ssml_init_func) (list 'exit_func ssml_exit_func) '(analysis_type xml) )) tts_text_modes)) ;;; Special functions (define (ssml-parse-xml ssml-text) (with-temp-file ssml-file (let ((fd (fopen ssml-file "w"))) (fwrite ssml-text fd) (fclose fd)) (tts_file ssml-file 'ssml))) (define (ssml-parse ssml-text) (set! ssml-parsed '()) (glet* ((token.singlecharsymbols "") (token.punctuation "") (token.prepunctuation "") (token.whitespace "")) (ssml-parse-xml (ssml-fix-text ssml-text))) (set! ssml-parsed (reverse ssml-parsed))) (define (ssml-fix-text text) ;; Work around Festival XML parsing bug (let ((pieces '())) (while (string-matches text ".*\\\\.*") (push (string-before text "\\") pieces) (push "\\\\" pieces) (set! text (string-after text "\\"))) (push text pieces) (apply string-append (reverse pieces)))) (define (ssml-say ssml-text) (ssml-parse ssml-text) (ssml-speak-chunks)) (define ssml-say* ssml-say) (define ssml-utterance-break-functions '(ssml.p.start ssml.p.end ssml.s.start ssml.s.end)) (define ssml-unbreakable-functions '(ssml.sub.start ssml.audio.start)) (define (ssml-next-parsed-part) (let ((open-elements '()) (next-part '()) (text "") (accepted-text "") (remaining-text "") (voice (ssml-current-voice)) (unbreakable '()) (finished nil)) ;; get next parts (while (and ssml-parsed (not finished)) (let* ((element (car ssml-parsed)) (function (first element)) (attlist (second element)) (element-text (third element)) (prev-voice voice)) (set! ssml-parsed (cdr ssml-parsed)) ;; recode text (unwind-protect (let ((orig-voice (ssml-current-voice))) (voice.select voice) (set! element-text (if (pair? element-text) (first element-text) (recode-utf8->current element-text)))) (voice.select orig-voice)) ;; add text (unless (string-equal element-text "") (set! text (string-append text element-text)) (set! remaining-text (second (next-chunk text))) (if unbreakable (begin (set! remaining-text "") (set! accepted-text element-text)) (begin ;; Attention, sometimes the whole text makes utterance break within ;; *previous* element (e.g. in "Some word. Another ;; word." (when (> (length remaining-text) (length element-text)) (set! remaining-text element-text)) (set! accepted-text (substring element-text 0 (- (length element-text) (length remaining-text)))))) (push (list 'ssml.cdata '() accepted-text) next-part)) ;; update element's text (set! element (list (first element) (second element) (if (string-equal remaining-text "") "" (list remaining-text)))) ;; utterance break (either implicit or explicit)? (when (or (not (string-equal remaining-text "")) (and (member function ssml-utterance-break-functions) (not unbreakable) ; incorrect but currently required (not (string-equal text "")))) (set! finished t)) ;; voice change? (when (and (not finished) (not unbreakable)) ;; Of course, break must be allowed on voice changed. ;; But in the current implmementation it is not. (let ((new-voice (ssml-change-language attlist))) (when (and new-voice (not (eq? new-voice voice))) (if (string-equal text "") (set! voice new-voice) (set! finished t))))) (if finished ;; finished -- return element and its remaining text to ssml-parsed (push element ssml-parsed) ;; not finished -- update open elements and next part (begin (cond ((string-matches function ".*\.start$") (push (list function attlist "" prev-voice) open-elements) (when (member function ssml-unbreakable-functions) (push t unbreakable))) ((string-matches function ".*\.end$") (let* ((closed-element (pop open-elements)) (function (first closed-element)) (restored-voice (fourth closed-element))) (when (member function ssml-unbreakable-functions) (pop unbreakable)) (unless (eq? restored-voice voice) (set! finished t))))) (push element next-part))))) ;; if tree split is necessary, finish it (when (or ssml-parsed remaining-text) (set! ssml-parsed (append (reverse open-elements) ssml-parsed))) ;; done (reverse next-part))) (define (ssml-process-parsed-part parsed) (let ((utt (token-utterance)) (orig-voice (ssml-current-voice)) (voice (ssml-current-voice))) ;; process elements (while parsed (let* ((element (car parsed)) (function (first element)) (attlist (second element)) (text (third element))) (ssml-append-text utt text) (set! voice (ssml-change-language attlist)) (set! voice (or ((symbol-value function) attlist utt) voice))) (set! parsed (cdr parsed))) ;; restore original voice and return the resulting utterance ; (voice.select orig-voice) utt)) (define (ssml-next-chunk) (let ((parsed (ssml-next-parsed-part))) (if parsed (ssml-process-parsed-part parsed) nil))) (define (ssml-play object) (if (symbol? object) (print object) (wave.play object))) (define (ssml-speak-chunks) (let ((utt (ssml-next-chunk))) (when utt (utt.synth utt) (event-eat-utt utt ssml-play) (ssml-speak-chunks)))) (provide 'ssml-mode) festival-freebsoft-utils-0.10/tokenize.scm0000644000175000017500000001336011075611374017050 0ustar pdmpdm;;; Tokenization and utterance chunking ;; Copyright (C) 2004, 2005, 2006 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'tts) (require 'spell-mode) (require 'util) (defvar max-number-of-tokens 100) (defvar max-number-of-token-chars 100) (define (token-utterance) (let ((utt (Utterance Tokens))) (utt.relation.create utt 'Token))) (define (token-utterance-append utt name whitespace punc prepunc) (token-utterance-append* utt name whitespace punc prepunc 'Token)) (define (token-utterance-append* utt name whitespace punc prepunc relation) (utt.relation.append utt relation `(,name ((name ,name) (whitespace ,whitespace) (punc ,punc) (prepunctuation ,prepunc))))) (define (get-regular-token utt text) (let* ((l-whitespace (symbolexplode token.whitespace)) (l-punc (symbolexplode token.punctuation)) (l-prepunctuation (symbolexplode token.prepunctuation)) (r-whitespace (lambda (c) (member_string c l-whitespace))) (r-punc (lambda (c) (member_string c l-punc))) (r-prepunctuation (lambda (c) (member_string c l-prepunctuation))) (r-name (lambda (c) (not (or (r-whitespace c) (r-punc c))))) (name "") (whitespace "") (punc "") (prepunctuation "") (oversized nil)) (let ((read-part (lambda (matcher) (let ((result-chars '()) (nchars 0) (char (substring text 0 1))) (while (and (not (string-equal char "")) (not oversized) (matcher char)) (set! result-chars (cons char result-chars)) (set! text (substring text 1 (- (length text) 1))) (set! nchars (+ nchars 1)) (when (>= nchars max-number-of-token-chars) (set! oversized t)) (set! char (substring text 0 1))) (apply string-append (reverse result-chars)))))) (set! whitespace (read-part r-whitespace)) (set! prepunctuation (read-part r-prepunctuation)) (set! name (read-part r-name)) (set! punc (read-part r-punc)) (while (and (not oversized) (not (string-equal text "")) (not (r-whitespace (substring text 0 1)))) (set! name (string-append name punc (read-part r-name))) (set! punc (read-part r-punc)) (when (>= (length name) max-number-of-token-chars) (set! oversized t))) ;; Presence of empty words is questionable and the built-in tokenization ;; process doesn't generate them (when (string-equal name "") (cond (oversized nil) ((not (string-equal punc "")) (set! name (substring punc 0 1)) (set! punc (substring punc 1 (- (length punc) 1)))) ((not (string-equal prepunctuation "")) (set! name (substring prepunctuation 0 1)) (set! prepunctuation (substring prepunctuation 1 (- (length prepunctuation) 1)))) (t ; final whitespace -- ignored (set! text ""))))) (unless (string-equal name "") (token-utterance-append utt name whitespace punc prepunctuation)) text)) (define (get-single-char-token utt text) (let ((name (substring text 0 1))) (set! text (substring text 1 (length text))) (unless (string-equal name "") (token-utterance-append utt name "" "" ""))) text) (define (get-token utt text) ((if spell-mode get-single-char-token get-regular-token) utt text)) (define (next-chunk text) (let ((utt (token-utterance)) (finished nil) (ntokens 1)) (while (not finished) (let* ((new-text (get-token utt text)) (token (utt.relation.last utt 'Token)) (ptoken (item.prev token))) (cond ((string-equal new-text "") (set! text "") (set! finished t)) ((and ptoken (string-equal (wagon_predict ptoken eou_tree) 1)) (item.delete token) (set! finished t)) ((>= ntokens max-number-of-tokens) ;; This could be handled (probably less efficiently) by eou_tree, but ;; we don't want to touch the tree just because of this (set! text new-text) (set! finished t)) (t (set! text new-text) (set! ntokens (+ ntokens 1)))))) (list utt text))) (define (append-token-utterances . utts) (let ((u (token-utterance))) (while utts (let ((i (utt.relation (car utts) 'Token))) (while i (token-utterance-append u (item.name i) (item.feat i 'whitespace) (item.feat i 'punc) (item.feat i 'prepunctuation)) (set! i (item.next i)))) (set! utts (cdr utts)))) u) (provide 'tokenize) festival-freebsoft-utils-0.10/util.scm0000644000175000017500000001467311075611374016205 0ustar pdmpdm;;; Miscellaneous utilities ;; Copyright (C) 2003, 2004, 2005, 2006, 2008 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ;;; Commonly used Lisp constructs (defmac (when form) `(if ,(cadr form) (begin ,@(cddr form)))) (defmac (unless form) `(if (not ,(cadr form)) (begin ,@(cddr form)))) (defmac (prog1 form) `(let ((result ,(cadr form))) ,@(cddr form) result)) (define (let*-bindings bindings body) (if bindings `(let (,(car bindings)) ,(let*-bindings (cdr bindings) body)) `(progn ,@body))) (defmac (let* form) (let ((bindings (cadr form)) (body (cddr form))) (let*-bindings bindings body))) (defmac (unwind-protect* form) (let ((protected-form (nth 1 form)) (cleanup-forms (nth_cdr 2 form))) `(unwind-protect (prog1 ,protected-form ,@cleanup-forms) (begin ,@cleanup-forms)))) (define (first list) (car list)) (define (second list) (cadr list)) (define (third list) (nth 2 list)) (define (fourth list) (nth 3 list)) (define (butlast list) (if (null? (cdr list)) '() (cons (car list) (butlast (cdr list))))) (define (min x y) (if (< x y) x y)) (define (max x y) (if (>= x y) x y)) (define (abs x) (if (>= x 0) x (- 0 x))) (define (remove-if test list) (let ((result '())) (while list (let ((elt (car list))) (unless (test elt) (push elt result))) (set! list (cdr list))) (reverse result))) (define (identity x) x) (define (complement func) (lambda args (not (apply func args)))) (define (apply* function list) (apply (if (eq? (typeof function) 'string) (intern function) function) list)) (defmac (dolist form) (let ((var (first (nth 1 form))) (items (second (nth 1 form))) (body (nth_cdr 2 form))) `(mapcar (lambda (,var) ,@body) ,items))) ;;; General utilities (defmac (add-hook form) (let ((hook-var (nth 1 form)) (hook (nth 2 form)) (to-end? (nth 3 form))) `(if (member ,hook ,hook-var) ,hook-var (set! ,hook-var (if ,to-end? (append ,hook-var (list ,hook)) (cons ,hook ,hook-var)))))) (define (assoc-set lst key value) (cons (cons key value) (remove (assoc key lst) lst))) (define (avalue-get key alist) (cadr (assoc_string key alist))) (define (avalue-set! key alist value) (set-cdr! (assoc_string key alist) (list value)) alist) (define (avg . args) (let ((n (length args))) (if (<= n 0) 0 (/ (apply + args) n)))) (define (dirname path) (path-as-directory (substring path 0 (- (length path) (length (basename path)))))) ;; There is a bug in speech-tools preventing it to honor $TMPDIR. ;; We can work around the bug by setting some other environment variables. (let ((tempdir (getenv "TMPDIR"))) (when (and tempdir (not (equal? tempdir ""))) (setenv "TEMP" tempdir) (setenv "TMP" tempdir))) (define (make-temp-filename template) (let ((tmp-name (string-append (make_tmp_filename) "%d"))) (set! template (format nil "%s%s" (dirname tmp-name) (format nil template (basename tmp-name)))) (let* ((i 0) (format-name (lambda (i) (format nil template i))) (name (format-name i)) (max-attempts 1000)) (while (and (< i max-attempts) (probe_file name)) (set! i (+ i 1)) (set! name (format-name i))) (if (eqv? i max-attempts) (error "Temporary file not created" nil)) name))) (defmac (with-temp-file form) (let ((filename (nth 1 form)) (body (nth_cdr 2 form))) `(let ((,filename (make-temp-filename "ffu%s"))) (unwind-protect* (begin ,@body) (delete-file ,filename))))) (define (string-replace string from to) (string-replace* string from to "")) (define (string-replace* string from to result) (let ((before (string-before string from))) (if (or (equal? before string) (and (equal? before "") (not (equal? (substring string 0 (length from)) from)))) (string-append result string) (string-replace* (string-after string from) from to (string-append result before to))))) ;;; Festival specific utilities (define (item.has_feat item feat) (assoc feat (item.features item))) (define (langvar symbol) (let ((lsymbol (intern (string-append symbol "." (Param.get 'Language))))) (symbol-value (if (symbol-bound? lsymbol) lsymbol symbol)))) (define (current-voice-coding) (or (cadr (assoc 'coding (cadr (voice.description current-voice)))) 'ISO-8859-1)) (define (utt-relation-top-items utt relation) (let ((items '()) (i (utt.relation.first utt relation))) (while i (push i items) (set! i (item.next i))) (reverse items))) (defmac (do-relation-items form) (let ((var (first (nth 1 form))) (utt (second (nth 1 form))) (relation (third (nth 1 form))) (body (nth_cdr 2 form))) `(dolist (,var (utt.relation.items ,utt (quote ,relation))) ,@body))) (defmac (do-relation-top-items form) (let ((var (first (nth 1 form))) (utt (second (nth 1 form))) (relation (third (nth 1 form))) (body (nth_cdr 2 form))) `(dolist (,var (utt-relation-top-items ,utt (quote ,relation))) ,@body))) (define (get-annotations utt item) (let ((annotation-list (item.feat item 'ffu-annotation))) (if (pair? annotation-list) annotation-list '()))) (define (add-annotation utt item annotation) (item.set_feat item 'ffu-annotation (append (get-annotations utt item) (list annotation)))) (define (set-annotations utt item annotations) (item.set_feat item 'ffu-annotation annotations)) (provide 'util) festival-freebsoft-utils-0.10/voice-select.scm0000644000175000017500000001537511075611374017612 0ustar pdmpdm;;; Selecting voices ;; Copyright (C) 2004, 2006, 2007 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'util) ;;; User configuration (defvar language-codes '((en english (US american) (BR british)) (cs czech) (de german) (es spanish) (fi finnish) (fr french) (hi hindi) (it italian) (mr marathi) (te telugu)) "Alist mapping ISO language codes to Festival language names. Each element of the alist is of the form (LANGUAGE-CODE LANGUAGE-NAME). Optionally, elements can have an extended form (LANGUAGE-CODE LANGUAGE-NAME . DIALECTS), where DIALECTS is a list of pairs (DIALECT-CODE DIALECT-NAME).") (defvar voice-select-defaults '((language nil) (dialect nil) (gender nil) (age nil) (variant nil) (name nil)) "Alist of default voice parameters. Each entry is of the form (NAME VALUE), where VALUE can be either the actual parameter value, or `nil' meaning the value is unspecified.") ;;; Internal functions and variables (define (voice-select-code-language code) (let* ((sep (if (string-matches code ".*_.*") "_" "-")) (lang-code (string-before code sep)) (dialect-code (string-after code sep))) (when (string-equal lang-code "") (set! lang-code code) (set! dialect-code nil)) (let* ((spec (cdr (assoc_string lang-code language-codes))) (language (car spec)) (dialect (avalue-get dialect-code (cdr spec)))) (list language dialect)))) (define (voice-property voice-name property) (avalue-get property (cadr (voice.description voice-name)))) (define (voice-select-parameter name value) (cond ((eq? value t) nil) ((eq? value nil) (avalue-get name voice-select-current-defaults)) (t value))) (define (voice-select-subset pname pvalue voices) (if pvalue (remove-if (lambda (voice-name) (not (string-equal (voice-property voice-name pname) pvalue))) voices) voices)) (define (select-voice-internal voices dialect gender age variant name) (cond ;; No voice for the given language at all ((not voices) (string-after voice_default "voice_")) ;; Name has the highest priority ((member name voices) name) ;; Let's try the best match (t (let* ((dialect-voices (voice-select-subset 'dialect dialect voices)) (gender-voices (voice-select-subset 'gender gender voices)) (matching-voices (remove-if (lambda (voice-name) (not (member voice-name gender-voices))) dialect-voices)) (variant* (read-from-string variant)) (choose-variant (lambda (voices) (or (and variant* (nth (- variant* 1) voices)) (first voices))))) ;; Select variant from what remained (age is ignored) (choose-variant (or matching-voices ;; Dialect is preferred over gender dialect-voices gender-voices voices)))))) ;;; External functions and variables (defvar voice-select-current-defaults voice-select-defaults) (define (voice-list) (let ((voices-1 (voice.list)) (voices-2 (mapcar car Voice_descriptions)) (voices '())) (while voices-2 (unless (member (car voices-2) voices-1) (push (car voices-2) voices)) (set! voices-2 (cdr voices-2))) (append voices-1 (reverse voices)))) (define (voice-list-language-codes) (let ((r-language-codes (mapcar (lambda (entry) (cons (second entry) (cons (first entry) (nth_cdr 2 entry)))) language-codes))) (mapcar (lambda (voice) (let* ((language (voice-property voice 'language)) (dialect (voice-property voice 'dialect)) (language-entry (assoc language r-language-codes)) (language-code (second language-entry)) (dialects (mapcar (lambda (entry) (list (second entry) (first entry))) (nth_cdr 2 language-entry))) (dialect-code (second (assoc dialect dialects)))) (list voice language-code dialect-code))) (voice.list)))) (define (select-voice language dialect gender age variant name) (let* ((language* (voice-select-parameter 'language language)) (dialect* (voice-select-parameter 'dialect dialect)) (gender* (voice-select-parameter 'gender gender)) (age* (voice-select-parameter 'age age)) (variant* (voice-select-parameter 'variant variant)) (name* (voice-select-parameter 'name name)) (voices (voice-select-subset 'language language* (voice-list))) (voice-name (select-voice-internal voices dialect* gender* age* variant* name*))) (voice.select voice-name) (set! voice-select-current-defaults `((language ,language*) (dialect ,dialect*) (gender ,gender*) (age ,age*) (variant ,variant*) (name ,name*))) voice-name)) (define (select-voice* lang-code gender age variant name) (let ((language-dialect (if lang-code (voice-select-code-language lang-code) '(nil nil)))) (select-voice (first language-dialect) (second language-dialect) gender age variant name))) (define (reset-voice) (set! voice-select-current-defaults voice-select-defaults) (select-voice nil nil nil nil nil nil)) (define (current-language-voices) (voice-select-subset 'dialect (avalue-get 'dialect voice-select-current-defaults) (voice-select-subset 'language (avalue-get 'language voice-select-current-defaults) (voice-list)))) (provide 'voice-select) festival-freebsoft-utils-0.10/wave.scm0000644000175000017500000000464611075611374016171 0ustar pdmpdm;;; Wave data handling utilities ;; Copyright (C) 2004 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'util) (define (wave-load filename) (let ((wave (and (not (string-matches filename ".*\.ogg")) (wave.load filename)))) (when (or (not wave) (<= (cadr (assoc 'num_samples (wave.info wave))) 0)) (let ((wavfile (make-temp-filename "%s.wav"))) (system (format nil "sox %s %s" filename wavfile)) (unwind-protect* (set! wave (wave.load wavfile)) (delete-file wavfile)))) wave)) (define (wave-concat waves) (let ((first-wave (car waves))) (if (<= (length waves) 1) first-wave ;; The order of concatenation matters -- the resulting sample of ;; wave.append has parameters (rate etc.) of the first argument sample (wave-concat (cons (wave.append first-wave (cadr waves)) (cddr waves)))))) (define (wave-subwave wave from to) (let ((ifile (make_tmp_filename)) (ofile (string-append (make-temp-filename "%s.sph")))) (unwind-protect* (let ((length (- to from))) (if (<= length 0) ;; sox doesn't trim if the length argument is 0 (set! length 0.001)) (wave.save wave ifile 'nist nil) (system (format nil "sox %s %s trim %s %s" ifile ofile from length)) (wave.load ofile nil nil nil)) (delete-file ifile) (delete-file ofile)))) (define (wave-utt wave) (let ((utt (Utterance Wave nil))) (utt.relation.create utt 'Wave) (item.set_feat (utt.relation.append utt 'Wave nil) 'wave wave) utt)) (define (wave-import-utt filename) (wave-utt (wave-load filename))) (provide 'wave) festival-freebsoft-utils-0.10/word-mapping.scm0000644000175000017500000000362011075611374017622 0ustar pdmpdm;;; Mapping words to events ;; Copyright (C) 2004, 2006 Brailcom, o.p.s. ;; Author: Milan Zamazal ;; COPYRIGHT NOTICE ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; This program 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 General Public License ;; for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. (require 'oo) (defvar word-mapping '(("(" sound "guitar-13.wav") (")" sound "guitar-12.wav") ("@" sound "cembalo-6.wav")) "Alist mapping words to events. Each element of the list is of the form (WORD EVENT-TYPE EVENT-VALUE), where WORD is a string representing a word or a punctuation character and EVENT-TYPE and EVENT-VALUE are the same as in `logical-event-mapping'.") (define (word-mapping-of word) (cdr (assoc (item.name word) (langvar 'word-mapping)))) (Param.wrap Word_Method word-mapping (lambda (utt) (do-relation-items (w utt Word) (let ((event (word-mapping-of w))) (if (and event (not (item-events utt w))) (begin (item.set_name w "") (add-event utt w event (let ((tw (item.relation w 'Token))) (if (and (not (item.prev tw)) (item.next tw)) 'next 'prev))))))) (apply* (next-value) (list utt)))) (provide 'word-mapping) festival-freebsoft-utils-0.10/doc/0000755000175000017500000000000011075611374015256 5ustar pdmpdmfestival-freebsoft-utils-0.10/doc/fdl.texi0000644000175000017500000005054311075611374016725 0ustar pdmpdm@display Copyright @copyright{} 2000,2001,2002 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @end display @enumerate 0 @item PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document @dfn{free} in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of ``copyleft'', which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. @item APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The ``Document'', below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as ``you''. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A ``Modified Version'' of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A ``Secondary Section'' is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The ``Invariant Sections'' are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The ``Cover Texts'' are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A ``Transparent'' copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not ``Transparent'' is called ``Opaque''. Examples of suitable formats for Transparent copies include plain @sc{ascii} without markup, Texinfo input format, La@TeX{} input format, @acronym{SGML} or @acronym{XML} using a publicly available @acronym{DTD}, and standard-conforming simple @acronym{HTML}, PostScript or @acronym{PDF} designed for human modification. Examples of transparent image formats include @acronym{PNG}, @acronym{XCF} and @acronym{JPG}. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, @acronym{SGML} or @acronym{XML} for which the @acronym{DTD} and/or processing tools are not generally available, and the machine-generated @acronym{HTML}, PostScript or @acronym{PDF} produced by some word processors for output purposes only. The ``Title Page'' means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, ``Title Page'' means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section ``Entitled XYZ'' means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as ``Acknowledgements'', ``Dedications'', ``Endorsements'', or ``History''.) To ``Preserve the Title'' of such a section when you modify the Document means that it remains a section ``Entitled XYZ'' according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. @item VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. @item COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. @item MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: @enumerate A @item Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. @item List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. @item State on the Title page the name of the publisher of the Modified Version, as the publisher. @item Preserve all the copyright notices of the Document. @item Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. @item Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. @item Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. @item Include an unaltered copy of this License. @item Preserve the section Entitled ``History'', Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled ``History'' in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. @item Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the ``History'' section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. @item For any section Entitled ``Acknowledgements'' or ``Dedications'', Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. @item Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. @item Delete any section Entitled ``Endorsements''. Such a section may not be included in the Modified Version. @item Do not retitle any existing section to be Entitled ``Endorsements'' or to conflict in title with any Invariant Section. @item Preserve any Warranty Disclaimers. @end enumerate If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled ``Endorsements'', provided it contains nothing but endorsements of your Modified Version by various parties---for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. @item COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled ``History'' in the various original documents, forming one section Entitled ``History''; likewise combine any sections Entitled ``Acknowledgements'', and any sections Entitled ``Dedications''. You must delete all sections Entitled ``Endorsements.'' @item COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. @item AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an ``aggregate'' if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. @item TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled ``Acknowledgements'', ``Dedications'', or ``History'', the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. @item TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. @item FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See @uref{http://www.gnu.org/copyleft/}. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License ``or any later version'' applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. @end enumerate @page @appendixsubsec ADDENDUM: How to use this License for your documents To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: @smallexample @group Copyright (C) @var{year} @var{your name}. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end group @end smallexample If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the ``with...Texts.'' line with this: @smallexample @group with the Invariant Sections being @var{list their titles}, with the Front-Cover Texts being @var{list}, and with the Back-Cover Texts being @var{list}. @end group @end smallexample If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software. @c Local Variables: @c ispell-local-pdict: "ispell-dict" @c End: festival-freebsoft-utils-0.10/doc/festival-freebsoft-utils.texi0000644000175000017500000012656611075611374023121 0ustar pdmpdm\input texinfo @c -*-texinfo-*- @comment %**start of header @setfilename festival-freebsoft-utils.info @set VERSION 0.10 @settitle festival-freebsoft-utils @value{VERSION} @syncodeindex fn cp @syncodeindex ky cp @syncodeindex vr cp @comment %**end of header @copying This manual is for festival-freebsoft-utils, version @value{VERSION}. Copyright @copyright{} 2004, 2005, 2006, 2007, 2008 Brailcom, o.p.s. @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end quotation Alternatively, you can distribute this manual under the same conditions as festival-freebsoft-utils itself: @quotation festival-freebsoft-utils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. WAusers 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. @end quotation @end copying @dircategory Sound @direntry * Festival Freebsoft Utilities: (festival-freebsoft-utils). Festival utilities used by the Freebsoft project. @end direntry @titlepage @title festival-freebsoft-utils @subtitle for version @value{VERSION} @author Milan Zamazal @author Brailcom, o.p.s. @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @ifnottex @node Top @top festival-freebsoft-utils @insertcopying @end ifnottex @menu * Motivation:: What is festival-freebsoft-utils? * Installation:: How to install it. * User Customization:: Configuration variables. * Reference Manual:: Description of all available functions. * Contact:: Authors, mailing lists, Web pages. * Copying This Manual:: GNU Free Documentation License. * Index:: Concept, function and variable. @end menu @c **************************************************************************** @node Motivation @chapter Motivation @cindex Festival @cindex Speech Dispatcher Festival is a powerful and extensible speech synthesis system, able to handle the whole text-to-speech process. The aim of festival-freebsoft-utils is to further extend Festival facilities, to the level providing complete set of features required by @ref{Top,Speech Dispatcher,,speech-dispatcher,Speech Dispatcher Manual}. As a side effect, festival-freebsoft-utils introduces interesting functionality, generalizing the text-to-speech system to a text-to-sound system. Festival is well suited to the speech synthesis process itself, but lacks some end-user features, especially those needed for application sound output. festival-freebsoft-utils tries to fill this gap, thus making Festival suitable for screen readers and other speech output software, used especially by the blind and visually impaired people. Main features of festival-freebsoft-utils are: @itemize @bullet @item Generalized concept of input events. festival-freebsoft-utils allows not only plain text synthesis, but also insertion of sounds and logical event mapping. @item Spell mode. @item Capital letter signalling. @item Punctuation modes, for reading or not reading punctuation characters. @item Function wrapping support. @item Speech Dispatcher Festival output interface. For more information about Speech Dispatcher, see @url{http://www.freebsoft.org/speechd} or @ref{Top,Speech Dispatcher,,speech-dispatcher,Speech Dispatcher manual}. @end itemize @cindex home page Up-to-date information about festival-freebsoft-utils can be found at its home page @url{http://www.freebsoft.org/festival-freebsoft-utils/}. @c **************************************************************************** @node Installation @chapter Installation festival-freebsoft-utils was tested with Festival 1.4.3. Other versions of Festival may or may not work. Having SoX (@url{http://sox.sourceforge.net}) installed is strongly recommended, many festival-freebsoft-utils functions don't work without it. As Festival does not support UTF-8 encoding, festival-freebsoft-utils uses the iconv utility for character coding conversions. iconv is a standard part of some (e.g. GNU) operating systems, if you don't have it you can install it as a part of the libiconv library available at @url{http://www.gnu.org/software/libiconv/}. Installation itself is easy, just copy all the @file{*.scm} files to one of the directories present in the Festival's load-path. This is typically @file{/usr/share/festival/}, you can get the exact list of the directories by evaluating @code{load-path} in the Festival command line interface. Then you can load the whole system at Festival startup by adding the line @lisp (require 'speech-dispatcher) @end lisp to the Festival initialization file (typically @file{/etc/festival.scm} system wide or @file{~/.festivalrc} for a particular user). Note you needn't do this for Speech Dispatcher operation as Speech Dispatcher invokes this call itself. @c **************************************************************************** @node User Customization @chapter User Customization You can customize festival-freebsoft-utils through several user variables described in the following sections. This chapter is primarily focused on Speech Dispatcher users and other users not using festival-freebsoft-utils directly. For a complete usage description see @ref{Reference Manual}. @cindex @code{SayText} Most of the extensions presented here don't work with usual Festival functions such as @code{SayText}, which are too limited in their use. You must use either the Speech Dispatcher functions, @ref{speech-dispatcher.scm}, or the event speaking functions, @ref{events.scm}, to utilize the features like word substitution, capital signalling or punctuation modes. @menu * Events:: Basic event handling. * Word Substitution:: Substituting events for certain words. * Capital Letters:: Capital letter signalling. * Punctuation Characters:: Pronouncing punctuation characters. * Initial Pauses:: Avoiding initial pauses. * Tokenization:: Utterance chunking. * Voice Selection:: Configuring voices and languages. * Speech Dispatcher:: Using with Speech Dispatcher. @end menu @node Events @section The Concept of Events @cindex events Default Festival interfaces expect text on their inputs, either in a plain form or in the form of some markup. The event module generalizes the concept of input to @emph{events}. Event is a general input object that can represent not only text, but also a pre-defined sound or an object just mapping to another input object. Currently the following kinds of events are supported: @table @code @item text @cindex text Text. The event value is a string containing the given text. @item ssml @cindex SSML Text represented in the SSML 1.0 markup. The event value is a string containing the given text. Please note that festival-freebsoft-utils does not provide conforming SSML implementation and implements only a limited subset of the standard. Moreover, due to the limitations of the built-in Festival XML parser, SSML markup texts must be provided in the target encoding of the document languages. @item sound @cindex sound @vindex sound-icon-directory Sound icon. The value is a string containing a file name of a sound file, either absolute, or relative to the @code{sound-icon-directory} variable value. @item character @cindex character Single character. The value is a string containing the character. The difference between character events and text events is that characters may be spoken in a different way than ordinary single-letter texts. @item key @cindex key @cindex Speech Synthesis Interface Protocol A key (as on keyboard). The value is a string containing key description in the format defined by the Speech Synthesis Interface Protocol, @ref{Top,SSIP,,ssip,SSIP}. @item logical @cindex logical Symbolic event name, usually mapped to another event. The value is an arbitrary symbol. Logical event values starting with the underscore character are considered special and shouldn't be generally used. @xref{events.scm}, for more details. @end table Any event may be mapped to another event. Before festival-freebsoft-utils functions process an event, they check for its mapping and if the event is mapped to another event, it is replaced by the target event. Event mapping is defined by the following variable: @vtable @code @item event-mappings Maps events of any supported kind (i.e. logical, text, sound, character, key) to other events (typically to text or sound events). All logical events used must be defined here, other kinds of events are processed in some default way if there are not defined in this variable. The variable contains an alist whose elements are of the form @code{(@var{event-type} @var{mappings})}. @var{event-type} is one of the symbols @code{logical}, @code{text}, @code{sound}, @code{character}, @code{key}. @var{mappings} is an alist with the elements of the form @code{(@var{value} @var{new-event-type} @var{new-event-value})}. See the default variable value for an example. @end vtable For a convenience, there is a function that allows you to add or replace single event mappings in the @code{event-mappings} variable in an easier way than redefining the whole variable value: @ftable @code @item set-event-mapping! @var{event-type} @var{event-value} @var{new-event-type} @code{new-event-value} Ensure the event of @var{event-type} and @var{event-value} is mapped to the event of @var{new-event-type} @code{new-event-value}. @end ftable Example: @lisp (set-event-mapping! 'logical 'hello 'text "Hello, world!") @end lisp @node Word Substitution @section Word Substitution You can map words to events. This is useful especially when you want to replace some words by sounds. @vtable @code @item word-mapping Alist mapping words to events. Each entry of the list is of the form @code{("@var{word}" @var{event-type} @var{event-value})}. If @var{word} is encountered in the input text, it is replaced by the given event. @end vtable @node Capital Letters @section Signalling Capital Characters When capital character signalling is enabled, @ref{cap-signalization.scm}, capital characters are signalled via the @code{capital} logical event. By default the event is mapped on the sound event @code{capital}. If you want to change it, change the logical mapping, as is described in @ref{Events}. For example, the following code in your @file{~/.festivalrc} changes the sound signalling to saying the word @emph{capital}: @lisp (require 'events) (set-event-mapping! 'logical 'capital 'text "capital") @end lisp @node Punctuation Characters @section Reading Punctuation Characters Through the punctuation modes, @ref{punctuation.scm}, you can force Festival to speak all punctuation characters. Since the default English voices don't have defined pronunciation of some punctuation characters, it is provided through the following variable: @vtable @code @item punctuation-pronunciation Alist of punctuation characters and their word forms. Each entry in the list is of the form @code{("@var{character}" "@var{word}" ...}, where @var{character} is the pronounced character and @var{word}s are the words of its pronunciation. Please note you must put each word inside separate double quotes. Example entry: @lisp ("!" "exclamation" "mark") @end lisp @end vtable @node Initial Pauses @section Avoiding Initial Pauses @cindex pauses Festival inserts initial pause in each synthesized utterance. There is a good reason for it---speech starts from silence and thus the first diphone of the synthesized sample should be @emph{pause-first phoneme}. However there are some situations when the initial pause is undesirable. For instance, when reading characters in a speech enabled editor, the initial pauses slow down the reading. So festival-freebsoft-utils provide a way to disable the initial pause by making its effective duration zero. First, you must load the corresponding code: @lisp (require 'nopauses) @end lisp After this, there is a variable available controlling the initial pause insertion: @vtable @code @item inhibit-initial-pauses When set to a non-@code{nil} value, initial pauses are inhibited. @end vtable @node Tokenization @section Tokenization @cindex eou_tree If you use the festival-freebsoft-utils tokenizer instead of the Festival built-in tokenizer, you can put additional limits on the tokenization process besides the @code{eou_tree}. @vtable @code @item max-number-of-tokens Maximum number of tokens in a single utterance. Utterance chunking is performed in such a way that each produced utterance contains at most this number of tokens. @item max-number-of-token-chars Maximum number of characters within a single token. If a token contains more characters than is stated by this limit, it is split into smaller tokens. @end vtable @node Voice Selection @section Voice Selection @cindex voices @cindex languages You can configure languages and voices used by the SSML, Speech Dispatcher and other interfaces supporting the mechanism with the following variables: @vtable @code @item language-codes Alist mapping ISO language codes to Festival language names. Each alist entry is of the form @code{("@var{language-code}" @var{language-name})}, where @var{language-code} is an ISO language code as used by Speech Dispatcher and @code{language-name} is the corresponding Festival language name. Optionally, the alist elements can have the extended form @code{(@var{language-code} @var{language-name} . @var{dialects})}, where @var{dialects} is a list of pairs @code{(@var{dialect-code} @var{dialect-name})}. @var{dialect-code} is the part of the language code after a hyphen or underscore and @var{dialect-name} is the dialect name used by Festival voices. @item voice-select-defaults Alist of default voice parameters. Each alist entry is of the form @code{(@var{name} @var{value})}, where @var{value} can be either the actual parameter value or @code{nil}, meaning the value is unspecified. @end vtable @node Speech Dispatcher @section Using with Speech Dispatcher One of the primary goals of festival-freebsoft-utils is to serve as a Speech Dispatcher interface to Festival. festival-freebsoft-utils is required by Speech Dispatcher for the use of Festival as the speech synthesis backend. In order to use festival-freebsoft-utils with Speech Dispatcher, you need not to make any special festival-freebsoft-utils arrangements. Just configure it as is described in the previous sections. It is particularly recommended to configure available languages if you want to use Festival for other languages than English, @xref{Voice Selection}. This version of festival-freebsoft-utils requires Speech Dispatcher 0.5 or higher. @c **************************************************************************** @node Reference Manual @chapter Reference Manual festival-freebsoft-utils consists of several modules described in the following sections. @menu * util.scm:: Miscellaneous utility functions. * wave.scm:: Wave form handling. * oo.scm:: Object oriented programming. * events.scm:: Generalized input events. * spell-mode.scm:: Spelling mode. * cap-signalization.scm:: Capital letter signalization. * punctuation.scm:: Punctuation reading modes. * tokenize.scm:: Alternative tokenization written in SIOD. * multiwave.scm:: Returning multiple wave forms for an event. * voice-select.scm:: Selecting voices and languages. * prosody-param.scm:: Changing prosodic parameters. * ssml-mode.scm:: Partial SSML support. * fileio.scm:: File utilities. * recode.scm:: Character set conversions. * speech-dispatcher.scm:: Speech Dispatcher interface. @end menu @node util.scm @section util.scm This module contains miscellaneous utilities useful in general SIOD and Festival programming. Macros and functions mostly available in Lisp dialects: @ftable @code @item when @var{condition} @var{body-form} @var{...} If and only if @var{condition} is true, evaluate @code{body-form}s. @item unless @var{condition} @var{body-form} @var{...} If and only if @var{condition} is false, evaluate @code{body-form}s. @item prog1 @var{form} @var{...} Evaluate all forms and return the return value of the first one. @item let* @var{bindings} @var{body-form} @var{...} The same as @code{let} except that variable bindings are applied sequentially rather than in parallel. @item unwind-protect* @var{protected-form} @var{cleanup-form} @var{...} Evaluate @var{protected-form}, and after it is finished, whether successfully or with errors, evaluate all @var{cleanup-form}s. If @var{protected-form} was evaluated successfully, return its return value. Unlike Festival's @code{unwind-protect}, @code{unwind-protect*} accepts multiple @var{cleanup-form}s and evaluates them even when @var{protected-form} doesn't signal an error. @item first @var{list} @item second @var{list} @item third @var{list} @item fourth @var{list} Return first, second, third or fourth element of @var{list}, respectively. @item butlast @var{list} Return the @var{list} without its last element. If @var{list} is empty, return an empty list. @item min @var{x} @var{y} Return minimum of the two numeric values @var{x} and @var{y}. @item max @var{x} @var{y} Return maximum of the two numeric values @var{x} and @var{y}. @item abs @var{x} Return absolute value of @var{x}. @item remove-if @var{test} @var{list} Return @var{list} with elements, for which the @var{test} call returns non-@code{nil}, removed. The order of list elements is preserved. @var{test} must be a function of a single argument. @item identity @var{object} Return @var{object}. @item complement @var{function} Return a function that is equivalent to function except that it returns the opposite truth value to the return value of function. @item apply* @var{function} @var{arglist} The same as @code{apply}, except that it also works if @var{function} is given as a string. @item dolist (@var{var} @var{items}) @var{body-form} @var{...} @cindex looping Loop over @var{items} and perform @var{body-form}s over each of them, binding it to the variable @var{var} (unevaluated). @item add-hook @var{hook-variable} @var{hook-function} @var{to-end?} Add @var{hook-function} to @var{hook-variable} if it is not already present there. @var{hook-variable} must be a variable containing a list. If @var{to-end?} is true, add @var{hook-function} to the end of the list contained in @var{hook-variable}, otherwise add it to the beginning. @item assoc-set @var{list} @var{key} @var{value} Add the @var{key}-@var{value} pair to the association @code{list} and return the resulting list. Contingent previously @var{list} entries stored under @var{key} are removed from the resulting list. @item avalue-get @var{key} @var{alist} Find the first @var{alist} element of the form @code{(@var{key*} @code{value})}, where @var{key*} is @code{string-equal} to @var{key}, and return @var{value}. @item avalue-set! @var{key} @var{alist} @var{value} Destructively set the @var{value*} of the first @var{alist} element of the form @code{(@var{key*} @code{value*})} to @var{value}. Return @var{alist}. @item avg . @var{args} @cindex math functions Return average value of @var{args}. @item dirname @var{path} Return the directory part of @var{path}. @item make-temp-filename @var{template} Return name of a (probably non-existent) temporary file. @var{template} is a basename of the file, that is formatted with the @code{format} function and must contain exactly one @code{%s} sequence to be replaced with a variable part of the file name. Actually, this function is somewhat limited by the available Festival system interface. So it is not safe, the file may be created before it is actually used or the function may fail with an error. But for simple purposes the function should work fine and it shouldn't be worse than the standard @code{make_tmp_filename} function. @item with-temp-file @var{filename} @var{body} Macro that binds newly generated temporary file name to a local variable @var{filename} and then performs @var{body}. The macro ensures the temporary file is deleted after finishing @var{body} in any way. @item string-replace @var{string} @var{from} @var{to} Replace all occurrences of @var{from} by @var{to} in @var{string} and return the result. @end ftable Festival specific utilities: @ftable @code @item item.has_feat @var{item} @var{feature} Return true if and only if @var{item} has @var{feature} set. @item langvar @var{symbol} Return language dependent value stored under @var{symbol}. First, the variable named @var{symbol.language}, where @var{language} is the language name as stored in the @code{Language} parameter is checked and if it is unbound, @var{symbol}'s value is returned. @item current-voice-coding Return character coding of the currently selected voice in Festival. The coding is taken from the @code{coding} attribute of the voice description, if it is undefined or @code{nil}, ISO@ 8859-1 coding is assumed. The @code{coding} voice attribute is introduced by festival-freebsoft-utils, it is not a standard Festival feature. @item utt-relation-top-items @var{utt} @var{relation} Return a list of top level items in @var{relation} in @code{utt}. @item do-relation-items (@var{var} @var{utterance} @var{relation}) @var{body-form} @var{...} @cindex looping Loop over @var{relation} items of @var{utterance}, performing @var{body-form}s for each of them, binding it to the variable @var{var}. The macro arguments @var{var} and @var{relation} are not evaluated. @item do-relation-top-items (@var{var} @var{utterance} @var{relation}) @var{body-form} @var{...} Similar to @code{do-relation-items}, but loops only over the relation's top items. @end ftable @node wave.scm @section Wave form handling @cindex wave forms There are some utility functions to help handling wave forms: @ftable @code @item wave-concat @var{waves} Append wave forms and return the resulting wave form. @var{waves} must be a list of wave forms to append. @item wave-subwave @var{wave} @var{from-time} @var{to-time} Return the part of @var{wave} form that starts at @var{from-time} and finishes at @var{to-time}. Both times are in seconds. @item wave-load @var{filename} @cindex Ogg Vorbis @cindex Vorbis Load and return a wave form from @var{filename}. This function is similar to @code{wave.load}, but more sound file formats (most significantly Ogg Vorbis, if your SoX installation supports it) can be loaded. @item wave-utt @var{wave} Create and return an utterance, that contains just the @code{Wave} relation holding @var{wave}. @item wave-import-utt @var{filename} Create and return an utterance, that contains just the @code{Wave} relation holding a wave loaded from @var{filename} via the function @code{wave-load}. @end ftable @node oo.scm @section oo.scm @cindex wrappers Sometimes it is useful to extend a Festival function in some way. Standard Festival functions don't provide easy to use means for it. This module tries to fill the gap. The following macro allows you to wrap a defined function: @ftable @code @item define-wrapper (@var{function} @var{arg ...}) @var{wrapper-name} . @var{body}) Wrap @var{function} with arguments @var{arg ...} by the code @var{body}. Given function arguments must match the arguments of the wrapped function. @var{wrapper-name} is a symbol uniquely identifying the wrapper, it allows redefinition of the wrapper. One function can be wrapped by any number of wrappers. None of the @code{define-wrapper} arguments is evaluated. @cindex next-func Within @var{body}, a function named @code{next-func} is automatically defined. It returns the next wrapper or the original function. Please note @code{next-func} is a function, not a variable, so its typical invocation looks as follows: @code{((next-func) @var{arg} @var{...})}. @item oo-ensure-function-wrapped @var{function-name} If a wrapped function gets redefined, its wrapper is lost. If you want to ensure the function is still wrapped before its use, you may call this function, with its symbol name as the argument. @item oo-unwrapped @var{function-name} Return the original definition of a wrapped function. @end ftable Example use: @lisp festival> (define (foo x) (+ x 42)) # festival> (foo 1) 43 festival> (define-wrapper (foo x) my-foo-wrapper (print "Foo called.") ((next-func) x)) nil festival> (foo 1) "Foo called." 43 @end lisp @cindex @code{Param.set} You can also wrap parameters, set by @code{Param.set}: @ftable @code @item Param.wrap @var{name} @var{wrapper-name} . @var{body} Wrap access to parameter @var{name} by code @var{body}. If the given parameter is accessed, its wrapper is invoked instead of just returning the parameter value. @var{wrapper-name} is the same as in @code{define-wrapper}. @cindex @code{next-value} Macro @code{next-value} is automatically defined within @var{body}. It returns the parameter value, either plain or modified by another wrapper. @end ftable Example use of parameter wrapping: @lisp festival> (Param.set 'foo 42) # festival> (Param.wrap foo foo-w (+ (next-value) 1)) nil festival> (Param.get 'foo) 43 @end lisp And finally, the @code{glet*} macro allows you to dynamically bind a global variable value: @ftable @code @item glet* @var{bindings} . @var{body} Similar to @code{let*} (@pxref{util.scm}) except that the variables in @var{bindings} are bound dynamically instead of lexically. All variables in @var{bindings} must be global variables. @end ftable @node events.scm @section events.scm For introductory and configuration information about events see @ref{Events}. The event module provides the following functions to synthesize events: @ftable @code @item event-synth @var{type} @var{value} Synthesize event of @var{type}, which may be one of the following symbols: @code{logical}, @code{text}, @code{sound}, @code{character}, @code{key}. @var{event} is the event value that must correspond to the event type. @item event-play @var{type} @var{value} Play event. The @var{type} and @var{value} arguments are the same as in @code{event-synth}. @end ftable Logical events starting with underscore are reserved for special purposes. Currently, the following special purpose logical events are recognized: @table @code @cindex @code{_debug_on} @item _debug_on* Turn on debugging. That means every processed event is logged. @code{_debug_off} is just a prefix, it can be followed by any symbol constituent characters. @cindex @code{_debug_off} @item _debug_off* Turn the debugging off. @code{_debug_off} is just a prefix, it can be followed by any symbol constituent characters. @end table @node spell-mode.scm @section spell-mode.scm @cindex @code{spell} Defines spelling mode, i.e. the mode in which the input text is spelled rather than read in the usual way. The @code{spell} mode is a normal Festival mode, so you can use it after loading this module immediately, e.g. @example (tts_file "file" 'spell) @end example @node cap-signalization.scm @section cap-signalization.scm Defines mode that allows signalling of capital letters through the logical event @code{capital}. @xref{Capital Letters}, for more details. @ftable @code @item set-cap-signalization-mode @var{mode} If @var{mode} is true, enable capital letter signalling, otherwise disable it. @end ftable @node punctuation.scm @section punctuation.scm Sometimes it is useful to get read all the punctuation characters present in the synthesized text (for exact information about the text) and sometimes it is useful to read no punctuation character (for faster reading). Punctuation modes allow you to tell Festival, whether it should read punctuation characters or not. @ftable @code @item set-punctuation-mode @var{mode} Set punctuation mode to @var{mode}. @var{mode} may be one of the following symbols: @code{all} meaning all the punctuation characters are read, @code{none} meaning no punctuation characters are read, and @code{default} that switches to the default Festival behavior corresponding to the current language and voice. @end ftable @xref{Punctuation Characters}, for information about punctuation mode configuration. @node tokenize.scm @section tokenize.scm Festival's tokenization is implemented mostly in C++, so it is impossible to use it when extending Festival. The @code{tokenize} module provides an alternative tokenization implemented in SIOD, that can be used wherever needed. @ftable @code @item next-chunk @var{text} Get the next part of @var{text} and create an utterance containing the corresponding tokens. A list of two elements, the utterance and the remaining unprocessed part of @var{text}, is returned. @end ftable @cindex @code{SayText} An alternative @code{SayText} function, splitting the text into smaller pieces (and thus speeding up the start of speech) might be implemented as follows: @lisp (define (SayText* text) (if (not (equal? text "")) (let ((utt-text (next-chunk text))) (let ((utt (car utt-text)) (text (cadr utt-text))) (utt.play (utt.synth utt)) (SayText* text))))) @end lisp @node multiwave.scm @section multiwave.scm @cindex multiple wave forms Sometimes it is convenient to return multiple synthesized wave forms instead of a single wave form. There are two typical situations when this can happen: @itemize @bullet @item @cindex long texts You want to synthesize a long text and you don't want to wait until it is all synthesized, you want to play the resulting audio as soon as possible. The text can be cut into smaller pieces, returning the corresponding wave forms in a sequence. @item @cindex resampling The resulting wave form is a mixture of a synthesized texts and sound icons, of different rates or other sound sample parameters. Concatenating them together may reduce the resulting sound quality. So the different sound parts may be better returned separately. @end itemize The @file{multiwave.scm} module provides the following interface for those purposes: @ftable @code @item multi-synth @var{type} @var{value} This function is similar to the @code{event-synth} function (@pxref{events.scm}), except that it doesn't return an utterance containing the resulting wave form. Instead, it setups the synthesis for the following @code{multi-next} calls. @item multi-next Return the next wave form of the last event synthesized via the @code{multi-synth} function. If there is no next wave form, return @code{nil}. If you synthesize an SSML text, the function may return a non-@code{nil} symbol instead of a wave form. Then the symbol is a name of the mark just reached. @item multi-clear Throw away the synthesized data. You usually don't need to call this function as the data is cleared on the next @code{multi-synth} call automatically, but the function may be useful under special circumstances. @end ftable @node voice-select.scm @section voice-select.scm The voice-select module provides a mechanism for voice and language selection. For its configuration information, see @xref{Voice Selection}. The following voice selection functions are available: @ftable @code @item voice-list Return the list of names of all available voices. Unlike the list returned by the standard Festival function @code{voice.list}, the list includes all registered voices. @item voice-list-language-codes Return the list of names, language codes and dialect codes of all available voices. Each element of the returned list is of the form @code{(@var{name} @var{language-code} @var{dialect-code})}, where all the elements of the tripple are symbols. If the language code or the dialect code is not known for the voice, the corresponding element is @code{nil}. @item current-language-voices Return a list of all the voices available for the current language. @item select-voice @var{language} @var{dialect} @var{gender} @var{age} @var{variant} @var{name} Select voice according to the specified parameters and return its name. @var{language} is the language name, @var{dialect} is a @var{language} dialect name. @var{gender} can be one of the symbols @code{male} or @code{female} (the value is currently ignored). @code{age} is age of the speaker in years given as a number. @code{variant} is a positive integer that selects one of several voices, if more than one voice is selected by all other parameters. @var{name} can be a particular voice name. Each of the function arguments can have @code{nil} as its value. In such a case, default value of the corresponding parameter is used. If there is no default value, the parameter is not considered in the selection process. If more than one voice matches, one of the matched voices is selected. If no voice satisfying all the given parameters is available, some voice satisfying the most important parameters is selected. @item select-voice* @var{lang-code} @var{gender} @var{age} @var{variant} @var{name} Like @code{select-voice}, except that language and dialect are specified by an ISO @var{lang-code}. @item reset-voice Reset currently selected voice parameters to their default values. @end ftable Additionally, there is a variable holding information about voice properties currently in effect for the purpose of voice selection by the @code{voice-select} function: @vtable @code @item voice-select-current-defaults Alist containing current voice properties used by voice selection. @end vtable @node prosody-param.scm @section prosody-param.scm Ever wished to be able to change prosodic parameters in Festival easily and in a uniform way for different voices? Well, here are the appropriate functions. They are no way guaranteed to work for all voices, since each voice can have its own unique way of prosody handling. But they should work for typical cases. @ftable @code @item set-pitch @var{value} Set mean pitch of the voice to @var{value} and return the old pitch value. @var{value} is given in Hertz. @item set-pitch-range @var{value} Set the pitch range of the voice to @var{value} and return the old pitch range value. The value is in percents of the mean pitch, its clear meaning is not defined. @item set-volume @var{value} Set volume to the given @var{value} and return the old volume value. @var{value} must be in the range 0--1 from silence to maximum (the default). @item set-rate @var{value} Set voice rate to @var{value} and return the old rate value. @var{value} is in the range 0.1--10 from the slowest to the fastest. The value 1 corresponds to the normal voice speed, other values multiply the voice speed appropriately. @end ftable The @var{value} argument of all the functions above may also be a function of a single argument accepting the current parameter value and returning its new value. The following convenience functions return functions which adjust the parameter values appropriately: @ftable @code @item prosody-shifted-value @var{shift} Return a function modifying the value by adding @var{shift} to it. @item prosody-relative-value @var{coef} Return a function modifying the value by multiplying it by @var{coef}. @end ftable Example setting doubling the current voice speed: @lisp (set-rate (prosody-relative-value 2)) @end lisp When you switch to a different voice, prosody parameters get lost. festival-freebsoft-utils offers a way to restore them, using the following functions: @ftable @code @item change-prosody @var{function} @var{value} Similar to the @code{set-*} functions described above, except it additionally saves the set prosodic value. @var{function} is one of the @code{set-*} functions and @var{value} is its parameter value. @item restore-prosody Set prosodic parameters according to their current saved values. @item reset-prosody Reset the list of the saved prosodic values. Note, it just deletes the saved settings and doesn't actually change the current prosodic parameters. @end ftable @node ssml-mode.scm @section ssml-mode.scm @cindex SSML festival-freebsoft-utils provides a text processing mode partially supporting the SSML 1.0 markup. You can process a SSML file in the following way in the Festival prompt: @lisp (tts_file "/the/path/to/the/file" 'ssml) @end lisp Moreover, there are some particular SSML processing functions available: @ftable @code @item ssml-say @var{text} Speak the given SSML @var{text}. @item ssml-parse @var{text} Parse the given SSML @var{text} for later processing by the @code{ssml-next-chunk} function. @item ssml-next-chunk Return next utterance containing tokens from the last SSML text parsed by @code{ssml-parse} or a mark name. If there is no next utterance or mark, return @code{nil}. The returned utterance contains only the @code{Token} relation and is intended to be further processed with the @code{utt.synth} function. The returned mark name is a non-@code{nil} symbol. @item ssml-speak-chunks Speak the SSML text processed by @code{ssml-parse}. @end ftable The @code{ssml-parse} and @code{ssml-next-chunk} functions are intended to be used when you want to synthesize an SSML text, but not to speak it immediately. A sample use of those functions for a hypothetic @code{ssml-say*} function similar to @code{ssml-say} might be as follows: @lisp (define (ssml-say* text) (ssml-parse text) (ssml-say*-1)) (define (ssml-say*-1) (let ((utt (ssml-next-chunk))) (if utt (begin (cond ((symbol? utt) (print utt)) (utt (utt.play (utt.synth utt)))) (ssml-say*-1))))) @end lisp If you need quick synthesizer response, avoid the DOCTYPE declaration in your SSML data. The DOCTYPE declaration takes an observable time when processed in the Festival's XML parser. festival-freebsoft-utils does not provide conforming SSML implementation and implements only a limited subset of the standard. Moreover, due to the limitations of the built-in Festival XML parser, SSML markup texts that contain non-ASCII characters can only be processed with the @code{ssml-parse} and @code{ssml-next-chunk} functions and must be provided in the UTF-8 encoding. It is not easy to fully support SSML in Festival. Contingent support and contributions are welcome. @node fileio.scm @section fileio.scm Functions in this module try to help to improve Festival file input/output. @ftable @code @item with-open-file (@var{variable} @var{filename} &optional @var{how}) @var{body-form} ... Open file named @var{filename} in mode @var{how} (for reading if not provided) and bind it to a newly created local @var{variable}. Execute @var{body-form}s in that context. @item read-file @var{filename} Read and return whole contents of the file named @var{filename}. @item write-file @var{filename} @var{string} Write @var{string} to a file named @var{filename}. @item make-read-line-state Create and return a state object required by the function @code{read-line}. @item read-line @var{file} @var{state} Read a single line from @var{file} and return it without the final newline character. If there is no next line in @var{file}, return @code{nil}. @var{state} is a state as initially returned by the @code{make-read-line-state} function. The typical @code{read-line} usage idiom is: @lisp (let ((state (make-read-line-state)) (f (fopen "...")) (line t)) (while line (set! line (read-line f state)) ...)) @end lisp @end ftable @node recode.scm @section recode.scm Festival doesn't support different character sets directly. But it is 8-bit clean and you can use whatever character coding you like if you can process it in the form of 8-bit characters. The @code{recode.scm} module offers the following functions to convert between different character sets: @ftable @code @item recode @var{string} @var{from-coding} @var{to-coding} Return given @var{string}, originally encoded in @var{from-coding}, recoded to @var{to-coding}. @vindex recode-special-utf8-translations @item recode-utf8->current @var{string} Return given @var{string}, originally encoded in @code{UTF-8}, recoded to the coding of the current voice. Before applying normal recoding this function translates strings as specified in @code{recode-special-utf8-translations} variable. This allows you to convert some unicode characters in a special way, e.g. to translate empty space to space (thus separating words around it). @code{recode-special-utf8-translations} contains lists of two elements, the converted substring and its translation. @end ftable The recoding functions use the @code{iconv} program and temporary files to convert between character sets. There is no known better way to do the conversions. @node speech-dispatcher.scm @section speech-dispatcher.scm This module provides Speech Dispatcher interface. You need it if you want to use Festival as a Speech Dispatcher output text-to-speech system. The module defines functions required by the Speech Dispatcher Festival output module and user configuration variables, see @ref{Speech Dispatcher}. @cindex @code{speechd-speak} To ease debugging, for each Speech Dispatcher function which returns a wave form, there is defined a corresponding function of the same name with star appended, that returns an utterance instead of wave form. For instance, the function @code{speechd-speak} returns a wave form (and can be used only in server mode), while the function @code{speechd-speak*} returns an utterance. @c **************************************************************************** @node Contact @chapter How to contact us @cindex author @cindex contact The author of festival-freebsoft-utils is Milan Zamazal @email{pdm@@freebsoft.org}. The home page of festival-freebsoft-utils is @url{http://www.freebsoft.org/festival-freebsoft-utils/}. @cindex bugs @cindex mailing list You can contact us with your comments, questions, suggestions, patches or anything at the Speech Dispatcher mailing list @email{speechd@@freebsoft.org}. Bug reports can be sent to the e-mail address @email{festival-freebsoft-utils@@bugs.freebsoft.org}. @cindex Free(b)soft project festival-freebsoft-utils is part of the Free(b)soft project aimed at making computers accessible to blind and sorely visually impaired people. The home page of the project is @url{http://www.freebsoft.org}. @c **************************************************************************** @node Copying This Manual @appendix GNU Free Documentation License @cindex FDL, GNU Free Documentation License @center Version 1.2, November 2002 @include fdl.texi @c **************************************************************************** @node Index @unnumbered Index @printindex cp @bye @c LocalWords: texinfo setfilename freebsoft utils settitle syncodeindex fn @c LocalWords: cp ky vr dircategory direntry titlepage vskip pt filll dir url @c LocalWords: insertcopying ifnottex cindex scm SayText emph vindex xref var @c LocalWords: vtable alist ftable nopauses speechd util prog dolist assoc oo @c LocalWords: avg args dirname basename tmp langvar concat subwave utt arg @c LocalWords: func foo Param synth FDL fdl texi printindex festivalrc pre @c LocalWords: Tokenization eou tokenizer tokenization backend signalization @c LocalWords: tokenize multiwave avalue glet pxref tts cadr festival-freebsoft-utils-0.10/doc/festival-freebsoft-utils.info0000644000175000017500000023052411075611374023071 0ustar pdmpdmThis is festival-freebsoft-utils.info, produced by makeinfo version 4.11 from festival-freebsoft-utils.texi. This manual is for festival-freebsoft-utils, version 0.10. Copyright (C) 2004, 2005, 2006, 2007, 2008 Brailcom, o.p.s. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". Alternatively, you can distribute this manual under the same conditions as festival-freebsoft-utils itself: festival-freebsoft-utils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. WAusers 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. INFO-DIR-SECTION Sound START-INFO-DIR-ENTRY * Festival Freebsoft Utilities: (festival-freebsoft-utils). Festival utilities used by the Freebsoft project. END-INFO-DIR-ENTRY  File: festival-freebsoft-utils.info, Node: Top, Next: Motivation, Up: (dir) festival-freebsoft-utils ************************ This manual is for festival-freebsoft-utils, version 0.10. Copyright (C) 2004, 2005, 2006, 2007, 2008 Brailcom, o.p.s. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". Alternatively, you can distribute this manual under the same conditions as festival-freebsoft-utils itself: festival-freebsoft-utils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. WAusers 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * Menu: * Motivation:: What is festival-freebsoft-utils? * Installation:: How to install it. * User Customization:: Configuration variables. * Reference Manual:: Description of all available functions. * Contact:: Authors, mailing lists, Web pages. * Copying This Manual:: GNU Free Documentation License. * Index:: Concept, function and variable.  File: festival-freebsoft-utils.info, Node: Motivation, Next: Installation, Prev: Top, Up: Top 1 Motivation ************ Festival is a powerful and extensible speech synthesis system, able to handle the whole text-to-speech process. The aim of festival-freebsoft-utils is to further extend Festival facilities, to the level providing complete set of features required by *note Speech Dispatcher: (speech-dispatcher)Top. As a side effect, festival-freebsoft-utils introduces interesting functionality, generalizing the text-to-speech system to a text-to-sound system. Festival is well suited to the speech synthesis process itself, but lacks some end-user features, especially those needed for application sound output. festival-freebsoft-utils tries to fill this gap, thus making Festival suitable for screen readers and other speech output software, used especially by the blind and visually impaired people. Main features of festival-freebsoft-utils are: * Generalized concept of input events. festival-freebsoft-utils allows not only plain text synthesis, but also insertion of sounds and logical event mapping. * Spell mode. * Capital letter signalling. * Punctuation modes, for reading or not reading punctuation characters. * Function wrapping support. * Speech Dispatcher Festival output interface. For more information about Speech Dispatcher, see `http://www.freebsoft.org/speechd' or *note Speech Dispatcher: (speech-dispatcher)Top. Up-to-date information about festival-freebsoft-utils can be found at its home page `http://www.freebsoft.org/festival-freebsoft-utils/'.  File: festival-freebsoft-utils.info, Node: Installation, Next: User Customization, Prev: Motivation, Up: Top 2 Installation ************** festival-freebsoft-utils was tested with Festival 1.4.3. Other versions of Festival may or may not work. Having SoX (`http://sox.sourceforge.net') installed is strongly recommended, many festival-freebsoft-utils functions don't work without it. As Festival does not support UTF-8 encoding, festival-freebsoft-utils uses the iconv utility for character coding conversions. iconv is a standard part of some (e.g. GNU) operating systems, if you don't have it you can install it as a part of the libiconv library available at `http://www.gnu.org/software/libiconv/'. Installation itself is easy, just copy all the `*.scm' files to one of the directories present in the Festival's load-path. This is typically `/usr/share/festival/', you can get the exact list of the directories by evaluating `load-path' in the Festival command line interface. Then you can load the whole system at Festival startup by adding the line (require 'speech-dispatcher) to the Festival initialization file (typically `/etc/festival.scm' system wide or `~/.festivalrc' for a particular user). Note you needn't do this for Speech Dispatcher operation as Speech Dispatcher invokes this call itself.  File: festival-freebsoft-utils.info, Node: User Customization, Next: Reference Manual, Prev: Installation, Up: Top 3 User Customization ******************** You can customize festival-freebsoft-utils through several user variables described in the following sections. This chapter is primarily focused on Speech Dispatcher users and other users not using festival-freebsoft-utils directly. For a complete usage description see *note Reference Manual::. Most of the extensions presented here don't work with usual Festival functions such as `SayText', which are too limited in their use. You must use either the Speech Dispatcher functions, *note speech-dispatcher.scm::, or the event speaking functions, *note events.scm::, to utilize the features like word substitution, capital signalling or punctuation modes. * Menu: * Events:: Basic event handling. * Word Substitution:: Substituting events for certain words. * Capital Letters:: Capital letter signalling. * Punctuation Characters:: Pronouncing punctuation characters. * Initial Pauses:: Avoiding initial pauses. * Tokenization:: Utterance chunking. * Voice Selection:: Configuring voices and languages. * Speech Dispatcher:: Using with Speech Dispatcher.  File: festival-freebsoft-utils.info, Node: Events, Next: Word Substitution, Up: User Customization 3.1 The Concept of Events ========================= Default Festival interfaces expect text on their inputs, either in a plain form or in the form of some markup. The event module generalizes the concept of input to _events_. Event is a general input object that can represent not only text, but also a pre-defined sound or an object just mapping to another input object. Currently the following kinds of events are supported: `text' Text. The event value is a string containing the given text. `ssml' Text represented in the SSML 1.0 markup. The event value is a string containing the given text. Please note that festival-freebsoft-utils does not provide conforming SSML implementation and implements only a limited subset of the standard. Moreover, due to the limitations of the built-in Festival XML parser, SSML markup texts must be provided in the target encoding of the document languages. `sound' Sound icon. The value is a string containing a file name of a sound file, either absolute, or relative to the `sound-icon-directory' variable value. `character' Single character. The value is a string containing the character. The difference between character events and text events is that characters may be spoken in a different way than ordinary single-letter texts. `key' A key (as on keyboard). The value is a string containing key description in the format defined by the Speech Synthesis Interface Protocol, *note SSIP: (ssip)Top. `logical' Symbolic event name, usually mapped to another event. The value is an arbitrary symbol. Logical event values starting with the underscore character are considered special and shouldn't be generally used. *Note events.scm::, for more details. Any event may be mapped to another event. Before festival-freebsoft-utils functions process an event, they check for its mapping and if the event is mapped to another event, it is replaced by the target event. Event mapping is defined by the following variable: `event-mappings' Maps events of any supported kind (i.e. logical, text, sound, character, key) to other events (typically to text or sound events). All logical events used must be defined here, other kinds of events are processed in some default way if there are not defined in this variable. The variable contains an alist whose elements are of the form `(EVENT-TYPE MAPPINGS)'. EVENT-TYPE is one of the symbols `logical', `text', `sound', `character', `key'. MAPPINGS is an alist with the elements of the form `(VALUE NEW-EVENT-TYPE NEW-EVENT-VALUE)'. See the default variable value for an example. For a convenience, there is a function that allows you to add or replace single event mappings in the `event-mappings' variable in an easier way than redefining the whole variable value: `set-event-mapping! EVENT-TYPE EVENT-VALUE NEW-EVENT-TYPE `new-event-value'' Ensure the event of EVENT-TYPE and EVENT-VALUE is mapped to the event of NEW-EVENT-TYPE `new-event-value'. Example: (set-event-mapping! 'logical 'hello 'text "Hello, world!")  File: festival-freebsoft-utils.info, Node: Word Substitution, Next: Capital Letters, Prev: Events, Up: User Customization 3.2 Word Substitution ===================== You can map words to events. This is useful especially when you want to replace some words by sounds. `word-mapping' Alist mapping words to events. Each entry of the list is of the form `("WORD" EVENT-TYPE EVENT-VALUE)'. If WORD is encountered in the input text, it is replaced by the given event.  File: festival-freebsoft-utils.info, Node: Capital Letters, Next: Punctuation Characters, Prev: Word Substitution, Up: User Customization 3.3 Signalling Capital Characters ================================= When capital character signalling is enabled, *note cap-signalization.scm::, capital characters are signalled via the `capital' logical event. By default the event is mapped on the sound event `capital'. If you want to change it, change the logical mapping, as is described in *note Events::. For example, the following code in your `~/.festivalrc' changes the sound signalling to saying the word _capital_: (require 'events) (set-event-mapping! 'logical 'capital 'text "capital")  File: festival-freebsoft-utils.info, Node: Punctuation Characters, Next: Initial Pauses, Prev: Capital Letters, Up: User Customization 3.4 Reading Punctuation Characters ================================== Through the punctuation modes, *note punctuation.scm::, you can force Festival to speak all punctuation characters. Since the default English voices don't have defined pronunciation of some punctuation characters, it is provided through the following variable: `punctuation-pronunciation' Alist of punctuation characters and their word forms. Each entry in the list is of the form `("CHARACTER" "WORD" ...', where CHARACTER is the pronounced character and WORDs are the words of its pronunciation. Please note you must put each word inside separate double quotes. Example entry: ("!" "exclamation" "mark")  File: festival-freebsoft-utils.info, Node: Initial Pauses, Next: Tokenization, Prev: Punctuation Characters, Up: User Customization 3.5 Avoiding Initial Pauses =========================== Festival inserts initial pause in each synthesized utterance. There is a good reason for it--speech starts from silence and thus the first diphone of the synthesized sample should be _pause-first phoneme_. However there are some situations when the initial pause is undesirable. For instance, when reading characters in a speech enabled editor, the initial pauses slow down the reading. So festival-freebsoft-utils provide a way to disable the initial pause by making its effective duration zero. First, you must load the corresponding code: (require 'nopauses) After this, there is a variable available controlling the initial pause insertion: `inhibit-initial-pauses' When set to a non-`nil' value, initial pauses are inhibited.  File: festival-freebsoft-utils.info, Node: Tokenization, Next: Voice Selection, Prev: Initial Pauses, Up: User Customization 3.6 Tokenization ================ If you use the festival-freebsoft-utils tokenizer instead of the Festival built-in tokenizer, you can put additional limits on the tokenization process besides the `eou_tree'. `max-number-of-tokens' Maximum number of tokens in a single utterance. Utterance chunking is performed in such a way that each produced utterance contains at most this number of tokens. `max-number-of-token-chars' Maximum number of characters within a single token. If a token contains more characters than is stated by this limit, it is split into smaller tokens.  File: festival-freebsoft-utils.info, Node: Voice Selection, Next: Speech Dispatcher, Prev: Tokenization, Up: User Customization 3.7 Voice Selection =================== You can configure languages and voices used by the SSML, Speech Dispatcher and other interfaces supporting the mechanism with the following variables: `language-codes' Alist mapping ISO language codes to Festival language names. Each alist entry is of the form `("LANGUAGE-CODE" LANGUAGE-NAME)', where LANGUAGE-CODE is an ISO language code as used by Speech Dispatcher and `language-name' is the corresponding Festival language name. Optionally, the alist elements can have the extended form `(LANGUAGE-CODE LANGUAGE-NAME . DIALECTS)', where DIALECTS is a list of pairs `(DIALECT-CODE DIALECT-NAME)'. DIALECT-CODE is the part of the language code after a hyphen or underscore and DIALECT-NAME is the dialect name used by Festival voices. `voice-select-defaults' Alist of default voice parameters. Each alist entry is of the form `(NAME VALUE)', where VALUE can be either the actual parameter value or `nil', meaning the value is unspecified.  File: festival-freebsoft-utils.info, Node: Speech Dispatcher, Prev: Voice Selection, Up: User Customization 3.8 Using with Speech Dispatcher ================================ One of the primary goals of festival-freebsoft-utils is to serve as a Speech Dispatcher interface to Festival. festival-freebsoft-utils is required by Speech Dispatcher for the use of Festival as the speech synthesis backend. In order to use festival-freebsoft-utils with Speech Dispatcher, you need not to make any special festival-freebsoft-utils arrangements. Just configure it as is described in the previous sections. It is particularly recommended to configure available languages if you want to use Festival for other languages than English, *Note Voice Selection::. This version of festival-freebsoft-utils requires Speech Dispatcher 0.5 or higher.  File: festival-freebsoft-utils.info, Node: Reference Manual, Next: Contact, Prev: User Customization, Up: Top 4 Reference Manual ****************** festival-freebsoft-utils consists of several modules described in the following sections. * Menu: * util.scm:: Miscellaneous utility functions. * wave.scm:: Wave form handling. * oo.scm:: Object oriented programming. * events.scm:: Generalized input events. * spell-mode.scm:: Spelling mode. * cap-signalization.scm:: Capital letter signalization. * punctuation.scm:: Punctuation reading modes. * tokenize.scm:: Alternative tokenization written in SIOD. * multiwave.scm:: Returning multiple wave forms for an event. * voice-select.scm:: Selecting voices and languages. * prosody-param.scm:: Changing prosodic parameters. * ssml-mode.scm:: Partial SSML support. * fileio.scm:: File utilities. * recode.scm:: Character set conversions. * speech-dispatcher.scm:: Speech Dispatcher interface.  File: festival-freebsoft-utils.info, Node: util.scm, Next: wave.scm, Up: Reference Manual 4.1 util.scm ============ This module contains miscellaneous utilities useful in general SIOD and Festival programming. Macros and functions mostly available in Lisp dialects: `when CONDITION BODY-FORM ...' If and only if CONDITION is true, evaluate `body-form's. `unless CONDITION BODY-FORM ...' If and only if CONDITION is false, evaluate `body-form's. `prog1 FORM ...' Evaluate all forms and return the return value of the first one. `let* BINDINGS BODY-FORM ...' The same as `let' except that variable bindings are applied sequentially rather than in parallel. `unwind-protect* PROTECTED-FORM CLEANUP-FORM ...' Evaluate PROTECTED-FORM, and after it is finished, whether successfully or with errors, evaluate all CLEANUP-FORMs. If PROTECTED-FORM was evaluated successfully, return its return value. Unlike Festival's `unwind-protect', `unwind-protect*' accepts multiple CLEANUP-FORMs and evaluates them even when PROTECTED-FORM doesn't signal an error. `first LIST' `second LIST' `third LIST' `fourth LIST' Return first, second, third or fourth element of LIST, respectively. `butlast LIST' Return the LIST without its last element. If LIST is empty, return an empty list. `min X Y' Return minimum of the two numeric values X and Y. `max X Y' Return maximum of the two numeric values X and Y. `abs X' Return absolute value of X. `remove-if TEST LIST' Return LIST with elements, for which the TEST call returns non-`nil', removed. The order of list elements is preserved. TEST must be a function of a single argument. `identity OBJECT' Return OBJECT. `complement FUNCTION' Return a function that is equivalent to function except that it returns the opposite truth value to the return value of function. `apply* FUNCTION ARGLIST' The same as `apply', except that it also works if FUNCTION is given as a string. `dolist (VAR ITEMS) BODY-FORM ...' Loop over ITEMS and perform BODY-FORMs over each of them, binding it to the variable VAR (unevaluated). `add-hook HOOK-VARIABLE HOOK-FUNCTION TO-END?' Add HOOK-FUNCTION to HOOK-VARIABLE if it is not already present there. HOOK-VARIABLE must be a variable containing a list. If TO-END? is true, add HOOK-FUNCTION to the end of the list contained in HOOK-VARIABLE, otherwise add it to the beginning. `assoc-set LIST KEY VALUE' Add the KEY-VALUE pair to the association `list' and return the resulting list. Contingent previously LIST entries stored under KEY are removed from the resulting list. `avalue-get KEY ALIST' Find the first ALIST element of the form `(KEY* `value')', where KEY* is `string-equal' to KEY, and return VALUE. `avalue-set! KEY ALIST VALUE' Destructively set the VALUE* of the first ALIST element of the form `(KEY* `value*')' to VALUE. Return ALIST. `avg . ARGS' Return average value of ARGS. `dirname PATH' Return the directory part of PATH. `make-temp-filename TEMPLATE' Return name of a (probably non-existent) temporary file. TEMPLATE is a basename of the file, that is formatted with the `format' function and must contain exactly one `%s' sequence to be replaced with a variable part of the file name. Actually, this function is somewhat limited by the available Festival system interface. So it is not safe, the file may be created before it is actually used or the function may fail with an error. But for simple purposes the function should work fine and it shouldn't be worse than the standard `make_tmp_filename' function. `with-temp-file FILENAME BODY' Macro that binds newly generated temporary file name to a local variable FILENAME and then performs BODY. The macro ensures the temporary file is deleted after finishing BODY in any way. `string-replace STRING FROM TO' Replace all occurrences of FROM by TO in STRING and return the result. Festival specific utilities: `item.has_feat ITEM FEATURE' Return true if and only if ITEM has FEATURE set. `langvar SYMBOL' Return language dependent value stored under SYMBOL. First, the variable named SYMBOL.LANGUAGE, where LANGUAGE is the language name as stored in the `Language' parameter is checked and if it is unbound, SYMBOL's value is returned. `current-voice-coding' Return character coding of the currently selected voice in Festival. The coding is taken from the `coding' attribute of the voice description, if it is undefined or `nil', ISO 8859-1 coding is assumed. The `coding' voice attribute is introduced by festival-freebsoft-utils, it is not a standard Festival feature. `utt-relation-top-items UTT RELATION' Return a list of top level items in RELATION in `utt'. `do-relation-items (VAR UTTERANCE RELATION) BODY-FORM ...' Loop over RELATION items of UTTERANCE, performing BODY-FORMs for each of them, binding it to the variable VAR. The macro arguments VAR and RELATION are not evaluated. `do-relation-top-items (VAR UTTERANCE RELATION) BODY-FORM ...' Similar to `do-relation-items', but loops only over the relation's top items.  File: festival-freebsoft-utils.info, Node: wave.scm, Next: oo.scm, Prev: util.scm, Up: Reference Manual 4.2 Wave form handling ====================== There are some utility functions to help handling wave forms: `wave-concat WAVES' Append wave forms and return the resulting wave form. WAVES must be a list of wave forms to append. `wave-subwave WAVE FROM-TIME TO-TIME' Return the part of WAVE form that starts at FROM-TIME and finishes at TO-TIME. Both times are in seconds. `wave-load FILENAME' Load and return a wave form from FILENAME. This function is similar to `wave.load', but more sound file formats (most significantly Ogg Vorbis, if your SoX installation supports it) can be loaded. `wave-utt WAVE' Create and return an utterance, that contains just the `Wave' relation holding WAVE. `wave-import-utt FILENAME' Create and return an utterance, that contains just the `Wave' relation holding a wave loaded from FILENAME via the function `wave-load'.  File: festival-freebsoft-utils.info, Node: oo.scm, Next: events.scm, Prev: wave.scm, Up: Reference Manual 4.3 oo.scm ========== Sometimes it is useful to extend a Festival function in some way. Standard Festival functions don't provide easy to use means for it. This module tries to fill the gap. The following macro allows you to wrap a defined function: `define-wrapper (FUNCTION ARG ...) WRAPPER-NAME . BODY)' Wrap FUNCTION with arguments ARG ... by the code BODY. Given function arguments must match the arguments of the wrapped function. WRAPPER-NAME is a symbol uniquely identifying the wrapper, it allows redefinition of the wrapper. One function can be wrapped by any number of wrappers. None of the `define-wrapper' arguments is evaluated. Within BODY, a function named `next-func' is automatically defined. It returns the next wrapper or the original function. Please note `next-func' is a function, not a variable, so its typical invocation looks as follows: `((next-func) ARG ...)'. `oo-ensure-function-wrapped FUNCTION-NAME' If a wrapped function gets redefined, its wrapper is lost. If you want to ensure the function is still wrapped before its use, you may call this function, with its symbol name as the argument. `oo-unwrapped FUNCTION-NAME' Return the original definition of a wrapped function. Example use: festival> (define (foo x) (+ x 42)) # festival> (foo 1) 43 festival> (define-wrapper (foo x) my-foo-wrapper (print "Foo called.") ((next-func) x)) nil festival> (foo 1) "Foo called." 43 You can also wrap parameters, set by `Param.set': `Param.wrap NAME WRAPPER-NAME . BODY' Wrap access to parameter NAME by code BODY. If the given parameter is accessed, its wrapper is invoked instead of just returning the parameter value. WRAPPER-NAME is the same as in `define-wrapper'. Macro `next-value' is automatically defined within BODY. It returns the parameter value, either plain or modified by another wrapper. Example use of parameter wrapping: festival> (Param.set 'foo 42) # festival> (Param.wrap foo foo-w (+ (next-value) 1)) nil festival> (Param.get 'foo) 43 And finally, the `glet*' macro allows you to dynamically bind a global variable value: `glet* BINDINGS . BODY' Similar to `let*' (*note util.scm::) except that the variables in BINDINGS are bound dynamically instead of lexically. All variables in BINDINGS must be global variables.  File: festival-freebsoft-utils.info, Node: events.scm, Next: spell-mode.scm, Prev: oo.scm, Up: Reference Manual 4.4 events.scm ============== For introductory and configuration information about events see *note Events::. The event module provides the following functions to synthesize events: `event-synth TYPE VALUE' Synthesize event of TYPE, which may be one of the following symbols: `logical', `text', `sound', `character', `key'. EVENT is the event value that must correspond to the event type. `event-play TYPE VALUE' Play event. The TYPE and VALUE arguments are the same as in `event-synth'. Logical events starting with underscore are reserved for special purposes. Currently, the following special purpose logical events are recognized: `_debug_on*' Turn on debugging. That means every processed event is logged. `_debug_off' is just a prefix, it can be followed by any symbol constituent characters. `_debug_off*' Turn the debugging off. `_debug_off' is just a prefix, it can be followed by any symbol constituent characters.  File: festival-freebsoft-utils.info, Node: spell-mode.scm, Next: cap-signalization.scm, Prev: events.scm, Up: Reference Manual 4.5 spell-mode.scm ================== Defines spelling mode, i.e. the mode in which the input text is spelled rather than read in the usual way. The `spell' mode is a normal Festival mode, so you can use it after loading this module immediately, e.g. (tts_file "file" 'spell)  File: festival-freebsoft-utils.info, Node: cap-signalization.scm, Next: punctuation.scm, Prev: spell-mode.scm, Up: Reference Manual 4.6 cap-signalization.scm ========================= Defines mode that allows signalling of capital letters through the logical event `capital'. *Note Capital Letters::, for more details. `set-cap-signalization-mode MODE' If MODE is true, enable capital letter signalling, otherwise disable it.  File: festival-freebsoft-utils.info, Node: punctuation.scm, Next: tokenize.scm, Prev: cap-signalization.scm, Up: Reference Manual 4.7 punctuation.scm =================== Sometimes it is useful to get read all the punctuation characters present in the synthesized text (for exact information about the text) and sometimes it is useful to read no punctuation character (for faster reading). Punctuation modes allow you to tell Festival, whether it should read punctuation characters or not. `set-punctuation-mode MODE' Set punctuation mode to MODE. MODE may be one of the following symbols: `all' meaning all the punctuation characters are read, `none' meaning no punctuation characters are read, and `default' that switches to the default Festival behavior corresponding to the current language and voice. *Note Punctuation Characters::, for information about punctuation mode configuration.  File: festival-freebsoft-utils.info, Node: tokenize.scm, Next: multiwave.scm, Prev: punctuation.scm, Up: Reference Manual 4.8 tokenize.scm ================ Festival's tokenization is implemented mostly in C++, so it is impossible to use it when extending Festival. The `tokenize' module provides an alternative tokenization implemented in SIOD, that can be used wherever needed. `next-chunk TEXT' Get the next part of TEXT and create an utterance containing the corresponding tokens. A list of two elements, the utterance and the remaining unprocessed part of TEXT, is returned. An alternative `SayText' function, splitting the text into smaller pieces (and thus speeding up the start of speech) might be implemented as follows: (define (SayText* text) (if (not (equal? text "")) (let ((utt-text (next-chunk text))) (let ((utt (car utt-text)) (text (cadr utt-text))) (utt.play (utt.synth utt)) (SayText* text)))))  File: festival-freebsoft-utils.info, Node: multiwave.scm, Next: voice-select.scm, Prev: tokenize.scm, Up: Reference Manual 4.9 multiwave.scm ================= Sometimes it is convenient to return multiple synthesized wave forms instead of a single wave form. There are two typical situations when this can happen: * You want to synthesize a long text and you don't want to wait until it is all synthesized, you want to play the resulting audio as soon as possible. The text can be cut into smaller pieces, returning the corresponding wave forms in a sequence. * The resulting wave form is a mixture of a synthesized texts and sound icons, of different rates or other sound sample parameters. Concatenating them together may reduce the resulting sound quality. So the different sound parts may be better returned separately. The `multiwave.scm' module provides the following interface for those purposes: `multi-synth TYPE VALUE' This function is similar to the `event-synth' function (*note events.scm::), except that it doesn't return an utterance containing the resulting wave form. Instead, it setups the synthesis for the following `multi-next' calls. `multi-next' Return the next wave form of the last event synthesized via the `multi-synth' function. If there is no next wave form, return `nil'. If you synthesize an SSML text, the function may return a non-`nil' symbol instead of a wave form. Then the symbol is a name of the mark just reached. `multi-clear' Throw away the synthesized data. You usually don't need to call this function as the data is cleared on the next `multi-synth' call automatically, but the function may be useful under special circumstances.  File: festival-freebsoft-utils.info, Node: voice-select.scm, Next: prosody-param.scm, Prev: multiwave.scm, Up: Reference Manual 4.10 voice-select.scm ===================== The voice-select module provides a mechanism for voice and language selection. For its configuration information, see *Note Voice Selection::. The following voice selection functions are available: `voice-list' Return the list of names of all available voices. Unlike the list returned by the standard Festival function `voice.list', the list includes all registered voices. `voice-list-language-codes' Return the list of names, language codes and dialect codes of all available voices. Each element of the returned list is of the form `(NAME LANGUAGE-CODE DIALECT-CODE)', where all the elements of the tripple are symbols. If the language code or the dialect code is not known for the voice, the corresponding element is `nil'. `current-language-voices' Return a list of all the voices available for the current language. `select-voice LANGUAGE DIALECT GENDER AGE VARIANT NAME' Select voice according to the specified parameters and return its name. LANGUAGE is the language name, DIALECT is a LANGUAGE dialect name. GENDER can be one of the symbols `male' or `female' (the value is currently ignored). `age' is age of the speaker in years given as a number. `variant' is a positive integer that selects one of several voices, if more than one voice is selected by all other parameters. NAME can be a particular voice name. Each of the function arguments can have `nil' as its value. In such a case, default value of the corresponding parameter is used. If there is no default value, the parameter is not considered in the selection process. If more than one voice matches, one of the matched voices is selected. If no voice satisfying all the given parameters is available, some voice satisfying the most important parameters is selected. `select-voice* LANG-CODE GENDER AGE VARIANT NAME' Like `select-voice', except that language and dialect are specified by an ISO LANG-CODE. `reset-voice' Reset currently selected voice parameters to their default values. Additionally, there is a variable holding information about voice properties currently in effect for the purpose of voice selection by the `voice-select' function: `voice-select-current-defaults' Alist containing current voice properties used by voice selection.  File: festival-freebsoft-utils.info, Node: prosody-param.scm, Next: ssml-mode.scm, Prev: voice-select.scm, Up: Reference Manual 4.11 prosody-param.scm ====================== Ever wished to be able to change prosodic parameters in Festival easily and in a uniform way for different voices? Well, here are the appropriate functions. They are no way guaranteed to work for all voices, since each voice can have its own unique way of prosody handling. But they should work for typical cases. `set-pitch VALUE' Set mean pitch of the voice to VALUE and return the old pitch value. VALUE is given in Hertz. `set-pitch-range VALUE' Set the pitch range of the voice to VALUE and return the old pitch range value. The value is in percents of the mean pitch, its clear meaning is not defined. `set-volume VALUE' Set volume to the given VALUE and return the old volume value. VALUE must be in the range 0-1 from silence to maximum (the default). `set-rate VALUE' Set voice rate to VALUE and return the old rate value. VALUE is in the range 0.1-10 from the slowest to the fastest. The value 1 corresponds to the normal voice speed, other values multiply the voice speed appropriately. The VALUE argument of all the functions above may also be a function of a single argument accepting the current parameter value and returning its new value. The following convenience functions return functions which adjust the parameter values appropriately: `prosody-shifted-value SHIFT' Return a function modifying the value by adding SHIFT to it. `prosody-relative-value COEF' Return a function modifying the value by multiplying it by COEF. Example setting doubling the current voice speed: (set-rate (prosody-relative-value 2)) When you switch to a different voice, prosody parameters get lost. festival-freebsoft-utils offers a way to restore them, using the following functions: `change-prosody FUNCTION VALUE' Similar to the `set-*' functions described above, except it additionally saves the set prosodic value. FUNCTION is one of the `set-*' functions and VALUE is its parameter value. `restore-prosody' Set prosodic parameters according to their current saved values. `reset-prosody' Reset the list of the saved prosodic values. Note, it just deletes the saved settings and doesn't actually change the current prosodic parameters.  File: festival-freebsoft-utils.info, Node: ssml-mode.scm, Next: fileio.scm, Prev: prosody-param.scm, Up: Reference Manual 4.12 ssml-mode.scm ================== festival-freebsoft-utils provides a text processing mode partially supporting the SSML 1.0 markup. You can process a SSML file in the following way in the Festival prompt: (tts_file "/the/path/to/the/file" 'ssml) Moreover, there are some particular SSML processing functions available: `ssml-say TEXT' Speak the given SSML TEXT. `ssml-parse TEXT' Parse the given SSML TEXT for later processing by the `ssml-next-chunk' function. `ssml-next-chunk' Return next utterance containing tokens from the last SSML text parsed by `ssml-parse' or a mark name. If there is no next utterance or mark, return `nil'. The returned utterance contains only the `Token' relation and is intended to be further processed with the `utt.synth' function. The returned mark name is a non-`nil' symbol. `ssml-speak-chunks' Speak the SSML text processed by `ssml-parse'. The `ssml-parse' and `ssml-next-chunk' functions are intended to be used when you want to synthesize an SSML text, but not to speak it immediately. A sample use of those functions for a hypothetic `ssml-say*' function similar to `ssml-say' might be as follows: (define (ssml-say* text) (ssml-parse text) (ssml-say*-1)) (define (ssml-say*-1) (let ((utt (ssml-next-chunk))) (if utt (begin (cond ((symbol? utt) (print utt)) (utt (utt.play (utt.synth utt)))) (ssml-say*-1))))) If you need quick synthesizer response, avoid the DOCTYPE declaration in your SSML data. The DOCTYPE declaration takes an observable time when processed in the Festival's XML parser. festival-freebsoft-utils does not provide conforming SSML implementation and implements only a limited subset of the standard. Moreover, due to the limitations of the built-in Festival XML parser, SSML markup texts that contain non-ASCII characters can only be processed with the `ssml-parse' and `ssml-next-chunk' functions and must be provided in the UTF-8 encoding. It is not easy to fully support SSML in Festival. Contingent support and contributions are welcome.  File: festival-freebsoft-utils.info, Node: fileio.scm, Next: recode.scm, Prev: ssml-mode.scm, Up: Reference Manual 4.13 fileio.scm =============== Functions in this module try to help to improve Festival file input/output. `with-open-file (VARIABLE FILENAME &optional HOW) BODY-FORM ...' Open file named FILENAME in mode HOW (for reading if not provided) and bind it to a newly created local VARIABLE. Execute BODY-FORMs in that context. `read-file FILENAME' Read and return whole contents of the file named FILENAME. `write-file FILENAME STRING' Write STRING to a file named FILENAME. `make-read-line-state' Create and return a state object required by the function `read-line'. `read-line FILE STATE' Read a single line from FILE and return it without the final newline character. If there is no next line in FILE, return `nil'. STATE is a state as initially returned by the `make-read-line-state' function. The typical `read-line' usage idiom is: (let ((state (make-read-line-state)) (f (fopen "...")) (line t)) (while line (set! line (read-line f state)) ...))  File: festival-freebsoft-utils.info, Node: recode.scm, Next: speech-dispatcher.scm, Prev: fileio.scm, Up: Reference Manual 4.14 recode.scm =============== Festival doesn't support different character sets directly. But it is 8-bit clean and you can use whatever character coding you like if you can process it in the form of 8-bit characters. The `recode.scm' module offers the following functions to convert between different character sets: `recode STRING FROM-CODING TO-CODING' Return given STRING, originally encoded in FROM-CODING, recoded to TO-CODING. `recode-utf8->current STRING' Return given STRING, originally encoded in `UTF-8', recoded to the coding of the current voice. Before applying normal recoding this function translates strings as specified in `recode-special-utf8-translations' variable. This allows you to convert some unicode characters in a special way, e.g. to translate empty space to space (thus separating words around it). `recode-special-utf8-translations' contains lists of two elements, the converted substring and its translation. The recoding functions use the `iconv' program and temporary files to convert between character sets. There is no known better way to do the conversions.  File: festival-freebsoft-utils.info, Node: speech-dispatcher.scm, Prev: recode.scm, Up: Reference Manual 4.15 speech-dispatcher.scm ========================== This module provides Speech Dispatcher interface. You need it if you want to use Festival as a Speech Dispatcher output text-to-speech system. The module defines functions required by the Speech Dispatcher Festival output module and user configuration variables, see *note Speech Dispatcher::. To ease debugging, for each Speech Dispatcher function which returns a wave form, there is defined a corresponding function of the same name with star appended, that returns an utterance instead of wave form. For instance, the function `speechd-speak' returns a wave form (and can be used only in server mode), while the function `speechd-speak*' returns an utterance.  File: festival-freebsoft-utils.info, Node: Contact, Next: Copying This Manual, Prev: Reference Manual, Up: Top 5 How to contact us ******************* The author of festival-freebsoft-utils is Milan Zamazal . The home page of festival-freebsoft-utils is `http://www.freebsoft.org/festival-freebsoft-utils/'. You can contact us with your comments, questions, suggestions, patches or anything at the Speech Dispatcher mailing list . Bug reports can be sent to the e-mail address . festival-freebsoft-utils is part of the Free(b)soft project aimed at making computers accessible to blind and sorely visually impaired people. The home page of the project is `http://www.freebsoft.org'.  File: festival-freebsoft-utils.info, Node: Copying This Manual, Next: Index, Prev: Contact, Up: Top Appendix A GNU Free Documentation License ***************************************** Version 1.2, November 2002 Copyright (C) 2000,2001,2002 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you". You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not "Transparent" is called "Opaque". Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text. A section "Entitled XYZ" means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as "Acknowledgements", "Dedications", "Endorsements", or "History".) To "Preserve the Title" of such a section when you modify the Document means that it remains a section "Entitled XYZ" according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled "History", Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled "Acknowledgements" or "Dedications", Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled "Endorsements". Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled "Endorsements" or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles. You may add a section Entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled "History" in the various original documents, forming one section Entitled "History"; likewise combine any sections Entitled "Acknowledgements", and any sections Entitled "Dedications". You must delete all sections Entitled "Endorsements." 6. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 7. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an "aggregate" if the copyright resulting from the compilation is not used to limit the legal rights of the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document's Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 8. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled "Acknowledgements", "Dedications", or "History", the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 9. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 10. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See `http://www.gnu.org/copyleft/'. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. A.0.1 ADDENDUM: How to use this License for your documents ---------------------------------------------------------- To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page: Copyright (C) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the "with...Texts." line with this: with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation. If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.  File: festival-freebsoft-utils.info, Node: Index, Prev: Copying This Manual, Up: Top Index ***** [index] * Menu: * _debug_off: events.scm. (line 28) * _debug_on: events.scm. (line 23) * abs X: util.scm. (line 53) * add-hook HOOK-VARIABLE HOOK-FUNCTION TO-END?: util.scm. (line 76) * apply* FUNCTION ARGLIST: util.scm. (line 68) * assoc-set LIST KEY VALUE: util.scm. (line 82) * author: Contact. (line 6) * avalue-get KEY ALIST: util.scm. (line 87) * avalue-set! KEY ALIST VALUE: util.scm. (line 91) * avg . ARGS: util.scm. (line 95) * bugs: Contact. (line 10) * butlast LIST: util.scm. (line 43) * change-prosody FUNCTION VALUE: prosody-param.scm. (line 51) * character: Events. (line 32) * complement FUNCTION: util.scm. (line 64) * contact: Contact. (line 6) * current-language-voices: voice-select.scm. (line 24) * current-voice-coding: util.scm. (line 134) * define-wrapper (FUNCTION ARG ...) WRAPPER-NAME . BODY): oo.scm. (line 12) * dirname PATH: util.scm. (line 98) * do-relation-items (VAR UTTERANCE RELATION) BODY-FORM ...: util.scm. (line 144) * do-relation-top-items (VAR UTTERANCE RELATION) BODY-FORM ...: util.scm. (line 149) * dolist (VAR ITEMS) BODY-FORM ...: util.scm. (line 72) * eou_tree: Tokenization. (line 6) * event-mappings: Events. (line 54) * event-play TYPE VALUE: events.scm. (line 15) * event-synth TYPE VALUE: events.scm. (line 10) * events: Events. (line 6) * FDL, GNU Free Documentation License: Copying This Manual. (line 6) * Festival: Motivation. (line 6) * first LIST: util.scm. (line 33) * fourth LIST: util.scm. (line 39) * Free(b)soft project: Contact. (line 15) * glet* BINDINGS . BODY: oo.scm. (line 69) * home page: Motivation. (line 39) * identity OBJECT: util.scm. (line 61) * inhibit-initial-pauses: Initial Pauses. (line 23) * item.has_feat ITEM FEATURE: util.scm. (line 125) * key: Events. (line 39) * language-codes: Voice Selection. (line 10) * languages: Voice Selection. (line 6) * langvar SYMBOL: util.scm. (line 128) * let* BINDINGS BODY-FORM ...: util.scm. (line 20) * logical: Events. (line 44) * long texts: multiwave.scm. (line 10) * looping: util.scm. (line 73) * mailing list: Contact. (line 10) * make-read-line-state: fileio.scm. (line 20) * make-temp-filename TEMPLATE: util.scm. (line 101) * math functions: util.scm. (line 96) * max X Y: util.scm. (line 50) * max-number-of-token-chars: Tokenization. (line 15) * max-number-of-tokens: Tokenization. (line 10) * min X Y: util.scm. (line 47) * multi-clear: multiwave.scm. (line 38) * multi-next: multiwave.scm. (line 29) * multi-synth TYPE VALUE: multiwave.scm. (line 23) * multiple wave forms: multiwave.scm. (line 6) * next-chunk TEXT: tokenize.scm. (line 11) * next-func: oo.scm. (line 20) * next-value: oo.scm. (line 53) * Ogg Vorbis: wave.scm. (line 17) * oo-ensure-function-wrapped FUNCTION-NAME: oo.scm. (line 25) * oo-unwrapped FUNCTION-NAME: oo.scm. (line 30) * Param.set: oo.scm. (line 45) * Param.wrap NAME WRAPPER-NAME . BODY: oo.scm. (line 47) * pauses: Initial Pauses. (line 6) * prog1 FORM ...: util.scm. (line 17) * prosody-relative-value COEF: prosody-param.scm. (line 40) * prosody-shifted-value SHIFT: prosody-param.scm. (line 37) * punctuation-pronunciation: Punctuation Characters. (line 11) * read-file FILENAME: fileio.scm. (line 14) * read-line FILE STATE: fileio.scm. (line 24) * recode STRING FROM-CODING TO-CODING: recode.scm. (line 12) * recode-special-utf8-translations: recode.scm. (line 16) * recode-utf8->current STRING: recode.scm. (line 16) * remove-if TEST LIST: util.scm. (line 56) * resampling: multiwave.scm. (line 15) * reset-prosody: prosody-param.scm. (line 59) * reset-voice: voice-select.scm. (line 50) * restore-prosody: prosody-param.scm. (line 56) * SayText <1>: tokenize.scm. (line 16) * SayText: User Customization. (line 12) * second LIST: util.scm. (line 35) * select-voice LANGUAGE DIALECT GENDER AGE VARIANT NAME: voice-select.scm. (line 27) * select-voice* LANG-CODE GENDER AGE VARIANT NAME: voice-select.scm. (line 46) * set-cap-signalization-mode MODE: cap-signalization.scm. (line 9) * set-event-mapping! EVENT-TYPE EVENT-VALUE NEW-EVENT-TYPE new-event-value: Events. (line 73) * set-pitch VALUE: prosody-param.scm. (line 12) * set-pitch-range VALUE: prosody-param.scm. (line 16) * set-punctuation-mode MODE: punctuation.scm. (line 12) * set-rate VALUE: prosody-param.scm. (line 26) * set-volume VALUE: prosody-param.scm. (line 21) * sound: Events. (line 27) * sound-icon-directory: Events. (line 27) * Speech Dispatcher: Motivation. (line 6) * Speech Synthesis Interface Protocol: Events. (line 39) * speechd-speak: speech-dispatcher.scm. (line 12) * spell: spell-mode.scm. (line 6) * SSML <1>: ssml-mode.scm. (line 6) * SSML: Events. (line 18) * ssml-next-chunk: ssml-mode.scm. (line 22) * ssml-parse TEXT: ssml-mode.scm. (line 18) * ssml-say TEXT: ssml-mode.scm. (line 15) * ssml-speak-chunks: ssml-mode.scm. (line 30) * string-replace STRING FROM TO: util.scm. (line 119) * text: Events. (line 15) * third LIST: util.scm. (line 37) * unless CONDITION BODY-FORM ...: util.scm. (line 14) * unwind-protect* PROTECTED-FORM CLEANUP-FORM ...: util.scm. (line 24) * utt-relation-top-items UTT RELATION: util.scm. (line 141) * voice-list: voice-select.scm. (line 12) * voice-list-language-codes: voice-select.scm. (line 17) * voice-select-current-defaults: voice-select.scm. (line 57) * voice-select-defaults: Voice Selection. (line 22) * voices: Voice Selection. (line 6) * Vorbis: wave.scm. (line 17) * wave forms: wave.scm. (line 6) * wave-concat WAVES: wave.scm. (line 8) * wave-import-utt FILENAME: wave.scm. (line 26) * wave-load FILENAME: wave.scm. (line 16) * wave-subwave WAVE FROM-TIME TO-TIME: wave.scm. (line 12) * wave-utt WAVE: wave.scm. (line 22) * when CONDITION BODY-FORM ...: util.scm. (line 11) * with-open-file (VARIABLE FILENAME &optional HOW) BODY-FORM ...: fileio.scm. (line 9) * with-temp-file FILENAME BODY: util.scm. (line 114) * word-mapping: Word Substitution. (line 9) * wrappers: oo.scm. (line 6) * write-file FILENAME STRING: fileio.scm. (line 17)  Tag Table: Node: Top1669 Node: Motivation3638 Node: Installation5293 Node: User Customization6638 Node: Events7966 Node: Word Substitution11295 Node: Capital Letters11787 Node: Punctuation Characters12500 Node: Initial Pauses13361 Node: Tokenization14316 Node: Voice Selection15059 Node: Speech Dispatcher16248 Node: Reference Manual17097 Node: util.scm18256 Node: wave.scm23646 Node: oo.scm24687 Node: events.scm27338 Node: spell-mode.scm28448 Node: cap-signalization.scm28867 Node: punctuation.scm29314 Node: tokenize.scm30246 Node: multiwave.scm31277 Node: voice-select.scm33082 Node: prosody-param.scm35655 Node: ssml-mode.scm38120 Node: fileio.scm40497 Node: recode.scm41723 Node: speech-dispatcher.scm43014 Node: Contact43850 Node: Copying This Manual44639 Node: Index67082  End Tag Table