I'm trying to figure out how to convert any phase response to the corresponding group delay response.

Is there a way to do that, and vice-versa if possible?


The group delay of a filter is defined as minus the change in the phase response with respect to frequency. If the phase response of a filter is $\Phi(\omega)$, the corresponding group delay $\tau_g$ is given by:

\begin{equation} \tau_g = -\frac{d\Phi(\omega)}{d\omega} \end{equation}

In Matlab code, the group delay of a 4th order Butterworth filter can be calculated like so:

[b a] = butter( 4, 0.25 ); % design the filter
[Hz fVec] = freqz( b, a ); % compute the frequency response and angular frequencies
phi  = unwrap(angle(Hz)); % extract phase response
taug = -diff(unwrap(angle(Hz)))/((fVec(2))); % compute group delay
figure; plot( fVec(2:end), taug );  % plot the result

The phase response must be unwrapped to avoid $\pi$ to $-\pi$ discontinuities. Because the difference between adjacent frequency bins is the same, we need only scale the -diff(phi) by 1/fVec(2). Finally, because the diff command produces a vector one less than its input, the group delay values are plotted against fVec(2:end) and not fVec.

Alternatively, you could use the matlab command grpdelay, though you're likely to learn more from the previous!

figure; grpdelay(b,a);
  • $\begingroup$ you didn't tell us what was fVec() or is it me? $\endgroup$
    – ion_one
    Aug 29 '13 at 13:34
  • $\begingroup$ fVec is the vector of angular frequencies corresponding to the frequency response -- I accidentally omitted it. Have edited my answer so that it's there now. Good luck! $\endgroup$
    – Kenneide
    Aug 29 '13 at 14:41

this is how to convert the raw data that the phase response is derived into the group delay without having to worry about unwrapping. i am assuming the time and frequency-domain data are are discrete. group delay is the negative of the derivative of the unwrapped phase with respect to frequency. this derivative is approximated with a finite difference for discrete-frequency data (like what comes outa an FFT).

if $h[n]$ is real, then $H[k]$ is Hermitian symmetric: $H[N-k]=\overline{H[k]}$. and $H[0]$ must be real. so the complex angle of $H[0]$ is either $0$ or $\pm \pi$ depending on if $H[0]$ is positive or negative.

$$ \arg\{ H[0] \} = \begin{cases} 0 & \text{for } \Re\{H[0]\} \ge 0 \\ \pm \pi & \text{for } \Re\{H[0]\} < 0 \\ \end{cases}$$

because $ \Im\{ H[0] \} = 0 $.

then after getting your starting phase, you can calculate phase increments:

$$\begin{align} \arg\{ H[k] \} - \arg\{ H[k-1] \} &= \arg\left\{ \frac{H[k]}{H[k-1]} \right\} \\ \\ &= \arg\left\{ \frac{H[k]\overline{H[k-1]}}{\Big|H[k-1]\Big|^2} \right\} \\ \\ &= \arg\left\{ H[k]\overline{H[k-1]} \right\} \\ \\ &= \arg\left\{ \big(\Re\{H[k]\}+j\Im\{H[k]\}\big)\big(\Re\{H[k-1]\}-j\Im\{H[k-1]\}\big) \right\} \\ \\ &= \arg\left\{ \Re\{H[k]\} \Re\{H[k-1]\} + \Im\{H[k]\} \Im\{H[k-1]\} + j\big( \Im\{H[k]\} \Re\{H[k-1]\} - \Re\{H[k]\} \Im\{H[k-1]\} \big) \right\} \\ \\ &= \arctan\left(\frac{ \Im\{H[k]\} \Re\{H[k-1]\} - \Re\{H[k]\} \Im\{H[k-1]\}} {\Re\{H[k]\} \Re\{H[k-1]\} + \Im\{H[k]\} \Im\{H[k-1]\}} \right) \\ \end{align}$$

or recursively

$$ \arg\{ H[k] \} = \arg\{ H[k-1] \} + \arctan\left(\tfrac{ \Im\{H[k]\} \Re\{H[k-1]\} - \Re\{H[k]\} \Im\{H[k-1]\}} {\Re\{H[k]\} \Re\{H[k-1]\} + \Im\{H[k]\} \Im\{H[k-1]\}} \right) $$

for $ 1 \le k \le \tfrac{N}{2} $.

this is assuming that every little phase increment is smaller in magnitude than $\tfrac{\pi}{2}$. this is how you deal with unwrapping phase naturally.

now the negative of this phase increment is proportional to your group delay:

$$\begin{align} \tau_\text{g}[k] &= -\frac{N}{2 \pi}\Big(\arg\{ H[k] \} -\arg\{ H[k-1] \}\Big) \\ \\ &= -\frac{N}{2 \pi} \arctan\left(\tfrac{ \Im\{H[k]\} \Re\{H[k-1]\} - \Re\{H[k]\} \Im\{H[k-1]\}} {\Re\{H[k]\} \Re\{H[k-1]\} + \Im\{H[k]\} \Im\{H[k-1]\}} \right) \\ \end{align}$$

where $\tau_\text{g}[k]$ is the group delay around angular frequency of $\omega = 2 \pi \frac{k}{N}$ and is in "units" of sample period.

  • $\begingroup$ i'm going to recheck my scaling. i am not entirely certain i am scaling this right. $\endgroup$ Oct 3 '17 at 3:01

This should be:

tau_g = -diff(unwrap(angle(Hz)))./diff(fVec); % compute group delay
  • $\begingroup$ Try using code formatting for your answer -- it will be more readable and useful. $\endgroup$
    – MBaz
    Oct 3 '17 at 0:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.