2011-11-07 20 views
7

Sto provando a riprodurre l'audio di sottofondo in un ciclo in un'applicazione JavaFX 2.0 utilizzando JavaFX SDK 2.0.1. Ho deciso di usare un MediaPlayer creato da seguente frammento di codice:Come riprodurre loop audio puliti e suoni one-shot in parallelo in JavaFX 2.0?

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

funziona questo fondo, ma quando un nuovo ciclo c'è una piccola (latenza?) Divario tra la fine e l'inizio dell'audio. Quindi non è un'opzione di lavoro per me dal momento che non sta giocando un ciclo pulito.

Ho deciso di creare un nuovo oggetto MediaPlayer e avviare la riproduzione ogni volta che termina. Questo funziona bene finora. Inoltre, quando clicco, utilizzo un pulsante che riproduce un breve AudioClip. Ho scoperto che fare clic su questo pulsante frequente e veloce porta a interruzioni nell'audio di sottofondo. Ho creato un esempio per riprodurre questo comportamento riproducendo in modo ineccepibile un AudioClip con il volume 0 quando si fa clic sul pulsante una volta. L'esempio non è autonomo, poiché mancano i file audio richiesti. Si richiede di inserire 2 file audio nella directory sorgente del progetto:

  • click.wav (davvero un breve suono di click ~ 300ms)
  • background.wav (~ 5 secondi di audio)

Come posso ottenere la riproduzione di un loop audio pulito in background senza questi interrupt quando vengono riprodotti altri suoni audio one-shot? È solo un problema di prestazioni?

Esempio:

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

Quando si utilizza 'javax.sound.sampled.SourceDataLine' per l'audio di sottofondo non ci sono problemi. La riproduzione audio con "javafx.scene.media.Media" sembra funzionare diversamente. – pmoule

risposta

0

Utilizzando un altro thread in

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

può risolvere il problema dell'interruzione

+1

Grazie, ma il codice viene già eseguito sul thread dell'applicazione JavaFX. Quindi, non c'è un comportamento diverso quando si chiama 'Platform.runlater (...)'. Ho provato ad eseguirlo in un thread appena creato con 'new Thread (new Runnable (...)). Start();'. Il problema è ancora presente. – pmoule

1

Hai guardato in ExecutorService? Avresti quindi un numero di thread predefiniti in questo modo:

ExecutorService service = Executors.newFixedThreadPool(4); 

dove 4 è il numero di thread che rende. Migliorerà le prestazioni perché utilizza thread già creati anziché crearne uno nuovo ogni volta che si desidera eseguire qualcosa.

Si creerebbe un Runnable ed eseguirlo con il servizio in questo modo:

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

Non solo questo migliorare le prestazioni, ma assegna automaticamente il lavoro a un thread non-attualmente occupato nel suo pool di thread.

Guarda anche questo: Playing sound loops using javafx che credo risolva il tuo piccolo problema di latenza.

MODIFICA: dannazione scusa, non sapevo che questo post fosse così vecchio. È stato un ottimo risultato su google.

Problemi correlati