2011-03-31 10 views
9

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 ...FreeTTS no audio Linux ubuntu - sin errores

Utilizando la misma computadora, ejecuté una caja virtual e inicié Windows XP, pude escuchar audio al ejecutar HelloWorld.jar y TTSHelloWorld.jar; sin embargo, freetts.jar todavía está en silencio cuando intento ingresar mi propio texto

Comando que uso.

java-jar lib/freetts.jar -text Hola

Cuando llegué a entrar en él se pone en marcha y me daba el mensaje de advertencia MBROLA falta pero ahora sólo se sienta allí hasta que yo Ctrl- C para detenerlo.

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

Gracias,

John

+0

I también se encontró con esto como se puede ver aquí: https://bugs.launchpad.net/communication/+bug/920734 –

Respuesta

10

no estoy seguro de si ya se logró resolver esto, 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 realiza una suposición sobre Línea, 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 que se haya abierto la línea (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: ... 

I extirpan ambos bloques de sincronización y en lugar de asegurar las dos partes están excluidos mutuamente utilicé un semáforo para indicar que la línea es de hecho 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;).

Por último, después de haber creado su nueva AudioPlayer que tendrá que instruir a FreeTTS utilizar su aplicación en lugar de la JavaStreamingAudioPlayer defecto. Esto se puede hacer usando

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

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

espero que esto funciona todo para usted.

+0

Cuando veo este tipo de respuesta, solo quiero morir. ¿Por qué, Dios, por qué? ¿Por qué no tengo este tipo de mente inteligente? Gracias por la genialidad :-) – Nabin

1

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

P.S. Buena guía para instalar SunJDK en Ubuntu y configurar como predeterminado http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/

10

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

Su respuesta fue perfecto, pero no puso su aplicación y esto me llevó bastante una hora para entender lo que 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 :).

En primer lugar, una explicación más detallada: alrededor de la línea 152, la 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 notifyAll() y lo hará solo cuando reciba un LineEvent de tipo "OPEN" que garantizará que la línea se haya abierto.

Sin embargo, como se explica por hakvroot aquí el problema es que la notificación no se envía nunca debido al comportamiento específico del DataLine utilizado por Ubuntu.

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

por lo que utiliza el semáforo, que havkroot utilizado (ver Javadoc para obtener explicaciones sobre este sistema de bloqueo) iniciados con 1 pila:

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

  • cuando se quiere utilizar la línea que trata de adquirir otra (por lo que se detuvo)

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

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

  • no se olvide de liberar de nuevo el semáforo por lo que tiene de nuevo 1 pila para la siguiente línea para abrir

Y aquí está mi código:

declara una variable del semáforo:

private Semaphore hackSemaphore; 

Iniciado en el constructor:

hackSemaphore = new Semaphore(1); 

A continuación, la primera parte para cambiar (consulte el 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(); 
     } 
    } 
+2

Muchas gracias por una explicación tan clara. He rodado su arreglo en mi copia de FreeTTS. Usted puede ver/usar el parche aquí: https://github.com/timabell/FreeTTS/commit/254086f22f0f53d6456a494826e72b7abab4d8bf - el estudiante ahora es el profesor :-) He probado el archivo jar helloworld y con este parche y freeTTS ya no se cuelga bajo openJdk. –

+2

@Tim Buen trabajo. He informado el error a Ubuntu [aquí] (https://bugs.launchpad.net/ubuntu/+source/freetts/+bug/1191512). Por favor, vote sobre ello. – HRJ

+0

¡Hecho! (si entiendo launchpad, de lo que no estoy convencido a veces). Gracias @HRJ –

Cuestiones relacionadas