添加音效用户预设

This commit is contained in:
lyswhut
2023-05-08 18:04:04 +08:00
parent df58c8eb80
commit 04337ef4b8
22 changed files with 571 additions and 60 deletions
@@ -0,0 +1,92 @@
<template>
<base-btn min :class="[$style.newPreset, {[$style.editing]: isEditing}]" :aria-label="$t('player__sound_effect_biquad_filter_save_btn')" @click="handleEditing($event)">
<svg-icon name="plus" />
<base-input ref="input" :class="$style.newPresetInput" :value="newPresetName" :placeholder="$t('player__sound_effect_biquad_filter_save_input')" @keyup.enter="handleSave($event)" @blur="handleSave($event)" />
</base-btn>
</template>
<script setup>
import { ref, nextTick } from '@common/utils/vueTools'
import { appSetting } from '@renderer/store/setting'
import { saveUserConvolutionPreset } from '@renderer/store/soundEffect'
const isEditing = ref(false)
const input = ref(false)
const newPresetName = ref('')
const handleEditing = () => {
if (isEditing.value) return
// if (!this.newPresetName) this.newPresetName = this.listName
isEditing.value = true
nextTick(() => {
input.value.$el.focus()
})
}
const handleSave = (event) => {
let name = event.target.value.trim()
newPresetName.value = event.target.value = ''
isEditing.value = false
if (!name) return
if (name.length > 20) name = name.substring(0, 20)
saveUserConvolutionPreset({
id: Date.now().toString(),
name,
source: appSetting['player.soundEffect.convolution.fileName'],
mainGain: appSetting['player.soundEffect.convolution.mainGain'],
sendGain: appSetting['player.soundEffect.convolution.sendGain'],
})
}
</script>
<style lang="less" module>
@import '@renderer/assets/styles/layout.less';
.newPreset {
position: relative;
border: 1px dashed var(--color-primary-font-hover);
// background-color: var(--color-main-background);
color: var(--color-primary-font-hover);
opacity: .7;
height: 22px;
&.editing {
opacity: 1;
width: 90px;
svg {
display: none;
}
.newPresetInput {
display: block;
}
}
:global {
.svg-icon {
vertical-align: 0;
}
}
}
.newPresetInput {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
// line-height: 16px;
background: none !important;
font-size: 12px;
text-align: center;
font-family: inherit;
box-sizing: border-box;
padding: 0 3px;
border-radius: 0;
display: none;
&::placeholder {
font-size: 12px;
}
}
</style>
@@ -0,0 +1,99 @@
<template>
<base-btn min :class="[$style.newPreset, {[$style.editing]: isEditing}]" :aria-label="$t('player__sound_effect_biquad_filter_save_btn')" @click="handleEditing($event)">
<svg-icon name="plus" />
<base-input ref="input" :class="$style.newPresetInput" :value="newPresetName" :placeholder="$t('player__sound_effect_biquad_filter_save_input')" @keyup.enter="handleSave($event)" @blur="handleSave($event)" />
</base-btn>
</template>
<script setup>
import { ref, nextTick } from '@common/utils/vueTools'
import { appSetting } from '@renderer/store/setting'
import { saveUserEQPreset } from '@renderer/store/soundEffect'
const isEditing = ref(false)
const input = ref(false)
const newPresetName = ref('')
const handleEditing = () => {
if (isEditing.value) return
// if (!this.newPresetName) this.newPresetName = this.listName
isEditing.value = true
nextTick(() => {
input.value.$el.focus()
})
}
const handleSave = (event) => {
let name = event.target.value.trim()
newPresetName.value = event.target.value = ''
isEditing.value = false
if (!name) return
if (name.length > 20) name = name.substring(0, 20)
saveUserEQPreset({
id: Date.now().toString(),
name,
hz31: appSetting['player.soundEffect.biquadFilter.hz31'],
hz62: appSetting['player.soundEffect.biquadFilter.hz62'],
hz125: appSetting['player.soundEffect.biquadFilter.hz125'],
hz250: appSetting['player.soundEffect.biquadFilter.hz250'],
hz500: appSetting['player.soundEffect.biquadFilter.hz500'],
hz1000: appSetting['player.soundEffect.biquadFilter.hz1000'],
hz2000: appSetting['player.soundEffect.biquadFilter.hz2000'],
hz4000: appSetting['player.soundEffect.biquadFilter.hz4000'],
hz8000: appSetting['player.soundEffect.biquadFilter.hz8000'],
hz16000: appSetting['player.soundEffect.biquadFilter.hz16000'],
})
}
</script>
<style lang="less" module>
@import '@renderer/assets/styles/layout.less';
.newPreset {
position: relative;
border: 1px dashed var(--color-primary-font-hover);
// background-color: var(--color-main-background);
color: var(--color-primary-font-hover);
opacity: .7;
height: 22px;
&.editing {
opacity: 1;
width: 90px;
svg {
display: none;
}
.newPresetInput {
display: block;
}
}
:global {
.svg-icon {
vertical-align: 0;
}
}
}
.newPresetInput {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
// line-height: 16px;
background: none !important;
font-size: 12px;
text-align: center;
font-family: inherit;
box-sizing: border-box;
padding: 0 3px;
border-radius: 0;
display: none;
&::placeholder {
font-size: 12px;
}
}
</style>
@@ -27,13 +27,19 @@
</div>
</div>
</div>
<div :class="['scroll', $style.saveList]">
<base-btn v-for="item in userPresetList" :key="item.id" min @click="handleSetPreset(item)" @contextmenu="handleRemovePreset(item.id)">{{ item.name }}</base-btn>
<AddConvolutionPresetBtn />
</div>
</div>
</template>
<script setup>
// import { ref } from '@common/utils/vueTools'
import { ref, onMounted } from '@common/utils/vueTools'
import { appSetting, updateSetting } from '@renderer/store/setting'
import { convolutions } from '@renderer/plugins/player'
import AddConvolutionPresetBtn from './AddConvolutionPresetBtn'
import { getUserConvolutionPresetList, removeUserConvolutionPreset } from '@renderer/store/soundEffect'
const updateConvolution = val => {
const target = convolutions.find(c => c.source == val)
@@ -54,6 +60,24 @@ const handleUpdateSendGain = (value) => {
updateSetting({ 'player.soundEffect.convolution.sendGain': Math.round(value) })
}
const handleSetPreset = (item) => {
updateSetting({
'player.soundEffect.convolution.fileName': item.source,
'player.soundEffect.convolution.mainGain': item.mainGain,
'player.soundEffect.convolution.sendGain': item.sendGain,
})
}
const userPresetList = ref([])
const handleRemovePreset = id => {
removeUserConvolutionPreset(id)
}
onMounted(() => {
getUserConvolutionPresetList().then(list => {
userPresetList.value = list
})
})
</script>
@@ -63,6 +87,7 @@ const handleUpdateSendGain = (value) => {
display: flex;
flex-flow: column nowrap;
gap: 3px;
min-height: 0;
}
.convolution {
display: flex;
@@ -110,4 +135,11 @@ const handleUpdateSendGain = (value) => {
color: var(--color-primary-font);
}
}
.saveList {
display: flex;
flex-flow: row wrap;
margin-top: 10px;
gap: 10px;
}
</style>
@@ -1,7 +1,7 @@
<template>
<div :class="$style.contnet">
<div :class="$style.header">
<h3 class="player__sound_effect_title">{{ $t('player__sound_effect_panner') }}</h3>
<div class="player__sound_effect_title" :class="$style.header">
<h3>{{ $t('player__sound_effect_panner') }}</h3>
<base-checkbox
id="player__sound_effect_panner_enabled"
:class="$style.checkbox"
@@ -11,16 +11,16 @@
/>
</div>
<div :class="$style.eqList">
<div :class="$style.eqItem">
<span :class="$style.label">{{ $t('player__sound_effect_panner_sound_r') }}</span>
<base-slider-bar :class="$style.slider" :value="appSetting['player.soundEffect.panner.soundR']" :min="1" :max="30" @change="handleUpdateSoundR" />
<span :class="[$style.value, { [$style.active]: appSetting['player.soundEffect.panner.soundR'] != 5 }]">{{ appSetting['player.soundEffect.panner.soundR'] }}</span>
</div>
<div :class="$style.eqItem">
<span :class="$style.label">{{ $t('player__sound_effect_panner_sound_speed') }}</span>
<base-slider-bar :class="$style.slider" :value="appSetting['player.soundEffect.panner.speed']" :min="1" :max="50" @change="handleUpdateSpeed" />
<span :class="[$style.value, { [$style.active]: appSetting['player.soundEffect.panner.speed'] != 25 }]">{{ appSetting['player.soundEffect.panner.speed'] }}</span>
</div>
<div :class="$style.eqItem">
<span :class="$style.label">{{ $t('player__sound_effect_panner_sound_r') }}</span>
<base-slider-bar :class="$style.slider" :value="appSetting['player.soundEffect.panner.soundR']" :min="1" :max="30" @change="handleUpdateSoundR" />
<span :class="[$style.value, { [$style.active]: appSetting['player.soundEffect.panner.soundR'] != 5 }]">{{ appSetting['player.soundEffect.panner.soundR'] }}</span>
</div>
</div>
</div>
</template>
@@ -53,9 +53,19 @@ const handleUpdateSpeed = (value) => {
<style lang="less" module>
@import '@renderer/assets/styles/layout.less';
.contnet {
padding-top: 15px;
position: relative;
display: flex;
flex-flow: column nowrap;
gap: 8px;
&:before {
.mixin-after;
position: absolute;
top: 0;
height: 1px;
width: 100%;
border-top: 1px dashed var(--color-primary-light-100-alpha-700);
}
}
.header {
display: flex;
@@ -63,7 +73,7 @@ const handleUpdateSpeed = (value) => {
justify-content: space-between;
align-items: center;
padding-bottom: 5px;
padding-top: 5px;
// padding-top: 5px;
}
.eqList {
display: flex;
@@ -1,16 +1,22 @@
<template>
<div :class="$style.contnet">
<div :class="$style.header">
<h3 class="player__sound_effect_title">{{ $t('player__sound_effect_biquad_filter') }}</h3>
<div class="player__sound_effect_title" :class="$style.header">
<h3>{{ $t('player__sound_effect_biquad_filter') }}</h3>
<base-btn min @click="handleReset">{{ $t('player__sound_effect_biquad_filter_reset_btn') }}</base-btn>
</div>
<div :class="$style.eqList">
<div v-for="(v, i) in freqs" :key="v" :class="$style.eqItem">
<span :class="$style.label">{{ labels[i] }}</span>
<base-slider-bar :class="$style.slider" :value="appSetting[`player.soundEffect.biquadFilter.hz${v}`]" :min="-20" :max="20" @change="handleUpdate(v, $event)" />
<base-slider-bar :class="$style.slider" :value="appSetting[`player.soundEffect.biquadFilter.hz${v}`]" :min="-15" :max="15" @change="handleUpdate(v, $event)" />
<span :class="$style.value">{{ appSetting[`player.soundEffect.biquadFilter.hz${v}`] }}db</span>
</div>
</div>
<div :class="['scroll', $style.saveList]">
<!-- <base-btn min @click="handleSetPreset(item)">{{ $t(`player__sound_effect_biquad_filter_preset_slow`) }}</base-btn> -->
<base-btn v-for="item in freqsPreset" :key="item.name" min @click="handleSetPreset(item)">{{ $t(`player__sound_effect_biquad_filter_preset_${item.name}`) }}</base-btn>
<base-btn v-for="item in userPresetList" :key="item.id" min @click="handleSetPreset(item)" @contextmenu="handleRemovePreset(item.id)">{{ item.name }}</base-btn>
<AddEQPresetBtn />
</div>
<!-- <div :class="$style.footer">
<base-btn min @click="handleReset">{{ $t('player__sound_effect_biquad_filter_reset_btn') }}</base-btn>
</div> -->
@@ -18,9 +24,11 @@
</template>
<script setup>
// import { reactive } from '@common/utils/vueTools'
import { freqs } from '@renderer/plugins/player'
import { onMounted, ref } from '@common/utils/vueTools'
import { freqs, freqsPreset } from '@renderer/plugins/player'
import { appSetting, updateSetting } from '@renderer/store/setting'
import AddEQPresetBtn from './AddEQPresetBtn'
import { getUserEQPresetList, removeUserEQPreset } from '@renderer/store/soundEffect'
const labels = freqs.map(num => num < 1000 ? num : `${num / 1000}k`)
@@ -39,6 +47,33 @@ const handleReset = () => {
updateSetting(setting)
}
const handleSetPreset = (item) => {
updateSetting({
'player.soundEffect.biquadFilter.hz31': item.hz31,
'player.soundEffect.biquadFilter.hz62': item.hz62,
'player.soundEffect.biquadFilter.hz125': item.hz125,
'player.soundEffect.biquadFilter.hz250': item.hz250,
'player.soundEffect.biquadFilter.hz500': item.hz500,
'player.soundEffect.biquadFilter.hz1000': item.hz1000,
'player.soundEffect.biquadFilter.hz2000': item.hz2000,
'player.soundEffect.biquadFilter.hz4000': item.hz4000,
'player.soundEffect.biquadFilter.hz8000': item.hz8000,
'player.soundEffect.biquadFilter.hz16000': item.hz16000,
})
}
const userPresetList = ref([])
const handleRemovePreset = id => {
removeUserEQPreset(id)
}
onMounted(() => {
getUserEQPresetList().then(list => {
userPresetList.value = list
})
})
</script>
<style lang="less" module>
@@ -47,6 +82,7 @@ const handleReset = () => {
display: flex;
flex-flow: column nowrap;
gap: 8px;
min-height: 0;
}
.header {
display: flex;
@@ -54,18 +90,40 @@ const handleReset = () => {
justify-content: space-between;
align-items: center;
padding-bottom: 5px;
padding-top: 5px;
// padding-top: 5px;
}
.eqList {
display: flex;
flex-flow: column nowrap;
gap: 15px;
flex-flow: row wrap;
// gap: 15px;
width: 100%;
justify-content: space-between;
position: relative;
&:before {
.mixin-after;
position: absolute;
left: 50%;
height: 100%;
border-left: 1px dashed var(--color-primary-light-100-alpha-700);
}
}
.eqItem {
display: flex;
flex-flow: row nowrap;
width: 50%;
gap: 8px;
margin-bottom: 15px;
box-sizing: border-box;
&:nth-child(odd) {
padding-right: 10px;
}
&:nth-child(even) {
padding-left: 10px;
}
&:nth-last-child(1), &:nth-last-child(2) {
margin-bottom: 0;
}
}
.label {
flex: none;
@@ -95,4 +153,11 @@ const handleReset = () => {
flex: auto;
}
.saveList {
display: flex;
flex-flow: row wrap;
margin-top: 10px;
gap: 10px;
}
</style>
@@ -1,22 +1,27 @@
<template>
<material-popup-btn :class="$style.btnContent">
<button :class="$style.btn" :aria-label="$t('player__sound_effect')">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="90%" viewBox="0 0 24 24" space="preserve">
<use xlink:href="#icon-tune-variant" />
</svg>
</button>
<template #content>
<div :class="$style.content">
<button :class="$style.btn" :aria-label="$t('player__sound_effect')" @click="visible = true">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xlink="http://www.w3.org/1999/xlink" width="90%" viewBox="0 0 24 24" space="preserve">
<use xlink:href="#icon-tune-variant" />
</svg>
</button>
<material-modal :show="visible" bg-close="bg-close" :teleport="teleport" @close="visible = false">
<!-- <main :class="$style.main"> -->
<!-- <h2 :class="$style.title">{{ $t('theme_edit_modal__title') }}</h2> -->
<div :class="$style.content">
<div :class="$style.row">
<AudioConvolution />
<AudioPanner />
</div>
<div :class="$style.row">
<BiquadFilter />
</div>
</template>
</material-popup-btn>
</div>
<!-- </main> -->
</material-modal>
</template>
<script setup>
// import { reactive, ref } from '@common/utils/vueTools'
import { ref } from '@common/utils/vueTools'
// import useNextTogglePlay from '@renderer/utils/compositions/useNextTogglePlay'
// import useToggleDesktopLyric from '@renderer/utils/compositions/useToggleDesktopLyric'
// import { musicInfo, playMusicInfo } from '@renderer/store/player/state'
@@ -27,16 +32,20 @@ import BiquadFilter from './BiquadFilter'
import AudioPanner from './AudioPanner'
import AudioConvolution from './AudioConvolution'
defineProps({
teleport: {
type: String,
default: '#root',
},
})
const visible = ref(false)
</script>
<style lang="less" module>
@import '@renderer/assets/styles/layout.less';
.btnContent {
flex: none;
height: 100%;
}
.btn {
position: relative;
// color: var(--color-button-font);
@@ -68,12 +77,40 @@ import AudioConvolution from './AudioConvolution'
}
}
.content {
.main {
min-width: 300px;
// max-height: 100%;
// overflow: hidden;
display: flex;
flex-flow: column nowrap;
padding: 5px 3px;
gap: 15px;
width: 400px;
justify-content: center;
min-height: 0;
}
// .title {
// flex: none;
// font-size: 16px;
// color: var(--color-font);
// line-height: 1.3;
// text-align: center;
// padding: 10px;
// }
.content {
display: flex;
flex-flow: row nowrap;
padding: 0 15px;
margin: 15px 0;
gap: 30px;
position: relative;
min-height: 0;
&:before {
.mixin-after;
position: absolute;
left: 50%;
height: 100%;
border-left: 1px dashed var(--color-primary-light-100-alpha-700);
}
// width: 400px;
:global {
// .player__sound_effect_contnet {
@@ -82,10 +119,16 @@ import AudioConvolution from './AudioConvolution'
.player__sound_effect_title {
// margin-bottom: 10px;
font-size: 14px;
padding-bottom: 5px;
padding-bottom: 8px;
}
}
}
.row {
width: 50%;
display: flex;
gap: 15px;
flex-flow: column nowrap;
}
</style>