私は 1 週間、Ubuntu で FreeTTS を動作させようとしている学生です。そして最後に、ここで答えを見つけました: hakvroot に感謝します!
あなたの答えは完璧でしたが、あなたは実装を入れていませんでした.JavaStreamingAudioPlayerクラスで何が起こっているのかを理解するのにかなり1時間かかりました. 完全に未知の Java コード (私はまだ学生です) で「ダイビング」に慣れていない私のような他の人々を助けるために、ここに私のコードを置き、それが他の人々の助けになることを願っています :) .
まず、より詳細な説明: 152 行目あたりで、JavaStreamingAudioPlayer が Line を開きます。ただし、この操作には時間がかかる場合があるため、使用する前に、開いていることを確認する必要があります。現在の実装で使用されている解決策は、この行をリッスンする LineListener を作成してからスリープすることです (スレッドの wait() メソッドを使用)。
LineListener は、notifyAll() を使用してメイン スレッドを「ウェイクアップ」し、ラインが開かれたことを保証するタイプ「OPEN」の LineEvent を受け取った場合にのみこれを行います。
ただし、ここで hakvroot によって説明されているように、問題は、Ubuntu で使用される DataLine の特定の動作のために、通知が送信されないことです。
そのため、コードの同期、wait()、および notifyAll() 部分を削除しましたが、hakvroot として、JavaStreamingAudioPlayer が Line を開く前に使用しようとする可能性があります。JavaStreamingAudioPlayer を停止するには、新しいメカニズムで確認を待つ必要があります。確認が到着したときに、後でそれを起こしてください。
そこで、havkroot が使用したセマフォを使用しました (このロック システムの説明については、Javadoc を参照してください)。
ラインが開かれると、1 つのスタックが取得されます (つまり、0 のままです)
回線を使用したい場合は、別の回線を取得しようとします (そのため停止します)
リスナーが探しているイベントを取得すると、セマフォが解放されます
これにより、次の部分に進むことができる JavaStreamingAudioPlayer が解放されます
セマフォを再度解放することを忘れないでください。これにより、次の行を開くためのスタックが再び 1 つになります。
そして、ここに私のコードがあります:
セマフォ変数を宣言します。
private Semaphore hackSemaphore;
コンストラクターで開始します。
hackSemaphore = new Semaphore(1);
次に、最初の部分を置き換えます (どこに置くかについては、hakvroot を参照してください)。
line = (SourceDataLine) AudioSystem.getLine(info);
line.addLineListener(new JavaStreamLineListener());
line.open(format, AUDIO_BUFFER_SIZE);
hackSemaphore.acquire();
hackSemaphore.acquire();
opened = true;
hackSemaphore.release();
そして第二部:
public void update(LineEvent event) {
if (event.getType().equals(LineEvent.Type.OPEN)) {
hackSemaphore.release();
}
}