/*
* BinaryOpDlg.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.gui;
import de.sciss.fscape.io.FloatFile;
import de.sciss.fscape.io.GenericFile;
import de.sciss.fscape.prop.Presets;
import de.sciss.fscape.prop.PropertyArray;
import de.sciss.fscape.session.ModulePanel;
import de.sciss.fscape.util.Constants;
import de.sciss.fscape.util.Param;
import de.sciss.fscape.util.ParamSpace;
import de.sciss.fscape.util.Util;
import de.sciss.io.AudioFile;
import de.sciss.io.AudioFileDescr;
import de.sciss.io.IOUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
/**
* Processing module for algebraic
* combination of two sound files on
* a sample-by-sample basis.
*/
public class BinaryOpDlg
extends ModulePanel {
// -------- private variables --------
// Properties (defaults)
private static final int PR_REINPUTFILE1 = 0; // pr.text
// private static final int PR_REINPUTFILE2 = 1;
private static final int PR_IMINPUTFILE1 = 2;
private static final int PR_IMINPUTFILE2 = 3;
private static final int PR_REOUTPUTFILE = 4;
private static final int PR_IMOUTPUTFILE = 5;
private static final int PR_OUTPUTTYPE = 0; // pr.intg
private static final int PR_OUTPUTRES = 1;
private static final int PR_OPERATOR = 2;
private static final int PR_GAINTYPE = 3;
// private static final int PR_INGAINTYPE1 = 4;
// private static final int PR_INGAINTYPE2 = 5;
private static final int PR_GAIN = 0; // pr.para
private static final int PR_INPUTGAIN1 = 1;
private static final int PR_INPUTGAIN2 = 2;
private static final int PR_OFFSET1 = 3;
private static final int PR_OFFSET2 = 4;
private static final int PR_LENGTH1 = 5;
private static final int PR_LENGTH2 = 6;
private static final int PR_DRYMIX = 7;
private static final int PR_WETMIX = 8;
private static final int PR_HASIMINPUT1 = 0; // pr.bool
private static final int PR_HASIMINPUT2 = 1;
private static final int PR_HASIMOUTPUT = 2;
private static final int PR_RECTIFY1 = 3;
// private static final int PR_RECTIFY2 = 4;
private static final int PR_INVERT1 = 5;
// private static final int PR_INVERT2 = 6;
private static final int PR_DRYINVERT = 7;
private static final int OP_ADD = 0;
private static final int OP_MULT = 1;
private static final int OP_DIV = 2;
private static final int OP_MOD = 3;
private static final int OP_POW = 4;
private static final int OP_AND = 5;
private static final int OP_OR = 6;
private static final int OP_XOR = 7;
private static final int OP_SIGN = 8;
private static final int OP_AMP = 9;
private static final int OP_MIN1 = 10; // a < b ? a : b
private static final int OP_MAX1 = 11;
private static final int OP_MIN2 = 12; // |a| < |b| ? a : b
private static final int OP_MAX2 = 13;
private static final int OP_MIN3 = 14; // min2( Re a, Re b ) + i min2( Im a, Im b )
private static final int OP_MAX3 = 15;
private static final int OP_MIN4 = 16; // min( a, b proj. auf a )
private static final int OP_MAX4 = 17;
private static final int OP_GATE = 18;
private static final int OP_ARCTAN = 19;
private static final String OPNAMES[] = { "Add", "Multiply", "Divide", "Modulo", "Power", "AND", "OR", "XOR",
"Apply sign (phase)", "Apply amp", "Min(a,b)", "Max(a,b)", "Min(|a|,|b|)",
"Max(|a|,|b|)", "Min(Re)+iMin(Im)", "Max(Re)+iMax(Im)", "Min(a,b->a)",
"Max(a,b->a)", "Gate", "ArcTangens" };
private static final String PRN_REINPUTFILE1 = "ReInFile1";
private static final String PRN_REINPUTFILE2 = "ReInFile2";
private static final String PRN_IMINPUTFILE1 = "ImInFile1";
private static final String PRN_IMINPUTFILE2 = "ImInFile2";
private static final String PRN_REOUTPUTFILE = "ReOutFile";
private static final String PRN_IMOUTPUTFILE = "ImOutFile";
private static final String PRN_OUTPUTTYPE = "OutputType";
private static final String PRN_OUTPUTRES = "OutputReso";
private static final String PRN_OPERATOR = "Operator";
private static final String PRN_INGAINTYPE1 = "InGainType1";
private static final String PRN_INGAINTYPE2 = "InGainType2";
private static final String PRN_INPUTGAIN1 = "InGain1";
private static final String PRN_INPUTGAIN2 = "InGain2";
private static final String PRN_OFFSET1 = "Offset1";
private static final String PRN_OFFSET2 = "Offset2";
private static final String PRN_LENGTH1 = "Length1";
private static final String PRN_LENGTH2 = "Length2";
private static final String PRN_DRYMIX = "DryMix";
private static final String PRN_WETMIX = "WetMix";
private static final String PRN_HASIMINPUT1 = "HasImInput1";
private static final String PRN_HASIMINPUT2 = "HasImInput2";
private static final String PRN_HASIMOUTPUT = "HasImOutput";
private static final String PRN_RECTIFY1 = "Rectify1";
private static final String PRN_RECTIFY2 = "Rectify2";
private static final String PRN_INVERT1 = "Invert1";
private static final String PRN_INVERT2 = "Invert2";
private static final String PRN_DRYINVERT = "DryInvert";
private static final String prText[] = { "", "", "", "", "", "" };
private static final String prTextName[] = { PRN_REINPUTFILE1, PRN_REINPUTFILE2, PRN_IMINPUTFILE1,
PRN_IMINPUTFILE2, PRN_REOUTPUTFILE, PRN_IMOUTPUTFILE };
private static final int prIntg[] = { 0, 0, OP_ADD, GAIN_UNITY, GAIN_ABSOLUTE, GAIN_ABSOLUTE };
private static final String prIntgName[] = { PRN_OUTPUTTYPE, PRN_OUTPUTRES, PRN_OPERATOR, PRN_GAINTYPE,
PRN_INGAINTYPE1, PRN_INGAINTYPE2 };
private static final Param prPara[] = { null, null, null, null, null, null, null, null, null };
private static final String prParaName[] = { PRN_GAIN, PRN_INPUTGAIN1, PRN_INPUTGAIN2, PRN_OFFSET1,
PRN_OFFSET2, PRN_LENGTH1, PRN_LENGTH2, PRN_DRYMIX, PRN_WETMIX };
private static final boolean prBool[] = { false, false, false, false, false, false, false, false };
private static final String prBoolName[] = { PRN_HASIMINPUT1, PRN_HASIMINPUT2, PRN_HASIMOUTPUT,
PRN_RECTIFY1, PRN_RECTIFY2, PRN_INVERT1, PRN_INVERT2, PRN_DRYINVERT };
private static final int GG_REINPUTFILE1 = GG_OFF_PATHFIELD + PR_REINPUTFILE1;
// private static final int GG_REINPUTFILE2 = GG_OFF_PATHFIELD + PR_REINPUTFILE2;
private static final int GG_IMINPUTFILE1 = GG_OFF_PATHFIELD + PR_IMINPUTFILE1;
private static final int GG_IMINPUTFILE2 = GG_OFF_PATHFIELD + PR_IMINPUTFILE2;
private static final int GG_REOUTPUTFILE = GG_OFF_PATHFIELD + PR_REOUTPUTFILE;
private static final int GG_IMOUTPUTFILE = GG_OFF_PATHFIELD + PR_IMOUTPUTFILE;
private static final int GG_OUTPUTTYPE = GG_OFF_CHOICE + PR_OUTPUTTYPE;
private static final int GG_OUTPUTRES = GG_OFF_CHOICE + PR_OUTPUTRES;
private static final int GG_OPERATOR = GG_OFF_CHOICE + PR_OPERATOR;
private static final int GG_GAINTYPE = GG_OFF_CHOICE + PR_GAINTYPE;
// private static final int GG_INGAINTYPE1 = GG_OFF_CHOICE + PR_INGAINTYPE1;
// private static final int GG_INGAINTYPE2 = GG_OFF_CHOICE + PR_INGAINTYPE2;
private static final int GG_GAIN = GG_OFF_PARAMFIELD + PR_GAIN;
private static final int GG_INPUTGAIN1 = GG_OFF_PARAMFIELD + PR_INPUTGAIN1;
// private static final int GG_INPUTGAIN2 = GG_OFF_PARAMFIELD + PR_INPUTGAIN2;
private static final int GG_OFFSET1 = GG_OFF_PARAMFIELD + PR_OFFSET1;
// private static final int GG_OFFSET2 = GG_OFF_PARAMFIELD + PR_OFFSET2;
private static final int GG_LENGTH1 = GG_OFF_PARAMFIELD + PR_LENGTH1;
// private static final int GG_LENGTH2 = GG_OFF_PARAMFIELD + PR_LENGTH2;
private static final int GG_DRYMIX = GG_OFF_PARAMFIELD + PR_DRYMIX;
private static final int GG_WETMIX = GG_OFF_PARAMFIELD + PR_WETMIX;
private static final int GG_HASIMINPUT1 = GG_OFF_CHECKBOX + PR_HASIMINPUT1;
private static final int GG_HASIMINPUT2 = GG_OFF_CHECKBOX + PR_HASIMINPUT2;
private static final int GG_HASIMOUTPUT = GG_OFF_CHECKBOX + PR_HASIMOUTPUT;
private static final int GG_RECTIFY1 = GG_OFF_CHECKBOX + PR_RECTIFY1;
// private static final int GG_RECTIFY2 = GG_OFF_CHECKBOX + PR_RECTIFY2;
private static final int GG_INVERT1 = GG_OFF_CHECKBOX + PR_INVERT1;
// private static final int GG_INVERT2 = GG_OFF_CHECKBOX + PR_INVERT2;
private static final int GG_DRYINVERT = GG_OFF_CHECKBOX + PR_DRYINVERT;
private static PropertyArray static_pr = null;
private static Presets static_presets = null;
// -------- public methods --------
/**
* !! setVisible() bleibt dem Aufrufer ueberlassen
*/
public BinaryOpDlg()
{
super( "Binary Operator" );
init2();
}
protected void buildGUI()
{
// einmalig PropertyArray initialisieren
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.para = prPara;
static_pr.para[ PR_INPUTGAIN1 ] = new Param( 0.0, Param.DECIBEL_AMP );
static_pr.para[ PR_INPUTGAIN2 ] = new Param( 0.0, Param.DECIBEL_AMP );
static_pr.para[ PR_OFFSET1 ] = new Param( 0.0, Param.ABS_MS );
static_pr.para[ PR_OFFSET2 ] = new Param( 0.0, Param.ABS_MS );
static_pr.para[ PR_LENGTH1 ] = new Param( 100.0, Param.FACTOR_TIME );
static_pr.para[ PR_LENGTH2 ] = new Param( 100.0, Param.FACTOR_TIME );
static_pr.para[ PR_DRYMIX ] = new Param( 0.0, Param.FACTOR_AMP );
static_pr.para[ PR_WETMIX ] = new Param( 100.0, Param.FACTOR_AMP );
static_pr.paraName = prParaName;
static_pr.bool = prBool;
static_pr.boolName = prBoolName;
// static_pr.superPr = DocumentFrame.static_pr;
fillDefaultAudioDescr( static_pr.intg, PR_OUTPUTTYPE, PR_OUTPUTRES );
fillDefaultGain( static_pr.para, PR_GAIN );
static_presets = new Presets( getClass(), static_pr.toProperties( true ));
}
presets = static_presets;
pr = (PropertyArray) static_pr.clone();
// -------- build GUI --------
GridBagConstraints con;
PathField ggImInputFile, ggReInputFile, ggReOutputFile, ggImOutputFile;
ParamField ggInputGain, ggOffset, ggLength, ggDryMix, ggWetMix;
JComboBox ggOperator;
JCheckBox ggHasImInput, ggHasImOutput, ggRectify, ggInvert, ggDryInvert;
PathField[] ggParent1, ggParent2;
Component[] ggGain;
ParamSpace[] spcOffset, spcLength;
int i, j;
gui = new GUISupport();
con = gui.getGridBagConstraints();
con.insets = new Insets( 1, 2, 1, 2 );
ggParent1 = new PathField[ 2 ];
ItemListener il = new ItemListener() {
public void itemStateChanged( ItemEvent e )
{
int ID = gui.getItemID( e );
switch( ID ) {
case GG_HASIMINPUT1:
case GG_HASIMINPUT2:
case GG_HASIMOUTPUT:
pr.bool[ ID - GG_OFF_CHECKBOX ] = ((JCheckBox) e.getSource()).isSelected();
reflectPropertyChanges();
break;
}
}
};
// -------- Input-Gadgets --------
spcOffset = new ParamSpace[ 3 ];
spcOffset[0] = new ParamSpace( -36000000.0, 36000000.0, 0.1, Param.ABS_MS ); // allow negative offset
spcOffset[1] = new ParamSpace( -240000.0, 240000.0, 0.001, Param.ABS_BEATS );
spcOffset[2] = new ParamSpace( -100.0, 100.0, 0.01, Param.FACTOR_TIME );
// spcOffset[0] = Constants.spaces[ Constants.offsetMsSpace ];
// spcOffset[1] = Constants.spaces[ Constants.offsetBeatsSpace ];
// spcOffset[2] = Constants.spaces[ Constants.offsetTimeSpace ];
spcLength = new ParamSpace[ 4 ];
spcLength[0] = Constants.spaces[ Constants.absMsSpace ];
spcLength[1] = Constants.spaces[ Constants.absBeatsSpace ];
spcLength[2] = Constants.spaces[ Constants.offsetTimeSpace ];
spcLength[3] = Constants.spaces[ Constants.factorTimeSpace ];
for( i = 0; i < 2; i++ ) {
con.fill = GridBagConstraints.BOTH;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addLabel( new GroupLabel( "Operand " + (i+1), GroupLabel.ORIENT_HORIZONTAL,
GroupLabel.BRACE_NONE ));
con.fill = GridBagConstraints.HORIZONTAL;
ggReInputFile = new PathField( PathField.TYPE_INPUTFILE + PathField.TYPE_FORMATFIELD,
"Select real part of input" );
ggReInputFile.handleTypes( GenericFile.TYPES_SOUND );
con.gridwidth = 1;
con.weightx = 0.1;
gui.addLabel( new JLabel( "Input [Real]", SwingConstants.RIGHT ));
con.gridwidth = 2;
con.weightx = 3.0;
gui.addPathField( ggReInputFile, GG_REINPUTFILE1 + i, null );
ggOffset = new ParamField( spcOffset );
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Offset", SwingConstants.RIGHT ));
con.weightx = 0.4;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addParamField( ggOffset, GG_OFFSET1 + i, null );
ggImInputFile = new PathField( PathField.TYPE_INPUTFILE + PathField.TYPE_FORMATFIELD,
"Select imaginary part of input" );
ggImInputFile.handleTypes( GenericFile.TYPES_SOUND );
ggHasImInput = new JCheckBox( "Input [Imaginary]" );
con.gridwidth = 1;
con.weightx = 0.1;
j = con.anchor;
con.anchor = GridBagConstraints.EAST;
gui.addCheckbox( ggHasImInput, GG_HASIMINPUT1 + i, il );
con.anchor = j;
con.weightx = 3.0;
con.gridwidth = 2;
gui.addPathField( ggImInputFile, GG_IMINPUTFILE1 + i, null );
ggLength = new ParamField( spcLength );
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Length", SwingConstants.RIGHT ));
con.weightx = 0.4;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addParamField( ggLength, GG_LENGTH1 + i, null );
ggParent1[ i ] = ggReInputFile;
ggParent2 = new PathField[ 1 ];
ggParent2[ 0 ] = ggReInputFile;
ggImInputFile.deriveFrom( ggParent2, "$D0$F0i$X0" );
ggInputGain = new ParamField( Constants.spaces[ Constants.decibelAmpSpace ]);
con.gridwidth = 1;
con.weightx = 0.1;
gui.addLabel( new JLabel( "Drive", SwingConstants.RIGHT ));
con.weightx = 0.4;
gui.addParamField( ggInputGain, GG_INPUTGAIN1 + i, null );
con.weightx = 0.1;
con.gridwidth = 2;
gui.addLabel( new JLabel( "" ));
ggRectify = new JCheckBox( "Rectify" );
con.gridwidth = 1;
con.weightx = 0.4;
gui.addCheckbox( ggRectify, GG_RECTIFY1 + i, il );
ggInvert = new JCheckBox( "Invert" );
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addCheckbox( ggInvert, GG_INVERT1 + i, il );
}
// -------- Output-Gadgets --------
gui.addLabel( new GroupLabel( "Output", GroupLabel.ORIENT_HORIZONTAL,
GroupLabel.BRACE_NONE ));
ggReOutputFile = new PathField( PathField.TYPE_OUTPUTFILE + PathField.TYPE_FORMATFIELD +
PathField.TYPE_RESFIELD, "Select output for real part" );
ggReOutputFile.handleTypes( GenericFile.TYPES_SOUND );
con.gridwidth = 1;
con.weightx = 0.1;
gui.addLabel( new JLabel( "File [Real]", SwingConstants.RIGHT ));
con.gridwidth = GridBagConstraints.REMAINDER;
con.weightx = 0.9;
gui.addPathField( ggReOutputFile, GG_REOUTPUTFILE, null );
gui.registerGadget( ggReOutputFile.getTypeGadget(), GG_OUTPUTTYPE );
gui.registerGadget( ggReOutputFile.getResGadget(), GG_OUTPUTRES );
ggImOutputFile = new PathField( PathField.TYPE_OUTPUTFILE, "Select output for imaginary part" );
// ggImOutputFile.handleTypes( GenericFile.TYPES_SOUND );
ggHasImOutput = new JCheckBox( "File [Imaginary]" );
con.gridwidth = 1;
con.weightx = 0.1;
j = con.anchor;
con.anchor = GridBagConstraints.EAST;
gui.addCheckbox( ggHasImOutput, GG_HASIMOUTPUT, il );
con.anchor = j;
con.gridwidth = GridBagConstraints.REMAINDER;
con.weightx = 0.9;
gui.addPathField( ggImOutputFile, GG_IMOUTPUTFILE, null );
ggParent2 = new PathField[ 1 ];
ggParent2[ 0 ] = ggReOutputFile;
ggReOutputFile.deriveFrom( ggParent1, "$D0$B0Op$B1$E" );
ggImOutputFile.deriveFrom( ggParent2, "$D0$F0i$X0" );
ggGain = createGadgets( GGTYPE_GAIN );
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Gain", SwingConstants.RIGHT ));
con.weightx = 0.4;
gui.addParamField( (ParamField) ggGain[ 0 ], GG_GAIN, null );
con.weightx = 0.5;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addChoice( (JComboBox) ggGain[ 1 ], GG_GAINTYPE, il );
// -------- Settings --------
gui.addLabel( new GroupLabel( "Operation", GroupLabel.ORIENT_HORIZONTAL,
GroupLabel.BRACE_NONE ));
ggOperator = new JComboBox();
for( i = 0; i < OPNAMES.length; i++ ) {
ggOperator.addItem( OPNAMES[ i ]);
}
con.gridwidth = 1;
con.weightx = 0.1;
gui.addLabel( new JLabel( "Operator", SwingConstants.RIGHT ));
con.weightx = 0.4;
gui.addChoice( ggOperator, GG_OPERATOR, il );
con.weightx = 0.1;
gui.addLabel( new JLabel( "" ));
ggDryMix = new ParamField( Constants.spaces[ Constants.ratioAmpSpace ]);
gui.addLabel( new JLabel( "Dry mix", SwingConstants.RIGHT ));
con.weightx = 0.4;
gui.addParamField( ggDryMix, GG_DRYMIX, null );
ggDryInvert = new JCheckBox( "Invert" );
con.weightx = 0.1;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addCheckbox( ggDryInvert, GG_DRYINVERT, il );
con.gridwidth = 3;
gui.addLabel( new JLabel( "" ));
ggWetMix = new ParamField( Constants.spaces[ Constants.ratioAmpSpace ]);
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Wet mix", SwingConstants.RIGHT ));
con.weightx = 0.4;
gui.addParamField( ggWetMix, GG_WETMIX, null );
con.weightx = 0.1;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addLabel( new JLabel( "" ));
initGUI( this, FLAGS_PRESETS | FLAGS_PROGBAR, gui );
}
/**
* Transfer values from prop-array to GUI
*/
public void fillGUI()
{
super.fillGUI();
super.fillGUI( gui );
}
/**
* Transfer values from GUI to prop-array
*/
public void fillPropertyArray()
{
super.fillPropertyArray();
super.fillPropertyArray( gui );
}
// -------- Processor Interface --------
/**
* Translation durchfuehren
*/
public void process()
{
int i, j, k;
int ch, op, len;
float f1, f2;
double d1, d2, d3, d4;
long progOff, progLen;
// io
AudioFile[] reInF = new AudioFile[ 2 ];
AudioFile[] imInF = new AudioFile[ 2 ];
AudioFile reOutF = null;
AudioFile imOutF = null;
AudioFileDescr[] reInStream = new AudioFileDescr[ 2 ];
AudioFileDescr[] imInStream = new AudioFileDescr[ 2 ];
AudioFileDescr reOutStream = null;
AudioFileDescr imOutStream = null;
FloatFile reFloatF[] = null;
FloatFile imFloatF[] = null;
File reTempFile[] = null;
File imTempFile[] = null;
int outChanNum;
float[][][] reInBuf = new float[2][][]; // [op][ch][i]
float[][][] imInBuf = new float[2][][]; // [op][ch][i]
float[][] reOutBuf = null; // [ch][i]
float[][] imOutBuf = null; // [ch][i]
float[] convBuf1, convBuf2, convBuf3, convBuf4;
boolean complex;
PathField ggOutput;
// Synthesize
Param ampRef = new Param( 1.0, Param.ABS_AMP ); // transform-Referenz
float gain; // gain abs amp
float dryGain, wetGain;
float[] inGain = new float[ 2 ];
float maxAmp = 0.0f;
Param peakGain;
int[] inLength = new int[ 2 ];
int[] pre = new int[ 2 ];
int[] post = new int[ 2 ];
int[] length = new int[ 2 ];
int framesWritten, outLength;
topLevel: try {
for( op = 0; op < 2; op++ ) {
reInF[op] = null;
imInF[op] = null;
}
complex = pr.bool[ PR_HASIMINPUT1 ] || pr.bool[ PR_HASIMINPUT2 ] || pr.bool[ PR_HASIMOUTPUT ];
// ---- open input ----
for( op = 0; op < 2; op++ ) {
reInF[op] = AudioFile.openAsRead( new File( pr.text[ PR_REINPUTFILE1 + op ]));
reInStream[op] = reInF[op].getDescr();
inLength[op] = (int) reInStream[op].length;
reInBuf[op] = new float[ reInStream[op].channels ][ 8192 ];
imInBuf[op] = new float[ reInStream[op].channels ][ 8192 ];
if( pr.bool[ PR_HASIMINPUT1 + op ]) {
imInF[op] = AudioFile.openAsRead( new File( pr.text[ PR_IMINPUTFILE1 + op ]));
imInStream[op] = imInF[op].getDescr();
if( imInStream[op].channels != reInStream[op].channels ) throw new IOException( ERR_COMPLEX );
inLength[op] = (int) Math.min( inLength[op], imInStream[op].length );
}
final Param lenRef = new Param(
AudioFileDescr.samplesToMillis( reInStream[op], inLength[op] ), Param.ABS_MS );
j = (int) (AudioFileDescr.millisToSamples( reInStream[op],
(Param.transform( pr.para[ PR_OFFSET1 + op], Param.ABS_MS,
lenRef, null )).value) + 0.5);
length[op] = (int) (AudioFileDescr.millisToSamples( reInStream[op],
(Param.transform( pr.para[ PR_LENGTH1 + op], Param.ABS_MS,
lenRef,
null )).value) + 0.5);
if( j >= 0 ) {
i = Math.min( j, inLength[op] );
reInF[op].seekFrame( i );
if( pr.bool[ PR_HASIMINPUT1 + op ]) {
imInF[op].seekFrame( i );
}
inLength[op]-= i;
pre[op] = 0;
} else {
i = Math.min( -j, length[op] );
pre[op] = i;
}
inLength[op] = Math.min( inLength[op], length[op] - pre[op] );
post[op] = length[op] - pre[op] - inLength[op];
// .... check running ....
if( !threadRunning ) break topLevel;
}
// zero pad operands so that their op-lengths are equal
i = length[0] - length[1];
if( i > 0 ) {
post[1] += i;
length[1] += i;
} else if( i < 0 ) {
post[0] -= i;
length[0] -= i;
}
// for( op = 0; op < 2; op++ ) {
// System.out.println( op +": pre "+pre[op]+" / len "+inLength[op]+" / post "+post[op] );
// }
// System.out.println( "tot "+length[0]);
outLength = length[0];
outChanNum = Math.max( reInStream[0].channels, reInStream[1].channels );
// ---- open output ----
ggOutput = (PathField) gui.getItemObj( GG_REOUTPUTFILE );
if( ggOutput == null ) throw new IOException( ERR_MISSINGPROP );
reOutStream = new AudioFileDescr( reInStream[0] );
ggOutput.fillStream( reOutStream );
reOutStream.channels = outChanNum;
// well, more sophisticated code would
// move and truncate the markers...
if( (pre[0] == 0) /* && (post[0] == 0) */ ) {
reInF[0].readMarkers();
reOutStream.setProperty( AudioFileDescr.KEY_MARKERS,
reInStream[0].getProperty( AudioFileDescr.KEY_MARKERS ));
}
reOutF = AudioFile.openAsWrite( reOutStream );
reOutBuf = new float[ outChanNum ][ 8192 ];
imOutBuf = new float[ outChanNum ][ 8192 ];
if( pr.bool[ PR_HASIMOUTPUT ]) {
imOutStream = new AudioFileDescr( reInStream[0] );
ggOutput.fillStream( imOutStream );
imOutStream.channels = outChanNum;
imOutStream.file = new File( pr.text[ PR_IMOUTPUTFILE ]);
imOutF = AudioFile.openAsWrite( imOutStream );
}
// .... check running ....
if( !threadRunning ) break topLevel;
// ---- Further inits ----
progOff = 0; // read 2x, transform, write
progLen = (long) outLength << 2;
wetGain = (float) (Param.transform( pr.para[ PR_WETMIX ], Param.ABS_AMP, ampRef, null )).value;
dryGain = (float) (Param.transform( pr.para[ PR_DRYMIX ], Param.ABS_AMP, ampRef, null )).value;
if( pr.bool[ PR_DRYINVERT ]) {
dryGain = -dryGain;
}
for( op = 0; op < 2; op++ ) {
inGain[op] = (float) (Param.transform( pr.para[ PR_INPUTGAIN1 + op ], Param.ABS_AMP, ampRef, null )).value;
if( pr.bool[ PR_INVERT1 + op ]) {
inGain[op] = -inGain[op];
}
}
// normalization requires temp files
if( pr.intg[ PR_GAINTYPE ] == GAIN_UNITY ) {
reTempFile = new File[ outChanNum ];
reFloatF = new FloatFile[ outChanNum ];
for( ch = 0; ch < outChanNum; ch++ ) { // first zero them because an exception might be thrown
reTempFile[ ch ] = null;
reFloatF[ ch ] = null;
}
for( ch = 0; ch < outChanNum; ch++ ) {
reTempFile[ ch ] = IOUtil.createTempFile();
reFloatF[ ch ] = new FloatFile( reTempFile[ ch ], GenericFile.MODE_OUTPUT );
}
if( pr.bool[ PR_HASIMOUTPUT ]) {
imTempFile = new File[ outChanNum ];
imFloatF = new FloatFile[ outChanNum ];
for( ch = 0; ch < outChanNum; ch++ ) { // first zero them because an exception might be thrown
imTempFile[ ch ] = null;
imFloatF[ ch ] = null;
}
for( ch = 0; ch < outChanNum; ch++ ) {
imTempFile[ ch ] = IOUtil.createTempFile();
imFloatF[ ch ] = new FloatFile( imTempFile[ ch ], GenericFile.MODE_OUTPUT );
}
}
progLen += (long) outLength;
} else {
gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP, ampRef, null )).value;
wetGain *= gain;
dryGain *= gain;
}
// .... check running ....
if( !threadRunning ) break topLevel;
// ----==================== the real stuff ====================----
// framesRead = 0;
framesWritten = 0;
while( threadRunning && (framesWritten < outLength) ) {
// ---- choose chunk len ----
len = Math.min( 8192, outLength - framesWritten );
for( op = 0; op < 2; op++ ) {
if( pre[op] > 0 ) {
len = Math.min( len, pre[op] );
} else if( inLength[op] > 0 ) {
len = Math.min( len, inLength[op] );
} else {
len = Math.min( len, post[op] );
}
}
// ---- read input chunks ----
for( op = 0; op < 2; op++ ) {
if( pre[op] > 0 ) {
Util.clear( reInBuf[op] );
if( complex ) {
Util.clear( imInBuf[op] );
}
pre[op] -= len;
} else if( inLength[op] > 0 ) {
reInF[op].readFrames( reInBuf[op], 0, len );
if( pr.bool[ PR_HASIMINPUT1 + op ]) {
imInF[op].readFrames( imInBuf[op], 0, len );
} else if( complex ) {
Util.clear( imInBuf[op] );
}
inLength[op] -= len;
} else {
Util.clear( reInBuf[op] );
if( complex ) {
Util.clear( imInBuf[op] );
}
post[op] -= len;
}
progOff += len;
// .... progress ....
setProgression( (float) progOff / (float) progLen );
// .... check running ....
if( !threadRunning ) break topLevel;
}
// ---- save dry signal ----
for( ch = 0; ch < outChanNum; ch++ ) {
convBuf1 = reInBuf[ 0 ][ ch % reInStream[0].channels ];
convBuf2 = reOutBuf[ ch ];
for( i = 0; i < len; i++ ) {
convBuf2[ i ] = convBuf1[ i ] * dryGain;
}
if( complex ) {
convBuf1 = imInBuf[ 0 ][ ch % reInStream[0].channels ];
convBuf2 = imOutBuf[ ch ];
for( i = 0; i < len; i++ ) {
convBuf2[ i ] = convBuf1[ i ] * dryGain;
}
}
}
// ---- rectify + apply input gain ----
for( op = 0; op < 2; op++ ) {
for( ch = 0; ch < reInStream[op].channels; ch++ ) {
convBuf1 = reInBuf[op][ ch ];
convBuf2 = imInBuf[op][ ch ];
// ---- rectify ----
if( pr.bool[ PR_RECTIFY1 + op ]) {
if( complex ) {
for( i = 0; i < len; i++ ) {
d1 = convBuf1[ i ];
d2 = convBuf2[ i ];
convBuf1[ i ] = (float) Math.sqrt( d1*d1 + d2*d2 );
convBuf2[ i ] = 0.0f;
}
} else {
for( i = 0; i < len; i++ ) {
convBuf1[ i ] = Math.abs( convBuf1[ i ]);
}
}
}
// ---- apply input gain ----
Util.mult( convBuf1, 0, len, inGain[op] );
if( complex ) {
Util.mult( convBuf2, 0, len, inGain[op] );
}
}
}
// ---- heart of the dragon ----
for( ch = 0; ch < outChanNum; ch++ ) {
convBuf1 = reInBuf[0][ ch % reInStream[0].channels ];
convBuf2 = reInBuf[1][ ch % reInStream[1].channels ];
convBuf3 = imInBuf[0][ ch % reInStream[0].channels ];
convBuf4 = imInBuf[1][ ch % reInStream[1].channels ];
switch( pr.intg[ PR_OPERATOR ]) {
case OP_ADD: // ================ Add ================
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (convBuf1[ i ] + convBuf2[ i ]);
}
if( complex ) {
for( i = 0; i < len; i++ ) {
imOutBuf[ ch ][ i ] += wetGain * (convBuf3[ i ] + convBuf4[ i ]);
}
}
break;
case OP_MULT: // ================ Multiply ================
if( complex ) {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (convBuf1[i]*convBuf2[i] - convBuf3[i]*convBuf4[i]);
imOutBuf[ ch ][ i ] += wetGain * (convBuf1[i]*convBuf4[i] + convBuf2[i]*convBuf3[i]);
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (convBuf1[ i ] * convBuf2[ i ]);
}
}
break;
case OP_DIV: // ================ Divide ================
if( complex ) {
for( i = 0; i < len; i++ ) {
if( Math.abs( convBuf2[i] ) >= Math.abs( convBuf4[i] )) {
f1 = convBuf4[i] / convBuf2[i];
f2 = convBuf2[i] + f1 * convBuf4[i];
reOutBuf[ ch ][ i ] += wetGain * (convBuf1[i] + f1 * convBuf3[i]) / f2;
imOutBuf[ ch ][ i ] += wetGain * (convBuf3[i] - f1 * convBuf1[i]) / f2;
} else {
f1 = convBuf2[i] / convBuf4[i];
f2 = convBuf4[i] + f1 * convBuf2[i];
reOutBuf[ ch ][ i ] += wetGain * (convBuf1[i] * f1 + convBuf3[i]) / f2;
imOutBuf[ ch ][ i ] += wetGain * (convBuf3[i] * f1 - convBuf1[i]) / f2;
}
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (convBuf1[ i ] / convBuf2[ i ]);
}
}
break;
case OP_MOD: // ================ Mod ================
if( complex ) {
throw new IOException( "Op. not yet implemented!" ); // XXX
} else {
for( i = 0; i < len; i++ ) {
if( convBuf2[ i ] != 0.0f ) {
reOutBuf[ ch ][ i ] += wetGain * (convBuf1[ i ] % convBuf2[ i ]);
}
}
}
case OP_POW: // ================ Power ================
if( complex ) {
for( i = 0; i < len; i++ ) {
d1 = Math.sqrt( convBuf1[i]*convBuf1[i] + convBuf3[i]*convBuf3[i] );
if( d1 > 0.0 ) {
// pow( r1, re2 ) * exp( -im2 * phi1 ) * exp( i( re2*phi1 + im2*ln r1 ))
d2 = Math.atan2( convBuf3[i], convBuf1[i] );
d3 = wetGain * Math.pow( d1, convBuf2[i] ) * Math.exp( -convBuf4[i] * d2 ); // new radius
d4 = convBuf2[i] * d2 + convBuf4[i] * Math.log( d1 ); // new angle
reOutBuf[ ch ][ i ] += (float) (d3 * Math.cos( d4 ));
imOutBuf[ ch ][ i ] += (float) (d3 * Math.sin( d4 ));
} else if( (convBuf2[i] == 0.0f) && (convBuf4[i] == 0.0f) ) {
reOutBuf[ ch ][ i ] += wetGain; // * pow( e, 0 ) = 1
} // else nothing : pow( 0, x ) = 0
}
} else {
for( i = 0; i < len; i++ ) {
f1 = convBuf1[i];
if( f1 != 0.0f ) {
reOutBuf[ ch ][ i ] += (float) (wetGain * Math.pow( f1, convBuf2[i] ));
} else if( convBuf2[i] == 0.0f ) {
reOutBuf[ ch ][ i ] += wetGain;
} // pow( 0, x ), x < 0 not defined ... ? interpolate?
}
}
break;
case OP_AND: // ================ AND ================
for( i = 0; i < len; i++ ) {
j = (int) convBuf1[i] & (int) convBuf2[i];
k = ((int) (((double) convBuf1[i] % 1.0) * 2147483647.0)) &
((int) (((double) convBuf2[i] % 1.0) * 2147483647.0));
reOutBuf[ ch ][ i ] += (float) (wetGain * (j + (double) k / 2147483647.0));
}
if( complex ) {
for( i = 0; i < len; i++ ) {
j = (int) convBuf3[i] & (int) convBuf4[i];
k = ((int) (((double) convBuf3[i] % 1.0) * 2147483647.0)) &
((int) (((double) convBuf4[i] % 1.0) * 2147483647.0));
imOutBuf[ ch ][ i ] += (float) (wetGain * (j + (double) k / 2147483647.0));
}
}
break;
case OP_OR: // ================ OR ================
for( i = 0; i < len; i++ ) {
j = (int) convBuf1[i] | (int) convBuf2[i];
k = ((int) (((double) convBuf1[i] % 1.0) * 2147483647.0)) |
((int) (((double) convBuf2[i] % 1.0) * 2147483647.0));
reOutBuf[ ch ][ i ] += (float) (wetGain * (j + (double) k / 2147483647.0));
}
if( complex ) {
for( i = 0; i < len; i++ ) {
j = (int) convBuf3[i] | (int) convBuf4[i];
k = ((int) (((double) convBuf3[i] % 1.0) * 2147483647.0)) |
((int) (((double) convBuf4[i] % 1.0) * 2147483647.0));
imOutBuf[ ch ][ i ] += (float) (wetGain * (j + (double) k / 2147483647.0));
}
}
break;
case OP_XOR: // ================ XOR ================
for( i = 0; i < len; i++ ) {
j = (int) convBuf1[i] ^ (int) convBuf2[i];
k = ((int) (((double) convBuf1[i] % 1.0) * 2147483647.0)) ^
((int) (((double) convBuf2[i] % 1.0) * 2147483647.0));
reOutBuf[ ch ][ i ] += (float) (wetGain * (j + (double) k / 2147483647.0));
}
if( complex ) {
for( i = 0; i < len; i++ ) {
j = (int) convBuf3[i] ^ (int) convBuf4[i];
k = ((int) (((double) convBuf3[i] % 1.0) * 2147483647.0)) ^
((int) (((double) convBuf4[i] % 1.0) * 2147483647.0));
imOutBuf[ ch ][ i ] += (float) (wetGain * (j + (double) k / 2147483647.0));
}
}
break;
case OP_SIGN: // ================ Apply sign (phase) ================
if( complex ) { // apply sign here means apply phase
for( i = 0; i < len; i++ ) {
d1 = wetGain * Math.sqrt( convBuf1[i]*convBuf1[i] + convBuf3[i]*convBuf3[i] );
d2 = Math.atan2( convBuf4[i], convBuf2[i] );
reOutBuf[ ch ][ i ] += (float) (d1 * Math.cos( d2 ));
imOutBuf[ ch ][ i ] += (float) (d1 * Math.sin( d2 ));
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += (convBuf2[i] >= 0 ? wetGain : -wetGain) * Math.abs( convBuf1[ i ]);
}
}
break;
case OP_AMP: // ================ Apply amp ================
if( complex ) {
for( i = 0; i < len; i++ ) { // |op1|
d1 = wetGain * Math.sqrt( convBuf2[i]*convBuf2[i] + convBuf4[i]*convBuf4[i] );
d2 = Math.atan2( convBuf3[i], convBuf1[i] );
reOutBuf[ ch ][ i ] += (float) (d1 * Math.cos( d2 ));
imOutBuf[ ch ][ i ] += (float) (d1 * Math.sin( d2 ));
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += (convBuf1[i] >= 0 ? wetGain : -wetGain) * Math.abs( convBuf2[ i ]);
}
}
break;
case OP_MIN1: // ================ Min(a,b) ================
if( complex ) {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * Math.min( convBuf1[ i ], convBuf2[ i ]);
imOutBuf[ ch ][ i ] += wetGain * Math.min( convBuf3[ i ], convBuf4[ i ]);
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * Math.min( convBuf1[ i ], convBuf2[ i ]);
}
}
break;
case OP_MAX1: // ================ Max(a,b) ================
if( complex ) {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * Math.max( convBuf1[ i ], convBuf2[ i ]);
imOutBuf[ ch ][ i ] += wetGain * Math.max( convBuf3[ i ], convBuf4[ i ]);
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * Math.max( convBuf1[ i ], convBuf2[ i ]);
}
}
break;
case OP_MIN2: // ================ Min(|a|,|b|) ================
if( complex ) {
for( i = 0; i < len; i++ ) {
d1 = convBuf1[i]*convBuf1[i] + convBuf3[i]*convBuf3[i];
d2 = convBuf2[i]*convBuf2[i] + convBuf4[i]*convBuf4[i];
if( d1 < d2 ) {
reOutBuf[ ch ][ i ] += wetGain * convBuf1[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf3[ i ];
} else {
reOutBuf[ ch ][ i ] += wetGain * convBuf2[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf4[ i ];
}
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf1[ i ]) < Math.abs( convBuf2[ i ]) ?
convBuf1[ i ] : convBuf2[ i ]);
}
}
break;
case OP_MAX2: // ================ Max(|a|,|b|) ================
if( complex ) {
for( i = 0; i < len; i++ ) {
d1 = convBuf1[i]*convBuf1[i] + convBuf3[i]*convBuf3[i];
d2 = convBuf2[i]*convBuf2[i] + convBuf4[i]*convBuf4[i];
if( d1 >= d2 ) {
reOutBuf[ ch ][ i ] += wetGain * convBuf1[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf3[ i ];
} else {
reOutBuf[ ch ][ i ] += wetGain * convBuf2[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf4[ i ];
}
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf1[ i ]) >= Math.abs( convBuf2[ i ]) ?
convBuf1[ i ] : convBuf2[ i ]);
}
}
break;
case OP_MIN3: // ================ Min(Re)+iMin(Im) ================
if( complex ) {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf1[ i ]) < Math.abs( convBuf2[ i ]) ?
convBuf1[ i ] : convBuf2[ i ]);
imOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf3[ i ]) < Math.abs( convBuf4[ i ]) ?
convBuf3[ i ] : convBuf4[ i ]);
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf1[ i ]) < Math.abs( convBuf2[ i ]) ?
convBuf1[ i ] : convBuf2[ i ]);
}
}
break;
case OP_MAX3: // ================ Max(Re)+iMax(Im) ================
if( complex ) {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf1[ i ]) >= Math.abs( convBuf2[ i ]) ?
convBuf1[ i ] : convBuf2[ i ]);
imOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf3[ i ]) >= Math.abs( convBuf4[ i ]) ?
convBuf3[ i ] : convBuf4[ i ]);
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * (Math.abs( convBuf1[ i ]) >= Math.abs( convBuf2[ i ]) ?
convBuf1[ i ] : convBuf2[ i ]);
}
}
break;
case OP_MIN4: // ================ Min(a,b->a) ================
if( complex ) {
for( i = 0; i < len; i++ ) { // |op1|
d1 = Math.sqrt( convBuf1[i]*convBuf1[i] + convBuf3[i]*convBuf3[i] );
if( d1 > 0.0 ) { // cos phi * |op2|
d2 = Math.abs( convBuf1[i]*convBuf2[i] + convBuf3[i]*convBuf4[i] ) / d1;
if( d1 <= d2 ) {
reOutBuf[ ch ][ i ] += wetGain * convBuf1[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf3[ i ];
} else {
d2 *= wetGain / d1; // Strecken um |op2->op1| / |op1|
reOutBuf[ ch ][ i ] += (float) (d2 * convBuf1[ i ]);
imOutBuf[ ch ][ i ] += (float) (d2 * convBuf3[ i ]);
}
} // else |op1| == 0, don't have to add anything
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += (convBuf1[i] >= 0 ? wetGain : -wetGain) *
Math.min( Math.abs( convBuf1[ i ]), Math.abs( convBuf2[ i ]));
}
}
break;
case OP_MAX4: // ================ Max(a,b->a) ================
if( complex ) {
for( i = 0; i < len; i++ ) { // |op1|
d1 = Math.sqrt( convBuf1[i]*convBuf1[i] + convBuf3[i]*convBuf3[i] );
if( d1 > 0.0 ) { // cos phi * |op2|
d2 = Math.abs( convBuf1[i]*convBuf2[i] + convBuf3[i]*convBuf4[i] ) / d1;
if( d1 >= d2 ) {
reOutBuf[ ch ][ i ] += wetGain * convBuf1[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf3[ i ];
} else {
d2 *= wetGain / d1; // Strecken um |op2->op1| / |op1|
reOutBuf[ ch ][ i ] += (float) (d2 * convBuf1[ i ]);
imOutBuf[ ch ][ i ] += (float) (d2 * convBuf3[ i ]);
}
} else { // phase undefined ;(
reOutBuf[ ch ][ i ] += wetGain * convBuf2[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf4[ i ];
}
}
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += (convBuf1[i] >= 0 ? wetGain : -wetGain) *
Math.max( Math.abs( convBuf1[ i ]), Math.abs( convBuf2[ i ]));
}
}
break;
case OP_GATE: // ================ Gate ================
if( complex ) {
for( i = 0; i < len; i++ ) { // |op1| resp. 2
d1 = convBuf1[i]*convBuf1[i] + convBuf3[i]*convBuf3[i];
d2 = convBuf2[i]*convBuf2[i] + convBuf4[i]*convBuf4[i];
if( d1 > d2 ) {
reOutBuf[ ch ][ i ] += wetGain * convBuf1[ i ];
imOutBuf[ ch ][ i ] += wetGain * convBuf3[ i ];
}
}
} else {
for( i = 0; i < len; i++ ) {
if( Math.abs( convBuf1[ i ]) > Math.abs( convBuf2[ i ]) ) {
reOutBuf[ ch ][ i ] += wetGain * convBuf1[ i ];
}
}
}
break;
case OP_ARCTAN: // ================ ArcTangens ================
if( complex ) {
throw new IOException( "Op. not yet implemented!" ); // XXX
} else {
for( i = 0; i < len; i++ ) {
reOutBuf[ ch ][ i ] += wetGain * Math.atan2( convBuf2[ i ], convBuf1[ i ]);
}
}
}
} // for outChan
progOff += len;
// .... progress ....
setProgression( (float) progOff / (float) progLen );
// .... check running ....
if( !threadRunning ) break topLevel;
// ---- write output chunk ----
if( reFloatF != null ) {
for( ch = 0; ch < outChanNum; ch++ ) {
reFloatF[ ch ].writeFloats( reOutBuf[ ch ], 0, len );
if( pr.bool[ PR_HASIMOUTPUT ]) {
imFloatF[ ch ].writeFloats( imOutBuf[ ch ], 0, len );
}
}
} else {
reOutF.writeFrames( reOutBuf, 0, len );
if( pr.bool[ PR_HASIMOUTPUT ]) {
imOutF.writeFrames( imOutBuf, 0, len );
}
}
// check max amp
for( ch = 0; ch < outChanNum; ch++ ) {
convBuf1 = reOutBuf[ ch ];
for( i = 0; i < len; i++ ) {
f1 = Math.abs( convBuf1[ i ]);
if( f1 > maxAmp ) {
maxAmp = f1;
}
}
if( pr.bool[ PR_HASIMOUTPUT ]) {
convBuf1 = imOutBuf[ ch ];
for( i = 0; i < len; i++ ) {
f1 = Math.abs( convBuf1[ i ]);
if( f1 > maxAmp ) {
maxAmp = f1;
}
}
}
}
progOff += len;
framesWritten += len;
// .... progress ....
setProgression( (float) progOff / (float) progLen );
} // while not framesWritten
// ----==================== normalize output ====================----
if( pr.intg[ PR_GAINTYPE ] == GAIN_UNITY ) {
peakGain = new Param( (double) maxAmp, Param.ABS_AMP );
gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP,
new Param( 1.0 / peakGain.value, peakGain.unit ), null )).value;
f1 = pr.bool[ PR_HASIMOUTPUT ] ? ((1.0f + getProgression()) / 2) : 1.0f;
normalizeAudioFile( reFloatF, reOutF, reOutBuf, gain, f1 );
if( pr.bool[ PR_HASIMOUTPUT ]) {
normalizeAudioFile( imFloatF, imOutF, imOutBuf, gain, 1.0f );
}
maxAmp *= gain;
for( ch = 0; ch < outChanNum; ch++ ) {
reFloatF[ ch ].cleanUp();
reFloatF[ ch ] = null;
reTempFile[ ch ].delete();
reTempFile[ ch ] = null;
if( pr.bool[ PR_HASIMOUTPUT ]) {
imFloatF[ ch ].cleanUp();
imFloatF[ ch ] = null;
imTempFile[ ch ].delete();
imTempFile[ ch ] = null;
}
}
}
// .... check running ....
if( !threadRunning ) break topLevel;
// ---- Finish ----
reOutF.close();
reOutF = null;
reOutStream = null;
if( imOutF != null ) {
imOutF.close();
imOutF = null;
imOutStream = null;
}
for( op = 0; op < 2; op++ ) {
reInF[op].close();
reInF[op] = null;
reInStream[op] = null;
if( pr.bool[ PR_HASIMINPUT1 + op ]) {
imInF[op].close();
imInF[op] = null;
imInStream[op] = null;
}
}
reOutBuf = null;
imOutBuf = null;
reInBuf = null;
imInBuf = null;
// inform about clipping/ low level
handleClipping( maxAmp );
}
catch( IOException e1 ) {
setError( e1 );
}
catch( OutOfMemoryError e2 ) {
reOutBuf = null;
imOutBuf = null;
reInBuf = null;
imInBuf = null;
convBuf1 = null;
convBuf2 = null;
convBuf3 = null;
convBuf4 = null;
System.gc();
setError( new Exception( ERR_MEMORY ));
}
// ---- cleanup (topLevel) ----
convBuf1 = null;
convBuf2 = null;
convBuf3 = null;
convBuf4 = null;
for( op = 0; op < 2; op++ ) {
if( reInF[op] != null ) {
reInF[op].cleanUp();
reInF[op] = null;
}
if( imInF[op] != null ) {
imInF[op].cleanUp();
imInF[op] = null;
}
}
if( reOutF != null ) {
reOutF.cleanUp();
reOutF = null;
}
if( imOutF != null ) {
imOutF.cleanUp();
imOutF = null;
}
if( reFloatF != null ) {
for( ch = 0; ch < reFloatF.length; ch++ ) {
if( reFloatF[ ch ] != null ) {
reFloatF[ ch ].cleanUp();
reFloatF[ ch ] = null;
}
if( reTempFile[ ch ] != null ) {
reTempFile[ ch ].delete();
reTempFile[ ch ] = null;
}
}
}
if( imFloatF != null ) {
for( ch = 0; ch < imFloatF.length; ch++ ) {
if( imFloatF[ ch ] != null ) {
imFloatF[ ch ].cleanUp();
imFloatF[ ch ] = null;
}
if( imTempFile[ ch ] != null ) {
imTempFile[ ch ].delete();
imTempFile[ ch ] = null;
}
}
}
} // process()
// -------- private methods --------
protected void reflectPropertyChanges()
{
super.reflectPropertyChanges();
Component c;
c = gui.getItemObj( GG_IMINPUTFILE1 );
if( c != null ) {
c.setEnabled( pr.bool[ PR_HASIMINPUT1 ]);
}
c = gui.getItemObj( GG_IMINPUTFILE2 );
if( c != null ) {
c.setEnabled( pr.bool[ PR_HASIMINPUT2 ]);
}
c = gui.getItemObj( GG_IMOUTPUTFILE );
if( c != null ) {
c.setEnabled( pr.bool[ PR_HASIMOUTPUT ]);
}
}
}
// class BinaryOpDlg