使用kevin或mbrola时使用Freetts的例外情况

我正在尝试使用freetts运行程序。 我能够编译程序但是我无法使用kevinmbrola语音我最后得到了以下输出消息

系统属性“mbrola.base”未定义。 不会使用MBROLA的声音。
LINE UNAVAILABLE:格式为pcm_signed 16000.0 Hz 16位1通道大端

import javax.speech.*; import javax.speech.synthesis.*; import java.util.*; class freetts { public static void main(String[] args) { try{ Calendar calendar = new GregorianCalendar(); String sayTime = "It is " + calendar.get(Calendar.HOUR) + " " + calendar.get(Calendar.MINUTE) + " " + (calendar.get(Calendar.AM_PM)==0 ? "AM":"PM"); Synthesizer synth = Central.createSynthesizer(null); synth.allocate(); synth.resume(); synth.speakPlainText(sayTime, null); synth.waitEngineState(Synthesizer.QUEUE_EMPTY); synth.deallocate(); } catch(Exception e){ e.printStackTrace(); } } } 

似乎“要为MBROLA启用FreeTTS支持,只需将mbrola / mbrola.jar复制到lib / mbrola.jar。然后,每当运行任何FreeTTS应用程序时,请将”mbrola.base“目录指定为系统属性:

  java -Dmbrola.base=/home/jim/mbrola -jar bin/FreeTTSHelloWorld.jar mbrola_us1" 

我发现这个:

http://freetts.sourceforge.net/mbrola/README.html

http://workorhobby.blogspot.com/2011/02/java-audio-freetts-line-unavailable.html

非常感谢作者。


基于FreeTTS的程序(Java的自由文本到语音引擎)偶尔会出现错误

 "LINE UNAVAILABLE: Format is ..." 

事实certificate,没有Javaexception或其他机制来检测FreeTTS库中发生的此错误。 所有你得到的是System.out上的消息,所以没有好的方法来以编程方式做出反应。

解决方法:配置FreeTTS音频播放器以尝试多次访问音频设备,直到成功为止。 在该示例中,使用0.1秒的短延迟来不错过抓取音频设备的机会; 我们继续尝试30秒:

 System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.openFailDelayMs", "100"); System.setProperty("com.sun.speech.freetts.audio.AudioPlayer.totalOpenFailDelayMs", "30000"); 

如果音频设备被其他程序永久使用,则当然无法访问。 在Linux下,此命令将显示当前持有音频设备的进程的ID,因此您可以尝试删除有问题的程序:

 /sbin/fuser /dev/dsp 

第二个短语与mbrola无关,但是有一个可怕的java linux声音bug仍然没有修复。 在这里查看第三篇文章: https : //forums.oracle.com/forums/thread.jspa?threadID = 2206163

这种情况正在发生,因为freetts“信任”sourcedataline,而不是在该post上进行解决方法。 该错误在jdk中,但可以通过查找正在发生的freetts中的位置并插入变通方法和重新编译来解决。

这是一个测试用例

 package util.speech; import java.util.Iterator; import java.util.Locale; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.DataLine; import javax.sound.sampled.LineUnavailableException; import javax.sound.sampled.Mixer; import javax.sound.sampled.SourceDataLine; import org.junit.After; import org.junit.AfterClass; import org.junit.Assume; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class VoiceTest { public VoiceTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testDataLineAvailableAndBuggyInJDK() throws LineUnavailableException { boolean failedSimpleGetLine = false; AudioFormat format = new AudioFormat(44100, 16, 2, true, false); SourceDataLine line = null; DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); try { line = (SourceDataLine) AudioSystem.getLine(info); } catch (LineUnavailableException e) { //ok, at least it says so throw e; } try { //if this fails the jdk is very buggy, since it just told us //the line was available line.open(format); } catch (LineUnavailableException e) { failedSimpleGetLine = true; } finally { if (line.isOpen()) { line.close(); } } //now if this is true, test if it's possible to get a valid sourcedataline //or the only bug is adquiring a sourcedataline doesn't throw a lineunavailable //exception before open Assume.assumeTrue(failedSimpleGetLine); line = getSourceDataLine(format); if (line == null) { return; } try { line.open(format); } catch (LineUnavailableException e) { //ok then it is consistent, and there is only one bug fail("Line Unavailable after being adquired"); } finally { if (line.isOpen()) { line.close(); } } fail("line available after first test not managing to adquire it"); } private SourceDataLine getSourceDataLine(AudioFormat format) { try { DataLine.Info info = new DataLine.Info(SourceDataLine.class, format); for (Mixer.Info mi : AudioSystem.getMixerInfo()) { SourceDataLine dataline = null; try { Mixer mixer = AudioSystem.getMixer(mi); dataline = (SourceDataLine) mixer.getLine(info); dataline.open(format); dataline.start(); return dataline; } catch (Exception e) { } if (dataline != null) { try { dataline.close(); } catch (Exception e) { } } } } catch (Exception e) { } return null; } } 

我知道我发帖很晚,但这可能对某人有所帮助。 我尝试了kevin和mbrola,它对我有用。 请在下面找到代码。

  package com.mani.texttospeech; import java.beans.PropertyVetoException; import java.util.Locale; import javax.speech.AudioException; import javax.speech.Central; import javax.speech.EngineException; import javax.speech.EngineStateError; import javax.speech.synthesis.Synthesizer; import javax.speech.synthesis.SynthesizerModeDesc; import javax.speech.synthesis.Voice; /** * * @author Manindar */ public class SpeechUtils { SynthesizerModeDesc desc; Synthesizer synthesizer; Voice voice; public void init(String voiceName) throws EngineException, AudioException, EngineStateError, PropertyVetoException { if (desc == null) { System.setProperty("freetts.voices", "com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory"); desc = new SynthesizerModeDesc(Locale.US); Central.registerEngineCentral("com.sun.speech.freetts.jsapi.FreeTTSEngineCentral"); synthesizer = Central.createSynthesizer(desc); synthesizer.allocate(); synthesizer.resume(); SynthesizerModeDesc smd = (SynthesizerModeDesc) synthesizer.getEngineModeDesc(); Voice[] voices = smd.getVoices(); for (Voice voice1 : voices) { if (voice1.getName().equals(voiceName)) { voice = voice1; break; } } synthesizer.getSynthesizerProperties().setVoice(voice); } } public void terminate() throws EngineException, EngineStateError { synthesizer.deallocate(); } public void doSpeak(String speakText) throws EngineException, AudioException, IllegalArgumentException, InterruptedException { synthesizer.speakPlainText(speakText, null); synthesizer.waitEngineState(Synthesizer.QUEUE_EMPTY); } public static void main(String[] args) throws Exception { SpeechUtils su = new SpeechUtils(); su.init("kevin16"); // su.init("kevin"); // su.init("mbrola_us1"); // su.init("mbrola_us2"); // su.init("mbrola_us3"); // high quality su.doSpeak("Hi this is Manindar. Welcome to audio world."); su.terminate(); } } 

并将以下依赖项添加到您的pom.xml文件中。

   net.sf.sociaal freetts 1.2.2   

希望这会有所帮助。