/* * ExtrapolateOp.java * (FScape) * * Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved. * * This software is published under the GNU General Public License v3+ * * * For further information, please contact Hanns Holger Rutz at * contact@sciss.de */ package de.sciss.fscape.op; import de.sciss.fscape.gui.FIRDesignerDlg; import de.sciss.fscape.gui.GroupLabel; import de.sciss.fscape.gui.OpIcon; import de.sciss.fscape.gui.PropertyGUI; import de.sciss.fscape.prop.OpPrefs; import de.sciss.fscape.prop.Prefs; import de.sciss.fscape.prop.Presets; import de.sciss.fscape.prop.PropertyArray; import de.sciss.fscape.spect.SpectFrame; import de.sciss.fscape.spect.SpectStream; import de.sciss.fscape.spect.SpectStreamSlot; import de.sciss.fscape.util.Constants; import de.sciss.fscape.util.Param; import de.sciss.fscape.util.Slots; import java.io.EOFException; import java.io.IOException; public class ExtrapolateOp extends Operator { // -------- private variables -------- protected static final String defaultName = "Extrapolate"; protected static Presets static_presets = null; protected static Prefs static_prefs = null; protected static PropertyArray static_pr = null; // Slots protected static final int SLOT_INPUT = 0; protected static final int SLOT_OUTPUT = 1; // Properties (defaults) private static final int PR_LOFREQ = 0; // pr.para private static final int PR_HIFREQ = 1; // private static final int PR_QUALITY = 0; // pr.intg private static final String PRN_HIFREQ = "HiFreq"; private static final String PRN_LOFREQ = "LoFreq"; private static final String PRN_QUALITY = "Quality"; private static final int prIntg[] = { FIRDesignerDlg.QUAL_MEDIUM }; private static final String prIntgName[] = { PRN_QUALITY }; private static final Param prPara[] = { null, null }; private static final String prParaName[] = { PRN_LOFREQ, PRN_HIFREQ }; protected static final String ERR_BANDS = "Band# not power of 2"; // -------- public methods -------- // public Container createGUI( int type ); public ExtrapolateOp() { super(); // initialize only in the first instance // preferences laden if( static_prefs == null ) { static_prefs = new OpPrefs( getClass(), getDefaultPrefs() ); } // propertyarray defaults if( static_pr == null ) { static_pr = new PropertyArray(); static_pr.intg = prIntg; static_pr.intgName = prIntgName; static_pr.para = prPara; static_pr.para[ PR_HIFREQ ] = new Param( 440.0, Param.ABS_HZ ); static_pr.para[ PR_LOFREQ ] = new Param( 0.0, Param.ABS_HZ ); static_pr.paraName = prParaName; static_pr.superPr = Operator.op_static_pr; } // default preset if( static_presets == null ) { static_presets = new Presets( getClass(), static_pr.toProperties( true )); } // superclass-Felder uebertragen opName = "ExtrapolateOp"; prefs = static_prefs; presets = static_presets; pr = (PropertyArray) static_pr.clone(); // slots slots.addElement( new SpectStreamSlot( this, Slots.SLOTS_READER )); // SLOT_INPUT slots.addElement( new SpectStreamSlot( this, Slots.SLOTS_WRITER )); // SLOT_OUTPUT // icon // XXX icon = new OpIcon( this, OpIcon.ID_FLIPFREQ, defaultName ); } // -------- Runnable methods -------- public void run() { runInit(); // superclass // Haupt-Variablen fuer den Prozess int ch, i, j; float f1, f2; SpectStreamSlot runInSlot; SpectStreamSlot runOutSlot; SpectStream runInStream = null; SpectStream runOutStream; SpectFrame runInFr = null; SpectFrame runOutFr = null; // Ziel-Frame Berechnung int srcBands, lpCoeffNum; float loFreq, hiFreq, freqSpacing; float[] lpCoeffBuf, convBuf1, convBuf2, convBuf3; float[][] lpBuf; int loBand, hiBand; topLevel: try { // for( i = 0; i < 8; i++ ) { // test[ i ] = (rnd.nextFloat() * 4.0f) - 2.0f; // System.out.println( "o"+i+" = "+test[i] ); // } // ------------------------------ Input-Slot ------------------------------ runInSlot = slots.elementAt( SLOT_INPUT ); if( runInSlot.getLinked() == null ) { runStop(); // threadDead = true -> folgendes for() wird uebersprungen } // diese while Schleife ist noetig, da beim initReader ein Pause eingelegt werden kann // und die InterruptException ausgeloest wird; danach versuchen wir es erneut for( boolean initDone = false; !initDone && !threadDead; ) { try { runInStream = runInSlot.getDescr(); // throws InterruptedException initDone = true; } catch( InterruptedException ignored) {} runCheckPause(); } if( threadDead ) break topLevel; // ------------------------------ Output-Slot ------------------------------ runOutSlot = slots.elementAt( SLOT_OUTPUT ); runOutStream = new SpectStream( runInStream ); runOutSlot.initWriter( runOutStream ); // ------------------------------ Vorberechnungen ------------------------------ freqSpacing = (runInStream.hiFreq - runInStream.loFreq) / runInStream.bands; srcBands = runInStream.bands; // srcSize = srcBands << 1; lpBuf = new float[ 2 ][ srcBands ]; loFreq = Math.min( runInStream.smpRate / 2, (float) pr.para[ PR_LOFREQ ].value); hiFreq = Math.max( 0.5f, Math.min( runInStream.smpRate / 2, (float) pr.para[ PR_HIFREQ ].value)); if( loFreq > hiFreq ) { f1 = loFreq; loFreq = hiFreq; hiFreq = f1; } loBand = (int) ((loFreq - runInStream.loFreq) / freqSpacing + 0.5f); hiBand = (int) ((hiFreq - runInStream.loFreq) / freqSpacing + 0.5f); lpCoeffNum = Math.min( 64, hiBand - loBand ); lpCoeffBuf = new float[ lpCoeffNum ]; // System.out.println( "SrcSize "+srcSize+"; loBand "+loBand+"; hiBand "+hiBand+"; lpCoeffNum "+lpCoeffNum ); // ------------------------------ Hauptschleife ------------------------------ runSlotsReady(); mainLoop: while( !threadDead ) { // ---------- Frame einlesen ---------- for( boolean readDone = false; (!readDone) && !threadDead; ) { try { runInFr = runInSlot.readFrame(); // throws InterruptedException readDone = true; runOutFr = runOutStream.allocFrame(); } catch( InterruptedException ignored) {} catch( EOFException e ) { break mainLoop; } runCheckPause(); } if( threadDead ) break mainLoop; // ---------- Process: Ziel-Frame berechnen ---------- for( ch = 0; ch < runOutStream.chanNum; ch++ ) { convBuf1 = runInFr.data[ ch ]; convBuf2 = lpBuf[ 0 ]; convBuf3 = lpBuf[ 1 ]; // for( i = loBand << 1, j = loBand; j < hiBand; ) { for( i = 0, j = 0; j < srcBands; ) { f2 = convBuf1[ i++ ]; // amp f1 = convBuf1[ i++ ]; // phase convBuf2[ j ] = f2 * (float) Math.cos( f1 ); // real convBuf3[ j++ ] = f2 * (float) Math.sin( f1 ); // imag } for( i = 0; i < 2; i++ ) { convBuf1 = lpBuf[ i ]; lpCoeffs( convBuf1, loBand, hiBand - loBand, lpCoeffBuf, lpCoeffNum ); // fixRoots( lpCoeffBuf, lpCoeffNum ); linearPrediction2( convBuf1, loBand, hiBand - loBand, lpCoeffBuf, lpCoeffNum, convBuf1, hiBand, srcBands - hiBand ); // XXX lo freq reverse lp } convBuf1 = runOutFr.data[ ch ]; convBuf2 = lpBuf[ 0 ]; convBuf3 = lpBuf[ 1 ]; for( i = 0, j = 0; j < srcBands; ) { f1 = convBuf2[ j ]; // real f2 = convBuf3[ j++ ]; // imag convBuf1[ i++ ] = complexAbs( f1, f2 ); // amp convBuf1[ i++ ] = (float) Math.atan2( f2, f1 ); // phase } } // calculation done runInSlot.freeFrame( runInFr ); for( boolean writeDone = false; (!writeDone) && !threadDead; ) { try { // Unterbrechung runOutSlot.writeFrame( runOutFr ); // throws InterruptedException writeDone = true; runFrameDone( runOutSlot, runOutFr ); runOutStream.freeFrame( runOutFr ); } catch( InterruptedException e ) {} // mainLoop wird eh gleich verlassen runCheckPause(); } } // end of main loop runInStream.closeReader(); runOutStream.closeWriter(); } // break topLevel catch( IOException e ) { runQuit( e ); return; } catch( SlotAlreadyConnectedException e ) { runQuit( e ); return; } // catch( OutOfMemoryError e ) { // abort( e ); // return; // } runQuit( null ); } // ---- predic routine from NR paragraph 13.6 ---- /* * Given data[dataOff...dataOff+dataLen-1] (!!), and given the data's LP coefficients d[0...m-1] (!!), this routine applies * equation (13.6.11) to predict the next nfut data points, which it returns in the array * future[futOff...futOff+futLen-1] (!!). Note that the routine references only the last m values of data, as initial * values for the prediction. */ // public static void predic(float data[], int ndata, float d[], int m, float future[], int nfut) public static void linearPrediction( float[] data, int dataOff, int dataLen, float[] coeffBuf, int coeffNum, float[] future, int futOff, int futLen ) { int i, j, k; float sum; // discrp; float[] reg = new float[ coeffNum ]; for( j = 0, k = dataOff + dataLen; j < coeffNum; ) { reg[ j++ ] = data[ --k ]; } for( j = futOff, i = futOff + futLen; j < i; j++ ) { // discrp = 0.0f; // This is where you would put in a known discrepancy if you were reconstructing a // function by linear predictive coding rather than extrapolating a function by linear prediction. // See text. sum = 0.0f; // discrp; for( k = 0; k < coeffNum; k++ ) { sum += coeffBuf[k] * reg[k]; } System.arraycopy( reg, 0, reg, 1, coeffNum-1 ); // [If you want to implement circular arrays, you can avoid this shifting of coefficients.] reg[0] = sum; future[j] = sum; } } public static void linearPrediction2( float[] data, int dataOff, int dataLen, float[] coeffBuf, int coeffNum, float[] future, int futOff, int futLen ) { int i, j, k; float sum; // discrp; float[] reg = new float[ coeffNum ]; float f1 = 1.0f; for( j = 0, k = dataOff + dataLen; j < coeffNum; ) { reg[ j++ ] = data[ --k ]; } for( j = futOff, i = futOff + futLen; j < i; j++ ) { // discrp = 0.0f; // This is where you would put in a known discrepancy if you were reconstructing a // function by linear predictive coding rather than extrapolating a function by linear prediction. // See text. sum = 0.0f; // discrp; for( k = 0; k < coeffNum; k++ ) { sum += coeffBuf[k] * reg[k]; } System.arraycopy( reg, 0, reg, 1, coeffNum-1 ); // [If you want to implement circular arrays, you can avoid this shifting of coefficients.] f1 = Math.min( 16f, f1 * 0.99f + 0.01f * Math.abs( future[j] ) / Math.max( 1.0e-6f, Math.abs( sum ))); future[j] = f1 * sum; reg[0] = f1 * sum; } } // ---- memcof routine from NR paragraph 13.6 ---- /* * Given a real vector of data[dataOff...dataOff+dataLen-1] (!!), and given m, this routine returns m linear prediction * coefficients as coeffBuf[0...m-1] (!!), and returns the mean square discrepancy as xms. */ // public static void memcof( float data[], int n, int m, float *xms, float d[]) protected static float lpCoeffs( float[] data, int dataOff, int dataLen, float[] coeffBuf, int coeffNum ) { int i, j, k; float f; float[] wk1 = new float[ dataLen-1 ]; float[] wk2 = new float[ dataLen-1 ]; float[] wkm = new float[ coeffNum-1 ]; float xms, num, denom; for( j = dataLen, i = dataLen + dataOff, f = 0.0f; j < i; j++ ) { f += data[j]*data[j]; } xms = f / dataLen; wk1[0] = data[0]; wk2[dataLen-2] = data[dataLen-1]; System.arraycopy( data, dataOff, wk1, 0, dataLen-1 ); System.arraycopy( data, dataOff+1, wk2, 0, dataLen-1 ); for( k = 0;; ) { num = 0.0f; denom = 0.0f; for( j = 0, i = dataLen - k - 1; j < i; j++ ) { num += wk1[j]*wk2[j]; denom += wk1[j]*wk1[j] + wk2[j]*wk2[j]; } if( denom > 0.0f ) { f = 2.0f * num / denom; } else { f = 1.0f; } coeffBuf[k] = f; xms *= 1.0f - f*f; for( i = 0; i < k; i++ ) { coeffBuf[i] = wkm[i] - f * wkm[k-i-1]; } // The algorithm is recursive, building up the answer for larger and larger values of m // until the desired value is reached. At this point in the algorithm, one could return // the vector d and scalar xms for a set of LP coefficients with k (rather than m) terms. if( ++k == coeffNum ) return xms; // !! k increased here for efficiency System.arraycopy( coeffBuf, 0, wkm, 0, k ); for( j = 0, i = dataLen - k - 1; j < i; j++ ) { wk1[j] -= f * wk2[j]; wk2[j] = wk2[j+1] - f * wk1[j+1]; } } } // ---- fixrts routine from NR paragraph 13.6 ---- /* * Given the LP coefficients d[0...m-1] (!!), this routine finds all roots of the characteristic polynomial * (13.6.14), reflects any roots that are outside the unit circle back inside, and then returns a * modified set of coefficients d[0...m-1]. */ protected static void fixRoots( float coeffBuf[], int coeffNum ) { int i, j, coeffNum2; float rootsRe, rootsIm, f1; coeffNum2 = coeffNum << 1; float[] a = new float[ coeffNum2 + 2 ]; float[] roots = new float[ coeffNum2 ]; float[] cmplxRes= new float[ 2 ]; a[ coeffNum2 ] = 1.0f; a[ coeffNum2+1 ] = 0.0f; for( i = 0, j = coeffNum2; j > 0; ) { // Set up complex coefficients for polynomial root finder. a[ --j ] = 0.0f; a[ --j ] = -coeffBuf[ i++ ]; } zRoots( a, coeffNum, roots, true ); // Find all the roots. for( j = 0; j < coeffNum2; j += 2 ) { // Look for a... f1 = complexAbs( roots[j], roots[j+1] ); if( f1 > 1.0f ) { // 1.0f // root outside the unit circle, // pull back on unit circle // roots[j] *= 0.0f / f1; // roots[j+1] *= 0.0f / f1; // alternative: reflection complexDiv( 1.0f, 0.0f, roots[ j ], -roots[ j+1 ], cmplxRes ); roots[ j ] = cmplxRes[0]; roots[ j+1 ] = cmplxRes[1]; } } a[0] = -roots[0]; a[1] = -roots[1]; a[2] = 1.0f; a[3] = 0.0f; // Now reconstruct the polynomial coefficients, for( j = 2; j < coeffNum2; j += 2 ) { // by looping over the roots a[ j+2 ] = 1.0f; a[ j+3 ] = 0.0f; rootsRe = roots[j]; rootsIm = roots[j+1]; for( i = j; i >= 2; i -= 2 ) { // and synthetically multiplying. a[i] = a[i-2] - (rootsRe * a[i] - rootsIm * a[i+1]); a[i+1] = a[i-1] - (rootsIm * a[i] + rootsRe * a[i+1]); } a[0] = -rootsRe * a[0] + rootsIm * a[1]; a[1] = -rootsIm * a[0] - rootsRe * a[1]; } for( i = coeffNum, j = 0; j < coeffNum2; j += 2 ) { // The polynomial coefficients are guaranteed to be real, so we need only return the real part as new LP coefficients. coeffBuf[ --i ] = -a[j]; } } // ---- zroots routine from NR paragraph 9.5 ---- protected static final float EXPECTEDERROR2 = 4.0e-6f; /* * Given the degree m and the m+1 complex coefficients a[0...m*2] of the polynomial (?) i=0...m(a[i]x^i), * this routine successively calls laguer and finds all m complex roots in roots[0...(m-1)*2] (!!). The * boolean variable polish should be input as true if polishing (also by Laguerre's method) * is desired, false if the roots will be subsequently polished by other means. */ protected static void zRoots( float[] coeffBuf, int coeffNum, float[] roots, boolean polish ) { int i, j, jj; float bRe,bIm, cRe,cIm; int coeffNum2 = coeffNum << 1; float[] ad = new float[ coeffNum2 + 2 ]; float[] x = new float[ 2 ]; System.arraycopy( coeffBuf, 0, ad, 0, coeffNum2 + 2 ); // Copy of coefficients for successive deflation. for( j = coeffNum2; j >= 2; j -= 2 ) { // Loop over each root to be found. jj = j - 2; // Start at zero to favor convergence to smallest remaining root, and find the root. x[0] = 0.0f; x[1] = 0.0f; /* i = */ laguerre( ad, j >> 1, x ); // if( i == 0 ) { //System.out.println( "retrying complex" ); // x[0] = 0.0f; // x[1] = 0.5f; // try complex // laguerre( ad, j >> 1, x ); // } if( Math.abs( x[1] ) <= EXPECTEDERROR2 * Math.abs( x[0] )) { x[1] = 0.0f; } roots[ jj ] = x[0]; roots[ jj+1 ] = x[1]; bRe = ad[ j ]; bIm = ad[ j + 1 ]; // Forward deflation. for( ; jj >= 0; jj -= 2 ) { cRe = ad[ jj ]; cIm = ad[ jj+1 ]; ad[ jj ] = bRe; ad[ jj+1 ] = bIm; bRe = x[0] * bRe - x[1] * bIm + cRe; bIm = x[1] * bRe + x[0] * bIm + cIm; } } if( polish ) { for( j = 0; j < coeffNum2; ) { // Polish the roots using the undeflated coefficients. x[0] = roots[ j ]; x[1] = roots[ j+1 ]; laguerre( coeffBuf, coeffNum, x ); roots[j++] = x[0]; roots[j++] = x[1]; } } for( j = 2; j < coeffNum2; j += 2 ) { // Sort roots by their real parts by straight insertion. x[0] = roots[ j ]; x[1] = roots[ j+1 ]; for( i = j - 2; i >= 2; i -= 2 ) { if( roots[ i ] <= x[0] ) break; roots[ i+2 ] = roots[ i ]; roots[ i+3 ] = roots[ i+1 ]; } roots[ i+2 ] = x[0]; roots[ i+3 ] = x[1]; } //System.out.println( "roots:" ); //for( j = 0; j < coeffNum; j++ ) { // System.out.println( roots[j<<1]+" + "+roots[(j<<1)+1]+"i" ); //} } // ---- laguer routine from NR paragraph 9.5 ---- protected static final float EXPECTEDERROR = 1.0e-7f; protected static final int MR = 8; protected static final int MT = 10; // 10; protected static final int MAXITER = (MT*MR); protected static final float[] frac = { 0.0f, 0.5f, 0.25f, 0.75f, 0.13f, 0.38f, 0.62f, 0.88f, 1.0f }; // Fractions used to break a limit cycle. [MR+1] /* * Given the degree m and the m+1 complex coefficients a[0..m] of the polynomial (?) i=0...m(a[i]x^i), * and given a complex value x, this routine improves x by Laguerre's method until it converges, * within the achievable roundoff limit, to a root of the given polynomial. The number of iterations * taken is returned as its. * * Here EXPECTEDERROR is the estimated fractional roundoff error. We try to break (rare) limit cycles with * MR different fractional values, once every MT steps, for MAXITER total allowed iterations. * * WARNING: dispite complex 'x' sucky algorithm doesn't work for complex roots!!!! * * @return number of iterations performed or 0 if not converged (complex root) */ // protected int laguer( fcomplex a[], int m, fcomplex *x ) protected static int laguerre( float[] coeffBuf, int coeffNum, float[] x ) { int iter, j, coeffNum2, fooInt; float absX, absP, absM, err, absB; float bRe,bIm, fRe,fIm, dRe,dIm, g2Re,g2Im, gRe,gIm, gmRe, gmIm; float gpRe,gpIm, sqRe,sqIm, hRe,hIm, x1Re,x1Im, dxRe,dxIm, fooFloat; float[] cmplxRes = new float[ 2 ]; // return values from complexDiv and complexSqrt coeffNum2 = coeffNum << 1; for( iter = 1; iter <= MAXITER; iter++ ) { // Loop over iterations up to allowed maximum. bRe = coeffBuf[ coeffNum2 ]; bIm = coeffBuf[ coeffNum2 + 1 ]; absB = complexAbs( bRe, bIm ); err = absB; fRe = 0.0f; fIm = 0.0f; dRe = 0.0f; dIm = 0.0f; absX = complexAbs( x[0], x[1] ); for( j = coeffNum2; j > 0; ) { // Effcient computation of the polynomial and its first two derivatives. f=Cadd(Cmul(*x,f),d); dRe = x[0] * dRe - x[1] * dIm + bRe; dIm = x[1] * dRe + x[0] * dIm + bIm; bIm = x[1] * bRe + x[0] * bIm + coeffBuf[ --j ]; bRe = x[0] * bRe - x[1] * bIm + coeffBuf[ --j ]; absB = complexAbs( bRe, bIm ); err = absB + absX * err; } err *= EXPECTEDERROR; // Estimate of roundoff error in evaluating polynomial. if( absB <= err ) return iter; // We are on the root. complexDiv( dRe, dIm, bRe, bIm, cmplxRes ); // The generic case: use Laguerre's formula. gRe = cmplxRes[0]; gIm = cmplxRes[1]; g2Re = gRe * gRe - gIm * gIm; g2Im = gIm * gRe * 2; complexDiv( fRe, fIm, bRe, bIm, cmplxRes ); hRe = g2Re - 2.0f * cmplxRes[0]; hIm = g2Im - 2.0f * cmplxRes[1]; sqRe = (float) (coeffNum - 1) * ((float) coeffNum * hRe - g2Re); sqIm = (float) (coeffNum - 1) * ((float) coeffNum * hIm - g2Im); complexSqrt( sqRe, sqIm, cmplxRes ); sqRe = cmplxRes[0]; sqIm = cmplxRes[1]; gpRe = gRe + sqRe; gpIm = gIm + sqIm; gmRe = gRe - sqRe; gmIm = gIm - sqIm; absP = complexAbs( gpRe, gpIm ); absM = complexAbs( gmRe, gmIm ); if( absP < absM ) { gpRe = gmRe; gpIm = gmIm; } if( (absP > 0.0f) || (absM > 0.0f) ) { complexDiv( (float) coeffNum, 0.0f, gpRe, gpIm, cmplxRes ); dxRe = cmplxRes[0]; dxIm = cmplxRes[1]; } else { fooFloat= (1.0f + absX); dxRe = fooFloat * (float) Math.cos( (float) iter ); dxIm = fooFloat * (float) Math.sin( (float) iter ); } x1Re = x[0] - dxRe; x1Im = x[1] - dxIm; if( (dxRe == 0.0f) && (dxIm == 0.0f) ) return iter; // Converged. if( (iter % MT) != 0 ) { x[0] = x1Re; x[1] = x1Im; } else { fooInt = iter / MT; x[0] -= frac[ fooInt ] * dxRe; x[1] -= frac[ fooInt ] * dxIm; // Every so often we take a fractional step, to break any limit cycle (itself a rare occurrence). } } // System.out.println( "too many iterations in laguerre()" ); // Very unusual | can occur only for complex roots. Try a different starting guess for the root. // XXX return 0; } // from NR Appendix C protected static float complexAbs( float re, float im ) { if( re == 0.0f ) return Math.abs( im ); if( im == 0.0f ) return Math.abs( re ); return (float) Math.sqrt( re*re + im*im ); } // from NR Appendix C protected static void complexDiv( float aRe, float aIm, float bRe, float bIm, float[] result ) { float r, den; if( Math.abs( bRe ) >= Math.abs( bIm )) { r = bIm / bRe; den = bRe + r * bIm; result[0] = (aRe + r * aIm) / den; result[1] = (aIm - r * aRe) / den; } else { r = bRe / bIm; den = bIm + r * bRe; result[0] = (aRe * r + aIm) / den; result[1] = (aIm * r - aRe) / den; } } // from NR Appendix C protected static void complexSqrt( float Re, float Im, float[] result ) { float absRe, absIm, w, r; if( (Re == 0.0f) && (Im == 0.0f)) { result[0] = 0.0f; result[1] = 0.0f; } else { absRe = Math.abs( Re ); absIm = Math.abs( Im ); if( absRe >= absIm ) { r = absIm / absRe; w = (float) (Math.sqrt( absRe ) * Math.sqrt( 0.5f * (1.0f + Math.sqrt( 1.0f + r*r )))); } else { r = absRe / absIm; w = (float) (Math.sqrt( absIm ) * Math.sqrt( 0.5f * (r + Math.sqrt( 1.0f + r*r )))); } if( Re >= 0.0 ) { result[0] = w; result[1] = Im / (2.0f * w); } else { result[1] = (Im >= 0.0f) ? w : -w; result[0] = Im / (2.0f * result[1] ); } } } // -------- GUI methods -------- public PropertyGUI createGUI(int type) { PropertyGUI gui; StringBuffer qualJComboBox = new StringBuffer(); if (type != GUI_PREFS) return null; for (int i = 0; i < FIRDesignerDlg.QUAL_NAMES.length; i++) { qualJComboBox.append(",it"); qualJComboBox.append(FIRDesignerDlg.QUAL_NAMES[i]); } gui = new PropertyGUI( "gl" + GroupLabel.NAME_GENERAL + "\n" + "lbHigh frequency;pf" + Constants.absHzSpace + ",pr" + PRN_HIFREQ + "\n" + "lbLow frequency;pf" + Constants.absHzSpace + ",pr" + PRN_LOFREQ + "\n" + "lbQuality;ch,pr" + PRN_QUALITY + qualJComboBox.toString() + "\n"); return gui; } }