marytts.tools.voiceimport.AcousticFeatureFileWriter 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.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import marytts.exceptions.MaryConfigurationException;
import marytts.features.FeatureDefinition;
import marytts.features.FeatureVector;
import marytts.unitselection.data.FeatureFileReader;
import marytts.unitselection.data.Unit;
import marytts.unitselection.data.UnitFileReader;
import marytts.util.data.MaryHeader;
import marytts.util.math.ArrayUtils;
import marytts.util.math.Polynomial;
public class AcousticFeatureFileWriter extends VoiceImportComponent {
protected File maryDir;
protected FeatureFileReader feats;
protected FeatureDefinition inFeatureDefinition;
protected File outFeatureFile;
protected FeatureDefinition outFeatureDefinition;
protected UnitFileReader unitFileReader;
protected FeatureFileReader contours;
protected DatabaseLayout db = null;
protected int percent = 0;
public final String UNITFILE = "AcousticFeatureFileWriter.unitFile";
public final String CONTOURFILE = "AcousticFeatureFileWriter.contourFile";
public final String FEATUREFILE = "AcousticFeatureFileWriter.featureFile";
public final String ACFEATUREFILE = "AcousticFeatureFileWriter.acFeatureFile";
public final String ACFEATDEF = "AcousticFeatureFileWriter.acFeatDef";
public String getName() {
return "AcousticFeatureFileWriter";
}
public SortedMap getDefaultProps(DatabaseLayout theDb) {
this.db = theDb;
if (props == null) {
props = new TreeMap();
String fileDir = theDb.getProp(theDb.FILEDIR);
String maryExt = theDb.getProp(theDb.MARYEXT);
props.put(UNITFILE, fileDir + "halfphoneUnits" + maryExt);
props.put(CONTOURFILE, fileDir + "syllableF0Polynomials" + maryExt);
props.put(FEATUREFILE, fileDir + "halfphoneFeatures" + maryExt);
props.put(ACFEATUREFILE, fileDir + "halfphoneFeatures_ac" + maryExt);
props.put(ACFEATDEF, theDb.getProp(theDb.CONFIGDIR) + "halfphoneUnitFeatureDefinition_ac.txt");
}
return props;
}
protected void setupHelp() {
if (props2Help == null) {
props2Help = new TreeMap();
props2Help.put(UNITFILE, "file containing all halfphone units");
props2Help.put(CONTOURFILE, "file containing the polynomial contours for all syllables, indexed by phone features");
props2Help.put(FEATUREFILE, "file containing all halfphone units and their target cost features");
props2Help.put(ACFEATUREFILE, "file containing all halfphone units and their target cost features"
+ " plus the acoustic target cost features. Will be created by this module.");
props2Help.put(ACFEATDEF, "file containing the list of phone target cost features, their values and weights");
}
}
@Override
public boolean compute() throws IOException, MaryConfigurationException {
System.out.println("Acoustic feature file writer started.");
maryDir = new File(db.getProp(db.FILEDIR));
if (!maryDir.exists()) {
maryDir.mkdir();
System.out.println("Created the output directory [" + (db.getProp(db.FILEDIR)) + "] to store the feature file.");
}
// System.out.println("A");
unitFileReader = new UnitFileReader(getProp(UNITFILE));
// System.out.println("B");
contours = new FeatureFileReader(getProp(CONTOURFILE));
// System.out.println("C");
feats = new FeatureFileReader(getProp(FEATUREFILE));
inFeatureDefinition = feats.getFeatureDefinition();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
inFeatureDefinition.writeTo(pw, true);
// And now, append the two float features for duration and f0:
pw.println("100 linear | unit_duration");
pw.println("100 linear | unit_logf0");
pw.println("0 linear | unit_logf0delta");
pw.close();
String fd = sw.toString();
System.out.println("Generated the following feature definition:");
System.out.println(fd);
StringReader sr = new StringReader(fd);
BufferedReader br = new BufferedReader(sr);
outFeatureDefinition = new FeatureDefinition(br, true);
outFeatureFile = new File(getProp(ACFEATUREFILE));
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(outFeatureFile)));
writeHeaderTo(out);
writeUnitFeaturesTo(out);
out.close();
System.out.println("Number of processed units: " + unitFileReader.getNumberOfUnits());
// make sure we have a feature definition with acoustic features
File featWeights = new File(getProp(ACFEATDEF));
if (!featWeights.exists()) {
try {
PrintWriter featWeightsOut = new PrintWriter(new OutputStreamWriter(new FileOutputStream(featWeights), "UTF-8"),
true);
outFeatureDefinition.generateFeatureWeightsFile(featWeightsOut);
} catch (Exception e) {
System.out.println("No halfphone feature weights ac file " + getProp(ACFEATDEF));
return false;
}
}
FeatureFileReader tester = FeatureFileReader.getFeatureFileReader(getProp(ACFEATUREFILE));
int unitsOnDisk = tester.getNumberOfUnits();
if (unitsOnDisk == unitFileReader.getNumberOfUnits()) {
System.out.println("Can read right number of units");
int r = new Random().nextInt(unitsOnDisk);
System.out.println("feature vector " + r + ":");
System.out.println("Orig: " + feats.getFeatureVector(r).toString());
System.out.println("AC : " + tester.getFeatureVector(r).toString());
return true;
} else {
System.out.println("Read wrong number of units: " + unitsOnDisk);
return false;
}
}
/**
* @param out
* out
* @throws IOException
* IOException
* @throws UnsupportedEncodingException
* UnsupportedEncodingException
* @throws FileNotFoundException
* FileNotFoundException
*/
protected void writeUnitFeaturesTo(DataOutput out) throws IOException, UnsupportedEncodingException, FileNotFoundException {
int numUnits = unitFileReader.getNumberOfUnits();
int unitSampleRate = unitFileReader.getSampleRate();
FeatureDefinition featureDefinition = feats.getFeatureDefinition();
int fiPhoneme = featureDefinition.getFeatureIndex("phone");
byte fvPhoneme_0 = featureDefinition.getFeatureValueAsByte(fiPhoneme, "0");
byte fvPhoneme_Silence = featureDefinition.getFeatureValueAsByte(fiPhoneme, "_");
int fiVowel = featureDefinition.getFeatureIndex("ph_vc");
byte fvVowel = featureDefinition.getFeatureValueAsByte(fiVowel, "+");
int fiLR = featureDefinition.getFeatureIndex("halfphone_lr");
byte fvLR_L = featureDefinition.getFeatureValueAsByte(fiLR, "L");
byte fvLR_R = featureDefinition.getFeatureValueAsByte(fiLR, "R");
int fiSylStart = featureDefinition.getFeatureIndex("segs_from_syl_start");
int fiSylEnd = featureDefinition.getFeatureIndex("segs_from_syl_end");
int iSylVowel = -1;
List unitDurs = new ArrayList();
out.writeInt(numUnits);
System.out.println("Number of units : " + numUnits);
int iCurrent = 0;
for (int i = 0; i < numUnits; i++) {
percent = 100 * i / numUnits;
FeatureVector inFV = feats.getFeatureVector(i);
Unit u = unitFileReader.getUnit(i);
float dur = u.duration / (float) unitSampleRate;
// No syllable structure for edge and silence phone entries:
if (inFV.getByteFeature(fiPhoneme) == fvPhoneme_0 || inFV.getByteFeature(fiPhoneme) == fvPhoneme_Silence) {
unitDurs.add(dur);
continue;
}
// Else, unit belongs to a syllable
if (inFV.getByteFeature(fiSylStart) == 0 && inFV.getByteFeature(fiLR) == fvLR_L) { // first segment in syllable
if (iCurrent < i) { // Something to output before this syllable
assert i - iCurrent == unitDurs.size();
writeFeatureVectors(out, iCurrent, iSylVowel, i - 1, unitDurs);
}
unitDurs.clear();
iSylVowel = -1;
iCurrent = i;
}
unitDurs.add(dur);
if (inFV.getByteFeature(fiVowel) == fvVowel && iSylVowel == -1) { // the first vowel in the syllable
iSylVowel = i;
}
if (inFV.getByteFeature(fiSylEnd) == 0 && inFV.getByteFeature(fiLR) == fvLR_R) { // last segment in syllable
writeFeatureVectors(out, iCurrent, iSylVowel, i, unitDurs);
iSylVowel = -1;
unitDurs.clear();
iCurrent = i + 1;
}
}
assert numUnits - iCurrent == unitDurs.size();
writeFeatureVectors(out, iCurrent, iSylVowel, numUnits - 1, unitDurs);
}
private void writeFeatureVectors(DataOutput out, int iFirst, int iVowel, int iLast, List unitDurs) throws IOException {
float[] coeffs = null;
if (iVowel != -1) { // Syllable contains a vowel
coeffs = contours.getFeatureVector(iVowel).getContinuousFeatures();
boolean isZero = true;
for (int c = 0; c < coeffs.length; c++) {
if (coeffs[c] != 0) {
isZero = false;
break;
}
}
if (isZero) {
coeffs = null;
}
}
assert unitDurs.size() == iLast - iFirst + 1;
float sylDur = 0;
for (int i = 0, max = unitDurs.size(); i < max; i++) {
sylDur += unitDurs.get(i);
}
// System.out.println("Syl dur: "+sylDur+", "+unitDurs.size()+" units");
float uStart = 0, uEnd = 0;
for (int i = 0; iFirst + i <= iLast; i++) {
float logF0 = Float.NaN;
float logF0delta = Float.NaN;
if (coeffs != null && unitDurs.get(i) > 0) {
float relUStart = uStart / sylDur; // in [0, 1[
float relUEnd = (uStart + unitDurs.get(i)) / sylDur; // in [0, 1[
double[] predUnitContour = Polynomial.generatePolynomialValues(ArrayUtils.copyFloat2Double(coeffs), 10,
relUStart, relUEnd);
// System.out.printf("From %.2f to %.2f:", relUStart, relUEnd);
// for (int k=0; k
© 2015 - 2025 Weber Informatics LLC | Privacy Policy