본문 바로가기
Audio Processing

다이내믹 신호처리(5)-실효치 컴프레서, 리미터

by gigasound 2021. 10. 21.

 

 

 

 


컴프레서의 동작 특성

컴프레서(compressor)는 다이내믹 신호처리(dynamic processing)의 한 종류로, 앞선 글에서 설명한 것과 같이 문턱 레벨(threshold) 이상의 신호를 압축비(ratio)로 압축해서 신호의 크기를 줄여주는 역할을 합니다. 

컴프레서는 아래 그림과 같이 어택(attack) 조건과 릴리즈(release) 조건을 가지고 포락선을 검출하고 이를 이용해서 VCA를 제어합니다. 이때 포락선을 실효치(rms) 대신 피크 검출을 사용해도 됩니다. 

그러면 아래 그림과 같은 입출력 관계를 가지게 됩니다. 아래의 그림은 문턱 레벨을 -30dB로 압축비를 2로 하여 문턱 레벨 이상의 신호들은 그 크기를 구간에서 1/2로 줄여 줍니다. 여기서 신호의 크기는 모두 dB 단위입니다. 예를 들어 -30dB가 입력되면 출력은 변화가 없습니다. 그런데 -10dB의 신호가 입력되면 출력은 -30과 -10dB의 차이인 -20dB가 압축비에 의해 -10dB가 되기 때문에 문턱 레벨에 -10dB만 증가한 -20dB가 출력됩니다. 

이를 압축 계수 $\alpha$라 하고 다음과 같이 정의됩니다. 

$$\alpha = (ratio \cdot threshold) - threshold $$

그러면 출력 신호는 다음과 같이 구해집니다.

$$v_{out}=\left\{\begin{matrix} v_{in}, (v_{in} \leq v_{threshold}) 
\\ (ratio \cdot v_{in}) - \alpha, (other)
\end{matrix}\right.$$


실효치 포락선을 이용한 컴프레서 구현

다른 글의 실효치 포락선 구하는 방식을 이용해서 컴프레서를 구현하도록 하겠습니다.

  • 기본 틀은 이전의 글과 같이 실효치 포락선을 먼저 구하고,
  • 포락선과 문턱 레벨 조건과 압축비를 이용해서 신호를 압축하는 이득을 구한 다음,
  • 입력 신호의 크기를 수정해서 출력하게 됩니다. 

아래의 GNU Octave에서는 실효치 포락선을 구하는 내용은 고정하고 압축비와 문턱 레벨 조건을 가지고 컴프레서의 동작 특성을 검토해 보겠습니다.

좀 더 쉽게 동작 상태를 알아보기 위해 세 개의 그림을 그릴 것입니다.

  • 첫째는 오디오 입력 신호와 컴프레서 처리 이후의 출력 신호를 겹쳐서 볼 것인데 녹색이 입력 신호 붉은색이 출력 신호입니다
  • 두 번째로 입력 신호와 출력 신호의 차이를 표시해서 얼마나 변했는지 검토할 것이고,
  • 마지막으로 데시벨 단위로 이득이 어떻게 변했는지 보겠습니다.  

아래의 코드에서 log10() 10^x 등과 같이 연산량을 차지하는 함수들이 있습니다. 실시간 처리를 할 경우에 이 함수들은 부담이 됩니다.

그럴때는 fastLog과 같은 함수로 대치해서 사용합니다. 물론 대치 함수는 정확한 값을 얻을 수 없으나 어차피 포락선 자체가 대충 값을 보는 것이기 때문에 이를 활용해서 적당한 선에서 사용하는것도 방법입니다. 

clear all
file_name = 'test.wav';
[xx,fs]=audioread(file_name);
fs = 44100;
alpha_avg = 5 * 10^-3;
alpha_a = 10 * 10^-3;
alpha_r = 100 * 10^-3;
tau_avg = exp(-1/ alpha_avg/fs);
tau_a = exp(-1/ alpha_a/fs);
tau_r = exp(-1/ alpha_r/fs);
start_x = 25000;
gap = 30000;
end_x = start_x + (gap-1);
x = xx(start_x:end_x,1);

dc_offset = 0.000000001;
ratio = 1;
thd = -21;
env_dB = dc_offset;
rms = 0;
avg = 0;
env = 0;

for i = 1 : gap
  #실효치 포락선 구하기
  tmp = x(i) * x(i);
  # log() 오류 방지
  if (tmp==0)
    tmp = dc_offset;
  endif
  avg = tmp + (tau_avg*(avg-tmp));
  rms = sqrt(avg);
  # 포락선을 데시벨로 환산
  signal_dB = 20*log10(rms);
  # 포락선과 문턱레벨의 차이를 구한다.
  over_dB = signal_dB - thd;
  # log 오류 방지
  if(over_dB<0)
    over_dB = dc_offset;    
  endif
  # 이득이 감소 또는 증가에 따라 포락선 이득 구함
  if(over_dB>env_dB)
    env_dB = over_dB +(tau_a*(env_dB-over_dB));
  else
    env_dB = over_dB +(tau_r*(env_dB-over_dB));
  endif
  # 포락선 내용 반영
  over_dB = env_dB;
  #압축비를고려하여 이득 수정
  if (over_dB==0)
    over_dB = dc_offset;
  else
    # 압축비가 1이면 아무일도 하지 않는다. 
    over_dB = over_dB * (1-ratio);
  endif
  #선형이득으로 변환
  gain_lin = 10^(over_dB/20);
  #출력 기록
  y(i,1) = x(i)*gain_lin;
  #입력과 출력의 차이 기록
  dy(i,1)=x(i)-y(i,1);
  # 이득의 변화를 기록
  g(i,1)=over_dB;
endfor

clf 
subplot(3,1,1)
plot(x,'g');
hold on 
plot(y,'r');
ylim([-0.4 0.4]);
grid on;
subplot(3,1,2);
plot(dy);
ylim([-0.4 0.4]);
grid on;
subplot(3,1,3);
plot(g);
ylim([-30 3]);
grid on;

컴프레서의 바이패스 

먼저 문턱 레벨을 -21dB로 정하고 압축비를 1로 설정하겠습니다. 그러면 다음과 같이 붉은색의 출력 신호만 보일 것입니다. 입력 신호위에 출력 신호가 겹쳐있어 출력만 보입니다.

신호의 변화 정도나 이득의 변화가 없습니다. 즉 압축비가 1이면 아무런 처리도 하지 않습니다. 당연하죠 압축비가 1-> 입력=출력이니 그렇죠. 이상태를 컴프레서의 바이패스(bypass) 동작이라고 합니다.

신호 압축

압축비를 4로 해보겠습니다. 그러면 출력 신호가 감소되어 있음을 알 수 있습니다. 앞쪽의 작은 신호에 대해서는 압축이 거의 되지 않아 문턱 레벨 조건을 잘 반영하고 이득의 변화도 거의 없습니다. 반면 중간의 조금 큰 신호의 경우에 어택 부분의 특성은 거의 반영되는 반면 릴리즈 부분에선 이득이 많이 줄어들어 있습니다. 그래도 오디오의 포락선 형태는 잘 유지하고 있습니다.  

사실 문텔레벨 조건은 사용하는 오디오 장치와 수음되는 신호의 조건 즉 현장 상황에 달라지기 때문에 미리 결정할 수 없는 인자입니다. 그러나 압축비 어택과 릴리즈 시간은 음원의 종류에 따라 권고 내용들이 있습니다. 

우선 압축비는 4, 어택은 10ms, 릴리즈는 100ms를 기준으로 증감하면서 조정합니다. 한번에 조정이 잘 되지 않기 때문에 여러번 교정해야 합니다. 

개인적인 의견이지만 다이내믹 신호처리는 특별한 경우가 아니면 사용하지 않는것도 좋은 방법입니다. 


리미터 

압축비를 10으로 설정해 보겠습니다. 앞쪽의 작은 신호에 대해서는 신호 압축이 거의 일어나지 않고 있지만 중간의 큰 신호에서 신호의 크기가 클수록 압축이 더욱 많이 이루어지고 있습니다. 그래도 어택 부분의 일부는 반영되고 있습니다. 반면 릴리즈 부분은 신호가 상당히 줄어듭니다.

똑똑하네요. 신호의 증감 상태에 따라 신호의 이득을 자동으로 조정해 줍니다. 

 

압축비가 10 이상이 되면 리미터(limiter)라고 부릅니다. 아래의 그림과 같이 높은 압축비로 인해 출력이 제한되는 기능을 가지기 때문에 붙여진 이름입니다.

이와 같이 컴프레서는 포락선을 이용해서 신호의 크기를 그때그때 줄여주는 역할을 합니다. 이 컴프레서는 음성 수음뿐만이 아니라 악기의 수음에 적용되어 음향 효과를 부가해 줍니다.


포스트 게인

컴프레서를 사용하면 신호의 크기가 전반적으로 작아집니다. 그야 컴프레서가 신호를 압축할 목적으로 사용되기 때문이요. 

압출된 신호를 그냥 사용하기에는 음량이 너무 작아지기 때문에 대부분의 다이내믹 처리기는 출력 이득을 보강해주는 이득기를 추가합니다. 이를 특별히 포스트 게인(post gain)이라고 합니다. 일반적으로 -30~30dB의 이득으로 조정합니다. 


컴프레서 모드의 특성

실효치 기반의 컴프레서에는 한 가지 제한점이 태생적으로 있습니다. 즉 아주 급격한 신호 변화에 다소 둔감하게 반응합니다. 이는 포락선 추출을 실효치를 사용하기 때문에 당연하고 이런 특성을 반영하도록 만들었기 때문입니다. 그러니 전체적인 음량의 변화에 대응하는 목적으로 사용하면 됩니다.  

이와 다르게 급격한 신호에 즉각 반응하는 방식이 피크 모드 컴프레서입니다. 피크모드는 신호변화에 빠르게 반응하지만 잘못하면 불필요한 동작특성이 나올 수도 있습니다. 그래서 어택과 릴리즈 조건을 잘 조정해야 합니다. 

 

위의 글의 내용과 같이 다이내믹 신호처리는 포락선을 구하는것이 내용의 전부이면서 핵심입니다. 구현하는 방법도 포락선을 구하는 내용을 포함해서 내용이 어렵지는 않습니다. 그러나 음향적인 효과와 실용성이 매우 높은 신호처리 방법입니다.


광고좀 꾹 눌러주시면 고맙겠습니다. 


위의 내용을 참조용으로만 사용해주세요. 무단 도용이나 무단 복제는 불허합니다.

기타 문의 사항은 gigasound@naver.com에 남겨 주시면 고맙겠습니다.