/** * Copyright 2007 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.adaptation; import marytts.signalproc.analysis.Label; import marytts.signalproc.analysis.Labels; import marytts.util.string.StringUtils; /** * A wrapper class for representing phonetic context * * @author Oytun Türk */ public class Context { public int numLeftNeighbours; public int numRightNeighbours; public String allContext; public String[] leftContexts; public String currentContext; public String[] rightContexts; private double[] scores; public static final char leftContextSeparator = '.'; public static final char rightContextSeparator = ','; public static final double LOWEST_CONTEXT_SCORE = 1.0; public Context(Context existing) { numLeftNeighbours = existing.numLeftNeighbours; numRightNeighbours = existing.numRightNeighbours; allContext = existing.allContext; setLeftContext(existing.leftContexts); currentContext = existing.currentContext; setRightContext(existing.rightContexts); setScores(); setAllContext(); } // Create a full context entry using a concatenated allContext entry public Context(String allContextIn) { allContext = allContextIn; parseAllContext(); } public Context(Labels labels, int currentLabelIndex, int totalNeighbours) { this(labels, currentLabelIndex, totalNeighbours, totalNeighbours); } // leftContexts[0] = labels.items[currentLabelIndex-totalLeftNeighbours].phn // leftContexts[1] = labels.items[currentLabelIndex-totalLeftNeighbours+1].phn // ... // leftContexts[totalLeftNeighbours-2] = labels.items[currentLabelIndex-2].phn // leftContexts[totalLeftNeighbours-1] = labels.items[currentLabelIndex-1].phn // currentContext = labels.items[currentLabelIndex].phn // rightContexts[0] = labels.items[currentLabelIndex+1].phn // rightContexts[1] = labels.items[currentLabelIndex+2].phn // ... // rightContexts[totalRightNeighbours-2] = labels.items[currentLabelIndex+totalRightNeighbours-1].phn // rightContexts[totalRightNeighbours-1] = labels.items[currentLabelIndex+totalRightNeighbours].phn // // Note that non-existing context entries are represented by "" public Context(Labels labels, int currentLabelIndex, int totalLeftNeighbours, int totalRightNeighbours) { leftContexts = null; rightContexts = null; currentContext = ""; int i; if (totalLeftNeighbours > 0) { leftContexts = new String[totalLeftNeighbours]; for (i = totalLeftNeighbours; i > 0; i--) { if (labels != null && currentLabelIndex - i >= 0) leftContexts[totalLeftNeighbours - i] = labels.items[currentLabelIndex - i].phn; else leftContexts[totalLeftNeighbours - i] = ""; } } currentContext = labels.items[currentLabelIndex].phn; if (totalRightNeighbours > 0) { rightContexts = new String[totalRightNeighbours]; for (i = 0; i < totalRightNeighbours; i++) { if (labels != null && currentLabelIndex + i + 1 < labels.items.length) rightContexts[i] = labels.items[currentLabelIndex + i + 1].phn; else rightContexts[i] = ""; } } setScores(); setAllContext(); } public void setLeftContext(String[] leftContextIn) { leftContexts = null; if (leftContextIn != null) { leftContexts = new String[leftContextIn.length]; System.arraycopy(leftContextIn, 0, leftContexts, 0, leftContexts.length); } } public void setRightContext(String[] rightContextIn) { rightContexts = null; if (rightContextIn != null) { rightContexts = new String[rightContextIn.length]; System.arraycopy(rightContextIn, 0, rightContexts, 0, rightContexts.length); } } public void setScores() { int maxContext = 0; if (leftContexts != null) maxContext = leftContexts.length; if (rightContexts != null) maxContext = Math.max(maxContext, rightContexts.length); scores = new double[maxContext + 1]; double tmpSum = LOWEST_CONTEXT_SCORE; for (int i = 0; i < maxContext + 1; i++) { scores[i] = tmpSum; tmpSum = 2 * tmpSum + 1; } } public double[] getPossibleScores() { double[] possibleScores = null; if (scores != null) { possibleScores = new double[2 * (scores.length - 1) + 1]; double tmpSum = 0.0; for (int i = 0; i < scores.length - 2; i++) { possibleScores[2 * i] = tmpSum + scores[i]; possibleScores[2 * i + 1] = tmpSum + 2 * scores[i]; tmpSum += 2 * scores[i]; } possibleScores[2 * (scores.length - 1)] = tmpSum + scores[scores.length - 1]; } return possibleScores; } // allContext = L[0].L[1]...L[N-2].L[N-1].C,R[0],R[1],R[2],...,R[N-1] // where L:leftContexts, C:currentContext, R:rightContexts, and "." "," are the left and rightContextSeparators respectively public void setAllContext() { allContext = ""; int i; for (i = 0; i < leftContexts.length; i++) allContext += leftContexts[i] + leftContextSeparator; allContext += currentContext + rightContextSeparator; for (i = 0; i < rightContexts.length - 1; i++) allContext += rightContexts[i] + rightContextSeparator; allContext += rightContexts[rightContexts.length - 1]; } public void parseAllContext() { int[] leftInds = StringUtils.find(allContext, leftContextSeparator); int i, start; if (leftInds != null) { leftContexts = new String[leftInds.length]; start = 0; for (i = 0; i < leftInds.length; i++) { leftContexts[i] = allContext.substring(start, leftInds[i]); start = leftInds[i] + 1; } } else leftContexts = null; int[] rightInds = StringUtils.find(allContext, rightContextSeparator); if (rightInds != null) { rightContexts = new String[rightInds.length]; for (i = 0; i < rightInds.length - 1; i++) rightContexts[i] = allContext.substring(rightInds[i] + 1, rightInds[i + 1]); rightContexts[rightInds.length - 1] = allContext.substring(rightInds[rightInds.length - 1] + 1, allContext.length()); } else rightContexts = null; if (leftInds != null) { if (rightInds != null) currentContext = allContext.substring(leftInds[leftInds.length - 1] + 1, rightInds[0]); else currentContext = allContext.substring(leftInds[leftInds.length - 1] + 1, allContext.length()); } else { if (rightInds != null) currentContext = allContext.substring(0, rightInds[0]); else currentContext = allContext; } setScores(); } public double matchScore(Context context) { assert leftContexts.length == context.leftContexts.length; assert rightContexts.length == context.rightContexts.length; int i; double score = 0.0; if (currentContext.compareTo(context.currentContext) == 0) { score += scores[scores.length - 1]; // current context for (i = leftContexts.length - 1; i >= 0; i--) { if (leftContexts[i].compareTo(context.leftContexts[i]) == 0) score += scores[i]; else break; } for (i = 0; i < rightContexts.length; i++) { if (rightContexts[i].compareTo(context.rightContexts[i]) == 0) score += scores[scores.length - 2 - i]; else break; } } return score; } public static void main(String[] args) { Label[] items1 = new Label[5]; Label[] items2 = new Label[5]; for (int i = 0; i < items1.length; i++) { items1[i] = new Label(); items2[i] = new Label(); } Labels labels1 = new Labels(items1); Labels labels2 = new Labels(items2); labels1.items[0].phn = "A"; labels1.items[1].phn = "B"; labels1.items[2].phn = "C"; labels1.items[3].phn = "D"; labels1.items[4].phn = "E"; labels2.items[0].phn = "A1"; labels2.items[1].phn = "B"; labels2.items[2].phn = "C"; labels2.items[3].phn = "D1"; labels2.items[4].phn = "E1"; Context c1 = new Context(labels1, 2, 2); Context c2 = new Context(labels2, 2, 2); System.out.println(String.valueOf(c1.matchScore(c2))); Context c3 = new Context("t.u.nl,i,n"); System.out.println(c3.currentContext); double[] possibleScores = c1.getPossibleScores(); System.out.println("Test completed"); } }