One By One Design

Digging into the Microphone in Flash Player 10.1

One of the big (well, maybe it wasn’t all that big, but it was interesting) announcements of the 10.1 Flash Player was its ability to access detailed sound data from the microphone in the same way you can access mp3 data now. Until now, microphone access has been limited to volume. With the 10.1 player though, you can extract a bytearray of 512 sound samples just as you can from an mp3 file.

Generally speaking, the Microphone class, like the Sound class, now listens for the SampleDataEvent.SAMPLE_DATA event. When this is triggered, the event’s data property will hold a bytearray of 8192 samples. Those samples can then be “read into” a sound instance (similar to the way dynamic sounds are created) and the sound instance played. At that point, you can use the good ol’ SoundMixer.computeSpectrum() method to read the current sound samples into another bytearray and do with them as thou wilt.

Below is a quick example using a 3d grid of Papervision3D spheres. Just click to get started then speak/sing/whistle/holler into your mic (of course, you’ll need the 10.1 player installed and you’ll have to allow access to the microphone):

[kml_flashembed publishmethod=”static” fversion=”10.1.0″ movie=”http://blog.onebyonedesign.com/wp-content/uploads/2010/01/spheres.swf” width=”550″ height=”450″ targetclass=”flashmovie”]

Get Adobe Flash player 10.1 Beta

[/kml_flashembed]

Seeing as how there doesn’t seem to be any documentation out there for doing this yet, for anyone interested, here’s a very basic example to play around with:

package {

	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.SampleDataEvent;
	import flash.media.Microphone;
	import flash.media.Sound;
	import flash.media.SoundMixer;
	import flash.utils.ByteArray;

	/**
	 * Simple Microphone test for Flash Player 10.1
	 * @author Devon O.
	 */

	[SWF(width='550', height='450', backgroundColor='#000000', frameRate='40')]
	public class Basic extends Sprite {

		// sound
		private var _soundBytes:ByteArray = new ByteArray();
		private var _micBytes:ByteArray;
		private var _micSound:Sound;
		private var _lines:Vector. = new Vector.(512, true);

		private var _ctr:int;

		public function Basic():void {
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}

		private function init(event:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);

			initEqualizer();
			initMic();
			initSound();

			addEventListener(Event.ENTER_FRAME, drawLines);
		}

		private function initEqualizer():void {
			var holder:Sprite = new Sprite();
			for (var i:int = 0; i < 512; i++) {
				var line:Shape = new Shape();
				with(line.graphics) {
					beginFill(0xFFFFFF);
					drawRect(0, -300, 1, 300);
					endFill();
				}
				line.x = i;
				line.scaleY = 0;
				holder.addChild(line);
				_lines[i] = line;
			}
			holder.y = 400;
			holder.x = stage.stageWidth * .5 - holder.width * .5;
			addChild(holder);
		}		

		private function initMic():void {
			var mic:Microphone = Microphone.getMicrophone();
            if ( mic ) {
                mic.setLoopBack(false);
                mic.rate = 44;
		mic.gain = 60;
                mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
            }
            else {
               // no mic
            }
		}

		private function micSampleDataHandler(event:SampleDataEvent) :void {
            _micBytes = event.data;
			_micSound.play();
        }

		private function initSound():void {
			_micSound = new Sound();
			_micSound.addEventListener(SampleDataEvent.SAMPLE_DATA, soundSampleDataHandler);
		}

		private function soundSampleDataHandler(event:SampleDataEvent):void {
			for (var i:int = 0; i < 8192 && _micBytes.bytesAvailable > 0; i++) {
				var sample:Number = _micBytes.readFloat();
				event.data.writeFloat(sample);
				event.data.writeFloat(sample);
			}
		}

		private function drawLines(event:Event):void {
			SoundMixer.computeSpectrum(_soundBytes, true);
			if (_soundBytes.bytesAvailable) {
				_ctr = 0;
				while (++_ctr < 512) {
					_lines[_ctr].scaleY = _soundBytes.readFloat();
				}
			}
		}
	}
}

EDIT:
Here is the above code compiled to .swf form, for those who'd like to check it out:

[kml_flashembed publishmethod="static" fversion="10.1.0" movie="http://blog.onebyonedesign.com/wp-content/uploads/2010/01/basic.swf" width="550" height="450" targetclass="flashmovie"]

Get Adobe Flash player

[/kml_flashembed]

Posted by

Post a comment

Your email address will not be published. Required fields are marked *