2011-11-07 8 views
7

JavaFX SDK 2.0.1を使用して、JavaFX 2.0アプリケーションのループでバックグラウンドオーディオを再生しようとしています。私は以下のコードで作成されたのMediaPlayerを使用することにしました:JavaFX 2.0でクリーンなオーディオループとワンショットサウンドを並行して再生する方法は?

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

これは基本的に動作しますが、新しいサイクルが開始すると終了と音声の開始との間に小さな(潜伏?)に隙間があります。それはクリーンなループを演奏していないので、私のために働くオプションではありません。

私は新しいMediaPlayerオブジェクトを作成し、メディアが終了するたびに再生を開始することに決めました。これはこれまでのところうまく動作します。また、クリックすると短いAudioClipを再生するボタンを使用します。 このボタンを頻繁に素早くクリックすると、バックグラウンドオーディオの割り込みが発生することがわかりました。私は、ボタンが一度クリックされたときにボリューム0のAudioClipを無期限に再生することによってこの動作を再現するサンプルを作成しました。この例は、必須のオーディオファイルがないため、自己完結型ではありません。これは、プロジェクトのソースディレクトリにある2つのオーディオファイルを配置する必要があります。

  • click.wav(本当に短いクリック音〜300msの)
  • background.wav(オーディオの〜5秒)

他のワンショットオーディオが再生されたときに、これらの割り込みなしでバックグラウンドでクリーンなオーディオループを再生するにはどうすればよいですか?パフォーマンス上の問題ですか?

例:

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

バックグラウンドオーディオに「javax.sound.sampled.SourceDataLine」を使用する場合、問題はありません。 「javafx.scene.media.Media」でのオーディオ再生は異なるようです。 – pmoule

答えて

0

+1

ありがとうございますが、コードはすでにJavaFXアプリケーションスレッド上で実行されています。したがって、 'Platform.runlater(...)'を呼び出すときの動作は変わりません。私は、 'new Thread(new Runnable(...))。start();'を使って新しく作成したスレッドでイベントを実行しようとしました。問題はまだ存在しています。 – pmoule

1

はあなたがExecutorServiceに見ている中断の問題を解決することができる

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

で別のスレッドを使用していますか?次のように定義済みのスレッドがいくつかあります。

ExecutorService service = Executors.newFixedThreadPool(4); 

ここで、4はスレッドの数です。 これは、実行するたびに新しいスレッドを作成するのではなく、すでに作成されたスレッドを使用するため、パフォーマンスが向上します。

あなたはRunnableをを作成して、そのようなサービスとそれを実行します:

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

が、これはパフォーマンスを改善するだけでなく、それは自動的にそのスレッドプールで、現在ビジーでないスレッドにジョブを割り当てます。

また、私はあなたの小さな待ち時間の問題を解決すると信じてPlaying sound loops using javafxを見てください。

EDIT:すみません、申し訳ありませんが、私はこの投稿が古いことは分かりませんでした。それはgoogleで最高の結果でした。

関連する問題