AS3でMP3を再生

Filed under AS3



MP3をロードして再生するサンプルです。

スペクトラムの表示はおまけ。

サンプルはこちら

UIにはminimalcompsを使っています。

MP3ファイルはこちらのものを使わせてもらってます。

以下、ソースです。

package
{
	import com.bit101.components.HSlider;
	import com.bit101.components.Label;
	import com.bit101.components.PushButton;
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.DropShadowFilter;
	import flash.geom.Rectangle;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundLoaderContext;
	import flash.media.SoundMixer;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;

	[SWF(backgroundColor="0xFFFFFF")]
	public class sound_player extends Sprite
	{
		private var sound:Sound;
		private var channel:SoundChannel;
		private var canvas:BitmapData;
		private var totalTime:Number;
		private var position:int;
		private var seekBar:Sprite;
		private var seekBtn:Sprite;
		private var seekRect:Rectangle;
		private var volumeSlider:HSlider;
		private var playing:int;
		private var playTimeLabel:Label;
		private var totalTimeLabel:Label;
		private var volumeLabel:Label;
		private var seeking:Boolean;
		private var bytes:ByteArray;
		private var errorLabel:Label;

		public function sound_player()
		{
			// ステージの設定
			stage.scaleMode=StageScaleMode.NO_SCALE;
			stage.align=StageAlign.TOP_LEFT;
			stage.quality=StageQuality.HIGH;
			stage.frameRate=40;

			// mp3のロード
			sound=new Sound;
			sound.addEventListener(Event.COMPLETE, onComplete);
			var req:URLRequest=new URLRequest("MP3ファイルまでのパス");
			sound.load(req, new SoundLoaderContext(1000, true));
		}

		private function onComplete(e:Event):void
		{
			sound.removeEventListener(Event.COMPLETE, onComplete);

			// BitmapDataの用意
			canvas=new BitmapData(512, 300, false, 0xffffff);
			var bmp:Bitmap=new Bitmap(canvas);
			addChild(bmp);
			bmp.x=bmp.y=100;

			// BitmapDataの枠線
			var frame:Shape=new Shape;
			frame.graphics.lineStyle(1, 0xAAAAAA);
			frame.graphics.drawRect(0, 0, 512, 300);
			frame.graphics.endFill();
			addChild(frame);
			frame.x=frame.y=100;

			// エラー用ラベル
			errorLabel=new Label(this, 250, 200, "Error.\n\nCannot get Sound wave data.\nYou may open FLV video (YouTube etc..) in other tabs.");

			// 再生フラグの初期化  0:停止 1:再生 2:一時停止
			playing=1;

			// 諸々の初期化
			position=0;
			seeking=false;
			seekRect=new Rectangle(0, 0, 340, 0);
			bytes=new ByteArray();

			// 再生、一時停止、停止用のボタン
			var playBtn:PushButton=new PushButton(this, 650, 100, "PLAY", onPlay);
			var pauseBtn:PushButton=new PushButton(this, 770, 100, "PAUSE", onPause);
			var stopBtn:PushButton=new PushButton(this, 890, 100, "STOP", onStop);

			// 再生時間と音量を表示するラベル
			volumeLabel=new Label(this, 650, 133, "Volume: 50%");
			playTimeLabel=new Label(this, 650, 175, "Time:00:00");
			totalTimeLabel=new Label(this, 700, 175, "");

			// 音量用スライダー
			volumeSlider=new HSlider(this, 650, 150, onSeekVolume);
			volumeSlider.width=340;
			volumeSlider.value=50;
			volumeSlider.maximum=100
			volumeSlider.minimum=0;

			// シークバー
			seekBar=new Sprite;
			seekBar.graphics.lineStyle(1, 0xAAAAAA);
			seekBar.graphics.drawRect(0, -5, 340, 10);
			seekBar.graphics.endFill();
			addChild(seekBar);
			seekBar.x=650;
			seekBar.y=200;

			// シークバーのボタン
			seekBtn=new Sprite;
			seekBtn.graphics.beginFill(0x666666);
			seekBtn.graphics.drawRect(-3, -8, 6, 16);
			seekBtn.graphics.endFill();
			seekBtn.filters=[new DropShadowFilter(2, 45, 0x444444, 0.5, 2, 3)]
			seekBar.addChild(seekBtn);

			// シークバーのボタンのドラッグ範囲
			seekRect=new Rectangle(0, 0, 340, 0);

			// 再生
			channel=sound.play();
			totalTime=sound.length;
			onSeekVolume();
			totalTimeLabel.text=" / " + createTimeText((totalTime / 1000) >> 0);
			addEventListener(Event.ENTER_FRAME, onFrame);

			// シーク用
			seekBtn.addEventListener(MouseEvent.MOUSE_DOWN, onStartSeek);
			stage.addEventListener(MouseEvent.MOUSE_UP, onStopSeek);
		}

		// 再生用関数
		private function onPlay(e:Event):void
		{
			if (playing != 1)
			{
				channel=sound.play(position);
				playing=1;
			}
		}

		// 一時停止用関数
		private function onPause(e:Event):void
		{
			if (playing == 1)
			{
				channel.stop();
				playing=2;
				position=channel.position;
				canvas.fillRect(canvas.rect, 0xffffff);
			}
		}

		// 停止用関数
		private function onStop(e:Event):void
		{
			if (playing != 0)
			{
				channel.stop();
				playing=0;
				position=0;
				canvas.fillRect(canvas.rect, 0xffffff);
			}
		}

		// 音量調整用関数
		private function onSeekVolume(e:Event=null):void
		{
			if (channel)
			{
				var transform:SoundTransform=channel.soundTransform;
				transform.volume=Number(volumeSlider.value / 100);
				channel.soundTransform=transform;
				volumeLabel.text="Volume: " + volumeSlider.value.toString() + "%";
			}
		}

		// フレームイベント用関数
		private function onFrame(e:Event):void
		{
			// 再生位置の更新
			position=(playing == 1 && channel) ? (channel.position) : (position);

			// シークの位置更新
			if (seeking)
			{
				position=(totalTime * seekBtn.x / 340) >> 0;
				if (playing == 1)
				{
					if (channel) channel.stop();
					channel=sound.play(position);
				}
			}
			else
				seekBtn.x=340 * position / totalTime;

			// 時間をmm:ssの形に整形
			var t:String=createTimeText((position / 1000) >> 0);
			playTimeLabel.text="Time:" + t;

			// スペクトラムの作成
			canvas.fillRect(canvas.rect, 0xffffff);
			if (playing == 1)
			{
				if (!SoundMixer.areSoundsInaccessible())
				{
					errorLabel.visible=false;
					canvas.lock();
					SoundMixer.computeSpectrum(bytes, true, 0);

					var spec:Number;
					var h:Number;
					var step:int;
					var j:int;
					for(var i:int=0; i < 256; ++i)
					{
						spec=bytes.readFloat();
						h=400 * spec;
						h=(h > 300) ? (300) : (h);
						step=(h / 2) >> 0;

						for(j=0; j < step; j++) canvas.setPixel(2 * i, 300 - 2 * j, 0x888888);
					}
					canvas.unlock();
				}
				else errorLabel.visible=true;
			}
		}

		// シーク開始用関数
		private function onStartSeek(e:MouseEvent):void
		{
			if (!seeking)
			{
				seeking=true;
				seekBtn.startDrag(false, seekRect);
			}
		}

		// シーク終了用関数
		private function onStopSeek(e:MouseEvent):void
		{
			if (seeking)
			{
				seeking=false;
				seekBtn.stopDrag();
			}
		}

		// 秒数を時間表示用 mm:ss に整形する関数
		private function createTimeText(time:int):String
		{
			var m:int=(time / 60) >> 0;
			var s:int=(time % 60) >> 0;
			var str:String=((m < 10) ? ("0" + m.toString()) : (m.toString()));
			str+=":" + ((s < 10) ? ("0" + s.toString()) : (s.toString()));

			return str;
		}
	}
}

Post a Comment

Your email is never published nor shared.