2

TL;DR: How can I access the audio instances created in the callback of createAdio?

I have the following code in my p5 sketch

  // in preload
  sound_a = createAudio('sound_a.mp3'); 

  // in setup
  sound_a.loop();
  sound_a.volume(0.2);
  sound_a.play();

This does what I want it to do. However, in my current circumstances, I have multiple audio files for which I wanted to call the same functions. I would want to use a callback to apply the loop, volume and play. My intended behavior is something like this:

  // in preload - this would just be a loop 
  sound_a = createAudio('sound_a.mp3', audio_callback); 
  sound_b = createAudio('sound_b.mp3', audio_callback); 
  .....
  sound_z = createAudio('sound_z.mp3', audio_callback); 

  function audio_callback(audio) {
        audio.loop();
        audio.volume(0.2);
        audio.play();
  }

However, the callback is not passed any arguments (i.e., console.log(audio) returns undefined and audio.loop() throws the expected errors.). How can I access the audio created in the callback?

Mitchell van Zuylen
  • 3,905
  • 4
  • 27
  • 64

1 Answers1

0

Whenever you're doing sound_a, sound_b, ... sound_z, you probably want an array. You can then use loops to avoid repetition and solve the problem you're having by binding an index i to each sound:

const urls = [
  "https://upload.wikimedia.org/wikipedia/commons/f/f7/BILIIE_EILISH.ogg",
  "https://upload.wikimedia.org/wikipedia/commons/7/7f/Bluetooth.ogg",
  "https://upload.wikimedia.org/wikipedia/commons/8/8d/Bismarck71_English_Voice_Sample_%28North_Wind_%26_Sun%29.ogg",
];
let sounds;

function preload() {
  sounds = urls.map((url, i) =>
    createAudio(url, () => {
      sounds[i].volume(0.2);

      // prohibited due to autoplay policy
      // sounds[i].loop();
      // sounds[i].play();
    })
  );
}

function setup() {}

function mousePressed() {
  sounds.forEach(e => {
    e.loop();
    e.play();
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
<h1>Click anywhere to play</h1>
<h4>File attribution:</h4>
<p>
  <a href="https://commons.wikimedia.org/wiki/File:BILIIE_EILISH.ogg">Laidaiturrate</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
</p>
<p>
  <a href="https://commons.wikimedia.org/wiki/File:Bluetooth.ogg">Sorondo27</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
</p>
<p>
  <a href="https://commons.wikimedia.org/wiki/File:Bismarck71_English_Voice_Sample_(North_Wind_%26_Sun).ogg">Bismarck71</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
</p>

You could also put the audio object in a data structure alongside each sound rather than in a separate array:

const sounds = [
  {url: "https://upload.wikimedia.org/wikipedia/commons/f/f7/BILIIE_EILISH.ogg"},
  {url: "https://upload.wikimedia.org/wikipedia/commons/7/7f/Bluetooth.ogg"},
  {url: "https://upload.wikimedia.org/wikipedia/commons/8/8d/Bismarck71_English_Voice_Sample_%28North_Wind_%26_Sun%29.ogg"},
];

function preload() {
  sounds.forEach(e => {
    e.audio = createAudio(e.url, () => {
      e.audio.volume(0.2);

      // prohibited due to autoplay policy
      // e.audio.loop();
      // e.audio.play();
    })
  });
}

function setup() {}

function mousePressed() {
  sounds.forEach(e => {
    e.audio.loop();
    e.audio.play();
  });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
<h1>Click anywhere to play</h1>
<h4>File attribution:</h4>
<p>
  <a href="https://commons.wikimedia.org/wiki/File:BILIIE_EILISH.ogg">Laidaiturrate</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
</p>
<p>
  <a href="https://commons.wikimedia.org/wiki/File:Bluetooth.ogg">Sorondo27</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
</p>
<p>
  <a href="https://commons.wikimedia.org/wiki/File:Bismarck71_English_Voice_Sample_(North_Wind_%26_Sun).ogg">Bismarck71</a>, <a href="https://creativecommons.org/licenses/by-sa/4.0">CC BY-SA 4.0</a>, via Wikimedia Commons
</p>

You might wish to open an issue or a PR for implementing the audio as a parameter to the callback.

ggorlen
  • 44,755
  • 7
  • 76
  • 106