private void Tick() { _time.Start(); while (true) { PlayerState state = State; bool playing = state == PlayerState.Playing; bool recording = state == PlayerState.Recording; if (!playing && !recording) { goto stop; } void MixerProcess() { _mixer.Process(_tracks, playing, recording); } while (_tempoStack >= 75) { _tempoStack -= 75; bool allDone = true; for (int i = 0; i < 0x10; i++) { Track track = _tracks[i]; if (track.Enabled) { byte prevDuration = track.NoteDuration; track.Tick(); bool update = false; while (track.Rest == 0 && !track.Stopped) { ExecuteNext(i, ref update); } if (i == _longestTrack) { if (ElapsedTicks == MaxTicks) { if (!track.Stopped) { ElapsedTicks = Events[i][track.CurEvent].Ticks[0] - track.Rest; _elapsedLoops++; if (ShouldFadeOut && !_mixer.IsFading() && _elapsedLoops > NumLoops) { _mixer.BeginFadeOut(); } } } else { ElapsedTicks++; } } if (prevDuration == 1 && track.NoteDuration == 0) // Note was not renewed { track.Channel.State = EnvelopeState.Release; } if (!track.Stopped) { allDone = false; } if (track.NoteDuration != 0) { allDone = false; if (update) { track.Channel.SetVolume(track.Volume, track.Panpot); track.Channel.SetPitch(track.GetPitch()); } } } } if (_mixer.IsFadeDone()) { allDone = true; } if (allDone) { MixerProcess(); State = PlayerState.Stopped; SongEnded?.Invoke(); } } _tempoStack += _tempo; MixerProcess(); if (playing) { _time.Wait(); } } stop: _time.Stop(); }