/* * BandSplitDlg.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.spect.Fourier; import de.sciss.fscape.util.Constants; import de.sciss.fscape.util.Filter; import de.sciss.fscape.util.Param; 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.EOFException; import java.io.File; import java.io.IOException; /** * Processing module for splitting a sound into * a number of adjacent frequency bands. */ public class BandSplitDlg extends ModulePanel { // -------- private variables -------- // Properties (defaults) private static final int PR_INPUTFILE = 0; // pr.text private static final int PR_OUTPUTFILE = 1; 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_QUALITY = 3; private static final int PR_NUMBANDS = 4; private static final int PR_GAIN = 0; // pr.para private static final int PR_FREQ1 = 1; private static final int PR_FREQ2 = 2; private static final int PR_FREQ3 = 3; private static final int PR_FREQ4 = 4; private static final int PR_FREQ5 = 5; private static final int PR_FREQ6 = 6; private static final int PR_FREQ7 = 7; private static final int PR_FREQ8 = 8; private static final int PR_ROLLOFF = 9; private static final int PR_NORMEACH = 0; // pr.bool // private static final int QUAL_LOW = 0; // PR_QUALITY // private static final int QUAL_MEDIUM = 1; private static final int QUAL_GOOD = 2; // private static final int QUAL_VERYGOOD = 3; private static final String[] QUAL_NAMES = { "Low", "Medium", "Good", "Very good" }; private static final String PRN_INPUTFILE = "InputFile"; private static final String PRN_OUTPUTFILE = "OutputFile"; private static final String PRN_OUTPUTTYPE = "OutputType"; private static final String PRN_OUTPUTRES = "OutputReso"; private static final String PRN_QUALITY = "Quality"; private static final String PRN_NUMBANDS = "NumBands"; private static final String PRN_FREQ1 = "Freq1"; private static final String PRN_FREQ2 = "Freq2"; private static final String PRN_FREQ3 = "Freq3"; private static final String PRN_FREQ4 = "Freq4"; private static final String PRN_FREQ5 = "Freq5"; private static final String PRN_FREQ6 = "Freq6"; private static final String PRN_FREQ7 = "Freq7"; private static final String PRN_FREQ8 = "Freq8"; private static final String PRN_ROLLOFF = "RollOff"; private static final String PRN_NORMEACH = "NormEach"; private static final String prText[] = { "", "" }; private static final String prTextName[] = { PRN_INPUTFILE, PRN_OUTPUTFILE }; private static final int prIntg[] = { 0, 0, 0, QUAL_GOOD, 2 }; private static final String prIntgName[] = { PRN_OUTPUTTYPE, PRN_OUTPUTRES, PRN_GAINTYPE, PRN_QUALITY, PRN_NUMBANDS }; private static final Param prPara[] = { null, null, null, null, null, null, null, null, null, null }; private static final String prParaName[] = { PRN_GAIN, PRN_FREQ1, PRN_FREQ2, PRN_FREQ3, PRN_FREQ4, PRN_FREQ5, PRN_FREQ6, PRN_FREQ7, PRN_FREQ8, PRN_ROLLOFF }; private static final boolean prBool[] = { false }; private static final String prBoolName[] = { PRN_NORMEACH }; private static final int GG_INPUTFILE = GG_OFF_PATHFIELD + PR_INPUTFILE; private static final int GG_OUTPUTFILE = GG_OFF_PATHFIELD + PR_OUTPUTFILE; 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_QUALITY = GG_OFF_CHOICE + PR_QUALITY; private static final int GG_NUMBANDS = GG_OFF_CHOICE + PR_NUMBANDS; private static final int GG_GAINTYPE = GG_OFF_CHOICE + PR_GAINTYPE; private static final int GG_GAIN = GG_OFF_PARAMFIELD + PR_GAIN; private static final int GG_FREQ1 = GG_OFF_PARAMFIELD + PR_FREQ1; // private static final int GG_FREQ2 = GG_OFF_PARAMFIELD + PR_FREQ2; // private static final int GG_FREQ3 = GG_OFF_PARAMFIELD + PR_FREQ3; // private static final int GG_FREQ4 = GG_OFF_PARAMFIELD + PR_FREQ4; // private static final int GG_FREQ5 = GG_OFF_PARAMFIELD + PR_FREQ5; // private static final int GG_FREQ6 = GG_OFF_PARAMFIELD + PR_FREQ6; // private static final int GG_FREQ7 = GG_OFF_PARAMFIELD + PR_FREQ7; // private static final int GG_FREQ8 = GG_OFF_PARAMFIELD + PR_FREQ8; private static final int GG_ROLLOFF = GG_OFF_PARAMFIELD + PR_ROLLOFF; private static final int GG_NORMEACH = GG_OFF_CHECKBOX + PR_NORMEACH; private static PropertyArray static_pr = null; private static Presets static_presets = null; // -------- public methods -------- public BandSplitDlg() { super("Band Splitting"); 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.para = prPara; static_pr.para[ PR_FREQ1 ] = new Param( 200.0, Param.ABS_HZ ); static_pr.para[ PR_FREQ2 ] = new Param( 800.0, Param.ABS_HZ ); static_pr.para[ PR_FREQ3 ] = new Param( 1600.0, Param.ABS_HZ ); static_pr.para[ PR_FREQ4 ] = new Param( 3200.0, Param.ABS_HZ ); static_pr.para[ PR_FREQ5 ] = new Param( 4800.0, Param.ABS_HZ ); static_pr.para[ PR_FREQ6 ] = new Param( 6400.0, Param.ABS_HZ ); static_pr.para[ PR_FREQ7 ] = new Param( 8000.0, Param.ABS_HZ ); static_pr.para[ PR_FREQ8 ] = new Param( 9600.0, Param.ABS_HZ ); static_pr.para[ PR_ROLLOFF ] = new Param( 100.0, Param.FACTOR_FREQ ); 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 ggInputFile, ggOutputFile; PathField[] ggParent1; JComboBox ggQuality, ggNumBands; JCheckBox ggNormEach; ParamField ggFreq, ggRollOff; Component[] ggGain; int i; 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_NUMBANDS: pr.intg[ ID - GG_OFF_CHOICE ] = ((JComboBox) e.getSource()).getSelectedIndex(); reflectPropertyChanges(); break; } } }; // -------- I/O-Gadgets -------- con.fill = GridBagConstraints.BOTH; con.gridwidth = GridBagConstraints.REMAINDER; gui.addLabel( new GroupLabel( "Waveform I/O", GroupLabel.ORIENT_HORIZONTAL, GroupLabel.BRACE_NONE )); ggInputFile = new PathField( PathField.TYPE_INPUTFILE + PathField.TYPE_FORMATFIELD, "Select input file" ); ggInputFile.handleTypes( GenericFile.TYPES_SOUND ); con.gridwidth = 1; con.weightx = 0.1; gui.addLabel( new JLabel( "Input file", SwingConstants.RIGHT )); con.gridwidth = GridBagConstraints.REMAINDER; con.weightx = 0.9; gui.addPathField( ggInputFile, GG_INPUTFILE, null ); ggOutputFile = new PathField( PathField.TYPE_OUTPUTFILE + PathField.TYPE_FORMATFIELD + PathField.TYPE_RESFIELD, "Select output file" ); ggOutputFile.handleTypes( GenericFile.TYPES_SOUND ); con.gridwidth = 1; con.weightx = 0.1; gui.addLabel( new JLabel( "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 ); ggParent1 = new PathField[ 1 ]; ggParent1[ 0 ] = ggInputFile; ggOutputFile.deriveFrom( ggParent1, "$D0$F0Splt$E" ); ggGain = createGadgets( GGTYPE_GAIN ); con.weightx = 0.1; con.gridwidth = 1; gui.addLabel( new JLabel( "Gain", SwingConstants.RIGHT )); con.weightx = 0.3; gui.addParamField( (ParamField) ggGain[ 0 ], GG_GAIN, null ); gui.addChoice( (JComboBox) ggGain[ 1 ], GG_GAINTYPE, il ); ggNormEach = new JCheckBox( "Norm. each file" ); con.gridwidth = GridBagConstraints.REMAINDER; con.gridwidth = GridBagConstraints.REMAINDER; gui.addCheckbox( ggNormEach, GG_NORMEACH, il ); // -------- Settings-Gadgets -------- gui.addLabel( new GroupLabel( "Band Adjust", GroupLabel.ORIENT_HORIZONTAL, GroupLabel.BRACE_NONE )); ggNumBands = new JComboBox(); for( i = 2; i <= 9; i++ ) { ggNumBands.addItem( String.valueOf( i )); } con.gridwidth = 1; con.weightx = 0.1; gui.addLabel( new JLabel( "# of Bands", SwingConstants.RIGHT )); con.weightx = 0.4; gui.addChoice( ggNumBands, GG_NUMBANDS, il ); ggQuality = new JComboBox(); for( i = 0; i < QUAL_NAMES.length; i++ ) { ggQuality.addItem( QUAL_NAMES[ i ]); } con.weightx = 0.1; gui.addLabel( new JLabel( "Quality", SwingConstants.RIGHT )); con.weightx = 0.4; con.gridwidth = GridBagConstraints.REMAINDER; gui.addChoice( ggQuality, GG_QUALITY, il ); for( i = 0; i < 8; i++ ) { ggFreq = new ParamField( Constants.spaces[ Constants.absHzSpace ]); con.weightx = 0.1; con.gridwidth = 1; gui.addLabel( new JLabel( "CrossOver " + (i+1), SwingConstants.RIGHT )); con.weightx = 0.4; con.gridwidth = (i & 1) == 0 ? 1 : GridBagConstraints.REMAINDER; gui.addParamField( ggFreq, GG_FREQ1 + i, null ); } ggRollOff = new ParamField( Constants.spaces[ Constants.ratioFreqSpace ]); con.weightx = 0.1; con.gridwidth = 1; gui.addLabel( new JLabel( "RollOff", SwingConstants.RIGHT )); con.weightx = 0.4; gui.addParamField( ggRollOff, GG_ROLLOFF, null ); initGUI( this, FLAGS_PRESETS | FLAGS_PROGBAR, gui ); } public void fillGUI() { super.fillGUI(); super.fillGUI(gui); } public void fillPropertyArray() { super.fillPropertyArray(); super.fillPropertyArray(gui); } // -------- Processor Interface -------- protected void process() { int i, j, len, band, off, ch, chunkLength, chunkLength2; long progOff, progLen; double d1, d2; float f1; // io AudioFile inF = null; AudioFile[] outF; AudioFileDescr inStream; AudioFileDescr[] outStream; FloatFile[][] floatF = null; File[][] tempFile = null; // buffers float[] fftBuf1, fftBuf2; float[][] fftBuf; float[] convBuf1; float[] win; float[][] inBuf; float[][][] overBuf; int inChanNum, inLength, fftLength, inputLen; int framesRead, framesWritten; Param ampRef = new Param( 1.0, Param.ABS_AMP ); // transform-Referenz float gain = 1.0f; // gain abs amp float[] maxAmp; PathField ggOutput; int numPeriods; int halfWinSize, fltLength, overLen, skip; float[] crossFreqs, cosineFreqs; double freqNorm, freqBase, cosineNorm, cosineBase, rollOff; int numBands = pr.intg[ PR_NUMBANDS ] + 2; outF = new AudioFile[ numBands ]; outStream = new AudioFileDescr[ numBands ]; maxAmp = new float[ numBands ]; for( i = 0; i < numBands; i++ ) { outF[ i ] = null; outStream[ i ] = null; maxAmp[ i ] = 0.0f; } topLevel: try { // ---- open input, output ---- // input inF = AudioFile.openAsRead( new File( pr.text[ PR_INPUTFILE ])); inStream = inF.getDescr(); inChanNum = inStream.channels; inLength = (int) inStream.length; // this helps to prevent errors from empty files! if( (inLength * inChanNum) < 1 ) throw new EOFException( ERR_EMPTY ); // .... check running .... if( !threadRunning ) break topLevel; // output ggOutput = (PathField) gui.getItemObj( GG_OUTPUTFILE ); if( ggOutput == null ) throw new IOException( ERR_MISSINGPROP ); j = pr.text[ PR_OUTPUTFILE ].lastIndexOf( '.' ); if( j < 0 ) j = pr.text[ PR_OUTPUTFILE ].length(); for( i = 0; threadRunning && (i < numBands); i++ ) { outStream[i] = new AudioFileDescr( inStream ); ggOutput.fillStream( outStream[i] ); outStream[i].file = new File( pr.text[ PR_OUTPUTFILE ].substring( 0, j ) + (i+1) + pr.text[ PR_OUTPUTFILE ].substring( j )); outF[i] = AudioFile.openAsWrite( outStream[i] ); } // .... check running .... if( !threadRunning ) break topLevel; // ---- calculate filters ---- crossFreqs = new float[ numBands+1 ]; crossFreqs[0] = 0.0f; crossFreqs[numBands]= (float) (inStream.rate/2); for( i = 1; i < numBands; i++ ) { crossFreqs[i] = (float) pr.para[ PR_FREQ1 + (i-1) ].value; } cosineFreqs = new float[ numBands+1 ]; cosineFreqs[0] = 0.0f; rollOff = pr.para[ PR_ROLLOFF ].value /100; for( i = 1; i < numBands; i++ ) { d1 = Math.sqrt( crossFreqs[i-1] * crossFreqs[i] ) - crossFreqs[i-1]; // middle freq - lower freq d2 = Math.sqrt( crossFreqs[i] * crossFreqs[i+1] ) - crossFreqs[i]; cosineFreqs[i] = Math.max( 0.0f, (float) (Math.min( d1, d2 ) * rollOff )); } cosineFreqs[numBands] = 0.0f; numPeriods = 3 * (1 << pr.intg[ PR_QUALITY ]); halfWinSize = Math.max( 1, (int) ((double) numPeriods * inStream.rate / crossFreqs[1] + 0.5) ); freqNorm = Constants.PI2 / inStream.rate; cosineNorm = 4.0 / (Math.PI*Math.PI); fltLength = halfWinSize + halfWinSize; win = Filter.createFullWindow( fltLength, Filter.WIN_BLACKMAN ); j = fltLength + fltLength - 1; for( fftLength = 2; fftLength < j; fftLength <<= 1 ) ; inputLen = fftLength - fltLength + 1; overLen = fftLength - inputLen; fftBuf = new float[ numBands ][ fftLength + 2 ]; fftBuf1 = new float[ fftLength + 2 ]; fftBuf2 = new float[ fftLength + 2 ]; inBuf = new float[ inChanNum ][ inputLen ]; overBuf = new float[ inChanNum ][ numBands ][ overLen ]; // for( i = 0; i < inChanNum; i++ ) { // Util.clear( overBuf[ i ]); // } // LP = +1.0 fc -1.0 Zero // HP = +1.0 pi/2 -1.0 fc // BP = +1.0 fc2 -1.0 fc1 // calculate impulse response of the bandpasses for( i = 0; i < numBands; i++ ) { convBuf1 = fftBuf[ i ]; freqBase = freqNorm * crossFreqs[ i+1 ]; cosineBase = freqNorm * cosineFreqs[ i+1 ]; for( j = 1; j < halfWinSize; j++ ) { // sinc-filter d1 = (Math.sin( freqBase * j ) / (double) j); // raised cosine modulation d2 = cosineNorm * cosineBase * j * cosineBase * j; d1 *= (Math.cos( cosineBase * j ) / (1.0 - d2)); convBuf1[ halfWinSize + j ] = (float) d1; convBuf1[ halfWinSize - j ] = (float) d1; } convBuf1[ halfWinSize ] = (float) freqBase; freqBase = freqNorm * crossFreqs[ i ]; cosineBase = freqNorm * cosineFreqs[ i ]; for( j = 1; j < halfWinSize; j++ ) { d1 = (Math.sin( freqBase * j ) / (double) j); // raised cosine modulation d2 = cosineNorm * cosineBase * j * cosineBase * j; d1 *= (Math.cos( cosineBase * j ) / (1.0 - d2)); convBuf1[ halfWinSize + j ] -= (float) d1; convBuf1[ halfWinSize - j ] -= (float) d1; } convBuf1[ halfWinSize ] -= (float) freqBase; // zero padding for( j = fltLength; j < fftLength; j++ ) { convBuf1[ j ] = 0.0f; } // windowing Util.mult( win, 0, convBuf1, 0, fltLength ); Fourier.realTransform( convBuf1, fftLength, Fourier.FORWARD ); } // ---- parameter inits ---- progOff = 0; progLen = (long) inLength * (1 + numBands * inChanNum); tempFile = new File[ numBands ][ inChanNum ]; floatF = new FloatFile[ numBands ][ inChanNum ]; for( i = 0; i < numBands; i++ ) { for( ch = 0; ch < inChanNum; ch++ ) { // first zero them because an exception might be thrown tempFile[i][ch] = null; floatF[i][ch] = null; } } for( i = 0; i < numBands; i++ ) { for( ch = 0; ch < inChanNum; ch++ ) { tempFile[i][ch] = IOUtil.createTempFile(); floatF[i][ch] = new FloatFile( tempFile[i][ch], GenericFile.MODE_OUTPUT ); } } progLen += (long) inLength * numBands; // .... check running .... if( !threadRunning ) break topLevel; if( pr.intg[ PR_GAINTYPE ] == GAIN_ABSOLUTE ) { gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP, ampRef, null ).value / Math.PI); } // ----==================== the real stuff ====================---- framesRead = 0; framesWritten = 0; skip = halfWinSize; while( threadRunning && (framesWritten < inLength) ) { chunkLength = Math.min( inputLen, inLength - framesRead ); // ---- read input chunk ---- for( off = 0; threadRunning && (off < chunkLength); ) { len = Math.min( 8192, chunkLength - off ); inF.readFrames( inBuf, off, len ); framesRead += len; progOff += len; off += len; // .... progress .... setProgression( (float) progOff / (float) progLen ); } // .... check running .... if( !threadRunning ) break topLevel; chunkLength2 = Math.min( inputLen, inLength - framesWritten ); // ---- channels loop ----------------------------------------------------------------------- for( ch = 0; threadRunning && (ch < inChanNum); ch++ ) { System.arraycopy( inBuf[ ch ], 0, fftBuf1, 0, chunkLength ); for( i = chunkLength; i < fftLength; i++ ) { fftBuf1[ i ] = 0.0f; } Fourier.realTransform( fftBuf1, fftLength, Fourier.FORWARD ); // ---- bands loop ---------------------------------------------------------------------- for( band = 0; threadRunning && (band < numBands); band++ ) { Fourier.complexMult( fftBuf1, 0, fftBuf[ band ], 0, fftBuf2, 0, fftBuf1.length ); Fourier.realTransform( fftBuf2, fftLength, Fourier.INVERSE ); Util.add( overBuf[ ch ][ band ], 0, fftBuf2, 0, overLen ); // System.arraycopy( fftBuf2, inputLen, overBuf[ ch ][ band ], 0, overLen ); System.arraycopy( fftBuf2, chunkLength, overBuf[ ch ][ band ], 0, overLen ); for( off = skip; threadRunning && (off < chunkLength2); ) { len = Math.min( 8192, chunkLength2 - off ); floatF[ band ][ ch ].writeFloats( fftBuf2, off, len ); // check max amp for( i = off, j = off + len; i < j; i++ ) { f1 = Math.abs( fftBuf2[ i ]); if( f1 > maxAmp[band] ) { maxAmp[band] = f1; } } progOff += len; off += len; // .... progress .... setProgression( (float) progOff / (float) progLen ); } } } framesWritten += Math.max( 0, chunkLength2 - skip ); if( skip > 0 ) { skip = Math.max( 0, skip - chunkLength2 ); } } // until framesWritten == outLength // .... check running .... if( !threadRunning ) break topLevel; // ----==================== normalize output ====================---- if( (pr.intg[ PR_GAINTYPE ] == GAIN_UNITY) && !pr.bool[ PR_NORMEACH ]) { f1 = 0.0f; for( i = 0; i < numBands; i++ ) { f1 = Math.max( f1, maxAmp[i] ); } gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP, new Param( 1.0 / f1, Param.ABS_AMP ), null )).value; } for( band = 0; threadRunning && (band < numBands); band++ ) { if( (pr.intg[ PR_GAINTYPE ] == GAIN_UNITY) && pr.bool[ PR_NORMEACH ]) { gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP, new Param( 1.0 / maxAmp[ band ], Param.ABS_AMP ), null )).value; } maxAmp[ band ] *= gain; f1 = getProgression() + (1.0f - getProgression()) / (numBands - band); normalizeAudioFile( floatF[ band ], outF[ band ], inBuf, gain, f1 ); for( ch = 0; ch < inChanNum; ch++ ) { floatF[band][ch].cleanUp(); floatF[band][ch] = null; tempFile[band][ch].delete(); tempFile[band][ch] = null; } } // .... check running .... if( !threadRunning ) break topLevel; // ---- Finish ---- for( i = 0; i < numBands; i++ ) { outF[i].close(); outF[i] = null; outStream[i] = null; } inF.close(); inF = null; inStream = null; fftBuf1 = null; fftBuf2 = null; fftBuf = null; overBuf = null; // inform about clipping/ low level f1 = 0.0f; for( i = 0; i < numBands; i++ ) { f1 = Math.max( f1, maxAmp[ i ]); } handleClipping( f1 ); } catch( IOException e1 ) { setError( e1 ); } catch( OutOfMemoryError e2 ) { inStream = null; outStream = null; fftBuf1 = null; fftBuf2 = null; overBuf = null; fftBuf = null; convBuf1 = null; System.gc(); setError( new Exception( ERR_MEMORY )); } // ---- cleanup (topLevel) ---- if( inF != null ) { inF.cleanUp(); inF = null; } if( outF != null ) { for( i = 0; i < numBands; i++ ) { if( outF[i] != null ) { outF[i].cleanUp(); outF[i] = null; } } } if( floatF != null ) { for( i = 0; i < numBands; i++ ) { for( ch = 0; ch < floatF[i].length; ch++ ) { if( floatF[i][ch] != null ) { floatF[i][ch].cleanUp(); floatF[i][ch] = null; } if( tempFile[i][ch] != null ) { tempFile[i][ch].delete(); tempFile[i][ch] = null; } } } } } // process() protected void reflectPropertyChanges() { super.reflectPropertyChanges(); Component c; int i; int numBands = pr.intg[PR_NUMBANDS]; for (i = 0; i < 8; i++) { c = gui.getItemObj(GG_FREQ1 + i); if (c != null) { c.setEnabled(i <= numBands); } } } }