首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

工作中用声音控制计算机上命令的执行(3)

工作中用声音控制计算机上命令的执行(3)

创建了音调模式后,它被放在 ~/.toneFile 文件中并由以下子例程读取。
清单 9. 创建音调模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 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 子例程将在音调的计时之间以及音调值之间执行一个简单的差别检查。请注意音调值与计时的差异不复合。少量缺少计时或音调并不会导致整体匹配失败。
对于音调文件中的每个音调,构建音调和时间数组以供匹配。第一次比较是在音调的数目之间,因为比较七分音序列和二分音序列是没有意义的。对于每个音调和时间,检查值是否处于可接受的偏差参数内。音调和时间偏差的最大值是允许按照正确度而不是精度来匹配音调序列的临界值。您可以增大音调或时间偏差的最大值以使您可以在节奏计时或音调生成方面更自由。当自由设置可能会导致出现假检测结果时将调用警告和试验。例如,将音调偏差阈值增大到 5,而时间偏差阈值保持在 100000,这将使您可以在正确的时间输入与期望模式相去较远的音调并且仍能匹配模式 —— 如果只需练习计时它会很有用。
如果整个模式都匹配,则在 ~/.toneFile 中指定的命令是 run 并且如果启用了 verbose 模式,还会输出结果。下一步,如果未找到匹配,就退出子例程;或者如果找到匹配,就重设当前音调和时间记录。
清单 10. 创建音调模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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




主程序逻辑子例程就绪后,主程序逻辑将允许用户创建音调序列,或以守护进程模式运行来侦听音调命令和执行命令。当用户指定选项 “-c” 用于创建模式时将执行第一部分。简单的超时进程用于结束此 knock 序列。将音调之间的最大超时长度变量增大到允许音调间的停顿超过 4 秒。如果让最大超时长度保留为 4,则程序将结束并打印当前输入的音调序列。
清单 11. 超时进程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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 变量以更快地达到音调输入次数,或延长超时变量以采集间隔更长的事件的音调模式。
清单 12. 修改 LISTEN_TIMEOUT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
}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 时要特别谨慎。
除了侦听程序记录并模仿所选音调序列以在系统中运行命令这一明显问题之外,还有很多与音调验证相关的其他变数,这表示它在严格环境中的使用还尚未成熟。音调序列目前以两位“音符”的形式与四至九位表示延迟(以毫秒为单位)的部分一起存储在 ~/.toneFile 中。读取此“密码”文件或只简单地尝试匹配音调模式以获得对系统的访问权相对来说都很容易。通过减少毫秒值的精度可以使用单向散列,但这是有风险的,风险的估计就留给感兴趣的读者吧。
返回列表