Хочется голосового управления в программах? Не! Конечно не во всех! Но в части "тупого дома" вполне вариант.
Господа разработчики одной из опенсурсных библиотек распознавания речи (CMU Pocketsphinx) полагают, что использовать их продукт можно и должно токма на ведроиде и сях. Пришлось малость поковыряться в их кривом коде и адаптировать его под свои нужды...
Ну пасквилянт я! Не могу опуститься до уродливого синтаксиса Це--
Пример использования библиотеки тут:
program project1;
{$mode objfpc}{$H+}
uses
Classes, SysUtils, pocketsphinx, CustApp;
type
TMyApplication = class(TCustomApplication)
protected
procedure DoRun; override;
procedure Say(txt: string);
public
procedure WriteHelp; virtual;
end;
const
cmdLn: array [0..3] of PChar = (
'-jsgf', '/usr/share/hobgoblin/my.jsgf',
'-dict', '/usr/share/hobgoblin/my.dict'
);
micBuffSize = 512;
procedure TMyApplication.DoRun;
var
ErrorMsg: String;
buff: array [0..micBuffSize - 1] of int16;
ad: PpsAudioDevice;
conf: PpsConfig;
ps: PpsDecoder;
b: integer;
uttStarted, inSpeech: boolean;
s, dt: string;
us: WideString;
s1: RawByteString;
begin
// parse parameters
if hasoption('h', 'help') then begin
writehelp;
terminate;
exit;
end;
{ add your program here }
say('parse settings...');
conf:= cmd_ln_parse_r(nil, psdefaultargs, length(cmdln), @cmdln, true);
if not assigned(conf) then begin
terminate;
exit;
end;
say('apply settings...');
ps_default_search_args(conf);
say('init sphinx...');
try // realy init stupid library
ps_start_utt(nil)
except end;
ps:= nil;
try
ps:= ps_init(conf);
except
on e: exception do say(e.message);
end;
if not assigned(ps) then begin
cmd_ln_free_r(conf);
say('sphinx not started :(');
terminate;
exit;
end;
say('starting mic...');
ad:= ad_open_sps(16000);
if not assigned(ad) then begin
ps_free(ps);
cmd_ln_free_r(conf);
say('mic not started :(');
terminate;
exit;
end;
ad_start_rec(ad);
say('starting sphinx...');
uttstarted:= false;
try
if ps_start_utt(ps) > -1 then while not Terminated do begin
b:= ad_read(ad, buff, micBuffSize);
if b < 1 then break;
ps_process_raw(ps, buff, b, 0, 0);
inSpeech:= ps_get_in_speech(ps) > 0;
if not uttStarted and inSpeech then Say('listen...');
uttStarted:= uttStarted or inSpeech;
if not inSpeech and uttStarted then begin
ps_end_utt(ps);
s:= string(ps_get_hyp(ps, nil));
if (s > '') then try
writeln(s);
us:= Utf8Decode(s);
s1:= '';
widestringmanager.Unicode2AnsiMoveProc(punicodechar(us), s1, 1251, length(us));
dt:= '';
for b:= 1 to length(s1) do dt:= dt + IntToHex(byte(s1[b]), 2);
//lineModule1.SendData('virt', 'T', dt);
except end;
if ps_start_utt(ps) < 0 then break;
uttStarted:= False;
Say('ready...');
sleep(100);
end;
end;
finally
ad_stop_rec(ad);
ad_close(ad);
Terminate;
end;
ps_free(ps);
cmd_ln_free_r(conf);
end;
procedure TMyApplication.WriteHelp;
begin
writeln('Usage: ', ExeName, ' -h');
end;
procedure TMyApplication.Say(txt: string);
begin
writeln(txt);
end;
var
Application: TMyApplication;
begin
Application:=TMyApplication.Create(nil);
Application.Title:='My Application';
Application.Run;
Application.Free;
end.
За "изящество" кода извиняйте! Сие - быстрая адаптация куска мелкого робота. Но, как мне кажется, вполне достаточная для понимания.
Я влепил в библиотеку только те функции и типы данных, которые мне шкурно и сиюсекундно были нужны. Если есть надобность (во что я не верю), остальное можете быстренько накидать из описаний на их сайте.
Инструкция по установке - там же.
Самая нудная работа по адаптации этого чуда (сбор начальных параметров из разных источников в сырцах) таки сделана. Остальное - мелочь.
Пользуйтесь ахы :)
З.Ы. в примере есть мелкий кривой кусочек:
try // realy init stupid library
ps_start_utt(nil)
except end;
Он нужен в случае инициализации библиотеки версии 5-prealpa для работы в консольных приложениях. Не знаю почему, но, без насильственного вызова сбоя при распознавании, библиотека выдает ошибку "Division by zero" во время передачи в нее настроек. Возможно, для пейсателей, хранящих настройки в коде в текстовом виде, это таки нормально.
Впрочем, если либу устанавливать из репозиториев Ubuntu, таких проблем не возникает и все работает как надо без этих извращений.
Для успешной компиляции проектов на линюхе (если библиотека устанавливалась из репозитория, а не компилировалась из исходников) выполните:
sudo apt-get install libpocketsphinx-dev libsphinxbase-dev