Search code examples
androidactionscript-3flashaudioair

actionscript3 calculator sound playing


I'm trying to make a math app using as3 in air for android. I have many frames with some stuff like

    stop();
QuestText.text = "0+2"
        Button1.LabelText.text = "6";
        Button2.LabelText.text = "2";
        Button3.LabelText.text = "0";

And I have some sounds: From 1.mp3 to 20.mp3 and plus.mp3 with minus.mp3

var DigitSound0:Sound = new Sound();
var DigitSound1:Sound = new Sound();
var DigitSound2:Sound = new Sound();
var DigitSound3:Sound = new Sound();
var DigitSound4:Sound = new Sound();
var DigitSound5:Sound = new Sound();
var DigitSound6:Sound = new Sound();
var DigitSound7:Sound = new Sound();
var DigitSound8:Sound = new Sound();
var DigitSound9:Sound = new Sound();
var DigitSoundplus:Sound = new Sound();
var DigitSoundminus:Sound = new Sound();
var DigitSoundChannel:SoundChannel = new SoundChannel();
DigitSound0.load(new URLRequest(FilePath+"speech/0.mp3"));
DigitSound1.load(new URLRequest(FilePath+"speech/1.mp3"));
DigitSound2.load(new URLRequest(FilePath+"speech/2.mp3"));
DigitSound3.load(new URLRequest(FilePath+"speech/3.mp3"));
DigitSound4.load(new URLRequest(FilePath+"speech/4.mp3"));
DigitSound5.load(new URLRequest(FilePath+"speech/5.mp3"));
DigitSound6.load(new URLRequest(FilePath+"speech/6.mp3"));
DigitSound7.load(new URLRequest(FilePath+"speech/7.mp3"));
DigitSound8.load(new URLRequest(FilePath+"speech/8.mp3"));
DigitSound9.load(new URLRequest(FilePath+"speech/9.mp3"));
DigitSoundplus.load(new URLRequest(FilePath+"speech/plus.mp3"));
DigitSoundminus.load(new URLRequest(FilePath+"speech/minus.mp3"));

All I need is for example when the problem is "4+5", make as3 play 4.mp3+plus.mp3+5.mp3

I can do it with soundcomplete event after every mp3 in every frame

stop();

DigitSoundChannel.addEventListener(Event.SOUND_COMPLETE, DigitSoundComplete);
DigitSoundChannel = DigitSound4.play();
function DigitSoundComplete(event:Event):void 
{
    ThemeSongChannel.removeEventListener(Event.SOUND_COMPLETE, DigitSoundComplete);
    DigitSoundChannel = DigitSoundplus.play();
    DigitSoundChannel.addEventListener(Event.SOUND_COMPLETE, DigitSoundComplete);
    DigitSoundChannel = DigitSound5.play();
    ThemeSongChannel.removeEventListener(Event.SOUND_COMPLETE, DigitSoundComplete);
}

QuestText.text = "4+5"

        Button1.LabelText.text = "1";
        Button2.LabelText.text = "0";
        Button3.LabelText.text = "4";

but I have more than 300 frames. Is there any easier way?


Solution

  • I won't use the word "easier". But more algorithmic, yes, it is possible. You'll actually be thrilled to learn that official Adobe documentation has an example how to play a sequence of sounds. Lets adapt it to your needs.

    First, you need to devise a sound cache so that you could get a sound by character value.

    package
    {
        import flash.media.Sound;
        import flash.events.Event;
    
        public class SoundCache
        {
            static private var loadingPlan:int;
            static private var completeHandler:Function;
            static private var hash:Object = new Object;
    
            // This method will return a Sound object by character value.
            static public function find(name:String):Sound
            {
                return hash[name];
            }
    
            static public function startEngine(handler:Function):void
            {
                loadingPlan = 12;
                completeHandler = handler;
    
                for (var i:int = 0; i < 10; i++)
                    loadSound(i + "", i + "");
    
                loadSound("+", "plus");
                loadSound("-", "minus");
            }
    
            static private function loadSound(name:String, fileName:String):void
            {
                var aSound:Sound = new Sound;
    
                hash[name] = aSound;
    
                aSound.addEventListener(Event.COMPLETE, onLoaded);
                aSound.load(FilePath + "speech/" + fileName + ".mp3");
            }
    
            static private function onLoaded(e:Event):void
            {
                var aSound:Sound = e.target as Sound;
    
                aSound.removeEventListener(Event.COMPLETE, onLoaded);
    
                loadingPlan--;
    
                if (loadingPlan == 0)
                {
                    if (completeHandler != null)
                    {
                        completeHandler();
                        completeHandler = null;
                    }
                }
            }
        }
    }
    

    So at the start of your application you call:

    import SoundCache;
    
    SoundCache.startEngine(onCache);
    
    function onCache():void
    {
        trace("All sounds are loaded!");
    }
    

    When all the sounds are loaded and ready, you can use them for playing sound sequences. Lets devise a sequence player.

    package
    {
        import SoundCache;
    
        import flash.events.Event;
    
        import flash.media.Sound;
        import flash.media.SoundChannel;
    
        public class SequencePlayer
        {
            // A list of active sequence players. If you don't keep
            // their references while they are playing,
            // Garbage Collector might go and get them.
            static private var list:Array = new Array;
    
            static public function play(sequence:String):void
            {
                // Sanity check.
                if (!sequence)
                {
                    trace("There's nothing to play!");
                    return;
                }
    
                var aSeq:SequencePlayer = new SequencePlayer;
    
                list.push(aSeq);
    
                aSeq.sequence = sequence;
                aSeq.playNext();
            }
    
            // *** NON-STATIC PART *** //
    
            private var sequence:String;
            private var channel:SoundChannel;
    
            private function playNext():void
            {
                var aChar:String;
                var aSound:Sound;
    
                // While there are still characters in the sequence,
                // search for sound by the first character.
                // If there's no such sound - repeat.
                while (sequence)
                {
                    // Get a sound from the cache by single character.
                    aChar = sequence.charAt(0);
                    aSound = SoundCache.find(aChar);
    
                    // Remove the first character from the sequence.
                    sequence = sequence.substr(1);
    
                    // Stop searching if there is a valid next sound.
                    if (aSound) break;
                }
    
                if (aSound)
                {
                    // If there is a valid Sound object to play, then play it
                    // and subscribe for the relevant event to move to the
                    // next sound when this one is done playing.
                    channel = aSound.play();
                    channel.addEventListener(Event.SOUND_COMPLETE, onSound);
                }
                else
                {
                    // If sequence is finished and there's no valid
                    // sound to play, remove this sequence player
                    // from the keepalive list and forget about it.
                    var anIndex:int = list.indexOf(this);
                    if (anIndex > -1) list.splice(anIndex, 1);
                }
            }
    
            // Event.SOUND_COMPLETE handler.
            private function onSound(e:Event):void
            {
                // Sanity checks.
                if (!channel) return;
                if (e.target != channel) return;
    
                // Release the current SoundChannel object.
                channel.removeEventListener(Event.SOUND_COMPLETE, onSound);
                channel = null;
    
                // Move on to the next sound if any.
                playNext();
            }
        }
    }
    

    Though it all might look frightening so far, we're almost done. At this point, all you need to do to play a random sequence of sounds is to call the SequencePlayer.play(...) method. All the horrors above drills your problem down to this:

    import SequencePlayer;
    
    // It will ignore the space charaters so it's fine.
    SequencePlayer.play(" 5 + 0 ");
    

    Please keep in mind that though I tried to provide you with well-documented and working solution, I never actually tested it so forgive me a random typo if any.