title: Better way to send voice over a socket in AS3
body: <p>I made an AIR application that sends voice between two computers, this is the code:</p>
  
  <pre><code>package
  {
      import fl.controls.List;
  
      import flash.events.ProgressEvent;
      import flash.events.SampleDataEvent;
      import flash.events.ServerSocketConnectEvent;
      import flash.media.Microphone;
      import flash.media.Sound;
      import flash.net.ServerSocket;
      import flash.net.Socket;
      import flash.utils.ByteArray;
      import flash.system.System;
  
      public class VoiceCommunication
      {
          private var soundBytes:ByteArray;
          private var mic:Microphone;
          private var voiceReceiver:ServerSocket;
          private var voiceSender:Socket;
          private var mLocalIP:String;
          private var mRemoteIP:String;
          private var mPort:uint;
          private var sound:Sound;
          private var sample:Number;
  
          public function VoiceCommunication(localIP:String, port:uint)
          {
              mLocalIP = localIP;
              mPort = port;
          }
  
          public function startSendingVoice(remoteIP:String = null):void
          {
              mic = Microphone.getMicrophone();//2-null
              mic.gain = 100;
              mic.rate = 44;
              voiceSender = new Socket();//3-null
  
              mRemoteIP = remoteIP;//5-null
              mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);//1-remove eventlistener
  
          }
  
          protected function micSampleDataHandler(event:SampleDataEvent):void
          {
              if(mRemoteIP != null)
              {
                  voiceSender.connect(mRemoteIP, mPort);
                  while(event.data.bytesAvailable)
                  {
                      sample = event.data.readFloat();
                      voiceSender.writeFloat(sample);
                  }
                  voiceSender.flush();
              }
          }
  
          public function startReceivingVoice():void
          {
              voiceReceiver = new ServerSocket;//2
              voiceReceiver.bind(mPort, mLocalIP);
              voiceReceiver.addEventListener(ServerSocketConnectEvent.CONNECT, handleConnection);//1
              voiceReceiver.listen();
          }
  
          protected function handleConnection(event:ServerSocketConnectEvent):void
          {
              var s:Socket = event.socket as Socket;
              s.addEventListener(ProgressEvent.SOCKET_DATA, handleData);      
          }
  
          protected function handleData(event:ProgressEvent):void
          {
              event.target.removeEventListener(ProgressEvent.SOCKET_DATA, handleData);
              var s:Socket = event.target as Socket;
              soundBytes = null;
              soundBytes = new ByteArray();//3
              s.readBytes(soundBytes);
              playSound();
              s = null;
          }
  
          private function playSound():void
          {
              soundBytes.position = 0;
              sound = null;
              sound = new Sound();//5
              sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler, false, 0, true);//4
              sound.play();       
          }
  
          protected function playbackSampleHandler(event:SampleDataEvent):void
          {
              sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
              for (var i:int = 0; i &lt; 8192 &amp;&amp; soundBytes.bytesAvailable &gt; 0; i++) 
              {
                  sample = soundBytes.readFloat();
                  event.data.writeFloat(sample);
                  event.data.writeFloat(sample);
              }
              System.gc();
          }
  
          public function destroySender():void
          {
              mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
              mic = null;
              voiceSender = null;
              mRemoteIP = null;
              System.gc();
          }
  
          public function destroyReceiver():void
          {
              voiceReceiver.removeEventListener(ServerSocketConnectEvent.CONNECT, handleConnection);//1
              voiceReceiver = null;
              soundBytes = null;
              sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
              sound = null;
              System.gc();
          }
      }
  }
  </code></pre>
  
  <p>This works fine and when I tried it, it did send the voice, but the problem is that sending the voice is too slow and gets split. So is there a better way to do it?</p>
  
  <p>I rewrote it using datagram socket but that didn't work at all, the code:</p>
  
  <pre><code>package
  {
      import fl.controls.List;
  
      import flash.events.DatagramSocketDataEvent;
      import flash.events.ProgressEvent;
      import flash.events.SampleDataEvent;
      import flash.events.ServerSocketConnectEvent;
      import flash.media.Microphone;
      import flash.media.Sound;
      import flash.net.DatagramSocket;
      import flash.net.ServerSocket;
      import flash.net.Socket;
      import flash.system.System;
      import flash.utils.ByteArray;
  
      public class VoiceComm
      {
          private var soundBytes:ByteArray;
          private var mic:Microphone;
          private var socket:DatagramSocket
          private var mList:List;
          private var mLocalIP:String;
          private var mRemoteIP:String;
          private var mPort:uint;
          private var sound:Sound;
          private var sample:Number;
          private var bytesToBeSent:ByteArray;
  
          public function VoiceComm(localIP:String, port:uint)
          {
              socket = new DatagramSocket();
              mLocalIP = localIP;
              mPort = port;
          }
  
          public function startSendingVoice(remoteIP:String = null):void
          {
              mic = Microphone.getMicrophone();
              mic.gain = 100;
              mic.rate = 44;
              mRemoteIP = remoteIP;
              mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
  
          }
  
          protected function micSampleDataHandler(event:SampleDataEvent):void
          {
              var sample:Number;
              if(mRemoteIP != null)
              {
                  while(event.data.bytesAvailable)
                  {
                      sample = event.data.readFloat();
                      bytesToBeSent = null;
                      bytesToBeSent = new ByteArray();
                      bytesToBeSent.writeFloat(sample);
                      socket.send(bytesToBeSent, 0, 0, mRemoteIP, mPort);
                  }
              }
          }
  
          public function startReceivingVoice():void
          {
              socket.bind(mPort, mLocalIP);
              socket.addEventListener(DatagramSocketDataEvent.DATA, handleData);
              socket.receive();
          }
  
  
          protected function handleData(event:DatagramSocketDataEvent):void
          {
  
              trace("Data inthere!");
              soundBytes = null;
              soundBytes = new ByteArray();//3
              event.data.readBytes(soundBytes);
              playSound();
  
          }
  
          private function playSound():void
          {
              soundBytes.position = 0;
              sound = null;
              sound = new Sound();//5
              sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler, false, 0, true);//4
              sound.play();       
          }
  
          protected function playbackSampleHandler(event:SampleDataEvent):void
          {
              sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
              for (var i:int = 0; i &lt; 8192 &amp;&amp; soundBytes.bytesAvailable &gt; 0; i++) 
              {
                  sample = soundBytes.readFloat();
                  event.data.writeFloat(sample);
                  event.data.writeFloat(sample);
              }
              System.gc();
          }
  
          public function destroySender():void
          {
              mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
              mic = null;
              mList = null;
              mRemoteIP = null;
              System.gc();
          }
  
          public function destroyReceiver():void
          {
              soundBytes = null;
              sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
              sound = null;
              System.gc();
          }
      }
  }
  </code></pre>
  
  <p>**Update:</p>
  
  <p>The code after modification:</p>
  
  <pre><code>package
  {
      import fl.controls.List;
      import flash.events.DatagramSocketDataEvent;
      import flash.events.SampleDataEvent;
      import flash.media.Microphone;
      import flash.media.Sound;
      import flash.net.DatagramSocket;
      import flash.net.Socket;
      import flash.system.System;
      import flash.utils.ByteArray;
  
      public class VoiceComm
      {
          private var mic:Microphone;
          private var soundBytes:ByteArray;
          private var sample:Number;
          private var sound:Sound;
          private var socket:DatagramSocket;
          private var mLocalIP:String;
          private var mPort:uint;
          private var mRemoteIP:String;
          private var receivedBytes:ByteArray;
  
          public function VoiceComm(localIP:String, port:uint)
          {
              socket = new DatagramSocket();
              mLocalIP = localIP;
              mPort = port;
          }
          //destroyers:
  
          public function destroySender():void
          {
              mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, sampleData);
              mic = null;
              soundBytes = null;
              System.gc();
          }
  
          public function destroyReceiver():void
          {
              socket.removeEventListener(DatagramSocketDataEvent.DATA, playSound);
              receivedBytes = null;
              System.gc();
          }
  
          //sending part
          public function startSendingVoice(ip:String = null):void
          {
              mRemoteIP = ip;
              mic = Microphone.getMicrophone();
              mic.rate = 44;
              mic.gain = 100;
              mic.addEventListener(SampleDataEvent.SAMPLE_DATA, sampleData);
          }
  
          protected function sampleData(event:SampleDataEvent):void
          {
              soundBytes = new ByteArray();
              while(event.data.bytesAvailable)
              {
                  var sample:Number = event.data.readFloat();
                  soundBytes.writeFloat(sample);
              }
              if(mRemoteIP != null)
              {
                  event.data.position = 0;
                  socket.send(soundBytes, 0, event.data.length, mRemoteIP, mPort);
              }
          }
  
  
          //receiving part
          public function startReceivingVoice():void
          {           
              socket.bind(mPort, mLocalIP);
              socket.addEventListener(DatagramSocketDataEvent.DATA, playSound);
              socket.receive();
          }
  
          protected function playSound(event:DatagramSocketDataEvent):void
          {
              trace("got data!");
              receivedBytes = new ByteArray();
              event.data.readBytes(receivedBytes);
              receivedBytes.position = 0;
              var sound:Sound = new Sound();
              sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler, false, 0, true);
              sound.play();
          }
  
          protected function playbackSampleHandler(event:SampleDataEvent):void
          {
              trace("Playing Sound...");
              for (var i:int = 0; i &lt; 8192 &amp;&amp; receivedBytes.bytesAvailable &gt; 0; i++) 
              {
                  var sample:Number = receivedBytes.readFloat();
                  event.data.writeFloat(sample);
                  event.data.writeFloat(sample);
                  System.gc();
              }
  
          }
  
      }
  }
  </code></pre>