/** * 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.smoothing; import marytts.signalproc.window.DynamicWindow; import marytts.signalproc.window.Window; /** * * Temporal smoother can be used to smooth acoustic feature vectors along a desired axis. This class is used in voice conversion * to smooth the frequency bins of the vocal tract transformation filter as described in: * * Türk, O., Büyük, O., Haznedaroglu, A., and Arslan, L. M., “Application of Voice Conversion for Cross-Language * Rap Singing Transformation”, “Application of voice conversion for crosslanguage rap singing transformation,” in Proc. of the * IEEE ICASSP 2009, Taipei, Taiwan, April 2009. * * @author Oytun Türk */ public class TemporalSmoother { public static final int DEFAULT_NUM_NEIGHBOURS = 4; // Default neighbours to use on the left and on the right (separately) public static final int DEFAULT_SMOOTHING_WINDOW = Window.HAMMING; public static double[] smooth(double[] x, int neighbours) { return smooth(x, neighbours, DEFAULT_SMOOTHING_WINDOW); } public static double[] smooth(double[] x, int neighbours, int windowType) { int i; double[][] xx = new double[x.length][1]; for (i = 0; i < x.length; i++) xx[i][0] = x[i]; xx = smooth(xx, neighbours, windowType); double[] y = new double[x.length]; for (i = 0; i < x.length; i++) y[i] = xx[i][0]; return y; } public static double[][] smooth(double[][] x, int neighbours) { return smooth(x, neighbours, DEFAULT_SMOOTHING_WINDOW); } // Smooth along each column // i.e. each row corresponds to acoustic features of one frame at a specific instant of time // Windowing based weighting is used public static double[][] smooth(double[][] x, int neighbours, int windowType) { if (neighbours <= 0) return x; else { double[][] y = new double[x.length][x[0].length]; int i, j, k; int windowSize = 2 * neighbours + 1; DynamicWindow w = new DynamicWindow(windowType); double[] weights = w.values(windowSize); double weightSum; for (i = 1; i < x.length; i++) assert x[i].length == x[0].length; for (i = 0; i < x[0].length; i++) { for (j = 0; j < x.length; j++) { y[j][i] = 0.0; weightSum = 0.0; for (k = -neighbours; k <= neighbours; k++) { if (j + k >= 0 && j + k < x.length) { y[j][i] += weights[k + neighbours] * x[j + k][i]; weightSum += weights[k + neighbours]; } } if (weightSum > 0.0) y[j][i] /= weightSum; } } return y; } } public static void main(String[] args) { double[][] xx = new double[10][2]; xx[0][0] = 100.0; xx[0][1] = 220.0; xx[1][0] = 110.0; xx[1][1] = 210.0; xx[2][0] = 150.0; xx[2][1] = 230.0; xx[3][0] = 90.0; xx[3][1] = 220.0; xx[4][0] = 80.0; xx[4][1] = 250.0; xx[5][0] = 120.0; xx[5][1] = 260.0; xx[6][0] = 140.0; xx[6][1] = 290.0; xx[7][0] = 180.0; xx[7][1] = 300.0; xx[8][0] = 150.0; xx[8][1] = 340.0; xx[9][0] = 120.0; xx[9][1] = 320.0; double[][] y = TemporalSmoother.smooth(xx, 3); System.out.println("Finished"); } }