content: /**
   * Copyright 2004-2006 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.signalproc.analysis;
  
  /**
   * @author sacha
   *         <p/>
   *         Implements the conversion between the Linear Prediction
   *         Coefficients (LPC) and the corresponding Linear Prediction
   *         Cepstrum Coefficients.
   */
  public class CepstrumLPCAnalyser {
  
      /**
       * Converts from LPC coefficients to LPCC coefficients.
       *
       * @param oneMinusA     A(z) = a0 - sum { ai * z^-i } . a0 = 1.
       * @param gain          The LPC gain factor.
       * @param cepstrumOrder Cepstrum order (equal to the index of the last cepstrum coefficient).
       * @return The LPCC coefficents. c[0] is set to log(gain).
       * @author sacha
       */
      public static double[] lpc2lpcc(double[] oneMinusA, double gain, int cepstrumOrder) {
  
          // Check the cepstrum order
          if (cepstrumOrder <= 0) {
              throw new RuntimeException("The cepstrum order [" + cepstrumOrder + "] must be a positive integer.");
          }
  
          // Declare misc. useful variables
          int k, m;
          double acc;
          double[] c = new double[cepstrumOrder + 1];
          int lpcOrder = oneMinusA.length - 1;
  
          /* First cepstral coeff */
          c[0] = Math.log(gain);
          /* Other coeffs: */
          for (m = 1; m <= cepstrumOrder; m++) {
              /* Coeffs within the LPC order: */
              if (m <= lpcOrder) {
                  acc = 0.0;
                  for (k = 1; k < m; k++) acc += ((m - k) * oneMinusA[k] * c[m - k]);
                  c[m] = acc / (m) + oneMinusA[m];
              }
              /* Coeffs above the LPC order: */
              else {
                  acc = 0.0;
                  for (k = 1; k <= lpcOrder; k++) acc += ((m - k) * oneMinusA[k] * c[m - k]);
                  c[m] = acc / (m);
              }
          }
  
          return (c);
      }
  
      /**
       * Converts from LPCC coefficients to LPC coefficients.
       *
       * @param c        the vector of cepstral coefficients. Note: c[0] = log(gain).
       * @param lpcOrder The original LPC order (equal to the index of the last LPC coefficient).
       * @return The LPC coefficents [1 -a_1 -a_2 ... -a_p].
       * @note The gain is not returned, but it can be recovered as exp(c[0]).
       * @author sacha
       */
      public static double[] lpcc2lpc(double[] c, int lpcOrder) {
  
          // Check the LPC order
          if (lpcOrder <= 0) {
              throw new RuntimeException("The LPC order [" + lpcOrder + "] must be a positive integer.");
          }
  
          // Declare misc. useful variables
          int k, m;
          double acc;
          double[] a = new double[lpcOrder + 1];
          int cepstrumOrder = c.length - 1;
  
          /* First lpc coeff */
          a[0] = 1.0;
          /* Other coeffs: */
          for (m = 1; m <= lpcOrder; m++) {
              /* Coeffs within the Cepstrum order: */
              if (m <= cepstrumOrder) {
                  acc = 0.0;
                  for (k = 1; k < m; k++) acc += ((k) * a[m - k] * c[k]);
                  a[m] = c[m] - acc / (m);
              }
              /* Coeffs above the Cepstrum order: */
              else {
                  acc = 0.0;
                  for (k = 1; k <= cepstrumOrder; k++) acc += ((k) * a[m - k] * c[k]);
                  a[m] = -acc / (m);
              }
          }
  
          return (a);
      }
  
  }
  
  