Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prefered method for looping sound flash as3

I'm having some issues with looping a sound in flash AS3, in that when I tell the sound to loop I get a slight delay at the end/beginning of the audio.

The audio is clipped correctly and will play without a gap on garage band.

I know that there are issues with sound in general in flash, bugs with encodings and the inaccuracies with the SOUND_COMPLETE event (And Adobe should be embarrassed with their handling of these issues)

I have tried to use the built in loop argument in the play method on the Sound class and also react on the SOUND_COMPLETE event, but both cause a delay.

But has anyone come up with a technique for looping a sound without any noticeable gap?

like image 764
BefittingTheorem Avatar asked Aug 04 '09 13:08

BefittingTheorem


4 Answers

The most reliable method, if you can use Flash Player 10, is to use the new SampleDataEvent.SAMPLE_DATA event.

Specifically, what you do is to first instantiate the sound you want, then use the new extract method to convert the sound into raw PCM data encoded in a ByteArray. Then you can create a new Sound object, and setup to listen for it's SampleDataEvent.SAMPLE_DATA event. When that event is called you'll push 2-8k (a lower amount reduces latency, but increases the possibility of audible artifacts) of data from the ByteArray. You'll just make sure that as you run off the end of the ByteArray you'll just loop back to the beginning.

This method ensures that you'll have fully gapless playback.

like image 55
Branden Hall Avatar answered Nov 14 '22 12:11

Branden Hall


Gapless looping of mp3's is not trivial due to the way the format works. To simplify a bit; the sound is fitted to a number of frames, this number cannot be chosen arbitrarily, instead some padding (with silence) is required. Mp3 has no way of storing how much padding was added, so this information is lost once the file is encoded.

The flash IDE get's around this by embedding this metadata, and you can too. You just need to know how much delay is added by the encoder.

Andre Michelle explains this way better than I can on his blog.

like image 21
grapefrukt Avatar answered Nov 14 '22 13:11

grapefrukt


Here is how id did it, with no noticeable delay. Main app:

package {

import flash.display.MovieClip; 
import flash.events.*;
import flash.utils.*;

public class MainApp extends MovieClip {
  private var player:Player;
  ..........

  public function MainApp() {
      .......
      player = new Player();
      player.addEventListener(Player.EVENT_SOUND_COMPLETED, handleSoundCompleted);
      ......
  }

  private function handleSoundCompleted(event:Event):void {
      player.setPosition(0);
      player.play();
  }

  .................

Player class:

package {

import flash.events.*;
import flash.media.*;
import flash.net.*;

public class Player extends EventDispatcher {

    private var sound:Sound;
    private var channel:SoundChannel;
    private var position:Number;

    static const SOUND_VOLUME:Number = 0.75;
    static const EVENT_SOUND_COMPLETED:String = "SOUND_COMPLETED";

    public function Player() {

        // init
        sound = new ThemeSong();
        position = 0;

        // listeners
        sound.addEventListener(IOErrorEvent.IO_ERROR, function(event:Event){trace(event)});

        trace("Player initialized...");
    }

    public function play():void {
        channel = sound.play(position);
        channel.soundTransform = new SoundTransform(SOUND_VOLUME);
        channel.addEventListener(Event.SOUND_COMPLETE, function(event:Event){dispatchEvent(new Event(EVENT_SOUND_COMPLETED));});
        trace("Player playing..");
    }

    public function pause():void {
        if (channel != null) {
            channel.stop();
            position = channel.position;
        }
        trace("Player paused..");
    }

    public function setPosition(pos:Number):void {
        position = pos;
    }

    public function getPosition():Number {
        if (channel == null) {
            return 0;
        } else {
            return channel.position;
        }
    }
}
}

You did say that the mp3 file has no delay at beginning/end, but I suggest opening it with audacity, and make sure there is no delay.

like image 1
Mercer Traieste Avatar answered Nov 14 '22 11:11

Mercer Traieste


According to this guy, you have to import the music loop as a wav, and have the Flash IDE itself compress to mp3. Having Flash use imported mp3 data means that it won't know how to loop it properly.

like image 3
aaaidan Avatar answered Nov 14 '22 12:11

aaaidan