Grundlagen
Lineare zeitinvariante Systeme
Linearität und Zeitinvarianz als Fundament der Filtertheorie — von der Impulsantwort bis zum FIR-Tiefpassfilter.
Ein lineares, zeitinvariantes (LZI- oder englisch LTI-) System ist eine fundamentale Kategorie in der Signalverarbeitung, die sich durch zwei wesentliche physikalische Eigenschaften auszeichnet: Linearität und Zeitinvarianz.
Die Linearität eines Systems bedeutet, dass es das Superpositionsprinzip (Überlagerungsprinzip) erfüllt. Dies besagt, dass die Reaktion des Systems auf eine Summe von Eingangssignalen exakt gleich der Summe der Reaktionen auf jedes einzelne dieser Eingangssignale ist. Mathematisch ausgedrückt bedeutet dies für eine Systemfunktion $f$, die ein Eingangssignal $x$ auf einen Ausgang abbildet:
$$f(x) + f(y) = f(x + y)$$
Darüber hinaus beinhaltet die Linearität auch das Homogenitätsprinzip (Verstärkungsprinzip), welches besagt, dass eine Skalierung des Eingangssignals um einen Faktor zu einer identischen Skalierung des Ausgangssignals führt. Die mathematische Definition eines linearen Systems fasst diese beiden Gesetzmäßigkeiten zusammen:
$$L{ lpha \cdot x_1(t) + eta \cdot x_2(t)} = lpha \cdot L{x_1(t)} + eta \cdot L{x_2(t)}$$
wobei $ lpha$ und $ eta$ beliebige komplexe oder reelle Skalierungskonstanten sind.
Die zweite Eigenschaft ist die Zeitinvarianz. Ein System ist zeitinvariant, wenn eine zeitliche Verschiebung des Eingangssignals zu einer identischen Zeitverschiebung des Ausgangssignals führt. Anders ausgedrückt: Die Eigenschaften des Systems verändern sich nicht über die Zeit; die Reaktion ist unabhängig vom Anwendungszeitpunkt. Wenn ein Eingangssignal $x(t)$ die Ausgabe $y(t)$ erzeugt, dann erzeugt ein zeitverschobenes Eingangssignal $x(t - au)$ die entsprechend verschobene Ausgabe $y(t - au)$.
[Image of an LTI system block diagram explaining linearity and time invariance principles]
Die Impulsantwort
Legt man an den Eingang eines LZI-Systems einen unendlich kurzen Impuls an, lässt sich am Ausgang die sogenannte Impulsantwort messen. Das Besondere daran: Die Impulsantwort charakterisiert ein LZI-System mathematisch vollständig. Kennt man sie, lässt sich die Reaktion des Systems auf ein beliebiges Eingangssignal über die mathematische Faltung berechnen.
Für ein kontinuierliches System ist dieser Eingangsimpuls durch die theoretische Dirac-Delta-Funktion $\delta(t)$ bestimmt – ein unendlich kurzer Peak mit unendlicher Amplitude und einer Fläche von exakt $1$. Da dies in der digitalen, diskreten Welt nicht abbildbar ist, kommt hier die Kronecker-Delta-Funktion $\delta[n]$ zum Einsatz. Sie ist mathematisch extrem einfach definiert:
$$\delta[n] = \begin{cases} 1 & \text{für } n = 0 \\ 0 & \text{für } n \neq 0 \end{cases}$$

Digitale Filter – sowohl FIR- (Finite Impulse Response) als auch IIR-Filter (Infinite Impulse Response) – sind klassische Beispiele für LZI-Systeme. In Software-Tools wie GNU Radio Companion lassen sie sich intuitiv über entsprechende Blöcke wie den FIR Filter oder IIR Filter implementieren.

Die Filterkoeffizienten (oft auch als Taps bezeichnet) definieren direkt die diskrete Impulsantwort des FIR-Filters. Möchte man die Impulsantwort eines solchen Blocks in GNU Radio experimentell ermitteln, kann man einen Einzelimpuls am Eingang einspeisen. Dies gelingt in der Praxis am einfachsten mit einem Vector Source-Block, dem man als Vektor ein Array der Form [1.0] + [0.0]*500 übergibt und die Option Repeat auf No setzt. Am Ausgang lässt sich die Impulsantwort dann direkt im Zeitbereich betrachten.
Implementierung am Beispiel eines FIR-Tiefpassfilters
Ein FIR-Filter (Filter mit endlicher Impulsantwort) besitzt eine zeitlich begrenzte Impulsantwort. Die Berechnung des aktuellen Ausgangssamples erfolgt ausschließlich als gewichtete Summe des aktuellen sowie einer endlichen Anzahl vergangener Eingangssamples. Die Filterkoeffizienten stellen dabei exakt die Gewichtungsfaktoren dar.
Die praktische Auslegung eines solchen Filters basiert häufig auf der Fenster-Methode: Die theoretisch unendlich lange ideale Impulsantwort eines Tiefpasses (eine abgetastete Sinc-Funktion) wird mathematisch mit einer zeitlich begrenzten Fensterfunktion (wie dem Hamming- oder Hann-Fenster) multipliziert. Dieses „Fenstern“ verhindert harte Abrisskanten im Zeitbereich und reduziert so die unerwünschte Welligkeit (das Gibbsche Phänomen) im Frequenzgang, insbesondere im Sperrbereich.
Systemparameter des Beispiels:
- Abtastrate ($f_s$): $100, ext{kHz}$
- Gewünschte Grenzfrequenz ($f_c$): $15, ext{kHz}$
- Nyquist-Frequenz ($f_{Nyquist}$): $50, ext{kHz}$ (Hälfte der Abtastrate)
- Normalisierte Grenzfrequenz: $\nu = \frac{f_c}{f_{Nyquist}} = \frac{15\,\text{kHz}}{50\,\text{kHz}} = 0{,}3$
- Filterlänge / Anzahl der Koeffizienten ($N$): $51$
- Fensterfunktion: Hamming
Berechnung der Koeffizienten (Python / SciPy):
from scipy import signal
import numpy as np
fs = 100000.0
fc = 15000.0
N = 51
f_nyquist = fs / 2
fc_normalized = fc / f_nyquist
fir_coeffs = signal.firwin(N, fc_normalized, window="hamming")
from scipy import signal
import numpy as np
fs = 100000.0
fc = 15000.0
N = 51
f_nyquist = fs / 2
fc_normalized = fc / f_nyquist
fir_coeffs = signal.firwin(N, fc_normalized, window="hamming")
Berechnung des Frequenzgangs:
w, h = signal.freqz(fir_coeffs, [1.0], worN=2000)
w, h = signal.freqz(fir_coeffs, [1.0], worN=2000)
wenthält die Frequenzpunkte im Bereich von $0$ bis $\pi, ext{rad/Sample}$.henthält die komplexwertigen Frequenzgangwerte. Der Betrag $|h|$ liefert die Amplitudenverstärkung des Filters, welche logarithmisch in Dezibel ausgedrückt werden kann: $A_{ ext{dB}} = 20 \cdot \log_{10}(|h|)$. Der Phasenwinkel $ ngle h$ (Argument) repräsentiert die frequenzabhängige Phasenverschiebung.

Legt man nun einen definierten Rechteckimpuls an den Filtereingang, lässt sich die Systemantwort mittels diskreter Faltung im Zeitbereich berechnen.

# Erzeugen und Filtern des Eingangs-Impulssignals
pulse_duration_ms = 0.2
pulse_duration_samples = int(pulse_duration_ms * 1e-3 * fs)
# Gesamtlänge des Testsignals (ausreichend lang für das Abklingen)
signal_length_samples = 300
input_signal = np.zeros(signal_length_samples)
# Platzieren des Impulses ab Index 50
pulse_start_index = 50
input_signal[pulse_start_index : pulse_start_index + pulse_duration_samples] = 1.0
# Zeitachse in Sekunden generieren
t_signal = np.arange(signal_length_samples) / fs
# Signalfilterung über die Systemfunktion
filtered_signal = signal.lfilter(fir_coeffs, [1.0], input_signal)
# Erzeugen und Filtern des Eingangs-Impulssignals
pulse_duration_ms = 0.2
pulse_duration_samples = int(pulse_duration_ms * 1e-3 * fs)
# Gesamtlänge des Testsignals (ausreichend lang für das Abklingen)
signal_length_samples = 300
input_signal = np.zeros(signal_length_samples)
# Platzieren des Impulses ab Index 50
pulse_start_index = 50
input_signal[pulse_start_index : pulse_start_index + pulse_duration_samples] = 1.0
# Zeitachse in Sekunden generieren
t_signal = np.arange(signal_length_samples) / fs
# Signalfilterung über die Systemfunktion
filtered_signal = signal.lfilter(fir_coeffs, [1.0], input_signal)
Das resultierende Signal im Zeitbereich:

Betrachtet man das Signal im Frequenzbereich, wird die Filterwirkung deutlich sichtbar: Frequenzanteile oberhalb der Grenzfrequenz von $15, ext{kHz}$ werden massiv gedämpft.

Einfluss der Filterlänge:
Verringert man die Anzahl der Koeffizienten $N$ (die Filterlänge), verliert das Filter an Selektivität. Die Übergangsflanke zwischen Durchlassbereich und Sperrbereich wird flacher, wodurch mehr unerwünschte Frequenzanteile oberhalb der Grenzfrequenz passieren können.


Eine hervorragende interaktive Web-Simulation zur Visualisierung und Manipulation digitaler Filter findest du hier:
GSN-Lib Digital Filter Simulation
Quellen: