audio_background AI audio codec 오디오압축

Audio Codec: 전통적 압축방식

Kwangjin Park

Aug 13, 2025 · 7 min read

Follow

1. 압축이 필요한 이유

  • 원본 파형은 1초에 44,100 x 16비트 = 705,600비트 → 대략 88KB 용량의 데이터 생성
  • 3분 길이의 노래를 기준으로 했을 때, 88 KB × 180초 ≈ 15.8 MB → 저장 및 전송에 부담되는 용량 / 불필요하거나, 들리지 않는 정보 제거하여 용량 축소의 필요성

왜 44,100번 샘플링을 사용하는가?

CD 품질 기준에서 1초에 44,100번 소리를 기록한다는 것은, ==디지털 오디오에서 가장 널리 쓰이는 표준 Sampling rate인 44.1kHz==를 의미 이 숫자는 1970년대 후반부터 소니와 필립스가 공동 개발한 오디오 CD(Compact Disc) 규격에서 채택된 값 여러 기술적, 역사적 이유가 복합되어 결정된 표준 Sampling rate → “1초에 44,100번”

인간 청각 범위 고려 (나이퀴스트 이론)

  • 인간이 들을 수 있는 소리의 최대 주파수 → “약 20kHz”
  • 나이퀴스트 샘플링 이론에 따르면, 어떤 신호도 ==최대 주파수의 두 배 이상 샘플링== 해야 정보를 잃지 않고 복원 가능 → 최대 20kHz 주파수를 정확히 포착하려면 ==최소 40kHz 이상== 샘플링 해야함
  • 44.1kHz는 이 기준을 충족하면서 마진을 두어 22.05kHz까지 정확한 복원이 가능하게 만든 Sampling rate

2. 전통적 코덱의 작동 원리

1) 아날로그 신호의 디지털 변환(ADC)

  1. 아날로그 신호 입력: 음성 입력 장치(마이크 등)으로 입력되는 공기의 입력 진동(아날로그 파형) → 전기신호로 변환
  2. 샘플링(Sampling): 입력된 아날로그 신호를 일정 시간 간격으로 나눠서 진폭 값 측정
  3. 양자화(Quantization): 측정된 연속적 진폭 값 → 비트 뎁스(16비트, 24비트 등)에 맞추어 유한한 단계로 반올림 → 모든 샘플이 비트 뎁스에서 지정한 레벨의 샘플로 저장될 수 있게 변환
  4. PCM(Pulse-Code Modulation) 저장
    • 샘플링 + 양자화된 데이터(PCM) → 임시 버퍼 또는 파일로 기록

2) 인코딩: 신호 변환 및 압축 단계

  1. 블록 분할 및 윈도우
    • PCM 데이터를 일정 길이(예: 20ms) 단위로 자름
    • 각 블록에 윈도우 함수(해밍·해닝 등)를 곱해 블록 끝단 끊김 시 생기는 불연속성을 완화
      • 블록 단위로 자르다 보면, 파형이 블록 끝에서 갑자기 뚝 끊어지는 경우 발생
      • 경계 불연속성 발생 → 주파수 변환 시 인공적 잡음 발생 원인
      • 윈도우 함수: 블록의 양 끝으로 갈 수록 0에 가까워지고, 가운데는 1에 가까워지는 곡선
      • 블록에 윈도우 함수를 곱하면? → 양쪽 끝이 부드럽게 0으로 떨어지며 끊김 → 인공적인 불연속이 매우 부드러운 꼬리로 자연스럽게 연결
  2. 시간 → 주파수 변환
    • 각 블록을 MDCT(Modified Discrete Cosine Transform) 등으로 변환
      • 시간 도메인 샘플 → 주파수 도메인 계수(coefficient)
      • 전반적 파형을 여러 주파수 성분(0Hz, 100Hz, 1kHz …)으로 분해
  3. 심리음향 모델(Psychoacoustic Model)
    • 인간 청각 특성을 모사 → “들리지 않는 성분” 제거
      1. 청각 마스킹: 일정 주파수에서 큰 소리가 있을 때, 인접 주파수의 작은 소리는 귀에 들리지 않음
      2. 임계 대역 계산: 주파수 대역별로 귀의 민감도를 반영
      3. 무손실 제거: 사람이 느끼지 못할 계수(마스킹된 계수)는 0으로 설정하거나 크게 감쇠
  4. 비트 할당(Bit Allocation)
    • 심리음향 결과를 바탕으로 주파수 계수별 비트 수 결정
      • 큰 성분(귀에 중요한 계수) → 더 많은 비트
      • 작은 성분(들리지 않거나 덜 중요한 계수) → 적은 비트
  5. 양자화(Quantization)
    • ADC 단계에 이어, 두번째로 양자화 과정을 거침
      • 디지털 음원을 용량 제한(비트레이트)에 맞추기 위하여 → 다시 근사시켜 데이터량 줄임
    • 주파수 계수(실수값)를 할당된 비트 수 만큼의 단계로 반올림
      • ex) 12kbps(bps: 1초에 몇 개의 bit로 데이터를 저장/전송 가능한지) 목표 → 총 비트 예산 내에서 각 대역별 양자화 레벨 결정
  6. 엔트로피 부호화(Entropy Coding)
    • 양자화된 이산 값(인덱스)을 허프만 코딩 또는 산술 코딩으로 추가 압축
      • 자주 등장하는 심볼 → 짧은 코드워드
      • 드문 심볼 → 긴 코드워드
    • Entropy Coding을 통해 추가적 용량 압축을 수행하는 이유
      • 중복(비효율) 제거, 저장 용량 추가 절약
        • 양자화 결과, 실제로 등장하는 값(인덱스들)은 자주 등장하는 값이 있고, 거의 안 나오는 값이 있음
        • ex) 양자화 후 “0”이 80%일 때, 모든 값을 8비트(00000000~11111111)로 같은 크기로 저장하면 용량 낭비
        • ==“0”은 매우 짧게, “희귀값”은 좀 더 길게 부호화==하면 전체 데이터 크기를 대폭 줄일 수 있음
      • 심볼 확률을 활용한 효율 최적화
        • 데이터에 실제로 어떤 값들이 얼마나 자주 등장하는지 통계적으로 분석하면, 그 분포에 최적화된 부호화 방법(허프만, 산술 등) 적용으로 더 적은 비트로 저장 가능
    • 압축 과정
      • (1) 양자화 후 데이터 수집
        • ex) 16단계(4비트)로 양자화했다면 → 0, 1, 2, … 15의 정수 인덱스가 나열됨 (예: 0,0,1,0,2,0,1, …)
      • (2) 데이터 분포(=빈도) 조사
        • ex) 위의 정수 인덱스의 분포를 확인해보면
          • “0”이 60%
          • “1”이 20%
          • “2”가 10%
          • 드물게 “3, 4, 5 …”
      • (3) 최적화된 부호표(코드북) 생성
        • 허프만 코딩(Huffman Coding)
          • 등장 빈도가 가장 높은 값(예: 0)에 가장 짧은 비트 코드(1비트, 예: “0”) 할당
          • 덜 나오는 값에 그보다 긴 코드(예: “10”, “110”, “1110” …)
          • 전체 데이터(양자화 인덱스열)를 이 코드로 치환 → 평균적으로 필요한 비트 수 감소
          • ex) 위의 정수 인덱스를 허프만 코딩에 의해 치환해보면
            • “0” → 0
            • “1” → 10
            • “2” → 110
            • “3” → 1110
          • 허프만 코딩에서 가장 많이 등장하는 인덱스(숫자)는 ==기존 숫자의 실제 크기(값)와는 전혀 무관하게== 가장 짧은 코드로 부여
            • ex) 만약에 양자화 인덱스 15가 가장 빈도가 높다 할지라도, 15라는 숫자와 관계없이 가장 짧은 코드인 “0”부여
        • 산술코딩(Arithmetic Coding)
          • 전체 데이터를 하나의 실수 구간(0~1 부동소수점) 내의 “좌표”로 변환
          • 빈도 높은 심볼은 구간을 넓게, 낮은 심볼은 아주 좁게 할당
          • 전체 데이터열을 단 하나의 부동소수점(혹은 그에 대응하는 비트열)로 압축
          • 허프만보다 더 세밀한 최적화(이론상 최저 엔트로피 부호화)에 근접
            • 허프만 코딩은 심볼별 “비트 단위”로만 코드를 나누는 것에 비해, 산술코딩은 “심볼 확률”이 아주 애매하게(예: 0.13, 0.19 등) 나올 때에도 이를 그대로 소수구간의 “길이”로 반영해줌
          • 산술코딩 과정 예시
            1. 심볼별 확률 구간 정하기
              • 데이터열의 심볼들과 등장 확률을 아래와 같이 가정
                • A (80%), B (15%), C (5%)
              • 0~1 사이의 “실수 범위”를 확률에 따라 구간으로 나눔
                • A: 0.00 ~ 0.80
                • B: 0.80 ~ 0.95
                • C: 0.95 ~ 1.00
            2. 좌표 압축 (데이터열 길이만큼 반복 세분화)
              • 데이터열이 “ABAC”라면
              • 0번째 단계(전체 0~1)
                • 첫 문자 ‘A’ → A구간(0.00~0.80)로 범위 압축
              • 1번째(0.00~0.80)
                • 다음 문자 ‘B’ → B구간은 이 안에서 0.80~0.95이므로,
                • “0.00~0.80”의 범위를 거기 비율로 다시 쪼개면 → 실제 범위는 0.64~0.76, 이렇게 반복적으로 세분화
              • 2번째(‘A’):
                • 현재 구간(0.64~0.76) 내에서 또 ‘A’구간(80쯤)만큼 재세분화…
              • … 마지막까지 반복 → 결국, 전체 데이터열은 ==점점 더 좁은 “실수 범위”에 딱 맞게 압축==됨
            3. 최종 소수(좌표)만 기록
              • 마지막 남은 구간의 임의의 점(소수점 좌표)을 기록하면 → 해당 점의 정보와 함께 코드북(확률표)을 참고해 역으로 데이터를 복원 가능
      • (4) 비트스트림으로 패키징
        • 부호화(코딩)된 비트열, 코드북/코딩 정보 등과 함께 묶음 → 전송/저장 가능한 패키지(비트스트림)로 완성
    • 압축 결과: 비트스트림(bitstream) 형식으로 패키징(MP3, AAC, OGG, FLAC 등 파일 포맷)

3) 저장 또는 전송

  • 생성된 압축 비트스트림을 파일(MP3, AAC 등)로 저장하거나 네트워크로 전송
  • 플레이어/디코더는 이 비트스트림을 받아 복원(디코딩) 준비

4) 디코딩: 복원 단계

  1. 엔트로피 역부호화(↔ 엔트로피 부호화)
    • 인코딩 때: 허프만/산술 코딩 사용 → “양자화 인덱스”를 ‘0,1’ 비트열의 짧은 코드로 바꿔 패키징
    • 디코딩 때: 역부호화
      • 저장된 비트 코드 해석
      • 다시 “양자화 인덱스”(정수 값의 배열)로 변환
  2. 역양자화(디퀀타이즈, ↔ 양자화)
    • 인코딩 때: 실수 계수 → 제한 비트수로 반올림(이산 인덱스)
    • 디코딩 때: 역양자화
      • 인덱스 값을 “코드북/레벨 표” 참조
      • 약간의 오차가 있지만, 실수 계수(근사값)로 복원
  3. 역변환(역MDCT, ↔ 주파수 변환(MDCT))
    • 인코딩 때: 시간 영역 샘플 → 주파수 영역 계수(MDCT 등)
    • 디코딩 때: 역변환
      • 복원된 주파수 계수를 역MDCT(Inverse MDCT)로 시간 도메인 샘플로 다시 합성

1-3번 과정은 인코딩 과정의 완벽한 역과정 손실압축 코덱(MP3 등)은 정보 손실(근사, 버림)이 이미 인코딩/양자화 때 발생했으므로, 복원 후 신호는 ==완전히 원본과 동일하지는 않지만==, 역연산으로 최대한 원본과 가까운 소리 파형을 재구성

  1. 블록 합성(Overlap-Add)
    • 블록 합성의 필요성 초기에 인코딩 단계에서, 디지털화한 전기신호를 20ms 단위로 블록화하여 인코딩을 하였음. 이 블록들은 변환(주파수 분석, 압축, 역변환 등) 과정을 따로 거쳐 복원되는데, 블록 단위로 따로 복원하면 경계가 딱딱 끊어져 연결부에서 잡음이나 이질감(“블록 경계 잡음”, “릿지 효과”)이 생길 수 있음.
    • 블록 합성 처리 과정
      • 인코딩 → 윈도우 함수(예: 해밍/해닝)를 곱해 블록의 양쪽이 부드럽게 0으로 가게 처리했는데,
      • 디코딩 → ==인접 블록이 겹치는 구간만큼 더해서== 매끄럽게 합성(Overlap–Add)
      • ex) 블록 A와 블록 B가 아래와 같이 있을 때,
        • 블록A: —-####__
        • 블록B: –####——
        • 위 두 블록의 #### 부분에서 ==값이 겹치게 더해져== “자연스럽게” 이어짐 → 결과적으로 전체 오디오 신호가 끊김이나 잡음 없이 자연스럽게 연결
  2. 후처리(Filter/Post-processing) 역변환(역MDCT 등)과 블록 합성을 마쳐 시간영역 연속 파형이 복원되었더라도, 압축·복원 과정에서 생기는 각종 ==잔여 왜곡, 잡음, 대역 손실 등을 보정==하는 후처리 단계
    • 후처리 종류
      • 필터링(Filter)
        • 디코딩 잡음 제거: 압축 과정에서 생긴 작은 인공 잡음(quantization noise, ringing, pre-echo 등) 감쇄를 위한 필터 적용 가능
        • 대역 보정(Band correction): 압축 단계에서 약화된 저역/고역 주파수 성분을 추가적으로 증폭 또는 감쇠(이퀄라이징)해 원음에 더 가깝게 만듦.
          • 이퀄라이제이션(Equalization): 사용자, 서비스 목적에 맞는 추가 보정
            • 저역(베이스) 쪽이 약하면 조금 도드라지게
            • 고역(트레블) 구간이 거칠면 살짝 깎거나 강조하는 등
      • 음향 효과(Post Effects)
        • 필요에 따라 여러 후처리 음향 효과도 적용 가능 → 리버브(공간감 부여), 노이즈 셰이핑(소음 스펙트럼을 덜 거슬리게 변형) 등
    • 후처리 완료 이후 → 디지털 오디오 파형(PCM, 샘플 데이터)의 형태로 출력
  3. 디지털→아날로그 변환
    • 최종 PCM(또는 실수 파형)을 DAC(Digital-to-Analog Converter) 로 보내 전기 신호로 변환: 각 디지털 샘플(숫자)이 1:1로 대응하는 전압 레벨을 만들어냄
    • 앰프→스피커를 통해 공기 압력 진동(아날로그 오디오)으로 재생
chat_bubble 0

chat_bubble 댓글남기기

댓글남기기