Howler.js: [Question]聽How to properly fade out and in sound sprites used for a 88-key piano

Created on 13 Mar 2020  路  3Comments  路  Source: goldfire/howler.js

Hi!

I am using a mp3 sprite containing all 88 notes of the piano. A piano keyboard lets the user hit the various keys and the proper sound sprite is played.

So far, so good.

Now I would like to implement a fade-out before the sound stops playing whenever the user releases the key. The current behaviour - a sudden and abrupt cut-off - sounds awful.

The fade-out actually works fine:

// Vue method
    stop (id) {
      howlerSoundObj.fade(0.25, 0, 250, id)
    },

but afterwards, when playing another key, the volume is messed up. Trying to implement a fade-in on the "play()" doesn't solve much:

// Vue method
    play (e) {
      const midiSoundNumber = note(e.target.dataset.name).midi
      // Fading in over 200 ms does not work
      howlerSoundObj.fade(0, .25, 200)
      howlerSoundObj.play(midiSoundNumber.toString())
    },

I don't see the mistake I am making. I don't even know, if going with sprites is the proper solution?
Can somebody please give me some advice? Thank you!

(Mentioning this (just in case): The goal is just to have some sound playing for a music theory tool, so not a having a multi-channel enable full-feature keyboard.)

Most helpful comment

On the fading in part, you want to call play first, storing the returned id, and pass that to the fade function.

All 3 comments

On the fading in part, you want to call play first, storing the returned id, and pass that to the fade function.

Wow, that was quick! Thank you so much, @themoonrat !

It seems this does the job:

      // First assign the return value of the new play() call to an id...
      const soundId = howlerSoundObj.play(midiSoundNumber.toString())
      // ...then assign the id to the fade() method
      howlerSoundObj.fade(0, 0.25, 50, soundId)

However, when the keyboard is played quickly, a sound from the previous attack can be heard, when the new sound is played. Could this be, because I handle volume wrongly? Currently it seems there is only one global volume per Howl(), but not per sprite...

Stopping the sound first, before a new one is played, helps. This is, what I eventually did:

let soundId = null

play() {
   howlerSoundObj.stop(soundId)

   soundId = howlerSoundObj.play(midiNumber)
   howlerSoundObj.fade(0, 0.25, 50, soundId)
}

stop() {
   howlerSoundObj.fade(0.25, 0, 50, soundId)
}

Thank you again, @themoonrat !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jacobedawson picture jacobedawson  路  3Comments

SandMoshi picture SandMoshi  路  3Comments

lili21 picture lili21  路  4Comments

kamkha picture kamkha  路  3Comments

Glutch picture Glutch  路  3Comments