[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: 返: ssが音を出さなくなる問題と白藤さんの解決案 (長文)



白藤です。お久しぶりです。
最終的な解決のめどがつかないので、とりあえず中間報告です。

koide wrote
>小出です。
>
>問題は、
>1.Stopを連続して送ったときに、以後読まなくなる。
>2.Queしているのに、だぶって音声が聞こえる
>ということですか?
>
>1.の問題はもう少しタイミングを考えてみないとわからないのですが、
>AudioResetをかけたときは、必ずTextDataDoneが発生するので
>そのときの処理(Queのリリース等)を見直すべきです。
>
どうもそのTextDataDone()が発生していないような気がします。

VoiceManager の start_queue(), next_queue(), stop(),
VMSink TextDataDone() を見てみました。

C-n, C-p で読み上げなくなったとき、
start_queue() の
	if(head == 0) {
		何も読み上げる物はない
		もしくはバグ?
	} else if(speaking_head == 0) {
		今は何も読み上げていない
		読み上げを開始する
	} else {
		今はすでに前の文字列を読み上げ中。
		そこにリストを追加する
	}
の最後のelseの所に来ています。
この時、Speach.exe 自身はTTSが文字列を読み上げている最中だと
思っていますが、実際には何も読み上げていません。
これではリストが長くなるだけで、永久にTTSに読み上げを開始する
処理には入りません。
これがしゃべらなくなる現象の実体のようです。

どういう場合にこの状態になるかが問題の糸口でしょう。
読み上げ中のバッファの解放は、TextDataDone() から呼ばれる
next_queue() で処理されています。next_queue() が再起的に
呼ばれることで最後までの同期的読み上げと解放が行われています。

stop()がかかったときに何らかの理由でTextDataDone()/next_queue() 
が呼ばれない場合があるように思います。



解決するためには、
1.確実にTextDataDone()/next_queue() が呼ばれるように直す
呼ばれないのはProTALKER 特有の問題のような気配も濃いです。
具体的にどのような状態の時に呼ばれないのか、確認方法が思い浮かびません。
また、はっきりと呼ばれていないとも確認できていません。

2.TTSが止まったことが確認してからspeaking_head が残っていれば解放する
Speach API のマニュアルを見てみましたが、停止の状態を確認する方法が
見つかりませんでした。
また、非同期で動作している状態で、TTSが停止していることを確認できるか
どうかにも疑問があります。

3.半分やけ
VSinkはCOM/OLE なので、Release() はどんな状態でも呼ばれるはずなので、
STDMETHODIMP_(ULONG) VMSink::Release (void)
{
	// normally this releases a reference count, but this object
	// is going to be freed when the application is freed so it doesnt
	// matter

	// BEP
	// If it has already stopped. clean up speaking buffer.
	vm->m_speaking_cs.Lock();
	if (vm->speaking_head != NULL &&
		vm->speaking_head->QText.IsEmpty()) {
		vm->next_queue();
	}
	vm->m_speaking_cs.Unlock();
	return 1;
}
というのも試してみました。
この前のソースよりはましですが、非常に重いです。
C-p を押し続けると、解放に時間がかかり、しばらくしゃべりません。
声が重なることはなさそうです。
VoiceManager のメンバー変数をpublic にする必要もあります。
やっぱりその場しのぎです。



// Name : Hideki Shirafuji
//
// mailto:shirafuji@mail.com