[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
返: ssが音を出さなくなる問題と白藤さんの解決案 (長文)
小出です。
問題は、
1.Stopを連続して送ったときに、以後読まなくなる。
2.Queしているのに、だぶって音声が聞こえる
ということですか?
1.の問題はもう少しタイミングを考えてみないとわからないのですが、
AudioResetをかけたときは、必ずTextDataDoneが発生するので
そのときの処理(Queのリリース等)を見直すべきです。
2.は音声エンジンが違うものに対しては、1つのQue管理で行うときは
AudioStop eventを利用しないとダブってしまいます。
TextDataDoneというのは、エンジンが次のデータを受け付けられるという
タイミングで、その時点では1秒ぶんぐらい音が未出力のケースがあります。
ただし、同じエンジンであればエンジンのなかでQue管理を行っているので、
重なることなく順繰りに出力されます。
ですから、ひとつのエンジンを使うのであればQue管理は必要なく、
かまわずTextDataで出力してしまえばよいということにもなります。
そして、AudoResetですべて消えてくれますし・・・。
AudioStop Eventは音が完全に消えてから発生するするので、
このタイミングで、次のデータを出力すればエンジンが違っていても
重なることはありませんが、AudioStop Eventは気になる人には
気になるくらいの時間が空く傾向があります。
===============================
クリエートシステム開発株式会社
小出富夫<koide@...>
===============================
> -----元のメッセージ-----
> 差出人 : Takayuki Watanabe [mailto:takayuki@la.shonan-it.ac.jp]
> 送信日時 : 2000年8月21日 23:56
> 宛先 : Hideki Shirafuji; BEP ML
> CC : 小出 富夫
> 件名 : ssが音を出さなくなる問題と白藤さんの解決案 (長文)
>
>
> 渡辺@湘南工科大です。
> CC:小出様、
>
> 今日 白藤さんから、スピーチサーバーが音を出さなくなる問題に関して、解
> 決のアイデアを頂きました。BEP MLで議論した方がよいように思ったので、
> MLに白藤さんへの返事を書きます。
>
> 今、ソースを見て思い出したのですが、stop()はBishopさんのオリジナルでは
> 以下のようになっていたのですが、このままでは日本語エンジンを使ったときに
> stop()でハングアップするので、小出さんに調べてもらって修正しました。
>
> A オリジナル:
> void VoiceManager::stop()
> {
> m_speaking_cs.Lock();
> QueueBlock *qb = speaking_head;
>
> for(int i=0; i<NUMENGINES; i++) {
> engines[i].mpITTSCentral->AudioReset();
> }
> while(qb != 0) { // empty the blocks but keep them...
> qb->QText = "";
> qb->QInit = "";
> qb = qb->next;
> }
>
> m_speaking_cs.Unlock();
> }
>
> B 小出改良版:
> void VoiceManager::stop()
> {
> m_speaking_cs.Lock();
> QueueBlock *qb = speaking_head;
> // BEP
> while(qb != 0) { // empty the blocks but keep them because...
> qb->QText = "";
> qb->QInit = "";
> qb = qb->next;
> }
> for(int i=0; i<NUMENGINES; i++) {
> engines[i].mpITTSCentral->AudioReset();
> }
>
> m_speaking_cs.Unlock();
> }
>
> 英語と日本語ではエンジンの応答速さが異なり、英語で問題なかったところ
> が日本語で問題化したようです。AudioResetをかけると TextDataDoneが発生
> してqueueを更新してしまい、そのあとで qbを操作すると不法なアクセスに
> なりました。
>
>
> C 白藤改良版は:
> > しゃべらない場合、start_queue() のif文の
> > 最後の else に入ってきています。
> >
> > if(head == 0) {
> > } else if(speaking_head == 0) {
> > } else {
> > //しゃべらないときはここに入ってくる。
> > }
> >
> > この部分に問題があるのか、speaking_head
> > から続くリストが長くて、そのほとんどのQInit, QTextが空で
> > あるために、TTS の解析で時間だけがかかってしまい、結果として
> > 人間側が求める時間以内にしゃべり始められないのが原因の
> > 可能性があります。
> > 今回のソースは問答無用(SAPIと同期もとらずに)に、リストの
> > 長さを0にすることで、SAPIが空の文を解析する必要がないように
> > しています。
>
> void VoiceManager::stop()
> {
> m_speaking_cs.Lock();
> QueueBlock *qb = speaking_head;
> // BEP
> while(qb != 0) { // empty the blocks but keep them
> // because notifications may come in...
> qb->QText = "";
> qb->QInit = "";
> qb = qb->next;
> }
> for(int i=0; i<NUMENGINES; i++) {
> engines[i].mpITTSCentral->AudioReset();
> }
>
> // BEP
> while(qb != 0) {
> QueueBlock *qbnext = qb->next;
> delete qb;
> qb = qbnext;
> }
> speaking_head = NULL;
> speaking_tail = NULL;
>
> m_speaking_cs.Unlock();
> }
>
> として、立て続けにstopを送った際に音がでなくなる問題を回避しようとい
> うわけですね。
> 全エンジンにAudioResetをかけたら、キューを空にしても問題ないような気
> がするからこれで構わないような気がします。
> と思ったのですが、前の文の途中でstop()をかけて次の文を音声化すると、
> 次の文のキューの音声化がフライングします。
>
> たとえば、
> MyPrintMessage();
> for ( i=0 ; i < MAX_SIZE ; i++ ){
> の場合、MyPrintMessageを読んでいる途中でC-nで次の文を読ますと、
>
> 以下 VoiceManger.cppの関数呼び出しのログ:
> // MyPrintMessage();を読んでいる途中でstop()がかかった
> (行664) Stopped speaking
> // 次の行を読む
> (行522) Start queue
> (行549) :np-indent TextData '\rst\\spd=225\indent 4'
> (行875) TextDataDone dw=0
> (行579) next queue
> (行586) deleting 7960e0
> (行619) BEP; :nu nq TextData '\rst\\spd=225\for'
> (行875) TextDataDone dw=0
> (行579) next queue
> (行586) deleting 796120
> (行619) BEP; :np nq TextData '\rst\\spd=225\ open parenthesis i
> equal 0 semicolon i less than'
> (行875) TextDataDone dw=0
> (行579) next queue
> (行586) deleting 796320
> (行619) BEP; :np-smooth nq TextData '\rst\\spd=225\MAX underscore SIZE'
> (行875) TextDataDone dw=0
> (行579) next queue
> (行586) deleting 796e20
> (行619) BEP; :np nq TextData '\rst\\spd=225\ semicolon i plus plus
> close parenthesis left brace '
> (行875) TextDataDone dw=0
> (行579) next queue
> (行586) deleting 797da0
>
> と正しい順番にキューイングしてキューを処理しているのに、この文の読み
> 上げに参加する 3つのキューが重なって聞こえてしまいます。
> なぜだろう? TextDataDoneが返ってくるタイミングが早すぎるからというの
> が正しい答えだと思いますが、ではなぜBだとタイミングが合うのだろう?
>
> Bのバージョンに戻すとちゃんと同期して喋ります。
> またCでも、MyPrintMessage()を読み終わるまで待ってから次の行を読ますと
> ちゃんと喋ります。
>
> というわけでなんかおかしくなっていますが、なぜだろう、難しい...
> 白藤さんや小出様、理由がわかりますか?
>
>