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

发布于 2024-08-26 17:22:40 字数 982 浏览 9 评论 0原文

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

系统属性“mbrola.base”未定义。不会使用 MBROLA 声音。
行不可用:格式为 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();
        }
    }
}

I am trying to run a program using freetts. I am able to compile the program however I am not able to use kevin or mbrola voices I get the follwing output message at the end

System property "mbrola.base" is undefined. Will not use MBROLA voices.
LINE UNAVAILABLE: Format is pcm_signed 16000.0 Hz 16 bits 1 channel big endian

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();
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

泛泛之交 2024-09-02 17:22:40

似乎“要启用对 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

It seems that "To enable FreeTTS support for MBROLA, merely copy mbrola/mbrola.jar to lib/mbrola.jar. Then, whenever you run any FreeTTS application, specify the "mbrola.base" directory as a system property:

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

I found this at:

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

眼泪都笑了 2024-09-02 17:22:40

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

非常感谢作者。


基于 FreeTTS(Java 的免费文本转语音引擎)的程序偶尔会出现错误

"LINE UNAVAILABLE: Format is ..."

事实证明,没有 Java 异常或其他机制来检测 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

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

A big thanks to the author.


A program based on FreeTTS, the free text-to-speech engine for Java, was getting occasional errors

"LINE UNAVAILABLE: Format is ..."

Turns out there is no Java Exception or other mechanism to detect this error that occurs inside the FreeTTS library. All you get is the message on System.out, so there is no good way to react programatically.

Workaround: Configure the FreeTTS audio player to attempt accessing the audio device more than once until it succeeds. In this example, a short delay of 0.1 seconds is used to not miss an opportunity to grab the audio device; we keep trying for 30 seconds:

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

If the audio device is permanently used by another program, there is of course no way to get access. Under Linux, this command will display the ID of the process that is currently holding the audio device, so you can then try to get rid of the offending program:

/sbin/fuser /dev/dsp
用心笑 2024-09-02 17:22:40

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

发生这种情况是因为 freetts“信任”sourcedataline,而不是在该帖子上执行解决方法。该错误存在于 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;
    }
}

The second phrase has nothing to do with mbrola, but with a horrendous java linux sound bug that is still not fixed.
Check the third post here:
https://forums.oracle.com/forums/thread.jspa?threadID=2206163

That is happening because freetts "trusts" the sourcedataline, instead of doing the workaround on that post. The bug is in the jdk, but can be worked around by finding where in freetts that is happening and inserting the workaround & recompiling.

Here is a testcase

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;
    }
}
梦罢 2024-09-02 17:22:40

我知道我发布的有点晚了,但这可能会对某人有所帮助。我尝试了凯文和姆布罗拉,这对我有用。请找到下面的代码。

    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 文件中。

<dependencies>
        <dependency>
            <groupId>net.sf.sociaal</groupId>
            <artifactId>freetts</artifactId>
            <version>1.2.2</version>
        </dependency>
    </dependencies>

希望这会有所帮助。

I know i am posting it little late, but this may help someone. I tried with both kevin and mbrola, and it worked for me. Please find the code below.

    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();
    }
}

And add the below dependencies to your pom.xml file.

<dependencies>
        <dependency>
            <groupId>net.sf.sociaal</groupId>
            <artifactId>freetts</artifactId>
            <version>1.2.2</version>
        </dependency>
    </dependencies>

Hope this will be helpful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文