3

I need to play some sounds in howler.js the thing is that I don't know how to chain it.

For example, at string BCG

would need to play b.ogg then c.ogg and finally g.ogg

If I just use (after loading):

sound.play('b');
sound.play('c');
sound.play('g');

All of them start and overlap which isn't what I need.

I see there's a onend property, however can't figure out how to use it properly.

Regards.

James Simpson
  • 13,488
  • 26
  • 83
  • 108
Javier S
  • 115
  • 2
  • 13

4 Answers4

7

Here is my simple solution, I am using tiny files so download delay is not an issue. sound is global in this case

function play_audio(file_names) {
    sound = new Howl({
        src: [audio_url+file_names[0]],
        volume: 0.5,
        onend: function() {
            file_names.shift();
            if (file_names.length > 0) {
                play_audio(file_names);
            }
        }
    });      
    sound.play();
}
Fong
  • 105
  • 1
  • 8
  • What does you play play_audio(file_names); do can you share the code? – Alex Onozor Jun 01 '18 at 07:36
  • files names is a list of mp3 files var sound_test = [ 'siren.mp3', 'test.mp3']; so I call it like play_audio(sound_test); – Fong Jun 19 '18 at 18:26
  • Is there a way to preload the audio files when doing this? Since preload only happens when a new Howl is defined, there can be a delay before the next track plays if it only loads "onend" of the first track. – Toma Nistor May 12 '21 at 21:58
5

You could use this code whic doesn't require sprites (jsfiddle, Github issue) :

var playlist = function(e) {
    // initialisation:
      pCount = 0;
      playlistUrls = [
        "https://upload.wikimedia.org/wikipedia/commons/8/8a/Zh-Beijing.ogg",
        "https://upload.wikimedia.org/wikipedia/commons/8/8a/Zh-Beijing.ogg",
        "./audio/a.mp3",
        "./audio/b.mp3",
        "./audio/c.mp3",
        "./audio/d.mp3"
        ], // audio list
      howlerBank = [],
      loop = true;

    // playing i+1 audio (= chaining audio files)
    var onEnd = function(e) {
      if (loop === true ) { pCount = (pCount + 1 !== howlerBank.length)? pCount + 1 : 0; }
      else { pCount = pCount + 1; }
      howlerBank[pCount].play();
    };

    // build up howlerBank:     
    playlistUrls.forEach(function(current, i) {   
      howlerBank.push(new Howl({ urls: [playlistUrls[i]], onend: onEnd, buffer: true }))
    });

    // initiate the whole :
        howlerBank[0].play();
}

Please share back your variation if you do one.

Hugolpz
  • 17,296
  • 26
  • 100
  • 187
4

You could create a function playString(yourString) that will read each character and dynamically set the onend property of your sound. The following example should play B C G A C:

var sound = new Howl({
    urls: ['http://shrt.tf/abcdefg.mp3'],
    volume: 1,
    sprite: {
        a: [0, 600],
        b: [700, 500],
        c: [1200, 600],
        d: [1900, 500],
        e: [2400, 500],
        f: [2900, 500],
        g: [3400, 500],
    }
});

Howl.prototype.playString = function(str){
    if(str.length>1){
        this._onend[0] = function(){this.playString(str.substring(1,str.length));};
    } else {
        this._onend[0] = function(){};
    }
    if(str.length>0){
        this.play(str.substring(0,1));
    }
};

sound.playString('bcgac');
<script src="http://shrt.tf/howler.js"></script>

Note that you could also tweak this function to work when a character is not in the sprite, or to use an array of names instead of a string.

blex
  • 24,941
  • 5
  • 39
  • 72
  • Thank you very much, was having a really bad time trying to figure out this. – Javier S Sep 29 '14 at 19:52
  • blex, where did you host your files that gave you the link http://shrt.tf/abcdefg.mp3 I have been looking for something like that so that I can test sound javascript programming. – Christopher Gaston Sep 11 '15 at 02:32
  • Hi @ChristopherGaston that is my personnal testing server. If you don't want to buy one, you could install a local server on your computer easily, using WAMP for Windows, or MAMP for Mac. Then, you'll be able to access your files via ˋhttp://localhost/your_files`. – blex Sep 11 '15 at 06:29
0

Simple solution to chain audio one after another. Code also does not create a new instance of Howl for every audio file in the list. I use audio sprites here.

const playSounds = (_audioList) => {
let sound = new Howl({
  src: ["/effects/effects.webm", "/effects/effects.mp3"],
  sprite: {
    a: [5000, 3648.004535147393],
    b: [14000, 2832.0181405895682],
    c: [57000, 2712.0181405895705],
  },
});
sound.play(_audioList.shift());

sound.on("end", () => {
  _audioList.length > 0 && sound.play(_audioList.shift());
});

playSounds(["a", "b", "c"];
tchoe
  • 38
  • 5