お世話になりっぱなしですみません。
Speak で連続して文字列を送信すると
おしゃべりが終了するのに時間がかかるのですが、
処理はとまることなく実行されていきます。
おしゃべりが終了するのをまってから、
次の処理へと移動したいのですが、
どうすればよいのでしょうか?
英語の言語使用では
以下のようにしなさいと使い方が説明してあります。
procedure TForm1.hoge;
var
A : IAgentCtlRequest;
begin
A := FCharacter.Speak('hoge','');
FCharacter.Wait(A);
//次の処理
end;
しかーし、なぜかDelphiでは動きません。
そこで、TAgentには「RequestComplete」というイベントが
あるので、このイベントが発生するまでは次の処理をさせない
といった管理をしてやるとうまく出来ます。
このイベントは、話したり動いたりが終わったら発生します。
誤字すいません(w
>英語の言語使用では
英語の言語仕様ですね。
ちなみにVBでの使い方として紹介されていました。
ぶちょうさんどうもお世話になります。
早速ですが、ためしてみました。
AgentRequestStart も AgentRequestComplete
のどちらも、イベントが発生しないんですが・・・
それから、別もんですみませんが、
Connected プロパティって
一度 True にすると False に戻りませんが、
このプロパティって何でしょうか?
ちなみにイベントは以下のようにしました。
RequestProcess: Boolean; をグローバルにして
procedure TFormMain.AgentRequestStart(Sender: TObject;
const Request: IDispatch);
begin
RequestProcess := True
end;
procedure TFormMain.AgentRequestComplete(Sender: TObject;
const Request: IDispatch);
begin
RequestProcess := False;
end;
呼び出し部分はこんな感じです。
Character.Show(False);
Character.Speak('メッセージ1', '');
Character.Speak('メッセージ2', '');
:
Character.Speak('メッセージn', '');
while RequestPRocess do Application.ProcessMessages;
// 処理
// この部分では別メニューを表示して音声を出すが、
// 以下のHide が途中で実行され、キャラが引っ込んでしまう・・・
//
Character.Hide(false);
意味不明かも知れませんけど、下のように一行追加してみてください。
>呼び出し部分はこんな感じです。
>Character.Show(False);
>Character.Speak('メッセージ1', '');
>Character.Speak('メッセージ2', '');
RequestPRocess := True;←この場所に、これをつけてみてください。
>Character.Speak('メッセージn', '');
>while RequestPRocess do Application.ProcessMessages;
>// 処理
>// この部分では別メニューを表示して音声を出すが、
>// 以下のHide が途中で実行され、キャラが引っ込んでしまう・・・
>//
>Character.Hide(false);
もっと簡単なテストプロ作ってみました。
しゃべり始める前に、ShowMessage が実行されます。
Delphi6 を使用しています。
Character.Show(False);
RequestProcess := True;
Character.Speak('メッセージ', '');
// しゃべり終わるまで待つ
while MSWSystem.RequestProcess do Application.ProcessMessages;
if RequestProcess
then ShowMessage('しゃべり終わった = True')
else ShowMessage('しゃべり終わった = False');
Character.Hide(False);
while RequestProcess do Application.ProcessMessages
↑
間違っていたので修正しました。
結果は同じです。
おかしいですね、イベント発生しないですか・・
どうも、フォームが2つ以上あるみたいなので、お手数ですが
いったん新しくプロジェクトを作成して試してみてください。
フォームに、ボタンとTAgentだけを貼り付けて、
グローバルにFFlg:booleanを作って、以下のコードで。
procedure TForm1.Button1Click(Sender: TObject);
begin
Agent.Characters.Load('MyChara','C:\WINDOWS\MSAGENT\CHARS\Genie.acs');//ここは環境にあわせて
Character := Agent.Characters.Character('MyChara')as IAgentCtlCharacterEx;
Character.Show(False);
FFlg := True;
Character.Speak('こんにちは', '');
while FFlg do Application.ProcessMessages;
Character.Speak('こんにちは', '');
Character.Hide(False);
end;
procedure TForm1.AgentRequestComplete(ASender: TObject;
const Request: IDispatch);
begin
FFlg := False;
Button1.Caption := datetimetostr(now);//反映されたか確認を
end;
procedure TForm1.AgentRequestStart(ASender: TObject;
const Request: IDispatch);
begin
FFlg := True;
end;
xpでDel7と2005しかないですが、こっちでは発生します。。
ぶちょうさん すみません。
なんらかの状態のときに発生しないことがあるようです。
いじってるうちに動くようになりました。
でも、発生しなかった状態にすることはできませんでした。
show, Speak, while, hide で、
while の入れる位置によって違うようなというより、
while 上記の問題で 別処理に移動して、そこでまた、
音声処理しているのでその辺が怪しいのかと・・・
サンプルで試したときはイベント発生は確かにしています。
ただ、問題は、前記のとおり、
イベントがすぐに発生し、て False になって
while 文をすぐに抜けてしまいます。
どうしてなんでしょうか?
先ほどから、めっちゃ気になっているのが
MSWSystem.RequestProcessの「MSWSystem」なのですが、
MSWSystemとは別フォームですか?これは何者ですか?
MSWSystemにもRequestProcessがあり、
メインルーチンが動いているフォームにもRequestProcess
があったりとか・・・しませんよね?
・・・まさかですよね。いや、失礼。
うーん、なぜでしょう。もっと判断材料があれば。。
ちなみに、イベント発生条件についてですが先のサンプルで書いた
> Character.Show(False);
> FFlg := True;
> Character.Speak('こんにちは', '');
の FFlg := True;の箇所をコメントアウトすると発生しなくなります。
これについてですが、私も意味不明です。Delphiが最適化してる?
MSWSystem は TObject から派生したクラスで・・・
アプリケーション内で使用している
グローバル変数や、関数をひとまとめにしたものです。
どうしてこんなことしてるかというと。
支援機能を使ったときに
[MSWSystem.]で変数名や、関数名の参照が出るためです。
そうすると[MSWSystem]だけ覚えておけばあとの共通で使用する関数や
変数といったものは支援機能のリストで表示されるからで、
VCLとかのクラスからの派生じゃありません。
MSWSystem.pas (基本ユニット)を作成しグローバル部で
---------------------------------
var
MSWSystem: TMSWSystem;
---------------------------------
と記述して、後は、MSWSystem を使用するユニット(すべてのユニット)に
Uses で追加指定して使用しています。
前置きが長くなりましたが、本題にはいります。
以下は現在のテストプログラムです
●ステップ実行で1行ずつ実行していくと3種類の音量になると思います。
●次に普通に実行します。そうするとPCにより違うかもしれませんが
メッセージ1とメッセージ2は同じ音量で、
メッセージ3は音がでません。
●イベント部分にブレークポイントを入れると停止します。
イベントは発生しています。
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleCtrls, AgentObjects_TLB, StdCtrls, MMSystem;
type
TForm1 = class(TForm)
Button1: TButton;
Agent1: TAgent;
procedure Button1Click(Sender: TObject);
procedure Agent1RequestComplete(Sender: TObject; const Request: IDispatch);
procedure FormCreate(Sender: TObject);
private
Character: IAgentCtlCharacterEx;
RequestPRocess: Boolean;
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Agent1.Characters.Load('MyChara', 'C:\Windows\MSAGENT\CHARS\Peedy.acs');
Character := Agent1.Characters.Character('MyChara') as IAgentCtlCharacterEx;
Character.Set_TTSModeID('{A778E061-A936-11d1-B17B-0020AFED142E}');
Character.LanguageID := $0411;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Character.Show(False);
WaveOutSetVolume(0, $40404040);
RequestPRocess := True;
Character.Speak('メッセージ1', '');
while RequestPRocess do Application.ProcessMessages;
WaveOutSetVolume(0, $80808080);
RequestPRocess := True;
Character.Speak('メッセージ2', '');
while RequestPRocess do Application.ProcessMessages;
WaveOutSetVolume(0, $FFFFFFFF);
RequestPRocess := True;
Character.Speak('メッセージ3', '');
while RequestPRocess do Application.ProcessMessages;
WaveOutSetVolume(0, 0);
Character.Hide(False);
end;
procedure TForm1.Agent1RequestComplete(Sender: TObject; const Request: IDispatch);
begin
RequestPRocess := False;
end;
end.
ボタンを押したときの処理を
以下のようにすると3種類の音量で聞けるのですが、
鳥さんが行ったりきたりしてしまうので、
これじゃ使用できないですよね。
もし、このアニメの表示をオフにできる方法があれば
行ったりきたりしないですむのですが、
そういった方法は・・??
と、思ったのですが、もしあったとしても、
アニメ表示がないとShow や、 Hide もなくなるわけですよね....
−−−−−−−−−−−−−−−−−−−−−−−−−−
Character.Show(False);
WaveOutSetVolume(0, $40404040);
Character.Speak('メッセージ1', '');
Character.Hide(False);
while Character.Visible do Application.ProcessMessages;
Character.Show(False);
WaveOutSetVolume(0, $80808080);
Character.Speak('メッセージ2', '');
Character.Hide(False);
while Character.Visible do Application.ProcessMessages;
Character.Show(False);
WaveOutSetVolume(0, $FFFFFFFF);
Character.Speak('メッセージ3', '');
Character.Hide(False);
while Character.Visible do Application.ProcessMessages;
WaveOutSetVolume(0, 0);
試しに、
グローバルに
ACR : IAgentCtlRequest;
と宣言して、
それぞれのSpeakをコールしている所を
ACR := Character.Speak('メッセージ?', '');
に変更して、
Agent1RequestCompleteを次のように変更したらどうでしょう?
procedure TForm1.Agent1RequestComplete(Sender: TObject; const Request: IDispatch);
begin
if ACR <> Request then Exit;
RequestPRocess := False;
end;
ぶちょう さん、
音量が3種類になり目的通りの処理ができました!
どうして?
いまひとつ理解できてません。
おー。よかったですね。
Speak以外にもリクエストがどこかで発行されていて、
それのコンプリートイベントを受信してしまっているからでしょうね。
エージェントが内部的にリクエストを発行しているのかも
しれませんし。
ぶちょうさん お手数をおかけして
どうもありがとうございました。
なんとかなりそうです。
ツイート | ![]() |