website | twitter

Tuesday, May 26, 2009

A complete example of generating a sound in Flash with SampleDataEvent

Flash version 10 has significant feature about audio, SampleDataEvent. Until this version, there was no way to generate a sound wave easily. Some people have tried to do that by rather magical way of how to make actionscript 3 play generated pcm wave data in Flash 9, however, now we have a straightforward API from Flash 10. I think this is a great improvement for hobby programmers who are interested in computer generated music. While it's shame from some perspective. Just this API finally brings us a point where old BASIC and PLAY statement could do a quarter centry ago!

You would find a lot of examples about SampleDataEvent, but some of those are wrong or uncompleted, since I think this API have been changed so often in beta version. And I wrote my version of simplest example for exercise.

There are a couple of tricks you might trap.
  • If you get an error message: "Flex error: type was not found or was not a compile-time constant: SampleDataEvent", you have to specify the Flash version to 10.0.0. Set -target-player option or Flex builder's Project's Properties - ActionScript Compiler - HTML Wrapper
  • Some documentation might use Event.SAMPLE_DATA, but this is not true.
// SineSound.as
// A simple sine sound.
//
// compile option
// mxmlc -target-player 10.0.0 SineSound.as
package {
import flash.display.Sprite;
import flash.events.SampleDataEvent;
import flash.media.Sound;
public class SineSound extends Sprite
{
private var frequency:Number= 440;
private var gain:Number= 0.25;
private var rate:int= 44100;
private var pitch:Number= rate / frequency;
public function SineSound()
{
var s:Sound= new Sound();
s.addEventListener(SampleDataEvent.SAMPLE_DATA, makeWave);
s.play();
}
private function makeWave(event:SampleDataEvent):void {
for (var i:int= 0; i < 8192; i++) {
var pos:int= i + event.position;
var phase:Number= (pos % pitch) / pitch; // 0 <= phase < pitch
var v:Number= Math.sin(2 * Math.PI * phase) * gain;
// var v:Number= phase < 0.5 ? gain : -gain; // Rectangle Wave
event.data.writeFloat(v);
event.data.writeFloat(v);
}
}
}
}
view raw SineSound.as hosted with ❤ by GitHub
Generated SWF file: http://languagegame.org/pub/SineSound.swf
 
Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.