WIP: StartOffset
This commit is contained in:
@@ -14,6 +14,7 @@ namespace OCES.Audio
|
||||
{
|
||||
readonly MusicContainerConfig m_containerConfig;
|
||||
readonly MusicTransitionConfig m_transitionConfig;
|
||||
readonly MusicSegmentConfig m_segmentConfig;
|
||||
readonly MonoBehaviour m_coroutineHost;
|
||||
readonly ChannelFader m_fader;
|
||||
readonly BeatClock m_beatClock;
|
||||
@@ -30,6 +31,7 @@ namespace OCES.Audio
|
||||
|
||||
internal MusicChannelPlayer(
|
||||
MusicContainerConfig containerConfig,
|
||||
MusicSegmentConfig segmentConfig,
|
||||
MusicTransitionConfig transitionConfig,
|
||||
LongAudioContainerPlayer player,
|
||||
MonoBehaviour coroutineHost,
|
||||
@@ -39,6 +41,7 @@ namespace OCES.Audio
|
||||
{
|
||||
this.m_containerConfig = containerConfig;
|
||||
this.m_transitionConfig = transitionConfig;
|
||||
this.m_segmentConfig = segmentConfig;
|
||||
this.m_coroutineHost = coroutineHost;
|
||||
this.m_fader = new ChannelFader(player, coroutineHost);
|
||||
this.m_beatClock = new BeatClock(coroutineHost, onBeat, onBar, onGrid);
|
||||
@@ -55,6 +58,7 @@ namespace OCES.Audio
|
||||
/// </summary>
|
||||
internal void SwitchTo(uint newContainerId)
|
||||
{
|
||||
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; // 已经在播目标,无需切换
|
||||
|
||||
@@ -110,6 +114,7 @@ namespace OCES.Audio
|
||||
|
||||
if (syncState.Mode == SyncPoint.SameAsCurrentSegment)
|
||||
{
|
||||
Debug.Log($"[MusicChannelPlayer] DoTransition L117: CurrentHandle={this.m_fader.CurrentHandle}, CurrentContainerId={this.m_fader.CurrentContainerId}");
|
||||
// 旧 Container 不存在(如游戏首次启动),静默降级为 Start
|
||||
if (this.m_fader.CurrentHandle == null)
|
||||
{
|
||||
@@ -129,6 +134,7 @@ namespace OCES.Audio
|
||||
syncState.BaseTimeSamples = oldSource.timeSamples;
|
||||
syncState.BaseDspTime = AudioSettings.dspTime;
|
||||
syncState.SampleRate = oldSource.clip.frequency;
|
||||
syncState.SourceStartOffset = GetEffectiveStartOffset(this.m_currentContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -161,23 +167,46 @@ namespace OCES.Audio
|
||||
{
|
||||
MusicContainer container = this.m_containerConfig.QueryById(newContainerId);
|
||||
float bpm = container.Bpm;
|
||||
|
||||
// SyncPoint: BeatClock 用调整后的 dspTime,对齐到音频实际播放位置
|
||||
|
||||
double newStartOffset = GetEffectiveStartOffset(container);
|
||||
double dspTime;
|
||||
|
||||
if (syncState is { Mode: SyncPoint.SameAsCurrentSegment })
|
||||
{
|
||||
double elapsedSeconds = AudioSettings.dspTime - syncState.BaseDspTime;
|
||||
int elapsedSamples = (int)(elapsedSeconds * syncState.SampleRate);
|
||||
double audioTime = (double)(syncState.BaseTimeSamples + elapsedSamples) / syncState.SampleRate;
|
||||
dspTime = AudioSettings.dspTime - audioTime;
|
||||
double currentAudioTime = (double)(syncState.BaseTimeSamples + elapsedSamples) / syncState.SampleRate;
|
||||
// 当前的source播到了哪里
|
||||
|
||||
double currentLogicalTime = Math.Max(0, currentAudioTime - syncState.SourceStartOffset);
|
||||
// EntryCue之后播了多少秒。要是小于0说明pre-entry还没播完。
|
||||
|
||||
double newAudioTime = currentLogicalTime + newStartOffset;
|
||||
// 新Audio应该从多少秒开始播放
|
||||
|
||||
bool isPlayPreEntry = true; //TODO transition 是否播放pre-entry
|
||||
syncState.TargetAudioTime = isPlayPreEntry ? currentLogicalTime + newStartOffset : currentLogicalTime;
|
||||
dspTime = AudioSettings.dspTime - newAudioTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
double startPlayTime;
|
||||
if (this.m_currentContainer == null)
|
||||
{
|
||||
startPlayTime = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double fadeInTime = transition?.FadeInTime ?? 0f;
|
||||
startPlayTime = newStartOffset - fadeInTime;
|
||||
startPlayTime = Math.Clamp(startPlayTime, 0, double.PositiveInfinity);
|
||||
}
|
||||
syncState.StartPlayTime = startPlayTime;
|
||||
dspTime = AudioSettings.dspTime;
|
||||
}
|
||||
|
||||
this.m_currentContainer = container;
|
||||
this.m_beatClock.Restart(container, bpm, dspTime);
|
||||
this.m_beatClock.Restart(container, bpm, dspTime, newStartOffset);
|
||||
}));
|
||||
yield return this.m_currentFadeInCoroutine;
|
||||
this.m_currentFadeInCoroutine = null;
|
||||
@@ -227,5 +256,26 @@ namespace OCES.Audio
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
double GetEffectiveStartOffset(MusicContainer container)
|
||||
{
|
||||
if (container.ContainerType == ContainerType.Blend)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (container.Segments is not { Count: > 0 })
|
||||
return 0.0;
|
||||
uint firstId = container.Segments[0];
|
||||
if (firstId < 1000000u)
|
||||
{
|
||||
MusicSegment segment = this.m_segmentConfig.QueryById(firstId);
|
||||
return segment?.StartOffset ?? 0.0;
|
||||
}
|
||||
|
||||
MusicContainer child = this.m_containerConfig.QueryById(firstId);
|
||||
return child != null ? GetEffectiveStartOffset(child) : 0.0;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user