검색
← 모듈 로드맵

소리를 숫자로: 샘플링 · 나이퀴스트 · 푸리에 변환 · 스펙트로그램 · 멜 스케일

강의 · 입문자 · KAITABASE 정리

원제 · Audio Features: Sampling, STFT, Mel Spectrogram (torchaudio 튜토리얼 참고)

샘플링 · 나이퀴스트 · DFT · 프레임 · 멜 스케일을 손계산하며 음성 모델 입력을 만드는 수업

먼저 알아야 할 것

벡터와 내적삼각함수 cos · sin로그 계산배열 다루기

다루는 내용

소리를 16 kHz 숫자 줄로 샘플링하고, 나이퀴스트 주파수와 앨리어싱을 이해한 뒤, 4샘플 DFT를 손으로 계산합니다. 25 ms 창 · 10 ms 홉으로 스펙트로그램 프레임 수를 구하고, 멜 스케일 식과 80채널 멜 필터뱅크로 Whisper 입력인 로그 멜 스펙트로그램이 만들어지는 과정을 정리합니다. MFCC 개요도 다룹니다.

해설

소리를 숫자로: 샘플링 · 나이퀴스트 · 푸리에 변환 · 스펙트로그램 · 멜 스케일

음성 AI는 소리를 그대로 듣지 않습니다. 공기의 떨림을 1초에 수만 번 재서 숫자 줄로 만들고, 그 줄을 짧게 잘라 "어떤 높이의 소리가 얼마나 센지"를 표로 바꾼 뒤(스펙트로그램), 사람 귀에 맞게 높이 축을 구부립니다(멜 스케일). 이 수업은 음성 인식 · 음성 합성 모델의 입력이 만들어지는 과정을 숫자로 하나씩 계산합니다.

항목내용
참고 출처torchaudio 공식 튜토리얼 「Audio Feature Extractions」(Spectrogram · Mel Filter Bank · MelSpectrogram · MFCC), torchaudio 소스의 멜 변환 함수, Whisper 논문(arXiv 2212.04356)의 입력 설정
트랙 · 수준음성 · 기초
이 수업이 다루는 범위파형과 샘플링, 나이퀴스트 주파수와 앨리어싱, 이산 푸리에 변환(DFT), 프레임 · 창 · 홉, 스펙트로그램과 데시벨, 멜 스케일과 멜 필터뱅크, 로그 멜 스펙트로그램, MFCC 개요

들어가기 전에

한눈에 보기

  • 샘플링 레이트 16 kHz가 무엇을 뜻하고, 왜 8 kHz 위의 소리는 담을 수 없는지(나이퀴스트) 설명할 수 있습니다.
  • 4개짜리 숫자 줄의 DFT를 손으로 계산해, "주파수 성분을 찾는다"는 말의 뜻을 확인합니다.
  • 25 ms 창 · 10 ms 홉으로 1초 음성이 몇 프레임이 되는지 계산합니다.
  • 멜 스케일 식 m=2595log⁡10(1+f/700)m = 2595\log_{10}(1+f/700) 로 높은 주파수가 왜 '압축'되는지 숫자로 봅니다.
  • 로그 멜 스펙트로그램이 Whisper 같은 모델의 입력이 되는 흐름을 그림으로 정리합니다.

1. 파형과 샘플링: 떨림을 숫자 줄로

직관(해설용 비유). 줄넘기하는 친구를 사진으로 찍는다고 합시다. 1초에 사진을 많이 찍을수록 줄의 움직임을 촘촘히 되살릴 수 있습니다. 마이크도 같습니다. 공기 압력(떨림)을 일정한 간격으로 재서 숫자로 적습니다. 이 숫자 줄이 파형(waveform) 이고, 1초에 몇 번 재는지가 샘플링 레이트(sampling rate) 입니다.

단계.

  1. 마이크가 압력 변화를 전기 신호로 바꿉니다.
  2. 일정 간격 1/fs1/f_s 초마다 값을 읽습니다(샘플링).
  3. 각 값을 정해진 비트 수의 정수로 반올림합니다(양자화, 예: 16비트).
  4. 결과는 길이 fs×f_s \times(초) 인 숫자 배열입니다.
x[n]=x연속 ⁣(nfs),n=0,1,2,…x[n] = x_{\text{연속}}\!\left(\frac{n}{f_s}\right),\qquad n = 0, 1, 2, \dots
기호뜻
x[n]x[n]nn 번째 샘플 값(배열의 nn 번째 숫자)
fsf_s샘플링 레이트(초당 샘플 수, 단위 Hz)
n/fsn/f_snn 번째 샘플을 잰 시각(초)

숫자로 해 보기(해설용). Whisper는 모든 오디오를 16,000 Hz로 다시 샘플링해 씁니다(논문 2.3절). 그러면 1초 음성은 16,000개, 30초는 480,000개의 숫자입니다. 문장 하나에 숫자 수십만 개라 그대로 모델에 넣기엔 너무 길고, 같은 '아' 소리도 파형 모양은 매번 조금씩 달라서 패턴을 찾기 어렵습니다. 그래서 아래의 '주파수 표'로 바꿉니다.

2. 나이퀴스트 주파수와 앨리어싱

직관. 바퀴가 빠르게 도는 영상을 보면 바퀴가 거꾸로 도는 것처럼 보일 때가 있습니다. 촬영 속도에 비해 바퀴가 너무 빨라, 사진 사이에 일어난 일을 잘못 해석한 것입니다. 소리도 샘플링이 느리면 높은 음이 엉뚱한 낮은 음으로 둔갑합니다. 이것이 앨리어싱(aliasing) 입니다.

규칙. 샘플링 레이트 fsf_s 로 온전히 담을 수 있는 가장 높은 주파수는 그 절반입니다. 이 값을 나이퀴스트 주파수(Nyquist frequency) 라 부릅니다.

fNyquist=fs2f_{\text{Nyquist}} = \frac{f_s}{2}

숫자로 해 보기(해설용).

  • fs=16f_s = 16 kHz → 담을 수 있는 최고 주파수는 8 kHz입니다. 사람 말소리의 핵심 정보(모음 · 자음의 특징)는 대부분 이 안에 있어 음성 인식에는 16 kHz가 흔히 쓰입니다.
  • 9 kHz 사인파를 16 kHz로 샘플링하면 ∣9−16∣=7|9 - 16| = 7 kHz 사인파와 똑같은 샘플이 나옵니다. 그래서 녹음 장비는 샘플링 전에 나이퀴스트보다 높은 성분을 걸러 내는 필터(안티앨리어싱 필터)를 둡니다.
  • 음악용 44.1 kHz는 나이퀴스트가 22.05 kHz로, 사람이 들을 수 있는 대략의 상한 근처까지 담습니다.

왜 이렇게 하나. 샘플링 레이트를 무작정 높이면 숫자가 늘어 계산 비용이 커집니다. 과제에 필요한 주파수 범위의 두 배 정도로 정하는 것이 효율적인 선택입니다. TTS처럼 음질이 중요한 과제는 22.05 kHz · 24 kHz를 자주 씁니다(다음 수업들에서 다시 나옵니다).

3. 푸리에 변환: 소리를 높이별로 나누기

직관(해설용 비유). 화음을 들으면 귀는 "도 · 미 · 솔이 섞였다"고 알아챕니다. 푸리에 변환은 이 일을 계산으로 합니다. 신호를 여러 높이의 사인파와 하나씩 비교(내적)해서, 각 높이가 얼마나 들어 있는지 점수를 매깁니다.

단계.

  1. 길이 NN 인 신호 조각을 준비합니다.
  2. 주파수 번호 k=0,1,…,N−1k = 0, 1, \dots, N-1 마다 그 주파수의 복소 사인파를 만듭니다.
  3. 신호와 사인파를 원소끼리 곱해 더합니다(내적).
  4. 결과 X[k]X[k] 의 크기 ∣X[k]∣|X[k]| 가 "그 높이의 세기"입니다.
X[k]=∑n=0N−1x[n] e−i2πkn/NX[k] = \sum_{n=0}^{N-1} x[n]\, e^{-i 2\pi k n / N}
기호뜻
X[k]X[k]kk 번째 주파수 성분(복소수)
NN조각의 샘플 수
e−i2πkn/Ne^{-i2\pi kn/N}cos⁡(2πkn/N)−isin⁡(2πkn/N)\cos(2\pi kn/N) - i\sin(2\pi kn/N), 즉 kk 번째 높이의 사인파
∣X[k]∣\lvert X[k]\rvert그 주파수의 크기(진폭에 비례)
kfs/Nk f_s / Nkk 번째 칸이 뜻하는 실제 주파수(Hz)

숫자로 해 보기(해설용, numpy로 확인). N=4N=4 일 때 e−i2πkn/4e^{-i2\pi kn/4} 는 1,−i,−1,i1, -i, -1, i 만 돌아가며 나와 손으로도 계산됩니다.

신호 xxX[0]X[0]X[1]X[1]X[2]X[2]X[3]X[3]해석
(1,1,1,1)(1,1,1,1)4000변화 없는 값(직류)만 있음
(1,0,−1,0)(1,0,-1,0)02024샘플에 한 번 도는 코사인
(2,1,0,1)(2,1,0,1)4202위 두 신호의 합 → 성분도 합

세 번째 줄을 직접 풀면 X[1]=2⋅1+1⋅(−i)+0⋅(−1)+1⋅i=2X[1] = 2\cdot1 + 1\cdot(-i) + 0\cdot(-1) + 1\cdot i = 2 입니다. 신호를 더하면 성분도 그대로 더해지는 성질(선형성) 덕분에 "섞인 소리를 높이별로 분리"할 수 있습니다. 실수 신호에서는 X[k]X[k] 와 X[N−k]X[N-k] 의 크기가 같으므로, 실제로는 앞쪽 N/2+1N/2+1 칸만 씁니다. 실제 계산은 O(Nlog⁡N)O(N\log N) 인 고속 푸리에 변환(FFT)으로 합니다.

4. 짧게 잘라 여러 번: 프레임 · 창 · 홉 → 스펙트로그램

직관. 말소리는 0.1초 사이에도 '가'에서 '나'로 바뀝니다. 문장 전체를 한 번에 푸리에 변환하면 "언제 어떤 소리였는지"가 사라집니다. 그래서 짧은 조각(프레임)으로 잘라 조각마다 변환합니다. 이것이 단시간 푸리에 변환(STFT) 이고, 결과를 시간 × 주파수 표로 늘어놓은 것이 스펙트로그램(spectrogram) 입니다.

단계.

  1. 창 길이(window length): 한 조각의 길이. 음성에서는 20~30 ms가 흔합니다.
  2. 홉 길이(hop length): 다음 조각으로 건너뛰는 간격. 보통 창보다 짧아 조각끼리 겹칩니다.
  3. 창 함수(window function): 조각 양 끝을 부드럽게 0으로 줄이는 곱셈(예: Hann 창). 끝이 뚝 잘리면 없던 주파수가 생기기 때문입니다.
  4. 조각마다 FFT → 크기의 제곱(파워) → 열 하나. 열을 시간 순으로 이어 붙입니다.
프레임 수=1+⌊L−WH⌋,주파수 칸 수=NFFT2+1\text{프레임 수} = 1 + \left\lfloor \frac{L - W}{H} \right\rfloor,\qquad \text{주파수 칸 수} = \frac{N_{\text{FFT}}}{2} + 1
기호뜻
LL전체 샘플 수
WW창 길이(샘플)
HH홉 길이(샘플)
NFFTN_{\text{FFT}}FFT 크기(보통 WW 이상)
⌊⋅⌋\lfloor\cdot\rfloor내림

이 식은 양 끝에 덧대기(padding)를 하지 않는 경우입니다. torchaudio처럼 가운데 정렬(center)로 덧대면 프레임이 조금 늘어납니다.

숫자로 해 보기(해설용). Whisper는 25 ms 창 · 10 ms 홉을 씁니다(논문 2.3절). 16 kHz에서

  • 창 W=0.025×16000=400W = 0.025\times16000 = 400 샘플, 홉 H=0.010×16000=160H = 0.010\times16000 = 160 샘플
  • 1초(L=16000L=16000): 1+⌊15600/160⌋=1+97=981 + \lfloor 15600/160 \rfloor = 1 + 97 = 98 프레임
  • 30초면 대략 30/0.01=3,00030 / 0.01 = 3{,}000 프레임(덧대기 방식에 따라 ±1)
  • NFFT=400N_{\text{FFT}} = 400 이면 주파수 칸 =201= 201 개, 칸 간격 =16000/400=40= 16000/400 = 40 Hz

즉 1초 음성 16,000개 숫자가 "98열 × 201행" 표로 바뀝니다. 참고로 torchaudio MelSpectrogram 의 기본값은 n_fft=400, hop_length = win_length // 2 (=200)라서, 10 ms 홉을 쓰려면 hop_length=160 을 직접 지정해야 합니다.

왜 이렇게 하나 — 시간과 주파수의 맞바꿈. 창을 길게 하면 주파수 칸 간격이 촘촘해지지만(정밀한 음높이), 시간 위치는 흐려집니다. 짧게 하면 반대입니다. torchaudio 튜토리얼도 n_fft 를 바꿔 가며 이 차이를 보여 줍니다. 말소리에는 25 ms 안팎이 두 요구를 적당히 절충하는 값으로 널리 쓰입니다.

데시벨. 파워 값은 범위가 너무 넓어(조용한 소리와 큰 소리가 수만 배 차이), 보통 10log⁡10(파워)10\log_{10}(\text{파워}) 인 데시벨(dB) 로 바꿔 봅니다. 파워 100은 20 dB, 0.01은 −20 dB입니다. 곱셈 차이가 덧셈 차이가 되어 모델이 다루기 쉬워집니다.

5. 멜 스케일: 귀가 느끼는 높이로 축 구부리기

직관. 사람 귀는 100 Hz와 200 Hz의 차이는 크게 느끼지만, 7,000 Hz와 7,100 Hz의 차이는 거의 못 느낍니다. 낮은 소리는 촘촘히, 높은 소리는 성기게 구분합니다. 멜 스케일(mel scale) 은 이 느낌에 맞춰 주파수 축을 다시 매긴 눈금입니다.

식. torchaudio의 기본(HTK 방식) 변환은 다음과 같습니다(torchaudio 소스의 _hz_to_mel, mel_scale="htk").

m=2595log⁡10 ⁣(1+f700)m = 2595 \log_{10}\!\left(1 + \frac{f}{700}\right)
기호뜻
ff주파수(Hz)
mm멜 값
2595, 7001,000 Hz가 약 1,000 멜이 되도록 맞춘 상수

또 다른 방식(Slaney)은 1,000 Hz 아래를 직선, 위를 로그로 이어 붙입니다. 라이브러리마다 기본값이 달라 같은 설정이라도 결과가 조금 다를 수 있으니, 학습과 추론에서 같은 방식을 써야 합니다.

숫자로 해 보기(해설용, 계산 확인).

주파수 (Hz)1002001,0002,0004,0007,0008,000
멜150.5283.21000.01521.42146.12702.42840.0
  • 100 → 200 Hz(100 Hz 차이): 132.7 멜 차이
  • 7,000 → 8,000 Hz(1,000 Hz 차이): 137.6 멜 차이

높은 곳의 1,000 Hz가 낮은 곳의 100 Hz와 비슷한 '귀 거리'라는 뜻입니다.

멜 필터뱅크(mel filter bank). 멜 축에서 같은 간격으로 삼각형 필터를 여러 개(예: 80개) 놓고, 각 필터 안의 파워를 가중합합니다. 그러면 201개 주파수 칸이 80개 멜 칸으로 줄어듭니다. 낮은 주파수 필터는 좁고 높은 주파수 필터는 넓습니다. 마지막으로 로그를 씌운 것이 로그 멜 스펙트로그램(log-mel spectrogram) 입니다.

숫자로 해 보기(해설용). Whisper 입력은 80채널 로그 멜 스펙트로그램입니다(논문 2.3절). 30초 조각이면 대략 "80행 × 3,000열" 표, 즉 약 24만 개 숫자로, 원래 48만 개 샘플보다 줄었고 무엇보다 패턴이 훨씬 뚜렷합니다. Whisper는 이 값을 전체 데이터 기준으로 −1~1 사이, 평균이 거의 0이 되게 맞춥니다.

왜 멜을 쓰나. 사람이 구분하지 못하는 높은 주파수의 미세한 차이에 숫자를 낭비하지 않고, 말소리 구분에 중요한 낮은 영역에 해상도를 몰아줍니다. 같은 이유로 Tacotron 2 같은 TTS도 80채널 멜 스펙트로그램을 중간 표현으로 씁니다(→ 이 트랙 세 번째 수업).

6. MFCC 개요와 전체 흐름

MFCC(멜 주파수 켑스트럼 계수). 로그 멜 값에 이산 코사인 변환(DCT)을 한 번 더 적용해 앞쪽 계수 몇 개(예: 13개)만 남긴 특징입니다. 옆 멜 칸끼리 강하게 얽힌 값을 서로 덜 얽힌 소수의 숫자로 압축합니다. 신경망 이전의 고전 음성 인식(가우시안 혼합 · HMM)에서 표준 특징이었고, torchaudio에도 MFCC 변환이 있습니다. 요즘 딥러닝 모델은 정보 손실이 적은 로그 멜 자체를 더 많이 씁니다.

mermaid
flowchart LR
  A[마이크 떨림] --> B[샘플링<br/>16 kHz 숫자 줄]
  B --> C[프레임 자르기<br/>25 ms 창 · 10 ms 홉]
  C --> D[창 함수 곱하기<br/>Hann]
  D --> E[FFT → 파워<br/>201 주파수 칸]
  E --> F[멜 필터뱅크<br/>80 멜 칸]
  F --> G[로그<br/>로그 멜 스펙트로그램]
  G --> H[음성 인식 · 합성 모델 입력]
  G --> I[DCT → MFCC<br/>고전 방식]

연습 문제

  1. 샘플링 레이트 24 kHz의 나이퀴스트 주파수와, 2초 음성의 샘플 수를 구하세요.
    • 풀이: 24/2=1224/2 = 12 kHz, 24,000×2=48,00024{,}000\times2 = 48{,}000 개입니다.
  2. x=(0,1,0,−1)x = (0, 1, 0, -1) 의 DFT를 구하세요.
    • 풀이: X[0]=0X[0] = 0, X[1]=0⋅1+1⋅(−i)+0+(−1)⋅i=−2iX[1] = 0\cdot1 + 1\cdot(-i) + 0 + (-1)\cdot i = -2i, X[2]=0X[2] = 0, X[3]=2iX[3] = 2i. 크기는 (0,2,0,2)(0, 2, 0, 2) 로 (1,0,−1,0)(1,0,-1,0) 과 같습니다. 모양(위상)만 다르고 같은 높이의 사인파라는 뜻입니다.
  3. 16 kHz, 창 400 · 홉 160(덧대기 없음)에서 2초 음성의 프레임 수는?
    • 풀이: 1+⌊(32000−400)/160⌋=1+197=1981 + \lfloor(32000-400)/160\rfloor = 1 + 197 = 198 프레임입니다.
  4. 멜 식으로 700 Hz는 몇 멜인가요?
    • 풀이: 2595log⁡10(1+1)=2595×0.30103≈781.22595\log_{10}(1+1) = 2595\times0.30103 \approx 781.2 멜입니다.
  5. 12 kHz 소리를 16 kHz로 샘플링하면 어떤 주파수로 보이나요?
    • 풀이: 나이퀴스트 8 kHz를 넘으므로 앨리어싱되어 ∣12−16∣=4|12-16| = 4 kHz로 보입니다.

스스로 점검

  1. 왜 문장 전체가 아니라 25 ms 조각마다 푸리에 변환을 하나요?
    • 답: 말소리는 짧은 시간 안에 계속 바뀌므로, 조각마다 변환해야 "언제 어떤 높이의 소리였는지"가 남기 때문입니다.
  2. 창을 길게 하면 무엇을 얻고 무엇을 잃나요?
    • 답: 주파수 칸이 촘촘해져 음높이 구분이 정밀해지지만, 한 조각이 긴 시간을 덮어 시간 위치가 흐려집니다.
  3. 멜 필터뱅크가 높은 주파수 쪽 필터를 넓게 만드는 이유는?
    • 답: 사람 귀가 높은 주파수의 작은 차이를 잘 구분하지 못하므로, 그 영역을 넓게 묶어 숫자를 아끼고 중요한 낮은 영역에 해상도를 몰아주기 위해서입니다.

용어 정리

용어쉬운 뜻
파형(waveform)시간에 따른 소리 압력 값을 숫자로 적은 줄
샘플링 레이트1초에 값을 몇 번 재는지(Hz)
나이퀴스트 주파수샘플링 레이트의 절반, 담을 수 있는 최고 주파수
앨리어싱너무 높은 주파수가 낮은 주파수로 잘못 보이는 현상
푸리에 변환(DFT · FFT)신호를 주파수별 성분으로 나누는 계산(FFT는 빠른 방법)
프레임 · 창 · 홉잘라 낸 조각, 조각 길이와 모양, 조각 사이 간격
스펙트로그램시간 × 주파수 표로 나타낸 소리의 세기
데시벨(dB)세기를 로그로 바꾼 단위
멜 스케일사람이 느끼는 음높이에 맞춘 주파수 눈금
멜 필터뱅크멜 눈금에 맞춰 놓은 삼각형 필터 묶음
로그 멜 스펙트로그램멜 필터뱅크 출력에 로그를 씌운 표, 음성 모델의 표준 입력
MFCC로그 멜에 DCT를 적용해 압축한 고전 음성 특징

더 깊이 보려면

  • torchaudio 튜토리얼 「Audio Feature Extractions」 — n_fft 를 바꿨을 때 스펙트로그램이 어떻게 달라지는지 그림과 코드로 확인할 수 있습니다.
  • Hugging Face Audio Course 1단원(오디오 데이터 다루기) — 같은 내용을 librosa · datasets 코드로 실습합니다.
  • Whisper 논문 2.3절 — 실제 대형 모델이 쓰는 입력 설정(16 kHz · 80채널 · 25 ms/10 ms · 30초 조각).

다음에 볼 것

라이선스

본문은 KAITABASE 자체 해설입니다. 참고 자료 torchaudio(코드 · 문서 저장소)는 BSD 2-Clause 라이선스입니다. DFT · 프레임 · 멜 숫자 예는 이 수업을 위해 만든 해설용 예이며 numpy로 계산을 확인했습니다.

출처

AI 원리부터 이해하기 · 음성 모듈

음성 모듈 학습

이 글은 음성 모듈의 학습 자료입니다. 전체 3개 자료 중 1번째입니다.

AI 기초 과정은 현재 진도 저장을 지원하지 않습니다.

출처·원문

원문 보기

요약만

본문 자체 작성 · 참고 자료 torchaudio(BSD 2-Clause)