예제 #1
0
 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();
 }
예제 #2
0
 /**
  * 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");
   }
 }
예제 #3
0
 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());
 }
예제 #4
0
  /**
   * 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;
  }
예제 #5
0
  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;
  }