Search code examples
javascriptaudiomidiweb-audio-api

Volume velocity to gain web audio


I'm trying to set a velocity value, a value that is in a midi signal to gain. The velocity ranges from 0 to 127.

The documentation on the web audio api albeit well done, doesn't really say anything about this.

At the moment I've this to play sounds :

  play(key, startTime) {    
    this.audioContext.decodeAudioData(this.soundContainer[key], (buffer) => {
      let source = this.audioContext.createBufferSource(); 
      source.buffer = buffer;                   
      source.connect(this.audioContext.destination);
      source.start(startTime);
     });
  }

I didn't find anything to use the velocity values that range from 0 to 127. However I found gain node that applies a gain.

So my function is now this:

  play(key:string, startTime, velocity) {    
    this.audioContext.decodeAudioData(this.soundContainer[key], (buffer) => {
      let source = this.audioContext.createBufferSource(); 
      source.buffer = buffer;                   
      source.connect(this.gainNode);
      this.gainNode.connect(this.audioContext.destination);
      this.gainNode.gain.value = velocity;
      source.start(startTime);
     });
  }

Eehhh... if I apply the midi velocity value to the gain, I obviously have a sound that is insanely loud. So I'd like to know either of those two questions:

  • Can I somehow use the velocity value directly ?
  • How can I convert the velocity value to gain ?

Solution

  • The MIDI specification says:

    Interpretation of the Velocity byte is left up to the receiving instrument. Generally, the larger the numeric value of the message, the stronger the velocity-controlled effect. If velocity is applied to volume (output level) for instance, then higher Velocity values will generate louder notes. A value of 64 (40H) would correspond to a mezzo-forte note […] Preferably, application of velocity to volume should be an exponential function.

    The General MIDI specifications are not any more concrete.

    The DLS Level 1 specification says:

    The MIDI Note Velocity value is converted to attenuation in dB by the Concave Transform according to the following formula:

    attendB = 20 × log10(1272 / Velocity2)

    and fed to control either the volume or envelope generator peak level.

    You then have to map this attenuation to the gain factor, i.e., gain = velocity² / 127².

    And many hardware synthesizers allow to select different curves to map the velocity to volume.