All Downloads are FREE. Search and download functionalities are using the official Maven repository.

marytts.tools.voiceimport.vocalizations.VocalizationTimelineMaker Maven / Gradle / Ivy

The newest version!
/**
 * 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 .
 *
 */

package marytts.tools.voiceimport.vocalizations;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.text.DecimalFormat;
import java.util.SortedMap;
import java.util.TreeMap;

import marytts.tools.voiceimport.DatabaseLayout;
import marytts.tools.voiceimport.TimelineWriter;
import marytts.tools.voiceimport.VoiceImportComponent;
import marytts.tools.voiceimport.WavReader;
import marytts.util.data.Datagram;
import marytts.util.data.ESTTrackReader;
import marytts.util.io.BasenameList;

public class VocalizationTimelineMaker extends VoiceImportComponent {

	String vocalizationsDir;
	BasenameList bnlVocalizations;

	protected DatabaseLayout db = null;
	protected int percent = 0;
	public final String WAVETIMELINE = "VocalizationTimelineMaker.waveTimeline";
	public final String WAVEDIR = "VocalizationTimelineMaker.inputWaveDir";
	public final String PMARKDIR = "VocalizationTimelineMaker.pitchmarkDir";

	public final String PMDIR = "db.pmDir";
	public final String PMEXT = "db.pmExtension";

	public String getName() {
		return "VocalizationTimelineMaker";
	}

	@Override
	protected void initialiseComp() {
		String timelineDir = db.getProp(db.VOCALIZATIONSDIR) + File.separator + "files";
		if (!(new File(timelineDir)).exists()) {

			System.out.println("vocalizations/files directory does not exist; ");
			if (!(new File(timelineDir)).mkdirs()) {
				throw new Error("Could not create vocalizations/files");
			}
			System.out.println("Created successfully.\n");

		}

		try {
			String basenameFile = db.getProp(db.VOCALIZATIONSDIR) + File.separator + "basenames.lst";
			if ((new File(basenameFile)).exists()) {
				System.out.println("Loading basenames of vocalizations from '" + basenameFile + "' list...");
				bnlVocalizations = new BasenameList(basenameFile);
				System.out.println("Found " + bnlVocalizations.getLength() + " vocalizations in basename list");
			} else {
				String vocalWavDir = db.getProp(db.VOCALIZATIONSDIR) + File.separator + "wav";
				System.out.println("Loading basenames of vocalizations from '" + vocalWavDir + "' directory...");
				bnlVocalizations = new BasenameList(vocalWavDir, ".wav");
				System.out.println("Found " + bnlVocalizations.getLength() + " vocalizations in " + vocalWavDir + " directory");
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public SortedMap getDefaultProps(DatabaseLayout db) {
		this.db = db;
		if (props == null) {
			props = new TreeMap();
			props.put(WAVEDIR, db.getProp(db.VOCALIZATIONSDIR) + File.separator + "wav");
			props.put(PMARKDIR, db.getProp(db.VOCALIZATIONSDIR) + File.separator + "pm");
			props.put(WAVETIMELINE, db.getProp(db.VOCALIZATIONSDIR) + File.separator + "files" + File.separator
					+ "vocalization_wave_timeline" + db.getProp(db.MARYEXT));
			// vocalizationsDir = db.getProp(db.ROOTDIR)+File.separator+"vocalizations";
		}
		return props;
	}

	protected void setupHelp() {
		props2Help = new TreeMap();
		props2Help.put(WAVETIMELINE, "file containing all wave files. Will be created by this module");
	}

	/**
	 * Reads and concatenates a list of waveforms into one single timeline file.
	 *
	 */
	public boolean compute() {
		System.out.println("---- Making a pitch synchronous waveform timeline\n\n");

		/* Export the basename list into an array of strings */
		String[] baseNameArray = bnlVocalizations.getListAsArray();
		System.out.println("Processing [" + baseNameArray.length + "] utterances.\n");

		try {
			/*
			 * 1) Determine the reference sampling rate as being the sample rate of the first encountered wav file
			 */
			WavReader wav = new WavReader(getProp(WAVEDIR) + baseNameArray[0] + db.getProp(db.WAVEXT));
			int globSampleRate = wav.getSampleRate();
			System.out.println("---- Detected a global sample rate of: [" + globSampleRate + "] Hz.");

			System.out.println("---- Folding the wav files according to the pitchmarks...");

			/* 2) Open the destination timeline file */

			/* Make the file name */
			String waveTimelineName = getProp(WAVETIMELINE);
			System.out.println("Will create the waveform timeline in file [" + waveTimelineName + "].");

			/* Processing header: */
			String processingHeader = "\n";

			/* Instantiate the TimelineWriter: */
			TimelineWriter waveTimeline = new TimelineWriter(waveTimelineName, processingHeader, globSampleRate, 0.1);

			/* 3) Write the datagrams and feed the index */

			float totalDuration = 0.0f; // Accumulator for the total timeline duration
			long totalTime = 0l;
			int numDatagrams = 0;

			/* For each EST track file: */
			ESTTrackReader pmFile = null;
			for (int i = 0; i < baseNameArray.length; i++) {
				percent = 100 * i / baseNameArray.length;

				/* - open+load */
				System.out.println(baseNameArray[i]);
				pmFile = new ESTTrackReader(getProp(PMARKDIR) + baseNameArray[i] + db.getProp(PMEXT));
				totalDuration += pmFile.getTimeSpan();
				wav = new WavReader(getProp(WAVEDIR) + baseNameArray[i] + db.getProp(db.WAVEXT));
				short[] wave = wav.getSamples();
				/* - Reset the frame locations in the local file */
				int frameStart = 0;
				int frameEnd = 0;
				int duration = 0;
				long localTime = 0l;
				/* - For each frame in the WAV file: */
				for (int f = 0; f < pmFile.getNumFrames(); f++) {

					/* Locate the corresponding segment in the wave file */
					frameStart = frameEnd;
					frameEnd = (int) ((double) pmFile.getTime(f) * (double) (globSampleRate));
					assert frameEnd <= wave.length : "Frame ends after end of wave data: " + frameEnd + " > " + wave.length;

					duration = frameEnd - frameStart;
					ByteArrayOutputStream buff = new ByteArrayOutputStream(2 * duration);
					DataOutputStream subWave = new DataOutputStream(buff);
					for (int k = 0; k < duration; k++) {
						subWave.writeShort(wave[frameStart + k]);
					}

					// Handle the case when the last pitch marks falls beyond the end of the signal

					/* Feed the datagram to the timeline */
					waveTimeline.feed(new Datagram(duration, buff.toByteArray()), globSampleRate);
					totalTime += duration;
					localTime += duration;
					numDatagrams++;
				}
				// System.out.println( baseNameArray[i] + " -> pm file says [" + localTime + "] samples, wav file says ["+
				// wav.getNumSamples() + "] samples." );
			}
			waveTimeline.close();

			System.out.println("---- Done.");

			/* 7) Print some stats and close the file */
			System.out.println("---- Waveform timeline result:");
			System.out.println("Number of files scanned: " + baseNameArray.length);
			System.out.println("Total speech duration: [" + totalTime + "] samples / ["
					+ ((float) (totalTime) / (float) (globSampleRate)) + "] seconds.");
			System.out.println("(Speech duration approximated from EST Track float times: [" + totalDuration + "] seconds.)");
			System.out.println("Number of frames: [" + numDatagrams + "].");
			System.out.println("Size of the index: [" + waveTimeline.getIndex().getNumIdx() + "] ("
					+ (waveTimeline.getIndex().getNumIdx() * 16) + " bytes, i.e. "
					+ new DecimalFormat("#.##").format((double) (waveTimeline.getIndex().getNumIdx()) * 16.0 / 1048576.0)
					+ " megs).");
			System.out.println("---- Waveform timeline done.");

		} catch (SecurityException e) {
			System.err.println("Error: you don't have write access to the target database directory.");
			e.printStackTrace();
			return false;
		} catch (Exception e) {
			e.printStackTrace();
			System.err.println(e);
			return false;
		}

		return (true);
	}

	/**
	 * Provide the progress of computation, in percent, or -1 if that feature is not implemented.
	 * 
	 * @return -1 if not implemented, or an integer between 0 and 100.
	 */
	public int getProgress() {
		return percent;
	}

	/**
	 * @param args
	 *            args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy