001/**
002 * Copyright 2002 DFKI GmbH.
003 * All Rights Reserved.  Use is subject to license terms.
004 *
005 * See the file "license.terms" for information on usage and
006 * redistribution of this file, and for a DISCLAIMER OF ALL
007 * WARRANTIES.
008 */
009
010package de.dfki.lt.freetts.mbrola;
011
012import com.sun.speech.freetts.Item;
013import com.sun.speech.freetts.ProcessException;
014import com.sun.speech.freetts.Relation;
015import com.sun.speech.freetts.Utterance;
016import com.sun.speech.freetts.UtteranceProcessor;
017
018/**
019 * Utterance processor converting phoneme timing and f0-time targets
020 * into MBROLA format.
021 */
022public class ParametersToMbrolaConverter implements UtteranceProcessor {
023
024    /**
025     * Convert phoneme timing and f0-time targets
026     * into MBROLA format. The results are saved in the Segment relations,
027     * as features <code>"mbr_dur"</code> (int-valued) and
028     * <code>"mbr_targets"</code> (String-valued). MBROLA-converted targets
029     * are saved in the Segment relation because in MBROLA input, targets
030     * are represented as properties of the segments during which they occur.
031     *
032     * @param  utterance  the utterance to process
033     *
034     * @throws ProcessException if an error occurs while
035     *         processing of the utterance
036     */
037    public void processUtterance(Utterance utterance) throws ProcessException {
038        Relation segmentRelation = utterance.getRelation(Relation.SEGMENT);
039        Relation targetRelation = utterance.getRelation(Relation.TARGET);
040
041        Item segment = segmentRelation.getHead();
042        Item target = null;
043        if (targetRelation != null) target = targetRelation.getHead();
044        float prevEnd = 0f;
045        while (segment != null) {
046            // String name = segment.getFeatures().getString("name");
047            // Accumulated duration of all segments in the utterance,
048            // in seconds:
049            float end = segment.getFeatures().getFloat("end");
050            // Individual duration of segment, in milliseconds:
051            int dur = (int) ((end - prevEnd) * 1000);
052            StringBuffer targetStringBuffer = new StringBuffer();
053            while (target != null &&
054                   target.getFeatures().getFloat("pos") <= end) {
055                float pos = target.getFeatures().getFloat("pos");
056                // time axis as percentage of segment duration:
057                int percentage = ((int) ((pos - prevEnd) * 1000)) * 100 / dur;
058                // f0 as an integer:
059                int f0 = (int) target.getFeatures().getFloat("f0");
060                targetStringBuffer.append(" ");
061                targetStringBuffer.append(percentage);
062                targetStringBuffer.append(" ");
063                targetStringBuffer.append(f0);
064                target = target.getNext();
065            }
066            // System.err.println(name + " " + dur + targetStringBuffer);
067            segment.getFeatures().setInt("mbr_dur", dur);
068            segment.getFeatures().setString("mbr_targets",
069                                            targetStringBuffer.toString().trim());
070            prevEnd = end;
071            segment = segment.getNext();
072        }
073    }
074
075    public String toString() {
076        return "ParametersToMbrolaConverter";
077    }
078}