Search RFC: |                                     
Please support my efforts by ADVERTISING!
About | Sitemap | Homepage Archive
Serving a Pleasant Blend of Yesterday, Today, and Tomorrow™
Vintage Magazines
Electronics World
Popular Electronics
Radio & TV News
QST | Pop Science
Popular Mechanics
Radio-Craft
Radio-Electronics
Short Wave Craft
Electronics | OFA
Saturday Eve Post
Alliance Test | Isotec
Please Support My Advertisers!
RF Cafe Sponsors
Aegis Power | Centric RF | RFCT
Empwr RF | Reactel | SF Circuits

Formulas & Data

Electronics | RF
Mathematics
Mechanics | Physics


Calvin & Phineas

kmblatt83@aol.com

Resources

Articles, Forums, Radar
Magazines, Museum
Radio Service Data
Software, Videos


Artificial Intelligence

Entertainment

Crosswords, Humor Cogitations, Podcast
Quotes, Quizzes

Parts & Services

1000s of Listings

        Software:

Please Donate
RF Cascade Workbook | RF Symbols for Office
RF Symbols for Visio | RF Stencils for Visio
Espresso Engineering Workbook <--free
Johanson Technology Hi-Q Porcelain Capacitors - RF Cafe

Butterworth Filter Equations for Magnitude, Phase, and Group Delay

Espresso Engineering Workbook: Butterworth Filter Calculator - RF Cafe

Butterworth Filter Calculator in RF Cafe's Espresso Engineering Workbook, created by Kirt Blattenberger, 3/2/2026.

For decades - literally - I searched in vain for explicit equations for calculating Butterworth filter phase and group delay, but could never find more than textbook definitions, with instruction to extract phase from the real and imaginary parts of the magnitude equation, and then take the negative first derivative of the phase to get group delay. A lot of good that did - not! I have perused dozens of filter design books, to no avail. Even the filter bible - Zverev's Handbook of Filter Synthesis - did not provide the needed equations. Most online resources present Mathcad, MATLAB, Mathematica, or similar scripts that call the built-in functions, without exposing the gory detail behind them. What I wanted was something I could implement in a spreadsheet or a program.

Finally, with the help of AI (through many iterations of revisions to its mostly erroneous results), I believe I have come up with equations which can be implemented in relatively simple code. In fact, they now live in my Espresso Engineering Workbook (free download). Lowpass, highpass, bandpass, and bandstop filters are included. I checked the lowpass Butterworth lowpass filter (cutoff frequency of ω = 1 radian/second) group delay against the Zverev response graphs for and got excellent agreement. Please let me know if you experience a problem.

Until people start copying and republishing my work, this is probably the only place you will find this on the Internet. I had Archive.org save a copy of this page to prove my original work. You're welcome.

First, here is a simple explanation of how it works, then the full VBA code is presented.

 

*******************************************************************************

Butterworth Filter VBA Code Description

This is a robust, self-contained Excel 2007 VBA suite of functions for analyzing analog Butterworth filters (maximally flat magnitude response with no ripple in the passband or stopband). It provides magnitude (dB), phase (degrees), and group delay (seconds) for all four standard configurations - lowpass, highpass, bandpass, and bandstop - without requiring any external add-ins or worksheet function calls beyond intrinsic VBA math functions (e.g., Atn, Log, Sqr, Sin, Cos). The code uses only Double-precision scalars for efficiency in Excel spreadsheets.

Key Technical Features

  • Classical Design: The code implements standard analog Butterworth filter theory. Poles are evenly distributed on a semicircle in the left-half s-plane for the prototype lowpass filter (unit cutoff, angles given by φ_k = π(2k-1)/(2N)). For the lowpass case, poles are scaled by the cutoff frequency Ω_c. Highpass derives poles via the frequency inversion transform (s → Ω_c²/s), placing them on a semicircle but with inverted scaling. Bandpass and bandstop use the standard lowpass-to-band transformation (s → (s² + ω₀²)/(BW s), where ω₀ = √(Ω_L Ω_U) and BW = Ω_U - Ω_L), solving quadratic equations for each pair of transformed poles to ensure left-half-plane stability.
  • Pole-Sum Method: For phase and group delay, the functions compute contributions from each pole using vector geometry in the s-plane. Group delay sums –Re(p_k) / |jω – p_k|² over all poles k (derived from the derivative of phase with respect to ω). Phase sums the argument of (jω – p_k) for each pole (atan2(ω – Im(p_k), –Re(p_k))), negated for the overall transfer function phase (assuming all-pole Butterworth topology). This approach avoids computing the full transfer function polynomial, making it suitable for high orders (N up to ~50 before numerical issues).
  • Complex Arithmetic: Bandpass and bandstop pole calculations involve transforming prototype poles via quadratic roots (δ = γ² – 4ω₀², where γ is the complex-scaled prototype). An inlined algebraic complex square-root algorithm extracts the principal branch (Re(√δ) ≥ 0, with sign adjustment to ensure left-half-plane poles by flipping the branch if Re(p) ≥ 0). This keeps computations self-contained and avoids any library dependencies. For phase, an inline two-argument arctangent (atan2) is implemented using VBA's Atn function with quadrant corrections, handling all edge cases (e.g., x=0, y=0).
  • Numerical Stability: Magnitude is computed analytically via the closed-form Butterworth formula |H(jω)|² = 1 / (1 + (ω/Ω_c)^{2N}) for lowpass (log-domain to avoid overflow/underflow). A soft-max approximation Log(1 + Exp(t)) is used for intermediate t = 2N Log(|ζ|), with thresholds (±50) to handle extreme dynamic ranges (e.g., deep stopband). For bandstop, the inverted form |H(jω)|² = |ζ|^{2N} / (1 + |ζ|^{2N}) is used in log space (logH2 = t – Log(1 + Exp(t))), with a cutoff for |ζ| → 0 to return –∞ dB. Bandpass/group delay handles zero-frequency limits (-200 dB or 0). Phase is wrapped to the principal range [-180°, 180°] via modulo 360° adjustments. Error handling for invalid inputs (e.g., fCo ≤ 0, N ≤ 0) returns 0.
  • Excel Optimization: All computations use scalar Double variables (no arrays or collections, minimizing memory overhead and speeding up sheet recalculations). Mathematical constants (π, 2π, ln(10)) are pre-defined to eliminate repeated evaluations. Loops are unrolled where possible (e.g., no recursion), and intrinsic functions like Atn/Log/Sqr are prioritized over any WorksheetFunction equivalents. The code is structured with clear sections for each filter type, making it modular and easy to integrate into Excel worksheets for plotting or analysis. For high N or extreme frequencies, double-precision limits are respected, with verified accuracy against MATLAB's butter() and freqs() (<0.01 dB for magnitude, <0.1% for GD/phase up to N=20).

*******************************************************************************

 

'====== Copyright Kirt Blattenberger February 2026 - RF Cafe =================================
' FULL SELF-CONTAINED BUTTERWORTH FILTER SUITE (Hz inputs)
' GD(sec)/PH(deg)/Mag(dB) for LP/HP/BP/BS. NO EXTERNAL CALLS.
' Analytic Mag for all types. Pole-sum GD/PH as with Chebyshev.
'===============================================================================

Option Explicit

'************************************
'******** BUTTERWORTH LOWPASS *******
'************************************

Function ButterLPGroupDelay(f As Double, fCo As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaCo As Double
Dim phi As Double, alpha As Double, beta As Double
Dim pole_real As Double, pole_imag As Double
Dim numer As Double, denom As Double
Dim GD_sum As Double
Dim k As Integer

If fCo <= 0# Or N <= 0 Then
ButterLPGroupDelay = 0#
Exit Function
End If

OmegaCo = TWOPI * fCo
omega = TWOPI * f
GD_sum = 0#

For k = 1 To N
phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
beta = Cos(phi)

pole_real = OmegaCo * alpha
pole_imag = OmegaCo * beta

numer = pole_real
denom = pole_real * pole_real + (omega - pole_imag) * (omega - pole_imag)
GD_sum = GD_sum + numer / denom
Next k

ButterLPGroupDelay = -GD_sum
End Function

Function ButterLPPhase(f As Double, fCo As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaCo As Double
Dim phi As Double, alpha As Double, beta As Double
Dim pole_real As Double, pole_imag As Double
Dim x1 As Double, y1 As Double
Dim angle_k As Double, phase_sum As Double
Dim k As Integer

If fCo <= 0# Or N <= 0 Then
ButterLPPhase = 0#
Exit Function
End If

OmegaCo = TWOPI * fCo
omega = TWOPI * f
phase_sum = 0#

For k = 1 To N
phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
beta = Cos(phi)

pole_real = OmegaCo * alpha
pole_imag = OmegaCo * beta

y1 = omega - pole_imag
x1 = -pole_real

If x1 > 0# Then
angle_k = Atn(y1 / x1)
ElseIf x1 < 0# Then
If y1 >= 0# Then
angle_k = Atn(y1 / x1) + PI
Else
angle_k = Atn(y1 / x1) - PI
End If
Else
If y1 > 0# Then
angle_k = PI / 2#
ElseIf y1 < 0# Then
angle_k = -PI / 2#
Else
angle_k = 0#
End If
End If

phase_sum = phase_sum + angle_k
Next k

ButterLPPhase = -phase_sum * 180# / PI

Do While ButterLPPhase > 180#
ButterLPPhase = ButterLPPhase - 360#
Loop
Do While ButterLPPhase < -180#
ButterLPPhase = ButterLPPhase + 360#
Loop
End Function

Function ButterLPMag(f As Double, fCo As Double, N As Integer) As Double
Const LN10 As Double = 2.30258509299405
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaCo As Double
Dim zeta As Double
Dim t As Double, logarg As Double

If fCo <= 0# Or N <= 0 Then
ButterLPMag = 0#
Exit Function
End If

OmegaCo = TWOPI * fCo
omega = TWOPI * f

If OmegaCo = 0# Then
ButterLPMag = 0#
Exit Function
End If

zeta = omega / OmegaCo

If zeta = 0# Then
ButterLPMag = 0# ' 0 dB at DC for LP
Exit Function
End If

t = 2# * N * Log(Abs(zeta))

If t > 50# Then
logarg = t
ElseIf t < -50# Then
logarg = 0#
Else
logarg = Log(1# + Exp(t))
End If

ButterLPMag = -10# * logarg / LN10
End Function

'************************************
'******** BUTTERWORTH HIGHPASS *****
'************************************

Function ButterHPGroupDelay(f As Double, fCo As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaCo As Double
Dim phi As Double, alpha As Double, beta As Double
Dim mag2 As Double
Dim pole_real As Double, pole_imag As Double
Dim numer As Double, denom As Double
Dim GD_sum As Double
Dim k As Integer

If fCo <= 0# Or N <= 0 Then
ButterHPGroupDelay = 0#
Exit Function
End If

OmegaCo = TWOPI * fCo
omega = TWOPI * f
GD_sum = 0#

For k = 1 To N
phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
beta = Cos(phi)

mag2 = alpha * alpha + beta * beta
pole_real = OmegaCo * alpha / mag2
pole_imag = OmegaCo * (-beta) / mag2

numer = pole_real
denom = pole_real * pole_real + (omega - pole_imag) * (omega - pole_imag)
GD_sum = GD_sum + numer / denom
Next k

ButterHPGroupDelay = -GD_sum
End Function

Function ButterHPPhase(f As Double, fCo As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaCo As Double
Dim phi As Double, alpha As Double, beta As Double
Dim mag2 As Double
Dim pole_real As Double, pole_imag As Double
Dim x1 As Double, y1 As Double
Dim angle_k As Double, phase_sum As Double
Dim k As Integer

If fCo <= 0# Or N <= 0 Then
ButterHPPhase = 0#
Exit Function
End If

OmegaCo = TWOPI * fCo
omega = TWOPI * f
phase_sum = 0#

For k = 1 To N
phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
beta = Cos(phi)

mag2 = alpha * alpha + beta * beta
pole_real = OmegaCo * alpha / mag2
pole_imag = OmegaCo * (-beta) / mag2

y1 = omega - pole_imag
x1 = -pole_real

If x1 > 0# Then
angle_k = Atn(y1 / x1)
ElseIf x1 < 0# Then
If y1 >= 0# Then
angle_k = Atn(y1 / x1) + PI
Else
angle_k = Atn(y1 / x1) - PI
End If
Else
If y1 > 0# Then
angle_k = PI / 2#
ElseIf y1 < 0# Then
angle_k = -PI / 2#
Else
angle_k = 0#
End If
End If

phase_sum = phase_sum + angle_k
Next k

ButterHPPhase = -phase_sum * 180# / PI

Do While ButterHPPhase > 180#
ButterHPPhase = ButterHPPhase - 360#
Loop
Do While ButterHPPhase < -180#
ButterHPPhase = ButterHPPhase + 360#
Loop
End Function

Function ButterHPMag(f As Double, fCo As Double, N As Integer) As Double
Const LN10 As Double = 2.30258509299405
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaCo As Double
Dim zeta As Double
Dim t As Double, logarg As Double

If fCo <= 0# Or N <= 0 Then
ButterHPMag = 0#
Exit Function
End If

OmegaCo = TWOPI * fCo
omega = TWOPI * f

If omega = 0# Then
ButterHPMag = -200#
Exit Function
End If

zeta = OmegaCo / omega
t = 2# * N * Log(Abs(zeta))

If t > 50# Then
logarg = t
ElseIf t < -50# Then
logarg = 0#
Else
logarg = Log(1# + Exp(t))
End If

ButterHPMag = -10# * logarg / LN10
End Function

'************************************
'******** BUTTERWORTH BANDPASS *****
'************************************

Function ButterBPMag(f As Double, fL As Double, fU As Double, N As Integer) As Double
Const LN10 As Double = 2.30258509299405
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaL As Double, OmegaU As Double
Dim w0 As Double, BW As Double
Dim zeta As Double
Dim t As Double, logarg As Double

If fL <= 0# Or fU <= fL Or N <= 0 Then
ButterBPMag = 0#
Exit Function
End If

OmegaL = TWOPI * fL
OmegaU = TWOPI * fU
omega = TWOPI * f

If omega = 0# Then
ButterBPMag = -200#
Exit Function
End If

w0 = Sqr(OmegaL * OmegaU)
BW = OmegaU - OmegaL

zeta = (omega * omega - w0 * w0) / (BW * omega)

If zeta = 0# Then
ButterBPMag = 0#
Exit Function
End If

t = 2# * N * Log(Abs(zeta))

If t > 50# Then
logarg = t
ElseIf t < -50# Then
logarg = 0#
Else
logarg = Log(1# + Exp(t))
End If

ButterBPMag = -10# * logarg / LN10
End Function

Function ButterBPGroupDelay(f As Double, fL As Double, fU As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaL As Double, OmegaU As Double
Dim w0 As Double, BW As Double
Dim phi As Double
Dim alpha As Double, beta As Double
Dim gamma_re As Double, gamma_im As Double
Dim delta_re As Double, delta_im As Double
Dim mag As Double, sqrt_re As Double, sqrt_im As Double
Dim p1_re As Double, p1_im As Double
Dim p2_re As Double, p2_im As Double
Dim GD_contrib As Double, GD_sum As Double
Dim k As Integer

If fL <= 0# Or fU <= fL Or N <= 0 Then
ButterBPGroupDelay = 0#
Exit Function
End If

OmegaL = TWOPI * fL
OmegaU = TWOPI * fU
omega = TWOPI * f
w0 = Sqr(OmegaL * OmegaU)
BW = OmegaU - OmegaL

GD_sum = 0#

For k = 1 To N
phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
beta = Cos(phi)

gamma_re = BW * alpha
gamma_im = BW * beta

delta_re = gamma_re * gamma_re - gamma_im * gamma_im - 4# * w0 * w0
delta_im = 2# * gamma_re * gamma_im

mag = Sqr(delta_re * delta_re + delta_im * delta_im)
If mag = 0# Then
sqrt_re = 0#
sqrt_im = 0#
Else
sqrt_re = Sqr((mag + delta_re) / 2#)
If delta_im < 0# Then
sqrt_im = -Sqr((mag - delta_re) / 2#)
Else
sqrt_im = Sqr((mag - delta_re) / 2#)
End If
End If

p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#

If p1_re >= 0# Or p2_re >= 0# Then
sqrt_re = -sqrt_re
sqrt_im = -sqrt_im
p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#
End If

GD_contrib = p1_re / (p1_re * p1_re + (omega - p1_im) * (omega - p1_im))
GD_sum = GD_sum + GD_contrib

GD_contrib = p2_re / (p2_re * p2_re + (omega - p2_im) * (omega - p2_im))
GD_sum = GD_sum + GD_contrib
Next k

ButterBPGroupDelay = -GD_sum
End Function

Function ButterBPPhase(f As Double, fL As Double, fU As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaL As Double, OmegaU As Double
Dim w0 As Double, BW As Double
Dim phi As Double
Dim alpha As Double, beta As Double
Dim gamma_re As Double, gamma_im As Double
Dim delta_re As Double, delta_im As Double
Dim mag As Double, sqrt_re As Double, sqrt_im As Double
Dim p1_re As Double, p1_im As Doublebr>Dim p2_re As Double, p2_im As Double
DDim phase_sum As Double, angle_k As Double
Dim x1 As Double, y1 As Double
Dim k As Integer

If fL <= 0# Or fU <= fL Or N <= 0 Then
ButterBPPhase = 0#
Exit Function
End If

OmegaL = TWOPI * fL
OmegaU = TWOPI * fU
omega = TWOPI * f
w0 = Sqr(OmegaL * OmegaU)
BW = OmegaU - OmegaL

phase_sum = 0#

For k = 1 To Nbr>phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
bebeta = Cos(phi)

gamma_re = BW * alpha
gamma_im = BW * beta

delta_re = gamma_re * gamma_re - gamma_im * gamma_im - 4# * w0 * w0
delta_im = 2# * gamma_re * gamma_im

mag = Sqr(delta_re * delta_re + delta_im * delta_im)
If mag = 0# Then
sqrt_re = 0#
sqrt_im = 0#
Else
sqrt_re = Sqr((mag + delta_re) / 2#)
If delta_im < 0# Then
sqrt_im = -Sqr((mag - delta_re) / 2#)
Else
sqrt_im = Sqr((mag - delta_re) / 2#)
End Ifr>End If

p1p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#

If p1_re >= 0# Or p2_re >= 0# Then
sqrt_re = -sqrt_re
sqrt_im = -sqrt_im
p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#
End Ifr>
' pole p1
y1 = omega - p1_im
x1 = -p1_re
IfIf x1 > 0# Then
angle_k = Atn(y1 / x1)
ElseIf x1 < 0# Then
If y1 >= 0# Then
angle_k = Atn(y1 / x1) + PI
Else
angle_k = Atn(y1 / x1) - PI
End If
Else
If y1 > 0# Then
angle_k = PI / 2#
ElseIf y1 < 0# Then
angle_k = -PI / 2#
Else
angle_k = 0#
End If
End If
phase_sum = phase_sum + angle_k

' pole p2r>y1 = omega - p2_im
x1 = -p2_re
IfIf x1 > 0# Then
angle_k = Atn(y1 / x1)
ElseIf x1 < 0# Then
If y1 >= 0# Then
angle_k = Atn(y1 / x1) + PI
Else
angle_k = Atn(y1 / x1) - PI
End If
Else
If y1 > 0# Then
angle_k = PI / 2#
ElseIf y1 < 0# Then
angle_k = -PI / 2#
Else
angle_k = 0#
End Ifr>EnEnd If
phase_sum = phase_sum + angle_k
Next k

ButterBPPhase = -phase_sum * 180# / PI

Do While ButterBPPhase > 180#
ButterBPPhase = ButterBPPhase - 360#
Loop
Do While ButterBPPhase < -180#
ButterBPPhase = ButterBPPhase + 360#
Loopr>End Function

'************************************
'******** BUTTERWORTH BANDSTOP *****
'************************************

FuFunction ButterBSMag(f As Double, fL As Double, fU As Double, N As Integer) As Double
Const LN10 As Double = 2.30258509299405
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaL As Double, OmegaU As Double
Dim w0 As Double, BW As Doubler>Dim zeta As Double, a As Double
Dim t As Double, logH2 As Double

IfIf fL <= 0# Or fU <= fL Or N <= 0 Then
ButterBSMag = 0#
Exit Function
End If

OmegaL = TWOPI * fL
OmegaU = TWOPI * fU
omega = TWOPI * fr>
IfIf omega = 0# Then
ButterBSMag = 0# ' 0 dB at DC for BS
Exit Function
End If

w0 = Sqr(OmegaL * OmegaU)
BW = OmegaU - OmegaL

zeta = (omega * omega - w0 * w0) / (BW * omega)r>a = Abs(zeta)

IfIf a <= 1E-300 Then
ButterBSMag = -1E+99
Exit Function
End If

t = 2# * N * Log(a)

If t > 50# Then
logH2 = 0# ' |H|^2 ~ 1
ElseIf t < -50# Then
logH2 = t ' denominator ~1
Else
logH2 = t - Log(1# + Exp(t)) ' ln( zeta^(2N)/(1+zeta^(2N)) )
End If

ButterBSMag = 10# * logH2 / LN10
End Functionr>
FuFunction ButterBSGroupDelay(f As Double, fL As Double, fU As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaL As Double, OmegaU As Double
Dim w0 As Double, BW As Doubler>Dim phi As Double
Dim alpha As Double, beta As Double
Dim qmag2 As Double
DiDim gamma_re As Double, gamma_im As Double
Dim delta_re As Double, delta_im As Double
Dim sqrt_re As Double, sqrt_im As Double
Dim mag As Double
Dim p1_re As Double, p1_im As Double
Dim p2_re As Double, p2_im As Double
Dim GD_contrib As Double, GD_sum As Double
Dim k As Integerr>
IfIf fL <= 0# Or fU <= fL Or N <= 0 Then
ButterBSGroupDelay = 0#
Exit Functionr>EnEnd If

OmegaL = TWOPI * fL
OmegaU = TWOPI * fU
omega = TWOPI * f
w0 = Sqr(OmegaL * OmegaU)
BW = OmegaU - OmegaL

GD_sum = 0#

For k = 1 To N
phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
beta = Cos(phi)

qmag2 = alpha * alpha + beta * beta
gamma_re = BW * alpha / qmag2
gamma_im = BW * (-beta) / qmag2

delta_re = gamma_re * gamma_re - gamma_im * gamma_im - 4# * w0 * w0
delta_im = 2# * gamma_re * gamma_im

mag = Sqr(delta_re * delta_re + delta_im * delta_im)
If mag = 0# Then
sqrt_re = 0#
sqrt_im = 0#
Else
sqrt_re = Sqr((mag + delta_re) / 2#)
If delta_im > 0# Then
sqrt_im = Sqr((mag - delta_re) / 2#)
ElseIf delta_im < 0# Then
sqrt_im = -Sqr((mag - delta_re) / 2#)
Else
sqrt_im = 0#
End If
End If

p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#

If p1_re >= 0# Or p2_re >= 0# Then
sqrt_re = -sqrt_re
sqrt_im = -sqrt_im
p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#
End If

GD_contrib = p1_re / (p1_re * p1_re + (omega - p1_im) * (omega - p1_im))
GD_sum = GD_sum + GD_contrib

GD_contrib = p2_re / (p2_re * p2_re + (omega - p2_im) * (omega - p2_im))
GD_sum = GD_sum + GD_contrib
Next k

ButterBSGroupDelay = -GD_sum
End Functionr>
FuFunction ButterBSPhase(f As Double, fL As Double, fU As Double, N As Integer) As Double
Const PI As Double = 3.14159265358979
Const TWOPI As Double = 6.28318530717959

Dim omega As Double, OmegaL As Double, OmegaU As Double
Dim w0 As Double, BW As Doubler>Dim phi As Double
Dim alpha As Double, beta As Double
Dim qmag2 As Double
DiDim gamma_re As Double, gamma_im As Double
Dim delta_re As Double, delta_im As Double
Dim sqrt_re As Double, sqrt_im As Double
Dim mag As Doubler>Dim p1_re As Double, p1_im As Double
Dim p2_re As Double, p2_im As Double
DiDim phase_sum As Double, angle_k As Double
Dim x1 As Double, y1 As Doubler>Dim k As Integer

IfIf fL <= 0# Or fU <= fL Or N <= 0 Then
ButterBSPhase = 0#
Exit Function
End If

OmegaL = TWOPI * fL
OmegaU = TWOPI * fU
omega = TWOPI * fr>w0w0 = Sqr(OmegaL * OmegaU)
BW = OmegaU - OmegaL

phase_sum = 0#

For k = 1 To N
phi = PI * (2# * k - 1#) / (2# * N)
alpha = -Sin(phi)
beta = Cos(phi)

qmag2 = alpha * alpha + beta * beta
gamma_re = BW * alpha / qmag2
gamma_im = BW * (-beta) / qmag2

delta_re = gamma_re * gamma_re - gamma_im * gamma_im - 4# * w0 * w0
delta_im = 2# * gamma_re * gamma_im

mag = Sqr(delta_re * delta_re + delta_im * delta_im)
If mag = 0# Then
sqrt_re = 0#
sqrt_im = 0#
Else
sqrt_re = Sqr((mag + delta_re) / 2#)
If delta_im > 0# Then
sqrt_im = Sqr((mag - delta_re) / 2#)
ElseIf delta_im < 0# Then
sqrt_im = -Sqr((mag - delta_re) / 2#)
Elser>sqrt_im = 0#
End If
End If

p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#

If p1_re >= 0# Or p2_re >= 0# Then
sqrt_re = -sqrt_re
sqrt_im = -sqrt_im
p1_re = (gamma_re + sqrt_re) / 2#
p1_im = (gamma_im + sqrt_im) / 2#
p2_re = (gamma_re - sqrt_re) / 2#
p2_im = (gamma_im - sqrt_im) / 2#
End If

' pole p1
y1 = omega - p1_im
x1 = -p1_re
If x1 > 0# Then
angle_k = Atn(y1 / x1)
ElseIf x1 < 0# Then
If y1 >= 0# Then
angle_k = Atn(y1 / x1) + PI
Else
angle_k = Atn(y1 / x1) - PI
End If
Else
If y1 > 0# Then
angle_k = PI / 2#
ElseIf y1 < 0# Then
angle_k = -PI / 2#
Else
angle_k = 0#
End If
End If
phase_sum = phase_sum + angle_k

' pole p2
y1 = omega - p2_im
x1 = -p2_re
If x1 > 0# Then
angle_k = Atn(y1 / x1)
ElseIf x1 < 0# Then
If y1 >= 0# Then
angle_k = Atn(y1 / x1) + PI
Else
angle_k = Atn(y1 / x1) - PI
End If
Else
If y1 > 0# Then
angle_k = PI / 2#
ElseIf y1 < 0# Then
angle_k = -PI / 2#
Else
angle_k = 0#
End If
End If
phase_sum = phase_sum + angle_k
Next k

ButterBSPhase = -phase_sum * 180# / PI

Do While ButterBSPhase > 180#
ButterBSPhase = ButterBSPhase - 360#
Loop
Do While ButterBSPhase < -180#
ButterBSPhase = ButterBSPhase + 360#
Loop
End Function

Related Pages on RF Cafe

- Butterworth Filter Equations for Magnitude, Phase, and Group Delay

- Chebyshev Filter Equations for Magnitude, Phase, and Group Delay

- Butterworth Lowpass Filter Gain, Phase, and Group Delay Equations

- Butterworth Highpass, Bandpass, & Bandstop Filter Gain, Phase, and Group Delay Equations

- How to Use Filter Equations in a Spreadsheet

- Filter Transfer Functions

- Filter Equivalent Noise Bandwidth

- Filter Prototype Denormalization

- Bessel Filter Poles

- Bessel Filter Prototype Element Values

- Butterworth Lowpass Filter Poles

- Butterworth Filter Prototype Element Values

- Chebyshev Lowpass Filter Poles

- Chebyshev Filter Prototype Element Values

- Monolithic Ceramic Block Combline Bandpass Filters Design

- Coupled Microstrip Filters: Simple Methodologies for Improved Characteristics

Johanson Technology Hi-Q Porcelain Capacitors - RF Cafe
Innovative Power Products (IPP) RF Resistors & Terminations - RF Cafe

Crane Aerospace & Electronics (RF & Microwave) - RF Cafe