[F] Fix lyrics out of sync when using speed change

This commit is contained in:
2025-11-23 14:37:39 +08:00
parent cb797cbb61
commit 93b674942d
2 changed files with 18 additions and 3 deletions
-1
View File
@@ -22,7 +22,6 @@ Practice Japanese Karaoke lyrics reading and typing at the same time with KaraDa
* [ ] 升降调
* [x] 播放/暂停音乐控制
* [x] 变速
* [ ] 變速歌詞一起變速
* [ ] 音域分析(自动推荐升降调幅度)
* [ ] 电视模式
* [ ] 和手机配对、用手机点歌
+18 -2
View File
@@ -13,6 +13,9 @@ export class MusicControl {
audioUrl: string
vocalsUrl?: string
private _lastSpeedChangeTransportTime: number = 0
private _accumulatedAudioTime: number = 0
constructor(audioUrl: string, vocalsUrl?: string) {
this.audioUrl = audioUrl
this.vocalsUrl = vocalsUrl
@@ -63,6 +66,10 @@ export class MusicControl {
await Promise.all(promises)
this.log('Audio loaded')
// Reset time tracking
this._lastSpeedChangeTransportTime = 0
this._accumulatedAudioTime = 0
// Sync player to transport and schedule start at 0
// We do this regardless of transport state to ensure it's scheduled
this.player.sync().start(0)
@@ -76,6 +83,13 @@ export class MusicControl {
}
setSpeed(speed: number) {
// Calculate how much audio time has passed since the last speed change
const currentTransportTime = Tone.getTransport().seconds
const transportDelta = currentTransportTime - this._lastSpeedChangeTransportTime
this._accumulatedAudioTime += transportDelta * this.speed
this._lastSpeedChangeTransportTime = currentTransportTime
this.speed = speed
this.player.playbackRate = this.speed
if (this.vocalsPlayer) {
@@ -88,7 +102,9 @@ export class MusicControl {
}
getTime() {
return Tone.getTransport().seconds
const currentTransportTime = Tone.getTransport().seconds
const transportDelta = currentTransportTime - this._lastSpeedChangeTransportTime
return this._accumulatedAudioTime + transportDelta * this.speed
}
startCheckLoop() {
@@ -102,7 +118,7 @@ export class MusicControl {
// In karaoke mode (dual tracks), we don't pause for typing
if (this.vocalsPlayer) return
const ct = Tone.getTransport().seconds
const ct = this.getTime()
const ni = this.currentLineIndex + 1
if (ni >= this.lyrics.length) return
const nt = this.parseTime(this.lyrics[ni].time)