WIP: StartOffset

This commit is contained in:
2026-05-07 12:09:16 +08:00
parent 0f30f98846
commit af4cd4da3f
51 changed files with 843 additions and 64 deletions
@@ -11,6 +11,7 @@ namespace OCES.Audio
double m_startDspTime, m_secondsPerBeat; // 本次计数周期的起点
Coroutine m_beatCoroutine, m_barCoroutine, m_gridCoroutine;
Coroutine m_delayCoroutine;
readonly Action<uint> m_onBeat, m_onBar, m_onGrid;
readonly MonoBehaviour m_host;
@@ -26,13 +27,13 @@ namespace OCES.Audio
this.m_onGrid = onGrid;
}
internal void Restart(MusicContainer container, float inheritedBpm, double dspTime)
internal void Restart(MusicContainer container, float inheritedBpm, double dspTime, double startOffset = 0d)
{
//Debug.Log($"[BeatClock] Restarting {container.Id}, inheritedBpm = {inheritedBpm}, dspTime = {dspTime}");
StopAll();
this.m_blendError = this.m_stopped = false;
this.m_containerId = container.Id;
this.m_startDspTime = dspTime;
this.m_startDspTime = dspTime + startOffset;
// BPM:优先用自己的,为 0 则用传入的继承值
float bpm = container.Bpm > 0f ? container.Bpm : inheritedBpm;
@@ -57,6 +58,32 @@ namespace OCES.Audio
this.m_barsPerGrid = container.Grid;
}
double delay = this.m_startDspTime - AudioSettings.dspTime;
if (delay > 0)
{
this.m_delayCoroutine = this.m_host.StartCoroutine(DelayedStart(delay, hasTimeSig, hasGrid));
}
else
{
StartCoroutines(hasTimeSig, hasGrid);
}
}
IEnumerator DelayedStart(double delay, bool hasTimeSig, bool hasGrid)
{
yield return new WaitUntil(() => AudioSettings.dspTime >= this.m_startDspTime - 0.02);
while (AudioSettings.dspTime < this.m_startDspTime)
yield return null;
if (this.m_stopped || this.m_blendError) yield break;
this.m_delayCoroutine = null;
StartCoroutines(hasTimeSig, hasGrid);
}
void StartCoroutines(bool hasTimeSig, bool hasGrid)
{
// 分层启动协程
// Beat:只要 BPM 有效就启动
this.m_beatCoroutine = this.m_host.StartCoroutine(BeatCoroutine());
@@ -82,10 +109,11 @@ namespace OCES.Audio
internal void StopAll()
{
this.m_stopped = true;
if (this.m_beatCoroutine != null) this.m_host.StopCoroutine(this.m_beatCoroutine);
if (this.m_barCoroutine != null) this.m_host.StopCoroutine(this.m_barCoroutine);
if (this.m_gridCoroutine != null) this.m_host.StopCoroutine(this.m_gridCoroutine);
this.m_beatCoroutine = this.m_barCoroutine = this.m_gridCoroutine = null;
if (this.m_delayCoroutine != null) this.m_host.StopCoroutine(this.m_delayCoroutine);
if (this.m_beatCoroutine != null) this.m_host.StopCoroutine(this.m_beatCoroutine);
if (this.m_barCoroutine != null) this.m_host.StopCoroutine(this.m_barCoroutine);
if (this.m_gridCoroutine != null) this.m_host.StopCoroutine(this.m_gridCoroutine);
this.m_delayCoroutine = this.m_beatCoroutine = this.m_barCoroutine = this.m_gridCoroutine = null;
}
internal double GetNextDspTime(AlignMode mode)
@@ -98,6 +126,11 @@ namespace OCES.Audio
}
double elapsed = now - this.m_startDspTime;
if (elapsed < 0)
{
return this.m_startDspTime;
}
double period = mode switch
{
AlignMode.Beat => this.m_secondsPerBeat,