📄 voice.java
字号:
speakable.started(); log(" --- started ---"); } // log(" utt: " + utterance.getString("input_text")); try { if (!speakable.isCompleted()) { runProcessor(audioOutput, utterance, timer); } else { ok = false; } } catch (ProcessException pe) { ok = false; } if (ok && utterance.isLast()) { getAudioPlayer().drain(); speakable.completed(); log(" --- completed ---"); } else if (!ok) { // getAudioPlayer().drain(); speakable.cancelled(); log(" --- cancelled ---"); } else { log(" --- not last: " + speakable.getText() + " --- "); } log("Calling speakable.completed() on " + speakable.getText()); } else { ok = false; log("STRANGE: speakable already completed: " +speakable.getText()); } return ok; } /** * Runs the given utterance processor. * * @param processor the processor to run. If the processor * is null, it is ignored * @param utterance the utterance to process * * @throws ProcessException if an exceptin occurs while processing * the utterance */ private void runProcessor(UtteranceProcessor processor, Utterance utterance, BulkTimer timer) throws ProcessException { if (processor != null) { String processorName = ".." + processor.toString(); log(" Running " + processorName); timer.start(processorName); processor.processUtterance(utterance); timer.stop(processorName); } } /** * Returns the tokenizer associated with this voice. * * @return the tokenizer */ public abstract Tokenizer getTokenizer(); /** * Return the list of UtteranceProcessor instances. Applications * should use this to obtain and modify the contents of the * UtteranceProcessor list. * * @return a List containing UtteranceProcessor instances */ public List getUtteranceProcessors() { return utteranceProcessors; } /** * Returns the feature set associated with this voice. * * @return the feature set. */ public FeatureSet getFeatures() { return features; } /** * Starts a batch of utterances. Utterances are sometimes * batched in groups for timing purposes. * * @see #endBatch */ public void startBatch() { runTimer.setVerbose(detailedMetrics); runTimer.start(); } /** * Ends a batch of utterances. * * @see #startBatch */ public void endBatch() { runTimer.stop(); if (metrics) { runTimer.show(getRunTitle() + " run"); threadTimer.show(getRunTitle() + " thread"); getAudioPlayer().showMetrics(); long totalMemory = Runtime.getRuntime().totalMemory(); System.out.println ("Memory Use : " + (totalMemory - Runtime.getRuntime().freeMemory()) / 1024 + "k of " + totalMemory / 1024 + "k"); } } /** * Sets the output queue for this voice. If no output queue is set * for the voice when the voice is loaded, a queue and thread will * be created when the voice is loaded. If the outputQueue is set * by an external entity by calling setOutputQueue, the caller is * responsible for shutting down the output thread. That is, if * you call 'setOutputQueue' then you are responsible for shutting * down the output thread on your own. This is necessary since the * output queue may be shared by a number of voices. * * <p>Utterances are placed on the * queue to be output by an output thread. This queue is * usually created via a call to 'createOutputThread' which * creates a thread that waits on the queue and sends the * output to the audio player associated with this voice. If * the queue is null, the output is rendered in the calling * thread. * * @param queue the output queue */ public void setOutputQueue(OutputQueue queue) { externalOutputQueue = true; outputQueue = queue; } /** * Returns the output queue associated with this voice. * * @return the output queue associated with this voice */ public OutputQueue getOutputQueue() { return outputQueue; } /** * Loads voice specific data. Subclasses of voice should * implement this to perform class specific loading. */ protected abstract void loader() throws IOException; /** * tokenizes the given the queue item. * * @return an iterator that will yield a series of utterances */ private Iterator tokenize(FreeTTSSpeakable speakable) { return new FreeTTSSpeakableTokenizer(speakable).iterator(); } /** * Converts the document to a string (a placeholder for more * sophisticated logic to be done). * * @param dom the jsml document * * @return the document as a string. */ private String documentToString(Document dom) { StringBuffer buf = new StringBuffer(); linearize(dom, buf); return buf.toString(); } /** * Appends the text for this node to the given StringBuffer. * * @param n the node to traverse in depth-first order * @param buf the buffer to append text to */ private void linearize(Node n, StringBuffer buf) { StringBuffer endText = processNode(n, buf); for (Node child = n.getFirstChild(); child != null; child = child.getNextSibling()) { linearize(child, buf); } if (endText != null) { buf.append(endText); } } /** * Adds text for just this node and returns any text that might * be needed to undo the effects of this node after it is * processed. * * @param n the node to traverse in depth-first order * @param buf the buffer to append text to * * @return a <code>String</code> containing text to undo the * effects of the node */ protected StringBuffer processNode(Node n, StringBuffer buf) { StringBuffer endText = null; int type = n.getNodeType(); switch (type) { case Node.ATTRIBUTE_NODE: break; case Node.DOCUMENT_NODE: break; case Node.ELEMENT_NODE: // endText = processElement((Element) n, buf); break; case Node.TEXT_NODE: buf.append(((Text) n).getData()); break; // Pass processing instructions (e.g., <?blah?> // right on to the synthesizer. These types of things // probably should not be used. Instead the 'engine' // element is probably the best thing to do. // case Node.PROCESSING_INSTRUCTION_NODE: break; // The document type had better be JSML. // case Node.DOCUMENT_TYPE_NODE: break; // I think NOTATION nodes are only DTD's. // case Node.NOTATION_NODE: break; // Should not get COMMENTS because the JSMLParser // ignores them. // case Node.COMMENT_NODE: break; // Should not get CDATA because the JSMLParser is // coalescing. // case Node.CDATA_SECTION_NODE: break; // Should not get ENTITY related notes because // entities are expanded by the JSMLParser // case Node.ENTITY_NODE: case Node.ENTITY_REFERENCE_NODE: break; // Should not get DOCUMENT_FRAGMENT nodes because I // [[[WDW]]] think they are only created via the API's // and cannot be defined via content. // case Node.DOCUMENT_FRAGMENT_NODE: break; default: break; } return endText; } /** * Dumps the voice in textual form. * * @param output where to send the formatted output * @param pad the initial padding * @param title the title to print when dumping out */ public void dump(PrintWriter output, int pad, String title) { Utilities.dump(output, pad, title); features.dump(output, pad + 4, title + " Features"); dumpProcessors(output, pad + 4, title + " Processors"); } /** * Dumps the voice processors. * * @param output where to send the formatted output * @param pad the initial padding * @param title the title to print when dumping out */ public void dumpProcessors(PrintWriter output, int pad, String title) { UtteranceProcessor[] processors; if (utteranceProcessors == null) { return; } processors = new UtteranceProcessor[utteranceProcessors.size()]; processors = (UtteranceProcessor[]) utteranceProcessors.toArray(processors); Utilities.dump(output, pad, title); for (int i = 0; i < processors.length; i++) { Utilities.dump(output, pad + 4, processors[i].toString()); } } /** * Returns a language/voice specific Feature Processor. * * @param name the name of the processor * * @return the processor associated with the name or null if none * could be found */ public FeatureProcessor getFeatureProcessor(String name) { return (FeatureProcessor) featureProcessors.get(name); } /** * Adds a language/voice specific Feature Processor to the set of * FeatureProcessors supported by this voice. * * @param name the name of the processor * @param fp the processor */ public void addFeatureProcessor(String name, FeatureProcessor fp) { featureProcessors.put(name, fp); } /** * Prints the given message to <code>System.out</code> if "verbose" * operation is enabled. * * @see #setVerbose * @see #isVerbose */ public void log(String message) { if (verbose) { System.out.println(toString() + ": " + message); } } /** * Sends the given warning message to stderr. */ public void warn(String message) { System.err.println("Warning: " + message); } /** * Sends the given error message to stderr and also throws * an error exception. */ public void error(String message) { System.err.println("Error: " + message); throw new Error(message); } /** * Gets the state of the verbose mode. * * @return true if verbose mode is on */ public boolean isVerbose() { return verbose; } /** * Sets the verbose mode. * * @param verbose true if verbose mode should be on */ public void setVerbose(boolean verbose) { this.verbose = verbose; log("Verbose mode is " + verbose); } /** * Gets the state of the metrics mode. * * @return true if metrics mode is on */ public boolean isMetrics() { return metrics; } /** * Sets the metrics mode. * * @param metrics true if metrics mode should be on */ public void setMetrics(boolean metrics) { this.metrics = metrics; log("Metrics mode is " + metrics); } /** * Gets the state of the detailedMetrics mode. * * @return true if detailedMetrics mode is on */ public boolean isDetailedMetrics() { return detailedMetrics; } /** * Sets the state of the detailedMetrics mode. * * @param detailedMetrics true if detailedMetrics mode should be on */ public void setDetailedMetrics(boolean detailedMetrics) { this.detailedMetrics = detailedMetrics; log("DetailedMetrics mode is " + detailedMetrics); } /** * Gets the state of the dumpUtterance mode. * * @return true if dumpUtterance mode is on */ public boolean isDumpUtterance() { return dumpUtterance; } /** * Sets the state of the dumpUtterance mode. * * @param dumpUtterance true if dumpUtterance mode should be on */ public void setDumpUtterance(boolean dumpUtterance) { this.dumpUtterance = dumpUtterance; log("DumpUtterance mode is " + dumpUtterance); } /** * Gets the state of the dumpRelations mode. * * @return true if dumpRelations mode is on */ public boolean isDumpRelations() { return dumpRelations; } /** * Sets the state of the dumpRelations mode. * * @param dumpRelations true if dumpRelations mode should be on */ public void setDumpRelations(boolean dumpRelations) { this.dumpRelations = dumpRelations; log("DumpRelations mode is " + dumpRelations); } /** * Sets the title for this run. * * @param runTitle the title for the run */ public void setRunTitle(String runTitle) { this.runTitle = runTitle; } /** * Gets the title for this run. * * @return the title for the run */ public String getRunTitle() { return runTitle; } /** * Given a phoneme and a feature name, returns the feature. * * @param phone the phoneme of interest * @param featureName the name of the feature of interest * * @return the feature with the given name */ public String getPhoneFeature(String phone, String featureName) { return null; } /** * Shuts down the voice processing. */ public void deallocate() { setLoaded(false); if (!externalAudioPlayer) { if (audioPlayer != null) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -