0. Neural Audio Codec 개요: vs. 전통적 오디오 코덱
- 전통적 코덱(MP3, AAC 등)
- 수학적 변환(MDCT 등) + 심리음향 모델 + 허프만 코딩 등 여러 단계를 순차적으로 거침
- Neural Audio Codec
- ==딥러닝 신경망 하나==가 전체 압축·복원 과정을 “학습”으로 처리
- ==딥러닝 신경망 하나==가 전체 압축·복원 과정을 “학습”으로 처리
1. Neural Audio Codec 압축과정
1) 입력: Raw 오디오 신호
- PCM 데이터(ex: 44.1kHz, 16비트 샘플)를 입력으로 받음 → 전통적 코덱과 동일
- 전처리 과정(블록 분할 및 윈도우 함수 적용 등)은 신경망이 자동 학습 → 전통적 코덱과 차이
2) Encoder 단계
Neural Audio Codec은 전통적 코덱과 달리, ==신경망에 기반하여 오디오의 특징을 추출==함
- 백본 아키텍처
- Convolutional Neural Network(CNN) 또는 Transformer 등을 사용 → 전체 압축 성능, 효율, 시간지연(지연시간), 복원 품질에 큰 영향
- 실제 사용되는 주요 백본 종류 1) CNN(Convolutional Neural Networks) 기반 - 대표 사례 - Meta의 Encodec: 완전 CNN 기반 인코더/디코더 - Google의 SoundStream: 주로 CNN 구조, 일부 RNN으로 보조 - CNN 기반 백본의 강점 - 오디오 신호도 시간축에서 ==국소적 연속 패턴==이 강함 → ==CNN이 패턴 추출에 유리== - 인접 샘플 간 “국소적” 특징(음색, 어택 등) 처리가 정확 - 계산 효율이 높고, 실시간 처리에 적합 2) RNN(Recurrent Neural Network) 보조/혼합형 - 대표 사례 - Google SoundStream: CNN 백본에 “게이트 순환(F-GRU)” 종류 RNN 모듈로 시간적 장기 의존성 보완 - RNN은 단독으로는 잘 활용되지 않음 - 순차 연산 위주라 처리 속도가 느리고, 병렬화에 약함 - 초고음질용, 실시간 대역폭, 장시간 입력 등에서는 한계 → CNN이 기본, RNN은 ==시간 구조 잡는 보조==로만 활용 3) Transformer(Attention) 기반/혼합형 - 대표 사례 - Tencent HiFi-Codec: CNN → Transformer 구조 - 왜 Transformer? - ==장기 의존성 특징 추출==에 매우 강함(전체 신호 컨텍스트 한꺼번에 처리) - ==최근 Trend → “CNN+Transformer” 조합== - 오디오 신호의 시간축 구조와 딥러닝의 공간/시간 패턴 인식 능력이 만나는 지점에서, - 국소(로컬) 특징 → CNN - 전역(글로벌) 특징, 장기 상관, 리듬 감지 등 → Transformer - 성능(음질/압축률) / 실시간성(지연) / 계산비용의 현실적 타협 측면에서 이 두 구조가 가장 효율적으로 검증됨 - 실제로는 둘을 “겹쳐 조합”해서 최고의 장점을 얻으려고 많이 시도 - 단점 - 계산량 많고, 모델이 커지면 리소스 소모도 급증 - 제한된 실시간 애플리케이션에서는 순수 Transformer만 사용은 현실적으로 드뭄
- 백본 아키텍처의 역할
- 입력 오디오를 ==압축된 잠재 표현(latent representation)==으로 변환
- 전통적 방식의 “주파수 계수”와 비슷하지만, 신경망이 스스로 학습한 최적의 특징
- 예: 1초 오디오 → 128차원 벡터 × 50개 (시간축 압축)
- 입력 오디오를 ==압축된 잠재 표현(latent representation)==으로 변환
- 오디오 특징 추출 과정(CNN+Transformer 기준)
- 입력: 연속 오디오 샘플
- ex) 1초짜리 44.1kHz 모노 PCM ->
[x₁, x₂, ..., x₄₄₁₀₀](44,100개 float값) - 위와 같은 시퀀스가 Neural Encoder의 입력으로 들어감
- ex) 1초짜리 44.1kHz 모노 PCM ->
- 1차원 CNN
- 오디오 샘플의 데이터 형태에 가장 알맞는 신경망
- 적용 패턴별 장단점
- 한 번의 Conv로 “특징 추출 + 다운샘플”을 동시에
- 구성: Conv1D(kernel=k, stride=s>1) → Norm → Activation
- 동작:
- 필터가 로컬 패턴을 감지(특징 추출)
- 동일 연산에서 stride=s로 시간축을 s배 줄임(다운샘플)
- 장점: ==연산/메모리 효율 좋고== 구현 간단. 실시간 파이프라인에 적합.
- 특징 추출(conv, s=1) 후 “따로” 다운샘플(conv/pool, s>1)
- 구성: (Conv(s=1) → Norm → Act) × n → Downsample(Conv s>1 또는 Pool)
- 동작:
- 먼저 stride=1로 촘촘히 패턴을 강화/정제(특징 추출을 더 풍부하게)
- 그 다음 단계에서 stride>1(conv) 또는 pooling으로 길이 축소
- 장점: Downsampling 전, 더 ==고급 특징==을 만들어 안정적으로 요약.
- 1,2번 방법 하이브리드(권장 실전 템플릿)
1) conv(s=1) 1~2개로 먼저 “유용한 패턴 강화”
2) conv(s=2)로 Downsampling
3) 필요 시 AvgPooling을 얕게 섞어 에너지 안정화
- 각 단계마다 채널 수는 증가시켜 표현력 확보
- 한 번의 Conv로 “특징 추출 + 다운샘플”을 동시에
- 1차원 CNN 적용과정
1) Local 단위 패턴 뽑기
여러 개의 필터(커널)가 정해진 짧은 구간(8~64샘플)마다 “슬라이딩”
→ “음의 경계, 리듬, 어택(건반 치는 순간), 웨이브 형태 등” 로컬 패턴 감지
- 예시
- 입력:
[10,000, 9,990, 10,005, ...]- CNN 필터 작동: - 필터1 : $0.8x₁ + 0.2x₂ - 0.4*x₃$ … (8샘플씩 묶어) - 여러 개의 필터는 각자 다른 ==음색/파형 패턴==에 특화됨 - 필터가 64개라면, 64개의 새로운 시퀀스가 생김 → Feature Map(Feature Channel)” - 후처리: Activation Function - 필터의 가중합 결과를 그냥 두지 않고, 활성화 함수를 통과시킴 → 강하게 맞는 곳만 살리고, 약한 곳은 줄여줌 2) Downsampling(축소) - 특징은 남기고 길이는 줄임 → 연산량↓, 잡음/세부변동↓, 요약↑ - 1초 신호 → 44,100 → 11,025 → 2,756 … - 각 레이어, 시간 해상도는 줄이고 (정보압축) - 필터(채널) 수는 늘림 (특징 다양성↑) - 결과: (수백 ~ 수천개 채널)(수십~수백개 시점) 특징 텐서 생성
- Transformer Layer → “선택사항”
- CNN만으로는 장기 구조(예: 멜로디 흐름, 전체적 리듬)를 잡기 어려움 → Transformer 블록 추가 통과
- Self-attention 메커니즘이 전 구간(또는 넓은 창) 패턴을 한꺼번에 감지
- ex) “앞부분 도~미~솔 진행 이후 1.2초 후에 반복됨” 같은 구조 파악
- 다양한 채널/포지션간 상관관계를 동적으로 연결
- Non-Linearity + Normalization
- 사이사이 비선형 활성화 함수(ReLU/SiLU 등)로 복잡한 모양도 포착
- BatchNorm/LayerNorm 등을 붙여 데이터 분포를 안정화
- 목적: 네트워크가 오버플로우 없이 전체 입력에 대해 고루고루 반응하도록
- 마지막 Conv./Linear Layer: 시간 축 / 채널 축에 맞춰 마지막 변환
- 시간 축: 해상도(원하는 토큰 레이트로)
- 앞단을 통과한 출력 결과를 곧바로 토큰화하기엔 시간 해상도가 과할 수 있음: T′(기존 시간축) = 1,000 스텝 / 토큰은 20ms 간격(초당 50개) → N=50만 필요
- 대표 방법 3가지
- Strided Conv1D
- Conv1D(kernel=k, stride=s)로 시간축을 s배 줄임.
- ex: T′=1,000 → stride=20 → 50 스텝
- Average Pooling / Frame Slicing
- 20ms씩 분할해 평균(혹은 가중 평균)으로 하나의 벡터로 요약
- 간결하지만 학습 유연성은 낮음
- Attention-based pooling
- 각 토큰 시간창마다 가중치를 학습해 중요 부분만 더 크게 반영(soft attention 가중 평균)
- Strided Conv1D
- 실행 결과: 시간축 T′ → N(ex: 50)으로 맞춰진 텐서 생성
- 채널 축: 목표 잠재공간(latent space)
- 현재 특징 채널 C′(예: 768, 1024) → VQ 코드북/양자화나 이후 디코더가 기대하는 차원(예: 128~1024)과 다를 수 있음
- 대표 방법(조합 가능)
- LayerNorm/GroupNorm
- 토큰별로 채널 분포를 안정화(평균0, 분산1 등) → 양자화 안정화, 훈련 수렴성 증가.
- 1x1 Conv1D 또는 Linear
- 각 토큰 벡터에 선형 변환 $W ∈ R[C′, Dlatent]$ 적용.
- $H[n] → z[n] = H[n]·W + b$
- 비선형 활성화(선택)
- SiLU/GELU 등을 한 번 더 붙여 비선형 표현력 강화
- LayerNorm/GroupNorm
- (선택, Residual VQ가 여러 단계 수행된 경우) Latent space 분할(멀티헤드)
- 각 스테이지에 최적화된 서브공간을 분리 → 각기 다른 VQ 스테이지에 투입 / Dlatent를 여러 그룹으로 쪼개 병렬 VQ(코드북) 적용
- 시간 축: 해상도(원하는 토큰 레이트로)
- Latent representation 출력
- 결과:
[z₁, z₂, ..., z₅₀](각 z는 512차원 등 벡터) - 각 벡터 $z$가 담고 있는 내용
- 국소 파형, 음색, 리듬, 전체 악기/보컬 구조, 심지어 “사람 귀에 중요한 정보” 등
- 네트워크가 학습으로 뽑은 패턴들이 정보 압축된 형태로 갇혀 있음
- 결과:
- 입력: 연속 오디오 샘플
- 자동 특징 학습
- 사람이 설계한 MDCT 대신, 신경망이 데이터로부터 학습한 최적의 변환
- 심리음향 모델도 신경망이 암묵적으로 학습 (사람이 들을 수 없는 부분 자동 감지)
3) 양자화(Quantization) 단계
인코더를 통한 오디오 특징을 추출함 → 양자화 단계로 넘어가기 전 전처리 단계 필요 전처리 단계
- 정규화
- Latent representation이 너무 크거나 작을 경우, 양자화 시 정보 손실이 불필요하게 커질 수 있음
- 정규화를 통해 양자화 성능 보장 및 학습 안정성 향상
- 이를 방지하기 위한 정규화 과정으로서, LayerNorm / BatchNorm 등을 적용 → 각 벡터의 차원을 정규화(평균 0, 분산 1)시켜주기 위한 과정
- 다운샘플링 및 치환
- Encoder에서 출력된 특징 벡터의 시퀀스 길이가 너무 길거나 복잡할 경우 → 실제 비트레이트에 맞게 정보량 축소
- 다운샘플링 → 시간 축의 해상도를 낮춰줌
- 치환/압축 → 양자화에 최적화된 배열로 재구성(임베딩 차원 수, 벡터 그룹핑 등)
- 양자화 준비
- VQ를 바로 적용해줄 수 있도록 준비하는 과정
- 입력분포가 균일하거나, 학습된 코드북 분포와 비슷하도록 해줌(안정적 분포)
- 필요시 추가 처리(비선형 변환(activation), 수치 제한(clipping), flatten, chunk split 등)
- VQ를 바로 적용해줄 수 있도록 준비하는 과정
- 양자화 모듈로 전달
양자화 단계: Vector Quantization (VQ) 또는 Residual VQ 전통적 방식의 “스칼라 양자화” 대신 벡터 양자화 사용
- 코드북(Codebook)란?
- 훈련에서 “음파 벡터” 백만 개를 관찰
- 그 중, 비슷한 벡터 그룹들마다 중심(대표) 벡터만 뽑아 저장 (예: 1024개 = 코드북 0번~1023번 벡터)
- 양자화 과정(Vector Quantization)
- 인코더 출력(잠재 벡터)을 가장 가까운 코드북 벡터로 근사
- 인코더의 출력: 잠재 벡터
- “잠재 벡터-코드북의 각 벡터” 간 거리 측정
- 그 중, 가장 거리가 가장 가까운 대표 벡터를 찾음(코드북 내 한 줄)
- 해당 잠재벡터는 가장 가까운 코드북 벡터의 인덱스 값으로 기록됨
- 1-4의 과정을 모든 잠재 벡터에 대해 반복
- 결과: 연속값 → 이산 인덱스 (전송/저장용)
- ex) 벡터 수가 100개라면 인덱스열만 남음: (12, 38, 574, 700, 220, …)
- 인코더 출력(잠재 벡터)을 가장 가까운 코드북 벡터로 근사
- Residual Quantization: VQ를 여러 단계로 연속 적용하여 더욱 정밀한 근사
- RVQ의 구체적 작동 과정
- 1단계 VQ: 원본 벡터를 코드북1(1단계 VQ에서 사용하는 코드북)에서 가장 가까운 벡터로 근사
- 잔차(Residual) 계산: 원본 - 1단계 근사값 = 잔차1
- 2단계 VQ: 잔차1(1단계 VQ 이후의 잔차)을 코드북2에서 가장 가까운 벡터로 근사
- 잔차 계속: 잔차2 = 잔차1 - 2단계 근사값
- 반복: 보통 8단계까지 반복
- RVQ의 코드북: 단계별로 목적이 다름
- 코드북1
- 인코더가 처음 뽑은 “원본 잠재 벡터”들을 가장 잘 근사할 수 있게 학습됨.
- 코드북2
- 코드북1로 근사한 뒤에 남은 “잔차(오차, residual)” 벡터들을 근사할 수 있게 학습됨.
- 코드북3
- 2단계까지 근사하고도 남은 잔차를 또다시 가장 잘 근사하도록 학습됨.
- 동일하게 남은 단계 반복
- 2단계부터는 ==이전 코드북이 커버하고도 남는 세밀한 차이만 집중==해서 대표 벡터 뽑음 → 각 단계 코드북은 서로 “최적화 목표(학습 데이터 분포)”가 달라짐
- 2단계부터는 ==이전 코드북이 커버하고도 남는 세밀한 차이만 집중==해서 대표 벡터 뽑음 → 각 단계 코드북은 서로 “최적화 목표(학습 데이터 분포)”가 달라짐
- 코드북1
- RVQ의 구체적 작동 과정
4) 압축 비트스트림 생성
- 엔트로피 부호화
- 양자화된 인덱스를 확률 모델에 기반하여 압축 (예: Range ANS)
- 전통적 허프만 코딩보다 더 효율적인 신경망 기반 엔트로피 모델 사용
- 구체적 과정:
- 양자화 결과 분석
- 인덱스가 나열된 벡터 형태
- 확률분포 파악 → 신경만 기반 확률 모델 활용
- ‘이전 토큰들’, ‘문맥 정보’, 또는 잠재 벡터 등을 입력받아
- 다음 토큰이 무엇일 확률 분포(예: 인덱스 13번 = 60%, 인덱스 7번 = 20%, …)를 조건부로 예측
- 엔트로피 코더 선정 → Range ANS
- Range ANS: 오디오 토큰, 혹은 인덱스가 등장할 확률에 기반해 비트열을 만들어 저장/전송하는 무손실 압축 방식
- 정수 기반 연산으로 빠르게 연산 가능 + ==분수 단위로 비트열을 생성== → 이론상 성공할 수 있는 최저 비트로 매우 유연하게 쪼개어 코딩 가능한 것이 특징 (정수 비트만 활용할 수 있는 허프만 코딩과 가장 큰 차이)
- 실제 압축
- ex) 확률분포 결과에 의거한 압축 결과
- 자주 나오는 12 → “0” (1비트)
- 보통인 574 → “101” (3비트)
- 드문 700 → “1100111” (7비트)
- ex) 확률분포 결과에 의거한 압축 결과
- 양자화 결과 분석
- 비트스트림 패키징
- 이렇게 압축된 인덱스(=비트스트림) → 헤더와 메타데이터 부착 → 최종 파일/스트림
- 패키징 구성 내용
- 헤더 - 코덱 정보, 샘플레이트, 압축 비트레이트, 복원에 필요한 모델 파라미터(각종 코드북, 양자화 엔트로피 모델 파라미터)
- 코드북 - VQ 코드북들 (디코딩시 필요)
- 엔트로피 모델 파라미터 - 확률 분포 정보
- 압축된 인덱스 데이터(비트스트림) - 실제 오디오 데이터
- 메타데이터 - 길이, 채널수 등
- 헤더 - 코덱 정보, 샘플레이트, 압축 비트레이트, 복원에 필요한 모델 파라미터(각종 코드북, 양자화 엔트로피 모델 파라미터)
- 기타 패키징 사항
- 프레임/패킷 구조화
- 오디오 전체 데이터를 일정 구간(ex: 20ms~100ms)마다 프레임(혹은 패킷)으로 쪼갬
- 각 프레임 → (프레임 헤더)(프레임 비트스트림)(오류 검출부) 등으로 구성
- 프레임 구조는 스트리밍, 오류 복구, 구간 탐색 등을 쉽게 해
- 오류 검출·복원 정보 포함
- 경우에 따라 함께 추가
- 목적: 네트워크/무선 전송 등 환경에서 오류나 손실에 대응하기 위함
- 컨테이너(파일 포맷) 최종 패키징
- 이렇게 만들어진 비트스트림(프레임, 메타데이터 포함) → 전용 파일 확장자(예: .nac, .encodec, .ecdc 등) 또는 범용 컨테이너(MP4, OGG 등)에 담아 저장/송신
- 컨테이너: 인덱스, 메타 정보, 구간 탐색 등 일반적 파일 관리에 필수
- 실제 우리가 파일로 관리하는 오디오 데이터 완성
- 프레임/패킷 구조화
- 패키징 구성 내용
- 이렇게 압축된 인덱스(=비트스트림) → 헤더와 메타데이터 부착 → 최종 파일/스트림
2. Neural Audio Codec 복원과정
1) 디코딩 시작
- 비트스트림 언패키징
- 입력: 압축된 오디오 파일(.nac, .encodec 등)
- 과정:
- 파일에서 헤더/메타데이터 추출 (샘플레이트, 채널수, 코덱 버전 등)
- 프레임별 비트스트림 데이터 분리
- 엔트로피 코딩에 필요한 확률 모델 파라미터 로드
- 출력: 순수 압축 비트스트림 + 복원 정보
- 엔트로피 역부호화
- 압축 비트스트림 → 양자화 인덱스 복원
- 과정:
- Range ANS 역과정 → 저장된 비트열을 확률 분포 기반으로 인덱스로 복원
- 신경망 확률 모델 → 인코딩 시 사용한 동일한 신경망으로 각 시점의 토큰 확률 예측
- 순차 복원 → 이전 복원된 인덱스들을 조건으로 다음 인덱스 확률 계산 → 비트스트림에서 해당 인덱스 추출
- ex)
- 비트스트림: $[0110100111010…]$ ↓ (Range ANS + 신경망 확률 모델)
- 인덱스 시퀀스: $[12, 574, 38, 700, 220, 12, 38, 574, …]$
- 역양자화
- 인덱스 → 코드북에서 대응하는 벡터 검색 → 근사된 ==잠재 표현 복원==
- ex)
- 단순 VQ 역과정 인덱스 12 → 코드북$[12]$ → $[2.30, -0.88, 0.57, 0.12, …]$ 인덱스 574 → 코드북 → $[1.45, 0.23, -1.12, 0.89, …]$
- Residual VQ (RVQ) 역과정
1단계: 인덱스₁ → 코드북₁(인덱스₁) → 벡터₁
2단계: 인덱스₂ → 코드북₂(인덱스₂) → 벡터₂
3단계: 인덱스₃ → 코드북₃(인덱스₃) → 벡터₃
…
최종 복원: 벡터₁ + 벡터₂ + 벡터₃ + … = 잠재벡터
2) 디코더(Decoder) 단계
잠재 벡터로부터 원본 오디오 신호를 복원하는 단계
- 시간축 업샘플링 (Upsampling)
- 입력: (50 토큰, 512차원) → 20ms 간격
- 과정
- Transposed Conv1D (stride>1): 시간 해상도 확장
- Interpolation + Conv: 선형보간 후 conv로 정제
- Sub-pixel convolution: 효율적 업샘플링
- ex) $[50, 512] → TransConv(stride=4) → [200, 256] → TransConv(stride=4) → [800, 128] → …$
- 채널 차원 조정
- 과정: 각 업샘플 단계에서 채널 수를 점진적 감소
- 방법: 1x1 Conv 또는 Linear로 차원 축소
- 로컬 디테일 복원
- 목적: 업샘플된 거친 신호를 세밀한 오디오로 정제
- 방법
- 잔차 블록(Residual blocks): 세부 질감 추가
- 1D CNN: 로컬 패턴 정제 (인코더 역순)
- 비선형 활성화: SiLU, LeakyReLU 등으로 자연스러운 파형 생성
- 최종 출력 레이어
- 목적: 신경망 출력을 실제 오디오 샘플값으로 변환
- 방법
- 1x1 Conv → 채널=1 (모노) 또는 2 (스테레오)
- Tanh 활성화: 출력을 $[-1, 1]$ 범위로 제한
- 스케일링: 필요시 16-bit/24-bit 정수로 변환
- 후처리
- DC 제거, 클리핑 방지, 페이드 처리 등
- 최종 출력
- 디코딩 결과 → PCM 오디오(44.1kHz (또는 원본 샘플레이트) 오디오 신호)
- PCM 오디오 활용
- 저장: WAV(무손실, 단순 컨테이너), FLAC(무손실 압축) 등 원하는 포맷으로 변환 후 저장
- 재생: PCM을 오디오 출력 장치로 보냄
- PCM: 디코더 또는 파일 리더로부퍼 PCM버퍼 공급받음
- DAC: 시스템 오디오 스택(드라이버)가 이 버퍼를 오디오 인터페이스로 전달
- 아날로그 변환: PCM(디지털)을 전압파형(아날로그)로 변환
- 앰프: 수신한 전압 파형 증폭
- 스피커 출력: 공기 진동(소리) 발생
chat_bubble 댓글남기기
댓글남기기