/*
* AnalysisOp.java
* (FScape)
*
* Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de
*/
package de.sciss.fscape.op;
import de.sciss.fscape.gui.GroupLabel;
import de.sciss.fscape.gui.OpIcon;
import de.sciss.fscape.gui.PathField;
import de.sciss.fscape.gui.PropertyGUI;
import de.sciss.fscape.prop.OpPrefs;
import de.sciss.fscape.prop.Prefs;
import de.sciss.fscape.prop.Presets;
import de.sciss.fscape.prop.PropertyArray;
import de.sciss.fscape.spect.Fourier;
import de.sciss.fscape.spect.SpectFrame;
import de.sciss.fscape.spect.SpectStream;
import de.sciss.fscape.spect.SpectStreamSlot;
import de.sciss.fscape.util.Constants;
import de.sciss.fscape.util.Filter;
import de.sciss.fscape.util.Param;
import de.sciss.fscape.util.Slots;
import de.sciss.fscape.util.Util;
import de.sciss.io.AudioFile;
import de.sciss.io.AudioFileDescr;
import java.awt.*;
import java.io.File;
import java.io.IOException;
/**
* Analysis Operator to transform sound file from time to frequency domain
*/
public class AnalysisOp
extends Operator {
// -------- private variables --------
protected static final String defaultName = "Analyse"; // "real" name (z.B. Icons)
protected static Presets static_presets = null;
protected static Prefs static_prefs = null;
protected static PropertyArray static_pr = null;
// Slots
protected static final int SLOT_OUTPUT = 0; // es kann nur einen geben
// Properties (defaults)
private static final int PR_FILENAME = 0; // Array-Indices: pr.text
private static final int PR_FFTLENGTH = 0; // pr.intg
private static final int PR_OVERSMP = 1;
private static final int PR_WINDOW = 2;
private static final int PR_OVERLAP = 3;
private static final int PR_TYPE = 4;
private static final int PR_ADJUSTSTART = 0; // pr.bool
private static final int PR_ADJUSTLENGTH = 1;
private static final int PR_ROTATE = 2;
private static final int PR_STARTSHIFT = 0; // pr.para
private static final int PR_LENGTH = 1;
private static final int PR_LOFREQ = 2;
private static final int PR_HIFREQ = 3;
private static final int PR_LORADIUS = 4;
private static final int PR_HIRADIUS = 5;
protected static final int TYPE_FFT = 0;
protected static final int TYPE_CZT = 1;
protected static final int TYPE_NONE = 2;
private static final String PRN_FILENAME = "Filename"; // Property-Keynames
private static final String PRN_FFTLENGTH = "FFTLength";
private static final String PRN_OVERSMP = "OverSmp";
private static final String PRN_WINDOW = "Window";
private static final String PRN_OVERLAP = "Overlap";
private static final String PRN_TYPE = "Type";
private static final String PRN_ADJUSTSTART = "AdjustStart";
private static final String PRN_ADJUSTLENGTH= "AdjustLength";
private static final String PRN_STARTSHIFT = "StartShift";
private static final String PRN_LENGTH = "Length";
private static final String PRN_LOFREQ = "LoFreq";
private static final String PRN_HIFREQ = "HiFreq";
private static final String PRN_LORADIUS = "LoRadius";
private static final String PRN_HIRADIUS = "HiRadius";
private static final String PRN_ROTATE = "Rotate";
private static final String prText[] = { "" };
private static final String prTextName[] = { PRN_FILENAME };
private static final int prIntg[] = { 6, 0, 0, 2, TYPE_FFT };
private static final String prIntgName[] = { PRN_FFTLENGTH, PRN_OVERSMP, PRN_WINDOW, PRN_OVERLAP,
PRN_TYPE };
private static final boolean prBool[] = { false, false, true };
private static final String prBoolName[] = { PRN_ADJUSTSTART, PRN_ADJUSTLENGTH, PRN_ROTATE };
private static final Param prPara[] = { null, null, null, null, null, null };
private static final String prParaName[] = { PRN_STARTSHIFT, PRN_LENGTH, PRN_LOFREQ, PRN_HIFREQ,
PRN_LORADIUS, PRN_HIRADIUS };
protected static final int[] overlaps = { 1, 2, 4, 8, 16 };
// Laufzeitfehler
protected static final String ERR_NOINPUT = "No input file";
// -------- public methods --------
public AnalysisOp()
{
super();
// initialize only in the first instance
// preferences laden
if( static_prefs == null ) {
static_prefs = new OpPrefs( getClass(), getDefaultPrefs() );
}
// propertyarray defaults
if( static_pr == null ) {
static_pr = new PropertyArray();
static_pr.text = prText;
static_pr.textName = prTextName;
static_pr.intg = prIntg;
static_pr.intgName = prIntgName;
static_pr.bool = prBool;
static_pr.boolName = prBoolName;
static_pr.para = prPara;
static_pr.para[ PR_STARTSHIFT ] = new Param( 0.0, Param.ABS_MS );
static_pr.para[ PR_LENGTH ] = new Param( 5000.0, Param.ABS_MS );
static_pr.para[ PR_LOFREQ ] = new Param( 0.0, Param.ABS_HZ );
static_pr.para[ PR_HIFREQ ] = new Param( 22050.0, Param.ABS_HZ );
static_pr.para[ PR_LORADIUS ] = new Param( 0.0, Param.DECIBEL_AMP );
static_pr.para[ PR_HIRADIUS ] = new Param( 0.0, Param.DECIBEL_AMP );
static_pr.paraName = prParaName;
static_pr.superPr = Operator.op_static_pr;
}
// default preset
if( static_presets == null ) {
static_presets = new Presets( getClass(), static_pr.toProperties( true ));
}
// superclass-Felder uebertragen
opName = "AnalysisOp";
prefs = static_prefs;
presets = static_presets;
pr = (PropertyArray) static_pr.clone();
// slots
slots.addElement( new SpectStreamSlot( this, Slots.SLOTS_WRITER )); // SLOT_OUTPUT
// icon
icon = new OpIcon( this, OpIcon.ID_INPUT, defaultName );
}
// -------- Runnable methods --------
public void run() {
runInit(); // superclass
int i, j, k, m, off, len, ch;
double d1, d2, d3, d4, d5, d6;
float f1;
// Haupt-Variablen fuer den Prozess
String runFileName;
AudioFile runFile = null;
int runStartFrame; // read-offset
int runFrames; // read-length
int runInLength;
int runFramesRead = 0;
SpectStreamSlot runOutSlot;
AudioFileDescr runInStream;
SpectStream tmpStream;
SpectStream runOutStream;
SpectFrame runOutFr;
// Berechnungs-Grundlagen
Param inLengthP; // transform-Referenz
double startShift;
double outLength;
int winSize = 131072 >> pr.intg[ PR_FFTLENGTH ];
int winHalf = winSize >> 1;
int winStep = winSize / overlaps[ pr.intg[ PR_OVERLAP ]];
int fftLength, fullFFTlength, bands;
float[] win;
int inLength, inChanNum;
float[] fftBuf, convBuf1;
float[][] inBuf;
int inBufOff;
int framesRead;
int chunkLength;
boolean chirp = pr.intg[ PR_TYPE ] == TYPE_CZT;
boolean fourier = pr.intg[ PR_TYPE ] == TYPE_FFT;
double loFreq, hiFreq, loRadius, hiRadius, chirpAngle, chirpRadius;
double[] chirpImpulse = null;
float[] fftBuf2 = null;
int oversmp = pr.intg[ PR_OVERSMP ];
// ------------------------------ Filename ------------------------------
if ((pr.text[PR_FILENAME] == null) || (pr.text[PR_FILENAME].length() == 0)) {
FileDialog fDlg; // ausnahmsweise nicht am methods-Anfang ;)
String fiName, fiDir;
final Component ownerF = owner.getModule().getComponent(); // .getWindow().getWindow();
final boolean makeF = !(ownerF instanceof Frame);
final Frame f = makeF ? new Frame() : (Frame) ownerF;
fDlg = new FileDialog(f, ((OpIcon) getIcon()).getName() +
": Select inputfile");
fDlg.setVisible(true);
if (makeF) f.dispose();
fiName = fDlg.getFile();
fiDir = fDlg.getDirectory();
fDlg.dispose();
if (fiDir == null) fiDir = "";
if (fiName == null) { // Cancel. Wir koennen folglich nichts mehr tun
runQuit(new IOException(ERR_NOINPUT));
return;
}
runFileName = fiDir + fiName;
} else {
runFileName = pr.text[PR_FILENAME];
}
try { // catching IOExceptions
runFile = AudioFile.openAsRead(new File(runFileName));
runInStream = runFile.getDescr();
inLength = (int) runInStream.length;
inChanNum = runInStream.channels;
// ------------------------------ Start/Endpunkt ------------------------------
inLengthP = new Param(AudioFileDescr.samplesToMillis(runInStream, inLength),
Param.ABS_MS);
startShift = Param.transform(pr.para[PR_STARTSHIFT], Param.ABS_MS, inLengthP, null).value;
outLength = Param.transform(pr.para[PR_LENGTH], Param.ABS_MS, inLengthP, null).value;
tmpStream = new SpectStream();
tmpStream.smpRate = (float) runInStream.rate; // this sucks like hell
loFreq = Param.transform(pr.para[PR_LOFREQ], Param.ABS_HZ, null, tmpStream).value *
Constants.PI2 / tmpStream.smpRate;
hiFreq = Param.transform(pr.para[PR_HIFREQ], Param.ABS_HZ, null, tmpStream).value *
Constants.PI2 / tmpStream.smpRate;
loRadius = Param.transform(pr.para[PR_LORADIUS], Param.ABS_AMP, new Param(1.0, Param.ABS_AMP),
null).value;
hiRadius = Param.transform(pr.para[PR_HIRADIUS], Param.ABS_AMP, new Param(1.0, Param.ABS_AMP),
null).value;
if (pr.bool[PR_ADJUSTSTART]) {
runStartFrame = Math.min(inLength, (int)
(AudioFileDescr.millisToSamples(runInStream, startShift) + 0.5));
} else {
runStartFrame = 0;
}
runFile.seekFrame(runStartFrame); // schonmal das erste anfahren
if (pr.bool[PR_ADJUSTLENGTH]) {
runInLength = Math.min(inLength - runStartFrame, (int)
(AudioFileDescr.millisToSamples(runInStream, outLength) + 0.5));
} else {
runInLength = inLength - runStartFrame;
}
// ------------------------------ weitere init ------------------------------
runFrames = (runInLength + winSize - 1) / winStep;
if (chirp) {
fftLength = winSize << (oversmp + 1);
fullFFTlength = fftLength << 1;
fftBuf2 = new float[fullFFTlength + 2];
Util.clear(fftBuf2);
chirpImpulse = new double[fullFFTlength + 2];
} else {
if (!fourier) oversmp++; // since waveform is real and spect-data complex
fftLength = winSize << oversmp;
fullFFTlength = fftLength;
}
bands = (winSize << oversmp >> 1); // +1
fftBuf = new float[fullFFTlength + 2];
inBuf = new float[inChanNum][winSize];
Util.clear(inBuf);
/*
int n, o;
float[] win2;
float f2;
for( i = 0; i <= Filter.WIN_MAX; i++ ) {
for( j = i; j <= Filter.WIN_MAX; j++ ) {
Util.clear( fftBuf );
win = Filter.createFullWindow( winSize, i );
win2 = Filter.createFullWindow( winSize, j );
for( k = 0; k < fftLength / winStep; k++ ) {
for( m = k * winStep, n = 0; n < winSize; m++, n++ ) {
fftBuf[ m % fftLength ] += win[ n ]*win2[ n ];
}
}
f1 = 99999f;
f2 = -99999f;
for( k = 0; k < fftLength; k++ ) {
if( fftBuf[k] < f1 ) f1 = fftBuf[k];
if( fftBuf[k] > f2 ) f2 = fftBuf[k];
}
f1 = (f2 - f1);
System.out.println( Filter.getWindowNames()[i]+" / "+Filter.getWindowNames()[j]+" : max dev. "+(f1*100)+"% " );
}
}
*/
win = Filter.createFullWindow(winSize, pr.intg[PR_WINDOW]);
if (chirp) { // -------------------- CZT --------------------
// modulate window by A^-n*W^(n*n/2) see Oppenheim/Schafer, DSP (6.41)
d5 = (double) bands; // -1 ?
chirpRadius = Math.pow(hiRadius / loRadius, 1.0 / d5);
chirpAngle = (hiFreq - loFreq) / d5;
// System.out.println( "loFreq "+loFreq+"; hiFreq "+hiFreq+"; loRadius "+loRadius+"; hiRadius "+hiRadius+"; chirpRadius "+chirpRadius+"; chirpAngle "+chirpAngle );
d3 = 1.0 / Math.sqrt(chirpRadius);
// used to be "-chirpAngle * -0.5" which produced a reversed output
// don't really know why we have to change the sign ??
d4 = chirpAngle * -0.5; // d3*exp(j d4) = W^(-1/2)
// System.out.println( "2*bands "+(bands*2)+"; chirpLen "+(chirpImpulse.length>>1)+"; fftLength"+fftLength );
for (i = 0, j = 0, m = fullFFTlength; i <= fftLength; j++) { // 0 (?) n (?) M-1
k = j * j;
d1 = Math.pow(d3, k);
d2 = d4 * k; // d1*exp(j d2) = W^(-n^2/2) = h(n)
chirpImpulse[i] = 1.0 / d1; // chirpImpulse stores 1/h(n)
fftBuf2[i] = (float) (d1 * Math.cos(d2)); // prepare to FFT h(n)
chirpImpulse[m] = chirpImpulse[i];
fftBuf2[m] = fftBuf2[i];
i++;
m++;
chirpImpulse[i] = -d2;
fftBuf2[i] = (float) (d1 * Math.sin(d2));
chirpImpulse[m] = chirpImpulse[i];
fftBuf2[m] = fftBuf2[i];
i++;
m -= 3;
}
Fourier.complexTransform(fftBuf2, fftLength, Fourier.FORWARD);
// Debug.view( fftBuf2, "linear filter" );
d3 = 1.0 / loRadius;
d4 = -loFreq; // now d1*exp(j d2) = A^-1
// normalize energy
for (i = 0, d6 = 0.0; i < winSize; i++) {
d6 += (double) win[i];
}
d6 = 1.0 / d6;
convBuf1 = win;
win = new float[win.length << 1]; // getting complex...
// k = (bands - winSize) << 1;
//System.out.println( "k = "+k );
k = 0;
for (i = 0, j = 0; j < winSize; j++) {
d1 = (double) convBuf1[j] * d6 * Math.pow(d3, j) * // d6 = energy normalization
chirpImpulse[k++];
d2 = d4 * j + chirpImpulse[k++]; // d1*exp(j d2) = A^-n/h(n) * w(n)
win[i++] = (float) (d1 * Math.cos(d2));
win[i++] = (float) (d1 * Math.sin(d2));
}
// Debug.view( win, "an window" );
} else { // -------------------- FFT --------------------
// normalize energy
for (i = 0, d1 = 0.0; i < winSize; i++) {
d1 += (double) win[i];
}
f1 = (float) (1.0 / d1); // (float) (1.0 / d1);
for (i = 0; i < winSize; i++) {
win[i] *= f1;
}
}
// ------------------------------ Output-Stream ------------------------------
i = (bands << 3) * inChanNum; // approx. frame size
// System.out.println( Math.max( 2, 0x40000 / i ));
runOutStream = new SpectStream(Math.max(2, 0x40000 / i)); // "good" bufsize
runOutStream.setChannels(inChanNum);
runOutStream.setBands(0.0f, (float) runInStream.rate / 2, bands + 1, SpectStream.MODE_LIN);
runOutStream.setRate((float) runInStream.rate, winStep);
runOutStream.setEstimatedLength(runFrames);
runOutSlot = slots.elementAt(SLOT_OUTPUT);
runOutSlot.initWriter(runOutStream);
// ------------------------------ Hauptschleife ------------------------------
runSlotsReady();
inBufOff = 0; // rotate offset instead of buffer content shifting (faster)
framesRead = 0;
// chunkLength = winSize; // first pass: fill full buffer
chunkLength = winStep; // always
// System.out.println( "Sy: chunkLen "+winStep );
while ((runFramesRead < runFrames) && !threadDead) {
// read sound chunk
len = Math.min(chunkLength, runInLength - framesRead);
off = (inBufOff + winSize - chunkLength) % winSize;
runFile.readFrames(inBuf, off, len);
// zero pad
if (len < chunkLength) {
for (ch = 0; ch < inChanNum; ch++) {
convBuf1 = inBuf[ch];
for (j = off + len, k = off + chunkLength; j < k; ) {
convBuf1[j++] = 0.0f;
}
}
}
runFramesRead++;
framesRead += len;
// transform
runOutFr = runOutStream.allocFrame();
for (ch = 0; ch < inChanNum; ch++) {
convBuf1 = inBuf[ch];
switch (pr.intg[PR_TYPE]) {
case TYPE_CZT: // -------------------- CZT --------------------
if (pr.bool[PR_ROTATE]) {
// we shift the origin so that the middle smp of inBuf becomes fftBuf[ 0 ],
// this gives better phasograms
// not compatible with soundhack; but we aren't anyways ;---)
for (i = inBufOff, j = fullFFTlength - winSize, k = 0; k < winSize; ) {
m = Math.min(winSize - k, Math.min(winSize - i, (fullFFTlength - j) >> 1));
k += m;
for (; m > 0; m--) {
f1 = convBuf1[i++];
fftBuf[j++] = f1;
fftBuf[j++] = f1;
}
i %= winSize;
j %= fullFFTlength;
}
// apply right wing window
for (i = 0, j = winSize; i < winSize; i++, j++) {
fftBuf[i] *= win[j];
}
// zero pad oversampling range
for (; i < fullFFTlength - winSize; i++) {
fftBuf[i] = 0.0f;
}
// apply left wing window
for (j = 0; i < fullFFTlength; i++, j++) {
fftBuf[i] *= win[j];
}
// if( (runOutStream.framesWritten == 4) && (ch == 0) ) Debug.view( fftBuf, "post" );
Fourier.complexTransform(fftBuf, fftLength, Fourier.FORWARD);
Fourier.complexMult(fftBuf2, 0, fftBuf, 0, fftBuf, 0, fullFFTlength); // convolved with h(n)
Fourier.complexTransform(fftBuf, fftLength, Fourier.INVERSE);
convBuf1 = runOutFr.data[ch];
// rect => polar + modulation
for (i = 0, j = fullFFTlength - winSize, k = 0; i <= bands; ) {
m = Math.min((fullFFTlength - j) >> 1, bands + 1 - i);
i += m;
for (; m > 0; m--) {
d1 = fftBuf[j++]; // rect
d2 = fftBuf[j++];
d3 = chirpImpulse[k]; // polar
d4 = chirpImpulse[k + 1];
convBuf1[k++] = (float) (Math.sqrt(d1 * d1 + d2 * d2) * d3); // modulate with 1/h(n)
convBuf1[k++] = (float) (Math.atan2(d2, d1) + d4);
}
j %= fullFFTlength;
}
} else { // no rotation
// copy windowed input portion
for (i = inBufOff, j = 0, k = 0; k < winSize; ) {
m = Math.min(winSize - k, winSize - i);
k += m;
for (; m > 0; m--) {
f1 = convBuf1[i++];
fftBuf[j] = f1 * win[j]; // Re modulated with A^-n/h(n)*w(n)
j++;
fftBuf[j] = f1 * win[j]; // Im
j++;
}
i %= winSize;
}
// zero pad oversmp range
for (; j < fullFFTlength; j++) {
fftBuf[j] = 0.0f;
}
Fourier.complexTransform(fftBuf, fftLength, Fourier.FORWARD);
Fourier.complexMult(fftBuf2, 0, fftBuf, 0, fftBuf, 0, fullFFTlength); // convolved with h(n)
Fourier.complexTransform(fftBuf, fftLength, Fourier.INVERSE);
convBuf1 = runOutFr.data[ch];
// rect => polar + modulation
for (i = 0, j = 0; i <= bands; i++, j += 2) {
k = j + 1;
d1 = fftBuf[j]; // rect
d2 = fftBuf[k];
d3 = chirpImpulse[j]; // polar
d4 = chirpImpulse[k];
convBuf1[j] = (float) (Math.sqrt(d1 * d1 + d2 * d2) * d3); // modulate with 1/h(n)
convBuf1[k] = (float) (Math.atan2(d2, d1) + d4);
}
}
// if( (runOutStream.framesWritten < 3) && (ch == 0) ) Debug.view( fftBuf, "an fft"+runOutStream.framesWritten );
break;
case TYPE_FFT: // -------------------- FFT --------------------
case TYPE_NONE: // -------------------- None --------------------
if (pr.bool[PR_ROTATE]) {
// we shift the origin so that the middle smp of inBuf becomes fftBuf[ 0 ],
// this gives better phasograms
// not compatible with soundhack; but we aren't anyways ;---)
for (i = inBufOff, j = fftLength - winHalf, k = 0; k < winSize; ) {
m = Math.min(winSize - k, Math.min(winSize - i, fftLength - j));
System.arraycopy(convBuf1, i, fftBuf, j, m);
i = (i + m) % winSize;
j = (j + m) % fftLength;
k += m;
}
// apply right wing window
for (i = 0, j = winHalf; i < winHalf; i++, j++) {
fftBuf[i] *= win[j];
}
// zero pad oversampling range
for (; i < fftLength - winHalf; i++) {
fftBuf[i] = 0.0f;
}
// apply left wing window
for (j = 0; i < fftLength; i++, j++) {
fftBuf[i] *= win[j];
}
} else {
// copy windowed input portion
for (i = inBufOff, j = 0, k = 0; k < winSize; ) {
m = Math.min(winSize - k, winSize - i);
for (; m > 0; m--) {
fftBuf[j++] = convBuf1[i++] * win[k++];
}
i %= winSize;
}
// zero pad oversmp range
for (; j < fftLength; j++) {
fftBuf[j] = 0.0f;
}
}
convBuf1 = runOutFr.data[ch];
if (fourier) {
Fourier.realTransform(fftBuf, fftLength, Fourier.FORWARD);
// if( (runOutStream.framesWritten < 3) && (ch == 0) ) Debug.view( fftBuf, "an fft"+runOutStream.framesWritten );
} else {
if (pr.bool[PR_ROTATE]) { // real => complex
for (i = fftLength - winSize, j = fftLength - winHalf; i < winSize; ) {
fftBuf[i++] = fftBuf[j++];
fftBuf[i++] = 0.0f;
}
for (i = winHalf, j = winSize; i > 0; ) {
fftBuf[--j] = 0.0f;
fftBuf[--j] = fftBuf[--i];
}
} else {
for (i = winSize, j = winSize * 2; i > 0; ) {
fftBuf[--j] = 0.0f;
fftBuf[--j] = fftBuf[--i];
}
}
}
Fourier.rect2Polar(fftBuf, 0, convBuf1, 0, fftLength + 2);
break;
} // switch( type ) ende
} // for channels
// send output
for (boolean writeDone = false; (!writeDone) && !threadDead; ) {
try { // Unterbrechung
runOutSlot.writeFrame(runOutFr); // throws InterruptedException
writeDone = true;
runFrameDone(runOutSlot, runOutFr);
runOutStream.freeFrame(runOutFr);
} catch (InterruptedException e) { /* ignored */} // mainLoop wird eh gleich verlassen
runCheckPause();
}
inBufOff = (inBufOff + chunkLength) % winSize;
} // end of main loop
runFile.close();
runOutStream.closeWriter();
} catch (IOException e) {
if (runFile != null) {
runFile.cleanUp();
}
runQuit(e);
return;
} catch (SlotAlreadyConnectedException e) {
if (runFile != null) {
runFile.cleanUp();
}
runQuit(e);
return;
}
runQuit(null);
}
// -------- GUI methods --------
public PropertyGUI createGUI(int type) {
PropertyGUI gui;
AudioFile inputFile = null;
AudioFileDescr inStream;
double fileLength; // millisec
String reference = "";
String[] winNames = Filter.getWindowNames();
StringBuffer winChoise = new StringBuffer();
if (type != GUI_PREFS) return null;
// try to get Filelength as reference
if ((pr.text[PR_FILENAME] != null) && (pr.text[PR_FILENAME].length() != 0)) {
try { // catching IOExceptions
inputFile = AudioFile.openAsRead(new File(pr.text[PR_FILENAME]));
inStream = inputFile.getDescr();
fileLength = AudioFileDescr.samplesToMillis(inStream, inStream.length);
inputFile.close();
reference = ",re" + fileLength + "|" + Param.ABS_MS;
} catch (IOException e) {
if (inputFile != null) inputFile.cleanUp();
}
}
for (int i = 0; i < winNames.length; i++) {
winChoise.append(",it");
winChoise.append(winNames[i]);
}
gui = new PropertyGUI(
"gl"+GroupLabel.NAME_GENERAL+"\n" +
"lbFilename;io"+PathField.TYPE_INPUTFILE+"|Select input file,pr"+PRN_FILENAME+"\n" +
"lbTransform;ch,ac0|3|di|4|di|5|di|6|di,ac1|3|en|4|en|5|en|6|en,pr"+PRN_TYPE+"," +
"itDiscrete Fourier," +
"itChirp Z," +
"itNone\n" +
"lbChunk(FFT) length;ch,pr"+PRN_FFTLENGTH+"," +
"it131072,it 65536,it 32768,it 16384,it 8192,it 4096,it 2048,it 1024,it 512,it 256,it 128,it 64,it 32\n"+
"lbOversampling;ch,pr"+PRN_OVERSMP+"," +
"it1x (none)," +
"it2x," +
"it4x," +
"it8x\n" +
"lbWindow;ch,pr"+PRN_WINDOW+winChoise.toString()+"\n"+
"lbWindow step;ch,pr"+PRN_OVERLAP+"," +
"it1/1," +
"it1/2," +
"it1/4," +
"it1/8," +
"it1/16\n" +
"cbRotate origin,pr"+PRN_ROTATE+"\n"+
"glChirp transform specs\n" +
"lbLow freq;pf"+Constants.absHzSpace+",id3,pr"+PRN_LOFREQ+"\n" +
"lbHigh freq;pf"+Constants.absHzSpace+",id4,pr"+PRN_HIFREQ+"\n" +
"lbLow radius;pf"+Constants.decibelAmpSpace+",id5,pr"+PRN_LORADIUS +"\n" +
"lbHigh radius;pf"+Constants.decibelAmpSpace+",id6,pr"+PRN_HIRADIUS +"\n" +
"glTruncation\n" +
"cbTime offset,actrue|1|en,acfalse|1|di,pr"+PRN_ADJUSTSTART+";" +
"pf"+Constants.absMsSpace+"|"+Constants.absBeatsSpace+
"|"+Constants.ratioTimeSpace + reference +",id1,pr"+PRN_STARTSHIFT+"\n" +
"cbLength,actrue|2|en,acfalse|2|di,pr"+PRN_ADJUSTLENGTH+";" +
"pf"+Constants.absMsSpace+"|"+Constants.absBeatsSpace+
"|"+Constants.ratioTimeSpace + reference +",id2,pr"+PRN_LENGTH );
return gui;
}
}