AS3 Before ActionScript 3, if you wanted or needed to include an audio visualizer in yourFlash app, you had to use something like FlashAmp Pro, which examined your audiofile and printed
Trang 1The preceding code is a pure XML representation of the example HTML content First, I have my XMLdeclaration specifying my version and encoding choices Next, I load or attach an XSL style sheet to mycontent (more on that in a minute) After the style sheet is the root node, <html>, which is where Istart defining the content To keep it simple and relative, I’m using the same tags that I would if cod-ing HTML The <head> tag contains all the data that I want to appear in the <head> of the HTML page:title plus description and keywords <meta> tags Following that is a series of <company> tags Think ofthese as the HTML body This is the data that will be rendered inside the Flex application Now, back
to the style sheet Here’s the code for that:
</script>
<style type="text/css">
/* hide from ie on mac \*/
html {height: 100%;
overflow: hidden;
}
#flexcontent {height: 100%;
}/* end hide */
body {height: 100%;
Trang 2In this chapter, I talked about SEO: what it is, its importance to Rich Internet Application developers,and some of the techniques that Flex developers can use to achieve this often-elusive goal Armedwith these kinds of tools, there’s no reason why the quantity and quality of the search traffic to yourFlex applications wouldn’t improve
Now that you’ve got more traffic coming in, you’ll see how you can pimp out your front end with anActionScript 3 audio visualizer in the next chapter
CHAPTER 17
8962CH17.qxd 11/7/07 10:55 AM Page 440
Trang 5Prior to Flash Player 9, Flash developers had to rely on third-party applications to ate equalizer-type displays or audio visualizers Now, thanks to improvements to theActionScript language, you can create these experience enhancers natively Combinethat with the relative ease of use of the Flex framework, and you can come up withsome pretty amazing visualizations with minimal effort But before getting intoexactly how to create one, I’ll show you how the landscape has changed fromActionScript 2 to ActionScript 3.
cre-In addition, this chapter introduces you to the SoundMixer class and the newByteArray class, and discusses design planning and implementation
AS2 vs AS3
Before ActionScript 3, if you wanted or needed to include an audio visualizer in yourFlash app, you had to use something like FlashAmp Pro, which examined your audiofile and printed an array of amplitude values to a text file that you would then importinto your FLA and use the values to animate your equalizer (EQ) movie clips.Figure 18-1 shows an example output file
BUILDING AN AUDIO VISUALIZER IN FLEX
By Hasan Otuome
Chapter 18
Trang 6Figure 18-1 Sample FlashAmp Pro output file
If you wanted a visualizer that actually responded to the audio spectrum of a track, this was the onlyway Although this method works, it is not the most streamlined, as you have to scan and create a peakfile for each MP3, and then do some ActionScript coding to actually read these values on the fly andanimate your clips accordingly Following is a basic example of the process of creating an audio visu-alizer in AS2 using Flash 8
Start off by creating a new Flash document and set the frame rate to 24 frames per second Next, ate a simple EQ band like the one in Figure 18-2
cre-Figure 18-2 Basic EQ-band graphic
CHAPTER 18
8962CH18.qxd 11/7/07 10:59 AM Page 444
Trang 7After you’ve created your EQ graphic, convert it to a movie clip and start laying duplicates out on thestage until you have 16 of them like in Figure 18-3.
#include flashamp.asNow, in your favorite text editor, create a new text file and save it as flashamp.as This is where all theActionScript magic will happen Note that the use of an external ActionScript file is completelyoptional The code you are about to write can just as easily be inserted into your Actionspanel inside
of the Flash IDE
As a matter of habit, I always start off my scripts with a variable declarations section This serves as mydictionary that I can quickly reference as the code continually grows So, the first few lines of ourexternal script file are dedicated to just that purpose
var titles:Array = new Array();
var tracks:Array = new Array();
var muzak:XML = new XML();
var spectrumInt:Number;
var spectrumUpdateInt:Number;
var spectrumArray:Array = new Array();
Trang 8Here’s a brief description of what these variables do:
The first two are counter variables to be used later on in some looping construct
index is a counter variable for stepping through the XML playlist
tl is a reference to the main timeline
alb is a placeholder for the currently loaded album’s ID
fps is the frame rate of the SWF
numBands is the number of EQ bands you’re dealing with
titles will hold all the song titles for the playlist
tracks will hold all the URLs for the playlist
muzak will be the name for our XML object
spectrumInt will be used as the interval in the setInterval() function thatspectrumUpdateInt will serve as the ID for
Next, create a new Sound object for the MP3 you’re going to load, and define what you want to pen when the song has loaded
hap-var snd:Sound = new Sound();
snd.onLoad = function(){
snd.setVolume(50);
snd.start(0, 1);
}There’s nothing fancy here You’re loading the song, cutting the volume in half so you don’t blow anyspeakers, and starting playback The next dilemma comes from how you process that spectrum datathat FlashAmp Pro created for you If you look at Figure 18-1 again, notice the double brackets aftersv= This means that FlashAmp Pro is outputting those spectrum values as a multidimensional array orarrays inside of an array So, each EQ band has an array of values representative of that bandwidth’sactivity at a given point of the song It’s these values that you’ll use to animate your movie clips, butfirst you have to get the values into Flash in a format that Flash can use Enter the str2array function.This utility will parse that text file with the spectrum values and return an array formatted for use inyour visualizer
spectrumIndex++;
}return(spectrumValues);
}That takes care of one of the hardest parts of the whole process Now, you need to zero out all the EQband clips This gives your animation that home stereo quality
CHAPTER 18
8962CH18.qxd 11/7/07 10:59 AM Page 446
Trang 9for(i=0, i < numBands; i++){
setProperty("tl.s"+i, _yscale, 0);
}Here you use the global function setProperty(target:Object, parameter:Object, expression:Object)
to change the _yscale of all your EQ clips from their defaults to 0 Now they will be hidden until audioplayback begins Next, you need to put the pieces in place to actually load the spectrum data For this,the LoadVars object is perfect Define a new LoadVars and set up a callback function for the onLoadevent of the LoadVars like the following:
var spectrumLV:LoadVars = new LoadVars();
}}With your “spectrum reader” set up, you can now focus on loading the XML playlist
function getTrax():Void{
var trax:Array = this.firstChild.childNodes;
for(i=0; i < trax.length; i++){
titles.push(trax[i].attributes.lbl);
tracks.push(trax[i].attributes.src);
}index=0;
function setStatus(){
spectrumInt = Math.floor(snd.position/1000*fps);
spectrumUpdateInt = setInterval(updateSV, spectrumInt, snd);
}
Trang 10So, you use spectrumInt to figure out the frequency or how often you want the animation to beupdated Next, you tell Flash that you want to call the updateSV() function every spectrumInt andyou’re passing your Sound, snd, as an optional parameter to updateSV() The updateSV() function willtake care of the actual clip animations by reading the spectrumArray and updating the corresponding_yscale property of each clip based on the current spectrum value multiplied by the volume toaccount for user-initiated volume adjustments.
function updateSV(){
var spectrumPos:Number = Math.floor(snd.position/1000*fps);
vol = snd.getVolume()/100;
for(i=0; i < numBands; i++){
setProperty("tl.s"+i, _yscale, spectrumArray[spectrumPos][i]*vol);
}}Now, that wasn’t extremely painful, but it wasn’t exactly painless either Thanks to the advancementsmade to the ActionScript language and the new ActionScript Virtual Machine in Flash Player 9, youcan bypass some of these steps and still produce some really cool user experiences The first improve-ment worth exploring is the new SoundMixer class
Introducing the SoundMixer
The SoundMixer class, found in the flash.media package, contains static properties and methods forglobal sound control in a SWF file The SoundMixer class controls embedded streaming sounds in aSWF; it does not control dynamically created Sound objects or Sound objects created in ActionScript.It’s a top-level class inheriting directly from Object, and it has a few properties and methods thatyou’ll be tapping into to build your Flex visualizer The most important method of the SoundMixerclass is computeSpectrum(outputArray:ByteArray, FFTMode:Boolean, stretchFactor:int) Whatthis method does is it takes a snapshot of the current sound wave and places it into the specifiedByteArray object This process is very similar to what FlashAmp Pro does when it creates that text filefor you Here, you’re able to keep it all in-house
The computed values are formatted as normalized floating-point values that range from –1.0 to 1.0and are stuffed into the outputArray parameter, a ByteArray object that holds the values associatedwith the sound The size of this ByteArray object is fixed at 512 floating-point values, with the first 256representing the left channel of audio and the second 256 values representing the right channel.FFTMode is a Boolean value indicating whether a Fourier transformation is performed on the sound
data first A Fourier transformation, named after French mathematician and physicist Joseph Fourier,
is a mathematical operation where you break something (technically referred to as the function) down
into a series of related elements (aka the components) A good example is a musical chord (function)and the individual notes that make up the chord (components)
Setting the FFTMode parameter to true causes the method to return a frequency spectrum instead ofthe raw sound wave In the resulting frequency spectrum, low frequencies are represented on the left,and high frequencies are on the right The stretchFactor parameter deals with the resolution of thesound samples The default is 0, which equates to data being sampled at 44.1 kHz A value of 1 cutsthat in half, reducing it to 22.05 kHz and so on
CHAPTER 18
8962CH18.qxd 11/7/07 10:59 AM Page 448
Trang 11All of this newly built-in functionality will prove very handy But before moving any further, you need
to get an understanding of the seemingly mysterious ByteArray
Understanding the ByteArray
The ByteArray class, found in the flash.utils package, offers methods and properties that optimizereading, writing, and working with data on a binary level (1s and 0s) To understand how cool this is,consider how the new ActionScript Virtual Machine in Flash Player 9 deals with things behind the
scenes The most compact representation of in-memory data is a packed array, or an array of bytes
packed into a specialized format to improve computational performance That’s why this class is fect for creating audio visualizers You can perform a complex computational analysis on an audio filevia SoundMixer.computeSpectrum() and easily gain access to the results through a ByteArray instanceusing standard ActionScript array access operators []
per-Now, while the ByteArray class has a bevy of properties and methods that enable you to really mize your data storage, streaming, and performance, you’ll be using just one method for this project,readFloat() readFloat() reads an IEEE 754 single-precision floating-point number from the bytestream and returns that number Don’t freak out about IEEE 754 It’s just the standard for binaryfloating-point arithmetic It defines the formats for representing floating-point numbers “Single-precision” just means the number occupies 32 bits or 4 bytes of data
opti-So, what this means for your visualizer is that you’ll use computeSpectrum() to take the audio streamand stuff the analysis of it into a ByteArray instance, and then you’ll use readFloat() to returnnumerical data from the stream that will be used to create an accurate animation of the audio spec-trum Armed with knowledge of the tools required, you should now be ready to build it, so let’s getstarted
Design planning
When it comes to architecting your Flex applications, you have a lot of options You can build themout using just MXML markup, ActionScript, or various combinations of the two For this sample proj-ect, you’ll need to use a combination This visualizer will implement the code-behind technique, which
is basically MXML markup powered by an ActionScript class
To get started, open up your copy of Flex Builder or Eclipse Next, create a new project either by clicking in the Navigator panel and selecting New ➤Flex Project or by selecting File ➤ New ➤FlexProjectfrom the application menu In the New Flex Projectwindow that pops up, you want to keep thedefault selection for how the application will access data since you won’t be using any of the options
right-in this project Click Nextand name the project visualizer After you’ve named it, click Finish
This method is subject to local file security restrictions (aka restrictions on domain loading) If you’re working with sounds loaded from a server in a different domain than the calling SWF, you might need to utilize a cross-domain policy file.
Trang 12cross-Flex will create a main application file with the same name as your project that’s empty and ready
to be filled Leave that alone for the time being, as you’re going to create your Equalizer componentand your Visualizer class first In the Navigator panel, right-click your new project and select
New ➤Folder Name this new folder components, make sure it’s selected, right-click, and choose
New ➤MXML Component Name this new component Equalizerand base it on Canvas Once the file isopened, input the following into the file:
xmlns:com="components.*"
This informs the compiler that you plan to have XML tags in your application that start with com andthat these tags are pointed at files located in the components subdirectory Now that you’ve addedthat namespace, you can add an instance of your Equalizer component to the application by insertingthe following line into visualizer.mxml:
<com:Equalizer id="eq" horizontalCenter="0" verticalCenter="0"/>
The most important of the three attributes in this tag is the id since that’s how you’ll be able to talk
to the component from the Visualizer class that you’ll soon create The other attributes relate to thelayout of the Equalizer component, which in this case is pinned to the center of the browser window.Your modified main application file should now look like the following:
<?xml version="1.0" encoding="utf-8"?>
<mx:Applicationxmlns:mx="http://www.adobe.com/2006/mxml"
CHAPTER 18
8962CH18.qxd 11/7/07 10:59 AM Page 450
Trang 13The visualization
This is where you’ll breathe life into your project by writing a Visualizer class that will serve as thebackbone of your entire application Your application will literally become an instance of theVisualizer class thanks to code-behind So, first thing you want to do is create the location wherethe class will reside, aka the package In the Navigator panel, right-click, choose New ➤Folder, andname the folder com With the com folder selected, create another new folder and name it almerblank.Now, with the almerblank folder selected, create another new folder named media Once you’redone, you will have created the package where the Visualizer class will live Now, it is time to createyour class, so, with the media folder selected, select New ➤ActionScript Class, name the new classVisualizer, and ensure that it extends Application
Flex Builder will then open the new class file complete with some basic stub code Now would be agood time to import all the necessary classes that you’ll be making use of in this class So, make sureyour import section looks as follows:
package com.almerblank.media {import mx.core.Application;
public class Visualizer extends Application {[Inspectable]
private var _mp3:String;
public function get file():String {return _mp3;
}public function set file(str:String):void {_mp3 = str;
}
Trang 14Next, you want to create private variables for your Sound and SoundChannel objects, variables for theleft and right audio peaks, and a public variable for your Equalizer component For the code-behind
to work, this variable’s name needs to be the same as the ID that you gave your component when youadded it to the main application file Since it’s named eq, this class variable should be named eq Yourvariable declaration section should now look like the following:
public class Visualizer extends Application {[Inspectable]
private var _mp3:String;
public function get file():String{
return _mp3;
}public function set file(str:String):void{
_mp3 = str;
}
private var _sound:Sound;
private var _channel:SoundChannel;
private var _leftStereoBarX:int = 131;
private var _rightStereoBarX:int = 140;
public var eq:Equalizer;
If you’re wondering about the values for _leftStereoBarX and _rightStereoBarX, they’re nothingspecial These values were reached through trial and error Feel free to play around with them toachieve your desired effect With your variables declared, it’s safe to move on to the constructor func-tion Your constructor should already have a call to its superclass, which in this case is Application.You now need to do two things; set the background color of the app and add an event listener for thecreationComplete event Your constructor should look like the following:
public function Visualizer() {super();
this.setStyle("backgroundGradientColors", [0x0033cc, 0x191970]);
addEventListener(FlexEvent.CREATION_COMPLETE,➥
_creationCompleteHandler);
}Here you’ve set the background color to a blue gradient and are delaying any further processing untilFlex fires a creationComplete event for the application This is clearly a matter of preference, as Idon’t like to have a whole lot going on in my constructors Next thing you need to do is create theevent handler for that Flex event This handler will create a listener for the ENTER_FRAME event, initial-ize the Equalizer component, and load and play the chosen MP3 file Following is the code for thatevent handler:
private function _creationCompleteHandler(event:FlexEvent):void {addEventListener(Event.ENTER_FRAME, _onEnterFrame, false, 0, true);
_initEQ();
CHAPTER 18
8962CH18.qxd 11/7/07 10:59 AM Page 452
Trang 15_sound = new Sound(new URLRequest(_mp3));
_channel = _sound.play();
}Next, you want to create your initEQ() method, which is responsible for drawing all the backgroundlines inside of your Equalizer component
private function _initEQ():void {var eqX:uint;
eq.bands.graphics.moveTo(_leftStereoBarX, - eqY);
eq.bands.graphics.lineTo(_leftStereoBarX+8, - eqY);
}for(eqY = 0; eqY < 60; eqY +=2) {eq.bands.graphics.moveTo(_rightStereoBarX, - eqY);
eq.bands.graphics.lineTo(_rightStereoBarX+8, - eqY);
}}
First, you declare two variables, eqX and eqY, that will be used as x- and y-coordinates when you start
drawing your lines The third line of code is where you define the characteristics of your drawing cil It also demonstrates another difference between AS2 and AS3 In ActionScript 2, you draw directly
pen-on your movie clips; but in Actipen-onScript 3, all methods that you can use to create a vector shape arepart of a new Graphics class, and your display objects, like Sprites and MovieClips, have a graphicsproperty, which is a Graphics object So, think of this property as your new sketchpad
The first for loop is responsible for drawing all the EQ background lines The inner for loop foundinside this one is used to determine the bars’ height The += notation just provides the gaps betweenthe bars The other two for loops draw the background lines for the left and right peaks, respectively.With the EQ initialization completed, you can add the event handler for the ENTER_FRAME event, whichwill simply call the drawEQ() method every frame
private function _onEnterFrame(event:Event):void {_drawEQ();
}
Trang 16Now, you’re ready for the drawEQ() method, which is where it really gets magical Here you’ll runcomputeSpectrum on the audio every frame and use the readFloat() method to get the numericaldata necessary to animate your graphics.
private function _drawEQ():void {var singleBand:Number = 0;
//create the byte arrayvar eqBytes:ByteArray = new ByteArray();
//fill it with dataSoundMixer.computeSpectrum(eqBytes);
//clear the graphics object every tripeq.bands.graphics.clear();
eq.bands.graphics.beginFill(0xff6600, 1);
//create the left channel visualizationfor(var i:uint = 0; i < 256; i++) {singleBand += eqBytes.readFloat()*2;
if(i%10==0 && i > 0 && i != 10) {for(var a:uint = 0; a < singleBand; a++){
eq.bands.graphics.beginFill(0xff6600, a/4);
eq.bands.graphics.drawRect(i/2, -(a*2), 4, 2);
}singleBand = 0;
}if(i == 10){
singleBand = 0;
}}//draw the stereo barsfor(a = 0; a < _channel.leftPeak*20; a++) {eq.bands.graphics.beginFill(0x66CC00, a/10);
eq.bands.graphics.drawRect(_leftStereoBarX, -(a*2), 8, 5);
}for(a = 0; a < _channel.rightPeak*20; a++) {eq.bands.graphics.beginFill(0x66CC00, a/10);
eq.bands.graphics.drawRect(_rightStereoBarX, -(a*2), 8, 5);
}eq.bands.graphics.endFill();
}CHAPTER 18
8962CH18.qxd 11/7/07 10:59 AM Page 454
Trang 17In this method, you define two variables, singleBand and eqBytes singleBand deals with each vidual EQ bar, and eqBytes is the ByteArray that is used to store the data retrieved withcomputeSpectrum() The for loops in this method are very similar to the ones from initEQ() Theyare responsible for drawing the EQ bars and peak bars Instead of drawing lines, here you’re drawingrectangular fills.
indi-That completes the Visualizer class All that’s left to do is convert the main application file from aninstance of the Application class to an instance of the Visualizer class First, add a new namespace
to the main tag that points to the package that Visualizer lives in, and then add a file property andset its value to the URL where your MP3 is located Your modified application file should appear asfollows:
<?xml version="1.0" encoding="utf-8"?>
<almerblank:Visualizerxmlns:mx="http://www.adobe.com/2006/mxml"
You can now run the application to see what it looks like by choosing Run ➤Run, clicking the Runicon
on the toolbar, or pressing Ctrl+Enter (Windows) or Cmd+Enter (OSX)
Summary
In this chapter, I covered one method of building an audio visualizer in Flex I shared with you some ofthe differences between accomplishing this task in Flex vs older versions of Flash I also explored thetwo ActionScript classes that allow you to easily create these visualizations without the use of third-party tools You have many more options available to you like creating waveform analyses, and soforth, and with the power of ActionScript 3 behind you, the sky’s the limit Now, it’s up to you to takewhat you’ve learned, extend it, and create some truly amazing visual effects
Trang 188962APX.qxd 11/7/07 11:05 AM Page 456
Trang 19As if Flex 2 wasn’t groundbreaking enough, Adobe has raised the bar even higherwith the next release of the Flex framework Chock-full of new development-enhancingfeatures, Flex 3 promises to change the way we all develop Rich Internet Applications(RIAs) Some of the improvements that Flex 3 introduces are improved designer anddeveloper workflow, code enhancements, component and Software DevelopmentKit (SDK) enhancements, and smaller SWF sizes.
In this chapter, I’ll cover what’s different in Flex 3, the Flash-Flex Integration Kit, andwhat open sourcing Flex means
Designer/Developer workflow
Flex 3 introduces many enhancements that aid in the workflow between developersand designers as well as improves skinning of all aspects of a Flex app Some of thoseenhancements include the new Skin Importer and CSS outlines
THE EVOLVING FLEX SCENE
By Hasan Otuome
Appendix
Trang 20Skin Importer
With the new Skin Importer, you can select afolder of bitmaps or a SWF or SWC file and importthem into a Flex project The Import wizard willtake care of mapping your assets to skin-able ele-ments in the Flex 3 SDK To import a folder ofbitmaps, follow these steps:
1. Select File ➤Import
2. Select Skin Artwork from the Flex importcategory, as shown in Figure A-1, and click
Figure A-1 Selecting Skin Artwork
Figure A-2 Choosing source and destination folders
8962APX.qxd 11/7/07 11:05 AM Page 458
Trang 21Figure A-3 Selecting the skins to import and setting their style and part names
CSS outlines
I really appreciate the CSS outlines feature, as I personally try to keep all of my styling information inexternal CSS files With this feature, I can traverse my CSS document and find a style definition quicklyand easily just as I have grown accustomed to doing in code view with my MXML and ActionScriptfiles From CSS outline view (see Figure A-4), when I select a style property, Flex 3 automatically navi-gates to that property, as Figures A-5 and A-6 illustrate
Trang 22Figure A-4 CSS outline view
Figure A-5 Choosing a style property
APPENDIX
8962APX.qxd 11/7/07 11:05 AM Page 460
Trang 23Figure A-6 Flex 3 automatically navigates to the selected style property.
of the views After I completed the component, I realized I wanted to change the name of the ponent, but I didn’t want to go through the chore of opening up all of the various files that made upthe component or used the component—enter refactoring To refactor my custom componentthroughout the project, I chose the class to refactor and then specified a new name, as illustrated inFigures A-7 and A-8 Figures A-9 and A-10 show the updated MXML and ActionScript after refactoring
Trang 24com-Figure A-7 Choosing the class to refactor
Figure A-8 Choosing the new class name
APPENDIX
8962APX.qxd 11/7/07 11:05 AM Page 462
Trang 25Figure A-9 MXML updated after refactoring
Figure A-10 ActionScript updated after refactoring
Trang 26Class outlines
The outline view (see Figure A-11) now includes supportfor imports, so you can easily explore and develop mas-sively large projects with ease when you combine thiswith the code search and code hints/completion fea-tures I find myself using outline view a lot when a classcontains a couple thousand lines of code and I need tofind an import, property, or method quickly
Code search
Flex 3 now includes a global search feature I cannotbegin to express how useful this feature is While you’redeveloping your project, select a property or methodname and press Ctrl+G (Windows) or Cmd+G (OSX) to search for all instances of that property ormethod in your project Figure A-12 shows what the Searchresults panel will look like after perform-ing a global search
Figure A-12 Global search results panel
APPENDIX
Figure A-11 Class outlines
8962APX.qxd 11/7/07 11:05 AM Page 464
Trang 27Multiple SDKs
With multiple SDK support, you can use Flex Builder 3 to develop and support not only your Flex 3apps, but also your legacy 2.0.1 apps as well And, when you’re ready, you can easily update your proj-ect to use a different SDK version (see Figure A-13) You can even customize the SDK and use yourcustom SDK across all of your projects That’s a pretty cool advancement, because that custom SDKcan even be shared across teams, and the projects using those settings will just work
Figure A-13 Switching Flex SDKs for a project