parent
800105e2e6
commit
8d9e7ca52d
|
@ -0,0 +1 @@
|
|||
Logarithmic scale for volume slider (#1222)
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
// Provides functions to convert between linear and logarithmic volume scales.
|
||||
// The logarithmic volume from the UI is converted to a linear volume with a
|
||||
// logarithmic function like exp(b*x)/a.
|
||||
// Compare https://www.dr-lex.be/info-stuff/volumecontrols.html for how the
|
||||
// values for a and b got derived.
|
||||
|
||||
const PARAM_A = 1000
|
||||
const PARAM_B = Math.log(1000) // ~ 6.908
|
||||
|
||||
function toLinearVolumeScale(v) {
|
||||
// Or as approximation:
|
||||
// return Math.pow(v, 4)
|
||||
if (v == 0.0) {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return Math.min(Math.exp(PARAM_B * v) / PARAM_A, 1.0)
|
||||
}
|
||||
|
||||
function toLogarithmicVolumeScale(v) {
|
||||
// Or as approximation:
|
||||
// return Math.exp(Math.log(v) / 4)
|
||||
if (v == 0.0) {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
return Math.log(v * PARAM_A) / PARAM_B
|
||||
}
|
||||
|
||||
exports.toLinearVolumeScale = toLinearVolumeScale
|
||||
exports.toLogarithmicVolumeScale = toLogarithmicVolumeScale
|
|
@ -29,7 +29,7 @@
|
|||
<input
|
||||
id="volume-slider"
|
||||
type="range"
|
||||
step="0.05"
|
||||
step="0.02"
|
||||
min="0"
|
||||
max="1"
|
||||
v-model="sliderVolume" />
|
||||
|
@ -38,6 +38,7 @@
|
|||
</template>
|
||||
<script>
|
||||
import { mapState, mapGetters, mapActions } from "vuex"
|
||||
import { toLinearVolumeScale, toLogarithmicVolumeScale } from '@/audio/volume'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
|
@ -49,10 +50,10 @@ export default {
|
|||
computed: {
|
||||
sliderVolume: {
|
||||
get () {
|
||||
return this.$store.state.player.volume
|
||||
return toLogarithmicVolumeScale(this.$store.state.player.volume)
|
||||
},
|
||||
set (v) {
|
||||
this.$store.commit("player/volume", v)
|
||||
this.$store.commit("player/volume", toLinearVolumeScale(v))
|
||||
}
|
||||
},
|
||||
labels () {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import { expect } from 'chai'
|
||||
|
||||
import { toLinearVolumeScale, toLogarithmicVolumeScale } from '@/audio/volume'
|
||||
|
||||
describe('store/auth', () => {
|
||||
describe('toLinearVolumeScale', () => {
|
||||
describe('it should return real 0', () => {
|
||||
expect(toLinearVolumeScale(0.0)).to.equal(0.0)
|
||||
})
|
||||
|
||||
describe('it should have logarithmic scale', () => {
|
||||
expect(2 * toLinearVolumeScale(0.5)).to.be.closeTo(toLinearVolumeScale(0.6), 0.001)
|
||||
})
|
||||
|
||||
describe('it should return full volume', () => {
|
||||
expect(toLogarithmicVolumeScale(1.0)).to.be.closeTo(1.0, 0.001)
|
||||
})
|
||||
})
|
||||
|
||||
describe('toLogarithmicVolumeScale', () => {
|
||||
describe('it should return real 0', () => {
|
||||
expect(toLogarithmicVolumeScale(0.0)).to.equal(0.0)
|
||||
})
|
||||
|
||||
describe('it should have logarithmic scale', () => {
|
||||
expect(toLogarithmicVolumeScale(0.6)).to.be.closeTo(0.9261, 0.001)
|
||||
expect(toLogarithmicVolumeScale(0.7)).to.be.closeTo(0.9483, 0.001)
|
||||
})
|
||||
|
||||
describe('it should return full volume', () => {
|
||||
expect(toLogarithmicVolumeScale(1.0)).to.be.closeTo(1.0, 0.001)
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue