001/*
002 * Copyright (C) 2005 DFKI GmbH. All rights reserved.
003 */
004package com.sun.speech.freetts.diphone;
005
006import java.io.DataOutputStream;
007import java.io.IOException;
008import java.nio.ByteBuffer;
009
010import com.sun.speech.freetts.relp.Sample;
011
012/**
013 * Represent an alias diphone which is just another name for an
014 * already-existing original diphone. This can be used just like a
015 * "real" diphone. 
016 * @author Marc Schröder
017 *
018 */
019public class AliasDiphone extends Diphone
020{
021    private String originalName;
022    private Diphone original;
023    /**
024     * @param name The alias name to use for the existing diphone
025     * @param originalName the original name of the diphone.
026     */
027    public AliasDiphone(String name, String originalName)
028    {
029        super(name);
030        this.originalName = originalName;
031    }
032
033    /**
034     * Get the name of the original name that this alias points to.
035     */
036    public String getOriginalName()
037    {
038        return originalName;
039    }
040    
041    /**
042     * Associate the actual diphone object of the original with this alias.
043     * @param original a diphone object whose getName() must return the same
044     * as our getOriginalName().
045     * @throws IllegalArgumentException if the diphone to be registered as the
046     * original has a name which is different from this AliasDiphone's original name
047     * as returned by getOriginalName().
048     */
049    public void setOriginalDiphone(Diphone original)
050    {
051        if (!originalName.equals(original.getName())) {
052            throw new IllegalArgumentException("The diphone to register ("+original.getName()
053                    +") does not match the original name ("+originalName+")");
054        }
055        this.original = original;
056    }
057    
058    /**
059     * Returns the samples associated with this diphone.
060     *
061     * @return the samples associated with this diphone
062     */
063    public Sample[] getSamples() {
064    return original.getSamples();
065    }
066
067    /**
068     * Returns a particular sample.
069     *
070     * @param which which sample to return
071     *
072     * @return the desired sample
073     */
074    public Sample getSamples(int which) {
075    return original.getSamples(which);
076    }
077
078    /**
079     * Returns the midpoint index. the midpoint index is the sample
080     * that divides the diphone into the first and second parts.
081     *
082     * @return the midpoint index.
083     */
084    public int getMidPoint() {
085    return original.getMidPoint();
086    }
087    
088    /**
089     * Returns the midpoint index. the midpoint index is the sample
090     * that divides the diphone into the first and second parts.
091     *
092     * @return the midpoint index.
093     */
094    public int getPbPositionMillis() {
095    return original.getPbPositionMillis();
096    }
097
098    /**
099     * Returns the sample that is closest to uIndex.
100     *
101     * @param uIndex the desired index
102     * @param unitPart do we want the first have (1) or the second
103     *      half (2)
104     *
105     * @return the sample nearest to the given index in the given
106     *      part
107     */ 
108    public Sample nearestSample(float uIndex, int unitPart) {
109        return original.nearestSample(uIndex, unitPart);
110    }
111
112    /**
113     * Returns the total number of residuals in the given part for this
114     * diphone.
115     *
116     * @param unitPart indicates which part is of interest (1 or 2)
117     *
118     * @return the number of residuals in the specified part
119     */
120    public int getUnitSize(int unitPart) {
121        return original.getUnitSize(unitPart);
122    }
123
124    /**
125     * dumps out this Diphone.
126     */
127    public void dump() {
128    System.out.println("AliasDiphone: " + getName() + " aliased to " + original.getName());
129    }
130
131    /**
132     * Dumps the diphone to the given channel.
133     *
134     * @param bb the ByteBuffer to write to
135     *
136     * @throws IOException if IO error occurs
137     */
138    public void dumpBinary(ByteBuffer bb) throws IOException {
139        char[] nameArray = (getName() + "        ").toCharArray();
140        char[] origNameArray = (original.getName() + "        ").toCharArray();
141
142        bb.putInt(ALIAS_MAGIC);
143        for (int i = 0; i < NAME_LENGTH; i++) {
144            bb.putChar(nameArray[i]);
145        }
146        for (int i = 0; i < NAME_LENGTH; i++) {
147            bb.putChar(origNameArray[i]);
148        }
149    }
150
151    /**
152     * Dumps the diphone to the given channel.
153     *
154     * @param os the DataOutputStream to write to
155     *
156     * @throws IOException if IO error occurs
157     */
158    public void dumpBinary(DataOutputStream os) throws IOException {
159        char[] nameArray = (getName() + "        ").toCharArray();
160        char[] origNameArray = (original.getName() + "        ").toCharArray();
161
162        os.writeInt(ALIAS_MAGIC);
163        for (int i = 0; i < NAME_LENGTH; i++) {
164            os.writeChar(nameArray[i]);
165        }
166        for (int i = 0; i < NAME_LENGTH; i++) {
167            os.writeChar(origNameArray[i]);
168        }
169    }
170
171    /**
172     * Determines if the two diphones are equivalent. This is for
173     * testing databases. This is not the same as "equals".
174     * For aliased diphones, this will return true if the compare() method
175     * of the original diphone returns true, even if the name used in this alias 
176     * is different.
177     *
178     * @param other the diphone to compare this one to
179     *
180     * @return <code>true</code> if the diphones match; otherwise
181     *      <code>false</code> 
182     */
183    boolean compare(Diphone other) {
184        return original.compare(other);
185    }
186
187}