Пример #1
0
        /// <summary>
        /// The value argument is the MNXC measure location string
        /// ("0.25", "3/8", "4:0.25", "4:1/4", "#event235" etc.)
        /// I assume that the argument value can be "incoming" and "outgoing"
        /// in addition to the values described at
        /// https://w3c.github.io/mnx/specification/common/#measure-location
        /// See https://w3c.github.io/mnx/specification/common/#the-tied-element
        /// I'd prefer not to allow the decimal representations of position.
        /// These just duplicate the other options, and create unnecessary work
        /// for parsers, so I'm currently ignoring them.
        /// </summary>
        public PositionInMeasure(string value)
        {
            if (value[0] == '#')
            {
                ID = value.Substring(1); // no '#' (okay?)
            }
            else if (value.IndexOf(':') < 0)
            {
                MeasureNumber = null; //  means "current measure"

                switch (value)
                {
                case "incoming":
                    Short = ShortTieOrSlur.incoming;
                    break;

                case "outgoing":
                    Short = ShortTieOrSlur.outgoing;
                    break;

                default:
                    Position = new MNXDurationSymbol(value);
                    break;
                }
            }
            else
            {
                char[]   separator = { ':' };
                string[] mStrs     = value.Split(separator, System.StringSplitOptions.None);
                int.TryParse(mStrs[0], out int measureNumber);
                MeasureNumber = measureNumber;
                Position      = new MNXDurationSymbol(mStrs[1]);
            }
        }
Пример #2
0
        public GlobalMeasure(XmlReader r, int measureIndex, TimeSignature currentTimeSig)
        {
            M.Assert(r.Name == "measure-global");
            // https://w3c.github.io/mnx/specification/common/#the-measure-element

            Index = measureIndex;                                    // ji: 23.06.2020

            GlobalDirections = new GlobalDirections(currentTimeSig); // default

            if (!r.IsEmptyElement)
            {
                int count = r.AttributeCount;
                for (int i = 0; i < count; i++)
                {
                    r.MoveToAttribute(i);
                    switch (r.Name)
                    {
                    // The optional MNX-Common "index" attribute is always ignored.
                    //case "index":
                    //    Index = Int32.Parse(r.Value);
                    //    M.Assert(Index > 0);
                    //    break;
                    case "number":
                        Number = Int32.Parse(r.Value);
                        M.Assert(Number > 0);
                        break;

                    case "barline":
                        Barline = GetBarlineType(r.Value);
                        break;

                    default:
                        throw new ApplicationException("Unknown attribute");
                    }
                }

                M.ReadToXmlElementTag(r, "directions-global");

                while (r.Name == "directions-global")
                {
                    if (r.NodeType != XmlNodeType.EndElement)
                    {
                        switch (r.Name)
                        {
                        case "directions-global":
                            GlobalDirections = new GlobalDirections(r, currentTimeSig);
                            currentTimeSig   = GlobalDirections.CurrentTimeSignature;
                            break;
                        }
                    }
                    M.ReadToXmlElementTag(r, "directions-global", "measure-global");
                }
            }

            TicksDuration = new MNXDurationSymbol(currentTimeSig.Signature).GetDefaultTicks();

            M.Assert(r.Name == "measure-global"); // end of measure-global
        }
Пример #3
0
        /// <summary>
        /// This function is called recursively.
        /// TicksPosInScore is not set. Grace groups are ignored.
        /// TicksPosInScore and TicksDurations are updated for grace notes
        /// when the whole score has been read (in MNX.AdjustForGraceNotes()).
        /// </summary>
        /// <param name="outerTicks"></param>
        private void SetTicksDurationsInContentIgnoringGraces(int outerTicks)
        {
            int GetBasicTicks(IHasTicksDuration component)
            {
                int rval = 0;

                if (component is Event e)
                {
                    MNXDurationSymbol defaultDuration = e.MNXDurationSymbol;
                    MNXDurationSymbol ticksOverride   = e.TicksOverride;
                    rval = (ticksOverride == null) ? defaultDuration.GetDefaultTicks() : ticksOverride.GetDefaultTicks();
                }
                else if (component is Forward f)
                {
                    rval = f.TicksDuration;
                }
                else if (component is TupletDef t)
                {
                    rval = t.OuterDuration.GetDefaultTicks();
                }
                return(rval);
            }

            List <int> eventForwardTupletBasicTicks      = new List <int>();
            List <IHasTicksDuration> eventForwardTuplets = new List <IHasTicksDuration>();

            // Get the default outer ticks of each contained Event, Forward and TupletDef component.
            foreach (IHasTicksDuration component in Components)
            {
                if (component is Event || component is Forward || component is TupletDef)
                {
                    eventForwardTupletBasicTicks.Add(GetBasicTicks(component));
                    eventForwardTuplets.Add(component);
                }
            }

            List <int> innerTicks = M.IntDivisionSizes(outerTicks, eventForwardTupletBasicTicks);

            // Set the default outer ticks of each contained Event, Forward and TupletDef component.
            for (int i = 0; i < eventForwardTuplets.Count; i++)
            {
                IHasTicksDuration eventForwardTuplet = eventForwardTuplets[i];
                int ticks = innerTicks[i];
                if (eventForwardTuplet is Event e)
                {
                    e.TicksDuration = innerTicks[i];
                }
                if (eventForwardTuplet is Forward f)
                {
                    f.TicksDuration = innerTicks[i];
                }
                if (eventForwardTuplet is TupletDef t)
                {
                    t.SetTicksDurationsInContentIgnoringGraces(innerTicks[i]); // recursive call
                }
            }
        }
Пример #4
0
        public Forward(XmlReader r)
        {
            // TicksDuration is initally be related to the default ticksDuration of the MNXDurationSymbol,
            // but it changes if this event is part of a tuplet, and again when the file has been completely
            // read, to accomodate Grace notes.
            // TicksPosInScore is set correctly when the complete file has been parsed.
            TicksPosInScore = 0;

            M.Assert(r.Name == "forward");

            r.MoveToAttribute("duration");
            MNXDurationSymbol = new MNXDurationSymbol(r.Value);


            M.ReadToXmlElementTag(r, "forward");

            M.Assert(r.Name == "forward"); // end of forward
        }
Пример #5
0
        public TupletDef(XmlReader r, bool isTopLevel)
        {
            M.Assert(r.Name == "tuplet");

            _isTopLevel = isTopLevel;

            int count = r.AttributeCount;

            for (int i = 0; i < count; i++)
            {
                r.MoveToAttribute(i);
                switch (r.Name)
                {
                case "outer":
                    OuterDuration = new MNXDurationSymbol(r.Value);
                    break;

                case "inner":
                    InnerDuration = new MNXDurationSymbol(r.Value);
                    break;

                case "orient":
                    Orient = GetMNXOrientation(r.Value);
                    break;

                case "staff":
                    int staff;
                    int.TryParse(r.Value, out staff);
                    if (staff > 0)
                    {
                        Staff = staff;
                    }
                    break;

                case "show-number":
                    ShowNumber = GetTupletNumberDisplay(r.Value);
                    break;

                case "show-value":
                    ShowValue = GetTupletNumberDisplay(r.Value);
                    break;

                case "bracket":
                    Bracket = GetTupletBracketDisplay(r.Value);
                    break;

                default:
                    throw new ApplicationException("Unknown attribute");
                }
            }

            M.ReadToXmlElementTag(r, "event", "grace", "forward", "tuplet");

            while (r.Name == "event" || r.Name == "grace" || r.Name == "forward" || r.Name == "tuplet")
            {
                if (r.Name == "tuplet" && r.NodeType == XmlNodeType.EndElement)
                {
                    break; //  pop 1 level
                }

                if (r.NodeType != XmlNodeType.EndElement)
                {
                    switch (r.Name)
                    {
                    case "event":
                        Event e = new Event(r);
                        Components.Add(e);
                        break;

                    case "grace":
                        Grace grace = new Grace(r);
                        Components.Add(grace);
                        break;

                    case "forward":
                        Forward forward = new Forward(r);
                        Components.Add(forward);
                        break;

                    case "tuplet":
                        TupletDef tuplet = new TupletDef(r, false);
                        Components.Add(tuplet);
                        break;
                    }
                }

                M.ReadToXmlElementTag(r, "event", "grace", "forward", "tuplet");
            }

            M.Assert(IEventsAndGraces.Count > 0);
            M.Assert(r.Name == "tuplet"); // end of (nested) tuplet content

            if (_isTopLevel)
            {
                int outerTicks = this.OuterDuration.GetDefaultTicks();
                this.OuterDuration.TicksDuration = outerTicks;
                SetTicksDurationsInContentIgnoringGraces(outerTicks);
            }
        }
Пример #6
0
        public Event(XmlReader r)
        {
            M.Assert(r.Name == "event");

            // TicksDuration is initally be related to the default ticksDuration of the MNXDurationSymbol,
            // but it changes if this event is part of a tuplet, and again when the file has been completely
            // read, to accomodate Grace notes.
            // TicksPosInScore is set correctly when the complete file has been parsed.
            TicksPosInScore = 0;

            int count = r.AttributeCount;

            for (int i = 0; i < count; i++)
            {
                r.MoveToAttribute(i);
                switch (r.Name)
                {
                case "value":
                    MNXDurationSymbol = new MNXDurationSymbol(r.Value);
                    break;

                case "measure":
                    M.ThrowError("Not Implemented");
                    break;

                case "orient":
                    M.ThrowError("Not Implemented");
                    break;

                case "staff":
                    M.ThrowError("Not Implemented");
                    break;

                case "duration":
                    TicksOverride = new MNXDurationSymbol(r.Value);
                    break;

                case "id":
                    ID = r.Value;
                    break;
                }
            }

            // extend the contained elements as necessary..
            M.ReadToXmlElementTag(r, "note", "rest", "slur");

            while (r.Name == "note" || r.Name == "rest" || r.Name == "slur")
            {
                if (r.NodeType != XmlNodeType.EndElement)
                {
                    switch (r.Name)
                    {
                    case "note":
                        if (Notes == null && Rest == null)
                        {
                            Notes = new List <Note>();
                        }
                        Notes.Add(new Note(r));
                        break;

                    case "rest":
                        if (Notes == null && Rest == null)
                        {
                            Rest = new Rest(r);
                        }
                        break;

                    case "slur":
                        if (SlurDefs == null)
                        {
                            SlurDefs = new List <SlurDef>();
                        }
                        SlurDefs.Add(new SlurDef(r));
                        break;
                    }
                }
                M.ReadToXmlElementTag(r, "note", "rest", "slur", "event");
            }
            M.Assert(r.Name == "event"); // end of event
        }