Skip to content

Distinguish important TimingChanges from simple subdivision changes #14

Description

@LumpBloom7

Currently, on master, there is no way to tell whether a TimingChange is important (holding a different BPM or different timing), or simply describes subdivision changes of a previous timing point.

SimaiSharp should distinguish between pure subdivision changes (where the BPM is inherited from a past TimingChange).

Use case:
TimingChanges are generated for every change in the subdivision. In a typical chart, several hundreds or thousands of these may be generated. For a visual editor, these may display as way too many timing changes. However, not all of them are "critical" in a sense. Filtering out simple subdivision changes will prevent blasting the charter with unimportant timing information.

Example structure change

namespace SimaiSharp.Internal.SyntacticAnalysis
{
    public struct TimingChange
    {
+        /// <summary>
+        /// If this field is <c>true</c>, then this TimingChange is likely to have been placed intentionally by a charter, as opposed to a simple subdivision change.
+        /// </summary>
+        /// <remarks>
+        /// <list type="bullet">
+        ///    <item>
+        ///        <description>If you are making a visual editor with displays the timing changes, you'd want to only display the important timing changes.</description>
+        ///    </item>
+        ///    <item>
+        ///        <description><see cref="NoteCollection"/>s created during SimaiSharp decoding will <i>not</i> ignore unimportant TimingChanges, as such, their start times will be correct.</description>
+        ///    </item>
+        ///</list>
+        /// </remarks>
+        public bool IsImportant;
+
+        /// <summary>
+        /// If this field is <c>true</c>, then the charter has provided a manual interval as an override. Typically, this implies that the note may be intentionally unaligned to the active TimingChange.
+        /// </summary>
+        /// 
+        /// <remarks>
+        /// If you are making a visual editor with displays the timing changes, you'd likely be able to get away with not including this TimingChange as "important".
+        /// </remarks>
+        public bool IsAbsoluteInterval;
+
        public double time;
        public double tempo;
        public double subdivisions;

        /// <summary>
        ///     Used in duration parsing.
        /// </summary>
        public double SecondsPerBar => tempo == 0 ? 0 : 60 / tempo;

        public double SecondsPerBeat => SecondsPerBar / ((subdivisions == 0 ? 4 : subdivisions) / 4);

        public void SetSeconds(double value)
        {
            tempo = 60 / value;
            subdivisions = 4;
+            IsAbsoluteInterval = true;
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions