content: /**
   * Copyright 2008 DFKI GmbH.
   * All Rights Reserved.  Use is subject to license terms.
   * <p/>
   * This file is part of MARY TTS.
   * <p/>
   * MARY TTS is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as published by
   * the Free Software Foundation, version 3 of the License.
   * <p/>
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU Lesser General Public License for more details.
   * <p/>
   * You should have received a copy of the GNU Lesser General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package marytts.language.en;
  
  import java.util.Locale;
  
  import marytts.datatypes.MaryXML;
  import marytts.modules.phonemiser.Allophone;
  import marytts.modules.phonemiser.AllophoneSet;
  import marytts.util.dom.DomUtils;
  import marytts.util.dom.MaryDomUtils;
  import mf.org.w3c.dom.Element;
  import mf.org.w3c.dom.traversal.TreeWalker;
  
  /**
   * A pronunciation model that takes into account some English postlexical rules.
   *
   * @author marc
   */
  public class PronunciationModel extends marytts.modules.PronunciationModel {
      /**
       *
       */
      public PronunciationModel() {
          super(Locale.ENGLISH);
      }
  
      /**
       * Optionally, a language-specific subclass can implement any postlexical rules
       * on the document.
       *
       * @param token        a <t> element with a <syllable> and <ph> substructure.
       * @param allophoneSet
       * @return true if something was changed in the content of the <ph> elements for this <t>, false otherwise
       */
      @Override
      protected boolean postlexicalRules(Element token, AllophoneSet allophoneSet) {
          String word = MaryDomUtils.tokenText(token);
  
          if (word.equals("'s") || word.equals("'ve") || word.equals("'ll") || word.equals("'d")) {
              Element sentence = (Element) DomUtils.getAncestor(token, MaryXML.SENTENCE);
              if (sentence == null) return false;
              TreeWalker tw = DomUtils.createTreeWalker(sentence, MaryXML.PHONE);
              tw.setCurrentNode(token);
              Element currentSegment = (Element) tw.nextNode();
              if (currentSegment == null) return false;
              Element prevSegment = (Element) tw.previousNode();
              if (prevSegment == null) return false;
              String pname = prevSegment.getAttribute("p");
              Allophone prev = allophoneSet.getAllophone(pname);
              if (prev == null) return false;
  
              if (word.equals("'s")) {
                  if ("fa".contains(prev.getFeature("ctype"))
                          && "ap".contains(prev.getFeature("cplace"))) {
                      // an alveolar or palatal fricative or affricate: s,z,S,Z,tS,dZ
                      prependSchwa(currentSegment);
                      return true;
                  } else if (prev.getFeature("cvox").equals("-")) {
                      // any unvoiced consonant
                      currentSegment.setAttribute("p", "s"); // devoice
                      return true;
                  }
              } else { // one of 've, 'll or 'd
                  if (prev.isConsonant()) {
                      prependSchwa(currentSegment);
                      return true;
                  }
              }
          }
          return false;
  
      }
  
      private void prependSchwa(Element currentSegment) {
          Element syllable = (Element) currentSegment.getParentNode();
          assert syllable != null;
          Element schwa = MaryXML.createElement(syllable.getOwnerDocument(), MaryXML.PHONE);
          schwa.setAttribute("p", "@");
          syllable.insertBefore(schwa, currentSegment);
      }
  }
  
  