Signal Theory Basics
Fundamental concepts for understanding and processing signals.
Signal Types
Continuous-Time vs Discrete-Time
Continuous-Time Signal: $x(t)$, defined for all $t \in \mathbb{R}$
Discrete-Time Signal: $x[n]$, defined only at integer values $n \in \mathbb{Z}$
Analog vs Digital
Analog: Continuous in both time and amplitude
Digital: Discrete in both time and amplitude (quantized)
Sampling
Converting continuous-time signals to discrete-time.
Sampling Theorem (Nyquist-Shannon)
A bandlimited signal with maximum frequency $f_{max}$ can be perfectly reconstructed if sampled at:
$$ f_s \geq 2f_{max} $$
Where:
- $f_s$ = sampling frequency
- $f_{Nyquist} = \frac{f_s}{2}$ = Nyquist frequency (maximum representable frequency)
Sampling Process
$$ x[n] = x(nT_s) $$
Where $T_s = \frac{1}{f_s}$ is the sampling period.
Aliasing
When $f_s < 2f_{max}$, high-frequency components appear as lower frequencies (aliases).
Aliased Frequency
$$ f_{alias} = |f_{signal} - k \cdot f_s| $$
Where $k$ is chosen so that $f_{alias} < \frac{f_s}{2}$.
Prevention
- Anti-aliasing filter: Low-pass filter before sampling
- Oversample: Use $f_s \gg 2f_{max}$
1import numpy as np
2import matplotlib.pyplot as plt
3
4# Demonstrate aliasing
5fs = 100 # Sampling frequency
6t = np.arange(0, 1, 1/fs)
7
8# Signal at 30 Hz (below Nyquist)
9f1 = 30
10x1 = np.sin(2 * np.pi * f1 * t)
11
12# Signal at 70 Hz (above Nyquist, will alias to 30 Hz)
13f2 = 70
14x2 = np.sin(2 * np.pi * f2 * t)
15
16# Both look identical when sampled!
17print(f"Nyquist frequency: {fs/2} Hz")
18print(f"Signal 1: {f1} Hz")
19print(f"Signal 2: {f2} Hz (aliases to {fs - f2} Hz)")
Basic Signal Properties
Energy Signal
Total energy is finite:
$$ E = \int_{-\infty}^{\infty} |x(t)|^2 dt < \infty $$
Discrete:
$$ E = \sum_{n=-\infty}^{\infty} |x[n]|^2 < \infty $$
Power Signal
Average power is finite:
$$ P = \lim_{T \to \infty} \frac{1}{T} \int_{-T/2}^{T/2} |x(t)|^2 dt < \infty $$
Discrete:
$$ P = \lim_{N \to \infty} \frac{1}{2N+1} \sum_{n=-N}^{N} |x[n]|^2 < \infty $$
Common Signals
Unit Impulse (Dirac Delta)
Continuous:
$$ \delta(t) = \begin{cases} \infty & t = 0 \ 0 & t \neq 0 \end{cases}, \quad \int_{-\infty}^{\infty} \delta(t) dt = 1 $$
Discrete (Kronecker Delta):
$$ \delta[n] = \begin{cases} 1 & n = 0 \ 0 & n \neq 0 \end{cases} $$
Unit Step
Continuous:
$$ u(t) = \begin{cases} 1 & t \geq 0 \ 0 & t < 0 \end{cases} $$
Discrete:
$$ u[n] = \begin{cases} 1 & n \geq 0 \ 0 & n < 0 \end{cases} $$
Sinusoid
$$ x(t) = A \cos(2\pi f t + \phi) $$
Where:
- $A$ = amplitude
- $f$ = frequency (Hz)
- $\phi$ = phase (radians)
Complex Exponential
$$ x(t) = Ae^{j(2\pi f t + \phi)} = A[\cos(2\pi f t + \phi) + j\sin(2\pi f t + \phi)] $$
System Properties
Linearity
A system is linear if:
$$ T{ax_1[n] + bx_2[n]} = aT{x_1[n]} + bT{x_2[n]} $$
Time-Invariance
A system is time-invariant if:
$$ y[n] = T{x[n]} \implies y[n-k] = T{x[n-k]} $$
LTI Systems
Linear Time-Invariant systems are fundamental in signal processing:
- Completely characterized by impulse response $h[n]$
- Output is convolution: $y[n] = x[n] * h[n]$
- Frequency response: $H(f) = \mathcal{F}{h[n]}$
Practical Implementation
Python
1import numpy as np
2
3def is_power_of_two(n):
4 """Check if n is a power of 2 (useful for FFT)"""
5 return n > 0 and (n & (n - 1)) == 0
6
7def next_power_of_two(n):
8 """Find next power of 2 >= n"""
9 return 2**int(np.ceil(np.log2(n)))
10
11def normalize_signal(x):
12 """Normalize signal to [-1, 1]"""
13 return x / np.max(np.abs(x))
14
15def generate_tone(frequency, duration, sample_rate=44100):
16 """Generate a pure tone"""
17 t = np.arange(0, duration, 1/sample_rate)
18 return np.sin(2 * np.pi * frequency * t)
19
20def add_noise(signal, snr_db):
21 """Add white Gaussian noise with specified SNR"""
22 signal_power = np.mean(signal**2)
23 noise_power = signal_power / (10**(snr_db/10))
24 noise = np.sqrt(noise_power) * np.random.randn(len(signal))
25 return signal + noise
Go
1package signals
2
3import "math"
4
5// GenerateTone creates a pure sine wave
6func GenerateTone(freq, duration, sampleRate float64) []float64 {
7 numSamples := int(duration * sampleRate)
8 signal := make([]float64, numSamples)
9
10 for i := 0; i < numSamples; i++ {
11 t := float64(i) / sampleRate
12 signal[i] = math.Sin(2 * math.Pi * freq * t)
13 }
14
15 return signal
16}
17
18// Normalize scales signal to [-1, 1]
19func Normalize(signal []float64) []float64 {
20 maxAbs := 0.0
21 for _, v := range signal {
22 if abs := math.Abs(v); abs > maxAbs {
23 maxAbs = abs
24 }
25 }
26
27 normalized := make([]float64, len(signal))
28 for i, v := range signal {
29 normalized[i] = v / maxAbs
30 }
31
32 return normalized
33}
Key Concepts Summary
| Concept | Continuous | Discrete |
|---|---|---|
| Signal | $x(t)$ | $x[n]$ |
| Impulse | $\delta(t)$ | $\delta[n]$ |
| Convolution | $\int x(\tau)h(t-\tau)d\tau$ | $\sum x[k]h[n-k]$ |
| Fourier Transform | $X(f) = \int x(t)e^{-j2\pi ft}dt$ | $X(e^{j\omega}) = \sum x[n]e^{-j\omega n}$ |
Further Reading
- The Scientist and Engineer's Guide to Digital Signal Processing
- Sampling Theorem - Wikipedia
- Aliasing - Wikipedia
Related Snippets
- Convolution
Linear systems and filtering operations - Correlation
Signal similarity and pattern matching - Fourier Transform
DFT, FFT, and frequency analysis - Laplace Transform
S-domain analysis and transfer functions - Sampling Theory
Nyquist theorem, reconstruction, and interpolation - Window Functions
Spectral leakage reduction for FFT analysis