2011-03-31 60 views
9

我使用Java 6運行Ubuntu 10.10,無法獲得FreeTTS輸出任何音頻。我現在已經在3臺不同的電腦上試過了,甚至還要求我的一個好友在他的Ubuntu PC上試用它,他也遇到了同樣的問題。在獲得MBROLA後,我絕對不會再收到有關未檢測到MBROLA聲音的警告,因此絕對不會顯示任何錯誤。等等。FreeTTS沒有音頻Linux的Ubuntu的 - 沒有錯誤

使用同一臺計算機我運行了一個虛擬的盒子並啓動了Windows XP,當運行HelloWorld.jar和TTSHelloWorld.jar時,我實際上能夠獲得音頻,但是freetts.jar仍然保持沉默。嘗試輸入我自己的文字。

我使用的命令。

Java的罐子的lib/freetts.jar -text你好

當我擊進入它啓動,並經常給我失蹤MBROLA警告消息,但現在它只是坐在那裏,直到我CTRL- C來阻止它。

我不明白我在做什麼錯,爲什麼沒有人有這個問題,當我在每臺計算機上展示它時,它在Windows上的工作方式都有所不同。誰能幫我?

感謝,

約翰

+0

我你也可以在這裏看到:https://bugs.launchpad.net/communication/+bug/920734 – 2013-01-08 22:34:16

回答

10

我不知道您是否已經成功地解決了這一個,但我遇到了同樣的問題(Ubuntu的10.10/JavaSE6)。在對FreeTTS源碼進行了一些調查後,我在com.sun.speech.freetts.audio.JavaStreamingAudioPlayer中發現了一個死鎖的罪魁禍首。當打開Line並且Line的類型爲org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine(這可能是Ubuntu 10.10和JavaSE6中的默認值)時,會發生此死鎖。既然你總是想打開一條線來獲取音頻,這個死鎖總是會發生。

這個死鎖的原因在於,在JavaStreamingAudioPlayer中對Line進行了一個假設,即所有的LineListeners都會被調用Line.open()時從同一個Thread中得到一個類型爲LineEvent的通知,或Line已打開後(以及對Line.open()的調用可返回)。 PulseAudioSourceDataLine不是這種情況;它首先調用PulseAudio事件Thread中的所有LineListeners,等待它們全部返回,然後從打開的調用中返回。使用JavaStreamingAudioPlayer在Line.open()的調用周圍強制同步並處理特定的LineListener,該任務是查看Line是否實際打開時發生死鎖。

我選擇解決此問題的解決方法是實現一個沒有此問題的AudioPlayer。我基本上覆制了JavaStreamingAudioPlayer並更改了196行和646行的同步塊(完整源代碼參考:http://www.javadocexamples.com/java_source/com/sun/speech/freetts/audio/JavaStreamingAudioPlayer.java.html)。

___: // This is the actual JavaStreamAudioPlayer source, not the fix 
195: ... 
196:  synchronized (openLock) { 
197:   line.open(format, AUDIO_BUFFER_SIZE); // Blocks due to line 646 
198:   try { 
199:    openLock.wait(); 
200:   } catch (InterruptedException ie) { 
201:    ie.printStackTrace(); 
202:  } 
203: ... 

643: ... 
644: public void update(LineEvent event) { 
645:  if (event.getType().equals(LineEvent.Type.OPEN)) { 
646:   synchronized (openLock) { // Blocks due to line 196 
647:    openLock.notifyAll(); 
648:   } 
649:  } 
650: } 
651: ... 

我除去兩個同步塊和代替確保兩個部分相互排除我使用的信號量的信號,該線實際上是開放的。當然,這並不是必須的,因爲PulseAudioSourceDataLine已經保證在返回時打開,但當在另一個平臺上測試相同的代碼時,它更可能發揮出色。我沒有深入研究代碼,只是說當你同時打開/關閉/打開多個線程時會發生什麼。如果你打算這樣做,你可能會考慮對JavaStreamingAudioPlayer進行更大的重寫;)。

最後,在創建新的AudioPlayer後,您必須指示FreeTTS使用您的實現,而不是默認的JavaStreamingAudioPlayer。這可以通過使用

System.setProperty("com.sun.speech.freetts.voice.defaultAudioPlayer", "classpath.to.your.AudioPlayer"); 

在代碼的早期某處。

希望這一切都適合你。

+0

當我看到這些答案時,我只想死。上帝啊,這到底是爲什麼?爲什麼我沒有這種聰明的頭腦?謝謝你的真棒:-) – Nabin 2015-10-18 15:53:22

1

我猜在Ubuntu 12.04/OpenJDK-6上有同樣的問題,執行卡在Voice.allocate()中,沒有錯誤,也沒有響應。 我嘗試使用Oracle/Sun JDK-6而不是OpenJDK,並且它工作正常。

P.S.在Ubuntu上安裝SunJDK和配置爲默認的好的指南 http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/

10

我是一名一直試圖讓FreeTTS在其Ubuntu上工作一週的學生。最後我在這裏找到了答案:非常感謝你hakvroot!

你的答案很完美,但你沒有把你的實現,這花了我一個多小時瞭解JavaStreamingAudioPlayer類中發生了什麼。爲了幫助像我這樣的人,他們不用在一個完全未知的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(); 
     } 
    } 
+2

非常感謝你這麼明確的解釋。我已將您的修補程序轉入我的FreeTTS副本。你可以在這裏看到/使用補丁:https://github.com/timabell/FreeTTS/commit/254086f22f0f53d6456a494826e72b7abab4d8bf - 學生現在是老師:-)我已經測試了helloworld jar文件,並且使用這個補丁和freeTTS不再掛在openJdk下。 – 2013-01-09 01:36:05

+2

@Tim很好的工作。我已經向Ubuntu報告了這個bug [這裏](https://bugs.launchpad.net/ubuntu/+source/freetts/+bug/1191512)。請投下您的投票。 – HRJ 2013-06-16 12:50:02

+0

完成! (如果我理解啓動板,有時我不相信)。謝謝@HRJ – 2013-06-17 22:18:43