views:

106

answers:

2

It appears my sound is off sync and the longer I play the movieclip, the farther off sync it goes. Its nothing too complicated, just some basic shooting sounds that fire every time I hit the space bar. My code is below:

package com.objects{

    import flash.display.MovieClip;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.net.URLRequest;
    import flash.events.Event;

    public class Avatar extends gameObject implements IKiller{

        public var targets:Array;
        public var delay:Number = 3000;
        public var weapon:Number = 1;
        private var fireSound:Sound;
        private var fireSound2:Sound;
        private var systems:Array;
        private var ext:Number = -1;
        private var channelTracer:SoundChannel;
        private var channelCount:Number = 0;


        public function Avatar():void
        {
            systems = new Array();
            channelTracer = new SoundChannel();
            var soundUrl = new URLRequest("com/images/mashingun_darkt.mp3");
            fireSound = new Sound();
            fireSound.load(soundUrl);

            var soundUrl = new URLRequest("com/images/mashingun_light.mp3");
            fireSound2 = new Sound();
            fireSound2.load(soundUrl);

            rotation = -90;
            lastTime = getTime();
            targets = new Array();
        }

        private function soundFinished(e:Event):void {
            channelCount--;
            trace(channelCount);
        }


        public function get Systems():Array
        {
            return systems;
        }

        override public function Attack(dir:Number = -40):void
        {
            switch(weapon){

                case 1:                 
                    var bullet1:Bullet = new Bullet();
                    bullet1.wielder = this;
                    bullet1.x = x + 35;
                    bullet1.y = y + 30;
                    bullet1.bulletDir = rotation;
                    eApi.addGameChild(bullet1);

                    var bullet2:Bullet = new Bullet();
                    bullet2.bulletDir = rotation;
                    bullet2.wielder = this;
                    bullet2.x = x - 35;
                    bullet2.y = y + 30;
                    eApi.addGameChild(bullet2);

                    var rand = Math.ceil(Math.random() * 100);
                    if (rand < 50) {
                        channelTracer = fireSound.play();
                        //RndSound = RndSound+50;
                    } else {
                        channelTracer = fireSound2.play();

                    }
                    channelTracer.addEventListener(Event.SOUND_COMPLETE, soundFinished);
                    channelCount++;
                    trace(channelCount);

                break;
                case 2:
                    if((getTime() - lastTime) > delay)
                    {
                        var missle = new Missile();
                        missle.shootOut *=  ext;
                        ext *= -1;
                        missle.x = x;
                        missle.y = y;
                        trace(ext);
                        missle.wielder = this;
                        eApi.addGameChildAt((eApi.numChildren - 2),missle);
                        lastTime = getTime();
                    }
                break;
                case 3:
                    var bullet1:Bullet = new Bullet();
                    bullet1.wielder = this;
                    bullet1.x = x + 35;
                    bullet1.y = y + 30;
                    bullet1.bulletDir = -80;
                    eApi.addGameChild(bullet1);

                    var laser = new StingerLaser();
                    laser.laserDir = -90;
                    laser.wielder.push(this);
                    laser.x = x + 20;
                    laser.y = y + -3;
                    eApi.addGameChild(laser);

                    var laser2 = new StingerLaser();
                    laser2.laserDir = -90;
                    laser2.wielder.push(this);
                    laser2.x = x + -20;
                    laser2.y = y + -3;
                    eApi.addGameChild(laser2);

                    var bullet2:Bullet = new Bullet();
                    bullet2.bulletDir = -100;
                    bullet2.wielder = this;
                    bullet2.x = x - 35;
                    bullet2.y = y + 30;
                    eApi.addGameChild(bullet2);
                break;              
                case 4:
                    if((getTime() - lastTime) > delay)
                    {
                        var missle1 = new Missile();
                        missle1.shootOut =  2;
                        missle1.x = x;
                        missle1.y = y;
                        missle1.wielder = this;
                        eApi.addGameChildAt((eApi.numChildren - 2),missle1);

                        var missle2 = new Missile();
                        missle2.shootOut =  -2;
                        missle2.x = x;
                        missle2.y = y;
                        missle2.wielder = this;
                        eApi.addGameChildAt((eApi.numChildren - 2),missle2);
                        lastTime = getTime();
                    }
                break;
                case 5:
                    if((getTime() - lastTime) > delay)
                    {
                        var side:Number = 1;
                        for(var i = 0; i < 20; i+=2)
                        {
                            var missle1 = new Missile();
                            missle1.shootOut =  (i+2) * side;
                            side *= -1;
                            missle1.straightShot = true;
                            missle1.x = x;
                            missle1.y = y;
                            missle1.wielder = this;
                            eApi.addGameChildAt((eApi.numChildren - 2),missle1);
                        }
                        lastTime = getTime();
                    }
                break;
                default:
            }
        }

        public function Hit(dmg:Number = .01):void {
            if(health > 0)
                health -= dmg;

            if(health < 0)
                health = 0,trace("dead");
        }

        override public function updateObject():void
        {

        }
    }
}

The Attack() method gets called from another class that handles all keyboard controls. when it gets called the sound then plays. firesound and firesound2 are almost the same. firesound2 sounds a little off pitch to make it sound more realistic. At first the sound sounds pretty good, not great. but then it gets terrible as time passes. Not sure if this is a known issue. But if anyone has any ideas, let me know. thanks!

I made a new .fla project. and I attached the following class to it by it self. so the following is the only code in the entire .fla project and the issue still occurs. I press the spacebar and the sound starts a day late.

package {
    import flash.display.MovieClip;
    import flash.events.*;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.net.URLRequest;

    public class test extends MovieClip
    {
        private var fireSound:Sound;
        private var fireSound2:Sound;
        private var aKeyPress:Array;

        public function test():void
        {
            aKeyPress = new Array();
            var soundUrl = new URLRequest("com/images/mashingun_darkt.mp3");
            fireSound = new Sound();
            fireSound.load(soundUrl);

            var soundUrl = new URLRequest("com/images/mashingun_light.mp3");
            fireSound2 = new Sound();
            fireSound2.load(soundUrl);
            addEventListener(Event.ENTER_FRAME, loop);
            stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownListener);
            stage.addEventListener(KeyboardEvent.KEY_UP,keyUpListener);
        }
        private function keyDownListener(e:KeyboardEvent) {
            //trace("down e.keyCode=" + e.keyCode);         
            aKeyPress[e.keyCode]=true;
        }

        private function keyUpListener(e:KeyboardEvent) {
            //trace("up e.keyCode=" + e.keyCode);
            aKeyPress[e.keyCode]=false;
        }
        public function loop(e:Event):void
        {
            if (aKeyPress[32]){//Right
                    var rand = Math.ceil(Math.random() * 100);
                    if (rand < 50) {
                        fireSound.play();
                        //RndSound = RndSound+50;
                    } else {
                        fireSound2.play();
                    }
            }
        }
    }
}
+1  A: 

Any chance this could be something to do with the number of concurrent sounds playing?

Each call to Sound.play() returns a new SoundChannel object (you can only have 32 of these at a time). You could monitor how the channels are being used like this:

private var channelTracer:SoundChannel;
private var channelCount:number = 0;
//...

private function soundFinished(e:Event):void {
channelCount--;
trace(channelCount);
}

//...

var rand = Math.random() * 100;
if (rand < 50) {
channelTracer = fireSound.play();
} else {
channelTracer = fireSound2.play();
}
channelTracer.addEventListener(Event.SOUND_COMPLETE, soundFinished);
channelCount++;
trace(channelCount);

This might help you pinpoint the problem.

EDIT: I changed the code above to keep a running count of how many sounds are playing concurrently (I hope - sorry you'll have to test it for me!)

Richard Inglis
I am unfamiluar with how channels work. I can tell you this. there are only 2 varibles in memory that hold sound. that is fireSound and fireSound2. And when I press and hold the space bar, either fireSound.play(); plays or fireSound2.play() plays depending on if the rand var is greater then or less then 50.
numerical25
as for channel tracer, there must be more to it then just tracing the varible because all trace(channelTracer ) does it tells me what type of object it is.
numerical25
Hmmm, yes you're right about trace(channelTracer) - I was hoping it would give you some information about which of the 32 channels was in use... sorry that wasn't much help.
Richard Inglis
OK, new code added above to track number of concurrent sounds...
Richard Inglis
wow, I think we might be getting somewhere. I did what you said and it went pass 32 like 10 secs into shooting. I waited about a minute or so and the count never decreased. I think I need to look into these channels more. it never calls the channel tracer event. I updated the avatar class code above.
numerical25
nevermind, the reason why it didnt work is because your suppose to put the varible that holds the sound, into the channeltracer object. I reupdated my code. (i.e. channelTracer = fireSound.play(); channelTracer.addEventListener(Event.SOUND_COMPLETE, soundFinished);) I did that now the highest its going is about 12. almost half of 32. I don't know what it could be. its just a basic sound. I might have to try to put the sound in the library. If that doesnt work then I am probably screwed
numerical25
Is there any relation between channelCount and the latency? ie does it suddenly kick in when you get above a certain number, or does it gradually get worse as time passes?
Richard Inglis
+1  A: 

I tested a build using this test code and my own sound files, and am unable to encounter the sound lagging issue. It could be your sound files, though there are no issues that I am aware of that would cause calls to Sound.play() to begin lagging.

The sound files I used to test were short (Mario fireball and jump sounds), and was unable to get more than 4 concurrent SoundChannels in use. No latency issues.

Using longer length sound files, I was able to push the number of SoundChannels to 32, at which point the channel tracer code began throwing null reference errors (as would be expected since Sound.play() cannot return more SoundChannels), and it sounded pretty awful, but once the sounds completed the count decremented to zero. After two straight minutes of punishing my headphones and soundcard, I still encountered no latency.

I'd suggest inserting calls to getTimer() throughout your code to see if it's a performance bottleneck (i.e. Flash Player not actually responding to events quickly) or a sound latency issue. Also, you may want try different sound files to see if the issue still occurs.

pixelbath