/** * Copyright 2010 DFKI GmbH. * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * * 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. * * 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. * * 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 PitchFileHeader header; private double[] contour; // f0 values in Hz (0.0 for unvoiced) private final float NEGATIVE_MAXIMUM = (float) -1.00E10; /** * read a SPTK lf0 file with following default values windowSizeInSeconds = 0.005f; skipSizeInSeconds = 0.005f; fs = 16000; // * in Hz * * @param lf0SPTKFile * lf0SPTKFile */ public SPTKPitchReaderWriter(String lf0SPTKFile) { this(lf0SPTKFile, 0.005f, 0.005f, 16000); } /** * read a SPTK lf0 file with external settings * * @param lf0SPTKFile * lf0SPTKFile * @param windowSizeInSeconds * windowSizeInSeconds * @param skipSizeInSeconds * skipSizeInSeconds * @param samplingRate * 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 * contour * @param header * header */ public SPTKPitchReaderWriter(double[] contour, PitchFileHeader header) { this.contour = contour; this.header = header; } /** * get f0 values in Hz (0.0 for unvoiced) * * @return self.contour */ public double[] getF0Contour() { return this.contour; } /** * get pitch file header * * @return self.header */ public PitchFileHeader getPitchFileHeader() { return this.header; } /** * * @param lf0SPTKFile * lf0SPTKFile * @return totalFrame * @throws IOException * IO Exception */ 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 * lf0SPTKFile * @return null if !FileUtils.exists(lf0SPTKFile), f0Data otherwise * @throws IOException * IO Exception */ 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 * sptk File Name * @throws IOException * IO Exception */ 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 * ptc file name * @throws IOException * IO Exception */ 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); } /** * @param args * args * @throws IOException * IO Exception */ 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); } }