title: AS3 Mic recorder - clear out old data
body: <p>I'm using this excellent class from <a href="http://www.jordansthings.com/blog/?p=5" rel="nofollow">http://www.jordansthings.com/blog/?p=5</a>, which is working well. </p>
  
  <p>The trouble I'm having is that if a user makes 2 recordings, the second has the first at the start of it, so the data is not being cleared out. </p>
  
  <p>I've tried a number of things, setting buffer to null, setting player to null. In Jordans comments he's stuggled to also clear out the old data. </p>
  
  <p>Anyone seen this and have a clue on how to clear out the old content? </p>
  
  <p>Thanks</p>
  
  <pre><code>public function startRecording():void
      {           
          if (!recording) 
          {
          //  TweenMax.to(btnrec, .3, {glowFilter:{color:0xFF0000, alpha:1, blurX:50, blurY:50}} )
              recorder.record() 
  
          } else if (recording) {
              recorder.stop()
              recording = false
              buttonTxt = "Start Recording";
          //  TweenMax.to(btnrec, .3, {glowFilter:{color:0xFF0000, alpha:0, blurX:10, blurY:10}} )                
          }
      }
      public function onRecording(e:RecordingEvent):void
      {           
          statusTxt = "make some noise!";
          buttonTxt = "Stop Recording";
          var al:Number = recorder.microphone.activityLevel;
      //  TweenMax.to(soundMeter, .1, {scaleX:al * .01, onUpdate:onActivitylevelUpdate});//, onUpdateParams:[al]})
          if (!recording) recording = true;
      }       
      public function onActivitylevelUpdate(al):void
      {
          //statusTxt = _activityLevel
          // draw a cool sine wave!
          xpos += speedX;
          ypos = centerY + Math.sin(angle) * amplitude * ((al &gt; 20)? al / 100 : 1)
          angle += speedAngle;
          graphics.lineTo(xpos,ypos)
      }
      private function onRecordComplete(e:Event):void
      {
      //  soundMeter.scaleX = 0
  
          recording = false;
          statusTxt = "recording complete"    
  
          var src = WaveFile.createSample(recorder.output) // this is fine
  
          // I think im not clearing out the old audio properly here somehow...
          var sequence = new ListPerformance()
          sequence.addSourceAt(0, src)
          var ap = new AudioPerformer(sequence, new AudioDescriptor())
          //player.play(ap)
  
          renderWav(ap, true)
  
          // save to wav?
          // new FileReference().save (recorder.output, "VOCariousRecording.wav")
      }
      private function renderWav(src, convertToMp3 = false):void
      {
          var innerTimer = new Timer(10,0)
          var framesPerChunk:uint = 8192;
  
          innerTimer.addEventListener(TimerEvent.TIMER, handleRenderTimer)
          innerTimer.start()
  
          function handleRenderTimer(e:TimerEvent)
          {
              src.getSample(framesPerChunk).writeWavBytes(myWavData)
  
              var m = Math.min(src.frameCount, src.position + framesPerChunk)
              var n = Math.max(0, m - src.position)
  
              if (n == 0)
              {
                  if (src.position &gt; 0) finishRender() else trace("cancel rendering")
  
              } else {
               statusTxt = "rendering audio: "+ Math.floor(src.position * 100 / src.frameCount) + "%";
              }
          }               
          function finishRender():void
          {
              innerTimer.stop()
              statusTxt = "finishing audio render"
              WaveFile.writeBytesToWavFile(myWavFile, myWavData, 44100, 2, 16)
  
              if (!convertToMp3)
              {
                  wavbtn.enabled = true;
              } else {
                  makeIntoMp3(myWavFile)
              }
          }               
      }
      private function makeIntoMp3(wav):void
      {
          wav.position = 0
          mp3Encoder = new ShineMP3Encoder(wav);
          mp3Encoder.addEventListener(Event.COMPLETE, mp3EncodeComplete);
          mp3Encoder.addEventListener(ProgressEvent.PROGRESS, mp3EncodeProgress);
          //mp3Encoder.addEventListener(ErrorEvent.ERROR, mp3EncodeError);
          mp3Encoder.start(); 
      }
  
      function mp3EncodeProgress(e:ProgressEvent) : void 
      {
          statusTxt = "encoding mp3: " + e.bytesLoaded + "%"
      }
  
      function mp3EncodeComplete(e: Event) : void 
      {
          statusTxt = "mp3 encoding complete\n"
          uploadVoiceover()
      }
  
      function uploadVoiceover() : void 
      {
          var sba:ByteArray = mp3Encoder.mp3Data;
          sba.position =  sba.length - 128;
          sba.writeByte(57);  
          statusTxt = "Uploading to server"
  
          var fileUpload:FileUploader = new FileUploader();
          fileUpload.upload("1","Voice_Recording.mp3",sba);
          fileUpload.addEventListener(Event.COMPLETE, onUploaderComplete);
  
      }
  
          private function onUploaderComplete(event:Event):void
          {
              var uploader:FileUploader = FileUploader(event.target);
  
              var id:String = new Uuid().toString();
              var soundData:SoundData = Model.guideScene != null 
                  ? SoundData.createForGuide(id, Model.guideScene.id)
                  : SoundData.createForScene(id, Model.currentScene.id);
              soundData.file = uploader.fileData;
              soundData.ambience = 1;
              soundData.pan = 0;
              soundData.tilt = 0;
              soundData.volume = 1;
              soundData.title = "Voice Recording";
  
              statusTxt = "Hotspot added"
  
  
              var hotspot:HotspotData = soundData;
  
              if(Model.isEditableGuide)
                  Model.guideScene.addHotspot(hotspot);
  
              else if(Model.isEditableScene)
                  Model.currentScene.addHotspot(soundData);
          }
  
  }
  </code></pre>
  
  <p>EDIT</p>
  
  <p>It seems the problem class is this one </p>
  
  <pre><code>package com.noteflight.standingwave3.performance
  {
      import __AS3__.vec.Vector;
  
      import com.noteflight.standingwave3.elements.*;
  
      /**
       * A ListPerformance is an ordered list of PerformableAudioSources, each of which possesses an onset relative to the
       * start of the performance.  The list is optimized for the case where elements are appended in order of start time.
       */
      public class ListPerformance implements IPerformance
      {
  
          private var _elements:Vector.&lt;PerformableAudioSource&gt; = new Vector.&lt;PerformableAudioSource&gt;;
  
          private var _dirty:Boolean = false;
  
          private var _frameCount:Number = 0;  
  
          private var _lastIndex:Number = 0;
  
          public function ListPerformance() {
  
          }
          /* added by jordan */
          public function removeSource(elementnum:int):void
          {
              _elements.length = 0;
              _elements.splice(elementnum, 1)
          }
          /**
           * Add a Performance Element to this Performance. 
           */
          public function addElement(element:PerformableAudioSource):void
          {
  
              if ((! _dirty)
                  &amp;&amp; _elements.length &gt; 0
                  &amp;&amp; element.start &lt; _elements[_elements.length - 1].start)
              {
                  // If we add an element which is out of order, note that we will have
                  // to re-sort the performance later.
                  //
                  _dirty = true;
              }
              _elements.push(element);
  
              // Maintain a cached duration for the overall performance.  Note that
              // the "long straw" element whose end determines the performance end may
              // not be the last element.
              //
              _frameCount = Math.max(_frameCount, element.end);
          }
  
          /**
           * Add an IAudioSource to this performance, to start at a particular start time.
           */
          public function addSourceAt(startTime:Number, source:IAudioSource, gain:Number=0, pan:Number=0):void
          {
              addElement(new PerformableAudioSource(startTime, source, gain, pan));
          }
  
          /**
           * The list of PerformableAudioSources within this Performance, sorted by onset. 
           */        
          public function get elements():Vector.&lt;PerformableAudioSource&gt;
          {
              ensureSorted();
              return _elements;
          }
  
          /**
           * The start of the last performance element in the Performance. 
           */
          public function get lastStart():Number
          {
              var el:Vector.&lt;PerformableAudioSource&gt; = elements;
              return (el.length == 0) ? 0 : el[el.length-1].start;
          }
  
          /**
           * The frame count of the entire Performance. 
           */
          public function get frameCount():Number
          {
              return _frameCount;
          }
  
          //
          // IPerformance interface implementation
          //
  
          /**
           * @inheritDoc 
           */        
          public function getElementsInRange(start:Number, end:Number):Vector.&lt;PerformableAudioSource&gt;
          {
              // This makes use of _lastIndex as a memory of what was last queried to optimize
              // the search for the first matching element, since queries will in general run
              // in forward order.
              //
              var el:Vector.&lt;PerformableAudioSource&gt; = elements;
              var result:Vector.&lt;PerformableAudioSource&gt; = new Vector.&lt;PerformableAudioSource&gt;();             
              _lastIndex = Math.max(0, Math.min(_lastIndex, el.length - 1));
  
              // back up if prior element is ahead of starting frame
              while (_lastIndex &gt; 0 &amp;&amp; el[_lastIndex - 1].start &gt;= start)
              {
                  _lastIndex--;
              }
  
              // advance if our current element is prior to starting frame
              while (_lastIndex &lt; el.length &amp;&amp; el[_lastIndex].start &lt; start)
              {
                  _lastIndex++;
              } 
  
              // Return elements that start in this time window (and may also end in it)
              while (_lastIndex &lt; el.length &amp;&amp; el[_lastIndex].start &lt; end)
              {
                  result.push(el[_lastIndex++]);
              }
  
              return result;
          }
  
          public function clone():IPerformance
          {
              var p:ListPerformance = new ListPerformance();
              for each (var element:PerformableAudioSource in elements)
              {
                  p.addElement(new PerformableAudioSource(element.startTime, element.source.clone()));
              }
              return p;
          }
  
          private function ensureSorted():void
          {
              if (_dirty)
              {
                  _elements.sort(sortByStart);
                  _dirty = false;
              }
          }
  
          private static function sortByStart(a:PerformableAudioSource, b:PerformableAudioSource):Number
          {
              var aStart:Number = a.start;
              var bStart:Number = b.start;
              if(aStart &gt; bStart)
              {
                  return 1;
              }
              else if(aStart &lt; bStart)
              {
                  return -1;
              }
              else
              {
                  return 0;
              }
          }
      }
  }
  </code></pre>
  
  <p>Jordan attempted to clear out the sequence with the class he added at the top (removeSource) I've attempted to work on this, but can't get the sequence to go back to zero, and remove the old data before recording a new one. </p>
  
  <p>Anyone see how to achieve this? </p>