If you have downloaded the
audio player from this site, you will have seen that during the mp3 reproduction, a graphic trace is drawn following faithfully the course of the sound.
With this article, I would want to enter into the specific and analyse the code used to create that sound trace.
You can see the SWF, here:
http://www.flepstudio.org/english/tu...071002144.html
If this was a recipe, I would say that the main ingredient are : BitmapData, ByteArray and SoundMixer'
Let us see how to mix and cook them'
I create a FLA and save it as 'grafico1.fla'.
I create a Document Class, an AS file saved as 'Grafico1.as', implemented the following way:
Code:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.events.TimerEvent;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundMixer;
import flash.utils.ByteArray;
import flash.net.URLRequest;
public class Grafico1 extends MovieClip
{
private var url:String='http://www.flepstudio.org/music/rondo_veneziano/rondo_veneziano.MP3';
private var _channel:SoundChannel;
private var _sound:Sound;
private var timer:Timer;
private var grafico:BitmapData;
public function Grafico1()
{
init();
initSound();
initTimer();
}
private function init():void
{
stage.frameRate=31;
grafico=new BitmapData(250,50,true,0x00000000);
var bitmap:Bitmap=new Bitmap(grafico);
bitmap.x=20;
bitmap.y=100;
addChild(bitmap);
}
private function initSound():void
{
_sound=new Sound(new URLRequest(url));
_channel=_sound.play();
}
private function initTimer():void
{
timer=new Timer(20,0);
timer.addEventListener(TimerEvent.TIMER,update);
timer.start();
}
private function update(evt:TimerEvent):void
{
var spectrum:ByteArray=new ByteArray();
SoundMixer.computeSpectrum(spectrum);
grafico.fillRect(grafico.rect,0x00666666);
grafico.fillRect(new Rectangle(1,1,250,30),0x00000000);
for(var i:Number=0;i<250;i++)
{
grafico.setPixel32(20+i,20+spectrum.readFloat()*35,0xFF000000);
}
for(var j:Number=0;j<250;j++)
{
grafico.setPixel32(20+j,30+spectrum.readFloat()*35,0xFF000000);
}
}
}
}
Let us analyse the code
Properties
a String variable with a value equal to the mp3's url
private var url:String='http://www.flepstudio.org/music/rondo_veneziano/rondo_veneziano.MP3';
an instance of the SoundChannel Class
private var _channel:SoundChannel;
an instance of the Sound Class
private var _sound:Sound;
an instance of the Timer Class
private var timer:Timer;
an instance of the BitmapData Class
private var grafico:BitmapData;
Constructor
I call respectively the methods init, initSound and initTimer
init();
initSound();
initTimer();
Methods
init();
I assign a frame rate to grafico1.fla
stage.frameRate=31;
I create a new BitmapData with a width of 250, height of 50, alpha value true and black colour
grafico=new BitmapData(250,50,true,0x00000000);
I create a bitmap instance and assign to it 'grafico' with the property BitmapData of Bitmap var bitmap:Bitmap=new Bitmap(grafico);
I position the Bitmap
bitmap.x=20;
bitmap.y=100;
I add the bitmap to the stage (otherwise it would not be visible)
addChild(bitmap);
initSound();
I create a new instance of the Sound Class and pass to it as value a new url request which contains the url to the mp3
_sound=new Sound(new URLRequest(url));
I start the instance of SoundChannel
_channel=_sound.play();
initTimer();
I create a new Timer and I impost the speed to 20 for a never ending cycle
timer=new Timer(20,0);
I add a listener which on start of the timer will call the method 'update' every 20 cents of seconds
timer.addEventListener(TimerEvent.TIMER,update);
I start the Timer
timer.start();
update();
I create a new instance of the ByteArray Class
var spectrum:ByteArray=new ByteArray();
using the method 'computeSpectrum' of the soundMixer Class, I take a picture of the actual sound wave and I pass it to ByteArray as a parameter
SoundMixer.computeSpectrum(spectrum);
with the method 'fillRect' of the BitmapData Class, I fill a specified rectangular area (in this case the rectangle defined by the property 'rect' of the graphic)
grafico.fillRect(grafico.rect,0x00666666);
I do the same thing but with a new instance Rectangle
grafico.fillRect(new Rectangle(1,1,250,30),0x00000000);
using a cycle and the methods setPixel32 of the BitmapData Class, I assign a colour to one pixel with the coordinates: x:20+i and y the numerical value returned by the method 'readFloat' of the ByteArray Class, multiplied by 35. The cycles are two: one by audio channel.
for(var i:Number=0;i<250;i++)
{
grafico.setPixel32(20+i,20+spectrum.readFloat()*35 ,0xFF000000);
}
for(var j:Number=0;j<250;j++)
{
grafico.setPixel32(20+j,30+spectrum.readFloat()*35 ,0xFF000000);
}
Second sample:
In this case, the code is the same as in the first example, only the method 'update' has been changed:
var spectrum:ByteArray=new ByteArray();
SoundMixer.computeSpectrum(spectrum);
grafico.fillRect(grafico.rect,0xFF000000);
grafico.fillRect(new Rectangle(1,1,250,250),0xFF000000);
for(var i:Number=0;i<250;i++)
{
grafico.setPixel32(175+spectrum.readFloat()*250,17 5+spectrum.readFloat()*250,0xFFFFFFFF);
}
See you soon!