How to implement a logarithmic range slider for audio?

663 Views Asked by At

Humans don't perceive sound linearly. We perceive sound on a logarithmic scale like so:

Linear Scale        0   1   2   3   4   5   6   7   8   9   10   (+1)
Logarithmic Scale   1   2   4   8  16  32  64  128 256 512 1024  (x2)

This creates a problem when trying to use an <input type="range" /> as an audio fader because the quiet sound takes up most of the scale and then gets loud super fast at the end.

Anyone know how to implement a logarithmic scale on a range input? I made this audio mixer but I was never able to figure out how to implement a logarithmic range slider. https://codesandbox.io/s/audio-mixer-linear-35cl7k?file=/src/components/ChannelStrip.js

1

There are 1 best solutions below

3
On

This got it working.

function scale(val, f0, f1, t0, t1) {
  return ((val - f0) * (t1 - t0)) / (f1 - f0) + t0;
}

function changeVolume(e) {
  const value = parseInt(e.target.value, 10);
  const vol = Math.log(value + 101) / Math.log(113);
  const scaledVol = scale(vol, 0, 1, -100,12);
  channel.set({ volume: scaledVol });
  setVolume(Math.round(scaledVol));
}

<input
  type="range"
  min={-100}
  max={12}
  step={0.1}
  onChange={changeVolume}
/>

function scale(val, f0, f1, t0, t1) 
{
  return ((val - f0) * (t1 - t0)) / (f1 - f0) + t0;
}

document.querySelector("#slider").addEventListener("change", function(e)
{
  const value = parseInt(e.target.value, 10);
  const vol = Math.log(value + 101) / Math.log(113);
  const scaledVol = scale(vol, 0, 1, -100, 12);

  document.querySelector("#vol").innerText = vol;
  document.querySelector("#scaledVol").innerText = scaledVol;
});
<input id="slider" type="range" min="-100" max="12" step="0.1" />

<div>
    <div>Volume : <span id="vol"></span></div>
    <div>Scaled : <span id="scaledVol"></span></div>
</div>