public bool Start(SoundSource music, int startTick, HashSet <int> ticks, IEnumerable <BPMChangeEvent> bpms) { if (Playing) { throw new InvalidOperationException(); } if (music == null) { throw new ArgumentNullException("music"); } if (IsStopAtLastNote && ticks.Count == 0) { return(false); } SoundManager.Register(ClapSource.FilePath); SoundManager.Register(music.FilePath); EndTick = IsStopAtLastNote ? ticks.Max() : GetTickFromTime(SoundManager.GetDuration(music.FilePath), bpms); if (EndTick < startTick) { return(false); } TickElement = new LinkedList <int>(ticks.Where(p => p >= startTick).OrderBy(p => p)).First; BPMElement = new LinkedList <BPMChangeEvent>(bpms.OrderBy(p => p.Tick)).First; // スタート時まで進める while (TickElement != null && TickElement.Value < startTick) { TickElement = TickElement.Next; } while (BPMElement.Next != null && BPMElement.Next.Value.Tick <= startTick) { BPMElement = BPMElement.Next; } int clapLatencyTick = GetLatencyTick(ClapSource.Latency, (double)BPMElement.Value.BPM); InitialTick = startTick - clapLatencyTick; CurrentTick = InitialTick; StartTick = startTick; TimeSpan startTime = GetTimeFromTick(startTick, bpms); TimeSpan headGap = TimeSpan.FromSeconds(-music.Latency) - startTime; ElapsedTick = 0; Task.Run(() => { LastSystemTick = Environment.TickCount; SyncObject.Invoke((MethodInvoker)(() => Timer.Start())); System.Threading.Thread.Sleep(TimeSpan.FromSeconds(Math.Max(ClapSource.Latency, 0))); if (headGap.TotalSeconds > 0) { System.Threading.Thread.Sleep(headGap); } if (!Playing) { return; // 音源再生前に停止されたら取り消す } SoundManager.Play(music.FilePath, startTime + TimeSpan.FromSeconds(music.Latency)); }); Playing = true; return(true); }
public static bool Start(this SoundPreviewManager manager, Score score, SoundSource source, int startTick, bool onlyNotes) { return(manager.Start(source, startTick, score.GetGuideTicks(onlyNotes), score.Events.BPMChangeEvents)); }