Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

play a randomly generated array of audio files, one by one, in javascript

I’m on the first steps of trying to create a simon game using vanilla javascript.

I am able to generate a randomized array of colors, which then I’m hoping to pass to a playSequentially function that will play the audio files related to each color, one by one.

However, my playSequentially function is not working as expected. It often will not play a sound if that sound has already been played. However, this behavior doesn’t seem predictable. For example, given this array [‘purple’, ‘red’, ‘blue’, ‘red’, ‘purple’, ‘red’], purple will be played twice but red will only be played once. I’ve been reading documentation on MDN – looking into currentTime, or reseting the ended attribute. I’ve ask chatGPT. But to no avail. Is there a way to fix this code, or am I just going about this the wrong way entirely? Thank you

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

let greenBtn = document.getElementById("green-button");
let redBtn = document.getElementById("red-button");
let blueBtn = document.getElementById("blue-button");
let purpleBtn = document.getElementById("purple-button");
let greenAudio = document.getElementById("green-audio");
let redAudio = document.getElementById("red-audio");
let blueAudio = document.getElementById("blue-audio");
let purpleAudio = document.getElementById("purple-audio");
let playback = document.getElementById("play");
greenBtn.addEventListener("click", () => {
  greenAudio.play();
})
redBtn.addEventListener("click", () => {
  redAudio.play();
})
blueBtn.addEventListener("click", () => {
  blueAudio.play();
})
purpleBtn.addEventListener("click", () => {
  purpleAudio.play();
})
let audioArray = [greenAudio, blueAudio, redAudio, purpleAudio];
function playAudio(audio) {
  audio.play();
}
function getAudioFromColor(color) {
  switch (color) {
    case "green":
      return greenAudio;
    case "blue":
      return blueAudio;
    case "red":
      return redAudio;
    case "purple":
      return purpleAudio;
  }
}
//create random array of colors of length n
function getRandomColorArray(n) {
  let randomColorArray = []
  let colors = ["green", "blue", "red", "purple"];
  let i = 0;
  while (i < n) {
    let index = Math.floor(Math.random() * 4);
    console.log(index)
    randomColorArray.push(colors[index]);
    i++;
  }
  return randomColorArray;
}
function playSequentially(audioColorArray) {
  let delay = 500;
  let currentAudio = getAudioFromColor(audioColorArray[0]);
  currentAudio.play();
  for (let i = 0; i < audioColorArray.length - 1; i++) {
    delay += 500;
    currentAudio = getAudioFromColor(audioColorArray[i]);
    currentAudio.onended = setTimeout(() => {
      getAudioFromColor(audioColorArray[i + 1]).play();
    }, delay);
  }
}
playback.addEventListener("click", () => {
  // let randomColorArray = getRandomColorArray(5);
  let randomColorArray = ['purple', 'red', 'blue', 'red', 'purple', 'red']
  console.log(randomColorArray)
  playSequentially(randomColorArray);
});
div {
  margin: 10px;
  /* padding: 10px; */
}
.game-btn {
  border: 1px solid black;
  border-radius: 20%;
  width: 200px;
  height: 200px;
}
.green {
  background-color: green;
}
.blue {
  background-color: blue;
}
.red {
  background-color: red
}
.purple {
  background-color: purple;
}
.green:hover {
  background-color: lightgreen;
}
.blue:hover {
  background-color: lightblue;
}
.red:hover {
  background-color: lightcoral
}
.purple:hover {
  background-color: plum;
}
#play {
  width: 100px;
  background-color: pink;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<title>Document</title>
<div class="container" style="max-width: 75%;">
  <div class="row justify-content-center">
    <div class=" btn" id="play"> Playback</div>
  </div>
  <div class="row justify-content-center">
    <div class="game-btn green btn" id="green-button"></div>
    <audio id="green-audio" src="./sounds/539252-Kalimba-INTIMATE-D5-01.wav"></audio>
    <div class="game-btn blue btn" id="blue-button"></div>
    <audio id="blue-audio" src="./sounds/539256-Kalimba-INTIMATE-E6-01.wav"></audio>
  </div>
  <div class="row justify-content-center">
    <div class="game-btn red btn" id="red-button"></div>
    <audio id="red-audio" src="./sounds/539257-Kalimba-INTIMATE-F4-01.wav"></audio>
    <div class="game-btn purple btn" id="purple-button"></div>
    <audio id="purple-audio" src="./sounds/539258-Kalimba-INTIMATE-F5-01.wav"></audio>
  </div>
</div>
<script src="./assignment22.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>

>Solution :

setTimeout is not a great way when you have onended, however you need to trim the notes if you do not want to have a delay while the note ebb out.

Also you have closure issues.

Here is one way of doing it

const playSequentially = (audioColorArray) => {
  let index = 0; // Start from the first color
  const playNextAudio = () => {
    if (index < audioColorArray.length) {
      const audioElement = getAudioFromColor(audioColorArray[index]);
      audioElement.currentTime = 0; // Reset the audio time
      audioElement.play(); 
      audioElement.onended = () => {
        index++; // Move to the next index
        playNextAudio(); // Recursively call to play the next audio
      };
    }
  }
  playNextAudio(); // Start 
};
const colorArray = ['purple', 'red', 'blue', 'red', 'purple', 'red'];

playback.addEventListener("click", () => {
  colorArray.sort((a, b) => 0.5 - Math.random());
  console.log(colorArray)
  playSequentially(colorArray);
});
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading