0

Having issues to get Tone Player to play anything, here is my simple VueJs code:

<template>
  <div>
    <h1>Simple Tone.js Demo</h1>
    <button style="background-color: cadetblue; padding: 4px 10px;" @click="play">Play</button>
  </div>
</template>

<script>
import * as Tone from "tone";

export default {
  data() {
    return {
      player: null,
    };
  },
  methods: {
    async play() {
      try {
        console.log("Tone.js context state:", Tone.context.state);
        if (Tone.context.state !== "running") {
          await Tone.start();
          console.log("audio context started");
        }
        this.player.start();
      } catch (error) {
        console.error("Error during playback:", error.message, error);
      }
    },

    async initializePlayer() {
      console.log(Tone.context.state);

      try {
        this.player = await new Tone.Player({
          url: "/sounds/rain.wav",
          loop: true,
          autostart: false,
        }).toDestination();

        this.player.loaded;
      } catch (error) {
        console.error("Error loading audio file:", error);
      }
      console.log("Audio file loaded", this.player.loaded);
    },
  },
  created() {
    this.initializePlayer();
  },
};
</script>

The sound I am loading exists at the correct location sound/rain.wav and browser is able to open it correctly if I enter it's path in chrome http://localhost:5173/sounds/rain.wav enter image description here

output I get from running the app:

enter image description here

Can somebody knowledgable with Tone.js help me get the Player to play a single file? I've spent whole day on this and even engaged with GPT4 but I got the same issue, Player is unable to play a simple file.

niko craft
  • 2,893
  • 5
  • 38
  • 67
  • 1
    This might help: https://stackoverflow.com/questions/49930680/how-to-handle-uncaught-in-promise-domexception-play-failed-because-the-use – Cornel Mar 18 '23 at 16:43

1 Answers1

1

I guess the error happens because the Player is not yet done with the download of the audio.

The constructor doesn't return a promise. If you want to wait for the Player to be ready you need to pass an onload function. It can be used to wait for the Player to be ready by wrapping it in a promise.

this.player = await new Promise((resolve, reject) => {
    const player = new Tone.Player({
        loop: true,
        onerror: (err) => reject(err),
        onload: () => resolve(player),
        url: '/sounds/rain.wav'
    });
});

this.player.toDestination();
chrisguttandin
  • 7,025
  • 15
  • 21