1

I'm looking to have an image, that when clicked plays a sound clip (from a list of sound clips) without repeating the same clip (until the user goes through the whole list of sounds.)

At the moment my code works but plays any one of my sound clips randomly and repeats a lot.

If anyone knows how to tweak this to make it play every clip in the list at least once before repeating that would be brilliant!

This is the code I'm using at the moment:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script>
function playSounds() {
    var sounds = [
        "AUDIO URL",
        "AUDIO URL",
        "AUDIO URL",
        "AUDIO URL",
        "AUDIO URL"
    ];

    var index = Math.floor(Math.random() * (sounds.length));
    $("#element").html("<embed src=\"" + sounds[index] + "\" hidden=\"true\" autostart=\"true\" />");
}
</script>

<a onclick="playSounds()"><img src="IMAGE URL" width="300px" id="ImageButton1"></a>

I'm guessing it's something to do with the Math.random() part of the code?

cmbuckley
  • 40,217
  • 9
  • 77
  • 91
Adam
  • 43
  • 1
  • 4

3 Answers3

3

You can use the Array as playlist and maintain the played sounds in a second array. Check my JSfiddle

<a onclick="playSounds()">
   <img src="http://www.stephaniequinn.com/Ani-Piano.gif" width="300px" id="ImageButton1">
</a>
<div id="element"></div>
<script>
var sounds = ["http://www.stephaniequinn.com/Music/Allegro%20from%20Duet%20in%20C%20Major.mp3",
              "http://www.stephaniequinn.com/Music/Canon.mp3",
              "http://www.stephaniequinn.com/Music/Handel%20Royal%20Fireworks%20-%2007.mp3",
              "http://www.stephaniequinn.com/Music/Commercial%20DEMO%20-%2009.mp3"],
    oldSounds = [];

var playSounds = function () {
    var index = Math.floor(Math.random() * (sounds.length)),
        thisSound = sounds[index];

        oldSounds.push(thisSound);
        sounds.splice(index, 1);

        if (sounds.length < 1) {
            sounds = oldSounds.splice(0, oldSounds.length);
        }

        $("#element").html("<audio autoplay><source src=\"" + thisSound + "\" type=\"audio/mpeg\"><embed src=\"" + thisSound + "\" hidden=\"true\" autostart=\"true\" /></audio>");
}
</script>
jkutianski
  • 580
  • 6
  • 16
1

I haven't ran the following code but the outline should be enough. This will always play the sounds in random order. The steps are:

  1. generate the random indices in a loop until we found one that has not been played yet
  2. when we find one that's not been played add it to an array for future reference and play it
  3. we know we've played all of the sounds when the array's length equals that of the sounds' array. At this point we empty the array and carry on.

    var playedSounds = [];
    
    var sounds = [
        "AUDIO URL",
        "AUDIO URL",
        "AUDIO URL",
        "AUDIO URL",
        "AUDIO URL"
    ];
    
    function hasPlayed(sound) {
    
        if (playedSounds.length == sounds.length) {
    
            // We've played all of the sounds. Reset and start again.
            playedSounds = [];
            playedSounds.push(sound);
            return false;
    
        }
    
        // We haven't played all the sounds yet but check to see whether we've played the current one.
        for (var i = 0; i < playedSounds.length; i++)
            if (playedSounds[i] == sound)
                return true;
    
        // Note that we've now played this sound.
        playedSounds.push(sound);
        return false;
    
    }
    
    function playSounds() {
    
        var index = Math.floor(Math.random() * (sounds.length));
    
        // Loop until we've found a sound that we've not yet played.
        while (hasPlayed(index)) {
    
            index = Math.floor(Math.random() * (sounds.length));
    
        }
    
        $("#element").html("<embed src=\"" + sounds[index] + "\" hidden=\"true\" autostart=\"true\" />");
    
    }
    
Greg Ross
  • 3,479
  • 2
  • 27
  • 26
  • Do you know how to get this code to work on mobile and tablet browsers? – Adam Nov 28 '13 at 16:43
  • This is the code I'm using http://jsfiddle.net/adamsears/kZF9T/ - which won't work on mobile/tablet – Adam Dec 03 '13 at 19:05
0

I would be tempted to do something like this (JSFiddle example):

var sounds = [];

// Return the full list of URLs in random order
function getSounds() {
    return [
        'url1',
        'url2',
        'url3'
    ].sort(function () {
        // http://stackoverflow.com/a/18650169/283078
        return (.5 - Math.random());
    });
}

// Play the next sound
function playSound() {
    if (!sounds.length) {
        // Get the list of sounds (random order)
        sounds = getSounds();
    }

    // Pops a URL every time, ensuring all are played exactly once
    $("#element").html(
        '<embed src="' + sounds.pop() +
        '" hidden="true" autostart="true" />'
    );

    // Once all the URLs have been popped, the process starts again
}
cmbuckley
  • 40,217
  • 9
  • 77
  • 91
  • Brilliant, thanks a lot, it worked! The only issue now is that the audio clips no longer autostart on page load. How could I solve this? – Adam Nov 26 '13 at 22:20
  • Have you tried [the updated JSFiddle](http://jsfiddle.net/cbuckley/FdLge/)? I've copied your embed code, so there shouldn't be any difference to the autostart. – cmbuckley Nov 26 '13 at 22:22
  • Do you know how to get this type of code to work on mobile and tablet browsers? – Adam Nov 28 '13 at 16:43
  • You need a user interaction to start your audio, otherwise it won't autoplay: http://stackoverflow.com/questions/13266474/autoplay-audio-on-mobile-safari – cmbuckley Nov 29 '13 at 10:10
  • I have an image that users click to make the audio clip play, can I get the audio to play on mobile when they click the image like on desktop? - I don't mind losing the autoplay on mobile – Adam Nov 29 '13 at 12:30
  • This is the code I'm using http://jsfiddle.net/adamsears/kZF9T/ - which won't work on mobile/tablet – Adam Dec 03 '13 at 19:05
  • None of the examples (mine or others) are likely to work on mobile or tablet. You'd need to solve this in a *very* different way to work on mobile — see my linked question above. You'd need to start thinking about audio sprites, which makes the whole problem a lot more complicated. You should read some of the other SO questions on the topic, or ask another one yourself. – cmbuckley Dec 03 '13 at 19:44