1

Using the output from either JTransform, or JWave, how should the phase spectrum be computed?

Do I simply write a similar method, but instead I compute the phase using: Math.atan2(im / re) * Math.PI * 180?

I've used the following to calculate the magnitude spectrum:

@Override
public void computeSpectrum()
{
    // The spectrum into which we store the data
    super.spectrum = new double[signal.getSampledAmplitudes().length >> 1];

  // Compute the magnitude spectrum of the signal
  double re = 0, im = 0;
  for (int bin = 0; bin < spectrum.length - 1; ++bin) {
       re = super.frequencyDomain[2 * bin];
       im = super.frequencyDomain[2 * bin + 1];
       super.spectrum[bin] = Math.sqrt(re * re + im * im);
  }
}
SleuthEye
  • 14,379
  • 2
  • 32
  • 61
Dan
  • 75
  • 6

1 Answers1

0

Indeed you can compute the phase spectrum in radians with a similar loop as you've used for the magnitude spectrum :

double re = 0, im = 0;
for (int bin = 0; bin < spectrum.length - 1; ++bin) {
   re = super.frequencyDomain[2 * bin];
   im = super.frequencyDomain[2 * bin + 1];
   super.spectrum[bin] = Math.atan2(im, re);

}

If you prefer a result in degrees simply convert the phases with toDegrees()

...
   super.spectrum[bin] = Math.toDegrees(Math.atan2(im, re));
SleuthEye
  • 14,379
  • 2
  • 32
  • 61
  • Will this yield a both positive and negative phase spectrum? Or do I have to 'unwrap' the phase? – Dan Mar 26 '19 at 09:07
  • As per `atan2` documentation: "This method computes the phase *theta* by computing an arc tangent of y/x in the range of *-pi* to *pi*." – SleuthEye Mar 26 '19 at 12:24
  • To get rid of noise in the phase spectrum, would I compute the amplitude (sqrt(re * re * im * im)) beforehand, and discard it it's below a certain threshold, or would I do this directly to the phase value (Math.atan2(im, re))? – Dan Apr 02 '19 at 09:23
  • If you are trying to isolate sections with a strong coherent signal having a relatively slow varying phase from otherwise weaker noise with randomly fluctuating phase, then the former would be the way to go (ie thresholding based on computed amplitude) – SleuthEye Apr 03 '19 at 03:26
  • Its to get rid of float / double rounding issues. – Dan Apr 03 '19 at 05:18
  • Then you could round to the nearest "x" degrees with something like `x*Math.round(Math.toDegrees(Math.atan2(im,re))/x)` – SleuthEye Apr 03 '19 at 12:28