feb19.jp

Nobuhiro Takahashi
Designer / Engineer

AS3でSoundを制御する

AS3でSoundを制御する

AS3はSound関連のクラスが増えて、制御するには複数のクラスを使う必要があるので、それのメモ。

NetStreamとかのビデオの制御より難しくなってません?そうでもないか。

Sound関連で必要になるクラスはSound、SoundChannel、SoundTransform、SoundLoaderContext、SoundMixer。全部flash.media.パッケージの中です。import flash.media.*;としちゃいましょう。これらをひとつひとつ簡単に解説してみます。

flash.media.Soundクラス
音を再生するために必要となる基本的なクラス。SoundChannelインスタンスの生成にも必要。レコーディングでいう音源とか、楽器とか、音のソースになるものというイメージ。

flash.media.SoundChannelクラス
Sound.play()で返ってくる戻り値から生成可能。新規チャンネルならnew SoundChannel。音楽やってた人ならわかりやすいと思いますが、SoundChannelは音楽のミキサーとかでいうチャンネル一つ一つのことです。
play()で返ってくるのは現在のトラックをチャンネルに割り当てるって感じのこと。newで生成するのはDAWのLogicとかProtoolsとかでいう「新規オーディオトラック」って感じのこと。でもplay()でしかチャンネルに割り当てられないからあんまり使うことは無いと思う。

flash.media.SoundTransformクラス
SoundChannelやSoundMixerのボリュームやパンを設定するクラス。これもミキサーが想像できる人は分かりやすいと思いますが、ミキサーのフェーダーをいじるっていう感じのイメージのクラスです。
SoundChannelクラスとか、SoundMixerクラスの中にはsoundTransformっていうプロパティがあって、それを変数に割り当てることで生成できます。var st = SoundChannel.soundTransform;みたいな感じで現在の値を拾って作るみたいな感じ。
新規でSoundTransformを作ってSoundChannelやSoundMixerに割り当てることはできないので、new SoundTransformはできないと考えてよさそう。多分、そのチャンネルとかミキサーが、トランスフォーム用の値とで関連づいてて、new SoundTransformで作ってしまった時、何も関連づいてないのでチャンネルとかミキサーに割り当てられないとか、そういう構造になっているんだと思う。MatrixとかColorTransformでもそんな感じだから、そういうことだと思う。でも、MovieClip.soundTransformや、NetStream.soundTransformに対してはnew SounTransform(0)とか使える。

flash.media.SoundLoaderContextクラス
外部MP3ファイルなどをロードする時のセキュリティ関連のチェックや、バッファ時間を設定する場合に使う。使うことはほぼ無いような気がする。ちなみに生成はnew SoundLoaderContextです。

flash.media.SoundMixerクラス
サウンド全体をコントロールするためのクラス。でも外部MP3ファイルは制御できないらしい。これのsoundTransform.volume制御したらSOUND ON/OFFできるとかいうのにすればいいのに。で、あとcomputeSpectrumとかでエロいことをしたい人は使う。
new SoundMixerします。

とクラスはいっぱいありますけど、シンプルにサウンドを操作するには以下のようなスクリプトを使います。

new Sound([new URLRequest [,new SoundLoaderContext]]);
Soundインスタンス生成。再生やロードとかの処理をしたり、SoundChannelを生成したりする。

Sound.load(new URLRequest [,new SoundLoaderContext]]);
外部サウンドのロード。第一引数は必須。

Sound.play([start秒数, loop回数, SoundTransform]);
サウンドを再生。戻り値にSoundChannelインスタンスを返す。

SoundChannel.stop();
サウンドを停止。Sound.stop();ではないので注意。

SoundChannel.position;
サウンドの現在再生位置(ミリ秒単位数値)。一時停止とかの処理を作るときはこれを使う。

SoundChannel.soundTransform;
チャンネルのボリュームやパンをコントロール。SoundTransform.volumeでボリューム(0〜1)、SoundTransform.pan(-1〜1)でパン。

これだけあれば問題なさそう。

というわけで、サウンドの制御に関する基本的なコードサンプル。

1. ライブラリに読み込んだサウンドを再生する場合

まず、ライブラリに読み込んだ再生する音声ファイルを右クリックして、リンケージを設定する。「クラス」をMySoundで、「基本クラス」をflash.media.Sound。「ActionScriptに設定」と、「最初のフレームに書き出し」とか、チェック。これで、MySoundというSoundクラスを継承した、その音声ファイルを音源とした基本となるクラスができました。これを使って制御します。

ステージ上にplay_btn、pause_btn、stop_btn、sndoff_btn、sndon_btnというインスタンスを作って、1フレーム目にnew SoundPlayer1(this);と書いて、以下のコードをSoundPlayer1.asというファイルで.flaファイルと同じディレクトリ内に保存して、実行してみてください。

package {
	import flash.media.*;
	import flash.net.*;
	import flash.display.*;
	import flash.events.*;
	public class SoundPlayer1 {
		private var basemc	:MovieClip;
		private var sound	:MySound;
		private var sc	:SoundChannel;
		private var pos	:uint;
		public function SoundPlayer1(mc) {
			basemc = mc;
			sound = new MySound();
			pos = 0;
			var btns = new Array();
			btns = [basemc.play_btn, basemc.pause_btn, basemc.stop_btn, basemc.sndoff_btn, basemc.sndon_btn];
			for(var i=0; i

2. 外部MP3ファイルを再生する場合

1. ライブラリに読み込んだサウンドを再生する場合と同じような感じでステージ上にplay_btn、pause_btn、stop_btn、sndoff_btn、sndon_btnというインスタンスを作って、1フレーム目にnew SoundPlayer(this);と書いて、以下のコードをSoundPlayer2.asというファイルで.flaファイルと同じディレクトリ内に保存して、sound.mp3というファイルも置いて、実行してみてください。

package {
	import flash.media.*;
	import flash.net.*;
	import flash.display.*;
	import flash.events.*;
	public class SoundPlayer2 {
		private var basemc	:MovieClip;
		private var sound	:Sound;
		private var sc	:SoundChannel;
		private var pos	:uint;
		public function SoundPlayer2(mc) {
			basemc = mc;
			sound = new Sound();
			// 増えたのここだけ!!! URLRequestインスタンスで指定した外部ファイルを読み込みます。
			sound.load(new URLRequest("sound.mp3"));
			pos = 0;
			//-----------------------
			var btns = new Array();
			btns = [basemc.play_btn, basemc.pause_btn, basemc.stop_btn, basemc.sndoff_btn, basemc.sndon_btn];
			for(var i=0; i

おまけで、「サウンドの再生が終わったら何かするイベント」も上のコードに追加してみました。SoundChannelインスタンスにaddEventListenerして、イベント定数にEvent.SOUND_COMPLETEで、拾えます。

バグ

ただ、1、2の方法、どちらもバグがあります。それは、play_btnをクリック連打すると、音がクリックした分だけ、重なって再生されてしまいます。これは、Sound.play()というメソッドが、音源に対して、「とにかく再生しろ」みたいな命令を出していて、SoundChannelはそれをそのまま受け取っていて音を流しているからです。というわけで、以下のような方法で回避します。

a. SoundChannel.stop()を再生直前に使って音を停止してからSound.play()

まずコンストラクタで一回playしてからすぐstopしておいて、SoundChannelを作っておくのが必要。で、play_btnのClickイベント内にはSoundChannel.stop()を。

上の例1でいうと、コンストラクタの中は

sound = new MySound();
st = sound.play();
st.stop();

クリックイベントの中は

case basemc.play_btn:
	sc.stop();
	sc = sound.play(pos);
	break;

簡単だけど、でもちょっと無理矢理な感じですよね。

b. var isPlaying:Booleanを用意しておいて、フラグ制御

なんとなくアナログな感じですが、こっちの方が無理矢理な感じじゃなくて、いいと思います。なんとなく。コンストラクタでisPlaying = false;としておいて、play_btnをクリックしたら、isPlaying = true。isPlayingがtrueの時は、条件分岐でSound.play()しないようにする。pause_btnやstop_btn、SOUND_COMPLETEイベント発生時はisPlaying = falseにするのをお忘れなく、という感じ。

こんな感じで、バグをつぶせます。実際に例に追加してみてください。

付録:ビデオの音の制御

ちなみに、埋め込みビデオの音を制御する場合は、埋め込まれたMovieClip.soundTransform = new SoundTransform();で。外部読み込みでLoaderを使っているなら、var mc = loader.content as MovieClip; mc.soundTransform = new SoundTransform();で。

FMSとか、普通のFLVストリーミングとかのNetStreamを使った、外部からのFLVストリーミングのサウンド制御は、NetStream.soundTransform = new SoundTransform();で制御可能。

SoundTransformの引数は省略可能だけど、第一引数がvolume、第二引数がpanなので、new SoundTransform(1)とかでSOUND ON、とかにできます。

こんなかんじでしょうか?後々サンプルも書こうと思います。ビデオ関連の音とか。

以上、完全なる自分のメモ用に書いていた文章なので、いつにも増して日本語がむちゃくちゃですが、おゆるしください。

Navigation

prev: 広松木工の7段チェスト&トレイ - SONO Chest Tray 028
next: AS3でポップアップウィンドウを呼び出す

Recently Entries