Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to play MP3 sound from buffer (ByteArray/Stream) in ActionScript 3?

So.. I have a buffer with MP3 data (If I would save this buffer and call it buffer.mp3 it would play, but in this situation I should not save it to file system). I have to play it, but I can not, what shall I do?


I tried the next code to play that buffrer(ByteArray\Stream) (I get MP3 data from server the method of getting data works fine (tested on text int's etc) I call the returned ByteArray readResponse because I have some seading method and It is it's response).

            protected function Play(event:MouseEvent):void
        {
            var mySound:Sound = new Sound();
            mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, soundFill);
            mySound.play(); 
        }

        public function soundFill(event:SampleDataEvent):void
        {
            event.data.writeBytes(readResponse.buffer, 0, readResponse.buffer.length);  
        }
like image 413
Rella Avatar asked Oct 25 '09 02:10

Rella


3 Answers

This one doesn't work since SampleDataEvent.data expects uncompressed raw sample data, not MP3. Use https://github.com/claus/as3swf/wiki/play-mp3-directly-from-bytearray instead.

like image 189
Vancura Avatar answered Nov 03 '22 01:11

Vancura


I don't think there is a solution to mp3 binary data, but if it's a wav one, then this should work:


   private function loaded(event:Event):void {
   var urlStream:URLStream = event.target as URLStream;
   bArr = new ByteArray();
   urlStream.readBytes(bArr, 0);
   /**
    * Remove wav header here
    */
   bArr.position = 0;
   sampleMP3.addEventListener(SampleDataEvent.SAMPLE_DATA, sampleDataHandler);
   soundChannel = sampleMP3.play();
  }

  private function sampleDataHandler(event:SampleDataEvent):void {
   var bytesToRead:int = (bArr.bytesAvailable > 65536 ? 65536 : bArr.bytesAvailable);
   event.data.writeBytes(bArr, bArr.position, bytesToRead);
   bArr.position += bytesToRead;
  }

Remember to remove wav header before sampling data though. Also, it only works well when sample rate is 44.1kHz. For other sample rates, you need to manually repeat or remove samples to make it 44.1kHz-like. Do pay attention to mono sounds, as you need to supply both left & right channel samples to Flash, thus need to repeat samples.

Good starting point is WavDecoder class inside Popforge's audio.format.wav package.

like image 36
YTF Avatar answered Nov 03 '22 01:11

YTF


The following works for me:

package
{
 import flash.display.Sprite;
 import flash.events.Event;
 import flash.events.SampleDataEvent;
 import flash.media.Sound;
 import flash.media.SoundChannel;
 import flash.net.URLRequest;
 import flash.net.URLStream;
 import flash.utils.ByteArray;

 public class QuickSoundTest extends Sprite
 {
  public var sampleMP3:Sound;
  private var soundChannel:SoundChannel; 
  public var bArr:ByteArray;

  public function QuickSoundTest()
  {
   sampleMP3 = new Sound();

   var urlReq:URLRequest = new URLRequest("test.mp3");
   var urlStream:URLStream = new URLStream();
   urlStream.addEventListener(Event.COMPLETE, loaded);
   urlStream.load(urlReq);

  }

  private function loaded(event:Event):void {
   var urlStream:URLStream = event.target as URLStream;
   bArr = new ByteArray();
   urlStream.readBytes(bArr, 0, 40960);
   sampleMP3.addEventListener(SampleDataEvent.SAMPLE_DATA, sampleDataHandler);
   soundChannel = sampleMP3.play();
  }

  private function sampleDataHandler(event:SampleDataEvent):void {
   event.data.writeBytes(bArr, 0, 40960);
  }
 }
}

You might need to check what is stored in your readResponse ByteArray or how the data is getting read in when you're loading it. Making sure that it's loaded the URLLoader using URLLoaderDataFormat.BINARY or just by using a URLStream as I've done here.

like image 31
Joshua Noble Avatar answered Nov 03 '22 00:11

Joshua Noble