수 년 동안, 컴퓨터 사용자들은 음성(voice) 프로세싱을 기반으로 명령을 실행하는 프로세서 중심의 음성 인식 애플리케이션을 실행했다. 최근, 프로세스 기능과 알고리즘이 향상되면서, 에러가 확실히 줄어든 사용자 독립적인(user-independent) 음성 인식 방식이 탄생했다. 이것은 음성(tone) 인식 시스템에 있어서 대단한 발전이다.
최근에 릴리스 된 sndpeek 프로그램을 사용하여, 간단한 Perl 프로그램을 실행하여 음성(tonal) 코드를 만들 것이다. 사용자는 음성 입력과 탐지 환경을 개인화 할 수 있도록 Perl 스크립트도 제공된다.
음성 입력(sound input)을 처리할 수 있는 시스템이어야 한다. 통합 마이크를 사용하는 것이 가장 좋지만, 그렇지 않더라도 뚜렷한 음성 이벤트를 만들어 내기만 하면 된다. 예를 들어, 컴퓨터에 휘파람을 부는 것으로도, (키보드와 마우스를 제외한) 제 3의 입력 채널이 될 수 있고, MP3 플레이어도 아웃풋 재생 설정만 잘 된다면 가능하다. 이 글에 삽입된 코드는 IBM® ThinkPad® T42p(900-MHz 프로세서, 1 GB RAM)에서 개발 및 테스트 되었다. sndpeek이 주로 리소스를 사용하는 것이기 때문에, 테스트 한 시스템보다 성능이 떨어지는시스템에서도 코드를 충분히 실행할 수 있다.
마이크를 사용하려면 음성 처리 소프트웨어 환경이 필요하다. 사운드 설정과 문제 해결 방법은 이 글의 주제는 아니지만, 사운드 하드웨어의 설정에 필요한 드라이버와 컴포넌트들이 모두 들어있는 Vector Linux Live CD에서 이 코드를 테스트 해보기 바란다. 3D 디스플레이를 할 것이 아니므로, 일부 sndpeek 프로그램만 설치하면 된다.
참고자료에서 sndpeek 웹 페이지 링크를 참조하기 바란다. 코드를 다운로드 하고, src/sndpeek/sndpeek.cpp 파일에서, 다음 코드라인을 찾는다.
Listing 1. sndpeek 수정
fprintf( stdout, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f ",
mfcc(0), mfcc(1), mfcc(2), mfcc(3), mfcc(4), mfcc(5), mfcc(6),
mfcc(7), mfcc(8), mfcc(9), mfcc(10), mfcc(11), mfcc(12) );
fprintf( stdout, "\n" );
|
위에서 Stdout에 해당 결과가 전달될 수 있도록 확실히 하기 위해서는, 모든 output에 플러쉬(flush) 하도록 하라. (역주:본 글에서는 fflush(stdout) 명령어를 사용하였다.) 위 코드를 다음과 같이 수정한다.
Listing 2. 두 번째 sndpeek 수정
fprintf( stdout, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f ",
mfcc(0), mfcc(1), mfcc(2), mfcc(3), mfcc(4), mfcc(5), mfcc(6),
mfcc(7), mfcc(8), mfcc(9), mfcc(10), mfcc(11), mfcc(12) );
fprintf( stdout, "\n" );
fflush(stdout);
|
./configure; make; make install 컴파일 명령어를 실행하여 리눅스에 sndpeek을 설치한다. Windows의 경우, 프로그램을 구현하는 많은 옵션들이 있기 때문에 더욱 주의해야 한다. Vector Linux Live CD를 통해 cmdWhistle이 작동하는 모습을 볼 수 있다.
그 다음, 명령어(command-line) 제어용 xwit 애플리케이션을 설치한다. 참고자료 섹션에서, xwit 다운로드 링크를 찾아 설치하기 바란다. 드디어, 간단한 음성(tone)을 만들 준비가 되었다.
소스 코드를 다운로드 하면, cmdWhistle.pl 스크립트를 얻을 수 있다. 이것은 메인 Perl 프로그램으로서, 음성 시퀀스를 생성하고, 특정 음성 시퀀스와 run 명령어들을 리스닝(listen) 한다. 이 글에서는, cmdWhistle.pl 프로그램의 사용자 공간에서의 사용법과 설정을 설명하고, 다양한 기능들을 소개하겠다.
sndpeek --print --nodisplay | perl cmdWhistle.pl -c 명령으로 cmdWhistle.pl 프로그램을 실행하면, sndpeek 프로그램을 시작하여 마이크에서 나오는 소리를 듣고, 그 결과를 Perl 프로그램에 출력한다. 프로그램이 실행되면, 몇 가지 휘파람 소리를 만든다. 뚜렷한 개별 음성을 만들거나, 3분의 1초 간격으로 점점 높아지는 음성을 만들어 본다. 가급적이면, 소음이 없는 환경에서 프로그램을 실행하는 것이 좋다.
다양한 속도와 톤으로 실험하여, cmdWhistle 프로그램이 어떻게 이벤트를 포착하는지를 파악할 수 있다. 프로그램의 음성 탐지 프로세스가 섬세할수록, 복잡한 음성 시퀀스를 만들 수 있다. 음성 시퀀스는 단순해야 한다. "beep beep"에 0.5초 간격을 두고, 두 개의 낮은 톤을 만드는 경우를 생각해 보자. sndpeek --print --nodisplay | perl cmdWhistle.pl -c를 실행하고, "enter a tone sequence(음성을 입력하시오)"라는 문구를 보면, 톤 사이에 0.5 초 간격으로 두 번 휘파람을 분다. 자동 타임아웃이 4초 후에 발생하고(설정 가능), 음성 시퀀스는 다음과 같이 출력될 것이다. 25.00 25.00 _#_ 0 500000 _#_ <command here> _#_ <comment here>
라인을 분석해 보면, 톤 값, 구분자(delimiter), 타임 값, 구분자, 명령어 영역, 구분자, 코멘트 영역으로 되어 있다. 이 라인을 cmdWhistle.pl 프로그램의 디폴트 설정 파일(/home/<username>/.toneFile인 {$HOME}/.toneFile)로 복사한다. 위 음성 시퀀스로 ~/.toneFile을 만들면, 라인을 수정하여 프로그램을 실행할 수 있다. 명령어 영역 텍스트를 /bin/echo "two low"로 바꾸고, 코멘트 영역을, 25.00 25.00 _#_ 0 500000 _#_ /usr/bin/echo "two low" _#_ two low tones로 수정한다.
설정 파일을 수정했다면, sndpeek --print --nodisplay | perl cmdWhistle.pl 명령어로 데몬 모드(daemon mode)에서 cmdWhistle.pl 스크립트를 실행한다. 이 프로그램은 ~/.toneFile 에서 나오는 이벤트를 듣는다. 같은 속도와 같은 음조로 두 개의 저음 휘파람을 불면, 스크린에 "two low"라는 텍스트가 출력된다. cmdWhistle.pl 스크립트의 실행 방법을 자세히 알고 싶다면, daemon 모드에서 sndpeek --print --nodisplay | perl cmdWhistle.pl -v를 실행하라. 시스템이 그래픽 디스플레이를 지원한다면, --nodisplay 옵션은 삭제해도 된다.
키보드 단축키 또는 마우스 움직임을 모방한 유용한 톤 입력 옵션들이 많이 있다. 아래 예제는 사용자가 홈(home) 위치에서 자신이 원하는 대로 창을 움직일 수 있는 방법을 설명하는 윈도우(window) 관리 방법 예제이다. "기타 예제" 섹션에서 다른 기능들을 설명하고 있다.
create" 모드에서, sndpeek --print --nodisplay | perl cmdWhistle.pl -c 명령어로 cmdWhistle.pl 프로그램을 실행해 보자. 윈도우(window) 관리를 위해 몇 가지 간단한 톤을 만들어야 한다. 낮은 톤은 "lower", 높은 톤은 "raise", 두 개의 중간 톤은 "iconify"로 설정한다. 반드시, 일관성 있고 정확하게 입력할 수 있는 것을 선택해야 한다. 음성 시퀀스를 입력할 때 정밀도를 관리하는 매개변수를 수정할 수는 있겠지만, 정확한 톤이나 타이밍을 매치하기란 상당히 까다롭다. 따라서, 넓은 피치(pitch) 공간을 차지하고 있는 세 개의 음성 옵션들이 우리에게는 알맞다. 다음은 이 세 개의 명령어를 포함하고 있는 ~/.toneFile 샘플이다.
Listing 3. ~/.toneFile 샘플
20.00 _#_ 0 _#_ /usr/bin/xwit -pop -names rxvt _#_ raise rxvt windows # # 40.00 _#_ 0 _#_ /usr/bin/xwit -pop -names nathan _ #_ raise xterms starting with nathan@localhost # # 25.00 25.00 _#_ 0 500000 _#_ /usr/bin/xwit -iconify -names nathan _ #_ iconify nathan@localhost~ |
xwit 명령어를 echo로 대체하고, 계속 사용하기 전에는 많은 연습이 필요하다.
xwit - 쉘 스크립트에서 액세스 할 수 있는 X 함수
X Window System에는 명령어를 사용한 윈도우 제어 방식들이 있지만, 그 중에서 xwit가 가장 단순하고 이식성 있으며, 다른 윈도우 매니저에도 잘 작동한다. xwit를 다운로드 해서 설치하고, xwit -iconify 명령어를 실행하여, 프로그램이 잘 작동하는지를 확인한다. (이 명령어는 현재 창(윈도우)를 최소화하는 명령어이다.) xwit에 "lower" 함수가 없지만, 이 때에는 다른 창(윈도우)들을 늘리면 된다. 이 예제에서는, 높은 톤(40.00)으로, "nathan"으로 시작하는 타이틀을 최대로 늘린다. xterms의 타이틀을 설정하는 것은 전형적인 프로그래밍 태스크에 적합하다. 창이 rxvt로 시작한다면, 낮은 톤(20.00)을 사용하여 최대화 된다. Half-Second 딜레이로 실행되는 두 개의 중간 톤(25.00)은 "nathan"으로 시작하는 모든 창(윈도우)을 아이콘으로(iconified) 만든다. (참고자료)
이렇게 설정하면 다른 창에서는 계속 입력을 하면서, 다른 창 화면을 볼 수 있다.(역주: 이후의 '윈도우' 용어는 '창'으로 번역하도록 한다.) 서브루틴 구조를 구현하면서, API 정보용 전문에 문서 레퍼런스를 가져오는데 유용하다. 실제로, 직접 타이핑 하는 것 보다 빠르게 처리되고, 동시에 창 환경을 관리할 수 있다.
Microsoft OS에서, 창을 늘릴 때 WshShell.AppActivate 명령어를 사용한다. 예를 들어, "gvim" 애플리케이션을 늘리고 싶다면, 다음과 같은 코드로 "gvimActivate.vbs" 파일을 만든다.
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.AppActivate "gvim";
|
파일을 만들어서 실행하면, "gvim" 창이 전면에 나타난다. Windows에서 작업한다면, ~/.toneFile의 "high-tone" 명령어를 40.00 _#_ 0 _#_ gvimActivate.vbs _#_ raise gvim window로 변경한다.
sndpeek 프로그램과 cmdWhistle.pl은 고유한 방식으로 사용할 수 있는 추가적인 사용자 입력 방식을 제공한다. 화면 보호기 암호해제를 설정하고, 책상 앞에서 휘파람을 불면, 더 이상 패스워드를 입력할 필요가 없다. 휘파람으로 이메일을 체크하고, 핸드폰의 고유 톤을 체크하고, 전화 벨을 울려 이메일을 보낼 수 있다.
고속 퓨리에 변환(Fast Fourier transform)시스템과와 Sliding percentage windows, 그리고 일부 리눅스 오디오 프로그래밍은 음성 인식 기능을 제공한다. Ge Wang, Perry R. Cook, Ananya Misra가 작성한 sndpeek 애플리케이션은 cmdWhistle.pl이 음성 이벤트를 탐지하기 위해 필요한 정보를 모으는데 있어서, 이식성 있고 빠른 유닉스® 방식을 제공한다. 'sndpeek --print' 명령어는 현재 사운드 소스에 대해 실시간으로 텍스트를 분석하고, 뛰어난 3D화면을 제공한다. sndpeek에서 출력된 텍스트 분석의 네 번째 엔트리는 sndtool의 "Marsyas" 컴포넌트를 사용하는 Rolloff 함수의 결과물이다. (역주:sndpeek의 실행화면을 확인하기 바란다.)
Listing 4. Rolloff.cpp 소스 코드의 디스크립션
Compute Rolloff (a percentile point) of the input fvec. For example if perc_ is 0.90 then Rolloff would be the index where the sum of values before that index are equal to 90% of the total energy. |
이러한 결과물을 기본 "톤(tone)"으로 사용하기 위해서는 cmdWhishle.pl 스크립트는 톤간의 다양한 시간 간격을 인지하여 구분하여야 한다.
cmdWhistle.pl의 타이밍(timing)과 센서(sensor) 매개변수 설정을 시작해 보자.
Listing 5. cmdWhistle.pl 타이밍 및 센서 매개변수
$|=1; #for non buffered standard output, useful for other programs to read require 'sys/syscall.ph'; # for subsecond timing my $option = $ARGV[0] || ""; # simple option handling my $MAX_TIMEOUT_LENGTH = 4; # maximum length in seconds of tone pattern my $LISTEN_TIMEOUT = 2; # timeout value in seconds between tone my $MAX_TIME_DEV = 100000; # maximum acceptable deviation between recorded # pattern values and current time values my $MAX_TONE_DEV = 2; # maximum acceptable deviation between recorded # pattern values and current tone values my $MAX_AVG_TONE = 5; # maximum number of samples to be averaged |
위 리스팅의 변수들과 코멘트들은 비교적 단순하다. 사용법과 설정 옵션에 대해서는 나중에 자세히 설명하겠다. 다음은 글로벌 변수의 나머지 부분이다.
Listing 6. 글로벌 변수와 디스크립션
my @queTones = (); # running queue of recent tones detected my $prevTone = 0; # the last solid tone detected, used for disambiguation my $prevInterval = 0; # previous interval of time my @baseTones = (); # the currently entered tone sequence my @baseTimes = (); # the currently entered temporal values my %toneHash = (); # tones, times and commands read from ~/.toneFile my $toneCount = 0; # the current count of tones entered my $startTime = ""; # start of a temporal block my $currTime = ""; # current time in the time out loop my $toneAge = 0; # for tone count synchronization my $timeOut = 0; # to reset the timer window |
음성 패턴의 상태에 대한 상세한 정보를 제공하는 getEpochSeconds와 getEpochMicroSeconds를 보자.
Listing 7. getEpochSeconds와 getEpochMicroSeconds 서브루틴
sub getEpochMicroSeconds {
my $TIMEVAL_T = "LL"; # LL for microseconds
my $timeVal = pack($TIMEVAL_T, ());
syscall(&SYS_gettimeofday, $timeVal, 0) != -1 or die "micro seconds: $!";
my @vals = unpack( $TIMEVAL_T, $timeVal );
$timeVal = $vals[0] . $vals[1];
$timeVal = substr( $timeVal, 6);
my $padLen = 10 - length($timeVal);
$timeVal = $timeVal . "0" x $padLen;
return($timeVal);
}#getEpochMicroSeconds
sub getEpochSeconds {
my $TIMEVAL_T = "LL"; # LL for microseconds
my $start = pack($TIMEVAL_T, ());
syscall(&SYS_gettimeofday, $start, 0) != -1 or die "seconds: $!";
return( (unpack($TIMEVAL_T, $start))[0] );
}#getEpochSeconds
|
readTones 서브루틴은 sndpeek의 아웃풋에서 Rolloff 데이터 값을 포착한다. 코멘트 섹션에서 보면 알겠지만, 이 코드는 다섯 개의 톤 샘플을 만들어서 이들을 서로 비교하여 기본 편차를 만든다. 톤 어레이 큐의 용량이 차면, 각 톤에 대한 편차를 계산한다. 큐에서 한 톤의 비교치가 최대 음성 편차를 초과하면, 현재 프로세싱이 뚜렷한 톤을 만들어내지 않은 것으로 지정한다.
큐에 있는 모든 톤의 편차가 허용 임계치 이하라면, 모호성 레이어를 탐지한다. 만일 당신이 천천히 증가하는 톤으로 휘파람 소리를 낸다면, 허용 가능한 임계치를 벗어나서 인식 가능한 음성 이벤트를 만들 것이다. 하지만, 이를 지속한다면 문제를 일으킬 수 있다. upDev와 downDev 변수들과 비교 로직은, MAX_TONE_DEV 변수 이상으로 편차가 벌어질 경우, 이러한 연속적인 음성 변화들을 인식하도록 설계된다. 최근의 톤 큐 체크와 연속적인 톤 체크가 완료되면, 나중에 비교할 수 있도록 음성 이벤트와 시간을 기록해 둔다.
변수들을 수정하면 특별한 음성 스타일과 편차들을 인식하도록 프로그램을 조정하는데 도움이 된다. 전체적인 주파수 리프레시(refresh) 비율의 분석 결과는 sndpeek 프로그램의 아웃풋에서 나타난다. 다른 모든 매개변수들은, 시간 임계치를 통해 동시 다중 음성 이벤트 또는 음성 이벤트들 간 다른 타이밍 같은, 넓은 공간을 차지하는(widely spaced) 음성 이벤트를 탐지하도록 설정될 수 있다.
Listing 8. 더 넓은 공간을 차지하는 음성 이벤트 탐지하기
sub readTones
{
# read the Rolloff output only,
my(undef, undef, undef, $currentTone ) = split " ", $_[0];
if( @queTones == $MAX_AVG_TONE )
{
my $localDiff = 0;
# check for a solid tone by comparing against the last five tones
# perform simple time related tonal smoothing, so if the tone
# wavers just a bit it's still counted as one tone
for my $chkHistTone ( @queTones )
{
if( abs($currentTone - $chkHistTone) > $MAX_TONE_DEV )
{
$localDiff =1;
$prevTone = 0;
}#if deviation less than threshold
}#for each tone
if( $localDiff == 0 )
{
# make sure the current tone is different than the previous one, this is to
# ensure that long duration tones are not acquired as multiple tone events
# this step up or down will allow you to whistle continuously and pick up the
# steps as discrete tone events
my $upDev = $currentTone + $MAX_TONE_DEV;
my $downDev = $currentTone - $MAX_TONE_DEV;
if( $prevTone > $upDev || $prevTone < $downDev )
{
my $currVal = getEpochMicroSeconds();
my $diffInterval = abs($prevInterval - $currVal);
if( $option ){
print "Tone: $currentTone ## last: [$currVal] curr: [$prevInterval] ";
print "difference is: $diffInterval\n";
}
if( $toneCount == 0 ){ $diffInterval = 0 }
push @baseTones, $currentTone;
push @baseTimes, $diffInterval;
$toneCount++;
$prevInterval = $currVal;
}#if deviation in tone
# now set the previous tone to the current tone so a continuous tone
# is not acquired as multiple tone events
$prevTone = $currentTone;
}#if a solid tone has been found
# if enough tones to create an useful queue have been added, pop one off
shift @queTones;
}#if enough tones to create a useful queue
# always push more tones on the avg
push @queTones, $currentTone;
}#readTones
|
음성 패턴이 만들어지면, ~/.toneFile 파일에 배치되고, 다음 서브루틴에 의해 읽힌다.
Listing 9. 음성 패턴 생성
# readToneFile reads tone sequences and commands from ~/.toneFile
# format is: tones _#_ times _#_ command _#_ comments
sub readToneFile
{
#give it a full path to .toneFile if on windows
open(TONEFILE,"$ENV{HOME}/.toneFile") or die "no tone file: $!";
while(<TONEFILE>){
if( !/^#/ ){
my @arrLine = split "_#_";
$toneHash{ "$arrLine[0] $arrLine[1]" }{ tones } = $arrLine[0];
$toneHash{ "$arrLine[0] $arrLine[1]" }{ times } = $arrLine[1];
$toneHash{ "$arrLine[0] $arrLine[1]" }{ cmd } = $arrLine[2];
$toneHash{ "$arrLine[0] $arrLine[1]" }{ comment } = $arrLine[3];
}#if not a comment line
}#for each line in file
close(TONEFILE);
}#readToneFile
|
readTone을 통해서 음성 패턴이 읽히고, readToneFile에서 로딩된 음성 패턴과 비교된다. compareToneSequences 서브루틴은 톤의 타이밍들간 차이를 검사하고, 톤들의 값의 차이를 체크한다. 아주 작은 타이밍 또는 톤을 놓친다고 해서 전체적인 매치 오류(Match Failure)가 일어나지는 않는다.
톤 파일에 있는 각 톤의 경우, 매칭(matching)을 위한 음성 어레이와 Temporal 어레이를 구현해야 한다. 7- tone시퀀스와 2-tone 시퀀스의 비교 포인트가 없으므로, 가장 먼저, 톤을 비교해야 한다. 각 톤과 시간의 경우, 허용 편차 매개변수 내에 값이 존재하는지를 확인해야 한다. 최대 톤과 Temporal 편차는 정확한 음성 시퀀스 매칭(matching)에 있어서 중요하다. 최대 톤 또는 타임 편차를 증가시켜서 타이밍에 변화를 주거나 보다 자유롭게 음성을 생성할 수 있다. 자유 설정(liberal setting)은 틀린 탐지 결과를 만들 수 있으므로 주의해야 한다. 톤 편차 임계치를 5로 늘리고, Temporal 편차 임계치를 100000으로 유지하면, 정확한 시간에, 기대했던 패턴과 관련된 톤을 원격에서 입력할 수 있고, 패턴도 맞출 수 있다.
전체 패턴이 일치하면, ~/.toneFile에서 지정된 명령어가 실행되고, verbose 모드가 실행되면 결과가 프린트 된다. 다음 단계는, 어떤 것도 매치하지 않을 때 서브루틴을 종료하거나, 매치되면, 현재 톤과 타임 기록을 리셋한다.
Listing 10. 음성 패턴 생성
sub compareToneSequences
{
my $baseCount = @baseTones;
my $countMatch = 0; # record how many tones matched
for my $toneFromFile ( keys %toneHash )
{
my @confTones = split " ", $toneHash{$toneFromFile}{tones};
my @confTimes = split " ", $toneHash{$toneFromFile}{times};
my $confCount = @confTones;
next unless( $confCount == $baseCount );
# as a learning aid, the matching and non matching portions of the
# comparison are printed out, so at least you can see what is going
# wrong while trying to remember your tone codes
my $pos =0;
my $toneMatchFail = 0;
for( @baseTones )
{
my $tonDiff = abs($confTones[$pos] - $baseTones[$pos]);
my $tonStr = "t $pos b $baseTones[$pos] ".
"c $confTones[$pos] \n";
my $timeDiff = abs($confTimes[$pos] - $baseTimes[$pos]);
my $timStr = "t $pos b $baseTimes[$pos] ".
"c $confTimes[$pos] d $timeDiff\n";
if( $tonDiff > $MAX_TONE_DEV )
{
$toneMatchFail = 1;
if( $option ){ print "NOTE DISSONANCE $tonStr" }
}else
{
if( $option ){ print "NOTE MATCH $tonStr" }
}#if tone detected outside of deviation
# if it's an exact match, increment the matching counter
if( $timeDiff < $MAX_TIME_DEV ){
if( $option ){ print "TIME MATCH $timStr" }
$countMatch++;
}else{
if( $option ){ print "TIME DISSONANCE $timStr" }
last;
}# deviation check
$pos++;
}# for each tone to check
if( $countMatch == $confCount && $toneMatchFail == 0 )
{
my $cmd = $toneHash{$toneFromFile}{ cmd };
if( $option ){ print "run: $cmd\n" }
$cmd =`$cmd`;
if( $option ){ print "result: $cmd\n" }
last;
# otherwise, make the count of matches zero, in order to not reset
}else
{
$countMatch = 0;
}
}#for each tone in tone file
# if the match count is zero, exit and don't reset variables so a longer
# tone sequence can be entered and checked
if( $countMatch == 0 ){ return() }
# if a match occured, reset the variables so it won't match another pattern
$toneCount = 0;
@baseTones = ();
@baseTimes = ();
}#compareToneSeqeunces
|
서브루틴이 있는 상태에서, 주 프로그램 로직으로 톤 시퀀스를 생성하거나, 데몬 모드(daemon mode)로 실행되어 톤을 듣고 명령을 실행한다. 사용자가 create mode의 "-c" 옵션을 지정하면 첫 번째 섹션이 실행된다. 간단한 타임아웃 프로세스가 사용되어 knock 시퀀스를 종료한다. 최대 타임아웃 길이 변수를 늘려서 톤 사이 중지(pause) 시간을 4초 이상 되도록 한다. 최대 타임아웃 길이를 4로 계속 둔다면, 프로그램은 종료하고, 현재 입력된 톤 시퀀스를 출력한다.
Listing 11. 타임아웃 프로세스
if( $option eq "-c" ){
print "enter a tone sequence:\n";
$startTime = getEpochSeconds(); # reset time out start
while( my $sndPeekOutput = <STDIN> )
{
$currTime = getEpochSeconds();
# check if there has not been a tone in a while
if( $currTime - $startTime > $MAX_TIMEOUT_LENGTH ){
$timeOut = 1; # exit the loop
}else{
# if a tone has been entered before timeout, reset timers so
# more tones can be entered
if( $toneCount != $toneAge ){
$startTime = $currTime; # reset timer for longer delay
$toneAge = $toneCount; # synchronize tone counts
}# if a new tone came in
}# if timer not reached
readTones( $sndPeekOutput );
if( $timeOut == 1 ){ last }
}#while stdin
if( @baseTones ){
print "place the following line in $ENV{HOME}/.toneFile\n\n";
for( @baseTones ){ print "$_ " }
print "_#_ ";
for( @baseTimes ){ print "$_ " }
print "_#_ (command here) _#_ <comments here>\n\n";
}#if tones entered
|
주 로직의 두 번째 섹션에서는 sndpeek의 print 명령어의 결과를 읽는다. 타임아웃 임계치에 다다른 후에 음성 그룹들은 자동으로 리셋되어 개별 음성 패턴들을 구분한다. LISTEN_TIMEOUT 변수를 수정하여 음성 입력 시간을 더욱 빠르게 하거나, 타임아웃을 늘려서 더 광범위한 폭의 이벤트를 가진 톤 패턴을 얻을 수 있다.
Listing 12. LISTEN_TIMEOUT 수정
}else
{
# main code loop to listen for tones and run commands
readToneFile();
$startTime = getEpochSeconds();
while( my $sndPeekOutput = <STDIN> )
{
$currTime = getEpochSeconds();
if( $currTime - $startTime > $LISTEN_TIMEOUT ){
$toneCount = 0;
@baseTones = ();
@baseTimes = ();
$startTime = $currTime;
if( $option ){ print "listen timeout - resetting tones \n" }
}else{
if( $toneCount != $toneAge ){
$startTime = $currTime; # reset timer for longer delay
$toneAge = $toneCount; # synchronize tone counts
}# if a new tone came in
compareToneSequences();
}#if not reset timeout
readTones( $sndPeekOutput );
}#while stdin
}#if option set
|
cmdWhistle 프로그램은 마우스와 키보드 외에, 또 하나의 입력 방식을 제공한다. 하지만 cmdWhistle를 사용하여 시스템 인증이 필요한 일을 수행할 때 주의해야 한다.
리스너(listener)가 음성 시퀀스를 녹음 및 모사(mimic)하여 시스템에서 명령을 수행해야 한다는 뚜렷한 문제 외에도, 아직은 시기 상조인 음성 인증 (tonal authentication)과 관련된 문제들도 남아있다. 음성 시퀀스는 현재 두 자리수 "노트(note)"로 ~/.toneFile에 저장되고, 여기에 네 자리에서 9 자리로 딜레이(마이크로초)를 나타낸다. "password" 파일을 읽고, 톤 패턴을 매치하여 시스템에 액세스 하는 것은 비교적 쉽다. 정밀도를 낮추어서 일방(One-way) 해쉬를 사용할 수도 있지만, 위험 부담은 독자들의 몫이다.
| 설명 | 이름 | 크기 | 다운로드 방식 |
|---|---|---|---|
| Source code | os-whistle.zip | 3KB | HTTP |
교육
-
Princeton University host - sndpeek program.
-
ibiblio.org host -xwit program.
- 예제 Video 보기 - YouTube.com 또는 Google Video
- IBM developerWorks' PHP project resources
-
developerWorks technical events and webcasts
-
IBM 오픈 소스 개발자들과 관련한 세계적인 컨퍼런스, 트레이드 쇼, 웹 캐스트, 이벤트를 확인하십시오.
- 한국 developerWorks 오픈 소스 존- 오픈 소스 개발과 구현의 참고자료
-
developerWorks podcasts.
제품 및 기술 얻기
토론