質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.34%

JavaFXでのMP3ファイル再生時のラグが大きいです.

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,413
退会済みユーザー

退会済みユーザー

はじめに

JavaFXを用いてアプリケーションを作っています.
その中で,クリック時などに効果音を付けたいと思っています.
再生することはできたのですが,そのラグが大きかったので質問します.

実現したいこと

ラグを人間が気にならない程度に抑えて,実行できるようにすること.

下記のコードだとクリックしてから再生されるまでの時間が大きすぎます.
理想は,クリックと同時になっていると人間が思えることです.

ソースコード

効果音を再生するクラス.

import java.nio.file.Path;

import javafx.scene.media.AudioClip;

public class MySoundPlayer implements Runnable{
  private AudioClip clip;

  public MySoundPlayer(Path path){
    this.clip = new AudioClip(path.toUri().toString());
  }

  @Override
  public void run(){
    try{
      this.clip.play();
      while(clip.isPlaying()) ;
    }catch(Exception e){
      e.printStackTrace();
    }
  }
}

上記のクラスのテスター.

import java.nio.file.Paths;
import javafx.scene.media.AudioClip;

public class SoundTester extends javafx.application.Application{
  public static void main(String[] args) throws Exception{
    launch(args);
  }

  @Override
  public void start(javafx.stage.Stage stage){
    javafx.scene.control.Button btnPlay = new javafx.scene.control.Button("再生");
    btnPlay.setPrefSize(100,30);
    btnPlay.setOnAction(event -> {
      try{
            //カレントディレクトリに"click.mp3"が存在すると仮定します.         
        MySoundPlayer mp3player = new MySoundPlayer(Paths.get("click.mp3"));
        Thread thread = new Thread(mp3player);
        thread.start();    
      }catch(Exception e){
        e.printStackTrace();
      }
    });

    javafx.scene.layout.VBox vbox = new javafx.scene.layout.VBox(btnPlay);
    vbox.setAlignment(javafx.geometry.Pos.CENTER);

    stage.setHeight(100);
    stage.setWidth(275);
    stage.setTitle("クリック音テスト");
    stage.setScene(new javafx.scene.Scene(vbox));
    stage.show();
  }
}

質問

  1. 現在のラグの原因はなんでしょうか?
  2. ラグを人間が気にならないようなレベルにするにはどうすればいいでしょうか.

具体的なソースコードをつけて解答いただけると幸いです.

補足など

2016/10/18 22:10 質問内容を追加しました.

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

長時間再生するような巨大なサウンドクリップなら再生開始時にスレッド開始、クリップ読み込み(と並行して再生開始)というふうにすると思いますが、即座に再生したいような短いサウンドクリップならあらかじめメモリーに読み込み即座に再生を開始するべきだと思います。

スレッドを起動する時間も気になるほど大きいなら常時専用スレッドを起動しておく方がよいかも知れません。スレッドプールサポート用クラスもあるのですが、もし大がかりなマルチスレッドのアプリケーションを作るのではなくとりあえずサウンドクリップを鳴らすだけといったものであれば自前で一つスレッドを起こして処理したほうがかえって簡単な気がします。

追記:

UIスレッドから別スレッドをたたき起こすというのが最初難しいと思うのでその例をかいてみます。必ずしもよいコードではないのでもっとスッキリした書き方もあるようにも思いますが。コメントつける代わりに変数やメソッド名に日本語つかってます。
クリップを一度だけロードして繰り返し鳴らすのはClipのリファレンスをみてトライしてみてください。

class Boo {
  Object lock = new Object();
  boolean 鳴らすのは今;

  public static void main(...) {
    Thread t = new Thread(() -> クリップスレッドの処理());
    t.setDaemon(true);
    t.start();
    ... 画面をつくって表示
  }

  // 鳴らしたいときJavaFXアプリケーションスレッドからこれを直接呼び出せます
  static void クリップスレッドさん再生してください() {
    synchronized (lock) {
      鳴らすのは今 = true;
      lock.notify();
    }
  }

  void クリップスレッドの処理() {
    try {
      for (;;) { // アプリケーション終了まで無限ループ
        synchornized (lock) {
          lock.wait();
        }
        System.out.println("デバッグ用: スレッドが起きました");
        if (鳴らすのは今) {
          鳴らすのは今 = false;
          ...音を鳴らす処理
        }
      }
    } catch (InterruptedException e) {
      ;
    }
  }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/10/18 22:16

    >あらかじめメモリーに読み込み即座に再生を開始するべきだと思います
    とのことですが,初心者故に具体的にどのようなコードを書くべきなのかわかりません.
    サンプルコードを教えていただけないでしょうか.

    キャンセル

  • 2016/10/19 00:26

    ところどろこ3点リーダー(...)で省略してますがスレッドのコード例を挙げてみました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る