Search code examples
actionscript-3audio

Strange sound error in my ActionScript3 game


Sometimes I get this strange error during gameplay:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.efg.framework_mod::SoundManager/playSound()[/Users/xxx/Documents/Developer/AS3_Flex/game_development/projects/xxx/SpaceGame/libs/src/com/efg/framework_mod/SoundManager.as:106]
at com.xxx.games.spacegame::Main/soundEventListener()[/Users/xxx/Documents/Developer/AS3_Flex/game_development/projects/xxx/SpaceGame/src/com/xxx/games/spacegame/Main.as:1407]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at com.xxx.games.spacegame::SpaceGame/createEnemyProj()[/Users/xxx/Documents/Developer/AS3_Flex/game_development/projects/xxx/SpaceGame/src/com/xxx/games/spacegame/SpaceGame.as:3708]

I still don't know what causes the error. The only thing I discovered is that sometimes an object is null inside of my SoundManager. But I don't know why. I already checked all appropriate arrays if something's missing there but all seems to be ok there.

This is the part of the SoundManager where the error occurs:

public function playSound(soundName:String, isSoundTrack:Boolean = false, loops:int = 1, offset:Number = 0, _volume:Number = 1, fadeIn:Boolean = false,
                                _duration:Number = 1):void {



    tempSoundTransform.volume = _volume;


    tempSound = sounds[soundName];//sometimes null (still don't know why)

    if (!fadeIn) {
        if (isSoundTrack) {
            if (soundTrackChannel != null) {
                soundTrackChannel.stop();
            }
            soundTrackChannel = tempSound.play(offset, loops);                              
            soundTrackChannel.soundTransform = tempSoundTransform;  
        } else {


            soundChannels[soundName] = tempSound.play(offset, loops);//sometimes null but still don't know why

            soundChannels[soundName].soundTransform = tempSoundTransform;//line 106 (see errors above)


        }
    } else {

        fadeInSoundTransform = new SoundTransform(0, 0);

        if (isSoundTrack) {
            if (soundTrackChannel != null) {
                soundTrackChannel.stop();
            }
            soundTrackChannel = tempSound.play(offset, loops, fadeInSoundTransform);
        } else {
            soundChannels[soundName] = tempSound.play(offset, loops, fadeInSoundTransform);

        }

        TweenLite.to(fadeInSoundTransform, _duration, {volume:_volume, onUpdate:updateFadeIn, onUpdateParams:[soundName, isSoundTrack]});
    }
}

This is line 3708 (see errors above):

dispatchEvent(new CustomEventSound(CustomEventSound.PLAY_SOUND, enemyProjSounds[tempEnemyProj._type], false, 0, 8, setSoundVolume, false, false, 0));

This is the class CustomEventSound:

public function CustomEventSound(type:String, name:String, isSoundTrack:Boolean = false, loops:int = 0,
            offset:Number = 0, _volume:Number = 1, fadeIn:Boolean = false, fadeOut:Boolean = false,
        _duration:Number = 2, startVol:Number = 1, bubbles:Boolean = false, cancelable:Boolean = false)
{
    super(type, bubbles, cancelable);
    this.name = name;
    this.loops = loops;
    this.offset = offset;
    this._volume = _volume;
    this.isSoundTrack = isSoundTrack;
    this.fadeIn = fadeIn;
    this.fadeOut = fadeOut;
    this._duration = _duration;
    this.startVol = startVol;

}

public override function clone():Event {
    return new CustomEventSound(type, name, isSoundTrack, loops, offset, _volume, fadeIn, fadeOut, _duration, startVol, bubbles, cancelable)
}


public override function toString():String {
    return formatToString(type, "type", "bubbles", "cancelable", "eventPhase", name, isSoundTrack, loops, offset, _volume, fadeIn,
                fadeOut, _duration, startVol);
}

The Listener-function for CustomEventSounds-Events

override public function soundEventListener(e:CustomEventSound):void {

if (e.type == CustomEventSound.PLAY_SOUND) {

soundManager.playSound(e.name, e.isSoundTrack, e.loops, e.offset, e._volume, e.fadeIn, e._duration);
} else {
    soundManager.stopSound(e.name, e.isSoundTrack, e.fadeOut, e._duration, e.startVol);
}
}

Solution

  • There's a maximum of 32 active sound channels at a time. When you call tempSound.play(offset, loops) it will return null when there are already 32 sounds currently playing.

    So you should keep track of the number of sounds playing, and stop() the oldest SoundChannel when you have 32 and a new sound must be played, or just ignore the new sound if Sound.play() returns null.