marytts.tools.voiceimport.SphinxLabeler Maven / Gradle / Ivy
The newest version!
/**
* Copyright 2006 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;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.util.SortedMap;
import java.util.StringTokenizer;
import java.util.TreeMap;
import marytts.util.io.StreamGobbler;
/**
* Preparate the directory of the voice for sphinx labelling
*
* @author Anna Hunecke
*/
public class SphinxLabeler extends VoiceImportComponent {
private DatabaseLayout db;
public final String SPHINX2DIR = "SphinxLabeler.sphinx2Dir";
public final String STDIR = "SphinxLabeler.stDir";
public final String getName() {
return "SphinxLabeler";
}
public SortedMap getDefaultProps(DatabaseLayout db) {
this.db = db;
if (props == null) {
props = new TreeMap();
String sphinx2dir = System.getProperty("SPHINX2DIR");
if (sphinx2dir == null) {
sphinx2dir = "/project/mary/anna/sphinx/sphinx2/";
}
props.put(SPHINX2DIR, sphinx2dir);
props.put(STDIR, db.getProp(db.ROOTDIR) + "st");
}
return props;
}
protected void setupHelp() {
props2Help = new TreeMap();
props2Help.put(SPHINX2DIR, "directory containing the local installation of Sphinx2");
props2Help.put(STDIR, "directory containing all files used for training and labeling");
}
/**
* Do the computations required by this component.
*
* @throws Exception
* Exception
* @return true on success, false on failure
*/
public boolean compute() throws Exception {
System.out.println("Labelling the voice data");
// get voicename and root dir name
// get the root dir and the voicename
String rootDirName = db.getProp(db.ROOTDIR);
String voicename = db.getProp(db.VOICENAME);
/* Sphinx2 variables */
System.out.println("Calling Sphinx2 ...");
String stdir = getProp(STDIR);
// model directory
String hmm = stdir + "/model_parameters/" + voicename + ".s2models/";
// the 'task'
String task = stdir + "/wav";
// dictionary and silence-symbol files
String dictfile = stdir + "/etc/" + voicename + ".dic";
String ndictfile = stdir + "/etc/" + voicename + ".sil";
// list of filenames
String ctlfile = stdir + "/etc/" + voicename + ".fileids";
// the transcription file
String tactlfn = stdir + "/etc/" + voicename + ".align";
// make lab-directory if it does not exist
File stLabDir = new File(stdir + "/lab");
if (!stLabDir.exists()) {
stLabDir.mkdir();
}
/* Run Sphinx2 */
Runtime rtime = Runtime.getRuntime();
// get a shell
Process process = rtime.exec("/bin/bash");
// get an output stream to write to the shell
PrintWriter pw = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
// go to voice directory
pw.print("cd " + rootDirName + "\n");
pw.flush();
// call Sphinx2 and exit
pw.print("( " + getProp(SPHINX2DIR) + "build/bin/sphinx2-batch -adcin TRUE -adcext wav " + "-ctlfn " + ctlfile
+ " -tactlfn " + tactlfn + " -ctloffset 0" + "-ctlcount 100000000 -datadir wav -agcmax FALSE "
+ "-langwt 6.5 -fwdflatlw 8.5 -rescorelw 9.5 -ugwt 0.5" + "-fillpen 1e-10 -silpen 1e-10 -inspen 0.65 -topn 5"
+ "-topsenfrm 3 -topsenthresh -70000 -beam 2e-90 " + "-npbeam 2e-90 -lpbeam 2e-90 -lponlybeam 0.0005 "
+ "-nwbeam 0.0005 -fwdflat FALSE -fwdflatbeam 1e-08 " + "-fwdflatnwbeam 0.0003 -bestpath TRUE -kbdumpdir " + task
+ " " + "-dictfn " + dictfile + " -fdictfn " + ndictfile + " " + "-phnfn " + hmm + "/phone -mapfn " + hmm
+ "/map -hmmdir " + hmm + " " + "-hmmdirlist " + hmm + " -8bsen TRUE -sendumpfn " + hmm + "/sendump" + " -cbdir "
+ hmm + " -phonelabdir st/lab" + "; exit)\n");
pw.flush();
pw.close();
// collect the output
// collect error messages
StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "err");
// collect output messages
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "out");
// start the stream readers
errorGobbler.start();
outputGobbler.start();
// shut down
process.waitFor();
process.exitValue();
System.out.println("... done.");
/* Write the labels into lab directory */
System.out.println("Exporting Labels ...");
// lab destination directory
String labDestDir = db.getProp(db.LABDIR);
String labExtension = db.getProp(db.LABEXT);
// used to prune the times to 5 positions behind .
DecimalFormat df = new DecimalFormat("0.00000");
String line;
// go through original lab files
File[] labFiles = stLabDir.listFiles();
for (int i = 0; i < labFiles.length; i++) {
File nextFile = labFiles[i];
System.out.println(nextFile.getName());
// open original lab file
BufferedReader labIn = new BufferedReader(new FileReader(nextFile));
// open destination lab file
PrintWriter labOut = new PrintWriter(new FileWriter(new File(labDestDir + nextFile.getName())));
String pauseString = null;
// go through original lab file
while ((line = labIn.readLine()) != null) {
if (line.startsWith("#")) {
// copy the line to destination lab file
labOut.println(line);
} else {
// tokenize the line
StringTokenizer tok = new StringTokenizer(line);
// first token is time
double time = Float.parseFloat(tok.nextToken());
// add 0.012
// TODO: find out why we are adding 0.012
time += 0.012;
// prune time to 5 positions behind the dot
String timeString = df.format(time);
// next token is some number
String mysteriousNumber = tok.nextToken();
// next token is the phone
String phone = tok.nextToken();
if (phone.equals("SIL")) {
// replace silence symbol
phone = "_";
// store the pause in pause string; to be written later
// (this has the effect that if two pauses follow
// each other, only the last one is printed)
pauseString = timeString + " " + mysteriousNumber + " " + phone;
} else {
if (pauseString != null) {
// there is still a pause to print
labOut.println(pauseString);
// remove the pause
pauseString = null;
}
// cut off the stuff behind the phone
phone = phone.substring(0, phone.indexOf("("));
// convert phone back to SAMPA
phone = convertPhone(phone);
labOut.println(timeString + " " + mysteriousNumber + " " + phone);
}
}
}
if (pauseString != null) {
// print last pause
labOut.println(pauseString);
}
// close files
labIn.close();
labOut.flush();
labOut.close();
}
System.out.println("... done.");
System.out.println("All done!");
return true;
}
/**
* Convert the given phone from Sphinx-readable format back to SAMPA
*
* @param phone
* the phone
* @return the converted phone
*/
private String convertPhone(String phone) {
boolean uppercase = false;
char[] phoneChars = phone.toCharArray();
StringBuilder convertedPhone = new StringBuilder();
for (int i = 0; i < phoneChars.length; i++) {
char phoneChar = phoneChars[i];
if (Character.isLetter(phoneChar)) {
if (uppercase) {
// character originally was uppercase
// append the phone as it is
convertedPhone.append(phoneChar);
uppercase = false;
} else {
// character originally was lowercase
// convert back to lowercase
convertedPhone.append(Character.toLowerCase(phoneChar));
}
} else {
if (phoneChar == '*') {
// next letter was uppercase, set uppercase to true
uppercase = true;
} else {
// just append other non-letter signs
convertedPhone.append(phoneChar);
}
}
}
return convertedPhone.toString();
}
/**
* 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 -1;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy