public static double[] fft(double[] data, boolean useWindowFunction) {
		double[] fftInput = new double[data.length];
		if (useWindowFunction) {
			int windowSize = data.length;
			double[] windowedInput = applyWindowFunc(data, hanning(windowSize));
			System.arraycopy(windowedInput, 0, fftInput, 0,
					windowedInput.length);
		} else {
			System.arraycopy(data, 0, fftInput, 0, data.length);
		}
		int dataLength = fftInput.length;
		RealDoubleFFT ftEngine = new RealDoubleFFT(dataLength);
		// coefficient returned: 0 -- 0th bin(real,0); 1,2 -- 1th
		// bin(real,imag); 3,4 -- 2th bin(real,imag)....
		// for even, n -- n/2 bin(real,0)
		ftEngine.ft(fftInput);
		// get the maginude from FFT coefficients
		double[] spectrum;
		if (dataLength % 2 != 0) {// if odd
			spectrum = new double[(dataLength + 1) / 2];
			spectrum[0] = Math.pow(fftInput[0] * fftInput[0], 0.5);// dc
			// component
			for (int index = 1; index < dataLength; index = index + 2) {
				// magnitude =re*re + im*im
				double mag = fftInput[index] * fftInput[index]
						+ fftInput[index + 1] * fftInput[index + 1];
				spectrum[(index + 1) / 2] = Math.pow(mag, 0.5);
			}
		} else {// if even
			spectrum = new double[dataLength / 2 + 1];
			spectrum[0] = Math.pow(fftInput[0] * fftInput[0], 0.5);// dc
			// component.
			// real only
			for (int index = 1; index < dataLength - 1; index = index + 2) {
				// magnitude =re*re + im*im
				double mag = fftInput[index] * fftInput[index]
						+ fftInput[index + 1] * fftInput[index + 1];
				spectrum[(index + 1) / 2] = Math.pow(mag, 0.5);
			}
			// dc component. real only
			spectrum[spectrum.length - 1] = Math.pow(fftInput[dataLength - 1]
					* fftInput[dataLength - 1], 0.5);
		}
		return spectrum;
	}