Sound Visualizer [Study]
...stage click で mp3 音源を自由に入れられるようにしたかったのですが、
FileReferenceで取得した data の ByteArray と、sound クラスの extract() で取得した ByteArray では違うものらしく、
現状のスキルではバイナリデータからの音生成が無理でした。。
なのでただ sin を視覚化して、マウスポイントで音量とパンを変化させてるだけのものです。
@author rettuce
/**
* Copyright rettuce ( http://wonderfl.net/user/rettuce )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/40yi
*/
package {
import flash.display.MovieClip;
import flash.display.BlendMode;
import flash.events.Event;
import flash.events.SampleDataEvent;
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.MouseEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.net.FileReference;
import flash.net.URLRequest;
import flash.media.SoundMixer;
import flash.utils.ByteArray;
import flash.system.LoaderContext;
import flash.media.SoundLoaderContext;
[SWF(width = 465, height = 465, backgroundColor = 0x000000, frameRate = 60)]
/**
* ...stage click で mp3 音源を自由に入れられるようにしたかったのですが、
* FileReferenceで取得した data の ByteArray と、sound クラスの extract() で取得した ByteArray では違うものらしく、
* 現状のスキルではバイナリデータからの音生成が無理でした。。
* なのでただ sin を視覚化して、マウスポイントで音量とパンを変化させてるだけのものです。
*
* @author rettuce
*/
public class FlashTest extends Sprite {
private var _channel:SoundChannel;
private var _byteArray:ByteArray;
private const CHANNEL_LENGTH:int = 256;
private var _barArray:Array = [ ];
private var _barYellow:Shape;
private var _barBlue:Shape;
private var _file:FileReference;
private var sound:Sound;
private var sound0:Sound;
private var dataSound:Sound;
private var _sampleData:ByteArray;
public function FlashTest() {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
for (var i:int = 0; i < CHANNEL_LENGTH; i++)
{
_barYellow = new Shape();
_barBlue = new Shape();
_barYellow.graphics.beginFill(0xFFFF00);
_barYellow.graphics.drawRect(0, -1, 1, 1);
_barYellow.graphics.endFill();
_barYellow.blendMode = BlendMode.ADD;
addChild(_barYellow);
_barBlue.graphics.beginFill(0x0000FF);
_barBlue.graphics.drawRect(0, -1, 1, 1);
_barBlue.graphics.endFill();
_barBlue.blendMode = BlendMode.ADD;
addChild(_barBlue);
_barYellow.y = _barBlue.y = stage.stageHeight-20;
_barYellow.x = _barBlue.x = i*2;
_barArray[i] = _barYellow;
_barArray[i+256] = _barBlue;
}
_byteArray = new ByteArray();
// 音源取得用 sound クラス生成
// sound0 = new Sound();
// sound0.load(new URLRequest("src/OorutaichiRemix.mp3"));
// sound0.addEventListener(Event.COMPLETE, function()
// {
// 再生用 sound クラスの 生成と sampleDataEvent 取得
sound = new Sound();
sound.load(new URLRequest("http://lab.rettuce.com/common/src/PieceOfCake.mp3"), new SoundLoaderContext(1000, true) )
_channel = sound.play(0,1);
addEventListener(Event.ENTER_FRAME, enterFrame);
// } );
}
private function fileSetHandler(e:MouseEvent):void { _file.browse();}
private function fileSelect(e:Event):void { _file.load(); }
private function fileComplete(e:Event):void // _file.data ByteArray
{
sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
dataSound = new Sound();
dataSound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData2);
_channel = dataSound.play(0, int.MAX_VALUE);
}
private function onSampleData(e:SampleDataEvent):void
{
// _sampleData = new ByteArray();
// var _sampleDataNumber:Number = sound0.extract(_sampleData, 8192); // _sampleData ByteArray
for (var c:int = 0; c < 8192; c++)
{
var rad:Number = Number(c+e.position)/Math.PI/ 8;
var amp:Number = Math.sin(rad) / 4; // -1 から 1 の間の値なら OK
e.data.writeFloat(amp); // 左チャネルの音
e.data.writeFloat(amp); // 右チャネルの音
}
}
private function onSampleData2(e:SampleDataEvent):void
{
_sampleData = new ByteArray();
_sampleData = _file.data;
var l:Number, r:Number;
_sampleData.position = 0;
for (var c:int = 0; c < 8192; c++)
{
l = _sampleData.readFloat();
e.data.writeFloat(l); // 左チャネルの音
r = _sampleData.readFloat();
e.data.writeFloat(r); // 右チャネルの音
}
}
private function enterFrame(e:Event):void
{
var soundTForm:SoundTransform = new SoundTransform();
soundTForm.pan = (mouseX - stage.stageWidth / 2) / (stage.stageWidth / 2);
soundTForm.volume = mouseY / stage.stageHeight;
_channel.soundTransform = soundTForm;
SoundMixer.computeSpectrum(_byteArray, false, 0);
var i:int;
var l:Number, r:Number;
var _barL:Shape, _barR:Shape;
for (i = 0; i < CHANNEL_LENGTH; i++)
{
_byteArray.position = i * 4;
l = _byteArray.readFloat();
_byteArray.position = i * 4 + 1024;
r = _byteArray.readFloat();
_barL = _barArray[i];
_barR = _barArray[i+256];
_barL.height = 300 * l;
_barR.height = 300 * r;
}
}
}
}