文が発音されない時があるのですが??


AS  2019-07-13 00:29:30  No: 49823

こんにちは。いつもお世話になっています。

日本語文と英語文を交互に発音させるために、
日本語の発音をC言語で作り使っていますが、
下の例では、ボタンを交互に押すと、発音されないことがあります。
SpeaktoMeを使うと、すべて発音されます。
日本語は発音されなくてもいいやと思って日本語文に使っていますが。
何か解決策があれば、教えていただきたいと思い投稿しました。

よろしくお願いします。

procedure TFLily.JSpeak(WD:string);
var
  s:string;
  res:boolean;
  Si: TStartupInfo;
  Pi: TProcessInformation;
begin
  Bunput(WD);     application.ProcessMessages;
  s := 'c:\lily\JapaneseSpeakB.exe';
  FillChar(SI, SizeOf(SI), #0);
  SI.cb := SizeOf(SI);
  SI.dwFlags := STARTF_USESHOWWINDOW;
  SI.wShowWindow := 1;
  Res := CreateProcess(PChar(s),nil,nil,nil,False,
         CREATE_DEFAULT_ERROR_MODE,nil,nil,SI, PI);

end;

procedure Tlily.BunPut(wd:string);
var
  InBuff: string;
  FileName1:string;
  F: textfile;
  i:integer;
begin
  FileName1:='c:\Flily\日本語文.txt';
  AssignFile(F, FileName1); Rewrite(F);
  INbuff:=WD;
  writeln(F,inBuff);
  CloseFile(F);
end;

procedure TFLily.Button3Click(Sender: TObject);
begin
  //SpeakToMe(Edit1.text);  application.processMessages;
  JSpeak(Edit1.text);   application.processMessages;
end;

procedure TFLily.Button4Click(Sender: TObject);
begin
  //SpeakToMe(Edit2.text);  application.processMessages;
  JSpeak(Edit2.text);   application.processMessages;

end;

procedure TFLily.SpeakToMe(WD:string);
var
  tts : OleVariant;
begin
//  if EJSWFLG=false then exit;
 // then tts.selectVoice('Zira') else tts.selectVoice('Haruka');
  tts := CreateOleObject('SAPI.SpVoice');
//  tts.volume:=100;
//  tts.voice:= 'Microsoft Haruka desktop';
  tts.Speak(WD);

{
  <英語用モジュール>
    synth.SelectVoice(英語者名:Zira)
            synth.Speak(英語発声文)
            synth.Dispose()
<日本語用モジュール>
    synth.SelectVoice(日本語者名:Haruka)
            synth.Speak(日本語発声文)
            synth.Dispose()
}
end;


take  2019-07-13 01:20:33  No: 49824

まずわかりにくさの整理を

CreateProcessを使ってコマンドライン実行で音声データをしゃべらせる場合と
CreateOleObjectを使ってOLEオブジェクトとしてしゃべらせる場合とで挙動が異なります。

前者は再生されないときがありますが、後者は正常に再生されます。

こういうことかな?

で次

CreateProcessもCreateOleObjectも使い終わったら終了処理が必要なのではないでしょうか?
CreateOleObjectは連続で実行されても多重で実行されるので見た目問題なし(メモリには残りそうですが)

CreateProcessは呼ばれたときに、現在再生中かどうか判断して
再生中なら再生しない仕様になっているのだと思います。

そしてCreateProcessで呼んだ場合はプロセス終了(音声の再生終了)まで待機してから終了処理を
実行すべきです。

どうやるかは、使いたい命令の後ろにスペースを空けて Delphi でググればすぐ答えが出てきます。


AS  2019-07-14 02:12:38  No: 49825

takeさんへ

ありがとうございます。
ネットで調べてみます。


AS  2019-07-14 19:21:42  No: 49826

ネットで検索すると、X-RAYさんのHPに行けて下記のように変更しました.
しかし、コンパイルすると、
 GetExitCodeProcess(PI.hProcess, Result);
の行でタイプが一致しないといけないとかのエラーが出ます。
IF分より上はマネしてないのですが、そこが問題でしょうか??

procedure TForm1.JSpeak(WD:string);
var
  s:string;
  result:integer; //boolean;
  Si: TStartupInfo;
  PI: TProcessInformation;
begin
  Bunput(WD);   application.ProcessMessages;
  s := 'c:\英文練\JapaneseSpeakB.exe';
  FillChar(SI, SizeOf(SI), #0);
  SI.cb := SizeOf(SI);
  SI.dwFlags := STARTF_USESHOWWINDOW;
  SI.wShowWindow := 1;

  if CreateProcess(PChar(s),nil,nil,nil,False,
     CREATE_DEFAULT_ERROR_MODE,nil,nil,SI, PI)=false then
  begin
    Result := WAIT_FAILED
  else
  begin  //起動したプロセスが終了するまで待つ
    while WaitForSingleObject(PI.hProcess, 100) = WAIT_TIMEOUT do
                                     Application.ProcessMessages;

    GetExitCodeProcess(PI.hProcess, Result);
    CloseHandle(PI.hProcess);
    CloseHandle(PI.hThread);
  end;

//  Res := CreateProcess(PChar(s),nil,nil,nil,False,
//         CREATE_DEFAULT_ERROR_MODE,nil,nil,SI, PI);

end;


通りすがり  2019-07-14 19:44:43  No: 49827

GetExitCodeProcessの定義を検索してみましたか?(ソースコード上で[Strl]+クリック)
第2パラメータが var lpExitCode: DWORD となってますよね?ですからここにはDWOD型の変数しか書けません。


AS  2019-07-15 12:53:03  No: 49828

通りすがりさんへ
いつもありがとうございます。

Var
 result:Dword;

とすると、コンパイルは成功しました。

連続使用すると、発音されない時があるという現象は変わりませんでした。

うまい方法があれば、教えてくださいませ。


通りすがり  2019-07-15 20:24:23  No: 49829

とりあえずJSpeakを連続に呼び出すときに、1回ずつSleep(1000);を挟んだらどうなりますか?
またうまくいくのであれば1000を減らしていくとどうなりますか?あたりを試してみては。


take  2019-07-16 17:23:32  No: 49830

アプリケーションの動きがちょっと理解しておられないだけかと

ボタンクリックイベント内で
JSpeak発音→JSpeak発音終了待ち
処理が行われますが
この間も  Application.ProcessMessagesによりボタンクリックが可能です。

発音中に再度発音させるので発音できないのでしたら
発音中は
1.発音中は発音させない
2.「キュー」を用意して処理を後回しにする
のどちらかが必要です。

とりあえず前者の処理を作ってみましょうか?


AS  2019-07-17 08:46:45  No: 49831

通りすがりさん、takeさん、ありがとうございました。

JSpeakの前後に2秒とかを置いて、起動後しゃべる前にボタンを
4連続クリックしたら4連続話をさせることができました。
ただ、やはり、話してるときにボタンをクリックしたら話しはしません。

話をさせないということで、話してる途中であるという変数speakingflgを
作って、話し中なら待つということもやってみましたが、
while speakingflg=true do sleep(1000);
いつまでも終わらない感じで、うまくいきませんでした。
で、ボタンが押されても、SpeakingFlg=trueのときは処理をしないようにしました。

形の上では、問題はなくなりました。


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加