2011-11-07 7 views
7

Estoy tratando de reproducir audio de fondo en un bucle en una aplicación JavaFX 2.0 usando JavaFX SDK 2.0.1. Decidí usar un MediaPlayer creado por el siguiente fragmento de código:¿Cómo se reproducen los loops de audio limpios y los sonidos de una sola ejecución en paralelo en JavaFX 2.0?

MediaPlayerBuilder 
.create().media(BACKGROUND_MEDIA) 
.cycleCount(MediaPlayer.INDEFINITE); 

funciona esto, básicamente, pero cuando un nuevo ciclo comienza hay una pequeña (latencia?) Entre el final y el inicio de la de audio. Por lo tanto, no es una opción que funcione porque no está jugando limpio.

Decidí crear un nuevo objeto MediaPlayer e iniciar la reproducción cada vez que Media termina. Esto funciona bien hasta ahora. Además, uso un botón que reproduce un corto AudioClip cuando hago clic. Descubrí que presionar con frecuencia y rápidamente este botón provoca interrupciones en el audio de fondo. Creé un ejemplo para reproducir este comportamiento al reproducir un AudioClip con volumen 0 cuando se hace clic en el botón una vez. El ejemplo no es autónomo, ya que faltan los archivos de audio requeridos. Se requiere colocar 2 archivos de audio en el directorio principal del proyecto:

  • click.wav (un muy corto sonido de clic ~ 300ms)
  • background.wav (~ 5 segundos de audio)

¿Cómo logro reproducir un loop de audio limpio en el fondo sin estas interrupciones cuando se reproducen otros sonidos de audio one-shot? ¿Es solo un problema de rendimiento?

Ejemplo:

package mediatest; 

import javafx.application.Application; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.media.AudioClip; 
import javafx.scene.media.Media; 
import javafx.scene.media.MediaPlayer; 
import javafx.scene.media.MediaPlayerBuilder; 
import javafx.stage.Stage; 

public class MediaTest extends Application { 

    private static final AudioClip CLICK_AUDIOCLIP = new AudioClip(MediaTest.class.getResource("/click.wav").toString()); 
    private static final Media BACKGROUND_MEDIA = new Media(MediaTest.class.getResource("/background.wav").toString()); 

    private MediaPlayerBuilder builder; 

    public static void main(String[] args) { 
     Application.launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     Group root = new Group(); 
     Scene scene = new Scene(root, 300, 250); 

     this.builder = MediaPlayerBuilder 
         .create() 
         .media(BACKGROUND_MEDIA) 
         .onEndOfMedia(new Runnable() { 

          public void run() { 
           MediaPlayer player = MediaTest.this.builder.build(); 
           player.play(); 
          } 
         }); 

     MediaPlayer player = this.builder.build(); 
     player.play(); 

     Button btn = new Button(); 
     btn.setText("Repeat playing short audio clip"); 
     btn.setOnAction(new EventHandler<ActionEvent>() { 

      public void handle(ActionEvent event) { 
       //Simulation of many button clicks 
       MediaTest.CLICK_AUDIOCLIP.setCycleCount(AudioClip.INDEFINITE); 
       MediaTest.CLICK_AUDIOCLIP.play(0); 
      } 
     }); 

     root.getChildren().add(btn); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 
} 
+1

Al usar 'javax.sound.sampled.SourceDataLine' para audio de fondo no hay ningún problema. La reproducción de audio con 'javafx.scene.media.Media' parece funcionar de manera diferente. – pmoule

Respuesta

0

El uso de otro hilo en

public void handle(ActionEvent event) { 
      Platform.runLater(new Runnable() 
      { 
       @Override 
       public void run() 
       { 
        //Simulation of many button clicks 
        MediaTest.CLICK_AUDIOCLIP.setCycleCount(AudioClip.INDEFINITE); 
        MediaTest.CLICK_AUDIOCLIP.play(0); 
       } 
      }); 
     } 
    }); 

puede resolver el problema de la interrupción

+1

Gracias, pero el código ya se ejecuta en el hilo de la aplicación JavaFX. Por lo tanto, no hay un comportamiento diferente al llamar a 'Platform.runlater (...)'. He intentado ejecutarlo en un hilo recién creado con 'nuevo Thread (new Runnable (...)). Start();'. El problema aún está presente. – pmoule

1

has mirado en ExecutorService? A continuación, tendría un número de hilos predefinidos, así:

ExecutorService service = Executors.newFixedThreadPool(4); 

donde 4 es el número de hilos que hace. Mejorará el rendimiento porque usa subprocesos ya creados en lugar de crear uno nuevo cada vez que desee ejecutar algo.

Para ello se crea un Ejecutable y ejecutarlo con el servicio de este modo:

Runnable r = new Runnable() { 
    @Override 
    public void run() { 
     playSound(); 
    } 
}; 
service.execute(r); 

Esto no sólo mejorar el rendimiento, sino que asigna automáticamente el trabajo a un hilo no-actualmente ocupado en su grupo de subprocesos.

También vea esto: Playing sound loops using javafx que creo que resuelve su pequeño problema de latencia.

EDIT: perdón, no sabía que esta publicación era tan antigua. Fue un resultado superior en google.

Cuestiones relacionadas