For the fade to sound smooth, it has to be incremented on a per-sample basis, inside your synthesis loop. A tween engine may update many times a second, but your ear can still hear the changes as a click.
In your sampleData event handler, you will have to multiply the individual samples by a volume modifier, with the range of 0 to 1, incrementing for every sample.
To quickly fade in the sound, start by setting the volume to 0, and adding a small value to it for each sample, until it reaches 1.0. You can later expand this into a more complex envelope controller.
This is a rough example of what you might start with:
for( i = 0; i < length; i++ ) {
_count++;
factor = _frequency * Math.PI * 2 / 4400;
volume += 1.0 / 4400;
if( volume > 1.0 ) volume = 1.0; //don't actually do it like this, ok?
n = Math.sin( (_count) * factor ) * volume;
_buffer.writeFloat(n);
_buffer.writeFloat(n);
}
NOTE: I haven't tested this snippet, nor would I recommend using it for production. It's just to show you roughly what I mean.
Another technique that may work for you is to put an ease / delay on the volume. Use a volumeEase variable that always 'chases' the target volume at a certain speed. This will prevent clicks when changing volumes and can be used to make longer envelopes:
var volume:Number = 0; // the target volume
var volumeEase:Number = 1.0; // the value to use in the signal math
var volumeEaseSpeed:Number = 0.001; // tweak this to control responsiveness of ease
for( i = 0; i < length; i++ ) {
_count++;
// bring the volumeEase closer to the target:
volumeEase += ( volume - volumeEase ) * volumeEaseSpeed;
factor = _frequency * Math.PI * 2 / 4400;
//use volumeEase in the maths, rather than 'volume':
n = Math.sin( (_count) * factor ) * volumeEase;
_buffer.writeFloat(n);
_buffer.writeFloat(n);
}
If you wanted to, you could just use a linear interpolation, and just go 'toward' the target at a constant speed.
Once again, the snippet is not tested, so you may have to tweak volumeEaseSpeed.