Click to switch between playing and recording.
I know there are better ways to do what I did here, but this was just hacked up pretty quickly, and meant to show how it's done.
I tried to comment pretty well, but I know it's not exactly pretty/reusable code; thus, if you have questions just ask.
//Originally written by NME a.k.a. Anthony R Pace
package {
import flash.events.StatusEvent;
import flash.text.TextField;
import flash.geom.Rectangle;
import flash.utils.ByteArray;
import flash.events.SampleDataEvent;
import flash.media.Microphone;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.media.Sound;
public class PlayRecordShow0_1 extends Sprite {
public var bmp:Bitmap = new Bitmap(new BitmapData(512,stage.stageHeight,false,0x3CD8FF)), //the bitmap that will be used to represent the time domain
mic:Microphone = Microphone.getMicrophone(),
sn:Number, //sample value at n, or s[n]
sampleRect:Rectangle = new Rectangle(0,0,4,20),//the spot on the line that represents the sample at a given point s[n]
A:Number = ((stage.stageHeight-sampleRect.height)/2),//'A' for amplitude factor. In this case (stageHeight - sampeRect.height)/2
recording:ByteArray = new ByteArray(),
sound:Sound = new Sound(),
isRecording:Boolean=true,
bafg:ByteArray= new ByteArray(),// temp byte array for graph
tf:TextField = new TextField();
public function drawGraph(ba:ByteArray):void{
var loopMax:Number = ba.length/4;//updated from fork, because bug was annoying.
if (loopMax>512){
loopMax = 512;
}
ba.position = 0;
bmp.bitmapData.lock();
bmp.bitmapData.fillRect(bmp.bitmapData.rect,0x3CD8FF);
for (var n:int = 0; n<loopMax; ++n){
sn = ba.readFloat();//reads 4 bytes = 32 bit floating point sample value
sampleRect.x = n-2;// as the width of the sample rect is 4, and we want 2 on each side. We could constraine this within bounds but I'm not going to.
sampleRect.y = A-sn*A; //In this case we are using A as the offest and the Amplitude; thus, YOffset - Amplitude*(the PCMvalue for S[n])
bmp.bitmapData.fillRect(sampleRect,0xd7f7ff);
}
bmp.bitmapData.unlock();
}
public function micSDEH(e:SampleDataEvent):void{//sample data event handler
e.data.position = 0;
recording.writeBytes(e.data);
drawGraph(e.data);
}
public function playBackSDEH(e:SampleDataEvent):void{
var n:int = 0,
floatsLeft:uint =(recording.length-recording.position)/4,
emptySpaceCount:int = 0,//float is at 2048/512 = 4, so that means 3 out of 4 will be empty, so we need to fill the empty space
lastValue:Number,//oh, and keep in mind that for stereo, you need to take my mono data and convert it to Left,Right,L,R,L,R,L,R,....
qMDiff:Number, //will be used to hold a quarter of the difference in magnitude, between x and x + 1
loopMax:int,
ed:ByteArray = e.data;
ed.position = 0;
bafg.position = 0;
if (floatsLeft>2048){
loopMax = 2048;
}else{
loopMax = floatsLeft;
}
while (n<loopMax){//just filling in the gaps with lastValue using knowledge of empty space for now
if (emptySpaceCount==0){
lastValue = recording.readFloat();
ed.writeFloat(lastValue);
bafg.writeFloat(lastValue);
emptySpaceCount = 3;
ed.writeFloat(lastValue);
qMDiff = (recording.readFloat() - lastValue) * 0.25;
recording.position -= 4;
}else{
lastValue += qMDiff;
ed.writeFloat(lastValue);
ed.writeFloat(lastValue);
--emptySpaceCount;
}
++n;
}
drawGraph(bafg);
if(floatsLeft<=2048){
startRecording();
}
}
public function startRecording():void{
sound.removeEventListener(SampleDataEvent.SAMPLE_DATA,playBackSDEH,false);
recording.clear();
mic.addEventListener(SampleDataEvent.SAMPLE_DATA,micSDEH,false);
isRecording = true;
echo('Status: Recording Audio --- Left click to Stop recording and Start playback');
}
public function startPlaying():void{
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA,micSDEH,false);
recording.position = 0;
sound.addEventListener(SampleDataEvent.SAMPLE_DATA,playBackSDEH,false);
sound.play(0);
isRecording = false;
echo('Status: Playing Audio --- Left click to Stop playback and Start recording');
}
public function mch(e:MouseEvent):void{
if (isRecording == true && recording.length>4) {
startPlaying();
}else {
startRecording();
}
}
public function micStatusEH(e:StatusEvent):void{
mic.removeEventListener(StatusEvent.STATUS, micStatusEH,false);
if (e.code == "Microphone.Unmuted"){
stage.addEventListener(MouseEvent.CLICK, mch,false);
echo('Status: Recording Audio --- Left click to Stop recording and Start playback');
}else if (e.code == "Microphone.Muted") {
echo("Status: Access to the Microphone was Denied :> Please Reload.");
}
}
public function echo(s:String = ''):void{tf.text = s; tf.width = tf.textWidth + 4;}
public function PlayRecordShow0_1():void{
stage.addChild(bmp);//make the bitmap visible on the display list;
stage.addChild(tf);//add tf advise to state if recording
echo('Status: Waiting for Microphone access to be granted');
mic.rate = 11;// sets N, the sample frequency to 11025
mic.setSilenceLevel(0);//setting this to 0 makes it so you hear all activity;
mic.addEventListener(SampleDataEvent.SAMPLE_DATA,micSDEH,false);// call the micSDEH function if the mic hears audio;
mic.addEventListener(StatusEvent.STATUS, micStatusEH,false);//mic status event handler
}
}
}