【JavaFX】mp3、wavを手軽に再生

2018年6月10日

本稿はJavaFXでmp3、wavファイルを再生する方法を紹介します。

MediaPlayerと違ってSwingアプリケーション上でも動作しますので、appletのAudioClipの上位APIといえるでしょう。

import指定する場合はappletのAudioClipと間違えないようにしてください。

今回のサンプルプログラム用に新しく4小節だけ適当に作曲したので、その音声ファイルを使用します。

JavaFX AudioClipを使用して再生する際のメリット

JavaFX AudioClipを使用するメリットは以下のようなものがあります。

  • mp3が再生できる
  • 使用方法がとにかく簡単

mp3が再生できるメリットは大きいと思います。mp3は自由に使えるフォーマットになったので、ライセンス料を考える必要もなくなりました。・・・なくなったよね?

もう一つは使用方法がとにかく簡単です。これも非常に大きなメリットになりますね。SourceDataLineみたいな長ったらしいわけのわからんコードを記述せずに済みます。インスタンス化してplayメソッドを呼ぶだけ。

JavaFX AudioClipを使用して再生する際のデメリット

JavaFX AudioClipを使用するデメリットは以下のようなものがあると考えています。

  • Java8でmp3のループ再生でバグるかも
  • 一時停止メソッドが用意されていない
  • メモリに全展開する再生方式
  • 音量の変更が再生中にできない
  • 音声が綺麗にループ再生されずに、一旦途切れてしまう

JavaFXはJava8から標準APIで使用できるようになりましたが、mp3のループ再生にはバグがあるみたいなので、注意してください。

私の環境ではJava9であればしっかりループ再生されました。Java9以降を使用する場合はこの点はデメリットになりません。

尚、wavはjava8でもバグは発生しませんでした。

次に、一時停止メソッドが用意されていないということです。MediaPlayerには用意されているのになぜかこっちには用意されていません。まあ一時停止なんてそうそう使いたいことは、ないですからいいんですけどね。

次に、メモリに全展開して再生する方式だということです。Clipと同じで読み込むファイル容量の大きさによってメモリを圧迫します。つまり再生時間が長い場合は推奨されません。

次に音量の変更が再生中にできない点ですが、BGMを再生中にフェードアウトしたいことが、たまにあるのでこれもできないのはデメリットになります。初期のグラディウスなどではBGMが切り替わる前にフェードアウトしてから次のBGMへ移行しますが、そういうことがプログラム側から制御できません。

最後に音声が綺麗にループ再生されずに、一旦途切れてしまう件ですが、個人的にはかなり気に入らない点ですね。これがあるのでゲームのループ再生を使用する場合はSound APIを使用します。

これらの欠点が気に入らない方はClipSourceDataLineの使用をオススメします。

もしくはアプリ自体がJavaFXアプリケーションである場合は、MediaPlayerの使用をオススメします。こちらのクラスであれば一時停止や再生途中での音量変更、メモリ全展開のデメリットは解消されます。使用難易度もAudioClipとほとんど同じレベルです。

MediaPlayerの使用方法に関連する記事も作成しました。

playメソッドで再生

音声ファイルを再生します。

import java.io.File;
import java.net.MalformedURLException;

import javafx.scene.media.AudioClip;

public class Test {

	public static void main(String[] args) throws Exception {
		AudioClip c = new AudioClip(new File("sample2.mp3").toURI().toString());
		c.play();
		Thread.sleep(6000);
	}
}
実行結果

stopメソッドで停止

stopメソッドで再生中の音声を停止できます。

サンプルではわかりやすいようにplayとstopを使用しました。

import java.io.File;
import java.net.MalformedURLException;

import javafx.scene.media.AudioClip;

public class Test {

	public static void main(String[] args) throws Exception {
		AudioClip c = new AudioClip(new File("sample2.mp3").toURI().toString());
		c.play();
		Thread.sleep(3000);
		c.stop();
		Thread.sleep(1000);
		c.play();
		Thread.sleep(3000);
	}
}
実行結果

setCycleCountでループ再生

setCycleCountメソッドでループ回数を指定できます。

AudioClip.INDEFINITEを指定すると無限ループになります。

import java.io.File;
import java.net.MalformedURLException;

import javafx.scene.media.AudioClip;

public class Test {

	public static void main(String[] args) throws Exception {
		AudioClip c = new AudioClip(new File("sample2.mp3").toURI().toString());

		//無限ループ指定
		c.setCycleCount(AudioClip.INDEFINITE);
    	
		c.play();
		Thread.sleep(12000);
	}
}
実行結果

FXのAudioClipではループ時に一旦途切れてしまいますが、ClipやSourceDataLineを使用した場合は途切れずに綺麗にループできます。一応Clipで再生したバージョンも比較用に用意しました。

setVolumeで音量変更

setVolumeで音量の変更ができます。

有効な範囲は0.0 (ミュート)から1.0 (フル・ボリューム)です。

再生前に設定しなければ反映されません。

import java.io.File;
import java.net.MalformedURLException;

import javafx.scene.media.AudioClip;

public class Test {

	public static void main(String[] args) throws Exception {
		AudioClip c = new AudioClip(new File("sample2.mp3").toURI().toString());
		c.play();
		Thread.sleep(3000);
		c.stop();
		c.setVolume(0.3);
		c.play();
		Thread.sleep(3000);
	}
}
実行結果

setRateで再生速度の変更

再生速度の変更ができます。

速度に従ってピッチ(音の高さ)も変更される点に注意です。

有効な範囲は0.125 (1/8速)から8.0 (8倍速)です。

import java.io.File;
import java.net.MalformedURLException;

import javafx.scene.media.AudioClip;

public class Test {

	public static void main(String[] args) throws Exception {
		AudioClip c = new AudioClip(new File("sample2.mp3").toURI().toString());
		c.setRate(1.5);
		c.play();
		Thread.sleep(4500);
	}
}
実行結果

JavaJavaFX

Posted by nompor