feat: StartOffset
- 实现startOffset - 修复EndOffset = 0 + 循环播放时,音乐会大量重复播放的错误。 - 增加数据校验和 BeatClock 联动。StartOffset不正确时停止bar+级 callback。 - BeatClock 现在会在每次重新播放时重启,以解决EndOffset配置错误被舍弃时,拍子对不上的问题。
This commit is contained in:
@@ -47,6 +47,7 @@ namespace OCES.Audio
|
||||
this.m_beatClock = new BeatClock(coroutineHost, onBeat, onBar, onGrid);
|
||||
|
||||
player.OnBlendError += this.m_beatClock.OnBlendError;
|
||||
player.OnContainerLooped += OnContainerLooped;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
@@ -58,12 +59,11 @@ namespace OCES.Audio
|
||||
/// </summary>
|
||||
internal void SwitchTo(uint newContainerId)
|
||||
{
|
||||
Debug.Log($"[MusicChannelPlayer] SwitchTo({newContainerId}): CurrentContainerId={this.m_fader.CurrentContainerId}, CurrentHandle={this.m_fader.CurrentHandle}");
|
||||
//Debug.Log($"[MusicChannelPlayer] SwitchTo({newContainerId}): CurrentContainerId={this.m_fader.CurrentContainerId}, CurrentHandle={this.m_fader.CurrentHandle}");
|
||||
if (newContainerId == this.m_fader.CurrentContainerId && this.m_fader.CurrentHandle != null)
|
||||
return; // 已经在播目标,无需切换
|
||||
|
||||
MusicTransition transition = ResolveTransition((int)this.m_fader.CurrentContainerId, (int)newContainerId);
|
||||
//Debug.Log($"[MusicChannelPlayer] Switch from {this.m_fader.CurrentContainerId} to {newContainerId} with transition {transition.Id}");
|
||||
|
||||
if (this.m_transitionCoroutine != null)
|
||||
this.m_coroutineHost.StopCoroutine(this.m_transitionCoroutine);
|
||||
@@ -91,6 +91,7 @@ namespace OCES.Audio
|
||||
|
||||
IEnumerator DoTransition(uint newContainerId, MusicTransition transition)
|
||||
{
|
||||
// Debug.Log($"[MusicChannelPlayer] Scheduled transition from {this.m_fader.CurrentContainerId} to {newContainerId} with transition {transition.Id}");
|
||||
if (this.m_currentFadeInCoroutine != null)
|
||||
{
|
||||
this.m_coroutineHost.StopCoroutine(this.m_currentFadeInCoroutine);
|
||||
@@ -114,14 +115,15 @@ namespace OCES.Audio
|
||||
|
||||
if (syncState.Mode == SyncPoint.SameAsCurrentSegment)
|
||||
{
|
||||
Debug.Log($"[MusicChannelPlayer] DoTransition L117: CurrentHandle={this.m_fader.CurrentHandle}, CurrentContainerId={this.m_fader.CurrentContainerId}");
|
||||
// Debug.Log($"[MusicChannelPlayer] DoTransition L117: CurrentHandle={this.m_fader.CurrentHandle}, CurrentContainerId={this.m_fader.CurrentContainerId}");
|
||||
// 旧 Container 不存在(如游戏首次启动),静默降级为 Start
|
||||
if (this.m_fader.CurrentHandle == null)
|
||||
{
|
||||
syncState.Mode = SyncPoint.Start;
|
||||
}
|
||||
// Blend 类型不支持 SameAsCurrentSegment,降级为 Start
|
||||
else if (this.m_currentContainer is { ContainerType: ContainerType.Blend })
|
||||
else if (this.m_currentContainer is { ContainerType: ContainerType.Blend }
|
||||
|| this.m_containerConfig.QueryById(newContainerId) is { ContainerType: ContainerType.Blend })
|
||||
{
|
||||
Debug.LogWarning($"[MusicChannelPlayer] SyncPoint.SameAsCurrentSegment 不支持 Blend 类型 Container({this.m_currentContainer.Id}),降级为 Start");
|
||||
syncState.Mode = SyncPoint.Start;
|
||||
@@ -144,9 +146,10 @@ namespace OCES.Audio
|
||||
}
|
||||
}
|
||||
|
||||
// ── 1. 等待节拍对齐(由 Transition 的 AlignMode 决定)──
|
||||
// ── 1. 等待节拍对齐(由 Transition 的 AlignMode 决定)── TODO 支持FadeInTime为负值时,等待FadeIn
|
||||
if (transition != null && this.m_currentContainer != null)
|
||||
{
|
||||
Debug.Log("[MusicChannelPlayer] Waiting for Alignment.");
|
||||
yield return this.m_coroutineHost.StartCoroutine(
|
||||
WaitForAlignment(transition.AlignMode, this.m_currentContainer));
|
||||
}
|
||||
@@ -158,6 +161,7 @@ namespace OCES.Audio
|
||||
ContainerPlayHandle outgoing = this.m_fader.CurrentHandle;
|
||||
float outVol = this.m_fader.CurrentVolume;
|
||||
|
||||
// Debug.Log("[MusicChannelPlayer] Start Crossfade.");
|
||||
this.m_currentFadeOutCoroutine = this.m_coroutineHost.StartCoroutine(
|
||||
this.m_fader.FadeOutBranch(outgoing, outVol, transition, syncState));
|
||||
|
||||
@@ -200,6 +204,7 @@ namespace OCES.Audio
|
||||
double fadeInTime = transition?.FadeInTime ?? 0f;
|
||||
startPlayTime = newStartOffset - fadeInTime;
|
||||
startPlayTime = Math.Clamp(startPlayTime, 0, double.PositiveInfinity);
|
||||
newStartOffset = 0;
|
||||
}
|
||||
syncState.StartPlayTime = startPlayTime;
|
||||
dspTime = AudioSettings.dspTime;
|
||||
@@ -277,5 +282,12 @@ namespace OCES.Audio
|
||||
return child != null ? GetEffectiveStartOffset(child) : 0.0;
|
||||
|
||||
}
|
||||
|
||||
void OnContainerLooped(MusicContainer container, float bpm, double dspTime)
|
||||
{
|
||||
if (this.m_currentContainer == null || this.m_currentContainer.Id != container.Id)
|
||||
return;
|
||||
this.m_beatClock.Restart(container, bpm, dspTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user