/**
* Copyright 2004-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 <http://www.gnu.org/licenses/>.
*
*/
package marytts.signalproc.display;
import java.awt.Color;
import java.awt.Graphics2D;
import java.io.File;
import java.util.ArrayList;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.swing.JPanel;
import marytts.signalproc.analysis.FrameBasedAnalyser;
import marytts.signalproc.analysis.ShortTermPhaseSpectrumAnalyser;
import marytts.signalproc.window.GaussWindow;
import marytts.signalproc.window.Window;
import marytts.util.data.BufferedDoubleDataSource;
import marytts.util.data.audio.AudioDoubleDataSource;
/**
*
* @author Marc Schröder
*
* Shows a phasogram of input signal
*
*/
public class Phasogram extends Spectrogram {
public static final int DEFAULT_WINDOWSIZE = 2047;
public static final Window DEFAULT_WINDOW = new GaussWindow(DEFAULT_WINDOWSIZE);
public static final int DEFAULT_WINDOWSHIFT = 1;
public static final int DEFAULT_FFTSIZE = 2048;
protected static final double FREQ_MAX = 4000; // Hz of upper limit frequency to show
public Phasogram(AudioInputStream ais) {
this(ais, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
public Phasogram(AudioInputStream ais, int width, int height) {
this(ais, DEFAULT_WINDOW, DEFAULT_WINDOWSHIFT, DEFAULT_FFTSIZE, width, height);
}
public Phasogram(AudioInputStream ais, Window window, int windowShift, int fftSize) {
this(ais, window, windowShift, fftSize, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
public Phasogram(AudioInputStream ais, Window window, int windowShift, int fftSize, int width, int height) {
super(ais, window, windowShift, fftSize, width, height);
}
public Phasogram(double[] signal, int samplingRate) {
this(signal, samplingRate, DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
public Phasogram(double[] signal, int samplingRate, int width, int height) {
this(signal, samplingRate, DEFAULT_WINDOW, DEFAULT_WINDOWSHIFT, DEFAULT_FFTSIZE, width, height);
}
public Phasogram(double[] signal, int samplingRate, Window window, int windowShift, int fftSize, int width, int height) {
super(signal, samplingRate, window, windowShift, fftSize, width, height);
}
protected void update() {
ShortTermPhaseSpectrumAnalyser spectrumAnalyser = new ShortTermPhaseSpectrumAnalyser(
new BufferedDoubleDataSource(signal), fftSize, window, windowShift, samplingRate);
spectra = new ArrayList();
// Frequency resolution of the FFT:
deltaF = spectrumAnalyser.getFrequencyResolution();
long startTime = System.currentTimeMillis();
FrameBasedAnalyser.FrameAnalysisResult[] results = spectrumAnalyser.analyseAllFrames();
for (int i = 0; i < results.length; i++) {
double[] phaseSpectrum = (double[]) results[i].get();
spectra.add(phaseSpectrum);
}
long endTime = System.currentTimeMillis();
System.err.println("Computed " + spectra.size() + " phase spectra in " + (endTime - startTime) + " ms.");
spectra_indexmax = (int) (FREQ_MAX / deltaF);
if (spectra_indexmax > fftSize / 2)
spectra_indexmax = fftSize / 2; // == spectra[i].length
super.updateData(0, (double) windowShift / samplingRate, new double[spectra.size()]);
// correct y axis boundaries, for graph:
ymin = 0.;
ymax = spectra_indexmax * deltaF;
repaint();
}
protected void initialiseDependentWindows() {
// do nothing, no dependent windows here.
}
protected JPanel getControls() {
return null; // no controls
}
protected void drawSpectrum(Graphics2D g, double[] spectrum, int image_X, int image_width, int image_refY, int image_height) {
double yScaleFactor = (double) image_height / spectra_indexmax;
if (image_width < 2)
image_width = 2;
int rect_height = (int) Math.ceil(yScaleFactor);
if (rect_height < 2)
rect_height = 2;
for (int i = 0; i < spectra_indexmax; i++) {
int color;
// 0 phase is white, +-Pi is black.
assert spectrum[i] >= -Math.PI && spectrum[i] <= Math.PI;
if (Double.isNaN(spectrum[i])) {
color = 255; // white
} else {
color = (int) (255 * (Math.PI + spectrum[i]) / (2 * Math.PI));
}
g.setColor(new Color(color, color, color));
g.fillRect(image_X, image_refY - (int) (i * yScaleFactor), image_width, rect_height);
}
}
public static void main(String[] args) throws Exception {
for (int i = 0; i < args.length; i++) {
AudioInputStream ais = AudioSystem.getAudioInputStream(new File(args[i]));
double[] signal = new AudioDoubleDataSource(ais).getAllData();
int nFrames = 500;
int startSample = 5000;
int fftSize = DEFAULT_FFTSIZE;
double[] excerpt = new double[nFrames + fftSize];
System.arraycopy(signal, startSample, excerpt, 0, excerpt.length);
Phasogram signalSpectrum = new Phasogram(excerpt, (int) ais.getFormat().getSampleRate());
signalSpectrum.showInJFrame(args[i], false, true);
}
}
}