2011-11-07 19 views
7

JavaFX SDK 2.0.1 kullanarak bir JavaFX 2.0 uygulamasında bir döngüde arkaplan sesini çalmaya çalışıyorum. Ben aşağıdaki kod parçası tarafından oluşturulan bir MediaPlayer kullanmaya karar:JavaFX 2.0'da temiz ses döngüleri ve tek atımlı sesler nasıl paralel olarak oynatılır?

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

Bu temelde çalışır, ancak yeni bir döngü küçücük (gecikme?) Bulunmaktadır sonu ve ses başlangıcı arasındaki boşluk başladığında. Bu benim için temiz bir döngü oynamadığından çalışmayan bir seçenek değil.

Yeni bir MediaPlayer nesnesi oluşturmaya karar verdim ve Media bittiğinde her zaman oynatmaya başladım. Bu çok iyi çalışıyor. Ayrıca, tıklandığında kısa bir AudioClip çalan bir düğme kullanıyorum. Bu düğmenin sık ve hızlı tıklatılmasının arka plan sesinde kesintilere yol açtığını keşfettim. Düğmeye bir kez tıklandığında, 0 düzeyiyle bir AudioClip oynatılarak bu davranışı yeniden oluşturmak için bir örnek oluşturdum. Gerekli ses dosyaları eksik olduğundan örnek kendi kendine yetmez. (~ Gerçekten kısa tık sesi 300 ms)

  • click.wav
  • background.wav (ses ~ 5 saniye)

: Bu projenin kaynak dizininde 2 ses dosyalarını yerleştirmek gerektirir Diğer tek çekim sesler çalınırken arka planda temiz bir ses döngüsü oynatmayı nasıl gerçekleştiririm? Bu sadece bir performans sorunu mu?

Örnek:

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

Arka plan ses için 'javax.sound.sampled.SourceDataLine' kullanırken sorun yoktur. 'Javafx.scene.media.Media' ile ses çalma farklı çalışıyor gibi görünüyor. – pmoule

cevap

0

+1

Teşekkürler, ancak kod zaten JavaFX uygulama iş parçacığı üzerinde yürüyor. Yani, Platform.runlater (...) 'ı çağırırken farklı bir davranış yoktur. Yeni olay (yeni Runnable (...)) ile yeni oluşturulmuş bir iş parçasında çalıştırmayı denedim: start(); '. Sorun hala mevcut. – pmoule

1

Eğer ExecutorService içine baktım kesinti sorununu çözmek Mayıs

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

başka iş parçacığı kullanarak? Ardından şöyle önceden tanımlanmış iş parçacığı bir dizi olurdu: 4 yapar parçacığı sayısıdır

ExecutorService service = Executors.newFixedThreadPool(4); 

. Performansı artıracak çünkü bir şeyi çalıştırmak istediğiniz her seferde yeni bir tane oluşturmak yerine zaten oluşturulmuş konuları kullanıyor.

Bir Runnable oluşturmak ve böylece gibi hizmetiyle çalıştırmak olacaktır:

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

Sadece bu performansı artıracak ancak otomatik olarak kendi iş parçacığı havuzunda değil-henüz-yoğun iş parçacığı işi atar.

Ayrıca, küçük gecikme sorununuzu çözdüğüne inandığım Playing sound loops using javafx.

DÜZENLEMEK: kahrolası üzgünüm, bu yazının eski olduğunu bilmiyordum. Google'da en iyi sonuç oldu.

İlgili konular