From 8079149ac35b6bb14d802ff0d3971ba6fa277448 Mon Sep 17 00:00:00 2001 From: toyobayashi Date: Tue, 4 Jan 2022 23:47:48 +0800 Subject: [PATCH] feat(live): add bgm volume slider --- app/src/ts/renderer/audio.ts | 20 ++++++++++++++++++-- app/src/ts/renderer/mishiro-live.ts | 10 ++++++++++ app/src/vue/view/MishiroLive.vue | 7 ++++++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/app/src/ts/renderer/audio.ts b/app/src/ts/renderer/audio.ts index 8912ba7..93b1c6e 100644 --- a/app/src/ts/renderer/audio.ts +++ b/app/src/ts/renderer/audio.ts @@ -10,6 +10,7 @@ const { Acb } = window.node.acb class MishiroAudio extends EventEmitter { #ctx: AudioContext = new AudioContext() + #gainNode = this.#ctx.createGain() #startedAt: number = 0 // absolute time #pausedAt: number = 0 // relative time @@ -92,6 +93,21 @@ class MishiroAudio extends EventEmitter { return this.#duration } + public get volume (): number { + return this.#gainNode.gain.value + } + + public set volume (value: number) { + if (Number.isNaN(value)) return + this.#gainNode.gain.value = value > 1 ? 1 : (value < 0 ? 0 : value) + this.emit('volumechange') + } + + public constructor () { + super() + this.#gainNode.connect(this.#ctx.destination) + } + private _initSource (audioBuffer: AudioBuffer, clearOnEnded = false): void { try { if (this.#source) { @@ -109,14 +125,14 @@ class MishiroAudio extends EventEmitter { this.#source.onended = () => { this.emit('ended') } - this.#source.connect(this.#ctx.destination) + this.#source.connect(this.#gainNode) } public async playRawSide (src: string | BufferLike): Promise { const audioBuffer = await decodeAudioBuffer(this.#ctx, src) let source = this.#ctx.createBufferSource() source.buffer = audioBuffer - source.connect(this.#ctx.destination) + source.connect(this.#gainNode) source.start(0) source.onended = () => { source.disconnect() diff --git a/app/src/ts/renderer/mishiro-live.ts b/app/src/ts/renderer/mishiro-live.ts index 1d03b91..829084f 100644 --- a/app/src/ts/renderer/mishiro-live.ts +++ b/app/src/ts/renderer/mishiro-live.ts @@ -64,6 +64,7 @@ export default class extends Vue { total: number = 0 current: number = 0 text: string = '' + playVolume: number = this.bgm.volume * 100 activeAudio: BGM | Live = {} as any duration: number = 100 currentTime: number = 0 @@ -124,6 +125,12 @@ export default class extends Vue { this.bgm.currentTime = Number(target.value) } + onVolumeChange (event: Event): void { + const value = Number((event.target as HTMLInputElement).value) + if (Number.isNaN(value)) return + this.bgm.volume = value / 100 + } + stopDownload (): void { this.playSe(this.cancelSe) this.current = 0 @@ -719,6 +726,9 @@ export default class extends Vue { mounted (): void { this.$nextTick(() => { + this.bgm.on('volumechange', () => { + this.playVolume = this.bgm.volume * 100 + }) this.bgm.on('timeupdate', () => { this.currentTime = this.bgm.currentTime for (let i = this.allLyrics.length - 1; i >= 0; i--) { diff --git a/app/src/vue/view/MishiroLive.vue b/app/src/vue/view/MishiroLive.vue index 677c752..102771f 100644 --- a/app/src/vue/view/MishiroLive.vue +++ b/app/src/vue/view/MishiroLive.vue @@ -35,6 +35,7 @@
+ {{Math.floor(currentTime) | time}} / {{Math.floor(duration) | time}} @@ -140,8 +141,12 @@ width: 100%; align-items: center; } -.display-prog-wrap .range-input { +.display-prog-wrap .volume-input { flex: 1; + margin-right: 12px; +} +.display-prog-wrap .range-input { + flex: 3; } .display-prog-wrap .left-time { width: 120px;