Created
June 26, 2023 21:45
-
-
Save jamiebuilds/da15b1272716708bcf7decc39b6cd1b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* If you have a volume input (0 to 1), such as a slider, use this to convert | |
* it to a logarithmic volume that is closer to human perception (0 to 1). | |
* | |
* A more robust approach would use a Fletcher-Munson curve, however this is a | |
* close enough approximation for most use cases. | |
* | |
* You can customize the curve to your liking, generally 3-4 is a good value. | |
* | |
* The inverse of this function is {@link convertVolumeToInput}. | |
* | |
* @example | |
* ```html | |
* <audio id="audio" hidden src="sound.mp3" /> | |
* <input id="volume" type="range" min="0" max="1" step="0.01" value="0.5"> | |
* <script type="module"> | |
* import { createAudioManager, convertInputToVolume } from 'audioboy/volume' | |
* document.querySelector('#volume').addEventListener('change', () => { | |
* document.querySelector('#audio').volume = convertInputToVolume(volume.valueAsNumber) | |
* }) | |
* </script> | |
* ``` | |
* | |
* @see https://www.dr-lex.be/info-stuff/volumecontrols.html | |
*/ | |
export function convertInputToVolume(input: number, curve = 4) { | |
return input ** curve | |
} | |
/** | |
* If you have a logarithmic volume you can use this to convert it to a linear | |
* volume. You should use the same curve value that you used to convert the | |
* input. | |
* | |
* This is the inverse of {@link convertInputToVolume}. | |
* | |
* @see https://www.dr-lex.be/info-stuff/volumecontrols.html | |
*/ | |
export function convertVolumeToInput(volume: number, curve = 4) { | |
return volume ** (1 / curve) | |
} | |
/** @internal */ | |
function convertDecibelToVolumeUnsafe(db: number) { | |
return 10 ** (db / 20) | |
} | |
/** | |
* Convert a volume into a decibel value. | |
* | |
* The inverse of this function is {@link convertDecibelToVolume}. | |
* | |
* Note: If you're unfamiliar, decibels work a bit differently than most units. | |
* | |
* Decibels are a logarithmic unit of measurement. This means that each 10db | |
* increase is approximately twice as loud as the previous 10db increase. | |
* | |
* For example: | |
* - 0db is the faintest sound that humans can hear. | |
* - 10db is approximately twice as loud as 0db. | |
* - 20db is approximately twice as loud as 10db. | |
* - and so on... | |
* | |
* Because 0db is the faintest sound that humans can hear, you can't have a | |
* negative decibel value, where each -10db decrease is approximately half as | |
* loud as the previous -10db decrease. | |
* | |
* If you had a volume of `0` then it would be `-Infinity` decibels. To avoid | |
* returning `-Infinity` we use `minDb` to set the minimum decibel value. | |
* | |
* If you want to display negative decibel values to the user, you can use | |
* `minDb` to set the minimum decibel value. | |
* | |
* The inverse of this function is {@link convertDecibelToVolume}. | |
*/ | |
export function convertVolumeToDecibel(volume: number, minDb = 0): number { | |
return volume <= convertDecibelToVolumeUnsafe(minDb) | |
? minDb | |
: 20 * Math.log10(volume) | |
} | |
/** | |
* Convert a decibel value into a volume. | |
* | |
* The inverse of this function is {@link convertVolumeToDecibel}. | |
*/ | |
export function convertDecibelToVolume(decibel: number, minDb = 0): number { | |
return decibel <= minDb ? 0 : convertDecibelToVolumeUnsafe(decibel) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment