Finite Impulse Response(FIR) 필터는 이산 웨이블릿 변환에서 필터 뱅크를 구성하는 기본적인 요소로, 입력 신호를 일정한 길이의 필터 커널을 사용하여 변환한다. FIR 필터는 입출력의 관계가 유한한 길이의 임펄스 응답으로 표현되며, 그 설계는 웨이블릿 변환의 성능에 직접적인 영향을 미친다. 이번 절에서는 FIR 필터의 수학적 배경과 설계 방법을 자세히 설명한다.

FIR 필터의 수학적 표현

FIR 필터의 기본 형태는 다음과 같이 표현된다:

y[n] = \sum_{k=0}^{N-1} h[k] x[n-k]

여기서: - y[n]은 출력 신호, - x[n]은 입력 신호, - h[k]는 필터 계수 (또는 커널), - N은 필터 계수의 수이다.

이 식은 입력 신호 x[n]에 필터 커널 h[k]를 컨볼루션(convolution)하는 과정을 나타낸다.

필터 설계의 핵심 요소

FIR 필터 설계에서 중요한 요소는 다음과 같다: 1. 필터 계수 h[k]: 필터의 성능을 결정하는 주요 요소로, 각 계수는 특정한 주파수 성분을 제어하는 역할을 한다. 2. 필터의 길이 N: 필터의 길이가 길수록 더 정밀한 주파수 분해능을 가질 수 있지만, 계산 복잡도가 증가한다. 3. 대칭성과 비대칭성: 필터의 계수가 대칭일 경우 필터는 선형 위상을 가지며, 이는 신호의 위상 왜곡을 최소화하는 데 유리한다.

FIR 필터의 설계 방법

FIR 필터를 설계하는 방법은 여러 가지가 있으며, 주요 설계 방법을 아래에 소개한다.

창 함수(Window Function) 방법

창 함수 방법은 이상적인 필터의 임펄스 응답을 트렁케이션(truncation)하여 실현 가능한 FIR 필터로 변환하는 방식이다. 다음과 같은 단계로 설계할 수 있다:

  1. 이상적인 필터의 임펄스 응답 계산: 먼저 원하는 주파수 응답을 가지는 이상적인 필터의 임펄스 응답 \mathbf{h}_{\text{ideal}}을 정의한다. 예를 들어, 저역 통과 필터(Low-Pass Filter, LPF)의 경우:
\mathbf{h}_{\text{ideal}}[n] = \frac{\sin(\omega_c n)}{\pi n} \quad \text{(for } n \neq 0)

여기서 \omega_c는 컷오프 주파수이다.

  1. 창 함수 선택: 이상적인 임펄스 응답은 무한한 길이를 가지므로, 이를 유한 길이로 만들기 위해 창 함수 \mathbf{w}[n]를 곱해준다. 일반적으로 사용하는 창 함수로는 Hamming, Hanning, Blackman 창 등이 있다.

  2. 최종 FIR 필터 계수 계산:

\mathbf{h}[n] = \mathbf{h}_{\text{ideal}}[n] \cdot \mathbf{w}[n]

주파수 샘플링 방법

이 방법은 필터의 주파수 응답을 샘플링한 후, 이를 이산 푸리에 변환(DFT)으로 변환하여 FIR 필터를 설계하는 방식이다. 주파수 영역에서 직접 설계할 수 있기 때문에 주파수 특성을 정확히 제어할 수 있는 장점이 있다.

  1. 목표 주파수 응답 정의: 원하는 주파수 응답 \mathbf{H}(\omega)를 정의한다.
  2. 주파수 샘플링: \mathbf{H}(\omega)를 이산적인 주파수 점에서 샘플링하여 \mathbf{H}[k]를 얻는다.
  3. 역 이산 푸리에 변환(IDFT): 샘플링된 주파수 응답을 시간 영역으로 변환하여 필터 계수 \mathbf{h}[n]를 계산한다.
\mathbf{h}[n] = \frac{1}{N} \sum_{k=0}^{N-1} \mathbf{H}[k] e^{j 2 \pi k n / N}

Least Squares 설계 방법

Least Squares 설계는 필터의 주파수 응답이 특정한 목표 주파수 응답에 최대한 근접하도록 설계하는 방법이다. 이 방법은 에러 함수를 최소화하는 것을 목표로 한다. 주파수 응답에서의 오차를 최소화하므로, 원하는 주파수 대역에서 정확한 필터링이 가능해진다.

  1. 목표 주파수 응답 정의: 먼저 설계하고자 하는 필터의 목표 주파수 응답 \mathbf{H}_d(\omega)를 정의한다.
  2. 오차 함수 설정: 주파수 대역에서의 오차를 측정하기 위해 오차 함수 E(\omega)를 다음과 같이 정의한다:
E(\omega) = \mathbf{H}_d(\omega) - \mathbf{H}(\omega)

여기서 \mathbf{H}(\omega)는 실제 필터의 주파수 응답이다. 3. Least Squares 최적화: 오차 E(\omega)의 제곱합을 최소화하는 방식으로 최적화 문제를 설정하고 해결하여 FIR 필터 계수 \mathbf{h}[n]를 도출한다.

이 방법은 필터의 길이와 주파수 대역별 정확도를 조절할 수 있는 유연성을 제공한다.

설계 예제: Low-Pass FIR 필터 설계

여기서는 창 함수 방법을 이용하여 간단한 저역 통과 FIR 필터를 설계하는 과정을 예제로 소개한다.

  1. 필터 사양 설정: 컷오프 주파수 \omega_c0.4 \pi로 설정하고, 필터 계수의 수를 N = 21로 정한다. 필터의 길이가 홀수이므로 대칭적인 필터를 설계하게 된다.
  2. 이상적인 임펄스 응답 계산:
\mathbf{h}_{\text{ideal}}[n] = \frac{\sin(0.4\pi (n - 10))}{\pi (n - 10)}, \quad n = 0, 1, ..., 20
  1. Hamming 창 적용:
\mathbf{w}[n] = 0.54 - 0.46 \cos\left(\frac{2\pi n}{N-1}\right)

최종 FIR 필터 계수는:

\mathbf{h}[n] = \mathbf{h}_{\text{ideal}}[n] \cdot \mathbf{w}[n]

이렇게 설계된 FIR 필터는 주파수 특성에서 저역 통과 기능을 수행하며, 윈도우를 적용함으로써 리플(ripple)과 같은 효과를 제어할 수 있다.

대칭 필터와 선형 위상

FIR 필터는 대칭 또는 비대칭의 계수 구조를 가질 수 있다. 대칭 필터의 경우 h[n] = h[N-1-n]이 성립하며, 이는 선형 위상 특성을 보장한다. 선형 위상 필터는 신호를 필터링할 때 위상 왜곡이 없다는 중요한 장점을 제공한다.

대칭 필터의 예시

\mathbf{h} = \{0.2, 0.5, 0.8, 0.5, 0.2\}

이 필터는 대칭적이며, 이를 사용하면 입력 신호가 필터링된 후에도 원래 신호의 위상이 보존된다.

FIR 필터 설계 시 고려 사항

FIR 필터를 설계할 때는 다음의 사항을 고려해야 한다: 1. 필터의 길이 N: 필터의 길이가 길수록 주파수 특성이 더 정밀해지지만, 실시간 처리를 위한 계산량이 증가한다. 2. 대역폭과 리플: 필터의 대역폭 내에서의 평탄함과 통과 대역 및 저지 대역 사이의 전이 대역폭을 조절하는 것이 중요하다. 3. 설계 방법의 선택: 창 함수, 주파수 샘플링, Least Squares 등 다양한 방법 중에서 특정 응용 분야에 적합한 방법을 선택해야 한다.

FIR 필터 설계의 예제 코드

아래의 코드는 간단한 FIR 필터를 C++로 구현하는 예제이다. 이 코드는 특정한 필터 계수를 설정하고 입력 신호에 대해 필터링을 수행하는 방식으로 작성되었다:

#include <iostream>
#include <vector>

std::vector<double> fir_filter(const std::vector<double>& input, const std::vector<double>& coeff) {
    int N = coeff.size();
    int M = input.size();
    std::vector<double> output(M);

    for (int i = 0; i < M; ++i) {
        output[i] = 0.0;
        for (int j = 0; j < N; ++j) {
            if (i - j >= 0) {
                output[i] += coeff[j] * input[i - j];
            }
        }
    }

    return output;
}

int main() {
    std::vector<double> coeff = {0.2, 0.5, 0.8, 0.5, 0.2};
    std::vector<double> input = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
    std::vector<double> output = fir_filter(input, coeff);

    for (auto& val : output) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

이 예제 코드에서는 fir_filter 함수가 입력 신호와 필터 계수를 받아 필터링된 결과를 반환한다. 필터의 계수를 바꾸거나 필터 길이를 조정하여 다양한 필터링 효과를 실험할 수 있다.