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):

Get Adobe Flash player 10.1 Beta

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.<Shape> = new Vector.<Shape>(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:

Get Adobe Flash player

27 Comments »

  1. Sinbu says:

    Can you please post the example as a swf? I can’t compile right now, but would like to see how it works. Thx

  2. Thor says:

    Can you tell me where I can download the flash sdk to compile this, I dont have the events.SampleDataEvent class.
    I am using eclipse and flex builder 3.

  3. Devon O. says:

    Hey, Thor, I used the 3.5 Flex SDK and the new Global SWC, that you can download from the 10.1 player page: http://labs.adobe.com/technologies/flashplayer10/ (oh, and FlashDevelop :) )

  4. [...] to Andre Michelle’s shared work on pitching MP3s and Devon Wolfgang’s microphone code example I was able to get the above up and [...]

  5. Thor says:

    Thanks for that, I forgot about the new Global SWC.
    I am having another rather annoying problem now, everything is working except the eventlistner is just not being called
    mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler)

    I have checked that the mic is not muted, and have tried with loopback both on and off, but it never gets called.
    What am I doing wrong? can you post a single mxml file for me to try?
    I am using flex builder 3 and eclipse 3 with flex sdk3.5

  6. Thor says:

    OK, as soon as you post something it works …

    Sorry for the post, but I have just tried it on firefox, chrome and it works fine, but it doesnt work on IE8 on my development machine for some reason. It works on IE8 on a different machine when I post it on the web.

  7. Devon O. says:

    Glad you got it (somewhat) sorted. Very strange it doesn’t work in IE8 on one machine, but does on another. But I guess I’ve seen stranger things..

    Thanks for the coffee!

    d.

  8. knuckfubuck says:

    Does this work without playing back the sound that is coming in? I’d like to computeSpectrum of the mic input but I don’t want to have to playback and double up the sound.

  9. Devon O. says:

    Hey knuck, You can actually play around with the bytearray returned from the Microphone directly. In the example above you can just use the _micBytes bytearray instance in the soundSampleDataHandler() method and not write them into a new bytearray or play the sound. The drawback to this is that instead of 512 bytes (256 left/right) you get 8192 bytes and they are not nice clean normalized values.

  10. David Law says:

    I would like to capture a few seconds of voice and send it back to my web server in the WAV format. Is that possible? Do I need a WAV encoder? Any help is much appreciated!

  11. Devon O. says:

    Hey David, not really sure how you’d get the data back to your web server, but it shouldn’t be impossible.. There’s a nice article on the adobe developer site about recording sound snippets in AIR: http://www.adobe.com/devnet/air/flex/articles/using_mic_api.html And Didier Brun did an AIR to mp3 app using AIR’s new access to native processes and LAME: http://www.bytearray.org/?p=1142 Those would be the places I’d start anyway.

    Good luck

  12. David Law says:

    Thank you, Devon. The first link seems to provide what I need. I’ll report back if I manage to get it work.

  13. Devon O. says:

    Cool. I might check it out this weekend if I have some time and see what I can come up with.

  14. [...] a previous post, “Digging into the Microphone in Flash Player 10.1″, reader David Law asked in the comments how it would be possible to save .wav files to the server. [...]

  15. David Law says:

    Just to update. I have done it with the help of the article below:
    http://www.adobe.com/devnet/air/flex/articles/using_mic_api.html

    which was kindly pointed out by Devon. Thanks!

  16. Jim Andrews says:

    I have a question. Does it require CS5 if you compile in the Flash IDE?

    I installed the Flash Player 10.1 and I see it works in the browser. But when I compile it in Flash Pro CS4 it doesn’t work. Guess I need Flash Pro CS5?

  17. Devon O. says:

    Hey, Jim. The main thing is that you have to be able to compile to the 10.1 Flash Player. Obviously Flash Pro CS4 can’t do that. So you can use Flash Pro CS5 or you can use the Flex 3.5 or Flex 4.0 SDK (when I wrote this post, I was using the Flex 3.5 SDK and the FlashDevelop IDE).

  18. [...] can see this capability in http://blog.onebyonedesign.com/?p=416 . This piece requires Flash Player 10.1 or later–10.1 is not released yet, as of this [...]

  19. Vahe Tomas says:

    Hi All,

    I have a question I would like to develop a WEB Flash application which records the voice from user and saves it to user local file. I did it with Adobe Air but how I can transform it to WEB.

  20. Vahe Tomas says:

    Thanks a lot, now it works quite well :)

  21. Thor says:

    Computing the spectrum of the mic input.

    Hi,
    I notice that someone else has talked about computing the spectrum without playing it back, but I don’t quite understand the response.
    How can you use the compute spec on the mic input without playing it back? Anything I try just gives zeros unless I actually play the sound back.

    Thanks
    Thor

  22. Devon O. says:

    Hey Thor, I don’t believe you can use the computeSpectrum method on the raw microphone bytes (though I may be wrong), but you can access them without playing the sound back by going straight into the bytearray holding the microphone data. In the above script, the bytearray _micBytes holds the raw microphone data. You can dig into that bytearray without first writing them into a _soundbytes array and playing that back. The _micBytes bytearray can get messy though, so be careful of that.

  23. Thor says:

    Hi,
    Thanks for the reply, I should have made it a bit clearer.
    I have done a lot of successful processing on the mic data, and have managed to access the byteArray etc.

    The reason I want to use computeSpectrum is that it has a built in fft (spectrum calculator) that doesn’t seem to be anywhere else in flex. Of course I could write my own fft/spectrum function, but that would take time, and run much slower than the built in one. I want to use the computeSpectrum function if at all possible, but just playing the sound back to get the spectrum isn’t acceptable as the user of my software would get horribly confused as to why the speech is being played back to them at that time.
    (It is speech recognition/language teaching software and sometimes you don’t want to play back what they said, just analyse it)

    If adobe is smart enough to make a spectrum function, but stupid enough so it can’t be used sensibly then I will be a bit annoyed …

    Is it not possible to just call computeSpectrum on given array, only the currently playing output sound?

    It is very difficult writing speech recognition code in flex, and it runs very slowly, so anything to speed it up is very helpful.

    Thanks
    Thor

  24. Devon O. says:

    Hi Thor,

    I’ve never seen anyone using computeSpectrum on a ‘non playing’ sound – and seeing as how it’s the SoundChannel rather than the Sound object itself that calls the method, I doubt that it is possible. Thinking off the top of my head, it may be somehow possible to load a bytearray into a sound instance, then use extract() to get cleaner data. Other than that, there may be something out there created in pixelbender or alchemy that could quickly and efficiently normalize a large bytearray. If I run across anything, I’ll post it, but don’t know of any way right this moment.

    d.

  25. Dennis S. says:

    I’ve made a Visualizer without playing the samples back.
    Just operrated on the raw microphone output.

    http://www.swfcabin.com/open/1282119401

RSS feed for comments on this post. / TrackBack URI

Leave a Reply

Devon O. Wolfgang

Technical Reviewer of “The Essential Guide to Flash CS4 AIR Development”

Contributing Author of “Flash AS3 for Interactive Agencies”

Senior Software Developer in Dublin, Ireland

Portfolio

Bayer Pixel Bender Filter

Bayer Mosaic Filter in Pixel Bender


Now, seeing as how I’ve been trying to learn some Pixel Bender coding lately[...]

Liquitext

Liquid Text Effect


Haven’t been too active around here lately due to a major on going project at work lately as well as the fact that my wife and I are in the slow process of moving homes. Really, the only free time it seems I have these days is during the lunch hour. So, over the past two days, I came up with this fun little toy during lunches[...]

Google’s Text To Speech Engine in Flash

I’m not sure how I managed to miss this, but I just happened to run across a ‘new’ (well, newish), albeit still unofficial, offering of Google today: text-to-speech. You can see what few details there are on this Techcrunch post. Basically, it just boils down to this though – you send your phrase to be [...]

Quick Sound Effects Generator


Need some beeps, boops, or bops, to go with your UI or games [...]

Quick QuickBox2D Tip II – Collision Detection

Custom collision detection/handling in QuickBox2D [...]

None of This Runs Eternal


No Flash/Actionscript stuff here. Just me rambling about the upcoming Current 93 concert [...]

Playing Around with the New UndoManager

Included in the Flex 4.0 SDK and the, just released, Flash Professional CS5 lies a new hidden little gem of a class: flashx.undo.UndoManager (although the Flex 4.0 SDK’s been out for awhile, I have to admit I didn’t even notice this until I installed Flash CS5 and started poking around the documentation looking for new [...]

Making Waves

In a previous post, “Digging into the Microphone in Flash Player 10.1″, reader David Law asked in the comments how it would be possible to save .wav files to the server. I wasn’t sure right offhand, but thought I’d spend my lunch hour yesterday looking into it. Well, after reading this quick tutorial on Adobe [...]

Some Drawing Fun and a Bad Movie You’ll Never See

Earlier today, Dave Gillem posted a link on Facebook to an incredible Processing based drawing application. Thought I’d have a go at reproducing something similar in Flash. Well, I failed miserably, but the results were still interesting enough to check out. You can play around with it below. Just mouse down to draw in the [...]

Animating Bezier Curves


The other day I got the notion in my head that I wanted to draw some bezier curves in an animated fashion. I’m sure this has been done a million times before, but sometimes reinventing the wheel can be a good learning experience [...]

My God, It’s Full of Stars…


Just a quick little thing I got an idea for (i.e. pretty much ripped off) while browsing Processing examples.

Another Year, Another Look

As a few folks may have noticed, the blog is looking a little bit different as of today [...]

The Webcam Warholizer


Just a little bit of quick Friday fun with webcam and bitmapata…

More With the JiglibFlash Terrain

Playing around a bit more with the animated JiglibFlash terrain idea from my last post, I wanted to see how it would work in conjunction with a webcam. So, needless to say, you’ll need a webcam to check out the results below.

Rockin and Rollin with the JiglibFlash Terrain


Finally got the chance to play around with the new JiglibFlash height map terrain, today, and have to say I am very impressed [...]