Skip to content

Commit

Permalink
add LoopPlayTiming
Browse files Browse the repository at this point in the history
  • Loading branch information
MikiraSora committed Dec 29, 2023
1 parent 22a2f5b commit ebd7534
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 7 deletions.
3 changes: 3 additions & 0 deletions OngekiFumenEditor/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@
<setting name="RecoveryCurrentTimeAfterExecuteAction" serializeAs="String">
<value>False</value>
</setting>
<setting name="LoopPlayTiming" serializeAs="String">
<value>False</value>
</setting>
</OngekiFumenEditor.Properties.EditorGlobalSetting>
<OngekiFumenEditor.Properties.AudioPlayerToolViewerSetting>
<setting name="ResampleSize" serializeAs="String">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,19 @@ namespace OngekiFumenEditor.Kernel.Audio.DefaultCommonImpl.Sound
[Export(typeof(IFumenSoundPlayer))]
public partial class DefaultFumenSoundPlayer : PropertyChangedBase, IFumenSoundPlayer, IDisposable
{
private record MeterAction(TimeSpan Time, TimeSpan BeatInterval, bool isSkip);

private IntervalTree<TimeSpan, DurationSoundEvent> durationEvents = new();
private HashSet<DurationSoundEvent> currentPlayingDurationEvents = new();
private object locker = new object();

private LinkedList<SoundEvent> events = new();
private LinkedListNode<SoundEvent> itor;

private LinkedList<MeterAction> meterActions = new();
private LinkedListNode<MeterAction> meterActionsItor;
private int currentMeterHitCount = 0;

private AbortableThread thread;

private IAudioPlayer player;
Expand Down Expand Up @@ -296,11 +302,32 @@ void AddDurationSound(SoundControl sound, TGrid tGrid, TGrid endTGrid, int loopI
foreach (var durationEvent in durationList)
durationEvents.Add(durationEvent.Time, durationEvent.EndTime, durationEvent);
itor = null;

meterActions.Clear();
if (EditorGlobalSetting.Default.LoopPlayTiming)
{
var oneTGrid = new TGrid(1, 0);

var timeSignatureList = fumen.MeterChanges.GetCachedAllTimeSignatureUniformPositionList(fumen.BpmList);
foreach (var timeSignature in timeSignatureList)
{
var beatCount = timeSignature.meter.BunShi;
var isSkip = beatCount == 0;
var beatInterval = (isSkip ? default :
TimeSpan.FromMilliseconds(MathUtils.CalculateBPMLength(TGrid.Zero, oneTGrid, timeSignature.bpm.BPM))
/ beatCount);

var action = new MeterAction(timeSignature.audioTime, beatInterval, isSkip);
meterActions.AddLast(action);
}
}
meterActionsItor = default;
currentMeterHitCount = 0;
}

private void UpdateInternal(CancellationToken token)
{
if (itor is null || player is null || token.IsCancellationRequested)
if ((itor is null && meterActionsItor is null) || player is null || token.IsCancellationRequested)
return;
if (!IsPlaying)
{
Expand All @@ -311,7 +338,7 @@ private void UpdateInternal(CancellationToken token)

var currentTime = player.CurrentTime;

//播放普通音乐
//播放物件音效
while (itor is not null)
{
var nextBeatTime = itor.Value.Time.TotalMilliseconds;
Expand All @@ -326,6 +353,47 @@ private void UpdateInternal(CancellationToken token)
break;
}

//播放节拍器
while (meterActionsItor is not null)
{
var nextActionItor = meterActionsItor.Next;

//检查当前是否有效
if (meterActionsItor.Value.isSkip)
{
meterActionsItor = nextActionItor;
currentMeterHitCount = 0;
continue;
}

var nextBeatTime = meterActionsItor.Value.Time +
meterActionsItor.Value.BeatInterval * currentMeterHitCount;

//检查是否超过下一个
if (nextActionItor != null)
{
if (nextBeatTime > nextActionItor.Value.Time)
{
meterActionsItor = nextActionItor;
currentMeterHitCount = 0;
continue;
}
}

//没超过就检查了
var ct = currentTime.TotalMilliseconds - nextBeatTime.TotalMilliseconds;
if (ct >= 0)
{
Log.LogDebug($"currentMeterHitCount:{currentMeterHitCount}, nextBeatTime:{nextBeatTime}, diff:{ct:F2}ms, meterActionsItor:{meterActionsItor.Value}");
if (editor.IsDesignMode && cacheSounds.TryGetValue(SoundControl.ClickSE, out var soundPlayer))
soundPlayer.PlayOnce();
currentMeterHitCount++;
}
else
break;
}

//检查循环音效
lock (locker)
{
var queryDurationEvents = durationEvents.Query(currentTime);
Expand All @@ -340,7 +408,6 @@ private void UpdateInternal(CancellationToken token)
soundPlayer.PlayLoop(durationEvent.LoopId, initPlayTime);

currentPlayingDurationEvents.Add(durationEvent);

}
}
}
Expand Down Expand Up @@ -402,6 +469,16 @@ public void Seek(TimeSpan msec, bool pause)
{
Pause();
itor = events.Find(events.FirstOrDefault(x => msec < x.Time));
meterActionsItor = meterActions.Find(meterActions.LastOrDefault(x => msec >= x.Time));
if (meterActionsItor is null)
currentMeterHitCount = 0;
else
{
if (meterActionsItor.Value.isSkip)
currentMeterHitCount = 0;
else
currentMeterHitCount = (int)((msec - meterActionsItor.Value.Time) / meterActionsItor.Value.BeatInterval);
}

if (!pause)
PlayInternal();
Expand Down Expand Up @@ -443,6 +520,9 @@ public void Play()
if (player is null)
return;
itor = itor ?? events.First;
meterActionsItor = meterActionsItor ?? meterActions.First;
currentMeterHitCount = 0;

PlayInternal();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,18 @@ public bool AdjustPastedObjects
}
}

private bool loopPlayTiming = Properties.EditorGlobalSetting.Default.LoopPlayTiming;
public bool LoopPlayTiming
{
get => loopPlayTiming;
set
{
loopPlayTiming = Properties.EditorGlobalSetting.Default.LoopPlayTiming = value;
RequestSave();
NotifyOfPropertyChange(() => loopPlayTiming);
}
}

public enum TimeFormat
{
TGrid,
Expand Down Expand Up @@ -308,6 +320,9 @@ private void Default_PropertyChanged(object sender, System.ComponentModel.Proper
case nameof(Properties.EditorGlobalSetting.AdjustPastedObjects):
adjustPastedObjects = Properties.EditorGlobalSetting.Default.AdjustPastedObjects;
break;
case nameof(Properties.EditorGlobalSetting.LoopPlayTiming):
loopPlayTiming = Properties.EditorGlobalSetting.Default.LoopPlayTiming;
break;
default:
Log.LogWarn($"unknown Properties.EditorGlobalSetting property changed : {e.PropertyName}");
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using OngekiFumenEditor.Modules.FumenVisualEditor.Kernel;
using OngekiFumenEditor.Modules.FumenVisualEditor.Models;
using OngekiFumenEditor.Modules.FumenVisualEditor.ViewModels;
using OngekiFumenEditor.Properties;
using OngekiFumenEditor.Utils;
using System.ComponentModel;
using System.ComponentModel.Composition;
Expand Down Expand Up @@ -78,9 +79,7 @@ private void OnActivateEditorChanged(FumenVisualEditorViewModel @new, FumenVisua
private void OnEditorPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(FumenVisualEditorViewModel.Setting))
{
Setting = Editor?.Setting;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@
SelectedValue="{Binding Setting.DisplayTimeFormat, Converter={StaticResource EnumToStringConverter}}">
</ComboBox>
</Grid>
<CheckBox
Margin="0,10,0,2"
Content="打开节拍器(仅编辑模式)"
IsChecked="{Binding Setting.LoopPlayTiming}">
</CheckBox>
</StackPanel>
</ScrollViewer>
</UserControl>
2 changes: 1 addition & 1 deletion OngekiFumenEditor/Properties/AudioSetting.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion OngekiFumenEditor/Properties/EditorGlobalSetting.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions OngekiFumenEditor/Properties/EditorGlobalSetting.settings
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,8 @@
<Setting Name="RecoveryCurrentTimeAfterExecuteAction" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="LoopPlayTiming" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

0 comments on commit ebd7534

Please sign in to comment.