This is done by evaluating a set of phonetic exponency rules, which have the following general form:
Category:Features --> ... Parameter(T0 .. T) = (V0 .. V).
Parameter
indicates a parameter for the synthesizer
(T0 .. T)
indicates points in time relative to the start time of a constituent
(V0 .. V)
indicates corresponding values between which the parameter should be interpolated
...
indicates optional pickup of values from the exponecy database, and the consultation of lookup tables
As exponency rules are evaluated, parameter tracks are added to a database, which is treated as a stack:
parameter_track(Parameter, T0, T, V0, V)The following predicate is used to retrieve values from this database:
value(Parameter, Time, Value) :- parameter_track(Parameter, T0, T, V0, V), T0 <= Time, T >= Time, !, Value is V0 + (Time - T0) * ((V - V) / (T - T0)). value(Parameter, _, Default) :- parameter_default(Parameter, Default).
Exponency rules for F2:
Nu --> A = END, B = F2_VALUE, f2(170, A) = (B, B). Co:[BACK, AFFRICATE] --> A = END, B = f2(-35), f2(-35, 10, 95, A) = (B, 1760+0.1*(B-1760), 2100, 1740).
END
calls a built-in macro that returns the end time of the current constituent relative to the start time
F2_VALUE
is a reference to a lookup table
f2(-35)
picks up a value for F2 at a point in time 35 ms before the start of the current constituent.
F2_VALUE = 1400 :- Nu:[MID, SPREAD]. F2_VALUE = 850 :- Nu:[MID, ROUND].The evaluation of these rules is shown below for the inputs /@J/ (spread vowel, voiced affricate) and /oC/ (rounded vowel, voiceless affricate):
/@J/ /oC/