Package com.sun.speech.freetts.diphone

Source Code of com.sun.speech.freetts.diphone.DiphoneUnitDatabase

/**
* Portions Copyright 2003 Sun Microsystems, Inc.
* Portions Copyright 1999-2001 Language Technologies Institute,
* Carnegie Mellon University.
* All Rights Reserved.  Use is subject to license terms.
*
* See the file "license.terms" for information on usage and
* redistribution of this file, and for a DISCLAIMER OF ALL
* WARRANTIES.
*/
package com.sun.speech.freetts.diphone;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.sun.speech.freetts.relp.Sample;
import com.sun.speech.freetts.relp.SampleInfo;
import com.sun.speech.freetts.util.BulkTimer;
import com.sun.speech.freetts.util.Utilities;

/**
* Represents and manages the unit data for all diphones.  The diphone
* data set is stored in a set of data files. These data are loaded by this
* class into internal data structures before diphone synthesis can
* occur.
* <p>
*The diphone data set is one of the largest sets of data that
* needs to be loaded by the synthesizer and therefore can add to the
* overall startup time for any system using this database.  For
* certain applications, the startup time is a critical spec that
* needs to be optimized, while for other applications, startup time
* is inconsequential.  This class provides settings (via system
* properties) that control how the database is to be loaded so that
* applications can tune for quick startup or optimal run time.
* <p>
* This class serves also as a testbed for comparing performance of
* the traditional java binary I/O and the new io ( <code>java.nio </code>)
* package.
* <p>
* <p> A diphone database can be loaded from a text data file, or a
* binary datafile.  The binary version loads significantly faster
* than the text version. Additionally, a binary index can be
* generated and used to reduce overall memory footprint.
* <p>
* <p>
* A DiphoneUnitDatabase contains an array of frames, and an aray of
* residuals. The frames are the samples of the wave, and the
* residuals are for linear predictive coding use. This is called
* "cst_sts" (a struct) in flite.
* <p>
* Note that if 'com.sun.speech.freetts.useNewIO' is set to true and
* the input type is binary, than the JDK1.4+ new IO api is used to
* load the database.
* <p>
* The system property
* <pre>
*  com.sun.speech.freetts.diphone.UnitDatabase.cacheType
* </pre>
*
* can be set to one of:
*
* <ul>
* <li> preload: database is loaded at startup
* <li> demand: database is loaded on demand
* <li> hard: database is loaded on demand but cached
* <li> soft: database is loaded on demand but cached with soft references
* </ul>
*
* This <code> cacheType </code> setting controls how the database is
* loaded. The default is to 'preload' the database. This setting
* gives best runtime performance but with longer initial startup
* cost. 
*/
public class DiphoneUnitDatabase {
    /** Logger instance. */
    private static final Logger LOGGER =
        Logger.getLogger(DiphoneUnitDatabase.class.getName());

    private String name;
    private int sampleRate;
    private int numChannels;
    private int residualFold = 1;
    private float lpcMin;
    private float lpcRange;
    private int lineCount = 0;
    private Diphone defaultDiphone;
    private Map diphoneMap = null;
    private Map diphoneIndex;
    private SampleInfo sampleInfo;
   
    private boolean useNewIO =
  Utilities.getProperty("com.sun.speech.freetts.useNewIO",
    "true").equals("true");
    // cache can be 'preload' 'none', 'soft' or 'hard'
    private String cacheType =
  Utilities.getProperty(
      "com.sun.speech.freetts.diphone.UnitDatabase.cacheType",
      "preload");
    private boolean useIndexing = !cacheType.equals("preload");
    private boolean useCache = !cacheType.equals("demand");
    private boolean useSoftCache = cacheType.equals("soft");

    private final static int MAGIC = 0xFEEDFACE;
    private final static int INDEX_MAGIC = 0xFACADE;
    private final static int VERSION = 1;
    private final static int MAX_DB_SIZE = 4 * 1024 * 1024;

    private String indexName = null;
    private MappedByteBuffer mbb = null;
    private int defaultIndex = -1;

    /**
     * Creates the DiphoneUnitDatabase from the given input stream.
     *
     * @param url the location of the database
     * @param isBinary if <code>true</code> the database is in
     *    binary format; otherwise it is in text format
     *
     * @throws IOException if there is trouble opening the DB
     */
    public DiphoneUnitDatabase(URL url, boolean isBinary) throws IOException {
        // MS, 22.04.2005: Commented out the "if" clause:
        // indexing is applied only when useNewIO is turned on and
        // data is read from a FileInputStream. This is not true when useing
        // the default settings but setting
        // com.sun.speech.freetts.diphone.UnitDatabase.cacheType=demand
        //if (!useIndexing || useCache) {
      diphoneMap = new LinkedHashMap();
      //}
  InputStream is = Utilities.getInputStream(url);

  indexName = getIndexName(url.toString());

  if (isBinary) {
      loadBinary(is);
  } else {
      loadText(is);
  }
  is.close();
  sampleInfo = new SampleInfo(sampleRate, numChannels,
    residualFold, lpcMin, lpcRange, 0.0f);
    }

    /**
     * Return the information about the sample data
     * for this database.
     *
     * @return the sample info
     */

    SampleInfo getSampleInfo() {
  return sampleInfo;
    }


    /**
     * Returns the index name from the databaseName.
     *
     * @param databaseName the database name
     *
     * @return the index name or null if the database is not
     *          a binary database.
     *
     * [[[ TODO the index should probably be incorporated into the
     * binary database ]]]
     */
    private String getIndexName(String databaseName) {
  String indexName = null;
  if (databaseName.lastIndexOf(".") != -1) {
      indexName = databaseName.substring(0,
        databaseName.lastIndexOf(".")) + ".idx";
  }
  return indexName;
    }

    /**
     * Loads the database from the given input stream.
     *
     * @param is the input stream
     */
    private void loadText(InputStream is) {
        BufferedReader reader;
        String line;

  if (is == null) {
      throw new Error("Can't load diphone db file.");
  }

  reader = new BufferedReader(new InputStreamReader(is));
        try {
            line = reader.readLine();
      lineCount++;
            while (line != null) {
                if (!line.startsWith("***")) {
                    parseAndAdd(line, reader);
                }
                line = reader.readLine();
            }
      reader.close();
        } catch (IOException e) {
            throw new Error(e.getMessage() + " at line " + lineCount);
        } finally {
  }
    }

    /**
     * Parses and process the given line. Used to process the text
     * form of the database.
     *
     * @param line the line to process
     * @param reader the source for the lines
     */
    private void parseAndAdd(String line, BufferedReader reader) {
  try {
      StringTokenizer tokenizer = new StringTokenizer(line," ");
      String tag = tokenizer.nextToken();
      if (tag.equals("NAME")) {
    name = tokenizer.nextToken();
      } else if (tag.equals("SAMPLE_RATE")) {
    sampleRate = Integer.parseInt(tokenizer.nextToken());
      } else if (tag.equals("NUM_CHANNELS")) {
    numChannels = Integer.parseInt(tokenizer.nextToken());
      } else if (tag.equals("LPC_MIN")) {
    lpcMin  = Float.parseFloat(tokenizer.nextToken());
      } else if (tag.equals("COEFF_MIN")) {
    lpcMin  = Float.parseFloat(tokenizer.nextToken());
      } else if (tag.equals("COEFF_RANGE")) {
    lpcRange  = Float.parseFloat(tokenizer.nextToken());
      } else if (tag.equals("LPC_RANGE")) {
    lpcRange  = Float.parseFloat(tokenizer.nextToken());
      } else if (tag.equals("ALIAS")) {
            String name = tokenizer.nextToken();
            String origName = tokenizer.nextToken();
            AliasDiphone diphone = new AliasDiphone(name, origName);
            add(diphone);
        } else if (tag.equals("DIPHONE")) {
    String name = tokenizer.nextToken();
    int start  = Integer.parseInt(tokenizer.nextToken());
    int mid = Integer.parseInt(tokenizer.nextToken());
    int end = Integer.parseInt(tokenizer.nextToken());
    int numSamples = (end - start);
    int midPoint = mid - start;

    if (numChannels <= 0) {
        throw new Error("For diphone '"+name+"': Bad number of channels " + numChannels);
    }

    if (numSamples <= 0) {
        throw new Error("For diphone '"+name+"': Bad number of samples " + numSamples);
    }

    Sample[] samples = new Sample[numSamples];

    for (int i = 0; i < samples.length; i++) {
        samples[i] = new Sample(reader, numChannels);
    }
    Diphone diphone = new Diphone(name, samples, midPoint);
    add(diphone);
      } else {
    throw new Error("Unsupported tag " + tag);
      }
  } catch (NoSuchElementException nse) {
      throw new Error("Error parsing db " + nse.getMessage());
  } catch (NumberFormatException nfe) {
      throw new Error("Error parsing numbers in db " + nfe.getMessage());
  }
    }


    /**
     * Adds the given diphone to the DB. Diphones are kept in a map so
     * they can be accessed by name.
     *
     * @param diphone the diphone to add.
     */
    private void add(Diphone diphone) {
        if (diphone instanceof AliasDiphone) {
            AliasDiphone adiph = (AliasDiphone) diphone;
            Diphone original = (Diphone)
                diphoneMap.get(adiph.getOriginalName());
            if (original != null) {
                adiph.setOriginalDiphone(original);
            } else {
                // No original was found for this alias
                // -- complain, and ignore
                if (LOGGER.isLoggable(Level.FINER)) {
                    LOGGER.finer("For diphone alias "
                        +adiph.getName()+", could not find original "
                        +adiph.getOriginalName());
                }
                return;
            }
        }
  diphoneMap.put(diphone.getName(), diphone);
  if (defaultDiphone == null) {
      defaultDiphone = diphone;
  }
    }

    /**
     * Looks up the diphone with the given name.
     *
     * @param unitName the name of the diphone to look for
     *
     * @return the diphone or the defaultDiphone if not found.
     */
    public Diphone getUnit(String unitName) {
  Diphone diphone = null;

  if (useIndexing) {
      diphone = getFromCache(unitName);
      if (diphone == null) {
    int index = getIndex(unitName);
    if (index != -1) {
        mbb.position(index);
        try {
      diphone = Diphone.loadBinary(mbb);
      if (diphone != null) {
                // If diphone is an alias, must also get the original
                if (diphone instanceof AliasDiphone) {
                    AliasDiphone adiph = (AliasDiphone) diphone;
                    Diphone original = getUnit(adiph.getOriginalName());
                    if (original != null) {
                        adiph.setOriginalDiphone(original);
                        putIntoCache(unitName, adiph);
                    } else {
                        // No original was found for this alias
                        // -- complain, and ignore
                        if (LOGGER.isLoggable(Level.FINER)) {
                            LOGGER.finer("For diphone alias "
                                +adiph.getName()+", could not find original "
                                +adiph.getOriginalName());
                        }
                        diphone = null;
                    }
                } else { // a normal diphone
                    putIntoCache(unitName, diphone);
                }
      }
        } catch (IOException ioe) {
      System.err.println("Can't load diphone " +
        unitName);
      diphone = null;
        }
    }
      }
  } else {
      diphone = (Diphone) diphoneMap.get(unitName);
  }

  if (diphone == null) {
      System.err.println("Can't find diphone " + unitName);
      diphone = defaultDiphone;
  }

  return diphone;
    }

    /**
     * Gets the named diphone from the cache. If we are using soft
     * caching, the reference may be a soft/weak reference so check to
     * see if the reference is still valid, if so return it; otherwise
     * invalidate it. Note that we have not had good success with weak
     * caches so far. The goal is to reduce the minimum required
     * memory footprint as far as possible while not compromising
     * performance. In small memory systems, the weak cache would
     * likely be reclaimed, giving us lower performance but with the
     * ability to still be able to run. In reality, the soft caches
     * did not help much. They just did not work correctly.
     * [[[ TODO: test weak/soft cache behavior with new versions of
     * the runtime to see if their behavior has improved ]]]
     *
     * @param name the name of the diphone
     *
     * @return the diphone or <code> null </code>  if not in the cache
     */
    private Diphone getFromCache(String name) {
  if (diphoneMap == null) {
      return null;
  }
  Diphone diphone = null;

  if (useSoftCache) {
      Reference ref  = (Reference) diphoneMap.get(name);
      if (ref != null) {
    diphone = (Diphone) ref.get();
    if (diphone == null) {
        diphoneMap.remove(name);
    } else {
    }
      }
  } else {
      diphone = (Diphone) diphoneMap.get(name);
  }
  return diphone;
    }

    /**
     * Puts the diphone in the cache.
     *
     * @param diphoneName the name of the diphone
     * @param diphone the diphone to put in the cache
     */
    private void putIntoCache(String diphoneName, Diphone diphone) {
  if (diphoneMap == null) {
      return ;
  }
  if (useSoftCache) {
        diphoneMap.put(diphoneName, new WeakReference(diphone));
  } else {
        diphoneMap.put(diphoneName, diphone);
  }
    }

    /**
     * Dumps the soft ref cache.
     */
    private void dumpCacheSize() {
  int empty = 0;
  int full = 0;
  System.out.println("Entries: " + diphoneMap.size());
  for (Iterator i = diphoneMap.values().iterator(); i.hasNext(); ) {
      Reference ref = (Reference) i.next();
      if (ref.get() == null) {
    empty++;
      } else {
    full++;
      }
  }
  System.out.println("   empty: " + empty);
  System.out.println("    full: " + full);
    }

   
    /**
     * Returns the name of this DiphoneUnitDatabase.
     */
    public String getName() {
  return name;
    }
   
    /**
     * Dumps the diphone database.
     */
    public void dump() {
  System.out.println("Name        " + name);
  System.out.println("SampleRate  " + sampleRate);
  System.out.println("NumChannels " + numChannels);
  System.out.println("lpcMin      " + lpcMin);
  System.out.println("lpcRange    " + lpcRange);

  for (Iterator i = diphoneMap.values().iterator(); i.hasNext(); ) {
      Diphone diphone = (Diphone) i.next();
      diphone.dump();
  }
    }

    /**
     * Dumps a binary form of the database.
     *
     * @param path the path to dump the file to
     */
    public void dumpBinary(String path) {
  try {
      FileOutputStream fos = new FileOutputStream(path);
            DataOutputStream os = new DataOutputStream(fos);
      int written;

      os.writeInt(MAGIC);
      os.writeInt(VERSION);
      os.writeInt(sampleRate);
      os.writeInt(numChannels);
      os.writeFloat(lpcMin);
      os.writeFloat(lpcRange);
      os.writeInt(diphoneMap.size());

      for (Iterator i = diphoneMap.values().iterator(); i.hasNext();) {
    Diphone diphone = (Diphone) i.next();
    diphone.dumpBinary(os);
      }
            os.flush();
            fos.close();

  } catch (FileNotFoundException fe) {
      throw new Error("Can't dump binary database " +
        fe.getMessage());
  } catch (IOException ioe) {
      throw new Error("Can't write binary database " +
        ioe.getMessage());
  }
    }

    /**
     * Dumps a binary index. The database index is used if our
     * cacheType is not set to 'preload' and we are loading a binary
     * database. The index is a simple mapping of diphone names (the
     * key) to the file position in the database. In situations where
     * the entire database is not preloaded, this index can be loaded
     * and used to provide quicker startup (since only the index need
     * be loaded at startup) and quick access to the diphone data.
     *
     * @param path the path to dump the file to
     */
    void dumpBinaryIndex(String path) {
  try {
      FileOutputStream fos = new FileOutputStream(path);
      DataOutputStream dos = new DataOutputStream(fos);

      dos.writeInt(INDEX_MAGIC);
      dos.writeInt(diphoneIndex.keySet().size());

      for (Iterator i = diphoneIndex.keySet().iterator(); i.hasNext();) {
    String key = (String) i.next();
    int pos = ((Integer) diphoneIndex.get(key)).intValue();
    dos.writeUTF(key);
    dos.writeInt(pos);
      }
      dos.close();

  } catch (FileNotFoundException fe) {
      throw new Error("Can't dump binary index " +
        fe.getMessage());
  } catch (IOException ioe) {
      throw new Error("Can't write binary index " +
        ioe.getMessage());
  }
    }

    /**
     * Loads a binary index.
     *
     * @param url the location  of the binary index file
     */
    private void loadBinaryIndex(URL url) {

  diphoneIndex = new HashMap();

  try {
      InputStream is = Utilities.getInputStream(url);
      DataInputStream dis = new DataInputStream(is);

      if (dis.readInt() != INDEX_MAGIC) {
    throw new Error("Bad index file format");
      }

      int size = dis.readInt();

      for (int i = 0; i < size; i++) {
    String diphoneName = dis.readUTF();
    int pos = dis.readInt();
    diphoneIndex.put(diphoneName, new Integer(pos));
      }
      dis.close();

  } catch (FileNotFoundException fe) {
      throw new Error("Can't load binary index " +
        fe.getMessage());
  } catch (IOException ioe) {
      throw new Error("Can't read binary index " +
        ioe.getMessage());
  }
    }

    /**
     * Gets the index for the given diphone.
     *
     * @param diphone the name of the diphone
     *
     * @return the index into the database for the diphone
     */
    private int getIndex(String diphone) {
  Integer index = (Integer) diphoneIndex.get(diphone);
  if (index != null) {
      int idx = index.intValue();
      if (defaultIndex == -1) {
    defaultIndex = idx;
      }
      return idx;
  } else {
      System.out.println("Can't find index entry for " + diphone);
      return defaultIndex;
  }
    }



    /**
     * Loads a binary file from the input stream.
     * <p>
     * Note that we currently have four! methods of loading up the
     * database. We were interested in the performance characteristics
     * of the various methods of loading the database so we coded it
     * all up.
     *
     * @param is the input stream to read the database
     *     from
     *
     * @throws IOException if there is trouble opening the DB
     *
     */
    private void loadBinary(InputStream is) throws IOException {
  // we get better performance if we can map the file in
  // 1.0 seconds vs. 1.75 seconds, but we can't
  // always guarantee that we can do that.
  if (useNewIO && is instanceof FileInputStream) {
      FileInputStream fis = (FileInputStream) is;
      if (useIndexing) {
    loadBinaryIndex(new URL(indexName));
    mapDatabase(fis);
      } else {
    loadMappedBinary(fis);
      }
  } else {
        useIndexing = false; // just to make this clear
      DataInputStream dis = new DataInputStream(
        new BufferedInputStream(is));
      loadBinary(dis);
  }
    }


    /**
     * Loads the binary data from the given input stream.
     *
     * @param dis the data input stream.
     */
    private void loadBinary(DataInputStream dis) throws IOException {
  int size;
  if (dis.readInt() != MAGIC)  {
      throw new Error("Bad magic in db");
  }
  if (dis.readInt() != VERSION)  {
      throw new Error("Bad VERSION in db");
  }

  sampleRate = dis.readInt();
  numChannels = dis.readInt();
  lpcMin = dis.readFloat();
  lpcRange = dis.readFloat();
  size = dis.readInt();

  for (int i = 0; i < size; i++) {
      Diphone diphone = Diphone.loadBinary(dis);
      add(diphone);
  }
    }


    /**
     * Loads the database from the given FileInputStream.
     *
     * @param is the InputStream to load the database from
     *
     * @throws IOException if there is trouble opening the DB
     */
    private void loadMappedBinary(FileInputStream is) throws IOException {
  FileChannel fc = is.getChannel();

  MappedByteBuffer bb =
      fc.map(FileChannel.MapMode.READ_ONLY, 0, (int) fc.size());
  bb.load();
  loadDatabase(bb);
  is.close();
    }

    /**
     * Maps the database from the given FileInputStream.
     *
     * @param is the InputStream to load the database from
     *
     * @throws IOException if there is trouble opening the DB
     */
    private void mapDatabase(FileInputStream is) throws IOException {
  FileChannel fc = is.getChannel();
  mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, (int) fc.size());
  mbb.load();
        loadDatabaseHeader(mbb);
    }

    /**
     * Loads the database header from the given byte buffer.
     *
     * @param bb the byte buffer to load the db from
     *
     * @throws IOException if there is trouble opening the DB
     */
    private void loadDatabaseHeader(ByteBuffer bb) throws IOException {
  if (bb.getInt() != MAGIC)  {
      throw new Error("Bad magic in db");
  }
  if (bb.getInt() != VERSION)  {
      throw new Error("Bad VERSION in db");
  }

  sampleRate = bb.getInt();
  numChannels = bb.getInt();
  lpcMin = bb.getFloat();
  lpcRange = bb.getFloat();
    }

    /**
     * Loads the database from the given byte buffer.
     *
     * @param bb the byte buffer to load the db from
     *
     * @throws IOException if there is trouble opening the DB
     */
    private void loadDatabase(ByteBuffer bb) throws IOException {
        int size;
  loadDatabaseHeader(bb);
  size = bb.getInt();

  diphoneIndex = new HashMap();
  for (int i = 0; i < size; i++) {
      int pos = bb.position();
      Diphone diphone = Diphone.loadBinary(bb);
      add(diphone);
      diphoneIndex.put(diphone.getName(), new Integer(pos));
  }
    }

    /**
     * Compares this database to another. This is used for testing.
     * With this method we can load up two databases (one perhaps from
     * a text source and one from a binary source) and compare to
     * verify that the dbs are identical
     *
     * @param other the other database
     *
     * @return <code>true</code>  if the DBs are identical;
     *    otherwise <code>false</code>
     */
    public boolean compare(DiphoneUnitDatabase other) {
  if (sampleRate != other.sampleRate) {
      return false;
  }

  if (numChannels != other.numChannels) {
      return false;
  }

  if (lpcMin != other.lpcMin) {
      return false;
  }

  if (lpcRange != other.lpcRange) {
      return false;
  }

  for (Iterator i = diphoneMap.values().iterator(); i.hasNext(); ) {
      Diphone diphone = (Diphone) i.next();
      Diphone otherDiphone = (Diphone) other.getUnit(diphone.getName());
      if (!diphone.compare(otherDiphone)) {
    System.out.println("Diphones differ:");
    System.out.println("THis:");
    diphone.dump();
    System.out.println("Other:");
    otherDiphone.dump();
    return false;
      }
  }
  return true;
    }


    /**
     * Manipulates a DiphoneUnitDatabase. This program is typically
     * used to generate the binary form (with index) of the
     * DiphoneUnitDatabase from the text form. Additionally, this program
     * can be used to compare two databases to see if they are
     * identical (used for testing).
     *
     * <p>
     * <b> Usage </b>
     * <p>
     <code> java com.sun.speech.freetts.diphone.DiphoneUnitDatabase
     *  [options]</code>
     * <p>
     * <b> Options </b>
     * <p>
     *    <ul>
     *          <li> <code> -src path </code> provides a directory
     *          path to the source text for the database
     *          <li> <code> -dest path </code> provides a directory
     *          for where to place the resulting binaries
     *    <li> <code> -generate_binary [filename] </code>
     *    reads in the text
     *    version of the database and generates the binary
     *    version of the database.
     *    <li> <code> -compare </code>  Loads the text and
     *    binary versions of the database and compares them to
     *    see if they are equivalent.
     *    <li> <code> -showTimes </code> shows timings for any
     *    loading, comparing or dumping operation
     *    </ul>
     *
     */
    public static void main(String[] args) {
  boolean showTimes = false;
        String srcPath = ".";
        String destPath = ".";
       
  try {
      if (args.length > 0) {
    BulkTimer timer = BulkTimer.LOAD;
    timer.start();
    for (int i = 0 ; i < args.length; i++) {
                    if (args[i].equals("-src")) {
                        srcPath = args[++i];
                    } else if (args[i].equals("-dest")) {
                        destPath = args[++i];
                    } else if (args[i].equals("-generate_binary")) {
       String name = "diphone_units.txt";
       if (i + 1 < args.length) {
                             String nameArg = args[++i];
                             if (!nameArg.startsWith("-")) {
                                 name = nameArg;
                             }
       }

       int suffixPos = name.lastIndexOf(".txt");

       String binaryName = "diphone_units.bin";
       if (suffixPos != -1) {
           binaryName = name.substring(0, suffixPos) + ".bin";
       }

       String indexName = "diphone_units.idx";

       if (suffixPos != -1) {
           indexName = name.substring(0, suffixPos) + ".idx";
       }

       System.out.println("Loading " + name);
       timer.start("load_text");
       DiphoneUnitDatabase udb = new DiphoneUnitDatabase(
        new URL("file:"
                                        + srcPath + "/" + name), false);
       timer.stop("load_text");

       System.out.println("Dumping " + binaryName);
       timer.start("dump_binary");
           udb.dumpBinary(destPath + "/" + binaryName);
       timer.stop("dump_binary");

       timer.start("load_binary");
       DiphoneUnitDatabase budb =
          new DiphoneUnitDatabase(
            new URL("file:"
                                            + destPath + "/" + binaryName),
                                    true);
       timer.stop("load_binary");

       System.out.println("Dumping " + indexName);
       timer.start("dump index");
           budb.dumpBinaryIndex(destPath + "/" + indexName);
       timer.stop("dump index");
        } else if (args[i].equals("-compare")) {

      timer.start("load_text");
       DiphoneUnitDatabase udb = new DiphoneUnitDatabase(
        new URL("file:./diphone_units.txt"), false);
      timer.stop("load_text");

      timer.start("load_binary");
      DiphoneUnitDatabase budb =
          new DiphoneUnitDatabase(
            new URL("file:./diphone_units.bin"), true);
      timer.stop("load_binary");

      timer.start("compare");
      if (udb.compare(budb)) {
          System.out.println("other compare ok");
      } else {
          System.out.println("other compare different");
      }
      timer.stop("compare");
        } else if (args[i].equals("-showtimes")) {
      showTimes = true;
        } else {
      System.out.println("Unknown option " + args[i]);
        }
    }
    timer.stop();
    if (showTimes) {
        timer.show("DiphoneUnitDatabase");
    }
      } else {
    System.out.println("Options: ");
    System.out.println("    -src path");
    System.out.println("    -dest path");
    System.out.println("    -compare");
    System.out.println("    -generate_binary");
    System.out.println("    -showTimes");
      }
  } catch (IOException ioe) {
      System.err.println(ioe);
  }
    }
}
TOP

Related Classes of com.sun.speech.freetts.diphone.DiphoneUnitDatabase

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.