WIP: Music callback

- 头几拍会抖动一下,导致对不上拍子
This commit is contained in:
2026-04-07 10:06:02 +08:00
parent 0f204aa794
commit 49a502e647
21 changed files with 353 additions and 61 deletions
@@ -1,3 +1,4 @@
using System;
using System.Collections;
using UnityEngine;
@@ -7,12 +8,13 @@ namespace OCES.Audio
/// 音乐通道播放器。
/// 负责:切换目标 Container、等待节拍对齐、执行淡入淡出 Transition。
/// </summary>
public class MusicChannelPlayer
class MusicChannelPlayer
{
readonly MusicContainerConfig m_containerConfig;
readonly MusicTransitionConfig m_transitionConfig;
readonly MonoBehaviour m_coroutineHost;
readonly ChannelFader m_fader;
readonly BeatClock m_beatClock;
Coroutine m_currentFadeInCoroutine;
Coroutine m_currentFadeOutCoroutine;
@@ -30,16 +32,23 @@ namespace OCES.Audio
// 正在进行的 transition 协程(防止重叠)
Coroutine m_transitionCoroutine;
public MusicChannelPlayer(
internal MusicChannelPlayer(
MusicContainerConfig containerConfig,
MusicTransitionConfig transitionConfig,
MusicContainerPlayer player,
MonoBehaviour coroutineHost)
MonoBehaviour coroutineHost,
Action<uint> onBeat,
Action<uint> onBar,
Action<uint> onGrid)
{
this.m_containerConfig = containerConfig;
this.m_transitionConfig = transitionConfig;
this.m_coroutineHost = coroutineHost;
this.m_fader = new ChannelFader(player, coroutineHost);
this.m_containerConfig = containerConfig;
this.m_transitionConfig = transitionConfig;
this.m_coroutineHost = coroutineHost;
this.m_fader = new ChannelFader(player, coroutineHost);
this.m_beatClock = new BeatClock(coroutineHost, onBeat, onBar, onGrid);
player.OnContainerEntered += this.m_beatClock.Restart;
player.OnBlendError += this.m_beatClock.OnBlendError;
}
// ─────────────────────────────────────────────
@@ -67,8 +76,10 @@ namespace OCES.Audio
/// <summary>
/// 立即停止当前播放(无淡出)
/// </summary>
public void Stop()
internal void Stop()
{
this.m_beatClock.StopAll();
if (this.m_transitionCoroutine != null)
this.m_coroutineHost.StopCoroutine(this.m_transitionCoroutine);
@@ -146,7 +157,7 @@ namespace OCES.Audio
}
else if (mode == AlignMode.Bar)
{
int beatsPerBar = ParseBeatsPerBar(container.TimeSig);
int beatsPerBar = MusicContainerConfig.GetBeatsPerBar(container.TimeSig);
double secondsPerBar = secondsPerBeat * beatsPerBar;
double barsElapsed = elapsed / secondsPerBar;
double nextBar = System.Math.Ceiling(barsElapsed);
@@ -155,18 +166,7 @@ namespace OCES.Audio
yield return new WaitForSeconds((float)waitSeconds);
}
}
/// <summary>
/// 解析拍号字符串(如 "4/4", "3/4"),返回每小节拍数。
/// </summary>
static int ParseBeatsPerBar(string timeSig)
{
if (string.IsNullOrEmpty(timeSig)) return 4;
string[] parts = timeSig.Split('/');
if (parts.Length >= 1 && int.TryParse(parts[0], out int beats))
return beats;
return 4;
}
// ─────────────────────────────────────────────
// 工具
// ─────────────────────────────────────────────