Software: Apache/2.2.3 (CentOS). PHP/5.1.6 uname -a: Linux mx-ll-110-164-51-230.static.3bb.co.th 2.6.18-194.el5PAE #1 SMP Fri Apr 2 15:37:44 uid=48(apache) gid=48(apache) groups=48(apache) Safe-mode: OFF (not secure) /usr/share/doc/festival-1.95/ drwxr-xr-x |
Viewing file: festival_27.html (23.47 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
27 ProgrammingThis chapter covers aspects of programming within the Festival environment, creating new modules, and modifying existing ones. It describes basic Classes available and gives some particular examples of things you may wish to add. 27.1 The source codeThe ultimate authority on what happens in the system lies in the source code itself. No matter how hard we try, and how automatic we make it, the source code will always be ahead of the documentation. Thus if you are going to be using Festival in a serious way, familiarity with the source is essential. The lowest level functions are catered for in the Edinburgh Speech Tools, a separate library distributed with Festival. The Edinburgh Speech Tool Library offers the basic utterance structure, waveform file access, and other various useful low-level functions which we share between different speech systems in our work. See section `Overview' in Edinburgh Speech Tools Library Manual. The directory structure for the Festival distribution reflects the conceptual split in the code.
One intended use of Festival is offer a software system where new modules may be easily tested in a stable environment. We have tried to make the addition of new modules easy, without requiring complex modifications to the rest of the system. All of the basic modules should really be considered merely as example modules. Without much effort all of them could be improved. 27.2 Writing a new moduleThis section gives a simple example of writing a new module. showing the basic steps that must be done to create and add a new module that is available for the rest of the system to use. Note many things can be done solely in Scheme now and really only low-level very intensive things (like waveform synthesizers) need be coded in C++. 27.2.1 Example 1: adding new modulesThe example here is a duration module which sets durations of phones for a given list of averages. To make this example more interesting, all durations in accented syllables are increased by 1.5. Note that this is just an example for the sake of one, this (and much better techniques) could easily done within the system as it is at present using a hand-crafted CART tree.
Our knew module, called #include <festival.h> The module itself must be declared in a fixed form. That is receiving a single LISP form (an utterance) as an argument and returning that LISP form at the end. Thus our definition will start LISP FT_Duration_Simple(LISP utt) { Next we need to declare an utterance structure and extract it from the LISP form. We also make a few other variable declarations EST_Utterance *u = get_c_utt(utt); EST_Item *s; float end=0.0, dur; LISP ph_avgs,ldur; We cannot list the average durations for each phone in the source code as we cannot tell which phoneset we are using (or what modifications we want to make to durations between speakers). Therefore the phone and average duration information is held in a Scheme variable for easy setting at run time. To use the information in our C++ domain we must get that value from the Scheme domain. This is done with the following statement. ph_avgs = siod_get_lval("phoneme_averages","no phoneme durations");
The first argument to Now that we have the duration data we can go through each segment in the utterance and add the duration. The loop looks like for (s=u->relation("Segment")->head(); s != 0; s = next(s)) {
We can lookup the average duration of the current segment name
using the function ldur = siod_assoc_str(s->name(),ph_avgs);
Note the return value is actually a LISP pair (phone name and duration),
or if (ldur == NIL) { cerr << "Phoneme: " << s->name() << " no duration " << endl; dur = 0.100; } else dur = get_c_float(car(cdr(ldur))); If this phone is in an accented syllable we wish to increase its duration by a factor of 1.5. To find out if it is accented we use the feature system to find the syllable this phone is part of and find out if that syllable is accented. if (ffeature(s,"R:SylStructure.parent.accented") == 1) dur *= 1.5;
Now that we have the desired duration we increment the end += dur; s->fset("end",end); } Finally we return the utterance from the function. return utt; }
Once a module is defined it must be declared to the system so it may be
called. To do this one must call the function
In `./src/Duration/' the function LISP FT_Duration_Simple(LISP args);
While at the end of the function festival_def_utt_module("Duration_Simple",FT_Duration_Simple, "(Duration_Simple UTT)\n\ Label all segments with average duration ... ");
In order for our new file to be compiled we must add it
to the `Makefile' in that directory, to the Of course we are not quite finished. We still have to say when our new duration module should be called. When we set (Parameter.set 'Duration_Method Duration_Simple)
for a voice it will use our new module, calls to the function
Note in earlier versions of Festival it was necessary to modify the duration calling function in `lib/duration.scm' but that is no longer necessary. 27.2.2 Example 2: accessing the utteranceIn this example we will make more direct use of the utterance structure, showing the gory details of following relations in an utterance. This time we will create a module that will name all syllables with a concatenation of the names of the segments they are related to. As before we need the same standard includes #include "festival.h" Now the definition the function LISP FT_Name_Syls(LISP utt) { As with the previous example we are called with an utterance LISP object and will return the same. The first task is to extract the utterance object from the LISP object. EST_Utterance *u = get_c_utt(utt); EST_Item *syl,*seg; Now for each syllable in the utterance we want to find which segments are related to it. for (syl=u->relation("Syllable")->head(); syl != 0; syl = next(syl)) { Here we declare a variable to cummulate the names of the segments. EST_String sylname = "";
Now we iterate through the for (seg=daughter1(syl,"SylStructure"); seg; seg=next(seg)) sylname += seg->name(); Finally we set the syllables name to the concatenative name, and loop to the next syllable. syl->set_name(sylname); } Finally we return the LISP form of the utterance. return utt; } 27.2.3 Example 3: adding new directoriesIn this example we will add a whole new subsystem. This will often be a common way for people to use Festival. For example let us assume we wish to add a formant waveform synthesizer (e.g like that in the free `rsynth' program). In this case we will add a whole new sub-directory to the modules directory. Let us call it `rsynth/'. In the directory we need a `Makefile' of the standard form so we should copy one from one of the other directories, e.g. `Intonation/'. Standard methods are used to identify the source code files in a `Makefile' so that the `.o' files are properly added to the library. Following the other examples will ensure your code is integrated properly. We'll just skip over the bit where you extract the information from the utterance structure and synthesize the waveform (see `donovan/donovan.cc' or `diphone/diphone.cc' for examples). To get Festival to use your new module you must tell it to compile the directory's contents. This is done in `festival/config/config'. Add the line ALSO_INCLUDE += rsynth to the end of that file (there are simialr ones mentioned). Simply adding the name of the directory here will add that as a new module and the directory will be compiled.
What you must provide in your code is a function
#include "festival.h" static LISP utt_rtsynth(LISP utt) { EST_Utterance *u = get_c_utt(utt); // Do format synthesis return utt; } void festival_rsynth_init() { proclaim_module("rsynth"); festival_def_utt_module("Rsynth_Synth",utt_rsynth, "(Rsynth_Synth UTT) A simple formant synthesizer"); ... }
Integration of the code in optional (and standard directories) is done
by automatically creating `src/modules/init_modules.cc' for the
list of standard directories plus those defined as
This mechanism is specifically designed so you can add modules to the system without changing anything in the standard distribution. 27.2.4 Example 4: adding new LISP objectsThis third examples shows you how to add a new Object to Scheme and add wraparounds to allow manipulation within the the Scheme (and C++) domain.
Like example 2 we are assuming this is done in a new directory.
Suppose you have a new object called #include "festival.h" #include "widget.h" // definitions for the widget class
In order to register the widgets as Lisp objects we actually
need to register them as VAL_REGISTER_CLASS(widget,Widget) SIOD_REGISTER_CLASS(widget,Widget) The first names given to these functions should be a short mnenomic name for the object that will be used in the defining of a set of access and construction functions. It of course must be unique within the whole systems. The second name is the name of the object itself. To understand its usage we can add a few simple widget maniplutation functions LISP widget_load(LISP filename) { EST_String fname = get_c_string(filename); Widget *w = new Widget; // build a new widget if (w->load(fname) == 0) // successful load return siod(w); else { cerr << "widget load: failed to load \"" << fname << "\"" << endl; festival_error(); } return NIL; // for compilers that get confused }
Note that the function If you want refer to these functions in other files within your models you can use VAL_REGISTER_CLASS_DCLS(widget,Widget) SIOD_REGISTER_CLASS_DCLS(widget,Widget) in a common `.h' file The following defines a function that takes a LISP object containing a widget, aplies some method and returns a string. LISP widget_apply(LISP lwidget, LISP string, LISP param) { Widget *w = widget(lwidget); EST_String s = get_c_string(string); float p = get_c_float(param); EST_String answer; answer = w->apply(s,p); return strintern(answer); }
The function Finally you wish to add these functions to the Lisp system void festival_widget_init() { init_subr_1("widget.load",widget_load, "(widget.load FILENAME)\n\ Load in widget from FILENAME."); init_subr_3("widget.apply",widget_apply, "(widget.apply WIDGET INPUT VAL)\n\ Returns widget applied to string iNPUT with float VAL."); }
In yout `Makefile' for this directory you'll need to add
the include directory where `widget.h' is, if it is not
contained within the directory itself. This done through
the make variable LOCAL_INCLUDES = -I/usr/local/widget/include And for the linker you 'll need to identify where your widget library is. In your `festival/config/config' file at the end add COMPILERLIBS += -L/usr/local/widget/lib -lwidget Go to the first, previous, next, last section, table of contents. |
:: Command execute :: | |
:: Shadow's tricks :D :: | |
Useful Commands
|
:: Preddy's tricks :D :: | |
Php Safe-Mode Bypass (Read Files)
|
--[ c999shell v. 1.0 pre-release build #16 Modded by Shadow & Preddy | RootShell Security Group | r57 c99 shell | Generation time: 0.0087 ]-- |