# Converting from a phase response to a group delay response and vice-versa

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:

$$\tau_g = -\frac{d\Phi(\omega)}{d\omega}$$

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);

• you didn't tell us what was fVec() or is it me? Aug 29 '13 at 13:34
• 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! 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.

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

This should be:

tau_g = -diff(unwrap(angle(Hz)))./diff(fVec); % compute group delay