/** * Changes the pronunciation of "the" from 'd ax' to 'd iy' if the following word starts with a * vowel. "The every" is a good example. * * @param utterance the utterance to process */ private void fixTheIy(Utterance utterance) { Voice voice = utterance.getVoice(); for (Item item = utterance.getRelation(Relation.SEGMENT).getHead(); item != null; item = item.getNext()) { if ("ax".equals(item.toString())) { String word = wordPath.findFeature(item).toString(); if ("the".equals(word) && ("+".equals(N_PH_VC.findFeature(item)))) { item.getFeatures().setString("name", "iy"); } } } }
/** * Fixes apostrophe s segments. * * @param utterance the utterance to fix */ private void fixApostrophe(Utterance utterance) { Voice voice = utterance.getVoice(); for (Item item = utterance.getRelation(Relation.SEGMENT).getHead(); item != null; item = item.getNext()) { String word = wordPath.findFeature(item).toString(); if (word.equals("'s")) { String pname = item.getPrevious().toString(); if (("fa".indexOf(voice.getPhoneFeature(pname, "ctype")) != -1) && ("dbg".indexOf(voice.getPhoneFeature(pname, "cplace")) == -1)) { prependSchwa(item); } else if (voice.getPhoneFeature(pname, "cvox").equals("-")) { item.getFeatures().setString("name", "s"); } } else if (word.equals("'ve") || word.equals("'ll") || word.equals("'d")) { if ("-".equals(P_PH_VC.findFeature(item))) { prependSchwa(item); } } } }
public MaryData process(MaryData d) throws Exception { Document doc = MaryXML.newDocument(); Element root = doc.getDocumentElement(); Locale locale = d.getLocale(); if (locale != null) { root.setAttribute("xml:lang", MaryUtils.locale2xmllang(locale)); } Element paragraph = MaryXML.appendChildElement(root, MaryXML.PARAGRAPH); List<Utterance> utterances = d.getUtterances(); Iterator<Utterance> it = utterances.iterator(); while (it.hasNext()) { Utterance utterance = it.next(); Element insertHere = paragraph; if (logger.getEffectiveLevel().equals(Level.DEBUG)) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); utterance.dump(pw, 2, name(), true); // padding, justRelations logger.debug("Converting the following Utterance to XML:\n" + sw.toString()); } // Make sure we have the correct voice: Voice maryVoice = null; if (utterance.getVoice() != null) { maryVoice = FreeTTSVoices.getMaryVoice(utterance.getVoice()); } if (maryVoice != null) { if (insertHere.getTagName().equals(MaryXML.VOICE)) { // Are utterance voice and voiceElement voice the same? if (maryVoice.hasName(insertHere.getAttribute("name"))) { // then insertHere is set OK, leave it like it is } else { // get one higher up, create new voice element after this // one, and make insertHere point to the new voice element Element parent = (Element) insertHere.getParentNode(); Element newVoice = MaryXML.createElement(doc, MaryXML.VOICE); parent.appendChild(newVoice); newVoice.setAttribute("name", maryVoice.getName()); insertHere = newVoice; } } else { // Check if the last child of insertHere is a voice with the right name Element lastChild = MaryDomUtils.getLastChildElement(insertHere); if (lastChild != null && lastChild.getTagName().equals(MaryXML.VOICE) && maryVoice.hasName(lastChild.getAttribute("name"))) { insertHere = lastChild; } else { // create a new voice element, insert it as a child of this // node, and let insertHere point to it Element newVoice = MaryXML.createElement(doc, MaryXML.VOICE); insertHere.appendChild(newVoice); newVoice.setAttribute("name", maryVoice.getName()); insertHere = newVoice; } } // Now insertHere is the correct <voice> element. // Any prosodic settings to insert? Element prosody = insertProsodySettings(insertHere, utterance); if (prosody != null) insertHere = prosody; } // Create a sentence element <s> for this utterance: Element sentence = MaryXML.createElement(doc, MaryXML.SENTENCE); insertHere.appendChild(sentence); fillSentence(sentence, utterance); } if (logger.getEffectiveLevel().equals(Level.DEBUG)) { logger.debug("Constructed the following XML structure:"); MaryNormalisedWriter mnw = new MaryNormalisedWriter(); ByteArrayOutputStream debugOut = new ByteArrayOutputStream(); mnw.output(doc, debugOut); logger.debug(debugOut.toString()); } MaryData output = new MaryData(outputType(), d.getLocale()); output.setDocument(doc); return output; }
/** * Depending on the data type, find the right information in the utterance and insert it into the * sentence. */ protected final void fillSentence(Element sentence, Utterance utterance) { Document doc = sentence.getOwnerDocument(); Relation tokenRelation = utterance.getRelation(Relation.TOKEN); if (tokenRelation == null) return; Item tokenItem = tokenRelation.getHead(); Relation phraseRelation = utterance.getRelation(Relation.PHRASE); Item phraseItem = null; if (phraseRelation != null) { phraseItem = phraseRelation.getHead(); // Challenge: Bring token and phrase relations together. They have // common children, which can be interpreted as Word or SylStructure // items. Algorithm: For a given phrase, look at tokens. If a token's // first child, interpreted in the phrase relation, has the phrase as // its parent, then insert the token and all its children, and move to // the next token. If not, move to the next phrase. while (phraseItem != null) { // The phrases: Element phrase = MaryXML.createElement(doc, MaryXML.PHRASE); sentence.appendChild(phrase); Element insertHere = phrase; // Is this token part of this phrase? while (tokenItem != null && tokenItem.getDaughter().findItem("R:Phrase.parent").equals(phraseItem)) { FeatureSet tokenFeatures = tokenItem.getFeatures(); if (tokenFeatures.isPresent(XML2UttBase.PROSODY_START)) { Element prosody = insertProsodySettings(insertHere, tokenFeatures); if (prosody != null) { insertHere = prosody; } } insertToken(tokenItem, phrase, true); // create deep structure if (tokenFeatures.isPresent(XML2UttBase.PROSODY_END)) { assert insertHere.getTagName().equals(MaryXML.PROSODY); insertHere = (Element) insertHere.getParentNode(); } tokenItem = tokenItem.getNext(); } phraseItem = phraseItem.getNext(); } } else { // No phrase relation, simply create tokens. Element insertHere = sentence; while (tokenItem != null) { FeatureSet tokenFeatures = tokenItem.getFeatures(); if (tokenFeatures.isPresent(XML2UttBase.PROSODY_START)) { Element prosody = insertProsodySettings(insertHere, tokenFeatures); if (prosody != null) { insertHere = prosody; } } insertToken(tokenItem, insertHere); if (tokenFeatures.isPresent(XML2UttBase.PROSODY_END)) { if (insertHere.getTagName().equals(MaryXML.PROSODY)) { insertHere = (Element) insertHere.getParentNode(); } // else, we are looking at an empty prosody tag with no arguments, which is being // deleted right now. } tokenItem = tokenItem.getNext(); } } }