public String toString() { return Objects.toStringHelper(this) .add("type", getType()) .add("locale", getLocale()) .add("output parameters", getOutputParams()) .add("data", getData()) .add("document", DomUtils.serializeToString(getDocument())) .add("validating", getValidating()) .add("plain text", getPlainText()) .add("audio", getAudio()) .add("audio file format", getAudioFileFormat()) .toString(); }
/** * Set the content data of this MaryData object from the given String. For XML data ({@link * MaryDataType#isXMLType()}), parse the String representation of the data into a DOM tree. * * @param dataString string representation of the input data. * @throws ParserConfigurationException ParserConfigurationException * @throws IOException IOException * @throws SAXException SAXException * @throws IllegalArgumentException if this method is called for MaryDataTypes that are neither * text nor XML. */ public void setData(String dataString) throws ParserConfigurationException, SAXException, IOException { // First, some data cleanup: dataString = StringUtils.purgeNonBreakingSpaces(dataString); // Now, deal with it. if (type.isXMLType()) { logger.debug( "Parsing XML input (" + (doValidate ? "" : "non-") + "validating): " + dataString); xmlDocument = DomUtils.parseDocument(dataString, doValidate); } else if (type.isTextType()) { logger.debug("Setting text input: " + dataString); plainText = dataString; } else { throw new IllegalArgumentException("Cannot set data of type " + type + " from a string"); } }
private void updateVoiceDescription(File rootDir, File packageFile) throws MalformedURLException, ParserConfigurationException, MaryConfigurationException, IOException { logger.debug("writing new voice description..."); voiceDescription.setVersion(Version.specificationVersion()); voiceDescription.setDependsVersion(Version.specificationVersion()); voiceDescription.setPackageFilename(packageFile.getName()); voiceDescription.setPackageMD5Sum(computeMD5(packageFile)); voiceDescription.setPackageSize((int) packageFile.length()); voiceDescription.removeAllLocations(); voiceDescription.addLocation( URI.create("http://mary.dfki.de/download/" + Version.specificationVersion() + "/").toURL()); Document doc = voiceDescription.createComponentXML(); File newVoiceDescriptionFile = new File(rootDir, getFilenamePrefix() + "-component.xml"); DomUtils.document2File(doc, newVoiceDescriptionFile); logger.debug("... created " + newVoiceDescriptionFile.getPath()); }
/** * Preselect a set of candidates that could be used to realise the given target. * * @param target a Target object representing an optimal unit * @return an <span style="color:red;">unsorted</span> ArrayList of ViterbiCandidates, each * containing the (same) target and a (different) Unit object */ public List<ViterbiCandidate> getCandidates(Target target) { // BEGIN blacklisting // The point of this is to get the value of the "blacklist" attribute in the first child element // of the MaryXML // and store it in the blacklist String variable. // This code seems rather inelegant; perhaps there is a better way to access the MaryXML from // this method? String blacklist = ""; String unitBasename = "This must never be null or the empty string!"; // otherwise candidate selection fails! Element targetElement = target.getMaryxmlElement(); blacklist = DomUtils.getAttributeFromClosestAncestorOfAnyKind(targetElement, "blacklist"); // END blacklisting // logger.debug("Looking for candidates in cart "+target.getName()); // get the cart tree and extract the candidates int[] clist = (int[]) preselectionCART.interpret(target, backtrace); logger.debug("For target " + target + ", selected " + clist.length + " units"); // Now, clist is an array of unit indexes. List<ViterbiCandidate> candidates = new ArrayList<ViterbiCandidate>(); for (int i = 0; i < clist.length; i++) { // The target is the same for all these candidates in the queue // remember the actual unit: Unit unit = unitReader.getUnit(clist[i]); candidates.add(new ViterbiCandidate(target, unit, targetCostFunction)); } // Blacklisting without crazy performance drop: // just remove candidates again if their basenames are blacklisted java.util.Iterator<ViterbiCandidate> candIt = candidates.iterator(); while (candIt.hasNext()) { ViterbiCandidate candidate = candIt.next(); unitBasename = getFilename(candidate.getUnit()); if (blacklist.contains(unitBasename)) { candIt.remove(); } } return candidates; }
public MaryData process(MaryData d) throws Exception { // prevUnitIndex; // numberOfConsecutiveUnits; // basenameDuration; // phoneTier; // PraatIntervalTier unitTier; // PraatIntervalTier sourceTier; // sourceInterval; Document doc = d.getDocument(); // initialize various variables: Double duration = 0.0; String phone = null; // initialize some class variables: PraatIntervalTier phoneTier = new PraatIntervalTier("phones"); Double basenameDuration = 0.0; int prevUnitIndex = Integer.MIN_VALUE; int numberOfConsecutiveUnits = 0; // counter to track consecutive units PraatInterval sourceInterval = new PraatInterval(basenameDuration); // until we have a robust way of checking the voice type, just initialize unit and source tiers // anyway: PraatIntervalTier unitTier = new PraatIntervalTier("units"); PraatIntervalTier sourceTier = new PraatIntervalTier("sources"); // prepare to iterate only over the PHONE, SENTENCE, and BOUNDARY nodes in the MaryXML: NodeIterator ni = DomUtils.createNodeIterator(doc, PHONE, BOUNDARY); Element element; // now iterate over these nodes: while ((element = (Element) ni.nextNode()) != null) { switch (element.getTagName()) { // <s>, <ph>, or <boundary> as specified above case PHONE: phone = element.getAttribute("p"); duration = Integer.parseInt(element.getAttribute("d")) / 1000.0; // duration is always in ms break; case BOUNDARY: phone = "_"; // TODO: perhaps we should access TargetFeatureComputer.getPauseSymbol() instead if (element.hasAttribute("duration")) { duration = Double.parseDouble(element.getAttribute("duration")) / 1000.0; // duration is always in ms } else { duration = 0.0; // HMM voices can have duration-less <boundary/> tags } break; default: logger.error( "NodeIterator should not find an element of type " + element.getTagName() + " here!"); break; } PraatInterval phoneInterval = new PraatInterval(duration, phone); // TODO: crude way of checking for unit selection voice; also, name of attribute could change! if (element.hasAttribute("units")) { // unitselectionProcessing(element, unitTier, prevUnitIndex, numberOfConsecutiveUnits, // basenameDuration, // sourceInterval, sourceTier); String units = element.getAttribute("units"); String[] unitStrings = units.split("; "); // boundaries have only one unit string boolean differentSource = false; String basename = null; String unitRange = null; for (String unitString : unitStrings) { // TODO verify that unit string matches "UNITNAME BASENAME UNITINDEX UNITDURATION" String[] unitFields = unitString.split(" "); String unitName = unitFields[0]; basename = unitFields[1]; int unitIndex = Integer.parseInt(unitFields[2]); Double unitDuration = Double.parseDouble(unitFields[3]); // units are straightforward, just like phones: unitTier.appendInterval(new PraatInterval(unitDuration, unitString)); // unit source processing is a little more elaborate: /* * Note: the following assumes that consecutive selected units are ALWAYS from the same basename! That could * change if basename boundaries are no longer marked by null units in the timeline. */ differentSource = unitIndex != prevUnitIndex + 1; // is source unit from a different part of the timeline?; if (differentSource) { // reset primary variables: numberOfConsecutiveUnits = 0; basenameDuration = 0.0; } // increment/increase primary variables: numberOfConsecutiveUnits++; basenameDuration += unitDuration; // construct unit index range string: unitRange = Integer.toString(unitIndex - numberOfConsecutiveUnits + 1); if (numberOfConsecutiveUnits > 1) { unitRange = unitRange + "-" + unitIndex; } // append source intervals to source tier: if (differentSource) { sourceInterval = new PraatInterval(basenameDuration, basename + ": " + unitRange); sourceTier.appendInterval(sourceInterval); } else { sourceInterval.setDuration(basenameDuration); sourceInterval.setText(basename + ": " + unitRange); } prevUnitIndex = unitIndex; } // HACK: arbitrary threshold to detect end points in ms (in the case of diphone voice or // boundary segment) } else if (duration > 10) { // TODO: there is still a bug somewhere regarding boundary durations with mbrola... phoneInterval.setDuration(duration / 1000.0); } phoneTier.appendInterval(phoneInterval); } PraatTextGrid textGrid = new PraatTextGrid(); phoneTier.updateBoundaries(); // force full specification of timings textGrid.appendTier(phoneTier); // fragile way of checking whether this is a unit selection voice: if (unitTier.getNumberOfIntervals() > 0) { // complete and append unit and source tiers: unitTier.updateBoundaries(); textGrid.appendTier(unitTier); sourceTier.updateBoundaries(); textGrid.appendTier(sourceTier); } // return raw TextGrid as result: MaryData result = new MaryData(getOutputType(), d.getLocale()); result.setPlainText(textGrid.toString()); return result; }