content: /**
   * Copyright 2010 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;
  
  import java.io.BufferedInputStream;
  import java.io.BufferedOutputStream;
  import java.io.EOFException;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.IOException;
  
  import marytts.util.io.FileUtils;
  import marytts.util.io.LEDataInputStream;
  import marytts.util.io.LEDataOutputStream;
  
  /**
   * File I/O for binary SPTK pitch contour files
   *
   * @author Sathish Pammi
   */
  public class SPTKPitchReaderWriter {
  
      private final float NEGATIVE_MAXIMUM = (float) -1.00E10;
      private PitchFileHeader header;
      private double[] contour; //f0 values in Hz (0.0 for unvoiced)
  
  
      /**
       * read a SPTK lf0 file with following default values
       * windowSizeInSeconds = 0.005f;
       * skipSizeInSeconds = 0.005f;
       * fs = 16000; // in Hz
       *
       * @param lf0SPTKFile
       */
      public SPTKPitchReaderWriter(String lf0SPTKFile) {
  
          this(lf0SPTKFile, 0.005f, 0.005f, 16000);
  
      }
  
      /**
       * read a SPTK lf0 file with external settings
       *
       * @param lf0SPTKFile
       * @param windowSizeInSeconds
       * @param skipSizeInSeconds
       * @param samplingRate
       */
      public SPTKPitchReaderWriter(String lf0SPTKFile, float windowSizeInSeconds, float skipSizeInSeconds, int samplingRate) {
          contour = null;
  
          header = new PitchFileHeader();
          header.windowSizeInSeconds = windowSizeInSeconds;
          header.skipSizeInSeconds = skipSizeInSeconds;
          header.fs = samplingRate;
  
          try {
              contour = readSPTKF0Data(lf0SPTKFile);
          } catch (IOException e) {
              e.printStackTrace();
          }
      }
  
      /**
       * create a SPTK Pitch reader writer with external contour
       *
       * @param contour
       * @param header
       */
      public SPTKPitchReaderWriter(double[] contour, PitchFileHeader header) {
          this.contour = contour;
          this.header = header;
      }
  
      /**
       * @param args
       * @throws IOException
       */
      public static void main(String[] args) throws IOException {
  
          String lf0File = "/home/sathish/Desktop/test/Poppy2_091.lf0";
          SPTKPitchReaderWriter sprw = new SPTKPitchReaderWriter(lf0File);
          double[] f0contour = sprw.getF0Contour();
          PitchFileHeader hdr = sprw.getPitchFileHeader();
          SPTKPitchReaderWriter sprw1 = new SPTKPitchReaderWriter(f0contour, hdr);
          sprw1.writeIntoSPTKLF0File("/home/sathish/Desktop/test/Dummy.lf0");
  
          SPTKPitchReaderWriter sprw2 = new SPTKPitchReaderWriter("/home/sathish/Desktop/test/Dummy.lf0");
          f0contour = sprw2.getF0Contour();
          hdr = sprw2.getPitchFileHeader();
  
          for (int i = 0; i < f0contour.length; i++) {
              System.out.println((float) Math.log(f0contour[i]));
          }
  
          System.out.println("No. of frames: " + f0contour.length);
  
      }
  
      /**
       * get f0 values in Hz (0.0 for unvoiced)
       *
       * @return
       */
      public double[] getF0Contour() {
          return this.contour;
      }
  
      /**
       * get pitch file header
       *
       * @return
       */
      public PitchFileHeader getPitchFileHeader() {
          return this.header;
      }
  
      /**
       * @param lf0SPTKFile
       * @return
       * @throws IOException
       */
      private int getNumberOfFrames(String lf0SPTKFile) throws IOException {
  
          LEDataInputStream lf0Data = new LEDataInputStream(new BufferedInputStream(new FileInputStream(lf0SPTKFile)));
          float fval;
          int totalFrame = 0;
  
          /* First i need to know the size of the vectors */
          try {
              while (true) {
                  fval = lf0Data.readFloat();
                  totalFrame++;
              }
          } catch (EOFException e) {
              lf0Data.close();
          }
  
          return totalFrame;
      }
  
      /**
       * convert a SPTK file into contour[]
       *
       * @param lf0SPTKFile
       * @return
       * @throws IOException
       */
      private double[] readSPTKF0Data(String lf0SPTKFile) throws IOException {
  
          if (!FileUtils.exists(lf0SPTKFile)) {
              System.out.println("SPTK Pitch file not found: " + lf0SPTKFile);
              return null;
          }
  
          int numberOfFrames = getNumberOfFrames(lf0SPTKFile);
          LEDataInputStream lf0Data = new LEDataInputStream(new BufferedInputStream(new FileInputStream(lf0SPTKFile)));
  
          double[] f0Data = new double[numberOfFrames];
          for (int i = 0; i < numberOfFrames; i++) {
              float f0Value = lf0Data.readFloat();
              if (f0Value < 0) {
                  f0Data[i] = 0.0f;
              } else {
                  f0Data[i] = new Double(Math.exp(f0Value));
              }
          }
          return f0Data;
      }
  
      /**
       * write contour into a lf0 file in SPTK format
       *
       * @param sptkFileName
       * @throws IOException
       */
      public void writeIntoSPTKLF0File(String sptkFileName) throws IOException {
          LEDataOutputStream lf0Data = new LEDataOutputStream(new BufferedOutputStream(new FileOutputStream(sptkFileName)));
          for (int i = 0; i < this.contour.length; i++) {
              double f0Val = contour[i];
              if (contour[i] == 0.0f) {
                  lf0Data.writeFloat(NEGATIVE_MAXIMUM);
              } else {
                  lf0Data.writeFloat((float) Math.log(contour[i]));
              }
          }
          lf0Data.flush();
          lf0Data.close();
      }
  
      /**
       * write contour into a lf0 file in MARY PTC format
       *
       * @param ptcFileName
       * @throws IOException
       */
      public void writeIntoMARYPTCfile(String ptcFileName) throws IOException {
          PitchReaderWriter.write_pitch_file(ptcFileName, this.contour, (float) this.header.windowSizeInSeconds, (float) this.header.skipSizeInSeconds, this.header.fs);
      }
  
  }
  