admin

[应用技巧] delphi利用微软SAPI实现语音控制(Delphi,TTS,SR,灰色代码)

和群里的大小牛们聊天时突发奇想,做了这个东西,通过麦克风发送命令控制电脑。程序没有什么深奥之处,调用了微软的SAPI实现语音识别,和文本语音,关于文本语音可参见我以前的文章。使用语音识别时最好根据个人情况进行语音训练,测试程序提供了鼠标移动,单击,运行指定程序等基本功能,可以酌情添加做成更丰富功能的软件。


安装微软语音朗读控件后,delphi,project,input type library,找到Microsoft speech 5.1,安装即可


Caption:=IntToStr(SpVoice1.Status.RunningState);


如果caption =2 正在朗读中。  =1 朗读完了  判断朗读状态




unit main;


interface


uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls, OleServer, SpeechLib_TLB,ActiveX, ComCtrls,ControlCenter;


type

TadeSoundControl = class(TForm)

SpVoice1: TSpVoice;

Edit1: TEdit;

Button1: TButton;

Edit2: TEdit;

Memo1: TMemo;

SpSharedRecoContext1: TSpSharedRecoContext;

ProgressBar1: TProgressBar;

Edit3: TEdit;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

procedure Speecker(id:Integer;speech:Integer;str:string);

procedure SpSharedRecoContext1SoundStart(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant);

procedure SpSharedRecoContext1SoundEnd(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant);

procedure SpSharedRecoContext1Recognition(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant;

RecognitionType: TOleEnum; const Result: ISpeechRecoResult);

procedure FormCreate(Sender: TObject);

procedure SpSharedRecoContext1AudioLevel(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant;

AudioLevel: Integer);

procedure vg2Background1Click(Sender: TObject);


private

SRGrammar: ISpeechRecoGrammar;

CmdLine:string;

ControlActive:Boolean;

public

procedure Log(s1:string);overload;

procedure Log(s1:string;s2:string);overload;


end;


var

adeSoundControl: TadeSoundControl;


implementation


{$R *.dfm}

procedure TadeSoundControl.Speecker(id:Integer;speech:Integer;str:string);

var

SOToken: ISpeechObjectToken;

SOTokens: ISpeechObjectTokens;

begin

SOTokens := SpVoice1.GetVoices('', '');

SOToken := SOTokens.Item(id);

SpVoice1.Voice := SOToken;

SpVoice1.Rate:=speech;

SpVoice1.Volume:=100;

spvoice1.Speak(str,SVSFDefault);

end;


procedure TadeSoundControl.Button1Click(Sender: TObject);

begin

Speecker(StrToInt(Edit2.Text),StrToInt(Edit3.Text),Edit1.Text);

end;

procedure TadeSoundControl.Log(s1:string);

begin


Memo1.Lines.Add(s1);

end;

procedure TadeSoundControl.Log(s1:string;s2:string);

begin

Memo1.Lines.Add(s1+s2);

end; 

procedure TadeSoundControl.Button2Click(Sender: TObject);

begin

Log('ade');

end;


procedure TadeSoundControl.Button3Click(Sender: TObject);

begin

Log('fuck','ade');

end;


procedure TadeSoundControl.SpSharedRecoContext1SoundStart(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant);

begin

Log('Sound Start');

end;


procedure TadeSoundControl.SpSharedRecoContext1SoundEnd(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant);

begin

Log('Sound End');

end;


procedure TadeSoundControl.SpSharedRecoContext1Recognition(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant;

RecognitionType: TOleEnum; const Result: ISpeechRecoResult);

var

adeString:string;

pt:TPoint;

h:HWND;

begin


with Result.PhraseInfo do

begin

adeString:=GetText(0, -1, True);

end;

if adeString='小二' then

begin

ControlActive:=True;

Speecker(3,6,'老爷,小的在!');

Self.Show;

Exit;

end;

if adeString='退下' then

begin

ControlActive:=False;

Speecker(3,5,'是,老爷。小的先退了');

Self.Hide;

//ShowWindow(Self.Handle,SW_HIDE);

Exit;

end;

if adeString='单击' then

begin

GetCursorPos(pt);

h:=WindowFromPoint(pt);

mouse_event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);

mouse_event(MOUSEEVENTF_LEFTUP,0,0,0,0);

Exit;

end;

if adeString='左移' then

begin

GetCursorPos(pt);

SetCursorPos(pt.X-150,pt.Y);

Exit;

end;

if adeString='右移' then

begin

GetCursorPos(pt);

SetCursorPos(pt.X+150,pt.Y);

Exit;

end;

if adeString='上移' then

begin

GetCursorPos(pt);

SetCursorPos(pt.X,pt.Y-150);

Exit;

end;

if adeString='下移' then

begin

GetCursorPos(pt);

SetCursorPos(pt.X,pt.Y+150);

Exit;

end;

if adeString<>'命令结束' then

begin

if CmdLine='' then

CmdLine:=adeString

else

CmdLine:=CmdLine+'|'+adeString;

log('正在等待下一条命令!命令结束请说"命令结束"');

end

else

begin

execCommand(CmdLine);

Log('已经成功执行命令:'+CmdLine);

CmdLine:='';

end;

end;


procedure TadeSoundControl.FormCreate(Sender: TObject);

begin

SpSharedRecoContext1.EventInterests:=SREAllEvents;

//SpSharedRecoContext.CreateGrammar(0);

SRGrammar := SpSharedRecoContext1.CreateGrammar(0);

SRGrammar.CmdLoadFromFile('adeCmdLine.xml', SLODynamic);

SRGrammar.CmdSetRuleIdState(0, SGDSActive);

end;


procedure TadeSoundControl.SpSharedRecoContext1AudioLevel(ASender: TObject;

StreamNumber: Integer; StreamPosition: OleVariant; AudioLevel: Integer);

begin

progressbar1.Position:=AudioLevel;

end;


procedure TadeSoundControl.vg2Background1Click(Sender: TObject);

begin

ControlActive:=False;

end;


end.






以下改为使用线程方式朗读,可以避免朗读时卡顿


function readnow(p:Pointer):Integer; stdcall; 

var

  SOToken: ISpeechObjectToken;

  SOTokens: ISpeechObjectTokens;

begin

  SOTokens := adeSoundControl.SpVoice1.GetVoices('','');

  SOToken := SOTokens.Item(0);

  adeSoundControl.SpVoice1.Voice := SOToken;

  adeSoundControl.SpVoice1.Rate:=0;

  adeSoundControl.SpVoice1.Volume:=100;

  adeSoundControl.spvoice1.Speak(speekstr,SVSFDefault);

end;



按钮click

var

  ID: THandle;

begin

      speekstr:=b;  //要朗读的内容

      CreateThread(nil,0,@readnow,nil,0,ID);

end;




#1楼
发帖时间:8月前   |   查看数:0   |   回复数:1
admin
uses Comobj;  
 
procedure TForm1.Button1Click(Sender: TObject);  
var  
 voice: OLEVariant;  
begin  
 voice := CreateOLEObject('SAPI.SpVoice');  
 voice.Speak('Hello World!', 0);  
end;
8月前 #2楼
游客组