Содержание


Насвистывайте во время работы, чтобы запускать команды на своем компьютере

Использование свободного ПО и ноутбуков с микрофонами для прослушивания определенных звуковых последовательностей и запуска команд.

Comments

Многие годы пользователи компьютеров имели возможность запускать приложения, требующие интенсивной работы процессора, для распознавания речи, выполняя команды, основанные на обработке голоса, для которых нужна громоздкая конфигурация. После того, как последние успехи в увеличении мощности процессоров и в алгоритмах обработки привели к возможности распознавания голоса независимо от пользователя и с уменьшенной частотой появления ошибок, появились прекрасные системы распознавания голоса, основанные на распознавании простых звуковых шаблонов.

Используя недавно появившуюся программу sndpeek для усовершенствованной обработки, мы запустим простую Perl-программу, позволяющую легко создавать звуковые коды. Ниже будет приведен Perl-скрипт, чтобы позволить пользователю настраивать входящие звуковые сигналы и режим распознавания.

Технические требования

Аппаратура

Вам понадобится система с возможностью обработки входящего звукового сигнала, предпочтительно со встроенного микрофона, но подойдет и любой источник звука, производящий дискретные звуковые сигналы. Например, насвистывание за компьютером -- это наиболее эффективный способ добавить третий канал для ввода команд (помимо клавиатуры и мыши), но воспроизведение звуков с MP3-плеера через разъем line-in при правильной конфигурации может дать тот же результат. Код, приведенный в данной статье, был разработан и протестирован на IBM® ThinkPad® T42p с процессором 900-MHz и 1 GB оперативной памяти. Значительно менее мощные системы вполне способны использовать код, приведенный в этой статье, так как sndpeek является основным потребителем ресурса, а он является эффективной программой.

Программное обеспечение

Вам необходимо программное окружение, позволяющее вам работать с микрофоном. Хотя настройка звука и поиск неисправностей лежат за пределами данной статьи, может оказаться полезным протестировать этот код на Vector Linux Live CD, который имеет большинство драйверов и компонентов, необходимых для функционирования разнообразного звукового оборудования. Вам понадобится, по крайней мере, неполная установка программы sndpeek, так как часть программы, связанная с 3-D отображением, нам не потребуется.

В Ресурсах, имеется ссылка на Web-страницу sndpeek. Загрузите код и в файле src/sndpeek/sndpeek.cpp найдите следующее:

Листинг 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" );

Убедитесь, что программа в действительности выводит данные в конце каждого окна печати. Измените вышеуказанный раздел, чтобы он выглядел следующим образом:

Листинг 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 для Linux. Для Windows убедитесь, что команда компилируется правильно. Имеется много опций для сборки программы в Windows, но это находится за пределами данной статьи. Если вы хотите посмотреть на cmdWhistle в действии, я рекомендую использовать Vector Linux Live CD.

Следующим является установка xwit приложения для контроля над окнами при помощи командной строки. Посмотрите ссылку в Ресурсах для загрузки xwit и установите его без изменений в исходном коде. Теперь вы готовы к созданию нескольких простых звуков.

Пример установки и настройки

Создание простой звуковой последовательности

Загрузите исходный код и найдите скрипт cmdWhistle.pl. Это основная Perl-программа, которая позволяет вам создавать звуковые последовательности, а также прослушивать определенные звуковые последовательности и запускать команды. В этой статье сначала будет рассказано об использовании программы cmdWhistle.pl пользователями, а затем будут описаны ее различные функции.

Запустите программу cmdWhistle.pl следующей командой: sndpeek --print --nodisplay | perl cmdWhistle.pl -c. Она запустит прослушивание вашего микрофона программой sndpeek и направит вывод программы в Perl-скрипт. Пока программа работает, произведите несколько простых свистов – отдельные чистые звуки или повышающиеся ноты с паузами в одну треть секунды между ними. Заметьте, что вы должны запускать программу в относительно тихой обстановке, так что вы должны вставить наушники и удостовериться, что ваш CD-ROM не работает. Если у вашего ноутбука может загореться батарея, то перед запуском программы постарайтесь отключить пожарную сигнализацию.

Поэкспериментируйте с темпом и тонами, чтобы почувствовать разрешающую способность программы cmdWhistle. Опыт работы с тонкостями процесса распознавания звуков важен при создании сложных последовательностей воспроизводящихся тонов. Ваша первая звуковая последовательность должна быть простой: два низких тона с полусекундным интервалом между ними для получения "beep beep.". Запустите sndpeek --print --nodisplay | perl cmdWhistle.pl -c и, когда вы увидите "enter a tone sequence", дважды свистните с полусекундным промежутком. Автоматическая блокировка по времени включится через 4 секунды (настраивается), и ваша звуковая последовательность будет распечатана так, как показано в следующем примере: 25.00 25.00 _#_ 0 500000 _#_ <command here> _#_ <comment here>.

Установка команд и распознавание звуковой последовательности

Давайте проанализируем следующую строку: значения тонов, разделитель, значения времен, разделитель, область команд, разделитель и комментарий. Ваш следующий шаг – копирование этой строки в конфигурационный файл программы cmdWhistle.pl: {$HOME}/.toneFile, который будет, по-видимому, называться /home/<username>/.toneFile. После того как вы создали ~/.toneFile с вышеуказанной строкой звуковой последовательности, вы можете модифицировать строку для запуска программы: /bin/echo "two low"/bin/echo "two low" и модифицировать комментарий, чтобы он был более информативен 25.00 25.00 _#_ 0 500000 _#_ /usr/bin/echo "два низких" _#_ два низких звука.

Теперь, когда вы модифицировали конфигурационный файл для печати сообщения, запустите cmdWhistle.pl в режиме демона с помощью команды sndpeek --print --nodisplay | perl cmdWhistle.pl. Программа будет прислушиваться, ожидая сигналов из списка ~/.toneFile. Попробуйте свистнуть дважды в низком тоне с тем же временным интервалом и вы увидите на экране текст "два низких". Если вы хотите увидеть работу cmdWhistle.pl в деталях, запустите ее в режиме демона с помощью команды sndpeek --print --nodisplay | perl cmdWhistle.pl -v. Если ваша система поддерживает графический дисплей, уберите --nodisplay опцию для 3-D визуализации звуковых сигналов.

Пример настройки для системы управления окнами xwit

Создание последовательностей для поднимания, опускания и минимизации окон

Во многих случаях удобно использовать звуковые команды вместо "горячих клавиш" или движения мыши. В нижеприведенном примере рассматриваются функции, обеспечивающие управление окнами, которые позволяют просто кашлять, и окна будут без участия рук располагаться по вашему желанию. Обратитесь к разделу "Дополнительные примеры", в котором детально описаны возможности этого перспективного метода ввода.

Запустите программу cmdWhistle.pl в режиме "create" с помощью команды sndpeek --print --nodisplay | perl cmdWhistle.pl -c. Вам нужно создать несколько простых звуков, которые вы можете легко воспроизводить для функций быстрого управления окнами. Я рекомендую низкий тон для "lower" и высокий для "raise", а также два средних тона для "iconify". Убедитесь, что вы выбрали то, что вы можете точно воспроизвести. Хотя вы можете модифицировать параметры, контролирующие точность, с которой вы должны вводить ваши звуковые последовательности (как по высоте, так и по длительности), может оказаться трудным точно соответствовать тону и согласованию по времени. Три звука, хорошо разнесенные по высоте, – хороший компромисс между гибкостью команды и простотой для тех из нас, кому нужна большая практика в этом караоке. Ниже пример ~/.toneFile с тремя командами:

Листинг 3. Пример ~/.toneFile с тремя командами
20.00 _#_ 0 _#_ /usr/bin/xwit -pop -names rxvt _#_ поднимает окно rxvt
#
#
40.00 _#_ 0 _#_ /usr/bin/xwit -pop -names nathan _#_ поднимает xterms, имя которого 
#начинается с nathan@localhost
#
25.00 25.00 _#_ 0 500000 _#_ /usr/bin/xwit -iconify -names nathan _#_ минимизирует
#nathan@localhost~

Перед тем как использовать команды xwit, попрактикуйтесь, заменив их на echo.

xwit - функции X-Windows доступные из shell

Хотя существует много методов контроля окон с помощью командной строки для системы X Window, xwit является одним из наиболее простых и переносимых методов, который будет работать для многих оконных менеджеров. Загрузите и установите xwit и выполните команду xwit -iconify, чтобы убедиться, что программа работает. (Это действие минимизирует текущее окно). Хотя xwit не имеет функции "lower", мы можем использовать искусственный прием путем поднятия других окон. В этом примере мы используем один высокий тон (40.00), чтобы поднять окна с заголовком, начинающимся на "nathan". Настройка заголовка ваших xterm -- это простой способ идентификации, подходящий для типичных задач. Другие окна будут подняты при использовании одного высокого тона (20.00), если они начинаются на rxvt. Два средних тона (25.00) с полусекундным интервалом будут приводить к тому, что минимизируются все окна, имеющие заголовок, начинающийся с "nathan". Смотрите Ресурсы для ознакомления с тем, как это выглядит.

Одно из важнейших преимуществ такой настройки состоит в возможности продолжать печатать в одном окне, вызывая другое на экран. Это полезно при построении структуры подпрограмм, когда в это время вы выносите на передний план документацию по API. На самом деле вы можете управлять компьютером быстрее, чем вы печатаете – вы можете печатать и управлять вашим окнами одновременно.

Программы для Windows для поднятия и опускания окон

Простейший способ управления окнами в операционных системах Microsoft -- это использовать команду WshShell.AppActivate. Если мы хотим развернуть, например, приложение "gvim", мы должны создать файл, называющийся "gvimActivate.vbs", с помощью следующей команды :

	Set WshShell = WScript.CreateObject("WScript.Shell")
	WshShell.AppActivate "gvim";

Имея этот файл, все, что мы должны сделать -- это выполнить его, и окно "gvim" сфокусируется и выйдет на передний план. Если вы работаете в Windows, измените команду простого высокого тона в ~/.toneFile на 40.00 _#_ 0 _#_ gvimActivate.vbs _#_ raise gvim window.

Дополнительные примеры

Программа sndpeek и cmdWhistle.pl обеспечивают дополнительный механизм ввода, который может быть использован уникальными способами. Установите код разблокировки для вашего screensaver и свистните, подходя к столу, и больше никаких надоедливых печатаний пароля. Проверяйте вашу почту каждый раз, как свистните, настройтесь на уникальные звуки вашего мобильного телефона и посылайте себе e-mail, когда у вас зазвонит телефон.

Код cmdWhistle.pl

История и стратегия

Быстрое преобразование Фурье и аудио программирование в Linux может дать вам возможности звукового распознавания на языке по вашему выбору. Приложение sndpeek, написанное Ge Wang, Perry R. Cook и Ananya Misra, обеспечивает переносимый, быстрый UNIX®-способ сбора информации, которая нужна cmdWhistle.pl для распознавания звуковых сигналов. Команда sndpeek --print покажет текстовую аналитику текущего звукового сигнала в реальном времени, а также прекрасную 3-D визуализацию. Четвертый элемент, выводимый в текстовой аналитике – это вывод функции Rolloff, использующей компонент "Marsyas" дистрибутива sndtools. Ниже. Описание из исходного кода Rolloff.cpp:

Листинг 4. Описание из исходного кода Rolloff.cpp
Вычислить Rolloff (процентильную точку) для fvec.
Например, если perc_ равно 0.90, тогда Rolloff будет значением,
для которого сумма значений до него равна 90% общей энергии.

Используя эту величину, как наш основной "тон", cmdWhistle.pl script определит различные интервалы между звуками.

Настройка параметров

Давайте начнем с начала cmdWhistle.pl -- с параметров, критичных ко времени и чувствительности :

Листинг 5. cmdWhistle.pl параметры, критичные ко времени и чувствительности
$|=1; # для не буферизированного стандартного выхода, пригодного для 
      # чтения другими программами
require 'sys/syscall.ph'; # для хронометрирования высокого разрешения

my $option = $ARGV[0] || ""; # простая обработка опций

my $MAX_TIMEOUT_LENGTH = 4; # максимальная длина звука в секундах
my $LISTEN_TIMEOUT = 2; # величина промежутка времени между звуками в секундах
my $MAX_TIME_DEV = 	100000; # максимально допустимое отклонение между записанными
	# значениями в образце и в текущих временных величинах
my $MAX_TONE_DEV = 2; # максимально допустимое отклонение между записанными 
	# значениями в образце и текущими значениями тонов
my $MAX_AVG_TONE = 5; # максимальное количество образцов, которое необходимо усреднить

Вышеприведенные переменные и их комментарии достаточно прямолинейны. Более подробно об их использовании и возможностях настройки будет сообщено дальше. Далее – оставшиеся глобальные переменные и их описание.

Листинг 6. Оставшиеся глобальные переменные и их описания
my @queTones = ();	# последняя последовательность распознанных звуков
my $prevTone = 0; 	# последний распознанный чистый тон, используемый
			# для устранения неоднозначности
my $prevInterval = 0; 	# предшествующий интервал времени
my @baseTones = (); # текущая введенная последовательность звуков
my @baseTimes = (); # текущие введенные временный величины
my %toneHash = (); 	# тоны, времена и команды считанные из ~/.toneFile
my $toneCount = 0; 	# текущий номер введенного тона
my $startTime = ""; 	# старт временного блока
my $currTime = ""; 	# текущее время цикле блокировки по времени
my $toneAge = 0; 		# для синхронизации счетчика тонов
my $timeOut = 0;		# для сброса таймера

Подпрограммы

Мы начнем с подпрограмм getEpochSeconds и getEpochMicroSeconds, используемых для обсепечения детальной и точной информации о статусе временных звуковых шаблонов.

Листинг 7. Подпрограммы getEpochSeconds и getEpochMicroSeconds
sub getEpochMicroSeconds {

 my $TIMEVAL_T = "LL";   # LL для микросекунд
 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 для микросекунд
 my $start = pack($TIMEVAL_T, ());
 syscall(&SYS_gettimeofday, $start, 0) != -1 or die "seconds: $!";
 return( (unpack($TIMEVAL_T, $start))[0] );
}#getEpochSeconds

Следующей будет подпрограмма readTones, которая сначала запрашивает значение Rolloff из вывода sndpeek. Как можно видеть из следующего раздела комментариев, программа сначала создает 5 образцов звуков, чтобы их сравнить для того, чтобы сформировать основу для вычисления отклонения. Если очередь массивов тонов заполнена, вычислить отклонение для каждого тона. Если сравнение любого звукового сигнала в очереди превышает максимальное отклонение, указать, что текущие данные не дают понятного тона.

Если отклонение всех тонов в очереди меньше, чем приемлемый порог, создать порог неоднозначного детектирования. Если вы насвистываете, слегка повышая тон, ваши индивидуальные ноты будут отклоняться достаточно мало от приемлемого порога и создадут узнаваемые звуковые события. Однако такое последовательное распознавание может создавать проблемы. Переменные upDev и downDev и логика сравнений сделаны так, чтобы воспринимать эти последовательные звуковые изменения, если они отклоняются более, чем на MAX_TONE_DEV. Если проверки как последних звуковых очередей, так и последовательных звуковых изменений выполнены, записать звуковые сигналы и их времена для дальнейшего вывода или сравнения.

Модификация этих переменных поможет настраивать программу для распознавания вашего собственного тонального стиля и временных отклонений. Скорость обновления частотного анализа определяется выводом программы sndpeek. Все остальные параметры можно настраивать для того, чтобы распознавать звуковые события в более широком диапазоне – множественные одновременные звуковые события в пределах временного порога или различные времена между звуковыми событиями.

Листинг 8. Детектируйте звуковые события в более широком диапазоне
sub readTones
{ 
 # считать только вывод Rolloff, 
 my(undef, undef, undef, $currentTone ) = split " ", $_[0];

 if( @queTones == $MAX_AVG_TONE )
 { 
  my $localDiff = 0;
  # проверить на чистоту тона, сравнивая с последними пятью тонами
  # выполнить простое сглаживание во времени, так что, если звук
  # немного колеблется, он еще считается одним тоном
  for my $chkHistTone ( @queTones )
  { 
   if( abs($currentTone - $chkHistTone) > $MAX_TONE_DEV )
   { 
    $localDiff =1;
    $prevTone = 0;
   }# если отклонение меньше порога
  }#для каждого тона

  if( $localDiff == 0 )
  { 
   # убедиться, что текущий тон отличается от предыдущего, это делается для того,  
   # чтобы убедиться, что тоны большой длительности не воспринимаются как множественные
   # звуковые события
   #
   # эти верхний и нижний пороги позволят вам свистеть постоянно и воспринимать
   # звуковые скачки как различные звуковые события
   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 (отклонение тона) 

   # теперь устанавливаем предыдущий тон равным  текущему так, что  
   # продолжительный тон не воспринимается как множественное звуковое 
   # событие
   $prevTone = $currentTone;

  }#if (найден чистый тон)

  # если добавлено достаточно тонов  для создания пригодной последовательности, 
  # вытолкнуть один из стека
  shift @queTones;

  }#if (добавлено достаточно тонов  для создания пригодной последовательности)

 # всегда помещайте в стек больше тонов
 push @queTones, $currentTone;

}#readTones

Когда звуковой шаблон создан, он помещается в файл ~/.toneFile и считывается следующей подпрограммой.

Листинг 9. Создание звуковых шаблонов
# readToneFile считывает звуковые последовательности и команды из ~/.toneFile
# формат: tones _#_ times _#_ command _#_ comments
sub readToneFile 
{
 #если вы находитесь в windows, укажите полный путь к .toneFile
 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 (не комментарий)

  }#для каждой строки в файле

 close(TONEFILE);

}#readToneFile

Когда звуковой шаблон считан при помощи readTone, он сравнивается звуковыми шаблонами, загруженными при помощи readToneFile. Подпрограмма compareToneSequences выполняет простую проверку различий между временными интервалами тонов, а также величинами тонов. Заметьте, что различия между тоновыми величинами и временными интервалами не смешиваются. Небольшие различия во временных интервалах или тонах на многих звуках не будут включаться в общую ошибку.

Для каждого тона в тоновом файле создайте тоновые и временные массивы для сопоставления. Первое сравнение производится по числу тонов, так как нет смысла проводить сравнение между 7-тоновой и 2-тоновой последовательностями. Для каждого тона и времени проверьте, что величины находятся в пределах допустимых параметров отклонений. Максимальное тоновое и временное отклонение критично для правильного, но не безошибочного сопоставления с вашей звуковой последовательностью. Вы можете увеличить максимальное отклонение тона или временного интервала, чтобы позволить себе быть более свободным в ритмике или тонах. Призываю вас быть осторожным и поэкспериментировать, так как более мягкие установки могут привести к ложным результатам детектирования. Например, попытайтесь увеличить порог отклонения тона до 5, оставляя порог временного отклонения равным 100000. Это позволит вам вводить звуки, отдаленно похожие на образец при правильных временах, и при этом соответствовать образцу – это полезно, если вы хотите использовать только ваши временные интервалы.

Если образец совпал целиком, команда, указанная в ~/.toneFile, запускается и распечатывается результат, если включен режим verbose. Следующий шаг – выход из подпрограммы, если не найдено совпадений, или сброс текущих звуков и времен, если было совпадение.

Листинг 10. Создание звуковых шаблонов
sub compareToneSequences 
{
 my $baseCount = @baseTones;
 my $countMatch = 0; # сколько звуков совпадает

 for my $toneFromFile ( keys %toneHash )
 {
  my @confTones = split " ", $toneHash{$toneFromFile}{tones};
  my @confTimes = split " ", $toneHash{$toneFromFile}{times};

  my $confCount = @confTones;

  next unless( $confCount == $baseCount );

  # для помощи в обучении  распечатываются совпавшие и не совпавшие части 
  # сравниваемого выражения, так что вы, по крайней мере, можете видеть, 
  # что происходит неправильно, пока вы пытаетесь запомнить ваши звуковые коды
  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 (распознанный звук за пределами разрешенных отклонений)


   # если звук  совпадает, увеличить счетчик совпадений
   if( $timeDiff < $MAX_TIME_DEV ){
    if( $option ){ print "TIME MATCH $timStr" }
    $countMatch++;
   }else{
    if( $option ){ print "TIME DISSONANCE $timStr" }
    last;
   }# проверка отклонения

   $pos++;

  }# проверить для каждого звука 

  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;

  # иначе, обнулить счетчик совпадений, чтобы переменные не были сброшены 
  }else
  { 
   $countMatch = 0;
  }

 }#для каждого звука в for each tone in tone file

 # если счетчик совпадений равен нулю, выйти и не сбрасывать переменные, поскольку может 
 #вводиться более длинная звуковая последовательность
 if( $countMatch == 0 ){ return() }

 # Если произошло совпадение, сбросить переменные, так как они не будут совпадать 
 # с другими шаблонами
 $toneCount = 0;
 @baseTones = ();
 @baseTimes = ();

}#compareToneSeqeunces

Логика основной программы

Вместе с подпрограммами логика основной программы позволяет пользователю создавать звуковую последовательность или работать в режиме демона для прослушивания звуков и выполнения команд. Первая часть выполняется, когда пользователь указывает опцию "-c" для режима "create". Для окончания последовательности звуков используется простая блокировка по времени. Увеличьте величину максимального таймаута для того чтобы разрешить паузу более 4 секунд между звуками. Если вы оставите максимальный таймаут равным 4, программа закончит работу и распечатает только что введенную вами звуковую последовательность.

Листинг 11. Блокировка по времени
if( $option eq "-c" ){

 print "enter a tone sequence:\n";

 $startTime = getEpochSeconds(); # установить время начала блокировки

 while( my $sndPeekOutput = <STDIN> )
 { 

  $currTime = getEpochSeconds();

  # проверить, не было ли звуков в промежутке  
  if( $currTime - $startTime > $MAX_TIMEOUT_LENGTH ){

   $timeOut = 1; # выход из цикла

  }else{

   # если звук был введен до блокировки, сбросить таймеры
   # так, чтобы можно было дальше вводить звуки

   if( $toneCount != $toneAge ){
    $startTime = $currTime;  # сбросить таймер задержки
    $toneAge = $toneCount; # синхронизовать счетчики звуков
   }# if (зафиксирован новый звук)

  }# if (таймаут не исчерпан)

  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 (введены звуки)

Вторая часть программы постоянно считывает вывод команды --print программы sndpeek. Группы звуковых сигналов автоматически сбрасываются после того, как достигнут порог блокировки по времени, для того, чтобы различать отдельные звуковые шаблоны. Рассмотрите модификацию переменной LISTEN_TIMEOUT для достижения более быстрого ввода звуковых последовательностей или увеличьте переменную блокировки по времени, чтобы запрашивать звуковые образцы с сильно разнесенными по времени звуками.

Листинг 12. Изменение LISTEN_TIMEOUT
}else
{ 
 # основной цикл для чтения звуков и запуска команд
 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;  #  сбросить таймер задержки
   $toneAge = $toneCount;  # синхронизовать счетчики звуков
   }# if (зафиксирован новый звук)

   compareToneSequences();

   }#if (таймаут не исчерпан)

  readTones( $sndPeekOutput );

 }#while stdin

}#if (установлена опция)

Предостережения и вопросы безопасности

Программа cmdWhistle хорошо подходит для обеспечения дополнительного канала для ввода информации в вашей системе, позволяя вашим рукам продолжать манипулировать мышью и клавиатурой. Будьте осторожны с использованием cmdWhistle для чего-либоб требующего подтверждения прав на доступ в вашей системе.

Вдобавок к очевидной проблеме возможности записи и имитации выбранной вами звуковой последовательности для запуска программ в вашей системе, существует множество других нюансов, связанных со звуковой идентификацией, которые указывают на то, что использование этого метода в любом серьезном контексте, по крайней мере, преждевременно. Звуковые последовательности постоянно сохраняются в ~/.toneFile как двузначные "ноты" вместе с четырех- и девятизначными значениями задержек в микросекундах. Прочесть такой "пароль" сравнительно легко и можно просто попытаться подобрать звуки, чтобы получить доступ к системе. Одностороннее хэширование может быть использовано для уменьшения точности в микросекундных значениях, но это лучше оставить читателю, желающему самому оценить степень риска.


Ресурсы для скачивания


Похожие темы

  • Оригинал этой статьи на developerWorks.
  • Программа sndpeek на сайте Princeton University.
  • ibiblio.org поддерживает зеркало программы xwit
  • Посетите IBM developerWorks PHP project resources, чтобы больше узнать о PHP.
  • Посетите developerWorks Open source zone для получения обширной справочной информации, утилит, и обновлений проектов. Все это поможет вам совершенствоваться вместе с opensource-технологиями и использовать их совместно с продуктами IBM.
  • Улучшите ваш следующий opensource-проект с помощью IBM trial software, доступного для загрузки или на DVD.

Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source, Linux
ArticleID=215809
ArticleTitle=Насвистывайте во время работы, чтобы запускать команды на своем компьютере
publish-date=04262007