Play 2 Sounds One after the Other

I want to add two sounds to an onEvent that will play one at a time instead of at the same time. Is this possible? If we put two playSound commands then they play at the same time even when the loop is set to false.

Hi @tdean1,

To make the sounds play separately, you’ll need to tell the onEvent which sound to play first and for how long and then which sound to play next. I think the easiest way to do this (although I’m sure there are many ways) is to use the setTimeOut block (found in the blue control block section). The first playSound block would be setup normally in the onEvent. The second playSound would be inside the setTimeOut block and the miliseconds would be set to the length of the first sound.

Good luck!
~Michelle

Hello @tdean1,

As @melynn states the best way to do with what your doing is by using a structured object with properties containing the sound and the duration of ms the song has 1000ms=1s so you could possibly program something to take in such parameters i figured you may want a proof of concept so I’ll put some demo code below

var musicInfo = {
    "sound://category_music/8bit_game_over_1.mp3": 4e3, // 4 seconds
    "sound://category_music/fun_game_win_musical_4.mp3": 3e3, // 3 seconds
    queue: [],
    playSync: function () {
        // exits if no songs are applied we ignore them
        if (arguments.length < 1) { return }
        // for reference context in asyncPlay
        var self = this;
        // checks if there's a running instance in asyncPlay
        var checksum = self.queue.length;
        // adds songs to the queue
        self.queue = self.queue.concat(arguments);
        // exits if the inital queue was occupied
        if (checksum > 0) { return }
        // handles songs at exact playtimes and orders them effectively
        (function asyncPlay(index) {
            // shortens reference to property
            var args = self.queue;
            // playSound(<string>, <boolean>, <function>?)
            playSound(args[index], false, function () {
                // this runs as soon as the song is loaded in for consistent results
                if (index < args.length-1) {
                    // recalls if the queue still has items left or were added by other calls
                    setTimeout(asyncPlay.bind(null, index+1), self[args[index]]);
                } else {
                    // clears current queue and removes the queue cache
                    self.queue = [];
                }
            });
        })(0)
    }
}
musicInfo.playSync("sound://category_music/8bit_game_over_1.mp3", "sound://category_music/fun_game_win_musical_4.mp3");
musicInfo.playSync("sound://category_music/8bit_game_over_1.mp3", "sound://category_music/fun_game_win_musical_4.mp3");

Note that stopSound() will not effect this since it is running via a callout loop you will have to make a function that does that or stops the sound or clears the queue manually

also i ended up making a library module for it but i wouldn’t recommend it to students who are starting out

var SyncPlay = (function () {
    function SyncPlay() {
        this.addSounds.apply(this, arguments);
        this.callout = -1;
        this.index = 0;
        this.queue = [];
        this.loop = false;
        this.mute = false;
    }
    SyncPlay.prototype.addSounds = function () {
        for (var i = 0; i < arguments.length; i += 2) {
            this[arguments[i]] = arguments[i + 1];
        }
    }
    SyncPlay.prototype.playSync = function () {
        if (arguments.length < 1) { return }
        var self = this;
        var checksum = self.queue.length;
        self.queue = self.queue.concat(arguments);
        if (checksum > 0) { return }
        (function asyncPlay() {
            var args = self.queue;
            playSound(self.mute ? "" : args[self.index], false, function () {
                if (self.index < args.length - 1) {
                    self.callout = setTimeout(function () {
                        if (self.queue.length > 0) {
                            self.index += 1;
                            asyncPlay()
                        }
                    }, self[args[self.index]]);
                } else {
                    self.callout = self.loop ? setTimeout(function(){self.index = 0; asyncPlay()}, self[args[self.index]]) :
                        setTimeout(self.stopSync.bind(self), self[args[self.index]]);
                }
            });
        })()
    }
    SyncPlay.prototype.skipSync = function () {
        if (!this.loop && this.index >= this.queue.length - 1) { return this.stopSync() }
        stopSound(this.queue[this.index])
        clearTimeout(this.callout);
        this.index = this.index >= this.queue.length-1 ? 0: this.index + 1;
        var nqueue = [].concat(this.queue);
        this.queue = [];
        this.playSync.apply(this, nqueue);
    }
    SyncPlay.prototype.stopSync = function () {
        stopSound(this.queue[this.index])
        clearTimeout(this.callout);
        this.callout = -1;
        this.index = 0;
        this.queue = [];
    }
    return SyncPlay;
})()

the code i wrote is now a modular library here is the the key if you wish to use this as well eimPrJpoVnzFwRdKkY-eq4jEdTDmnMvY1kS0xjEPodA though my original mock up code is probably better than the library i provided

1 Like