Пример #1
0
 /// <summary>
 /// This function uses a sophisticated algorithm to decide whether flats or sharps are to be used to
 /// represent the chord. Chords can have naturals and either sharps or flats (but not both).
 /// The display of naturals is forced if the same notehead height also exists with a sharp or flat.
 /// (The display of other accidentals are always forced in the Head constructor.)
 /// Exceptions: This function throws an exception if
 ///     1) any of the input midiPitches is out of midi range (0..127).
 ///     2) the midiPitches are not in ascending order
 ///     3) the midiPitches are not unique.
 /// The midiPitches argument must be in order of size (ascending), but Heads are created in top-down order.
 /// </summary>
 /// <param name="midiPitches"></param>
 public void SetNoteheadPitches(List<byte> midiPitches)
 {
     #region check inputs
     int previousPitch = -1;
     foreach(int midiPitch in midiPitches)
     {
         Debug.Assert(midiPitch >= 0 && midiPitch <= 127, "midiPitch out of range.");
         Debug.Assert(midiPitch > previousPitch, "midiPitches must be unique and in ascending order.");
         previousPitch = midiPitch;
     }
     #endregion
     this.HeadsTopDown.Clear();
     bool useSharp = UseSharps(midiPitches, null); // returns false if flats are to be used
     for(int i = midiPitches.Count - 1; i >= 0; --i)
     {
         Head head = new Head(this, midiPitches[i], -1, useSharp);
         this.HeadsTopDown.Add(head);
     }
     for(int i = 0; i < midiPitches.Count; i++)
     {
         if(this.HeadsTopDown[i].Alteration == 0)
         {
             this.HeadsTopDown[i].DisplayAccidental = DisplayAccidental.suppress;
         }
     }
     for(int i = 1; i < midiPitches.Count; i++)
     {
         if(this.HeadsTopDown[i].Pitch == this.HeadsTopDown[i - 1].Pitch)
         {
             this.HeadsTopDown[i - 1].DisplayAccidental = DisplayAccidental.force;
             this.HeadsTopDown[i].DisplayAccidental = DisplayAccidental.force;
         }
     }
 }
Пример #2
0
        /// <summary>
        /// Head.Alteration is either 0 or 1 (natural or sharp).
        /// Returns the sharp/flat preference for representing the interval on this head,
        /// or null if there is no preference.
        /// </summary>
        /// <param name="head"></param>
        /// <param name="interval"></param>
        /// <returns></returns>
        private bool?GetUseSharps(Head head, int interval)
        {
            M.Assert(interval > 0 && interval < 12);
            M.Assert(head.Alteration == 0 || head.Alteration == 1);
            bool?useSharpsOrNull = null;

            #region Head is A
            if (head.Pitch[0] == 'A')
            {
                if (head.Alteration == 0) // (A)
                {
                    switch (interval)
                    {
                    case 11:
                    case 9:
                    case 4:
                        useSharpsOrNull = true;
                        break;

                    case 1:
                        useSharpsOrNull = false;
                        break;

                    default:
                        break;
                    }
                }
                else // Alteration == 1 (A#)
                {
                    switch (interval)
                    {
                    case 11:
                    case 9:
                    case 7:
                    case 4:
                    case 2:
                        useSharpsOrNull = false;
                        break;

                    case 1:
                        useSharpsOrNull = true;
                        break;

                    default:
                        break;
                    }
                }
            }
            #endregion A
            #region Head is B
            else if (head.Pitch[0] == 'B')
            {
                if (head.Alteration == 0) // (B)
                {
                    switch (interval)
                    {
                    case 11:
                    case 9:
                    case 7:
                    case 4:
                    case 2:
                        useSharpsOrNull = true;
                        break;

                    default:
                        break;
                    }
                }
                else // Alteration == 1 (B#)
                {
                    useSharpsOrNull = false;
                }
            }
            #endregion
            #region Head is C
            else if (head.Pitch[0] == 'C')
            {
                if (head.Alteration == 0) // (C)
                {
                    switch (interval)
                    {
                    case 10:
                    case 8:
                    case 3:
                    case 1:
                        useSharpsOrNull = false;
                        break;

                    default:
                        break;
                    }
                }
                else // Alteration == 1 (C#)
                {
                    switch (interval)
                    {
                    case 4:
                        useSharpsOrNull = false;
                        break;

                    case 10:
                    case 8:
                    case 3:
                    case 1:
                        useSharpsOrNull = true;
                        break;

                    default:
                        break;
                    }
                }
            }
            #endregion Head is C
            #region Head is D
            else if (head.Pitch[0] == 'D')
            {
                if (head.Alteration == 0) // (D)
                {
                    switch (interval)
                    {
                    case 11:
                    case 4:
                        useSharpsOrNull = true;
                        break;

                    case 8:
                    case 1:
                        useSharpsOrNull = false;
                        break;

                    default:
                        break;
                    }
                }
                else // Alteration == 1 (D#)
                {
                    switch (interval)
                    {
                    case 11:
                    case 9:
                    case 4:
                    case 2:
                        useSharpsOrNull = false;
                        break;

                    case 8:
                    case 1:
                        useSharpsOrNull = true;
                        break;

                    default:
                        break;
                    }
                }
            }
            #endregion Head is D
            #region Head is E
            else if (head.Pitch[0] == 'E')
            {
                if (head.Alteration == 0) // (E)
                {
                    switch (interval)
                    {
                    case 11:
                    case 9:
                    case 4:
                    case 2:
                        useSharpsOrNull = true;
                        break;

                    default:
                        break;
                    }
                }
                else // Alteration == 1 (E#)
                {
                    useSharpsOrNull = false;
                }
            }
            #endregion Head is E
            #region Head is F
            else if (head.Pitch[0] == 'F')
            {
                if (head.Alteration == 0) // (F)
                {
                    switch (interval)
                    {
                    case 10:
                    case 8:
                    case 5:
                    case 3:
                    case 1:
                        useSharpsOrNull = false;
                        break;

                    default:
                        break;
                    }
                }
                else // Alteration == 1 (F#)
                {
                    switch (interval)
                    {
                    case 10:
                    case 8:
                    case 5:
                    case 3:
                    case 1:
                        useSharpsOrNull = true;
                        break;

                    case 11:     // should really be G-flat, but I dont like G-flats!
                        //useSharpsOrNull = false;
                        break;

                    default:
                        break;
                    }
                }
            }
            #endregion Head is F
            #region Head is G
            else if (head.Pitch[0] == 'G')
            {
                if (head.Alteration == 0) // (G)
                {
                    switch (interval)
                    {
                    case 8:
                    case 3:
                    case 1:
                        useSharpsOrNull = false;
                        break;

                    case 11:
                        useSharpsOrNull = true;
                        break;

                    default:
                        break;
                    }
                }
                else // Alteration == 1 (G#)
                {
                    switch (interval)
                    {
                    case 11:
                    case 9:
                    case 4:
                        useSharpsOrNull = false;
                        break;

                    case 8:
                    case 3:
                    case 1:
                        useSharpsOrNull = true;
                        break;

                    default:
                        break;
                    }
                }
            }
            #endregion Head is G
            return(useSharpsOrNull);
        }
Пример #3
0
        /// <summary>
        /// Returns true if sharps are to be used to represent the midiPitches,
        /// or false if flats are to be used.
        /// </summary>
        /// <param name="midiPitches"></param>
        /// <returns></returns>
        internal bool UseSharps(List <byte> midiPitches, List <byte> midiVelocities)
        {
            for (int i = 0; i < midiPitches.Count; i++)
            {
                M.Assert(midiPitches[i] >= 0 && midiPitches[i] < 128);
            }

            bool       useSharps     = true;
            List <int> midiIntervals = new List <int>();

            for (int i = 1; i < midiPitches.Count; i++)
            {
                midiIntervals.Add(midiPitches[i] - midiPitches[i - 1]);
            }
            List <int> collapsedIntervals = new List <int>();

            foreach (int midiInterval in midiIntervals)
            {
                collapsedIntervals.Add(midiInterval % 12);
            }

            // look in the following order (I dont like augmented seconds at all)!
            int[] preferredIntervals = { 3, 7, 1, 2, 4, 5, 6, 8, 9, 10, 11 };
            bool? useSharpsOrNull    = null;

            foreach (int interval in preferredIntervals)
            {
                int index = 0;
                if (collapsedIntervals.Contains(interval))
                {
                    foreach (int value in collapsedIntervals)
                    {
                        if (value == interval)
                        {
                            break;
                        }
                        index++;
                    }
                    // index is now both the index of the "most preferred" interval
                    // and the index of the lower midiPitch of the "most preferred" interval.
                    Head head = null;
                    M.Assert(midiVelocities != null); // April 2020 (InputChordSymbols no longer exist)
                    if (midiVelocities != null)
                    {
                        head = new Head(null, midiPitches[index], midiVelocities[index], true);
                    }
                    else
                    {
                        //head = new Head(null, midiPitches[index], -1, true);  // a Head in an InputChordSymbol
                    }
                    // head is either natural or sharp.
                    int preferredInterval = collapsedIntervals[index];
                    useSharpsOrNull = GetUseSharps(head, preferredInterval);
                }
                if (useSharpsOrNull != null)
                {
                    useSharps = (bool)useSharpsOrNull;
                    break;
                }
            }
            return(useSharps);
        }
Пример #4
0
        /// <summary>
        /// Returns true if sharps are to be used to represent the midiPitches,
        /// or false if flats are to be used.
        /// </summary>
        /// <param name="midiPitches"></param>
        /// <returns></returns>
        internal bool UseSharps(List<byte> midiPitches, List<byte> midiVelocities)
        {
            for(int i = 0; i < midiPitches.Count; i++)
            {
                Debug.Assert(midiPitches[i] >= 0 && midiPitches[i] < 128);
            }

            bool useSharps = true;
            List<int> midiIntervals = new List<int>();
            for(int i = 1; i < midiPitches.Count; i++)
            {
                midiIntervals.Add(midiPitches[i] - midiPitches[i - 1]);
            }
            List<int> collapsedIntervals = new List<int>();
            foreach(int midiInterval in midiIntervals)
            {
                collapsedIntervals.Add(midiInterval % 12);
            }

            // look in the following order (I dont like augmented seconds at all)!
            int[] preferredIntervals = { 3, 7, 1, 2, 4, 5, 6, 8, 9, 10, 11 };
            bool? useSharpsOrNull = null;
            foreach(int interval in preferredIntervals)
            {
                int index = 0;
                if(collapsedIntervals.Contains(interval))
                {
                    foreach(int value in collapsedIntervals)
                    {
                        if(value == interval)
                            break;
                        index++;
                    }
                    // index is now both the index of the "most preferred" interval
                    // and the index of the lower midiPitch of the "most preferred" interval.
                    Head head = null;
                    if(midiVelocities != null)
                    {
                        head = new Head(null, midiPitches[index], midiVelocities[index], true);
                    }
                    else
                    {
                        head = new Head(null, midiPitches[index], -1, true);  // a Head in an InputChordSymbol
                    }
                    // head is either natural or sharp.
                    int preferredInterval = collapsedIntervals[index];
                    useSharpsOrNull = GetUseSharps(head, preferredInterval);
                }
                if(useSharpsOrNull != null)
                {
                    useSharps = (bool)useSharpsOrNull;
                    break;
                }
            }
            return useSharps;
        }
Пример #5
0
        /// <summary>
        /// Head.Alteration is either 0 or 1 (natural or sharp).
        /// Returns the sharp/flat preference for representing the interval on this head,
        /// or null if there is no preference.
        /// </summary>
        /// <param name="head"></param>
        /// <param name="interval"></param>
        /// <returns></returns>
        private bool? GetUseSharps(Head head, int interval)
        {
            Debug.Assert(interval > 0 && interval < 12);
            Debug.Assert(head.Alteration == 0 || head.Alteration == 1);
            bool? useSharpsOrNull = null;
            #region Head is A
            if(head.Pitch[0] == 'A')
            {
                if(head.Alteration == 0) // (A)
                {
                    switch(interval)
                    {
                        case 11:
                        case 9:
                        case 4:
                            useSharpsOrNull = true;
                            break;
                        case 1:
                            useSharpsOrNull = false;
                            break;
                        default:
                            break;
                    }
                }
                else // Alteration == 1 (A#)
                {
                    switch(interval)
                    {
                        case 11:
                        case 9:
                        case 7:
                        case 4:
                        case 2:
                            useSharpsOrNull = false;
                            break;
                        case 1:
                            useSharpsOrNull = true;
                            break;
                        default:
                            break;
                    }

                }
            }
            #endregion A
            #region Head is B
            else if(head.Pitch[0] == 'B')
            {
                if(head.Alteration == 0) // (B)
                {
                    switch(interval)
                    {
                        case 11:
                        case 9:
                        case 7:
                        case 4:
                        case 2:
                            useSharpsOrNull = true;
                            break;
                        default:
                            break;
                    }
                }
                else // Alteration == 1 (B#)
                {
                    useSharpsOrNull = false;
                }
            }
            #endregion
            #region Head is C
            else if(head.Pitch[0] == 'C')
            {
                if(head.Alteration == 0) // (C)
                {
                    switch(interval)
                    {
                        case 10:
                        case 8:
                        case 3:
                        case 1:
                            useSharpsOrNull = false;
                            break;
                        default:
                            break;
                    }
                }
                else // Alteration == 1 (C#)
                {
                    switch(interval)
                    {
                        case 4:
                            useSharpsOrNull = false;
                            break;
                        case 10:
                        case 8:
                        case 3:
                        case 1:
                            useSharpsOrNull = true;
                            break;
                        default:
                            break;
                    }
                }
            }
            #endregion Head is C
            #region Head is D
            else if(head.Pitch[0] == 'D')
            {
                if(head.Alteration == 0) // (D)
                {
                    switch(interval)
                    {
                        case 11:
                        case 4:
                            useSharpsOrNull = true;
                            break;
                        case 8:
                        case 1:
                            useSharpsOrNull = false;
                            break;
                        default:
                            break;
                    }
                }
                else // Alteration == 1 (D#)
                {
                    switch(interval)
                    {
                        case 11:
                        case 9:
                        case 4:
                        case 2:
                            useSharpsOrNull = false;
                            break;
                        case 8:
                        case 1:
                            useSharpsOrNull = true;
                            break;
                        default:
                            break;
                    }
                }
            }
            #endregion Head is D
            #region Head is E
            else if(head.Pitch[0] == 'E')
            {
                if(head.Alteration == 0) // (E)
                {
                    switch(interval)
                    {
                        case 11:
                        case 9:
                        case 4:
                        case 2:
                            useSharpsOrNull = true;
                            break;
                        default:
                            break;
                    }
                }
                else // Alteration == 1 (E#)
                {
                    useSharpsOrNull = false;
                }
            }
            #endregion Head is E
            #region Head is F
            else if(head.Pitch[0] == 'F')
            {
                if(head.Alteration == 0) // (F)
                {
                    switch(interval)
                    {
                        case 10:
                        case 8:
                        case 5:
                        case 3:
                        case 1:
                            useSharpsOrNull = false;
                            break;
                        default:
                            break;
                    }
                }
                else // Alteration == 1 (F#)
                {
                    switch(interval)
                    {
                        case 10:
                        case 8:
                        case 5:
                        case 3:
                        case 1:
                            useSharpsOrNull = true;
                            break;
                        case 11: // should really be G-flat, but I dont like G-flats!
                            //useSharpsOrNull = false;
                            break;
                        default:
                            break;
                    }
                }
            }
            #endregion Head is F
            #region Head is G
            else if(head.Pitch[0] == 'G')
            {
                if(head.Alteration == 0) // (G)
                {
                    switch(interval)
                    {
                        case 8:
                        case 3:
                        case 1:
                            useSharpsOrNull = false;
                            break;
                        case 11:
                            useSharpsOrNull = true;
                            break;
                        default:
                            break;
                    }
                }
                else // Alteration == 1 (G#)
                {
                    switch(interval)
                    {
                        case 11:
                        case 9:
                        case 4:
                            useSharpsOrNull = false;
                            break;
                        case 8:
                        case 3:
                        case 1:
                            useSharpsOrNull = true;
                            break;
                        default:
                            break;
                    }
                }
            }
            #endregion Head is G
            return useSharpsOrNull;
        }
Пример #6
0
 /// <summary>
 /// Accidentals
 /// </summary>
 /// <param name="name"></param>
 /// <returns></returns>
 private string GetClichtCharacterString(Head head)
 {
     string cLichtCharacterString = null;
     switch(head.Alteration)
     {
         case -1:
             cLichtCharacterString = "b";
             break;
         case 0:
             cLichtCharacterString = "n";
             break;
         case 1:
             cLichtCharacterString = "#";
             break;
         default:
             Debug.Assert(false, "unknown accidental type");
             break;
     }
     return cLichtCharacterString;
 }
Пример #7
0
        public CLichtCharacterMetrics(Head head, float fontHeight)
            : base()
        {
            _objectType = GetClichtCharacterString(head);

            Debug.Assert(_objectType != null);
            Metrics m = CLichtFontMetrics.CLichtGlyphBoundingBoxesDictPX[_objectType];

            _originY = 0;
            _top = m.Top * fontHeight;
            _bottom = m.Bottom * fontHeight;

            // move so that Left = 0.
            _left = 0;
            _right = (m.Right - m.Left) * fontHeight;
            _originX = -m.Left * fontHeight;

            _fontHeight = fontHeight;
        }
Пример #8
0
        public AccidentalMetrics(Head head, float fontHeight, float gap)
            : base(head, fontHeight)
        {
            float verticalPadding = gap / 5;
            _top -= verticalPadding;
            _bottom += verticalPadding;

            switch(_objectType)
            {
                case "b":
                    _left -= gap * 0.2F;
                    _right += gap * 0.2F;
                    break;
                case "n":
                    _left -= gap * 0.2F;
                    _right += gap * 0.2F;
                    break;
                case "#":
                    _left -= gap * 0.1F;
                    _right += gap * 0.1F;
                    break;
            }
            if(head != null && head.ColorAttribute != null)
            {
                _colorAttribute = head.ColorAttribute;
            }
        }
Пример #9
0
        public HeadMetrics(ChordSymbol chord, Head head, float gapVBPX)
            : base(chord.DurationClass, false, chord.FontHeight)
        {
            Move((Left - Right) / 2F, 0F); // centre horizontally

            float horizontalPadding = chord.FontHeight * 0.04F;
            _leftStemX = _left;
            _rightStemX = _right;
            _left -= horizontalPadding;
            _right += horizontalPadding;
            if(head != null && head.ColorAttribute != null)
            {
                _colorAttribute = head.ColorAttribute;
            }
        }
Пример #10
0
        public AccidentalMetrics(Head head, float fontHeight, float gap)
            : base(head, fontHeight)
        {
            float verticalPadding = gap / 5;
            _top -= verticalPadding;
            _bottom += verticalPadding;

            switch(_objectType)
            {
                case "b":
                    _left -= gap * 0.2F;
                    _right += gap * 0.2F;
                    break;
                case "n":
                    _left -= gap * 0.2F;
                    _right += gap * 0.2F;
                    break;
                case "#":
                    _left -= gap * 0.1F;
                    _right += gap * 0.1F;
                    break;
                //case "#":
                //    _left -= gap * 0.05F;
                //    _right += gap * 0.05F;
                //    break;
            }
        }