src/main/java/net/sourceforge/jaad/aac/gain/GainControl.java
private void calculateFunctionData(int samples, int band, WindowSequence winSeq, int blockID) {
		final int[] locA = new int[10];
		final float[] levA = new float[10];
		final float[] modFunc = new float[samples];
		final float[] buf1 = new float[samples/2];
		final float[] buf2 = new float[samples/2];
		final float[] buf3 = new float[samples/2];

		int maxLocGain0 = 0, maxLocGain1 = 0, maxLocGain2 = 0;
		switch(winSeq) {
			case ONLY_LONG_SEQUENCE:
			case EIGHT_SHORT_SEQUENCE:
				maxLocGain0 = maxLocGain1 = samples/2;
				maxLocGain2 = 0;
				break;
			case LONG_START_SEQUENCE:
				maxLocGain0 = samples/2;
				maxLocGain1 = samples*7/32;
				maxLocGain2 = samples/16;
				break;
			case LONG_STOP_SEQUENCE:
				maxLocGain0 = samples/16;
				maxLocGain1 = samples*7/32;
				maxLocGain2 = samples/2;
				break;
		}

		//calculate the fragment modification functions
		//for the first half region
		calculateFMD(band, 0, true, maxLocGain0, samples, locA, levA, buf1);

		//for the latter half region
		int block = (winSeq.equals(WindowSequence.EIGHT_SHORT_SEQUENCE)) ? blockID : 0;
		float secLevel = calculateFMD(band, block, false, maxLocGain1, samples, locA, levA, buf2);

		//for the non-overlapped region
		if(winSeq.equals(WindowSequence.LONG_START_SEQUENCE)||winSeq.equals(WindowSequence.LONG_STOP_SEQUENCE)) {
			calculateFMD(band, 1, false, maxLocGain2, samples, locA, levA, buf3);
		}

		//calculate a gain modification function
		int i;
		int flatLen = 0;
		if(winSeq.equals(WindowSequence.LONG_STOP_SEQUENCE)) {
			flatLen = samples/2-maxLocGain0-maxLocGain1;
			for(i = 0; i<flatLen; i++) {
				modFunc[i] = 1.0f;
			}
		}
		if(winSeq.equals(WindowSequence.ONLY_LONG_SEQUENCE)||winSeq.equals(WindowSequence.EIGHT_SHORT_SEQUENCE)) levA[0] = 1.0f;

		for(i = 0; i<maxLocGain0; i++) {
			modFunc[i+flatLen] = levA[0]*secLevel*buf1[i];
		}
		for(i = 0; i<maxLocGain1; i++) {
			modFunc[i+flatLen+maxLocGain0] = levA[0]*buf2[i];
		}

		if(winSeq.equals(WindowSequence.LONG_START_SEQUENCE)) {
			for(i = 0; i<maxLocGain2; i++) {
				modFunc[i+maxLocGain0+maxLocGain1] = buf3[i];
			}
			flatLen = samples/2-maxLocGain1-maxLocGain2;
			for(i = 0; i<flatLen; i++) {
				modFunc[i+maxLocGain0+maxLocGain1+maxLocGain2] = 1.0f;
			}
		}
		else if(winSeq.equals(WindowSequence.LONG_STOP_SEQUENCE)) {
			for(i = 0; i<maxLocGain2; i++) {
				modFunc[i+flatLen+maxLocGain0+maxLocGain1] = buf3[i];
			}
		}

		//calculate a gain control function
		for(i = 0; i<samples; i++) {
			_function[i] = 1.0f/modFunc[i];
		}
	}
private void calculateFunctionData(int samples, int band, WindowSequence winSeq, int blockID) {
		final int[] locA = new int[10];
		final float[] levA = new float[10];
		final float[] modFunc = new float[samples];
		final float[] buf1 = new float[samples/2];
		final float[] buf2 = new float[samples/2];
		final float[] buf3 = new float[samples/2];

		int maxLocGain0 = 0, maxLocGain1 = 0, maxLocGain2 = 0;
		switch(winSeq) {
			case ONLY_LONG_SEQUENCE:
			case EIGHT_SHORT_SEQUENCE:
				maxLocGain0 = maxLocGain1 = samples/2;
				maxLocGain2 = 0;
				break;
			case LONG_START_SEQUENCE:
				maxLocGain0 = samples/2;
				maxLocGain1 = samples*7/32;
				maxLocGain2 = samples/16;
				break;
			case LONG_STOP_SEQUENCE:
				maxLocGain0 = samples/16;
				maxLocGain1 = samples*7/32;
				maxLocGain2 = samples/2;
				break;
		}

		//calculate the fragment modification functions
		//for the first half region
		calculateFMD(band, 0, true, maxLocGain0, samples, locA, levA, buf1);

		//for the latter half region
		int block = (winSeq.equals(WindowSequence.EIGHT_SHORT_SEQUENCE)) ? blockID : 0;
		float secLevel = calculateFMD(band, block, false, maxLocGain1, samples, locA, levA, buf2);

		//for the non-overlapped region
		if(winSeq.equals(WindowSequence.LONG_START_SEQUENCE)||winSeq.equals(WindowSequence.LONG_STOP_SEQUENCE)) {
			calculateFMD(band, 1, false, maxLocGain2, samples, locA, levA, buf3);
		}

		//calculate a gain modification function
		int i;
		int flatLen = 0;
		if(winSeq.equals(WindowSequence.LONG_STOP_SEQUENCE)) {
			flatLen = samples/2-maxLocGain0-maxLocGain1;
			for(i = 0; i<flatLen; i++) {
				modFunc[i] = 1.0f;
			}
		}
		if(winSeq.equals(WindowSequence.ONLY_LONG_SEQUENCE)||winSeq.equals(WindowSequence.EIGHT_SHORT_SEQUENCE)) levA[0] = 1.0f;

		for(i = 0; i<maxLocGain0; i++) {
			modFunc[i+flatLen] = levA[0]*secLevel*buf1[i];
		}
		for(i = 0; i<maxLocGain1; i++) {
			modFunc[i+flatLen+maxLocGain0] = levA[0]*buf2[i];
		}

		if(winSeq.equals(WindowSequence.LONG_START_SEQUENCE)) {
			for(i = 0; i<maxLocGain2; i++) {
				modFunc[i+maxLocGain0+maxLocGain1] = buf3[i];
			}
			flatLen = samples/2-maxLocGain1-maxLocGain2;
			for(i = 0; i<flatLen; i++) {
				modFunc[i+maxLocGain0+maxLocGain1+maxLocGain2] = 1.0f;
			}
		}
		else if(winSeq.equals(WindowSequence.LONG_STOP_SEQUENCE)) {
			for(i = 0; i<maxLocGain2; i++) {
				modFunc[i+flatLen+maxLocGain0+maxLocGain1] = buf3[i];
			}
		}

		//calculate a gain control function
		for(i = 0; i<samples; i++) {
			_function[i] = 1.0f/modFunc[i];
		}
	}
produces gain control function data, stores it in 'function' array