⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diphoneunitdatabase.java

📁 这是java 开发的的免费语音播放插件,很值得学习参考!!!!!!!!!!!!111
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/** * 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 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;import com.sun.speech.freetts.Unit;import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.InputStream;import java.io.InputStreamReader;import java.io.IOException;import java.net.MalformedURLException;import java.net.URL;import java.nio.ByteBuffer;import java.nio.channels.Channels;import java.nio.channels.FileChannel;import java.nio.channels.ReadableByteChannel;import java.nio.MappedByteBuffer;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.lang.ref.Reference;import java.lang.ref.SoftReference;import java.lang.ref.WeakReference;/** * 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 {    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 {	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("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("Bad number of channels " + numChannels);		}		if (numSamples <= 0) {		    throw new Error("Bad number of samples " + numSamples);		}		Sample[] samples = new Sample[numSamples];		for (int i = 0; i < samples.length; i++) {		    samples[i] = new Sample(reader, numChannels);		    assert samples[i].getFrameData().length == 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) {	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) {			    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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -