/* * SerialKillaDlg.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.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.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.text.MessageFormat; import java.util.Locale; /** * Serialism sucked and it's still there out in the world in * the heads of too many composers who think pitch is some * important quality of music. This module generates tracks * of three alternative parameters which can be used to * organize sound. */ public class SerialKillaDlg extends ModulePanel { // Properties (defaults) private static final int PR_INPUTFILE = 0; // pr.text private static final int PR_NOUTPUTFILE = 1; private static final int PR_TOUTPUTFILE = 2; private static final int PR_EOUTPUTFILE = 3; private static final int PR_NOUTPUTTYPE = 0; // pr.intg private static final int PR_NOUTPUTRES = 1; private static final int PR_TOUTPUTTYPE = 2; // pr.intg private static final int PR_TOUTPUTRES = 3; private static final int PR_EOUTPUTTYPE = 4; // pr.intg private static final int PR_EOUTPUTRES = 5; // private static final int PR_GAINTYPE = 6; private static final int PR_FRAMESIZE = 7; private static final int PR_OVERLAP = 8; // private static final int PR_GAIN = 0; // pr.para private static final int PR_OUTNOISE = 0; // pr.bool private static final int PR_OUTTILT = 1; private static final int PR_OUTENERGY = 2; private static final String PRN_INPUTFILE = "InputFile"; private static final String PRN_NOUTPUTFILE = "NOutputFile"; private static final String PRN_NOUTPUTTYPE = "NOutputType"; private static final String PRN_NOUTPUTRES = "NOutputReso"; private static final String PRN_TOUTPUTFILE = "TOutputFile"; private static final String PRN_TOUTPUTTYPE = "TOutputType"; private static final String PRN_TOUTPUTRES = "TOutputReso"; private static final String PRN_EOUTPUTFILE = "EOutputFile"; private static final String PRN_EOUTPUTTYPE = "EOutputType"; private static final String PRN_EOUTPUTRES = "EOutputReso"; private static final String PRN_OUTNOISE = "OutNoise"; private static final String PRN_OUTTILT = "OutTilt"; private static final String PRN_OUTENERGY = "OutEnergy"; private static final String PRN_FRAMESIZE = "FrameSize"; private static final String PRN_OVERLAP = "Overlap"; private static final String prText[] = { "", "", "", "" }; private static final String prTextName[] = { PRN_INPUTFILE, PRN_NOUTPUTFILE, PRN_TOUTPUTFILE, PRN_EOUTPUTFILE }; private static final int prIntg[] = { 0, 0, 0, 0, 0, 0, GAIN_UNITY, 5, 2 }; private static final String prIntgName[] = { PRN_NOUTPUTTYPE, PRN_NOUTPUTRES, PRN_TOUTPUTTYPE, PRN_TOUTPUTRES, PRN_EOUTPUTTYPE, PRN_EOUTPUTRES, PRN_GAINTYPE, PRN_FRAMESIZE, PRN_OVERLAP }; private static final boolean prBool[] = { true, false, false }; private static final String prBoolName[] = { PRN_OUTNOISE, PRN_OUTTILT, PRN_OUTENERGY }; // private static final Param prPara[] = { null }; // private static final String prParaName[] = { PRN_GAIN }; private static final int GG_INPUTFILE = GG_OFF_PATHFIELD + PR_INPUTFILE; private static final int GG_NOUTPUTFILE = GG_OFF_PATHFIELD + PR_NOUTPUTFILE; private static final int GG_NOUTPUTTYPE = GG_OFF_CHOICE + PR_NOUTPUTTYPE; private static final int GG_NOUTPUTRES = GG_OFF_CHOICE + PR_NOUTPUTRES; private static final int GG_TOUTPUTFILE = GG_OFF_PATHFIELD + PR_TOUTPUTFILE; private static final int GG_TOUTPUTTYPE = GG_OFF_CHOICE + PR_TOUTPUTTYPE; private static final int GG_TOUTPUTRES = GG_OFF_CHOICE + PR_TOUTPUTRES; private static final int GG_EOUTPUTFILE = GG_OFF_PATHFIELD + PR_EOUTPUTFILE; private static final int GG_EOUTPUTTYPE = GG_OFF_CHOICE + PR_EOUTPUTTYPE; private static final int GG_EOUTPUTRES = GG_OFF_CHOICE + PR_EOUTPUTRES; // private static final int GG_GAINTYPE = GG_OFF_CHOICE + PR_GAINTYPE; private static final int GG_FRAMESIZE = GG_OFF_CHOICE + PR_FRAMESIZE; private static final int GG_OVERLAP = GG_OFF_CHOICE + PR_OVERLAP; // private static final int GG_GAIN = GG_OFF_PARAMFIELD + PR_GAIN; private static final int GG_OUTNOISE = GG_OFF_CHECKBOX + PR_OUTNOISE; private static final int GG_OUTTILT = GG_OFF_CHECKBOX + PR_OUTTILT; private static final int GG_OUTENERGY = GG_OFF_CHECKBOX + PR_OUTENERGY; private static PropertyArray static_pr = null; private static Presets static_presets = null; private static final String ERR_NOOUTPUT = "No outputs checked!"; private static final String PTRN_NOISE = "Mean noise : {0,number,#,##0.0}%"; private static final String PTRN_TILT = "Mean tilt : {0,number,#,##0.0} Hz"; private static final String PTRN_ENERGY = "Mean energy : {0,number,#,##0.0} dB"; // -------- public methods -------- /** * !! setVisible() bleibt dem Aufrufer ueberlassen */ public SerialKillaDlg() { super("Serial Killer"); 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_GAIN ] = new Param( 0.0, Param.DECIBEL_AMP ); // static_pr.paraName = prParaName; static_pr.bool = prBool; static_pr.boolName = prBoolName; // static_pr.envl = prEnvl; // static_pr.envl[ PR_RATEMODENV ] = Envelope.createBasicEnvelope( Envelope.BASIC_TIME ); // static_pr.envl[ PR_RIGHTCHANMODENV ]= Envelope.createBasicEnvelope( Envelope.BASIC_TIME ); // static_pr.envlName = prEnvlName; // static_pr.superPr = DocumentFrame.static_pr; fillDefaultAudioDescr( static_pr.intg, PR_NOUTPUTTYPE ); // just the type fillDefaultAudioDescr( static_pr.intg, PR_TOUTPUTTYPE ); fillDefaultAudioDescr( static_pr.intg, PR_EOUTPUTTYPE ); static_presets = new Presets( getClass(), static_pr.toProperties( true )); } presets = static_presets; pr = (PropertyArray) static_pr.clone(); // -------- build GUI -------- GridBagConstraints con; PathField ggInputFile, ggNOutputFile, ggTOutputFile, ggEOutputFile; PathField[] ggInputs; JComboBox ggFrameSize, ggOverlap; JCheckBox ggOutNoise, ggOutTilt, ggOutEnergy; 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_OUTNOISE: case GG_OUTTILT: case GG_OUTENERGY: pr.bool[ ID - GG_OFF_CHECKBOX ] = ((JCheckBox) e.getSource()).isSelected(); reflectPropertyChanges(); break; } } }; // -------- Input-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 ); ggNOutputFile = new PathField( PathField.TYPE_OUTPUTFILE + PathField.TYPE_FORMATFIELD + PathField.TYPE_RESFIELD, "Select output file" ); ggNOutputFile.handleTypes( GenericFile.TYPES_SOUND ); ggInputs = new PathField[ 1 ]; ggInputs[ 0 ] = ggInputFile; ggNOutputFile.deriveFrom( ggInputs, "$D0$F0SKNoise$E" ); con.gridwidth = 1; con.weightx = 0.1; ggOutNoise = new JCheckBox( "Noise output" ); gui.addCheckbox( ggOutNoise, GG_OUTNOISE, il ); con.gridwidth = GridBagConstraints.REMAINDER; con.weightx = 0.9; gui.addPathField( ggNOutputFile, GG_NOUTPUTFILE, null ); gui.registerGadget( ggNOutputFile.getTypeGadget(), GG_NOUTPUTTYPE ); gui.registerGadget( ggNOutputFile.getResGadget(), GG_NOUTPUTRES ); ggTOutputFile = new PathField( PathField.TYPE_OUTPUTFILE + PathField.TYPE_FORMATFIELD + PathField.TYPE_RESFIELD, "Select output file" ); ggTOutputFile.handleTypes( GenericFile.TYPES_SOUND ); ggTOutputFile.deriveFrom( ggInputs, "$D0$F0SKTilt$E" ); con.gridwidth = 1; con.weightx = 0.1; ggOutTilt = new JCheckBox( "Tilt output" ); gui.addCheckbox( ggOutTilt, GG_OUTTILT, il ); con.gridwidth = GridBagConstraints.REMAINDER; con.weightx = 0.9; gui.addPathField( ggTOutputFile, GG_TOUTPUTFILE, null ); gui.registerGadget( ggTOutputFile.getTypeGadget(), GG_TOUTPUTTYPE ); gui.registerGadget( ggTOutputFile.getResGadget(), GG_TOUTPUTRES ); ggEOutputFile = new PathField( PathField.TYPE_OUTPUTFILE + PathField.TYPE_FORMATFIELD + PathField.TYPE_RESFIELD, "Select output file" ); ggEOutputFile.handleTypes( GenericFile.TYPES_SOUND ); ggEOutputFile.deriveFrom( ggInputs, "$D0$F0SKEnergy$E" ); con.gridwidth = 1; con.weightx = 0.1; ggOutEnergy = new JCheckBox( "Energy output" ); gui.addCheckbox( ggOutEnergy, GG_OUTENERGY, il ); con.gridwidth = GridBagConstraints.REMAINDER; con.weightx = 0.9; gui.addPathField( ggEOutputFile, GG_EOUTPUTFILE, null ); gui.registerGadget( ggEOutputFile.getTypeGadget(), GG_EOUTPUTTYPE ); gui.registerGadget( ggEOutputFile.getResGadget(), GG_EOUTPUTRES ); // 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, this ); // con.weightx = 0.5; // con.gridwidth = GridBagConstraints.REMAINDER; // gui.addChoice( (JComboBox) ggGain[ 1 ], GG_GAINTYPE, this ); // -------- Settings -------- gui.addLabel( new GroupLabel( "Settings", GroupLabel.ORIENT_HORIZONTAL, GroupLabel.BRACE_NONE )); ggFrameSize = new JComboBox(); for( int i = 32; i <= 32768; i <<= 1 ) { ggFrameSize.addItem( String.valueOf( i )); } con.weightx = 0.1; con.gridwidth = 1; gui.addLabel( new JLabel( "Frame size [smp]", SwingConstants.RIGHT )); con.weightx = 0.4; gui.addChoice( ggFrameSize, GG_FRAMESIZE, il ); ggOverlap = new JComboBox(); for( int i = 0; i < 8; i++ ) { ggOverlap.addItem( (1<<i) + "x" ); } con.weightx = 0.1; gui.addLabel( new JLabel( "Overlap", SwingConstants.RIGHT )); con.weightx = 0.4; con.gridwidth = GridBagConstraints.REMAINDER; gui.addChoice( ggOverlap, GG_OVERLAP, 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() { int i, j, k, m, ch, off; int len, chunkLength; long progOff, progLen; float f1, f2, f3; double d1, d4; // io AudioFile inF = null; AudioFile nOutF = null; AudioFile tOutF = null; AudioFile eOutF = null; AudioFileDescr inStream = null; AudioFileDescr nOutStream = null; AudioFileDescr tOutStream = null; AudioFileDescr eOutStream = null; // FloatFile[] floatF = null; // File[] tempFile = null; float[][] inBuf = null; float[][] nOutBuf = null; float[][] tOutBuf = null; float[][] eOutBuf = null; float[] convBuf1, fftBuf, weightBuf, window, wincorr, maxima; int[] maximaPos; int numMaxima; // Synthesize // float gain = 1.0f; // gain abs amp // Param ampRef = new Param( 1.0, Param.ABS_AMP ); // transform-Referenz // Smp Init int inLength, inChanNum, outLength, outChanNum; int framesRead, framesWritten; int fftLength, frameLength, winStep; // float maxAmp = 0.0f; // float winEnergy; double totalTilt, totalNoise, totalEnergy; boolean outNoise, outTilt, outEnergy; MessageFormat msgForm; Object[] msgArgs = new Object[1]; PathField ggOutput; topLevel: try { // ---- open input, output; init ---- // 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; outChanNum = inChanNum; outNoise = pr.bool[ PR_OUTNOISE ]; outTilt = pr.bool[ PR_OUTTILT ]; outEnergy = pr.bool[ PR_OUTENERGY ]; if( !outNoise && !outTilt && !outEnergy ) throw new IOException( ERR_NOOUTPUT ); // output if( outNoise ) { ggOutput = (PathField) gui.getItemObj( GG_NOUTPUTFILE ); if( ggOutput == null ) throw new IOException( ERR_MISSINGPROP ); nOutStream = new AudioFileDescr( inStream ); nOutStream.channels = outChanNum; ggOutput.fillStream( nOutStream ); nOutF = AudioFile.openAsWrite( nOutStream ); // .... check running .... if( !threadRunning ) break topLevel; } if( outTilt ) { ggOutput = (PathField) gui.getItemObj( GG_TOUTPUTFILE ); if( ggOutput == null ) throw new IOException( ERR_MISSINGPROP ); tOutStream = new AudioFileDescr( inStream ); tOutStream.channels = outChanNum; ggOutput.fillStream( tOutStream ); tOutF = AudioFile.openAsWrite( tOutStream ); // .... check running .... if( !threadRunning ) break topLevel; } if( outEnergy ) { ggOutput = (PathField) gui.getItemObj( GG_EOUTPUTFILE ); if( ggOutput == null ) throw new IOException( ERR_MISSINGPROP ); eOutStream = new AudioFileDescr( inStream ); eOutStream.channels = outChanNum; ggOutput.fillStream( eOutStream ); eOutF = AudioFile.openAsWrite( eOutStream ); // .... check running .... if( !threadRunning ) break topLevel; } frameLength = 32 << pr.intg[ PR_FRAMESIZE ]; fftLength = frameLength << 1; winStep = frameLength >> pr.intg[ PR_OVERLAP ]; numMaxima = frameLength >> 7; outLength = (inLength + winStep - 1) / winStep; inBuf = new float[ inChanNum ][ frameLength ]; nOutBuf = new float[ outChanNum ][ 8 ]; // XXX tOutBuf = new float[ outChanNum ][ 8 ]; // XXX eOutBuf = new float[ outChanNum ][ 8 ]; // XXX fftBuf = new float[ fftLength + 2 ]; window = Filter.createFullWindow( frameLength, Filter.WIN_HAMMING ); wincorr = new float[ frameLength ]; maxima = new float[ numMaxima ]; maximaPos = new int[ numMaxima ]; totalTilt = 0.0; totalNoise = 0.0; totalEnergy = 0.0; // Fenster muss aus Autokorr. rausgerechnet werden System.arraycopy( window, 0, fftBuf, 0, frameLength ); for( i = frameLength; i < fftLength; ) { fftBuf[ i++ ] = 0.0f; } Fourier.realTransform( fftBuf, fftLength, Fourier.FORWARD ); d1 = 0.0; for( i = 0, k = 0; i <= fftLength; ) { j = i++; f1 = (fftBuf[ j ]*fftBuf[ j ] + fftBuf[ i ]*fftBuf[ i ]); fftBuf[ j ] = f1; d1 += f1; // fftBuf[ j ] = (fftBuf[ j ]*fftBuf[ j ] + fftBuf[ i ]*fftBuf[ i ]) * weightBuf[ k++ ]; fftBuf[ i++ ] = 0.0f; } // winEnergy = (float) Math.sqrt( d1 ); Fourier.realTransform( fftBuf, fftLength, Fourier.INVERSE ); Util.mult( fftBuf, 0, frameLength, 1.0f / fftBuf[0] ); f1 = fftBuf[ 0 ]; for( i = 1; i < frameLength; i++ ) { f1 = ((float) (frameLength - i) / (float) frameLength) / fftBuf[ i ]; if( f1 > 500f ) break; // begins to oscillate wild wincorr[i] = f1; } for( ; i < frameLength; i++ ) { wincorr[i] = 500f; } //Debug.view( wincorr, "win corr" ); // calc dB(A) weighting factors weightBuf = new float[ frameLength + 1 ]; f1 = (float) inStream.rate / 2; for( i = 0; i <= frameLength; i++ ) { weightBuf[ i ] = (float) i / (float) frameLength * f1; } Filter.getDBAweights( weightBuf, weightBuf, frameLength + 1 ); for( i = 0; i <= frameLength; i++ ) { weightBuf[ i ] *= weightBuf[ i ]; // squared to be used directly in autocorrelation formula } // initialize various stuff progOff = 0; progLen = (long) inLength + (long) outLength; // normalization requires temp files // if( pr.intg[ PR_GAINTYPE ] == GAIN_UNITY ) { // tempFile = new File[ outChanNum ]; // floatF = new FloatFile[ outChanNum ]; // for( ch = 0; ch < outChanNum; ch++ ) { // first zero them because an exception might be thrown // tempFile[ ch ] = null; // floatF[ ch ] = null; // } // for( ch = 0; ch < outChanNum; ch++ ) { // tempFile[ ch ] = IOUtil.createTempFile(); // floatF[ ch ] = new FloatFile( tempFile[ ch ], FloatFile.MODE_OUTPUT ); // } // progLen += (long) outLength; // } // if( pr.intg[ PR_GAINTYPE ] == GAIN_ABSOLUTE ) { // gain = (float) ((Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP, ampRef, null )).value); //gain = 1.0f; // } // // .... check running .... // if( !threadRunning ) break topLevel; // ----==================== core ====================---- // // How it works: overlapped FFT-frames read in ---> autocorrelation calculated + normalized // 24 biggest local maxima picked out // areas between neighbouring maxima calculated (triangular interpolation) // 1.0 - ratio between area and max. area calculated = degree of noise // needs smoothing? framesWritten = 0; framesRead = 0; off = 0; while( threadRunning && (framesWritten < outLength) ) { // ==================== read input chunk ==================== len = Math.min( inLength - framesRead, frameLength - off ); chunkLength = len + off; inF.readFrames( inBuf, off, len ); framesRead += len; progOff += len; // .... progress .... setProgression( (float) progOff / (float) progLen ); // .... check running .... if( !threadRunning ) break topLevel; // zero-padding last chunk if( chunkLength < frameLength ) { for( ch = 0; ch < inChanNum; ch++ ) { convBuf1 = inBuf[ ch ]; for( i = chunkLength; i < frameLength; i++ ) { convBuf1[ i ] = 0.0f; } } } for( ch = 0; ch < inChanNum; ch++ ) { convBuf1 = inBuf[ ch ]; System.arraycopy( convBuf1, 0, fftBuf, 0, frameLength ); Util.mult( window, 0, fftBuf, 0, frameLength ); for( i = frameLength; i < fftLength; ) { fftBuf[ i++ ] = 0.0f; } Fourier.realTransform( fftBuf, fftLength, Fourier.FORWARD ); d1 = 0.0; // d2 = 0.0; d4 = 0.0; // Autocorrelation (a + ib) * (a - ib) for( i = 0, k = 0; i <= fftLength; k++ ) { j = i++; // fftBuf[ j ] = (fftBuf[ j ]*fftBuf[ j ] + fftBuf[ i ]*fftBuf[ i ]); f1 = (fftBuf[ j ]*fftBuf[ j ] + fftBuf[ i ]*fftBuf[ i ]) * weightBuf[ k ]; d4 += f1; if( outTilt ) { d1 += f1 * k; } fftBuf[ j ] = f1; fftBuf[ i++ ] = 0.0f; } //if( framesWritten == 0 ) System.out.println( "d1 "+d1+"; d2 "+d2 ); // d4 = Math.sqrt( d4 ) / frameLength; // ---------- Tilt ---------- if( outTilt ) { if( d4 > 0.0 ) { f1 = (float) (d1 / (d4 * frameLength)); // XXX logarithmische korrektur XXX } else { f1 = 0.5f; } tOutBuf[ ch ][ 0 ] = f1; totalTilt += f1; } // ---------- Energy ---------- if( outEnergy ) { f1 = Math.min( 1.0f, (float) (Math.sqrt( d4 ) / frameLength) ); // RMS (nach Parseval) eOutBuf[ ch ][ 0 ] = f1; totalEnergy += f1; } // ---------- Noise ---------- if( outNoise ) { Fourier.realTransform( fftBuf, fftLength, Fourier.INVERSE ); f1 = fftBuf[0]; if( f1 > 0.0f ) { Util.mult( fftBuf, 0, frameLength, 1.0f / f1 ); Util.mult( wincorr, 0, fftBuf, 0, frameLength ); //if( (framesWritten == 0) && (ch == 0) ) { // float[] test = new float[ frameLength ]; // System.arraycopy( fftBuf, 0, test, 0, frameLength ); // Debug.view( test, "AutoCorr" ); //} Util.clear( maxima ); for( i = 0; i < numMaxima; i++ ) { maximaPos[ i ] = frameLength; } fftBuf[ fftLength ] = 0f; // last sample is allowed to be local maximum f2 = 1.1f; d1 = 0.0; for( i = 0; i < frameLength; i++ ) { f3 = fftBuf[i]; if( (f3 > f2) && (f3 > fftBuf[i+1]) && (f3 > 0.0f) ) { // trace local maxima contour if( f3 > maxima[0] ) { for( j = 1; j < numMaxima; j++ ) { if( f3 <= maxima[j] ) break; } j--; for( k = 0; k < j; k++ ) { maxima[k] = maxima[k+1]; maximaPos[k] = maximaPos[k+1]; } maxima[j] = f3; maximaPos[j] = i; } // d1 += (f3 + f1) / 2.0f * (i - j); // linear area interpolation // f1 = f3; // j = i; } f2 = f3; } //System.out.println( "----Maxima----" ); //for( i = 0; i < numMaxima; i++ ) { // System.out.println( " "+i+" : "+maximaPos[i]+" = "+maxima[i]); //} //System.out.println( "max.[0] = "+maxima[0]+" @ "+ maximaPos[0] + " ---> "+(maxima[0] / 2.0f * (frameLength - maximaPos[0]))); d1 += maxima[0] / 2.0f * (frameLength - maximaPos[0]); // "kleinstes" Maximum bis zum Ende interpolieren // ; damit auch Funktionen wie hochfreq. Sinus // nicht unterbewertet werden, sondern das // Autokorr.-Dreieck quasi fortgesetzt wird f1 = 1.0f; j = 0; do { m = -1; k = frameLength; for( i = 0; i < numMaxima; i++ ) { // chronologisch naechstes max finden if( maximaPos[i] < k ) { k = maximaPos[i]; m = i; } } if( m < 0 ) break; d1 += (f1 + maxima[m]) / 2.0f * (maximaPos[m] - j); // linear area interpolation j = maximaPos[m]; f1 = maxima[m]; maximaPos[m] = frameLength; // raus aus dem spiel } while( true ); f1 = 1.13f - ((float) d1 * 2.1f / frameLength); // Erfahrungswerte ;-) f1 = Math.min( 1.0f, Math.max( 0.0f, f1 * f1 )); } else { f1 = 0.0f; } //if( (framesWritten == 0) && (ch == 0) ) System.out.println( "f1 = "+f1 ); // nOutBuf[ ch ][ 0 ] = f1 * gain; nOutBuf[ ch ][ 0 ] = f1; totalNoise += f1; } // if( outNoise ) } // for( channels ) // ----- write output ----- if( outTilt ) { tOutF.writeFrames( tOutBuf, 0, 1 ); } if( outNoise ) { nOutF.writeFrames( nOutBuf, 0, 1 ); } if( outEnergy ) { eOutF.writeFrames( eOutBuf, 0, 1 ); } framesWritten++; progOff++; // .... progress .... setProgression( (float) progOff / (float) progLen ); // .... check running .... if( !threadRunning ) break topLevel; // ----- buffer rotation ----- off = frameLength - winStep; for( ch = 0; ch < inChanNum; ch++ ) { System.arraycopy( inBuf[ ch ], winStep, inBuf[ ch ], 0, off ); } } // while( framesWritten < outLength ) // .... check running .... if( !threadRunning ) break topLevel; // ---- clean up, normalize ---- if( outNoise ) { msgArgs[0] = new Double( totalNoise / (outLength * outChanNum) * 100 ); msgForm = new MessageFormat( PTRN_NOISE ); msgForm.setLocale( Locale.US ); msgForm.applyPattern( PTRN_NOISE ); System.out.println( msgForm.format( msgArgs ) ); } if( outTilt ) { msgArgs[0] = new Double( totalTilt / (outLength * outChanNum) * (inStream.rate/2) ); msgForm = new MessageFormat( PTRN_TILT ); msgForm.setLocale( Locale.US ); msgForm.applyPattern( PTRN_TILT ); System.out.println( msgForm.format( msgArgs ) ); } if( outEnergy ) { msgArgs[0] = new Double( 20 * Math.log( totalEnergy / (outLength * outChanNum) ) / Constants.ln10 ); msgForm = new MessageFormat( PTRN_ENERGY ); msgForm.setLocale( Locale.US ); msgForm.applyPattern( PTRN_ENERGY ); System.out.println( msgForm.format( msgArgs ) ); } inF.close(); inF = null; inStream = null; // if( pr.intg[ PR_GAINTYPE ] == GAIN_UNITY ) { // gain = (float) (Param.transform( pr.para[ PR_GAIN ], Param.ABS_AMP, // new Param( 1.0 / (double) maxAmp, Param.ABS_AMP ), null )).value; // // normalizeAudioFile( floatF, nOutF, inBuf, gain, 1.0f ); // for( ch = 0; ch < outChanNum; ch++ ) { // floatF[ ch ].cleanUp(); // floatF[ ch ] = null; // tempFile[ ch ].delete(); // tempFile[ ch ] = null; // } // maxAmp *= gain; // } if( nOutF != null ) { nOutF.close(); nOutF = null; } if( tOutF != null ) { tOutF.close(); tOutF = null; } if( eOutF != null ) { eOutF.close(); eOutF = null; } // ---- Finish ---- // inform about clipping/ low level // handleClipping( maxAmp ); } catch( IOException e1 ) { setError( e1 ); } catch( OutOfMemoryError e2 ) { inStream = null; nOutStream = null; tOutStream = null; inBuf = null; nOutBuf = null; tOutBuf = null; eOutBuf = null; fftBuf = null; weightBuf = null; window = null; wincorr = null; System.gc(); setError( new Exception( ERR_MEMORY )); } // ---- cleanup (topLevel) ---- if( inF != null ) { inF.cleanUp(); } if( nOutF != null ) { nOutF.cleanUp(); } if( tOutF != null ) { tOutF.cleanUp(); } if( eOutF != null ) { eOutF.cleanUp(); } // if( floatF != null ) { // for( ch = 0; ch < floatF.length; ch++ ) { // if( floatF[ ch ] != null ) floatF[ ch ].cleanUp(); // if( tempFile[ ch ] != null ) tempFile[ ch ].delete(); // } // } } // process() // -------- private methods -------- protected void reflectPropertyChanges() { super.reflectPropertyChanges(); Component c; c = gui.getItemObj( GG_NOUTPUTFILE ); if( c != null ) { c.setEnabled( pr.bool[ PR_OUTNOISE ]); } c = gui.getItemObj( GG_TOUTPUTFILE ); if( c != null ) { c.setEnabled( pr.bool[ PR_OUTTILT ]); } c = gui.getItemObj( GG_EOUTPUTFILE ); if( c != null ) { c.setEnabled( pr.bool[ PR_OUTENERGY ]); } } }