Flash Player 10 Sound API changes, SampleData and SampleDataEvent

With the new beta 2 version of Flash Player 10 the Sound API has changed a bit.

Most of the changes is very straight forward and only renaming of some methods, events and properties:

SamplesCallbackEvent is now SampleDataEvent
samplesCallback is now sampleData or Event.SAMPLE_DATA
Instead of accessing Sound.samplesCallbackData to write to the output buffer one now use the SampleDataEvent.data.

Tinic Uro has updated his examples if you like to look at some example code with the new API.

So basically very straight forward changes but there was one thing that I managed to waste a bit of time on. This is what the documentation say about the buffer size for the SampleDataEvent:

Provide between 2048 and 8192 samples in a SampleDataEvent object. For best performance, provide as many samples as possible. The fewer samples you provide, the more likely it is that clicks and pops will occur during playback. This behaviour can differ on various platforms and can occur in various situations - for example, when resizing the browser. You might write code that works on one platform when you provide only 2048 samples, but that same code might not work as well when run on a different platform. If you require the lowest latency possible, consider making the amount of data user-selectable.

If you provide fewer than 2048 samples, Flash Player plays the remaining samples and then stops the sound as if the end of a sound file was reached, generating a SoundComplete event.

All my code was using a buffer size of less than 2048 and hence did not work any more.
I'm not sure why the available range has been made smaller since it was nice to be able to lower the latency by having a 512 samples buffer.
I guess it is a common problem that Flash developers are a bit irresponsible with the users CPU power and I can understand that they want to avoid the reputation of being a CPU hog, but IMHO it's a bit like if they would have decided that the maximum frame rate should be limited to 20FPS.

Collection of tools and resources for actionscript developers

I have collected some of the tools and resources that I find very useful when developing Actionscript applications that with the exception of one are free and/or open source.
If you are an experienced Actionscript developer you are probably already familiar with most of them, but there might be one of two that you have missed.
And there is probably a lot that I have missed that should be included, so if there is any you think should be placed on the list please give suggestions in the comments.

Actionscript 3.0 migration
Very useful AS2 to AS3 migration reference.

AMFPHP
PHP implementation of the Action Message Format. If you need to transfer large data sets between the server and your Flash application remoting enables you to use native Flash data types which cuts down on time and resources needed to parse and transfer data.

AS3 Optimizations
Collection of useful AS3 optimization suggestions and links.

ASUnit
Unit test framework for Actionscript.

Charles
Web debugging proxy which I find indispensable for inspecting traffic between server and swf files.
Has support for remoting (AMF0 and AMF3) and can do bandwidth throttling.
The only resource listed here that is not free, but definitely worth a mention here due to being extremely useful.
You can try the 30 day demo and see if you think it's worth the asking price compared to for example Fiddler which is a free alternative.

FlashDevelop
My favourite Actionscript editor. IMO the code completion is much better than FlexBuilder and it comes with MTASC and SWFMill to create AS2 swf's and integrates with MXMLC for AS3 projects so it very easy to get started using it as an all-in-one solution for developing Actionscript applications.

FlashTracer
Simple but very useful Firefox extension that enables you to view trace output in your web browser which is very handy when you need to debug an application while it's running on the server.

GAIA Framework
I have to admit that I haven't actually tried it out properly yet since it hasn't been applicable for the kind of projects I have been working on lately, but I had a quick look at it and it really seems like a very neat framework for certain types of projects.

MinimalComps
A neat little AS3 component set from bit101. As the name suggests it's very minimal but usually I find full fledged architectures, like ASWing or the ones that comes with CS3, to be a bit overkill in most cases and it's a great example to study if you like to make your own AS3 components.
They are drawn from code and hence have a tiny footprint but are not skinning friendly.
For AS2 I have mostly been using Bit101's commercial
BitComponentSet
and I would love to see a similar set for AS3 but for now MinimalComps has come in very handy for simple little apps and prototyping.

Popforge
Open source AS3 audio library started by Andre Michelle and Joa Ebert.
If you want to be able to generate or process sound without using Flash Player 10 it will help you do that, but it's also possible to use the generators and processors with the new samplesCallbackEvent functionality of FP10 as well.
So if you are interested in Flash audio it certainly very worthwhile to check out.

Red5
Open source Flash server for media streaming and remoting. A very good free alternative to Flash Media Server.

SWFAddress
To implement deeplinking and back button functionality when possible on Flash projects have been a concern of mine for quite a while, both due to usability and SEO concerns. Back in 2005 I developed my own solution, but it was something I quickly hacked together and although functioning and better than anything I could find at that time I always thought it could be a lot neater and was hoping someone would step up and create a package that could gain popularity with a lot of developers.
Hence I was very happy when SWFAddress came along with a package that is solid, neat and easy to implement.

SWFObject
I guess there is not much to say here. You're probably familiar with SWFObject already, but in case you are not just get it and start using it to embed you swf with it now.
Not only is it a very convenient way of adding version detection, providing alternate content and passing on query parameters to the swf but it also has the benefit of avoiding the IE issues with activation of embedded content.

TortoiseSVN
Easy to use version control software for Windows.

TweenMax
The fastest tweening engine for AS3 with very neat syntax and always my first choice for tweening duties along with it's smaller siblings TweenLite and TweenFilterLite.
I have come across scenarios where it doesn't behave as expected (I guess due to the fact that it doesn't search for overlapping tween properties to overwrite only those properties) and then I stick with Tweener which has very respectable speed and equally neat syntax.
EDIT:Jack Doyle, the developer behind TweenMax, got in touch and had a look at my code to find the reason why it did not behave the same as Tweener. Basically TweenMax will not search through existing tweens to check what properties to overwrite and instead by initializing a new tween of one property you stop existing tweens of other properties. This is done to optimize speed but means that your code might have to be slightly different compared to other tweening engines.
In my case it was simply a matter of adding the property that gets overwritten to the new tween and issue was solved.

Tweaking the samplesCallbackEvent loop

Playing around with the new Flash player 10 audio processing functionality the need for optimization becomes very apparent when you want to apply effects to several tracks of audio.

With a sample rate of 44100 and a dozen stereo tracks we are talking over a million samples to be processed per second where each process you apply will have probably at least some 30 operations. All of a sudden the great performance of AVM2 becomes quite limiting.

So it's important to squeeze out every drop of performance you can by optimizing the code.
First of all I have been benchmarking the performance of running code inside the processing loop, in a function, in an external class and inside a loaded swf (would have been neat for the possibility to plug in effects without recompiling the main swf).

The code I used for testing was to process a value and return it like this (obviously without function enclosure when doing the processing in the local scope):


public function calculate(num:Number):Number
{
	return num * 1.01;
}

The time needed in ms when calling the function 10 000 000 times:

  • Locally: 46
  • Calling a function in the same class: 213
  • Calling a function in a separate class: 213
  • Calling a function in an externally loaded swf: 2347

Not so surprising results.
Having processing code in an external swf is obviously not an option. I tried with both simply sticking a function in the swf or in a class which I retrieved by applicationDomain.getDefinition and both methods performed equally bad.
Doing processing locally instead of in a separate function or class is a lot faster, but obviously that could easily becomes very cumbersome and ugly.
At least there is nothing lost on having the function in a separate class compared to having a function in the same class.

Something that does surprise me a bit is that when just calling the function once and having the loop inside the function instead the resulting time was 75ms.
That's about 30 ms added for just one function call so it seems like the first call is a lot more expensive.

One would think that the conclusion is that the best approach when processing audio if one like to avoid placing the code inside the samplesCallbackEvent loop seems to be calling the processing code once and then iterate over the size of the buffer in the class for the effect.
This is exactly what I was suggested by Spender when I posted a 3-band EQ example.

The problem there and why my attempt at implementing his suggestion failed at making an improvement is that reading and writing floats in a ByteArray is slower than the function calls.
Testing to writeFloat 10 000 000 times to then read loop through them to read them again takes 1727 ms. So compared with the 213 ms doing the same amount of function calls it's clear that function calls actually is comparatively cheap. A Vector fares a bit better then the ByteArray with 1239 ms.

So the optimal approach seems to be to only do samples.readFloat once then use the returned value doing function calls for each process you like to apply before you do samplesCallbackData.writeFloat

Simple 3-band EQ with Flash Player 10

Yes, a Flash equalizer. We all heard it mentioned before...for some reason the word equalizer has been adopted to mean spectral analyser when mentioned along with Flash.

 

An equalizer will process the sound boosting or attenuating frequencies while a spectral analyser will only show you the spectral content of the audio.
Now with the new functionality of Flash Player 10 I hope this means that people will call things by their correct name since we now will have applications with both analysers and equalizers.

 

So with that off my chest, here is the code for an actual equalizer.

The algorithm is taken from this c++ snippet on musicdsp.org and might not be the highest fidelity but should be fairly efficient.

 

You can also view this online example. (requires Flash Player 10)

Random thoughts on Vectors and samplesCallbackData

I have had reason to play around with some of the new functionality of Flash Player 10 and the vectors is just awesome.
On top of the benefits of the strict typing they are about 50% faster than Arrays according to my tests.

Being completely new to the concept, how to create multidimensional vectors was not completely obvious since you need to type every dimension when declaring the bottom level dimension:


var v1:Vector.<Vector.<Vector.<int>>>= new Vector.<Vector.<Vector.<int>>>();
var v2:Vector.<Vector.<int>> ;
var v3:Vector.<int>;
for (var i:int = 0; i < 10; i++) {
	v2 = new Vector.<Vector.<int>>();
	for (var ii:int = 0; ii < 10; ii++) {
		v3 = new Vector.<int>();
			for (var iii:int = 0; iii < 10; iii++){
				v3[iii] = iii;
			}
		v2[ii]=v3;
	}
	v1[i]=v2;
}

 

So far I have mostly been experimenting with the new samplesCallbackData to create a little mixer.
It seems like one needs to bypass the mixer in the Flash Player if one want to write to the output buffer because creating several sounds and then doing samplesCallbackData.writeFloat() on them will not work.
Of course each channel doesn't have its own output buffer, so you can only write to the master output.
The problem I'm having with this is that if one would like to have a level meter for each individal track I cannot figure out a way to determine what sample is currently being output.
Here is a simplified version of how I implemented the mixing in the SamplesCallbackEvent handler:


var i:int = 0, l:int = _sounds_vect.lengt;
while (i < l) {
	samples = new ByteArray();
	samples.position = 0;
	snd = _sounds_vect[i];
	snd.extract(samples, _bufferSize);
	_samples_vect[i] = samples;
	_samples_vect[i].position = 0;
	i++;
}
while (c < _bufferSize) {
	left = 0;
	right = 0;
	i = 0;
	while (i < l) {
		valL = _samples_vect[i].readFloat();
		valR = _samples_vect[i].readFloat();
		left += valL;
		right += valR;
		i++;
	}
	valL = left;
	valR = right;
	_out_snd.samplesCallbackData.writeFloat(valL);
	_out_snd.samplesCallbackData.writeFloat(valR);
	c++;
}

So the audio is mixed in chunks the size of the buffer and then written to the buffer using samplesCallbackData.writeFloat().

 

For the main output I can create a level meter using:


_out_chn = new SoundChannel();
_out_chn = _out_snd.play();
function onEnterFrame(e:Event):void {
	_masterSlider.drawLevel(_out_chn.leftPeak, _out_chn.rightPeak);
}

 

But for the individal channels I will never issue a play() and hence cannot find a way to get a really consistently behaving level meter or spectrum.
I'm sure there is some clever way to do it that is escaping me.

 

What I currently do is to get the value in the mixing loop like so:


while (i < l) {
	valL = _samples_vect[i].readFloat();
	valR = _samples_vect[i].readFloat();
	left += valL;
	right += valR;
	if (c == 0){ // tried with (c == _bufferSize - 1) and (c == _bufferSize/2) as well
		_levelR_vect[i] = valL;
		_levelL_vect[i] = valR;
	}
	i++;
}

I then use the _levelL_vect and levelR_vect values in my onEnterFrame handler to draw the bars, but the result is a lot less accurate than what is possible using my_chn.leftPeak and far from satisfactory.
I guess what I would need is a way to be able to tell what sample from the output buffer that is playing a certain moment in time.

 

Apart from that small issue it's great to have the functionality to generate and process audio and I think we will see some very cool applications appearing eventually.

FlashPlayer 10 support in FlashDevelop

A new build of FlashDevelop with support for FlashPlayer 10 was just made available:
http://www.flashdevelop.org/community/viewtopic.php?t=3034

I guess I'm off installing Visual C# Express to compile the thing...

Sound generation in FlashPlayer 10

Finally Flash will have built in ability to access the sound output buffer when using FlashPlayer 10 that just has been released.
Tinic Uro have posted a little information about the implementation.
So no more relying on complicated hacks, this is all the code you will need to generate a sine wave (snipped from Tinics post):


  var sound:Sound = new Sound();
  function sineWavGenerator(event:SamplesCallbackEvent):void {
    for ( var c:int=0; c<1234; c++ ) {
      var sample:Number = Math.sin(
               (Number(c+event.position)/Math.PI/2))*0.25;
      sound.samplesCallbackData.writeFloat(sample);
      sound.samplesCallbackData.writeFloat(sample);
    }
  }
  sound.addEventListener("samplesCallback",sineWavGenerator);
  sound.play();

Stupid keep it simple?

Simplicity, accessibility and content should always be the main focus when you design, at least that's what we are usually told. But are they actually only factors to consider and sometimes they can be somewhat disregarded in favour of other considerations?

Many times when discussing various aspects of graphics or software design I find that a lot of people love to deal in absolutes. They catch on to some idea that might contain a lot of truth and it becomes a mantra that should be obeyed at all times and at all costs.

 

KISS

Keeping it simple is certainly good advice, both when it comes to programming and design.
But this doesn't mean that simplicity always should be the first priority.
For example if we look at desktop applications targeted at professionals a lot of audio and graphics software is very complex. You can't just dive in to 3dsmax or Logic Audio and get immediate results. Sketchup or Reason for sure wins over the pro-end software in terms of simplicity.
But many pros or more dedicated enthusiasts do need more features than the simpler software provide and they are prepared to invest some time studying the applications to discover functionality that will speed up their work flow or improve the results.

With the web people often have little time and patience to figure out a complex interface, so many times simplicity is very important. But it's always a balancing act, and there is not ultimate truth that the simpler the better a website is. The need for simplicity depends a lot in the target audience and intended purpose. If it is a RIA where people will come back and use it many times and are likely to be willing to spend time to overcome the complexity it can be worthwhile adding features that initially may confuse the users somewhat if they are likely to understand it and find it useful after the initial learning curve.

 

Accessibility

Something I hear very often is statements like "excluding even 1% of the visitors should be avoided". Usually this is said when discussing using Javascript or Flash on a web page.
In many cases one can use progressive enhancement and then i think one should try to do so to avoid excluding anyone, but in some cases it's simply not possible.

Let's for example say that you have a e-commerce website that you are considering to implement a RIA where people can design their own product. Doing it in HTML would mean a really tedious process of typing in values in fields and on each change reload the page to see the result.
Of course it's not worth making the experience horrible for 99% just to make sure that the one 1% without the technology needed to access a reasonable implementation should have to suffer.

You simply cannot just count on how many customers you loose because they are not able to use your application, you also have to evaluate how many you will gain by having something that is really usable for the vast majority of visitors.

And lets not even mention where for example youtube would be today if they decided that they cannot rely on any technology that doesn't have 100% coverage.

 

Content is king

Sure the internet is mainly about information and entertainment, but there are examples of successful sites that have hardly no content.
No, I don't count milliondollarhomepage. Despite being successful it's too stupid to prove a point.

But some sites mostly deal with branding and the content is actually not that important.
How many people have visited 2advanced.com because of the content?
Still I would guess it's a very successful site when it comes to achieving it's goals and that it has done a lot to promote their services. Not thanks to the content but almost exclusively due to the looks.

 

While all of these mantras are very important aspects when it comes to design I think it's important to see them as factors rather than absolutes. It's not always easy to evaluate how much complexity your users will appreciate or how much a certain technology can add and compare that to the impact of that to excluding some visitors.
But it's always about trying to find a correct balance and thinking that there is one answer for every scenario is fooling yourself into thinking reality is simpler than it is.

Rumours of the death of Flash have been greatly exaggerated

Recently we have seen a lot of progress with the capabilities of Javascript to leverage the capabilities of HTML to do things that was previously only possible using Flash.
Thanks to for example mootools and jQuery you can now create sites that looks like they are made with Flash with nice tweening animations, and of course AJAX have already for a few years been an option to update the content without reloading the page.
Does this mean that the future of Flash looks bleak?
Somerandomdude seems to think so, and points to some of examples if the impeding demise of Flash. John Resig’s Processing.js and experiments with HTML 5’s video element.

 

First of all, does any of these developments offer improvements over what Flash have been capable of for years?
Maybe if a site that is heavy on information but you might want to jazz it up a bit with some nice transitions.
When it comes to presenting text HTML has some advantages, mainly due to the browser integration.
Using the browsers built in search or select and right click to google a phrase for example.
Usually those advantages are greater than the possibility to embed font outlines with Flash.
But most implementations I have seen of for example slideshows and menus does not offer any advantages what I can see. Implementing them in Javascript still performs worse, gives you less possibilities and makes it less accessible.

 

When it comes to video on the surface I cannot see any reason why a video playback native to the browser would be preferable.
Of course one could argue that since you have a limited choice of compression formats with Flash it would open up to more options there. But to deploy content you will still have to make sure you use a codec that is included with a majority of browsers. It remains to be seen if it will mean much of an improvement in practice, and personally I do think that h264 is quite satisfactory.
All the above is true for the HTML5 audio element as well.

 

Of course the technical merits is only a part of the parameters that decide the acceptance of a technology. There are a lot of developers that really dislike Flash for various reasons and they are just really happy that they now can do the same things as has been possible for a long time with Flash.
The fact that it can be more tedious to implement and performs worse is not as important as various factors like avoiding proprietary formats or using a environment they are already accustomed to.

 

But even if Flash is not necessary to do a lot of things that previously was it's exclusive domain to me it seems like it's constantly gaining acceptance with developers.
Flash is still quite far ahead of the capabilities of DHTML/AJAX and how long will it take before HTML5 is widespread enough to make it a viable option?
Flash is still developing rapidly and the new versions of the plug-in is spreading extremely fast, so by the time HTML5 capable browsers is widespread enough probably 95% will have the Flash 15 plug-in installed.

 

I think the main issue here is the different ways in which Flash and HTML is being developed.
A lot of the hate against Flash is based on the fact that swf is a proprietary format, and even if that is not entirely true any more it's certainly not based on an open standard.
And that what makes it possible for it to stay on the cutting edge, and that's why the capabilities of DHTML, XHTML, Javascript, SVG etc. always is one step behind.
Even if I prefer open standards in theory it just doesn't seem to work as well in practice.
Rather than being impressed how HTML and Javascript is catching up with the capabilities of Flash I'm continuously surprised at how slowly it's happening.

 

I have been fanatic about Flash since I first discovered it in 1999, and I really have trouble being completely neutral even I try. But IMO Flash is not going anywhere. With AS3, AVM2 and FLEX a lot of new possibilities has opened up that DHTML will not be capable of any time soon, like for example decent 3d engines, socket connections and sound synthesis.
Overall I do see a trend though that the web is getting less and less fixated with certain technologies.
On the server side we have seen Python and Ruby gaining acceptance. MS will be trying with Silverlight to present an alternative to Flash and HTML will be able to compete as well.
But it's not a war where anyone has to die...there is certainly room for more than either ASP, perl or PHP on the server and HTML, Shockwave or Flash on the client, which pretty much used to be the case.

SVN version control in Flashdevelop projects

A couple of applications that really have helped my work flow a lot is Flashdevelop and TortoiseSVN.

For those of you not familiar with them Flashdevelop is an actionscript editor that integrates with MTASC or MXMLC compilers and swfmill to include assets into the project.
TortoiseSVN is a version control system which basically is a must on large projects and very handy even on smaller projects even if you are developing alone and just keep the repository on your local machine. TortoiseSVN also comes with a program called SubWCRev which we will use to write information about the current version into a textfile, which is handy so we can load it into our swf to display the current version.

First of all you need to download and install the applications if you don't have them already.

Get Flashdevelop
Get TortoiseSVN

First step is to set up your "repository" and "working copy" directories.
I will not explain that part here since there is already many good guides on that subject, for example this pfd.
It is a little bit of an effort initially but I can assure you it's energy well spent.

 

Now in Flashdevelop select Project->New Project in the menu to create a new AS2 or AS3 project in your working copy directory.
For example say we have created a working copy folder called "E:\_dev\Example", you settings will look like this in the new project dialogue:

flashdevelop new project dialogue

 

Ok, so now we are all set up to actually integrate the SVN with our Flashdevelop project.
First of all create a new text file in your working directory and name it "build.bat".
In it enter the following:

@ECHO OFF

set TORTOISESVN_PATH=C:\Program Files\TortoiseSVN\bin
set CURRENT_PATH=%CD%

"%TORTOISESVN_PATH%\TortoiseProc.exe" /command:commit /path:"%CURRENT_PATH%\*"/logmsgfile:"%CURRENT_PATH%\logmsg.txt" /notempfile /closeonend:3

"%TORTOISESVN_PATH%\SubWCRev.exe" "%CURRENT_PATH%" "%CURRENT_PATH%\version.a" "%CURRENT_PATH%\version.txt"

pause

Make sure that the "TORTOISESVN_PATH" is the same as the one you have installed TortoiseSVN to and save.
Basically what this batch file is doing is first to call TortoiseSVN telling it to commit changes and then calling SubWCRev to take the template for our version text (version.a) and use that to write a file that we will load into our app for displaying the version information (version.txt).

So we need to create a file called version.a containing the following text:

major=0;
minor=1;
build=$WCREV$ ;
date="$WCDATE$" ;

The stuff between the $'s is what will be substituted by SubWCRev.
Here is a complete list of substitution keywords if you like to include more information, but usually the build number is all that I would use.
The major and minor version numbers one have to update by hand, at least to my knowledge.

 

Now in Flashdevelop go Project->Properties and open the "Build" tab.
In the "Post-Build Command Line" type: $(ProjectDir)\build.bat:
flashdevelop build settings
Now you are set up and each time you build in Flashdevelop you will get presented with a screen where you can enter a log message for the change if you like to commit it, or you can choose cancel and the change will not be committed.
If you like to have a default log message for the commit add a logmsg.txt in the working copy directory with the text you like to appear.

 

If you like to display the version information in your swf you have to load the version.txt and display the information. Here is an AS3 example:

package com.blixtsystems.utils {
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	/**
	* Class to display version information
	* @author leo@blixtsystems.com
	*/
	public class ShowVersion {
		private var _owner:Object;
		public function ShowVersion(owner:Object) {
			this._owner = owner;
			loadTxt();
		}
		private function loadTxt():void {
			var loader:URLLoader = new URLLoader();
			configureListeners(loader);
			var request:URLRequest = new URLRequest("version.txt");
			try {
				loader.load(request);
			} catch (error:Error) {
				trace("Unable to load version.txt.");
			}
		}
		private function configureListeners(dispatcher:IEventDispatcher):void {
			dispatcher.addEventListener(Event.COMPLETE, completeHandler);
		}
		private function completeHandler(event:Event):void {
			var loader:URLLoader = URLLoader(event.target);
			this.draw(loader.data);
		}
		private function draw(data:Object):void {
			var a:Array = data.split(";");
			var major:String = a[0].split("=")[1];
			var minor:String = a[1].split("=")[1];
			var build:String = a[2].split("=")[1];

			var tf:TextField = new TextField();
			tf.autoSize = TextFieldAutoSize.LEFT;

			var format:TextFormat = new TextFormat();
			format.font = "Verdana";
			format.color = 0x000000;
			format.size = 10;

			tf.defaultTextFormat = format;
			tf.text = major + "." + minor + "." + build;
			this._owner.addChild(tf);
		}
	}
}

 

That's it, now every time you press F8 in Flashdevelop you will add any altered files to the repository and your swf will reflect the current version number!

Next Page »