スペクトラムアナライザを表示する

(サンプル一覧を表示する)

スペクトラムアナライザを表示するサンプルです。

SoundMixer.computeSpectrum() を呼び出して、
周波数帯域ごとのデータを取得しています。
詳しく調べていないので、グラフのどの辺の位置が何ヘルツなのか分かりません。
左側 (配列の最初の方) が低い音っぽいです。

曲は、フリー素材曲(MIDI/MP3)のダウンロードサイト / ハイパースペシャル さんからお借りしました。

プロジェクトファイルの中に曲データは入っていないので、
HDD の中に入っている MP3 ファイルを持ってきて代用してください。
SWF ファイルが生成される bin フォルダに一緒に入れると、再生時のエラーが出なくなります。
Flash の実行画面
スペクトラムアナライザを表示する

Flashプレーヤーが入っていないか、JavaScriptが無効になっているようです。

Get Adobe Flash player

スペクトラムアナライザを表示する

ソースコード

package 
{
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundMixer;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.utils.ByteArray;
	
	/**
	 * スペクトラムアナライザを表示するサンプル
	 * @author Hikipuro
	 */
	public class Main extends Sprite 
	{
		/**
		 * ボタン
		 */
		private var button1:SimpleButton;
	
		/**
		 * ボタンのラベル
		 */
		private var buttonText1:TextField;
		
		/**
		 * Left と書かれたテキストフィールド
		 */
		private var textLeft:TextField;
		
		/**
		 * Right と書かれたテキストフィールド
		 */
		private var textRight:TextField;
		
		/**
		 * サウンドのローダ
		 */
		private var sound:Sound;
		
		/**
		 * サウンド制御用サウンドチャネル
		 */
		private var soundChannel:SoundChannel;
		
		/**
		 * コンストラクタ
		 */
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		/**
		 * 初期化イベント
		 * @param	e
		 */
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			// Left と書かれたテキストフィールドを配置
			textLeft = new TextField();
			textLeft.autoSize = TextFieldAutoSize.RIGHT;
			textLeft.selectable = false;
			textLeft.x = 36;
			textLeft.y = 127;
			textLeft.text = "Left";
			addChild(textLeft);
			
			// Right と書かれたテキストフィールドを配置
			textRight = new TextField();
			textRight.autoSize = TextFieldAutoSize.RIGHT;
			textRight.selectable = false;
			textRight.x = 36;
			textRight.y = 197;
			textRight.text = "Right";
			addChild(textRight);
			
			// ボタンのラベルの作成
			buttonText1 = new TextField();
			buttonText1.autoSize = TextFieldAutoSize.CENTER;
			buttonText1.selectable = false;
			buttonText1.x = 60;
			buttonText1.y = 30;
			buttonText1.text = "再生";
			addChild(buttonText1);
			
			// ボタンの作成
			button1 = new SimpleButton();
			button1.upState = makeRoundRect(0xDDDDDD, 100, 20, 10);
			button1.overState = makeRoundRect(0xFFFFFF, 100, 20, 10);
			button1.downState = makeRoundRect(0xBBBBBB, 100, 20, 10);
			button1.hitTestState = button1.upState;
			button1.addEventListener(MouseEvent.MOUSE_DOWN, onButtonMouseDown);
			button1.x = 10;
			button1.y = 30;
			addChild(button1);
			
			// フレーム開始イベントの登録
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
			
			// サウンドの URL を指定
			var urlRequest:URLRequest;
			urlRequest = new URLRequest("khs_come_cross_the_winter.mp3");
			sound = new Sound(urlRequest);
		}
		
		/**
		 * フレーム開始イベント
		 * @param	event
		 */
		private function onEnterFrame(event:Event):void 
		{
			// 周波数帯域ごとのデータを格納する ByteArray の準備
			// 512 個のデータが入る。
			var byteArray:ByteArray = new ByteArray();
			
			// 周波数帯域ごとのデータを取得
			SoundMixer.computeSpectrum(byteArray, true, 0);
			byteArray.position = 0;
			
			// 図形をいったんクリア
			graphics.clear();
			
			// 描く線の状態を初期化
			graphics.lineStyle(1, 0xFF0000, 0.5);
			
			// 変数の準備
			var i:uint = 0;
			var n:Number = 0;
			
			// 左チャネルのデータを描く
			graphics.beginFill(0xFF8000);
			graphics.moveTo(50, 140);
			for (i = 0; i < 256; i++)
			{
				n = 140 - byteArray.readFloat() * 50;
				graphics.lineTo(i + 50, n);
			}
			graphics.lineTo(256 + 50, 140);
			graphics.endFill();
			
			// 右チャネルのデータを描く
			graphics.beginFill(0xFF8000);
			graphics.moveTo(50, 210);
			for (i = 0; i < 256; i++)
			{
				n = 210 - byteArray.readFloat() * 50;
				graphics.lineTo(i + 50, n);
			}
			graphics.lineTo(256 + 50, 210);
			graphics.endFill();
		}

		/**
		 * ボタンが押された時のイベント
		 * @param	event
		 */
		private function onButtonMouseDown(event:MouseEvent):void
		{
			if (buttonText1.text == "再生")
			{
				buttonText1.text = "停止";
				soundChannel = sound.play(0, 0);
			}
			else if (buttonText1.text == "停止")
			{
				buttonText1.text = "再生";
				soundChannel.stop();
			}
		}
		
		/**
		 * 角丸の図形を描いたスプライトを作って返す
		 * @param	color	色
		 * @param	width	幅
		 * @param	height	高さ
		 * @param	round	角丸の大きさ
		 * @return	スプライト
		 */
		private function makeRoundRect(color:uint, width:int, height:int, round:int):Sprite
		{
			var s:Sprite = new Sprite();
			s.graphics.lineStyle(2);
			s.graphics.beginFill(color);
			s.graphics.drawRoundRect(0, 0, width, height, round);
			s.graphics.endFill();
			s.alpha = 0.3;
			return s;
		}
		
	}
}
		

computeSpectrum() メソッドは今のところ (2009/06/13)、
「Firefox で Youtube のタブを開いているとエラーが発生する」
というバグがあります。

これを回避するには、Sound.extract() メソッドを使用すると良いようです。
しかし、Sound.extract() メソッドは Flash Player 10 以降でサポートされ始めたメソッドのため、
これを使う場合は、 Flash Player 9 以前の環境でスペクトラムアナライザが使用できなくなります。

また、Sound.extract() メソッドは computeSpectrum() メソッドで返されるデータとは
内容が異なるため、同じように機能させる時には FFT の処理を入れる必要があるそうです。

・CodeProject: How to implement the FFT algorithm. Free source code and programming help
http://www.codeproject.com/KB/recipes/howtofft.aspx

参照

外部リンク