Chapter 10

샘플링과 신호

연속 그래프를 점들의 배열로 바꾸기
핵심 질문

컴퓨터는 그래프 전체를 어떻게 배열로 저장할까?

샘플링과 신호

핵심 질문

연속적인 그래프를 컴퓨터가 다루는 점들의 배열로 바꾸면 무엇이 달라질까?

교과서 설명

컴퓨터는 모든 순간의 값을 무한히 저장할 수 없다. 그래서 일정한 간격으로 값을 뽑아 배열로 저장한다. 이것을 샘플링이라고 한다.

여기서 은 샘플 개수이고, 번째 샘플 값이다.

은 실제 시간이 아니라 “몇 번째로 찍은 값인가”를 나타내는 번호다. 샘플 간격을 라고 하면 실제 시간은 대략 로 생각할 수 있다.

샘플을 충분히 촘촘하게 찍지 않으면 빠른 파동이 느린 파동처럼 보일 수 있다. 이런 현상을 aliasing이라고 한다.

입문 기준으로는 가장 빠른 흔들림보다 적어도 두 배 정도 자주 찍어야 한다고 생각하면 된다. 이 생각을 Nyquist 기준이라고 부른다. 정확히 두 배는 경계라서 신호의 시작 위치에 따라 애매해질 수 있으므로, 실제로는 여유를 두고 더 촘촘하게 찍는다.

예를 들어 1초에 3번 흔들리는 신호를 보려면 1초에 6번 정도가 이론적 경계이고, 실제로는 그보다 더 자주 샘플을 찍는 편이 안전하다.

오른쪽 실습에서는 alias 모드를 켜서 빠른 파동이 느린 파동처럼 보이는지 직접 확인할 수 있다. 아주 빠르게 흔들리는 곡선이라도 샘플 점만 드문드문 보면, 그 점들이 느린 파동 위에 놓인 것처럼 보일 수 있다. 그래서 DFT가 읽는 것은 “원래 세상 전체의 파동”이 아니라 “지금 찍은 표본 배열 안에서 구분 가능한 파동”이라는 점을 항상 기억해야 한다.

표본화 모델과 주파수 눈금

연속 시간 신호를 라고 하자. 샘플 간격이 이면 컴퓨터가 저장하는 배열은

이다. 전체 관측 시간은 대략

이고, 1초에 몇 번 샘플을 찍는지는

로 나타낸다. 이를 샘플링 주파수라고 부른다.

DFT의 번호 는 실제 주파수 그 자체가 아니라 주파수 칸, 즉 frequency bin이다. 실제 단위가 Hz인 주파수로 바꾸려면 다음처럼 해석한다.

인접한 두 주파수 칸 사이의 간격은

이다. 관측 시간을 길게 해서 가 커지면 가 작아져 더 촘촘한 주파수 눈금을 얻는다. 하지만 샘플링 주파수 가 정하는 구분 가능한 최고 주파수의 한계는 여전히 대략 근처다.

숫자로 보면 더 쉽다. 1초에 번 샘플링했다면 이다. 이때 개 샘플로 DFT를 하면 주파수 칸 간격은

이다. 따라서 칸은

로 읽는다. 같은 조건에서 은 뒤쪽 번호이므로 번 칸, 즉 방향 정보처럼 해석할 수 있다.

다만 실수 신호에서는 뒤쪽 번호가 음수 주파수처럼 해석된다. 예를 들어 에서 와 같은 방향 정보를 담는다. 그래서 실제 스펙트럼을 읽을 때는 근처와 그 뒤쪽의 음수 주파수 해석을 구분해야 한다.

aliasing은 서로 다른 연속 주파수가 샘플링 뒤에 같은 배열처럼 보이는 현상이다. 예를 들어 샘플링 주파수가 일 때 는 샘플 지점에서 같은 회전값을 만들 수 있다.

  • : 원래 연속 신호의 주파수다. 예를 들어 이면 1초에 3바퀴 돈다는 뜻이다.
  • : 샘플링 주파수다. 1초에 샘플을 몇 번 찍는지 나타내며, 위에서 로 두었다.
  • : 원래 주파수 에 샘플링 주파수 를 한 번 더한 주파수다.
  • : 번째 샘플을 찍는 실제 시간이다.
  • : 그 시간 동안 주파수의 파동이 회전한 바퀴 수다.
  • : 바퀴 수를 라디안 각도로 바꾼 값이다. 한 바퀴가 라디안이기 때문이다.
  • : 복소평면에서 회전을 표현하기 위한 허수 단위다. 그래서 는 단위원 위의 회전값으로 읽는다.

마지막 등식은 이기 때문이다. 그래서 샘플링은 단순히 “점을 찍는다”가 아니라, 구분 가능한 주파수 범위를 정하는 과정이다.

직관 비유

동영상을 사진 여러 장으로 저장하는 것과 같다. 사진을 충분히 자주 찍으면 움직임이 자연스럽게 보인다. 너무 드물게 찍으면 움직임을 잘못 이해할 수 있다.

바퀴가 빠르게 도는 영상을 너무 드문드문 찍으면 바퀴가 천천히 돌거나 거꾸로 도는 것처럼 보일 수 있다. 샘플링에서도 같은 일이 생긴다.

예제

길이가 인 신호는 다음처럼 쓸 수 있다.

이 배열은 실제 그래프 전체가 아니라 여덟 번 찍은 사진이다. DFT는 이 여덟 장의 사진 안에서 구분 가능한 주파수만 비교한다.

조금 더 실제적인 신호는 여러 기본 파동을 더해서 만들 수 있다.

이 식은 “한 바퀴 도는 코사인 파동”과 “두 바퀴 도는 사인 파동”을 더한 것이다. 배열만 보면 복잡해 보여도, DFT는 이 안에 섞인 주파수 번호를 따로 읽어 내려고 한다.

샘플 개수가 이면 DFT는 보통 다음 번호들을 검사한다.

이때 개 샘플 안에서 기본 파동이 몇 바퀴 도는지 세는 번호다. 은 흔들리지 않는 평균 성분이고, 은 전체 샘플 묶음 안에서 한 바퀴 도는 성분이다.

뒤쪽 번호는 반대 방향 회전으로 해석할 수 있다. 예를 들어 이면 이므로, 바퀴 도는 파동의 반대 방향 짝처럼 보인다.

손풀이 체크

  1. 에서 는?

    답 보기

    2-2

  2. 1초에 5번 흔들리는 신호를 보려면 이론적 경계는 1초에 몇 번 샘플링일까?

    답 보기

    1초에 10번 정도가 경계이고, 실제로는 그보다 더 자주 찍는 편이 안전하다.

  3. 이면 DFT가 검사하는 번호는?

    답 보기

    0,1,2,3,4,5,6,70,1,2,3,4,5,6,7

다음으로 이어지는 생각

DFT는 이 배열을 주파수별 점수표로 바꾸는 방법이다.

이번 장에서 기억할 3문장

  1. 샘플링은 연속 신호를 일정 간격의 배열 x[n]x[n]으로 바꾸는 과정이다.
  2. 샘플링 주파수와 샘플 개수는 DFT의 kk 번호를 실제 Hz 눈금으로 바꾸는 기준이다.
  3. 너무 드문 샘플링은 빠른 파동을 느린 파동처럼 보이게 할 수 있다.

C++ Practice

C++로 확인하기

연속 함수 x(t)x(t)NN개의 샘플 배열 x[n]x[n]으로 바꾸기

#include <cmath>
#include <iomanip>
#include <iostream>
#include <vector>

using namespace std;

double signal(double t) {
    return sin(t) + 0.5 * sin(3 * t);
}

int main() {
    const double pi = acos(-1.0);
    int N = 8;
    vector<double> x;

    for (int n = 0; n < N; ++n) {
        double t = 2.0 * pi * n / N;
        x.push_back(signal(t));
    }

    cout << fixed << setprecision(2);
    for (double value : x) {
        cout << value << ' ';
    }
    cout << "\n";
}

연습: N=4,8,16N=4,8,16으로 바꿔서 같은 신호를 얼마나 자세히 기억하는지 비교해 보자.