0

So I am trying to make an app that generates music, but I cant seem to figure out how to only play one sound at a time. When i click the generate button then it plays all the sounds at once instead of one at a time. Here is my code:

var melody_notes = [A3, A4, A5, A6, B3, B4, B5, B6, C3, C4, C5, C6, D3, D4, D5, D6, E3, E4, E5, E6, F3, F4, F5, F6, G3, G4, G5, G6];

function generate() {

    for (var a = 0; a < 100; a++) {
        for (var i = 0; i < 1; i++) {
            var pick = Math.floor(Math.random() * melody_notes.length);
            var note = new Audio(melody_notes[pick]);
            note.play();
        }
    }
}

So the list up above are the sound files, then it picks a random one and plays it. The first for loop is the amount of notes in the song, and the inner for loop is the amount of notes played together. But when i press the button which activates the function plays all the notes at once. Is there any way to fix that?

Caleb Gross
  • 391
  • 3
  • 12
  • Please check: https://stackoverflow.com/questions/5915096/get-a-random-item-from-a-javascript-array – prettyInPink Sep 29 '21 at 08:35
  • Does this answer your question? [Get a random item from a JavaScript array](https://stackoverflow.com/questions/5915096/get-a-random-item-from-a-javascript-array) – prettyInPink Sep 29 '21 at 08:35
  • It chooses the random option, but it doesn't play them one at a time instead it plays the sounds all at once. I know what the problem is I just cant figure out how to fix it. – Caleb Gross Sep 29 '21 at 08:39

2 Answers2

1

You can create a promise and start the next sound when the previous one resolves.

const audios = [
  'https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3', 
  'https://dl.dropboxusercontent.com/s/h2j6vm17r07jf03/snare.mp3',
  'https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3', 
  'https://dl.dropboxusercontent.com/s/h2j6vm17r07jf03/snare.mp3'
];

async function playSounds(arr) {
  for (let i = 0; i < arr.length; i++) {
    await new Promise((resolve) => {
      sound = new Audio(arr[i]);
      sound.onended = resolve;
      sound.play();
    });
  }
}
<button onclick="playSounds(audios);">play</button>
M4C4R
  • 356
  • 4
  • 13
0

I figured it out thanks to a post that just got deleted!

async function generate() {

    for (var a = 0; a < 100; a++) {
        var pick = Math.floor(Math.random() * melody_notes.length);
        var note = new Audio(melody_notes[pick]);
        await note.play();
        sleep(500);
    }
}

function sleep(milliseconds) {
    var start = new Date().getTime();
    for (var i = 0; i < 1e7; i++) {
        if ((new Date().getTime() - start) > milliseconds) {
            break;
        }
    }
}

Whoever posted that thanks a lot! I have been trying to fix this problem for a while!

Caleb Gross
  • 391
  • 3
  • 12