JavaでBMSを音楽ファイルに変換してみた

ものすごくお久しぶりです。カサコンでございますw
気づいたら外も蒸し暑くなってすっかり夏って感じになってきましたね。
夏というとあれ。リトルバスターズのOPを流したい気分に駆られますw

あ。眼の方はほぼ完治したといってもいいくらいになりました。
相変わらず階段を登るときものすごく立体的に見えているので登る度に感動しておりますw
BMSでの収穫といえば久々に発狂初段(旧)を受けてみたらハード出来たくらいでしょうか。
放置効果は恐ろしい。

久しぶりの発狂初段

さて。前置きはこの辺にしておいて。
最近自分は新難易度表導入支援ツールというプロジェクトに参加してちょくちょく開発しています。
まぁそんな大層な事はやっていないんですけどもw
今回は開発していて出来たプログラムだったりノウハウを備忘録として残しておこうと思います。
という訳でつまらない記事になることをご了承くださいw
これからちょくちょく残せれば残していきたいと思います。
まずはBMSからBMX2WAVlameを使用してWAV、MP3を作成する機能を追加したのでそれをば。

Javaでexeの起動ってどうやるん?

はい。開発するとか言っておいてこのザマですw
いいもん。これから慣れていけばいいんだもん!

.exe他外部プロセスの起動にはProcessBuilderというのを使えばできるみたいなのでやってみる。
※参考:Java外部プロセス起動メモ

んでこんな感じになった。

protected String call() {
	Process pro = null;
	ProcessBuilder pb = null;
	// ツールパス
	String toolpath = "bmx2wavのパス(フォルダ)";
	// 曲名に以下の文字がある場合は置き換える
	title = title.replace("*", "")
			.replace("?", "").replace(":", "")
			.replace("<", "").replace(">", "")
			.replace("/", "").replace("|", "")
			.trim();
	//ツールの起動準備
	// -auto_start 自動起動
	// -auto_close 自動終了
	pb = new ProcessBuilder(toolpath
			+ "\\bmx2wav.exe",
			"-auto_start",
			"-auto_close"
			, path, toolpath + "\\" + title + ".wav"
	);
	// 標準エラー出力をマージして出力する
	pb.redirectErrorStream(true);
	try {
		pro = pb.start();
		InputStream is = pro.getInputStream();
		while (is.read() >= 0);
		is.close();

	} catch (IOException ex) {
		ex.printStackTrace();
	} finally {
		pro.destroy();
	}
	return "完了しました。";
}

ここで備忘録として残すこととしてはプロセスを起動する場合には標準エラー出力をしておかないと途中で処理が止まってしまうってことです。( ´_ゝ`)
コマンドラインについてはbmx2wavの作者様が丁寧に解説してくださっていたので非常に助かりました。
ありがとうございます。

MP3にも出来たらいいよね

これでWAVが作成されるようにはなったのですがWAVは容量が大きくて持ち運ぶには色々と大変!
電車に乗りながら気に入ったBMS聴きたいよねー。って事でlameを使ってMP3を作成することに挑戦。
あ。lameってのは『れいむ』って読みます。
決して『霊夢』でも『らめ○』でもないんでそこんとこ注意だぞっ(何

とりあえずWAVを作成する所までは同じなのでそこでWAVにするかMP3か分岐させればいいかーとか考えてみる。

protected String call() {
	Process pro = null;
	ProcessBuilder pb = null;
	// ツールパス
	String toolpath = "bmx2wavのパス(フォルダ)";
	// 曲名に以下の文字がある場合は置き換える
	title = title.replace("*", "")
			.replace("?", "").replace(":", "")
			.replace("<", "").replace(">", "")
			.replace("/", "").replace("|", "")
			.trim();
	//ツールの起動準備
	// -auto_start 自動起動
	// -auto_close 自動終了
	pb = new ProcessBuilder(toolpath
			+ "\\bmx2wav.exe",
			"-auto_start",
			"-auto_close"
			, path, toolpath + "\\" + title + ".wav"
	);
	// 標準エラー出力をマージして出力する
	pb.redirectErrorStream(true);
	try {
		pro = pb.start();
		InputStream is = pro.getInputStream();
		while (is.read() >= 0)
			;
		is.close();

		// MP3エンコード
		if (isMp3 == true) {
			String lamepath = "lameのパス(フォルダ)"
			pb = new ProcessBuilder(
					"\"cmd.exe\"", "\"/c\"",
					"\"" + lamepath + "\\lame.exe" + "\"",
					"\"-V2\"",
					"\"" + toolpath + "\\" + title + ".wav\"",
					"\"" + toolpath + "\\" + title + ".mp3\""
			);
			pb.redirectErrorStream(true);
			// 実行
			pro = pb.start();
			is = pro.getInputStream();
			while (is.read() >= 0);
			is.close();
			// 元のWAVを削除
			File file = new File(toolpath
					+ "\\" + title + ".wav");
			if (file.exists()) {
				file.delete();
			}
		}
	} catch (IOException ex) {
		ex.printStackTrace();
	} finally {
		pro.destroy();
	}
	return "完了しました。";
};

isMp3の値で処理を分岐するようにしてみました。
MP3にする際のlameの設定はとりあえず -V2 を設定しておきました。
そのうち変更出来るようにするかも?いや。分からないw
※参考:コマンドライン指南

んでMP3を作成後は基にしたWAVファイルを削除しておきます。

最終的な実装

最終的に出来たのはこんな感じ。
プロジェクトはJavaFXで組まれているので理解するのが難しかった。。。
ま。楽しいからいいんだけどねw

/**
 * BMX2WAVを起動し音楽ファイルを作成するメニューアイテム
 *
 * @author KASAKON
 */
class BMX2WAVMenuItem extends MenuItem {

	private String name;
	private String path;
	private String title;

	/**
	 * 指定のBMSをWAV又はMP3に変換
	 * @param name
	 * @param isMp3
	 */
	public BMX2WAVMenuItem(String name, final boolean isMp3) {
		this.name = name;
		this.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent arg0) {
				indicatorPane.addIndicatorPane(parent);
				indicatorPane.showIndicatorPane();

				Service<String> service = new Service<String>() {
					@Override
					protected Task<String> createTask() {
						Task<String> task = new Task<String>() {
							protected String call() {
								Process pro = null;
								ProcessBuilder pb = null;
								// ツールパス
								String toolpath = cm
										.get(ConfigurationMap.BMX2WAV_PATH)
										.toString().replace("/", "\\");
								// 曲名
								title = title.replace("*", "")
										.replace("?", "").replace(":", "")
										.replace("<", "").replace(">", "")
										.replace("/", "").replace("|", "")
										.trim();
								pb = new ProcessBuilder(toolpath
										+ "\\bmx2wav.exe",
										"-auto_start",
										"-auto_close"
										, path, toolpath + "\\" + title + ".wav"
								);
								// 標準エラー出力をマージして出力する
								pb.redirectErrorStream(true);
								try {
									pro = pb.start();
									InputStream is = pro.getInputStream();
									while (is.read() >= 0)
										;
									is.close();
									// MP3エンコード
									if (isMp3 == true) {
										String lamepath = cm
												.get(ConfigurationMap.LAME_PATH)
												.toString()
												.replace("/", "\\");
										pb = new ProcessBuilder(
												"\"cmd.exe\"", "\"/c\"",
												"\"" + lamepath + "\\lame.exe" + "\"",
												"\"-V2\"",
												"\"" + toolpath + "\\" + title + ".wav\"",
												"\"" + toolpath + "\\" + title + ".mp3\""
										);
										pb.redirectErrorStream(true);
										// 実行
										pro = pb.start();
										is = pro.getInputStream();
										while (is.read() >= 0)
											;
										is.close();
										// 元のWAVを削除
										File file = new File(toolpath
												+ "\\" + title + ".wav");
										if (file.exists()) {
											file.delete();
										}
									}
								} catch (IOException ex) {
									ex.printStackTrace();
								} finally {
									pro.destroy();
								}
								return "完了しました。";
							}
						};

						task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
							@Override
							public void handle(WorkerStateEvent event) {
								// タスク終了
								FXOptionPane.showMessageDialog(parent, getValue());
								indicatorPane.hideIndicatorPane();
								indicatorPane.removeIndicatorPane(parent);
							}
						});
						return task;
					}
				};
				service.start();
			}
		});
	}

	public void setPath(String path, String title, final boolean isMp3) {
		File bmx2wav = new File(cm.get(ConfigurationMap.BMX2WAV_PATH)
				.toString() + "/bmx2wav.exe");
		File lame = new File(cm.get(ConfigurationMap.LAME_PATH).toString()
				+ "/lame.exe");
		if (isMp3 == true) {
			if (bmx2wav.exists() == false) {
				this.setText("bmx2wav.exeを確認できないため" + title + "を" + name
						+ "できません");
				this.setDisable(true);
			} else if (lame.exists() == false) {
				this.setText("lame.exeを確認できないため" + title + "を" + name
						+ "できません");
				this.setDisable(true);
			} else if (path == null) {
				this.setText("楽曲がないため" + title + "を" + name + "できません");
				this.setDisable(true);
			} else {
				this.setText(title + "を" + name);
				this.setDisable(false);
				this.path = path;
				this.title = title;
			}
		} else {
			if (bmx2wav.exists() == false) {
				this.setText("bmx2wav.exeを確認できないため" + title + "を" + name
						+ "できません");
				this.setDisable(true);
			} else if (path == null) {
				this.setText("楽曲がないため" + title + "を" + name + "できません");
				this.setDisable(true);
			} else {
				this.setText(title + "を" + name);
				this.setDisable(false);
				this.path = path;
				this.title = title;
			}
		}
	}
}

こうやって見直すと汚いコードだなぁとしんみり。
ま。こうやって備忘録残しておけば忘れても安心だし成長も見れるだろうから気にしないことにしよう。うん。

んじゃまたねー。

[最終更新日]2015/11/01

Sponsored Link

ブログをチェックする?

ブログチェックにはRSS登録がオススメです!
更新をイチ速くお知らせします。ぜひぜひ!

関連記事

お探しの記事は見つかりましたか?
コチラが参考になるかもしれません。

関連記事が見つかりませんでした。

LR2最新ニュース

Powered by RSSリスティング

Comment