[SOLVED] Updating Music/Sounds volumes with JS

I’m wondering if someone has already found a way to decrease the volume of a song or sound using js for a wick editor game/app… (while it’s playing)

I think that I got from @pumpkinhead how to stop only one sound using js for the Space Rush game.

I don’t know how sounds work for Wick, but in JS you can change the volume with:
document.querySelector("frame").volume = 0.5;
Do you know how Wick sound works?

Nope, thats why I’m asking…

1 Like

Wick Editor uses howler.js (I got this from an old post @blurredPixels made)

Try using this to set the volume of all sounds:

Howler.volume(0.5); // Change 0.5 with a variable or any number

(Haven’t tried it yet)

3 Likes

I think that it would set all sound tracks to that volume… I guess…

1 Like

@Jovanny
I just went code diving and I found how to get and set the volume of sound attached to a frame:

  /**
   * The volume of the sound attached to the selected frame.
   * @type {number}
   */


  get soundVolume() {
    return this._getSingleAttribute('soundVolume');
  }

  set soundVolume(soundVolume) {
    this._setSingleAttribute('soundVolume', soundVolume);
  }

And this:

  /**
   * The volume of the sound attached to the frame.
   * @type {number}
   */


  get soundVolume() {
    return this._soundVolume;
  }

  set soundVolume(soundVolume) {
    this._soundVolume = soundVolume;
  }
Here's the code for volume
/**
 * Get/set the volume of this sound or of the Howl group. This method can optionally take 0, 1 or 2 arguments.
 *   volume() -> Returns the group's volume value.
 *   volume(id) -> Returns the sound id's current volume.
 *   volume(vol) -> Sets the volume of all sounds in this Howl group.
 *   volume(vol, id) -> Sets the volume of passed sound id.
 * @return {Howl/Number} Returns self or current volume.
 */
volume: function() {
  var self = this;
  var args = arguments;
  var vol, id;

  // Determine the values based on arguments.
  if (args.length === 0) {
    // Return the value of the groups' volume.
    return self._volume;
  } else if (args.length === 1 || args.length === 2 && typeof args[1] === 'undefined') {
    // First check if this is an ID, and if not, assume it is a new volume.
    var ids = self._getSoundIds();
    var index = ids.indexOf(args[0]);
    if (index >= 0) {
      id = parseInt(args[0], 10);
    } else {
      vol = parseFloat(args[0]);
    }
  } else if (args.length >= 2) {
    vol = parseFloat(args[0]);
    id = parseInt(args[1], 10);
  }

  // Update the volume or return the current volume.
  var sound;
  if (typeof vol !== 'undefined' && vol >= 0 && vol <= 1) {
    // If the sound hasn't loaded, add it to the load queue to change volume when capable.
    if (self._state !== 'loaded'|| self._playLock) {
      self._queue.push({
        event: 'volume',
        action: function() {
          self.volume.apply(self, args);
        }
      });

      return self;
    }

    // Set the group volume.
    if (typeof id === 'undefined') {
      self._volume = vol;
    }

    // Update one or all volumes.
    id = self._getSoundIds(id);
    for (var i=0; i<id.length; i++) {
      // Get the sound.
      sound = self._soundById(id[i]);

      if (sound) {
        sound._volume = vol;

        // Stop currently running fades.
        if (!args[2]) {
          self._stopFade(id[i]);
        }

        if (self._webAudio && sound._node && !sound._muted) {
          sound._node.gain.setValueAtTime(vol, Howler.ctx.currentTime);
        } else if (sound._node && !sound._muted) {
          sound._node.volume = vol * Howler.volume();
        }

        self._emit('volume', sound._id);
      }
    }
  } else {
    sound = id ? self._soundById(id) : self._sounds[0];
    return sound ? sound._volume : 0;
  }

  return self;
},

/**
 * Fade a currently playing sound between two volumes (if no id is passsed, all sounds will fade).
 * @param  {Number} from The value to fade from (0.0 to 1.0).
 * @param  {Number} to   The volume to fade to (0.0 to 1.0).
 * @param  {Number} len  Time in milliseconds to fade.
 * @param  {Number} id   The sound id (omit to fade all sounds).
 * @return {Howl}
 */
fade: function(from, to, len, id) {
  var self = this;

  // If the sound hasn't loaded, add it to the load queue to fade when capable.
  if (self._state !== 'loaded' || self._playLock) {
    self._queue.push({
      event: 'fade',
      action: function() {
        self.fade(from, to, len, id);
      }
    });

    return self;
  }

  // Make sure the to/from/len values are numbers.
  from = parseFloat(from);
  to = parseFloat(to);
  len = parseFloat(len);

  // Set the volume to the start position.
  self.volume(from, id);

  // Fade the volume of one or all sounds.
  var ids = self._getSoundIds(id);
  for (var i=0; i<ids.length; i++) {
    // Get the sound.
    var sound = self._soundById(ids[i]);

    // Create a linear fade or fall back to timeouts with HTML5 Audio.
    if (sound) {
      // Stop the previous fade if no sprite is being used (otherwise, volume handles this).
      if (!id) {
        self._stopFade(ids[i]);
      }

      // If we are using Web Audio, let the native methods do the actual fade.
      if (self._webAudio && !sound._muted) {
        var currentTime = Howler.ctx.currentTime;
        var end = currentTime + (len / 1000);
        sound._volume = from;
        sound._node.gain.setValueAtTime(from, currentTime);
        sound._node.gain.linearRampToValueAtTime(to, end);
      }

      self._startFadeInterval(sound, from, to, len, ids[i], typeof id === 'undefined');
    }
  }

  return self;
},

/**
 * Starts the internal interval to fade a sound.
 * @param  {Object} sound Reference to sound to fade.
 * @param  {Number} from The value to fade from (0.0 to 1.0).
 * @param  {Number} to   The volume to fade to (0.0 to 1.0).
 * @param  {Number} len  Time in milliseconds to fade.
 * @param  {Number} id   The sound id to fade.
 * @param  {Boolean} isGroup   If true, set the volume on the group.
 */
_startFadeInterval: function(sound, from, to, len, id, isGroup) {
  var self = this;
  var vol = from;
  var diff = to - from;
  var steps = Math.abs(diff / 0.01);
  var stepLen = Math.max(4, (steps > 0) ? len / steps : len);
  var lastTick = Date.now();

  // Store the value being faded to.
  sound._fadeTo = to;

  // Update the volume value on each interval tick.
  sound._interval = setInterval(function() {
    // Update the volume based on the time since the last tick.
    var tick = (Date.now() - lastTick) / len;
    lastTick = Date.now();
    vol += diff * tick;

    // Make sure the volume is in the right bounds.
    vol = Math.max(0, vol);
    vol = Math.min(1, vol);

    // Round to within 2 decimal points.
    vol = Math.round(vol * 100) / 100;

    // Change the volume.
    if (self._webAudio) {
      sound._volume = vol;
    } else {
      self.volume(vol, sound._id, true);
    }

    // Set the group's volume.
    if (isGroup) {
      self._volume = vol;
    }

    // When the fade is complete, stop it and fire event.
    if ((to < from && vol <= to) || (to > from && vol >= to)) {
      clearInterval(sound._interval);
      sound._interval = null;
      sound._fadeTo = null;
      self.volume(to, sound._id);
      self._emit('fade', sound._id);
    }
  }, stepLen);
},

/**
 * Internal method that stops the currently playing fade when
 * a new fade starts, volume is changed or the sound is stopped.
 * @param  {Number} id The sound id.
 * @return {Howl}
 */
_stopFade: function(id) {
  var self = this;
  var sound = self._soundById(id);

  if (sound && sound._interval) {
    if (self._webAudio) {
      sound._node.gain.cancelScheduledValues(Howler.ctx.currentTime);
    }

    clearInterval(sound._interval);
    sound._interval = null;
    self.volume(sound._fadeTo, id);
    sound._fadeTo = null;
    self._emit('fade', id);
  }

  return self;

muting works but it’s delayed by abt half a sec. when i set the value to 0.5 it doesn’t half the volume tho

Idk if this will help, but here’s how to refer to the volume of a frame with sound:

project.timeline.getChildren('Layer')[1].frames[0].soundVolume

project.timeline.getChildren(‘Layer’)[1].frames[0] refers to the frame, and soundVolume refers to the volume of that frame

You can then use something like

project.timeline.getChildren('Layer')[1].frames[0].soundVolume+=0.1;

to slowly increase the volume, or the other way around for the opposite effect.

Here’s an example file:
My Project4-5-2021_17-30-15.wick (115.4 KB)

When you play the example, watch the frame with sound. It’ll start off like this: image
Then it’ll slowly increase the volume of the frame until it looks like this: image

3 Likes

I’ll take a look to that project later today. Im wondering if we could do it with playSound(‘sound.mp3’) rather than having the volume attached to a frame…

Probably the wick playSound attached the sound to the current frame anyways. Im not sure…

Have a look here


and read about howler methods


the main issue in my opinion is that you have to have your sounds files outside the wick library

audio settings in this game


are made using howler methods

1 Like

This really does what I was needing… so Thank you @Hamzah_Al_Ani.

2 Likes