Example #1
0
        /// <summary>
        ///     Gets the nearest snap time at a given direction.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="direction"></param>
        /// <param name="snap"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        /// <exception cref="AudioEngineException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static double GetNearestSnapTimeFromTime(Qua map, Direction direction, int snap, double time)
        {
            if (map == null)
            {
                throw new ArgumentNullException(nameof(map));
            }

            // Get the current timing point
            var point = map.GetTimingPointAt(time);

            if (point == null)
            {
                return(0);
            }

            // Get the amount of milliseconds that each snap takes in the beat.
            var snapTimePerBeat = 60000 / point.Bpm / snap;

            // The point in the music that we want to snap to pre-rounding.
            double pointToSnap;

            switch (direction)
            {
            case Direction.Forward:
                pointToSnap = time + snapTimePerBeat;
                break;

            case Direction.Backward:
                pointToSnap = time - snapTimePerBeat;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(direction), direction, null);
            }

            var nearestTick = Math.Round((pointToSnap - point.StartTime) / snapTimePerBeat) * snapTimePerBeat + point.StartTime;

            if ((int)Math.Abs(nearestTick - time) <= (int)snapTimePerBeat)
            {
                return(nearestTick);
            }

            if (direction == Direction.Backward)
            {
                return((Math.Round((pointToSnap - point.StartTime) / snapTimePerBeat) + 1) * snapTimePerBeat + point.StartTime);
            }

            return((Math.Round((pointToSnap - point.StartTime) / snapTimePerBeat) - 1) * snapTimePerBeat + point.StartTime);
        }
Example #2
0
        /// <summary>
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime)
        {
            if (!AudioEngine.Track.IsPlaying || Qua.TimingPoints.Count == 0)
            {
                return;
            }

            var time = AudioEngine.Track.Time + ConfigManager.GlobalAudioOffset.Value;

            var point = Qua.GetTimingPointAt(time);

            if (time < point.StartTime)
            {
                LastBeat = -1;
                return;
            }

            // Get the total amount of beats that'll be played for the timing point.
            // This can depend on if the user wants 8 beats or 4.
            var totalBeats = (time - point.StartTime) / (point.MillisecondsPerBeat / (ConfigManager.EditorMetronomePlayHalfBeats.Value ? 2 : 1));

            CurrentTotalBeats = (int)Math.Floor(totalBeats);
            CurrentBeat       = (int)totalBeats % 4;

            // Play samples
            if (CurrentTotalBeats == 0 && LastTotalBeats < 0 || CurrentBeat != LastBeat)
            {
                if (CurrentBeat == 0)
                {
                    MeasureTickSample.CreateChannel().Play();
                }
                else
                {
                    BeatTickSample.CreateChannel().Play();
                }
            }

            // Keep track of the last beat & last total beats in the current frame, so we know when to play
            // the next sample.
            LastBeat       = CurrentBeat;
            LastTotalBeats = CurrentTotalBeats;
        }
Example #3
0
        /// <summary>
        ///     Seeks to the nearest snap(th) beat in the audio based on the
        ///     current timing point's snap.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="direction"></param>
        /// <param name="snap"></param>
        public static void SeekTrackToNearestSnap(Qua map, Direction direction, int snap)
        {
            if (Track == null || Track.IsDisposed || Track.IsStopped)
            {
                throw new AudioEngineException("Cannot seek to nearest snap if a track isn't loaded");
            }

            if (map == null)
            {
                throw new ArgumentNullException(nameof(map));
            }

            // Get the current timing point
            var point = map.GetTimingPointAt(Track.Time);

            // Get the amount of milliseconds that each snap takes in the beat.
            var snapTimePerBeat = 60000 / point.Bpm / snap;

            // The point in the music that we want to snap to pre-rounding.
            double pointToSnap;

            switch (direction)
            {
            case Direction.Forward:
                pointToSnap = Track.Time + snapTimePerBeat;
                break;

            case Direction.Backward:
                pointToSnap = Track.Time - snapTimePerBeat;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(direction), direction, null);
            }

            // Snap the value and seek to it.
            var seekTime = Math.Round((pointToSnap - point.StartTime) / snapTimePerBeat) * snapTimePerBeat + point.StartTime;

            Track.Seek(seekTime);
        }