Flash CS3: ByteArray, Sound e grafici sincronizzati
This is a discussion on Flash CS3: ByteArray, Sound e grafici sincronizzati within the Articoli e tutorials forums, part of the Flash CS3 e Actionscript 3.0 category; Per chi di voi ha scaricato l' audio player di questo sito, si sarà accorto che durante la riproduzione ...
Flash CS3: ByteArray, Sound e grafici sincronizzati
Per chi di voi ha scaricato l' audio player di questo sito, si sarà accorto che durante la riproduzione audio dell' mp3 viene disegnato una sorta di grafico, un tracciato audio che riproduce fedelmente l' andamento dei timbri del suono.
Con questo articolo, vorrei proprio entrare nello specifico e analizzare il codice utilizzato per creare quel tracciato audio.
Se questa fosse una ricetta* direi che gli ingredienti prinicpali sono: BitmapData, ByteArray e* SoundMixer.
Vediamo come cucinarli ...*
Creo un FLA che salvo con nome ' grafico1.fla '.
Creo la Document Class, un file AS che salvo con nome ' Grafico1.as ' , implementata in questo modo:
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);
}
}
}
}
Risultato:
Analizziamo il codice
Proprietà
una variabile di tipo String col valore dell' url al file .mp3
private var url:String='http://www.flepstudio.org/music/rondo_veneziano/rondo_veneziano.MP3';
una istanza della classe SoundChannel
private var _channel:SoundChannel;
una istanza della classe Sound
private var _sound:Sound;
una istanza della classe Timer
private var timer:Timer;
una istanza della classe BitmapData
private var grafico:BitmapData;
Funzione costruttrice
chiamo rispettivamente i metodi init, initSound e initTimer
init();
initSound();
initTimer();
Metodi
init();
assegno una velocità di frame rate a grafico1.fla
stage.frameRate=31;
creo una nuova BitmapData con larghezza 250, altezza 50, valore alpha getibile, colore nero
grafico=new BitmapData(250,50,true,0x00000000);
creo una istanza Bitmap e gli assegno grafico come proprietà BitmapData di Bitmap
var bitmap:Bitmap=new Bitmap(grafico);
posiziono la Bitmap
bitmap.x=20;
bitmap.y=100;
inserisco la Bitmap nello stage ( altrimenti non sarebbe visibile )
addChild(bitmap);
initSound();
creo una nuova istanza della classe Sound e gli passo come valore una nuova richiesta url ( URLRequest ) che a sua volta contiene l' url al file .mp3
_sound=new Sound(new URLRequest(url));
dico all' istanza di SoundChannel di iniziare a riprodurre il suono
_channel=_sound.play();
initTimer();
creo un nuovo Timer impostando una velocità di 20 a ciclo infinito
timer=new Timer(20,0);
aggiungo un listener in ascolto che allo start del timer chiamerà il metodo update ogni 20 centesimi di secondo
timer.addEventListener(TimerEvent.TIMER,update);
faccio partire il timer
timer.start();
update();
creo una nuova istanza della clase ByteArray
var spectrum:ByteArray=new ByteArray();
utilizzando il metodo computeSpectrum della classe SoundMixer scatto un' istantanea dell' onda del sound attuale e la inserisco nel ByteArray passandogliela come parametro.
SoundMixer.computeSpectrum(spectrum);
tramite il metodo fillRect della classe BitmapData riempio una specifica area rettangolare ( in questo caso il rettangolo definito dalla proprietà rect di grafico )
grafico.fillRect(grafico.rect,0x00666666);
quì faccio la stessa cosa ma con una nuova istanza Rectangle
grafico.fillRect(new Rectangle(1,1,250,30),0x00000000);
attraverso un ciclo e i metodi setPixel32 della classe BitmapData assegno un colore ad un pixel che ha come coordinate: x: 20+i e y il valore numerico restituito dal metodo readFloat della classe ByteArray moltiplicato per 35. I cicli sono due: no per canale audio.
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);
}
Un altro esempio di grafico:
in questo caso, il codice è lo stesso del primo esempio, cambia solo il metodo update:
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);
}