FreeTTS нет аудио Linux Ubuntu - без ошибок - PullRequest
9 голосов
/ 31 марта 2011

Я использую Ubuntu 10.10 с использованием Java 6 и не могу получить FreeTTS для вывода звука. Я попробовал его сейчас на 3 разных компьютерах и даже попросил моего друга попробовать его на своем компьютере с Ubuntu, и у него возникла та же проблема. Абсолютно нет ошибок, которые отображаются, после получения MBROLA я больше не получаю даже предупреждение о том, что голоса MBROLA не обнаружены. бла бла бла ..

Используя тот же компьютер, я запустил виртуальную коробку и запустил Windows XP. Я смог получить аудио при запуске HelloWorld.jar и TTSHelloWorld.jar, однако файл freetts.jar по-прежнему молчит, когда я пытаюсь ввести собственный текст. .

Используемая мной команда.

java -jar lib / freetts.jar -text Привет

Когда я нажимаю ввод, он запускается и используется, чтобы дать мне пропущенное предупреждающее сообщение MBROLA, но теперь он просто сидит там, пока я не нажму CTRL-C, чтобы остановить его.

Я не понимаю, что я делаю неправильно, и почему никто больше не сталкивается с этой проблемой, когда я использую ее на каждом компьютере, она работает в Windows. Кто-нибудь может мне помочь?

Спасибо

John

Ответы [ 3 ]

10 голосов
/ 17 июля 2012

Я студент, который пытался заставить FreeTTS работать с Ubuntu в течение одной недели.И, наконец, я нашел ответ здесь: большое спасибо hakvroot!

Ваш ответ был идеальным, но вы не поместили свою реализацию, и мне потребовался целый час, чтобы понять, что происходит в классе JavaStreamingAudioPlayer.Чтобы помочь другим людям, таким как я, которые не используются для «погружения» в совершенно неизвестном коде Java (я еще студент), я добавлю сюда свой код и надеюсь, что он поможет другим людям :).

Во-первых, более подробное объяснение: около строки 152 JavaStreamingAudioPlayer открывает строку.Однако эта операция может занять некоторое время, поэтому перед ее использованием она хочет проверить, открыта ли она.В текущей реализации используемое решение состоит в том, чтобы создать LineListener, прослушивающий эту строку, а затем перевести его в спящий режим (используя метод wait () потоков).

LineListener "разбудит" основной поток, используяa notifyAll () и будет делать это только тогда, когда он получит LineEvent типа «OPEN», который будет гарантировать, что линия была открыта.

Однако, как объясняется здесь hakvroot, проблема заключается в том, что уведомление никогда не отправляетсяиз-за специфического поведения DataLine, используемого Ubuntu.

Так что я удалил синхронизированные части кода, 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();
        }
    }
10 голосов
/ 07 июня 2011

Я не уверен, что вам уже удалось решить эту проблему, но я столкнулся с той же проблемой (Ubuntu 10.10 / JavaSE6).После некоторого исследования источника FreeTTS я нашел виновника, тупик, в com.sun.speech.freetts.audio.JavaStreamingAudioPlayer.Эта взаимоблокировка возникает, когда строка открывается и строка имеет тип org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine (которая, вероятно, используется по умолчанию в Ubuntu 10.10 с JavaSE6).Поскольку вы всегда хотите открыть Line для вывода звука, эта тупиковая ситуация всегда будет иметь место.

Причина этой тупиковой ситуации заключается в том, что в JavaStreamingAudioPlayer делается предположение о Line, а именно, что всеLineListeners будет уведомлен о LineEvent типа, открытого из того же потока, в котором был вызван Line.open (), или после того, как Line была открыта (и вызов Line.open () может вернуться).Это не относится к PulseAudioSourceDataLine;сначала он вызывает все LineListeners из события PulseAudio Thread, ожидает их возврата и затем возвращается из открытого вызова.С JavaStreamingAudioPlayer, заставляющим синхронизацию вокруг вызова Line.open () и обработки определенного LineListener, задача которого состоит в том, чтобы видеть, действительно ли Линия открыта, возникает тупик.

Обходной путь, который я выбрал для решения этой проблемыпроблема заключается в реализации 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");

где-то в начале кода.

Надеюсь, это все работает для вас.

1 голос
/ 03 июля 2012

Полагаю, у Ubuntu 12.04 / OpenJDK-6 возникла та же проблема: выполнение застряло в Voice.allocate () без ошибок и без ответа.Я попытался использовать Oracle / Sun JDK-6 вместо OpenJDK, и он работал нормально.

PS Хорошее руководство по установке SunJDK в Ubuntu и настройке по умолчанию http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/

...