Un4seen BASS Audio Library でサウンド再生してみよう


おはようございます、一昨日は大雪でしたね。私の近所でも雪がどっさり降って大騒ぎしておりました。でも、雪を掻くスコップ、雪道を歩くゴム長すら家にはないわけで、登山靴を引っ張り出して歩き回ったりしておりました。雪はすぐに止んで雨になったのですが、その後も寒波というやつです。今度は凍結してつるっつる。というわけで、今回もつーるつるのオーディオツールの話を始めましょう。

さて、ずっと NAudio というライブラリをいじくってきたのですが、ずっと気になっているライブラリがもう一つありまして、やはりそちらも少し試してみたいという気持ちになったのです。雪も降ったことですしね。ええ、あんまり意味はないですけど。

BASS audio library とは?

BASS audio libraryは、 Un4seen というプロジェクトのライブラリです。BASS とついてますが、楽器のベースとは関係ないみたい。XMPlay などのオーディオ再生ツールもこのライブラリを元に出してます。NAudioは Microsoft Public License (Ms-PL) というライセンスを採用してまして、こいつは相当に緩い自由な奴です。で、BASS のほうは、非商用は無料、シェアウエアや商用は有料というライセンス形態です。先に結論的にいうと、NAudio は緩いだけのことはあってベータ感たっぷり、それに比べると BASS のほうがすこしカチッとした印象を受けます。それに、同じライブラリで MacOS、Linux、WindowsCE、Android、iOSなんかも共通でサポートしてますし。

そんなわけで、C#/.NET でも使えるらしいので、本体である bass24.zip と C#/.NET のラッパーである base24.Net.zip をダウンロードして使います。

さっそくコードを書いてみる

まず、デバイスの初期化です。Bass.BASS_GetDeviceInfos() 関数で出力デバイスの配列が得られますので、それをコンボボックスに突っ込みます。あとで番号が必要ですが、まあうまい具合に一致するのでよしとします。

foreach(var bdi in Bass.BASS_GetDeviceInfos())
{
	string dname="";
	if (bdi.IsDefault) dname = "*";
	dname += bdi.name;
	comboBoxDevice.Items.Add(dname);
}

再生ボタンを押したときの動作がこれ。Bass.BASS_SetDevice で出力デバイスを選んで、Bass.BASS_Init で初期化。Bass.BASS_StreamCreateFile でサウンドファイルからストリームというかチャンネルを生成してしまえば、あとは再生するだけです。チャンネルという概念でコントロールされます。ボリュームもただfloat値(0~1f)をセットするだけです。

bass_play1

private void buttonPlay_Click(object sender, EventArgs e)
{
	string file = textBoxSoundFile.Text;
	Bass.BASS_SetDevice(comboBoxDevice.SelectedIndex);
	Bass.BASS_Init(comboBoxDevice.SelectedIndex, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
	stream = Bass.BASS_StreamCreateFile(file, 0L, 0L, BASSFlag.BASS_DEFAULT);
	if (stream != 0)
	{
		Bass.BASS_SetVolume((float)trackBarVol.Value / trackBarVol.Maximum);
		Bass.BASS_ChannelPlay(stream, false);
	}
}

レベルメーターを表示するためのコールバック関数などはなさそうですので、タイマーで見にいきましょう。再生時間などもまとめて処理します。

private void timer1_Tick(object sender, EventArgs e)
{
	if (stream != 0 && Bass.BASS_ChannelIsActive(stream)==BASSActive.BASS_ACTIVE_PLAYING)
	{
		// レベルメーター
		float[] level = new float[2];
		Bass.BASS_ChannelGetLevel(stream, level);
		pictureBoxMeterDraw(pictureBoxL, level[0]);
		pictureBoxMeterDraw(pictureBoxR, level[1]);
		// 再生位置
		long pos=Bass.BASS_ChannelGetPosition(stream,BASSMode.BASS_POS_BYTES);
		progressBarStream.Value = (int)(pos * progressBarStream.Maximum / Bass.BASS_ChannelGetLength(stream));
		// 再生時刻
		double time = Bass.BASS_ChannelBytes2Seconds(stream, pos);
		labelProgress.Text = Math.Floor(time).ToString() + " sec";
		// 再生状態
		switch(Bass.BASS_ChannelIsActive(stream))
		{
			case BASSActive.BASS_ACTIVE_PLAYING:
				labelPlayStatus.Text = "Playing";
				break;
			case BASSActive.BASS_ACTIVE_STOPPED:
				labelPlayStatus.Text = "Stop";
				break;
			case BASSActive.BASS_ACTIVE_PAUSED:
				labelPlayStatus.Text = "Pause";
				break;
		}
	}
	else
	{
		pictureBoxMeterDraw(pictureBoxL, 0f);
		pictureBoxMeterDraw(pictureBoxR, 0f);
		labelProgress.Text="";
		progressBarStream.Value=progressBarStream.Minimum;
		labelPlayStatus.Text = "Stop";
	}
}

pictureBoxMeterDraw は毎回使いまわしている PictureBox をレベルメーター代わりにして描画する関数です。曲が終わった時の再生停止イベントなども探しても見つかりません。もしかするとどこかにあるのかもしれませんね。

NAudio と比べた BASS の印象

コールバックがないことなどもあり、NAudio に比べて煩わしさを全く感じません。ドキュメントなどを見ると、リバーブなどのエフェクトをかけたりするプラグインを追加すれば、わりと簡単に使えそうな印象です。ハードウェアに近いところがうまく隠蔽されている気がします。NAudioみたいに、mp3とwav で処理を分けるようなことも必要ないようです。また、クラスも静的な関数ばかりでチャンネルさえ理解しておけばうまく使えそう。そんなわけで、こちらのライブラリにすこし浮気心を出して遊んでみようかと思っています。

load_downloadBassCodeTest.zip

参考

  • Microsoft Public License (高橋 忍さん)
    http://blogs.msdn.com/b/shintak/archive/2012/09/09/10347542.aspx

You can skip to the end and leave a response. Pinging is currently not allowed.
Subscribe to RSS Feed Twitter は Ume108 だよ