DTMF의 구현

○ DTMF(Dual Tone Multi Frequency)란?

DTMF는 현재 일반 전화기에서 상대방을 결정하기 위해 전화국으로 전달되는 신호 방식의 하나이다. 즉. 전화기의 버튼을 누를 때마다 ‘삐’하고 울리는 소리가 바로 그것인데, 인간의 귀로는 다 똑같은 소리로 들리지만 실제로는 각 버튼에 해당되는 고유의 소리(주파수; 주파수에 따라 소리가 다르다)가 할당되어 있다. 우리나라를 비롯하여 여러 나라에서 이런 방식을 사용함으로써 다이얼식 전화기를 대체한 이 전화기를 터치톤 전화기 또는 전자식 전화기라 한다. DTMF가 적용되는 전화기는 사용자가 버튼을 누르면, 각 버튼에 해당하는 두개의 서로 다른 주파수의 음을 발생한다. 이 방식의 전화기는 단순히 전화기 내부의 기계 장치에 의해서 전화국과 직접 신호를 주고받는 것이 아니라, 소리만을 발생하여 이를 전화선을 통해 전화국에 전달하는 방식을 사용한다. 그렇기 때문에 사람의 육성이나 외부 소리에 의해서도 신호로서 받아들일 수 있다. 즉, 수화기에 적절할 소리를 인가할 수 있다면 버튼을 누르지 않고도 상대방과 전화를 할 수 있다는 것이다. 그러므로 두개의 서로 다른 특정 주파수를 사용하는 것은, 노이즈 또는 인위적인 조작에 의해 각 버튼에 해당하는 음이 발생하여 기기가 마치 정상적인 신호인 것처럼 동작하는 것을 막기 위해서이다. 뿐만 아니라 각 주파수 사이에도 고조파를 방지하도록 설정 되어 있어, 다른 주파수들에 의한 간섭을 배제하고 있다. 다음은 각 버튼에 해당되는 주파수를 도시한 그림이다. 실제 상용 제품에서는 1633Hz의 주파수는 사용하지 않고 있다.

○ DTMF의 개념

DTMF의 구현은 크게 합성과 인식의 두 단계로 구분되어진다. 합성은 위에서 언급되어진대로 각 버튼에 해당하는 두개의 각기 다른 주파수를 생성한 후 이를 하나로 합하는 것이다. 예를 들어 ‘9’라는 버튼을 누른다면 1477Hz(high-freq.)와 852Hz(low-freq.)의 두개의 음이 발생하게 되며 이 두 신호는 하나의 전화선을 통해 동시에 전송되게 된다. 다음은 이들 과정을 블록 다이어그램을 통해 나타낸 그림이다.

반대로 인식은 이렇게 합성되어 전송되어진 신호를 분리하여 어떤 버튼이 눌러졌는가를 찾아내는 역할을 한다. 그러기 위해서는 아래 그림에서와 같이 각 주파수를 통과 시킬 수 있는 대역통과(bandpass) 필터가 필요하다. 즉, 각 주파수에 해당하는 필터를 만들어 여기에 DTMF 신호를 통과시킴으로서, 특정 주파수를 검출할 수 있다. 예들 들어 위에서의 9의 신호가 전송되었다면 아래의 필터 중 1477Hz와 852Hz 필터에서만 출력 신호를 검출해 낼 수 있다. 물론 이것은 이상적인 경우에 서의 결과이며, 실제적으로는 잡음 등의 의해 다른 필터에서도 신호를 검출할 수 있다. 그러므로 인식 단계에서는 이런 잡음들의 영향을 고려하여 시스템을 설계할 필요가 있다.

○ DTMF의 구현

DTMF의 구현은 다음과 같은 과정을 따른다. 여기서는 MATLAB 코드를 사용하여 이를 구현하였다.

1. 생성 및 합성

DTMF의 MATLAB 구현을 위해서는 우선 최종 변환 형태인 wave 파일을 생성해 주는 WAVWRITE 함수를 고려해야 한다. 이 함수의 원형은 다음과 같다.

WAVWRITE(y, fs, 'filename.wav')

첫 번째 인자인 y는 출력하고자 하는 최종 신호(데이터)이며, 함수 정의에 의해 -1에서부터 1까지의 실수 값(-1 <= y <= 1) 을 가진다. 두 번째 인자 fs는 이 신호의 샘플링 주기로서 크게 두 가지 점을 상기해야 한다. 하나는 Shannon의 정리에 따라 생성하고자 하는 DTMF 신호 중 가장 높은 주파수인 1477Hz 보다 최소 2배 이상 커야한다는 점이다. 여기서는 8kHz의 샘플링 주파수를 사용하였다. 다른 하나는 1초 동안 fs만큼의 데이터가 출력된다는 것인데, 이는 출력 데이터 값이 fs개가 필요함을 의미한다. 즉, y의 데이터 길이가 fs이다(8kHz의 경우 1초 동안 신호를 발생하기 위해서는 y가 8000개의 값들로 구성되어야 한다). 그러므로 y를 통해 DTMF의 sin(정현파) 파형을 만들기 위해서는 이 주파수가 절대적인 기준이 된다. 마지막 인자는 생성되는 웨이브 신호의 이름이다. sin(또는 cos) 파는 SIN 함수를 통해 구현된다. SIN(2*pi*freq*index)의 원형에서 알 수 있듯이 인자 값으로 라디안 단위(pi는 MATLAB 상수)를 사용하며, index는 시간 축에서의 시간값 t의 역할을 한다. 여기서 중요한 점은 freq 값에 생성하고자 하는 신호의 주파수를 바로 넣어서는 안 된다는 것이다. 앞서 언급한대로 1 초 동안 신호를 발생하기 위해서는 fs만큼의 데이터가 필요하며, 이는 index의 기준이 된다. 즉, index가 1서부터 증가(MATLAB은 1부터 시작한다)하여 fs가 되었다면 1초간 신호가 발생한 것이 된다. 그러므로 만일 freq에 1477를 바로 대입하게 된다면 1477*index가 되어 전혀 엉뚱한 신호가 되어 버린다. 그렇기 때문에 freq에는 f/fs 값을 대입한다.

  >> yLow(index) = sin(2*pi*(freqLow / fs)*index);
  >> yHigh(index) = sin(2*pi*(freqLow / fs)*index);

주기 ts(= 1/fs)는 index들의 실제 시간 간격이 된다. 예를 들어 10kHz의 샘플링 주파수(fs)와 1kHz의 주파수(f)를 갖는 신호가 있다고 하자. index의 시간 간격은 0.1msec이 된다. 반면 1kHz의 신호의 주기는 1msec이며, 이는 index의 값이 10의 배수가 될 때마다 1주기가 됨을 의미한다. 그러므로 index 값이 10이 될 때마다 1주기가 되기 위해서는 샘플링 주기(ts)로 신호 주기(t)를 나눈 값에 역수를 취하면 된다. 즉, freq = ts/t = f/fs이다. 최종적으로 이렇게 얻어진 두 신호는 더해지며 웨이브 출력을 위하여 1/2로 스케일링 된다.

>> y = (yLow + yHigh) / 2;

다음은 합성 이전과 이후의 신호를 파형으로 나타낸 것이다.

2. 인식

인식은 다이얼 신호에서 주파수를 분리해내기 위해 각 주파수만을 통과시킬 수 있는 대역 통과(bandpass) 필터가 필요하다. 필터 h[n]은 다음 식을 통해 구현할 수 있다.

h[n] = 2 * cos(2*pi*f b*n /fs) / L 0 <= n <= L

여기서 L은 필터의 길이이며 L이 클수록 밴드 폭은 줄어든다. fs는 입력신호의 샘플링 주파수이며 fb는 통과시키고자 하는 주파수이다. 이렇게 얻어진 필터는 입력 신호와의 컨벌루션(convolution)을 통해 필터링된 신호를 얻는다. 즉 해당 주파수의 필터는 신호를 통과시키지만 그 이외의 필터들은 출력을 차단한다.

  >> temp = conv(h, sig);

○ 참고 문헌

1) 먼저 배우는 DSP, 2000, 인터비전, 이동욱 외 공역
2) Analog and Digital Signal Processing, 1999, Brooks/Cole, Ashok Ambardar
3) Digital Signal Processing, 1999, Wiley Inter-science, Rulph Chassing
4) Digital Signal Processing, 2001, Mc Graw Hill, Sanjit K. Mitra

○ 코드

number = [3 8 2 8];
len = length(number);

% order : {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, *, #}
timeLow = [941 697 697 697 770 770 770 852 852 852 941 941];
timeHigh = [1336 1209 1336 1477 1209 1336 1477 1209 1336 1477 1209 1477];

% sampling frequency
fs = 8000;
ts = 1/ fs;
indexSignal = fs / 2;
indexDelay = fs / 5;
indexTotal = indexSignal + indexDelay;

for i = [1:1:len]
  unitLow = timeLow(number(i)+1) / fs;
  unitHigh = timeHigh(number(i)+1) / fs;

  for j = [1:1:indexTotal]
    if(j <= indexSignal)
      freqLow(((i-1) * indexTotal) + j) = sin(2*pi*unitLow*(j-1));
      freqHigh(((i-1) * indexTotal) + j) = sin(2*pi*unitHigh*(j-1));
    else freqLow(((i-1) * indexTotal) + j) = 0;
    freqHigh(((i-1) * indexTotal) + j) = 0;
    end
  end

end

% output file generating
output = (freqLow + freqHigh) / 2;
wavwrite(output, fs, 'dtmf.wav');

Signature
이 글의 관련글
4주간 인기글
오늘 올라온 글
  • 오늘 올라온 글이 없습니다.

트랙백 주소 :: http://imakeit.ibbun.com/blog/trackback/940

댓글을 달아 주세요

[로그인][오픈아이디란?]

세상 사람들이 연봉을 얼마나 받을까여? 궁금하지 않으세요?