/*
* BlunderFingerOpDlg.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
*
*
* Changelog:
* 20-Dec-08 created
*/
package de.sciss.fscape.gui;
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.spect.Wavelet;
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 javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* Processing module for approaching a file (fit input)
* throw evolution using a genetic algorithm.
*/
public class BlunderFingerDlg
extends ModulePanel {
// -------- private variables --------
// Properties (defaults)
private static final int PR_INFITFILE = 0; // pr.text
private static final int PR_INPOPFILE = 1;
private static final int PR_OUTPUTFILE = 2;
private static final int PR_OUTPUTTYPE = 0; // pr.intg
private static final int PR_OUTPUTRES = 1;
private static final int PR_GAINTYPE = 2;
private static final int PR_CHROMOLEN = 3;
private static final int PR_CHANFIT = 4;
private static final int PR_DOMAIN = 5;
private static final int PR_GAIN = 0; // pr.para
private static final int PR_CROSSPOINTS = 1;
private static final int PR_POPULATION = 2;
private static final int PR_ITERATIONS = 3;
private static final int PR_MUTAPROB = 4;
private static final int PR_MUTAAMOUNT = 5;
private static final int PR_ELITISM = 0; // pr.bool
private static final String PRN_INPUTFILE = "InFitFile";
private static final String PRN_OUTPUTFILE = "OutputFile";
private static final String PRN_PATTERNFILE = "InPopFile";
private static final String PRN_OUTPUTTYPE = "OutputType";
private static final String PRN_OUTPUTRES = "OutputReso";
private static final String PRN_CROSSPOINTS = "CrossPoints";
private static final String PRN_POPULATION = "Population";
private static final String PRN_ITERATIONS = "Iterations";
private static final String PRN_CHROMOLEN = "ChromoLen";
private static final String PRN_CHANFIT = "ChanFit";
private static final String PRN_DOMAIN = "Domain";
private static final String PRN_MUTAPROB = "MutaProb";
private static final String PRN_MUTAAMOUNT = "MutaAmount";
private static final String PRN_ELITISM = "Elitism";
private static final int CHANFIT_WORST = 0;
private static final int CHANFIT_BEST = 1;
private static final int CHANFIT_MEAN = 2;
private static final int DOMAIN_TIME = 0;
private static final int DOMAIN_WAVELET = 1;
private static final String prText[] = { "", "", "" };
private static final String prTextName[] = { PRN_INPUTFILE, PRN_PATTERNFILE, PRN_OUTPUTFILE };
private static final int prIntg[] = { 0, 0, GAIN_UNITY, 4, CHANFIT_WORST, DOMAIN_TIME };
private static final String prIntgName[] = { PRN_OUTPUTTYPE, PRN_OUTPUTRES, PRN_GAINTYPE, PRN_CHROMOLEN, PRN_CHANFIT, PRN_DOMAIN };
private static final Param prPara[] = { null, null, null, null, null, null };
private static final String prParaName[] = { PRN_GAIN, PRN_CROSSPOINTS, PRN_POPULATION, PRN_ITERATIONS, PRN_MUTAPROB, PRN_MUTAAMOUNT };
private static final boolean prBool[] = { true };
private static final String prBoolName[] = { PRN_ELITISM };
private static final int GG_INFITFILE = GG_OFF_PATHFIELD + PR_INFITFILE;
private static final int GG_OUTPUTFILE = GG_OFF_PATHFIELD + PR_OUTPUTFILE;
private static final int GG_INPOPFILE = GG_OFF_PATHFIELD + PR_INPOPFILE;
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_GAINTYPE = GG_OFF_CHOICE + PR_GAINTYPE;
private static final int GG_CHROMOLEN = GG_OFF_CHOICE + PR_CHROMOLEN;
private static final int GG_CHANFIT = GG_OFF_CHOICE + PR_CHANFIT;
private static final int GG_DOMAIN = GG_OFF_CHOICE + PR_DOMAIN;
private static final int GG_GAIN = GG_OFF_PARAMFIELD + PR_GAIN;
private static final int GG_CROSSPOINTS = GG_OFF_PARAMFIELD + PR_CROSSPOINTS;
private static final int GG_POPULATION = GG_OFF_PARAMFIELD + PR_POPULATION;
private static final int GG_ITERATIONS = GG_OFF_PARAMFIELD + PR_ITERATIONS;
private static final int GG_MUTAPROB = GG_OFF_PARAMFIELD + PR_MUTAPROB;
private static final int GG_MUTAAMOUNT = GG_OFF_PARAMFIELD + PR_MUTAAMOUNT;
private static final int GG_ELITISM = GG_OFF_CHECKBOX + PR_ELITISM;
private static PropertyArray static_pr = null;
private static Presets static_presets = null;
private static final String ERR_CHANNELS = "Inputs must share\nsame # of channels!";
// -------- public methods --------
public BlunderFingerDlg() {
super("BlunderFinger");
init2();
}
protected void buildGUI() {
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_CROSSPOINTS ] = new Param( 1.0, Param.NONE );
static_pr.para[ PR_POPULATION ] = new Param( 32.0, Param.NONE );
static_pr.para[ PR_ITERATIONS ] = new Param( 300.0, Param.NONE );
static_pr.para[ PR_MUTAPROB ] = new Param( 33.3, Param.REL_PERCENT);
static_pr.para[ PR_MUTAAMOUNT ] = new Param( 0.1, Param.FACTOR_AMP );
static_pr.paraName = prParaName;
// 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 ggInFitFile, ggOutputFile, ggInPopFile;
PathField[] ggInputs;
JComboBox ggChromoLen, ggChanFit, ggDomain;
JCheckBox ggElitism;
Component[] ggGain;
ParamField ggCrossPoints, ggPopulation, ggIterations, ggMutaProb, ggMutaAmount;
ParamSpace[] spcMutaAmt;
gui = new GUISupport();
con = gui.getGridBagConstraints();
con.insets = new Insets( 1, 2, 1, 2 );
ItemListener il = new ItemListener() {
public void itemStateChanged( ItemEvent e )
{
int ID = gui.getItemID( e );
switch( ID ) {
case GG_CHROMOLEN:
pr.intg[ ID - GG_OFF_CHOICE ] = ((JComboBox) e.getSource()).getSelectedIndex();
reflectPropertyChanges();
break;
}
}
};
// -------- Input-Gadgets --------
con.fill = GridBagConstraints.BOTH;
con.gridwidth = GridBagConstraints.REMAINDER;
// gui.addLabel( new JLabel( "Fuck the genfood mafia", SwingConstants.RIGHT ));
gui.addLabel( new GroupLabel( "Waveform I/O", GroupLabel.ORIENT_HORIZONTAL,
GroupLabel.BRACE_NONE ));
ggInFitFile = new PathField( PathField.TYPE_INPUTFILE + PathField.TYPE_FORMATFIELD,
"Select input fit file" );
ggInFitFile.handleTypes( GenericFile.TYPES_SOUND );
con.gridwidth = 1;
con.weightx = 0.1;
gui.addLabel( new JLabel( "Fit input", SwingConstants.RIGHT ));
con.gridwidth = GridBagConstraints.REMAINDER;
con.weightx = 0.9;
gui.addPathField( ggInFitFile, GG_INFITFILE, null );
ggInPopFile = new PathField( PathField.TYPE_INPUTFILE + PathField.TYPE_FORMATFIELD,
"Select input population file" );
ggInPopFile.handleTypes( GenericFile.TYPES_SOUND );
con.gridwidth = 1;
con.weightx = 0.1;
gui.addLabel( new JLabel( "Population input", SwingConstants.RIGHT ));
con.gridwidth = GridBagConstraints.REMAINDER;
con.weightx = 0.9;
gui.addPathField( ggInPopFile, GG_INPOPFILE, null );
ggOutputFile = new PathField( PathField.TYPE_OUTPUTFILE + PathField.TYPE_FORMATFIELD +
PathField.TYPE_RESFIELD, "Select output file" );
ggOutputFile.handleTypes( GenericFile.TYPES_SOUND );
ggInputs = new PathField[ 2 ];
ggInputs[ 0 ] = ggInFitFile;
ggInputs[ 1 ] = ggInPopFile;
ggOutputFile.deriveFrom( ggInputs, "$D0$B0Gen$B1$E" );
con.gridwidth = 1;
con.weightx = 0.1;
gui.addLabel( new JLabel( "Evolved output", SwingConstants.RIGHT ));
con.gridwidth = GridBagConstraints.REMAINDER;
con.weightx = 0.9;
gui.addPathField( ggOutputFile, GG_OUTPUTFILE, null );
gui.registerGadget( ggOutputFile.getTypeGadget(), GG_OUTPUTTYPE );
gui.registerGadget( ggOutputFile.getResGadget(), GG_OUTPUTRES );
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 );
// -------- Plot Settings --------
gui.addLabel( new GroupLabel( "Evolution settings", GroupLabel.ORIENT_HORIZONTAL,
GroupLabel.BRACE_NONE ));
ggChromoLen = new JComboBox();
for( int i = 2; i <= 16384; i <<= 1 ) {
ggChromoLen.addItem( String.valueOf( i ));
}
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Chromosome length", SwingConstants.RIGHT ));
con.weightx = 0.2;
gui.addChoice( ggChromoLen, GG_CHROMOLEN, il );
ggCrossPoints = new ParamField( new ParamSpace[] {
new ParamSpace( 1, 1000000, 1, Param.NONE )});
con.weightx = 0.1;
// con.gridwidth = 1;
gui.addLabel( new JLabel( "Crossing points", SwingConstants.RIGHT ));
con.weightx = 0.4;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addParamField( ggCrossPoints, GG_CROSSPOINTS, null );
ggIterations = new ParamField( new ParamSpace[] {
new ParamSpace( 1, 1000000, 1, Param.NONE )});
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Iterations", SwingConstants.RIGHT ));
con.weightx = 0.4;
// con.gridwidth = GridBagConstraints.REMAINDER;
gui.addParamField( ggIterations, GG_ITERATIONS, null );
ggMutaProb = new ParamField( Constants.spaces[ Constants.unsignedModSpace ]);
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Mutation probability", SwingConstants.RIGHT ));
con.weightx = 0.4;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addParamField( ggMutaProb, GG_MUTAPROB, null );
ggPopulation = new ParamField( new ParamSpace[] {
new ParamSpace( 2, 65536, 2, Param.NONE )});
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Population", SwingConstants.RIGHT ));
con.weightx = 0.4;
gui.addParamField( ggPopulation, GG_POPULATION, null );
spcMutaAmt = new ParamSpace[ 2 ];
spcMutaAmt[0] = Constants.spaces[ Constants.ratioAmpSpace ];
spcMutaAmt[1] = new ParamSpace( Constants.minDecibel, 0.0, 0.01, Param.DECIBEL_AMP );
ggMutaAmount = new ParamField( spcMutaAmt );
con.weightx = 0.1;
gui.addLabel( new JLabel( "Mutation amount", SwingConstants.RIGHT ));
con.weightx = 0.4;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addParamField( ggMutaAmount, GG_MUTAAMOUNT, null );
ggElitism = new JCheckBox();
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Elitism", SwingConstants.RIGHT ));
con.weightx = 0.2;
gui.addCheckbox( ggElitism, GG_ELITISM, il );
ggChanFit = new JComboBox();
ggChanFit.addItem( "Worst" );
ggChanFit.addItem( "Best" );
ggChanFit.addItem( "Mean" );
con.weightx = 0.1;
// con.gridwidth = 1;
gui.addLabel( new JLabel( "Multichannel fitness", SwingConstants.RIGHT ));
con.weightx = 0.2;
con.gridwidth = GridBagConstraints.REMAINDER;
gui.addChoice( ggChanFit, GG_CHANFIT, il );
ggDomain = new JComboBox();
ggDomain.addItem( "Time" );
ggDomain.addItem( "Wavelet" );
con.weightx = 0.1;
con.gridwidth = 1;
gui.addLabel( new JLabel( "Domain", SwingConstants.RIGHT ));
con.weightx = 0.2;
gui.addChoice( ggDomain, GG_DOMAIN, il );
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 --------
protected void process()
{
long progOff;
final long progLen;
AudioFile inFitF = null;
AudioFile outF = null;
AudioFile inPopF = null;
final AudioFile tmpF;
final AudioFileDescr inFitDescr;
final AudioFileDescr outStream;
final AudioFileDescr inPopDescr;
final int inChanNum, outChanNum, inPopChanNum;
final long inFitLength, inPopLength;
long fitFramesRead;
final Param ampRef = new Param( 1.0, Param.ABS_AMP ); // transform-Referenz
float gain = 1.0f; // gain abs amp
float maxAmp = 0.0f;
final PathField ggOutput;
final Random rnd = new Random();
final int population, populationM1, iterations, chromoLen, inPopBufSize;
final int chromoLenM1, multiChanType, numCrossPoints;
final float[][] inFitBuf, inPopBuf;
double[] fitness, newFitness, tempFit;
final List<Integer> crossings;
final float[] weights;
final int[] crossPoints;
final boolean elitism;
final float mutaProb, mutaAmtD;
float[][][] tempPop, popBuf, newPopBuf;
float[][] outBuf;
final float[] inOverlap, popOverlap;
final float[][] outOverlap; // includes DC-block filter coeffs
float muta;
int chunkLen, chunkLen2, inPopBufOff, newPopCount;
int parentIdx1, parentIdx2;
long popFramesRead;
final boolean wavelet;
final boolean diff = true; // XXX
final float[][] waveletCoeffs;
float f1, f2, f3, f4;
float[] convBuf1;
topLevel:
try {
// ---- open input, output; init ----
// input
inFitF = AudioFile.openAsRead( new File( pr.text[ PR_INFITFILE ]));
inFitDescr = inFitF.getDescr();
inChanNum = inFitDescr.channels;
inFitLength = (int) inFitDescr.length;
// this helps to prevent errors from empty files!
if( (inFitLength < 1) || (inChanNum < 1) ) throw new EOFException( ERR_EMPTY );
// .... check running ....
if( !threadRunning ) break topLevel;
// ptrn input
inPopF = AudioFile.openAsRead( new File( pr.text[ PR_INPOPFILE ]));
inPopDescr = inPopF.getDescr();
inPopChanNum = inPopDescr.channels;
inPopLength = inPopDescr.length;
// this helps to prevent errors from empty files!
if( (inPopLength < 1) || (inPopChanNum < 1) ) throw new EOFException( ERR_EMPTY );
// .... check running ....
if( !threadRunning ) break topLevel;
if( inChanNum != inPopChanNum ) {
throw new IOException( ERR_CHANNELS );
}
// output
ggOutput = (PathField) gui.getItemObj( GG_OUTPUTFILE );
if( ggOutput == null ) throw new IOException( ERR_MISSINGPROP );
outStream = new AudioFileDescr( inFitDescr );
ggOutput.fillStream( outStream );
outChanNum = inChanNum;
outStream.channels = outChanNum;
outF = AudioFile.openAsWrite( outStream );
// .... check running ....
if( !threadRunning ) break topLevel;
// ---- further inits ----
chromoLen = 2 << pr.intg[ PR_CHROMOLEN ];
chromoLenM1 = chromoLen - 1;
inFitBuf = new float[ inChanNum ][ Math.max( 8192, chromoLen )];
inOverlap = new float[ inChanNum ];
popOverlap = new float[ inChanNum ];
outOverlap = new float[ inChanNum ][ 3 ];
population = (int) pr.para[ PR_POPULATION ].value;
populationM1 = population - 1;
inPopBufSize = chromoLen + populationM1;
inPopBuf = new float[ inChanNum ][ inPopBufSize ];
inPopBufOff = 0;
popBuf = new float[ population ][ inChanNum ][ chromoLen ];
newPopBuf = new float[ population ][ inChanNum ][ chromoLen ];
fitness = new double[ population ];
newFitness = new double[ population ];
mutaProb = (float) (pr.para[ PR_MUTAPROB ].value / 100);
multiChanType = pr.intg[ PR_CHANFIT ];
elitism = pr.bool[ PR_ELITISM ];
iterations = (int) pr.para[ PR_ITERATIONS ].value;
numCrossPoints = (int) pr.para[ PR_CROSSPOINTS ].value;
mutaAmtD = (float) ((Param.transform( pr.para[ PR_MUTAAMOUNT ], Param.ABS_AMP, ampRef, null )).value * 2);
weights = new float[ population ];
final int div = ((population + 1) * population) / 2;
double sum = 0.0;
double weight;
for( int i = 0; i < population; i++ ) {
weight = (double) (population - i) / div;
weights[ i ] = (float) (weight + sum);
sum += weight;
}
// assert( Math.abs( sum - 1.0 ) < 1.0e-6 ) : sum;
assert( Math.abs( weights[ population - 1 ] - 1.0 ) < 1.0e-6 ) : weights[ population - 1 ];
weights[ populationM1 ] = 1.0f;
crossings = new ArrayList<Integer>( chromoLen - 2 );
crossPoints = new int[ numCrossPoints + 1 ];
crossPoints[ numCrossPoints ] = chromoLen;
wavelet = pr.intg[ PR_DOMAIN ] == DOMAIN_WAVELET;
if( wavelet ) {
waveletCoeffs = Wavelet.getCoeffs( Wavelet.COEFFS_DAUB4 );
} else {
waveletCoeffs = null;
}
if( pr.intg[ PR_GAINTYPE ] == GAIN_ABSOLUTE ) {
gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP, ampRef, null )).value;
tmpF = null;
} else {
tmpF = createTempFile( outStream );
}
progLen = (inFitLength << 2) + (tmpF == null ? 0 : inFitLength);
progOff = 0;
// framesWritten = 0;
popFramesRead = 0;
// ----==================== processing loop ====================----
for( fitFramesRead = 0; threadRunning && (fitFramesRead < inFitLength); ) {
chunkLen = (int) Math.min( chromoLen, inFitLength - fitFramesRead );
inFitF.readFrames( inFitBuf, 0, chunkLen );
if( chunkLen < chromoLen ) {
Util.clear( inFitBuf, chunkLen, chromoLen - chunkLen );
}
if( diff ) {
for( int ch = 0; ch < inChanNum; ch++ ) {
convBuf1 = inFitBuf[ ch ];
f2 = inOverlap[ ch ];
for( int i = 0; i < chunkLen; i++ ) {
f1 = convBuf1[ i ];
convBuf1[ i ] -= f2;
f2 = f1;
}
inOverlap[ ch ] = f2;
}
}
if( wavelet ) {
for( int ch = 0; ch < inChanNum; ch++ ) {
Wavelet.fwdTransform( inFitBuf[ ch ], chromoLen, waveletCoeffs );
}
}
// XXX
//popFramesRead = Math.min( inPopLength, fitFramesRead );
//inPopF.seekFrame( popFramesRead );
chunkLen2 = (int) Math.min( inPopBufSize - inPopBufOff, inPopLength - popFramesRead );
Util.copy( inPopBuf, chromoLen, inPopBuf, 0, populationM1 );
inPopF.readFrames( inPopBuf, inPopBufOff, chunkLen2 );
if( chunkLen2 + inPopBufOff < inPopBufSize ) {
Util.clear( inPopBuf, chunkLen2 + inPopBufOff, inPopBufSize - (chunkLen2 + inPopBufOff) );
}
if( diff ) {
for( int ch = 0; ch < inChanNum; ch++ ) {
convBuf1 = inPopBuf[ ch ];
f2 = popOverlap[ ch ];
for( int i = inPopBufOff, j = i + chunkLen2; i < j; i++ ) {
f1 = convBuf1[ i ];
convBuf1[ i ] -= f2;
f2 = f1;
}
popOverlap[ ch ] = f2;
}
}
for( int i = 0; i < population; i++ ) {
Util.copy( inPopBuf, i, popBuf[ i ], 0, chromoLen );
if( wavelet ) {
for( int ch = 0; ch < inChanNum; ch++ ) {
Wavelet.fwdTransform( popBuf[ i ][ ch ], chromoLen, waveletCoeffs );
}
}
fitness[ i ] = calcFitness( popBuf[ i ], inFitBuf, multiChanType );
}
Util.sort( fitness, popBuf, 0, population );
for( int it = 0; it < iterations; it++ ) {
newPopCount = 0;
if( elitism ) {
for( int i = 0; i < 2; i++, newPopCount++ ) {
Util.copy( popBuf[ newPopCount ], 0, newPopBuf[ newPopCount ], 0, chromoLen );
newFitness[ newPopCount ] = fitness[ newPopCount ];
}
}
for( ; newPopCount < population; newPopCount += 2 ) {
// parent selection
parentIdx1 = wchoose( weights, rnd );
parentIdx2 = wchoose( weights, rnd );
if( parentIdx2 == parentIdx1 ) { // no hermaphrodites
parentIdx2 = (parentIdx1 == populationM1) ? parentIdx1 - 1 : parentIdx1 + 1;
}
// selecting crossings
crossings.clear();
for( int i = 1; i < chromoLenM1; i++ ) {
crossings.add( new Integer( i ));
}
for( int i = 0; i < numCrossPoints; i++ ) {
crossPoints[ i ] = crossings.remove(
rnd.nextInt( crossings.size() )).intValue();
}
Arrays.sort( crossPoints, 0, numCrossPoints );
// breeding
for( int i = 0, lastPoint = 0, tempIdx; i <= numCrossPoints; i++ ) {
Util.copy( popBuf[ parentIdx1 ], lastPoint, newPopBuf[ newPopCount ], lastPoint, crossPoints[ i ] - lastPoint );
Util.copy( popBuf[ parentIdx2 ], lastPoint, newPopBuf[ newPopCount + 1 ], lastPoint, crossPoints[ i ] - lastPoint );
tempIdx = parentIdx1;
parentIdx1 = parentIdx2;
parentIdx2 = tempIdx;
lastPoint = crossPoints[ i ];
}
// mutation
if( mutaProb > 0f ) {
for( int ch = 0; ch < inChanNum; ch++ ) {
for( int child = 0; child < 2; child++ ) {
for( int i = 0; i < chromoLen; i++ ) {
if( rnd.nextFloat() < mutaProb ) {
muta = (rnd.nextFloat() - 0.5f) * mutaAmtD;
newPopBuf[ newPopCount + child ][ ch ][ i ] += muta;
}
}
}
}
}
for( int child = 0; child < 2; child++ ) {
newFitness[ newPopCount + child ] =
calcFitness( newPopBuf[ newPopCount + child ], inFitBuf, multiChanType );
}
}
// new pop becomes current pop
tempPop = popBuf;
popBuf = newPopBuf;
newPopBuf = tempPop;
tempFit = fitness;
fitness = newFitness;
newFitness = tempFit;
Util.sort( fitness, popBuf, 0, population );
}
// best fit is written out
outBuf = popBuf[ 0 ];
if( wavelet ) {
for( int ch = 0; ch < inChanNum; ch++ ) {
Wavelet.invTransform( outBuf[ ch ], chromoLen, waveletCoeffs );
}
}
if( diff ) {
for( int ch = 0; ch < inChanNum; ch++ ) {
convBuf1 = outBuf[ ch ];
f2 = outOverlap[ ch ][ 0 ];
f3 = outOverlap[ ch ][ 1 ];
f4 = outOverlap[ ch ][ 2 ];
for( int i = 0; i < chunkLen; i++ ) {
f2 += convBuf1[ i ];
// convBuf1[ i ] = f2;
convBuf1[ i ] = f2 - f3 + 0.99f * f4;
f3 = f2;
f4 = convBuf1[ i ];
}
outOverlap[ ch ][ 0 ] = f2;
outOverlap[ ch ][ 1 ] = f3;
outOverlap[ ch ][ 2 ] = f4;
}
}
maxAmp = Math.max( maxAmp, Util.maxAbs( outBuf, 0, chunkLen ));
if( pr.intg[ PR_GAINTYPE ] == GAIN_ABSOLUTE ) {
Util.mult( outBuf, 0, chunkLen, gain );
}
if( tmpF != null ) {
tmpF.writeFrames( outBuf, 0, chunkLen );
} else {
outF.writeFrames( outBuf, 0, chunkLen );
}
fitFramesRead += chunkLen;
popFramesRead += chunkLen2;
inPopBufOff = populationM1;
progOff += chunkLen << 2;
// .... progress ....
setProgression( (float) progOff / (float) progLen );
}
// .... check running ....
if( !threadRunning ) break topLevel;
inPopF.close();
inPopF = null;
inFitF.close();
inFitF = null;
// adjust gain
if( pr.intg[ PR_GAINTYPE ] == GAIN_UNITY ) {
gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP,
new Param( 1.0 / maxAmp, Param.ABS_AMP ), null )).value;
normalizeAudioFile( tmpF, outF, inFitBuf, gain, 1.0f );
deleteTempFile( tmpF );
}
// .... check running ....
if( !threadRunning ) break topLevel;
// ---- Finish ----
outF.close();
outF = null;
// inform about clipping/ low level
maxAmp *= gain;
handleClipping( maxAmp );
}
catch( IOException e1 ) {
setError( e1 );
}
catch( OutOfMemoryError e2 ) {
setError( new Exception( ERR_MEMORY ));
}
// ---- cleanup (topLevel) ----
if( inFitF != null ) inFitF.cleanUp();
if( outF != null ) outF.cleanUp();
if( inPopF != null ) inPopF.cleanUp();
} // process()
// -------- private methods --------
private static double calcFitness( float[][] pop, float[][] fit, int multiChanType )
{
double fitness = 0f, d1;
// double d2;
float f1;
float[] popC, fitC;
for( int ch = 0; ch < pop.length; ch++ ) {
popC = pop[ ch ];
fitC = fit[ ch ];
d1 = 0.0;
for( int i = 0; i < popC.length; i++ ) {
f1 = popC[ i ] - fitC[ i ];
// d2 = popC[ i ] - fitC[ i ];
// d1 += d2 * d2;
d1 += f1 * f1;
// d1 = Math.max( d1, d2 * d2 );
// d1 += d2 * d2 * d2 * d2;
}
if( ch == 0 ) {
fitness = d1;
} else {
switch( multiChanType ) {
case CHANFIT_WORST:
fitness = Math.max( fitness, d1 );
break;
case CHANFIT_BEST:
fitness = Math.min( fitness, d1 );
break;
case CHANFIT_MEAN:
fitness += d1;
break;
default:
throw new IllegalArgumentException( String.valueOf( multiChanType ));
}
}
}
return fitness;
}
private static int wchoose(float[] weights, Random rnd) {
final int idx = Arrays.binarySearch(weights, rnd.nextFloat());
return (idx < 0 ? -(idx + 1) : idx);
}
protected void reflectPropertyChanges() {
super.reflectPropertyChanges();
final JComboBox ggChromoLen = (JComboBox) gui.getItemObj(GG_CHROMOLEN);
final ParamField ggCrossPoints = (ParamField) gui.getItemObj(GG_CROSSPOINTS);
if ((ggChromoLen != null) && (ggCrossPoints != null)) {
final int chromoLenM1 = (2 << ggChromoLen.getSelectedIndex()) - 1;
ggCrossPoints.setSpaces(new ParamSpace[]{
new ParamSpace(1, chromoLenM1, 1, Param.NONE)
});
if (ggCrossPoints.getParam().value > chromoLenM1) {
ggCrossPoints.setParam(new Param(chromoLenM1, Param.NONE));
}
}
}
}