Items consist of a bundle of features and a set of named links to nodes in relations. Items can be linked into any number of relations - in the above example words were linked into 2 relations, but in principle any number of relations is possible.
The information in items themselves are represented by features which are stored as a list of key-value pairs. Feature values are commonly numbers or strings, but may also take complex objects as values if necessary. A item can have arbitrarily many features, including zero: syllable items often have no features at all, for example.
As well as simple values, features can also take functions as values. Function features are a powerful facility which can help to greatly reduce the amount of redundant information in a utterance structure.
Consider the case of a simple phone segmentation of an utterance, which comprises a contiguous list of named segments each with timing information. If the phones are properly contiguous, only one timing value for each phone is needed to fully represent all the timing information of the segmentation. If the end point is used, the start time of an item will be equal to the end point of the previous item and the duration will be equal to the start subtracted from the end. However, it is often useful to have access to the start times and duration of the phone also. Without the use of function features, there are two choices. Either the end information alone can be stored and calculations can be done on the fly to compute start times and durations, or else the start and durations can be written in as additional features to the item. The first solution is unattractive as this can make algorithm writing unwieldy and overly complicated. While the second solution will may make algorithm writing easier, it involves effectively copying information, which can lead to out of date information being present.
Function features provide a neat solution to this problem. In the current example, a start function is written (in Festival this can be written in C++ or scheme) which looks at the previous item and returns its end. This function is then assigned as the value of a key named ``start'' in the items in question. When one accesses the start feature a time value is returned as if it were actually stored. A duration function returns the value of the start feature subtracted from the end feature. The duration function simply evaluates the feature named ``start'' - it doesn't need to know if it is a simple feature or a function feature.
In our current usage of the Festival architecture, we only keep time positions in items linked to the segment relation: all other times are calculated by functions. Different start functions can be written for different purposes. For example, the end function assigned to the non-terminal nodes in the syntax tree descends from the current node until a terminal node is encountered and that node's item's end value is returned. Of course the terminal node's item, being a word, has its end feature as a function also - a common operation is for the word's end function to return the time of the last syllable it is related to, which returns the time of the last phone etc. In each case a separate end function is used, but all are assigned to the key ``end'' in the item. This means that algorithms can evaluate the end feature on any item, and be sure of a legitimate value being returned without having to worry about the details of calculation.
Although the function feature implementation is very efficient in Festival, it can still sometimes be expense to constantly evaluate these functions in the middle of a time critical loop. A global evaluation facility is therefore provided which can evaluate all the feature functions in items in a relation and re-write the features with their evaluation. After the loop, these can be discarded and the feature functions used again, thus ensuring little chance of out of date information being present.
Function features can be used for a variety of purposes other than timing. Another common usage in Festival is to use functions for intonation. Typically, intonation accents are associated with syllables. Thus one can ask whether a syllable is accented or not. However it is also useful to know if words are accented also. In this case we define a function feature on word items which looks at that word's main stressed syllable and returns true if that syllable is accented.