java audio text-to-speech javasound freetts

java - FreeTTS no audio Linux Ubuntu-sin errores



text-to-speech javasound (3)

No estoy seguro de si ya logró resolver este problema, pero me encontré con el mismo problema (Ubuntu 10.10 / JavaSE6). Después de investigar un poco sobre la fuente FreeTTS, encontré al culpable, un punto muerto, en com.sun.speech.freetts.audio.JavaStreamingAudioPlayer. Este punto muerto se produce cuando se abre una línea y la línea es del tipo org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine (que es probable que sea la predeterminada en Ubuntu 10.10 con JavaSE6). Como siempre querrá abrir una línea para obtener audio, este punto muerto siempre ocurrirá.

La causa de este punto muerto reside en el hecho de que en el JavaStreamingAudioPlayer se hace una suposición acerca de Line, es decir, que todos los LineListeners serán notificados de un LineEvent de tipo abierto desde el mismo Thread que Line.open (), o después de Line ha sido abierto (y la llamada a Line.open () puede regresar). Este no es el caso para PulseAudioSourceDataLine; primero llama a todos los LineListeners desde el evento PulseAudio Thread, espera a que todos ellos regresen y luego regresa de la llamada abierta. Con JavaStreamingAudioPlayer forzando la sincronización alrededor de la llamada de Line.open () y el manejo de un LineListener específico, cuya tarea es ver si la Línea actually realmente está abierta, se produce el punto muerto.

La solución alternativa que elegí para resolver este problema es implementar un AudioPlayer que no tiene este problema. Básicamente copié JavaStreamingAudioPlayer y alteré los bloques de sincronización en la línea 196 y la línea 646 (fuente completa para referencia: 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: ...

Quité ambos bloques de sincronización y, en lugar de asegurar que ambas partes se excluyan mutuamente, utilicé un semáforo para indicar que la línea, de hecho, está abierta. Por supuesto, esto no es realmente una necesidad, ya que PulseAudioSourceDataLine ya garantiza que se abrirá al regresar, pero es más probable que funcione bien cuando se prueba el mismo código en otra plataforma. No profundicé en el código el tiempo suficiente para decir lo que sucederá cuando abras / cierres / abres la línea por varios hilos al mismo tiempo. Si va a hacer esto, probablemente esté buscando una reescritura más grande de JavaStreamingAudioPlayer;).

Finalmente, después de haber creado su nuevo AudioPlayer, tendrá que indicar a FreeTTS que use su implementación en lugar del JavaStreamingAudioPlayer predeterminado. Esto se puede hacer mediante el uso de

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

en algún lugar al principio de tu código.

Espero que todo esto funcione para ti.

Estoy ejecutando Ubuntu 10.10 usando Java 6 y no puedo obtener FreeTTS para producir ningún audio. Lo intenté ahora en 3 computadoras diferentes e incluso le pedí a un amigo mío que lo probara en su PC Ubuntu y tuvo el mismo problema. Absolutamente no hay errores que se muestran, después de obtener el MBROLA ya no recibo la advertencia sobre las voces No MBROLA detectadas. bla, bla, bla..

Utilizando la misma computadora, ejecuté una caja virtual e inicié Windows XP. De hecho, pude obtener audio cuando ejecuté HelloWorld.jar y TTSHelloWorld.jar. Sin embargo, freetts.jar aún está en silencio cuando trato de ingresar mi propio texto.

Comando que uso

java -jar lib / freetts.jar -text Hello

Cuando presiono enter, arranca y se usa para darme el mensaje de advertencia de MBROLA que faltaba, pero ahora solo queda allí hasta que presione CTRL-C para detenerlo.

No entiendo lo que estoy haciendo mal y por qué nadie más tiene este problema, cuando lo explico en cada computadora, funciona un poco en Windows. ¿Alguien puede ayudarme?

Gracias,

John


Soy un estudiante que ha estado tratando de hacer FreeTTS trabajando en su Ubuntu por una semana. Y finalmente encontré la respuesta aquí: ¡muchas gracias, hakvroot!

Tu respuesta fue perfecta, pero no pusiste tu implementación y esto me llevó una hora entender qué estaba pasando en la clase JavaStreamingAudioPlayer. Para ayudar a otras personas como yo que no se utilizan para "bucear" en un código Java completamente desconocido (todavía soy un estudiante), voy a poner aquí mi código y espero que ayude a otras personas :).

Primero, una explicación más detallada: alrededor de la línea 152, JavaStreamingAudioPlayer abre una línea. Sin embargo, esta operación puede requerir algo de tiempo, por lo que antes de usarla, quiere verificar que esté abierta. En la implementación actual, la solución utilizada es crear un LineListener escuchando esta línea y luego dormir (usando el método wait () de los hilos).

El LineListener "activará" el hilo principal utilizando un notifyAll () y lo hará solo cuando reciba un LineEvent de tipo "OPEN" que garantizará que la línea se haya abierto.

Sin embargo, como explicaba hakvroot aquí, el problema es que la notificación nunca se envía debido al comportamiento específico de la línea de datos utilizada por Ubuntu.

Así que eliminé las partes sincronizadas, wait () y notifyAll () del código, pero como hakvroot, su JavaStreamingAudioPlayer podría intentar usar su línea antes de abrirla: debe esperar la confirmación con un nuevo mecanismo para detener el JavaStreamingAudioPlayer. y para despertarlo más tarde, cuando llegó la confirmación.

Así que utilicé el semáforo que havkroot utilizó (ver Javadoc para explicaciones en este sistema de bloqueo) iniciado con 1 pila:

  • cuando se abre la línea, adquiere una pila (por lo que 0 queda)

  • cuando quiere usar la línea intenta adquirir otra (por lo que se detiene)

  • cuando el oyente obtiene el evento que estamos buscando, libera el semáforo

  • esto libera al JavaStreamingAudioPlayer que puede ir para la siguiente parte

  • no te olvides de volver a soltar el semáforo para que tenga nuevamente 1 pila para abrir la siguiente línea

Y aquí está mi código:

Declarar una variable de semáforo:

private Semaphore hackSemaphore;

Iniciarlo en el constructor:

hackSemaphore = new Semaphore(1);

Luego, la primera parte para reemplazar (ver hakvroot para ver dónde ponerlo):

line = (SourceDataLine) AudioSystem.getLine(info); line.addLineListener(new JavaStreamLineListener()); line.open(format, AUDIO_BUFFER_SIZE); hackSemaphore.acquire(); hackSemaphore.acquire(); opened = true; hackSemaphore.release();

Y la segunda parte:

public void update(LineEvent event) { if (event.getType().equals(LineEvent.Type.OPEN)) { hackSemaphore.release(); } }


Supongo que tenía el mismo problema en Ubuntu 12.04 / OpenJDK-6, la ejecución se atascó en Voice.alocate () sin errores y sin respuesta. Intenté usar Oracle / Sun JDK-6 en lugar de OpenJDK, y funcionó bien.

Guía de PS Nice para instalar SunJDK en Ubuntu y configurarlo como predeterminado http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/