/// <summary>
        /// Calculates slur height trying to avoid collisions with stems
        /// </summary>
        /// <param name="note"></param>
        /// <param name="endPoint"></param>
        /// <returns></returns>
        private double DetermineSlurHeight(Note note, Slur slur, SlurInfo slurStartInfo, Point endPoint)
        {
            var notesUnderSlur = note.Staff.EnumerateUntilConditionMet <Note>(note, n => n.Slurs.FirstOrDefault(s => s.Number == slur.Number)?.Type == NoteSlurType.Start, true).ToArray();

            if (notesUnderSlur.Length < 3)
            {
                return(10);
            }

            var notesUnderSlurExclusive = notesUnderSlur.Take(notesUnderSlur.Length - 1).Skip(1);
            var mostExtremePoint        = GetMostExtremePoint(notesUnderSlurExclusive, slurStartInfo.StartPlacement);

            var angle = UsefulMath.BeamAngle(slurStartInfo.StartPoint.X, slurStartInfo.StartPoint.Y, endPoint.X, endPoint.Y);
            var slurYPositionInMostExtremePoint = slurStartInfo.StartPoint.TranslateHorizontallyAndMaintainAngle(angle, mostExtremePoint.X - slurStartInfo.StartPoint.X).Y;
            var mostExtremeYPosition            = mostExtremePoint.Y;

            if (slurStartInfo.StartPlacement == VerticalPlacement.Above && mostExtremeYPosition < slurYPositionInMostExtremePoint)
            {
                return(Math.Abs(mostExtremeYPosition - slurYPositionInMostExtremePoint) + 10);
            }
            if (slurStartInfo.StartPlacement == VerticalPlacement.Below && mostExtremeYPosition > slurYPositionInMostExtremePoint)
            {
                return(Math.Abs(slurYPositionInMostExtremePoint - mostExtremeYPosition) + 10);
            }

            return(10);
        }
Esempio n. 2
0
        private PrintSuggestion CreateSuggestion(XElement element, MusicXmlParserState state, Staff staff)
        {
            PrintSuggestion suggestion = new PrintSuggestion();

            element.IfAttribute("new-system").HasValue("yes").Then(() => suggestion.IsSystemBreak = true);
            element.IfAttribute("new-page").HasValue("yes").Then(() => suggestion.IsPageBreak     = true);
            if (suggestion.IsPageBreak)
            {
                suggestion.IsSystemBreak = true;                                        //Page breaks are treated also as system breaks.
            }
            element.IfDescendant("system-distance").Exists().Then(n =>
            {
                suggestion.SystemDistance = UsefulMath.TryParse(n.Value);
            });

            //Issue #45: Kopiujemy ustawienia z pierwszego staffa do wszystkich pozostałych staffów (bo są zdefiniowane tylko w pierwszym), innaczej się układ rozjedzie:
            if (!suggestion.SystemDistance.HasValue && staff != staff.Score.Staves.First())
            {
                var thisStaffPrintSuggestions  = staff.Elements.OfType <PrintSuggestion>().ToList();
                var firstStaffPrintSuggestions = staff.Score.Staves.First().Elements.OfType <PrintSuggestion>().ToList();
                var indexOfThisBreak           = (thisStaffPrintSuggestions.Any() ? thisStaffPrintSuggestions.IndexOf(thisStaffPrintSuggestions.Last()) : -1) + 1;
                if (firstStaffPrintSuggestions.Count > indexOfThisBreak)
                {
                    suggestion.SystemDistance = firstStaffPrintSuggestions[indexOfThisBreak].SystemDistance;
                }
            }
            element.IfDescendant("staff-distance").Exists().Then(n =>
            {
                staff.Score.Pages.Last().DefaultStaffDistance = UsefulMath.TryParse(n.Value);
            });

            return(suggestion);
        }
Esempio n. 3
0
        public override Model.Score Parse(string source)
        {
            var score    = Score.CreateOneStaffScore(Clef.Treble, MajorScale.C);
            var splitted = source.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var element in splitted)
            {
                if (element.Contains("_"))
                {
                    var pitchAndDuration        = element.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
                    var midiPitch               = int.Parse(pitchAndDuration[1]);
                    var denominator             = int.Parse(pitchAndDuration[0].Replace(".", ""));
                    var numberOfNotes           = pitchAndDuration[0].ToCharArray().Where(c => c == '.').Count();
                    var denominatorAsPowerOfTwo = UsefulMath.Log2(denominator);
                    var note = Note.FromMidiPitch(midiPitch, new RhythmicDuration(denominatorAsPowerOfTwo, numberOfNotes));
                    score.FirstStaff.Elements.Add(note);
                }
                else if (element == "|")
                {
                    score.FirstStaff.Elements.Add(new Barline());
                }
                else
                {
                    var denominator             = int.Parse(element.Replace(".", ""));
                    var numberOfNotes           = element.ToCharArray().Where(c => c == '.').Count();
                    var denominatorAsPowerOfTwo = UsefulMath.Log2(denominator);
                    var rest = new Rest(new RhythmicDuration(denominatorAsPowerOfTwo, numberOfNotes));
                    score.FirstStaff.Elements.Add(rest);
                }
            }
            return(score);
        }
Esempio n. 4
0
 public override void DrawArc(Primitives.Rectangle rect, double startAngle, double sweepAngle, Primitives.Pen pen, Model.MusicalSymbol owner)
 {
     Canvas.AppendLine("context.beginPath();");
     Canvas.AppendLine(string.Format("context.arc({0},{1},{2},{3},{4});", rect.X.ToStringInvariant(), rect.Y.ToStringInvariant(),
                                     rect.Height.ToStringInvariant(),
                                     UsefulMath.GradToRadians(startAngle).ToStringInvariant(),
                                     UsefulMath.GradToRadians(sweepAngle).ToStringInvariant()));
     Canvas.AppendLine("context.stroke();");
 }
Esempio n. 5
0
        public void CentsTest()
        {
            Assert.AreEqual(Proportion.Dupla.Cents, 1200);
            Assert.AreEqual(UsefulMath.CentsToLinear(1200), Proportion.Dupla.DoubleValue);

            var second1 = new Proportion(9, 8);
            var second2 = Proportion.GetApproximatedProportionFromCents(second1.Cents);

            Assert.AreEqual((int)second1.Cents, (int)second2.Cents);

            var pureFifth = Proportion.Sesquialtera.Cents;
        }
Esempio n. 6
0
 public override string ToString()
 {
     if (Score == null || !Score.Staves.Contains(this))
     {
         string.Format("Staff (detached from score).");
     }
     if (Part == null || !Part.Staves.Contains(this))
     {
         return(string.Format("Staff ({0} in score).", UsefulMath.NumberToOrdinal(Score.Staves.IndexOf(this) + 1)));
     }
     return(string.Format("Staff {0} of part {1} ({2} in score).", Part.Staves.IndexOf(this) + 1, Part.PartId, UsefulMath.NumberToOrdinal(Score.Staves.IndexOf(this) + 1)));
 }
        private static Tuple <Point, Point> GetBezierControlPoints(Point start, Point end, VerticalPlacement placement, double height)
        {
            var factor   = placement == VerticalPlacement.Above ? -1 : 1;
            var angle    = UsefulMath.BeamAngle(start.X, start.Y, end.X, end.Y);
            var angle2   = angle + (Math.PI / 2) * factor;
            var distance = Point.Distance(start, end);
            var startPointForControlPoints = start.TranslateByAngleOld(angle2, height);
            var control1 = startPointForControlPoints.TranslateByAngleOld(angle, distance * 0.25);
            var control2 = startPointForControlPoints.TranslateByAngleOld(angle, distance * 0.75);

            return(new Tuple <Point, Point>(control1, control2));
        }
 private static T?ParseValue <T>(string value) where T : struct
 {
     if (typeof(T) == typeof(int))
     {
         return(UsefulMath.TryParseInt(value) as T?);
     }
     if (typeof(T) == typeof(double))
     {
         return(UsefulMath.TryParse(value) as T?);
     }
     if (typeof(T) == typeof(DateTime))
     {
         return(UsefulMath.TryParseDateTime(value) as T?);
     }
     throw new NotImplementedException("Type not supported");
 }
Esempio n. 9
0
        private DateTime?GetDirectoryDate(string directory)
        {
            if (directory.Length < 14)
            {
                return(null);
            }
            var year = UsefulMath.TryParseInt(directory.Substring(0, 4));

            if (!year.HasValue)
            {
                return(null);
            }
            var month = UsefulMath.TryParseInt(directory.Substring(4, 2));

            if (!month.HasValue)
            {
                return(null);
            }
            var day = UsefulMath.TryParseInt(directory.Substring(6, 2));

            if (!day.HasValue)
            {
                return(null);
            }
            var hour = UsefulMath.TryParseInt(directory.Substring(8, 2));

            if (!hour.HasValue)
            {
                return(null);
            }
            var minute = UsefulMath.TryParseInt(directory.Substring(10, 2));

            if (!minute.HasValue)
            {
                return(null);
            }
            var second = UsefulMath.TryParseInt(directory.Substring(12, 2));

            if (!second.HasValue)
            {
                return(null);
            }
            return(new DateTime(year.Value, month.Value, day.Value).AddHours(hour.Value).AddMinutes(minute.Value).AddSeconds(second.Value));
        }
Esempio n. 10
0
 /// <summary>
 /// Calculates beam angle
 /// </summary>
 /// <param name="beamStart">Beam start position</param>
 /// <param name="beamEnd">Beam end position</param>
 /// <returns></returns>
 public static double BeamAngle(Point beamStart, Point beamEnd)
 {
     return(UsefulMath.BeamAngle(beamStart.X, beamStart.Y, beamEnd.X, beamEnd.Y));
 }
        public override XDocument Parse(XDocument source)   //TODO: Przetestować dokładnie i zrefaktorować
        {
#if CSHTML5
            throw new NotImplementedException("This method is not yet implemented for CSHTML5.");
#else
            if (!NormalizeSpaceBeforeFirstNotesOfMeasures)
            {
                return(source);
            }
            if (source.Descendants(XName.Get("repeat")).Any())
            {
                return(source);                                               //Workaround - pomiń na razie te ze znakiem repetycji, bo się źle rysują
            }
            if (source.Descendants(XName.Get("time")).Count() > 1)
            {
                return(source);                                                   //Workaround - pomiń na razie te ze zmianami metrum, bo się źle rysują
            }
            foreach (XElement staffNode in source.Descendants(XName.Get("part")))
            {
                //
                // FIRST PASS: Determine median note default-x
                //
                List <double> measureWidths = new List <double>();
                List <double> spacesBeforeFirstNoteOfMeasure = new List <double>();
                foreach (XElement measureNode in staffNode.Descendants(XName.Get("measure")).Skip(1)) //Don't remove space in first measure
                {
                    //if (measureNode.Elements(XName.Get("barline")).Any()) continue; //Nie bierz pod uwagi tych ze znakami repetycji, itp.
                    //TODO: Nie uwzględniać taktu, który następuje zaraz po zmianie metrum/klucza/znaków przykluczowych

                    //Read widths of all measures:
                    double?measureWidth   = null;
                    var    widthAttribute = measureNode.Attributes().FirstOrDefault(a => a.Name == "width");
                    if (widthAttribute != null)
                    {
                        measureWidth = UsefulMath.TryParse(widthAttribute.Value);
                    }
                    if (measureWidth.HasValue)
                    {
                        measureWidths.Add(measureWidth.Value);
                    }

                    XElement firstNoteNode = measureNode.Descendants(XName.Get("note")).FirstOrDefault();
                    if (firstNoteNode != null)
                    {
                        double?noteDefaultX      = null;
                        var    defaultXAttribute = firstNoteNode.Attributes().FirstOrDefault(a => a.Name == "default-x");
                        if (defaultXAttribute != null)
                        {
                            noteDefaultX = UsefulMath.TryParse(defaultXAttribute.Value);
                        }
                        if (noteDefaultX.HasValue)
                        {
                            spacesBeforeFirstNoteOfMeasure.Add(noteDefaultX.Value);
                        }
                    }
                }
                double medianNoteDefaultX  = UsefulMath.Median(spacesBeforeFirstNoteOfMeasure.ToArray());
                double averageNoteDefaultX = UsefulMath.Mean(spacesBeforeFirstNoteOfMeasure.ToArray());

                //
                // SECOND PASS: Apply calculated median note default-x to all measures
                //
                //TODO: Nie uwzględniać taktu, który następuje zaraz po zmianie metrum/klucza/znaków przykluczowych
                foreach (XElement measureNode in staffNode.Descendants(XName.Get("measure")).Skip(1))   //Don't remove space in first measure
                {
                    //if (measureNode.Elements(XName.Get("barline")).Any()) continue; //Nie bierz pod uwagi tych ze znakami repetycji, itp.

                    double?  currentValue  = null;
                    XElement firstNoteNode = measureNode.Descendants(XName.Get("note")).FirstOrDefault();
                    if (firstNoteNode == null)
                    {
                        continue;
                    }

                    var defaultXAttribute = firstNoteNode.Attributes().FirstOrDefault(a => a.Name == "default-x");
                    if (defaultXAttribute == null)
                    {
                        continue;
                    }

                    currentValue = UsefulMath.TryParse(defaultXAttribute.Value);
                    if (!currentValue.HasValue)
                    {
                        continue;
                    }
                    double difference = currentValue.Value - medianNoteDefaultX;

                    if (currentValue > averageNoteDefaultX)
                    {
                        foreach (var noteNode in measureNode.Descendants(XName.Get("note")))
                        {
                            defaultXAttribute = noteNode.Attributes().FirstOrDefault(a => a.Name == "default-x");
                            if (defaultXAttribute == null)
                            {
                                continue;
                            }

                            currentValue = UsefulMath.TryParse(defaultXAttribute.Value);
                            if (!currentValue.HasValue)
                            {
                                continue;
                            }

                            defaultXAttribute.Value = (currentValue.Value - difference).ToString(CultureInfo.InvariantCulture);
                        }
                        var widthAttribute = measureNode.Attributes().FirstOrDefault(a => a.Name == "width");
                        currentValue = UsefulMath.TryParse(widthAttribute.Value);
                        if (!currentValue.HasValue)
                        {
                            continue;
                        }
                        if (widthAttribute != null)
                        {
                            widthAttribute.Value = (currentValue.Value - difference).ToString(CultureInfo.InvariantCulture);
                        }
                    }
                }
            }
            return(source);
#endif
        }
        public static IEnumerable <Note> AddUniformRhythm(this IEnumerable <Pitch> pitches, int duration)
        {
            var durationAsPowerOfTwo = UsefulMath.Log2(duration);

            return(AddUniformRhythm(pitches, new RhythmicDuration(durationAsPowerOfTwo)));
        }
Esempio n. 13
0
    static void Main()
    {
        Mandlebrot.MaxCount = 100;
        Console.SetWindowSize(Console.LargestWindowWidth - 10, Console.LargestWindowHeight - 10);

        zoom   = (float)1 / 45;
        width  = Console.WindowWidth;
        height = Console.WindowHeight - 1;

        ConsoleKey keyPressed;

        do
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    double xMin = -width * zoom * charAspect + xOffset;
                    double xMax = width * zoom * charAspect + xOffset;
                    double yMin = -height * zoom + yOffset;
                    double yMax = height * zoom + yOffset;

                    double a = UsefulMath.Map(0, width - 1, xMin, xMax, x);
                    double b = UsefulMath.Map(0, height - 1, yMin, yMax, y);

                    string charToWrite = Mandlebrot.InSet(Mandlebrot.MandlebrotCalc(a, b)) ? "o" : " ";

                    Console.SetCursorPosition(x, y);
                    Console.Write(charToWrite[0]);
                }
            }
            keyPressed = Console.ReadKey().Key;

            switch (keyPressed)
            {
            // Change Offsets
            case ConsoleKey.LeftArrow:
                xOffset -= 0.45f * zoom * 45;
                break;

            case ConsoleKey.RightArrow:
                xOffset += 0.45f * zoom * 45;
                break;

            case ConsoleKey.UpArrow:
                yOffset -= 0.45f * zoom * 45;
                break;

            case ConsoleKey.DownArrow:
                yOffset += 0.45f * zoom * 45;
                break;

            // Change zooms
            case ConsoleKey.PageUp:
                zoom /= 2;
                break;

            case ConsoleKey.PageDown:
                zoom *= 2;
                break;
            }
        } while (!keyPressed.Equals(ConsoleKey.Escape));
    }
Esempio n. 14
0
        public override void ParseElement(MusicXmlParserState state, Staff staff, XElement element)
        {
            var builder = new NoteOrRestBuilder(state);

            element.IfAttribute("default-x").HasValue <double>().Then(m => builder.DefaultX = m);
            element.IfAttribute("measure").HasValue("yes").Then(m => builder.FullMeasure    = true);
            element.IfAttribute("print-object").HasValue(new Dictionary <string, bool> {
                { "yes", true }, { "no", false }
            }).Then(m => builder.IsVisible = m);
            element.IfAttribute("size").HasValue(new Dictionary <string, NoteOrRestSize>
            {
                { "cue", NoteOrRestSize.Cue },
                { "full", NoteOrRestSize.Full },
                { "large", NoteOrRestSize.Large },
            }).Then(s => builder.Size = s);
            element.IfElement("staff").HasValue <int>().Then(m => builder.Staff = staff.Part.Staves.ElementAt(m - 1));
            element.IfElement("type").HasValue(new Dictionary <string, RhythmicDuration> {
                { "breve", RhythmicDuration.DoubleWhole },
                { "whole", RhythmicDuration.Whole },
                { "half", RhythmicDuration.Half },
                { "quarter", RhythmicDuration.Quarter },
                { "eighth", RhythmicDuration.Eighth },
                { "16th", RhythmicDuration.Sixteenth },
                { "32nd", RhythmicDuration.D32nd },
                { "64th", RhythmicDuration.D64th },
                { "128th", RhythmicDuration.D128th }
            }).Then(m => builder.BaseDuration = m);
            var typeElement = element.GetElement("type");

            if (typeElement != null)
            {
                typeElement.IfAttribute("size").HasValue(new Dictionary <string, NoteOrRestSize>
                {
                    { "cue", NoteOrRestSize.Cue },
                    { "full", NoteOrRestSize.Full },
                    { "large", NoteOrRestSize.Large },
                }).Then(s => builder.Size = s);   //"size" attribute apparently can be added to element "type" too
            }

            element.IfElement("voice").HasValue <int>().Then(m => builder.Voice = m);
            var graceElement = element.GetElement("grace");

            if (graceElement != null)
            {
                graceElement.IfAttribute("slash").HasValue("yes")
                .Then(v => builder.GraceNoteType      = GraceNoteType.Slashed)
                .Otherwise(v => builder.GraceNoteType = GraceNoteType.Simple);
            }
            element.IfElement("chord").Exists().Then(() => builder.IsChordElement             = true);
            element.IfElement("accidental").HasValue("natural").Then(() => builder.HasNatural = true);
            element.IfElement("rest").Exists().Then(() => builder.IsRest = true);
            element.ForEachDescendant("dot", f => f.Exists().Then(() => builder.NumberOfDots++));

            var pitchElement = element.IfElement("pitch").Exists().ThenReturnResult();

            pitchElement.IfElement("step").HasAnyValue().Then(v => builder.Step        = v);
            pitchElement.IfElement("octave").HasValue <int>().Then(v => builder.Octave = v);
            pitchElement.IfElement("alter").HasValue <int>().Then(v => builder.Alter   = v);

            var unpitchedElement = element.IfElement("unpitched").Exists().Then(x => builder.IsUnpitched = true).AndReturnResult();

            unpitchedElement.IfElement("display-step").HasAnyValue().Then(v => builder.Step        = v);
            unpitchedElement.IfElement("display-octave").HasValue <int>().Then(v => builder.Octave = v);
            unpitchedElement.IfElement("display-alter").HasValue <int>().Then(v => builder.Alter   = v);

            var tieElements = element.Elements().Where(e => e.Name == "tie");

            foreach (var tieElement in tieElements)
            {
                tieElement.IfAttribute("type").HasValue("start").Then(v =>
                {
                    if (builder.TieType == NoteTieType.Stop)
                    {
                        builder.TieType = NoteTieType.StopAndStartAnother;
                    }
                    else
                    {
                        builder.TieType = NoteTieType.Start;
                    }
                }).Otherwise(r => builder.TieType = NoteTieType.Stop);
            }

            element.IfElement("stem").HasValue("down")
            .Then(() => builder.StemDirection     = VerticalDirection.Down)
            .Otherwise(r => builder.StemDirection = VerticalDirection.Up);
            element.GetElement("stem").IfAttribute("default-y").HasValue <float>().Then(v =>
            {
                builder.StemDefaultY          = v;
                builder.CustomStemEndPosition = true;
            });

            element.ForEachDescendant("beam", h => h.HasValue(new Dictionary <string, NoteBeamType> {
                { "begin", NoteBeamType.Start },
                { "end", NoteBeamType.End },
                { "continue", NoteBeamType.Continue },
                { "forward hook", NoteBeamType.ForwardHook },
                { "backward hook", NoteBeamType.BackwardHook }
            }).Then(v => builder.BeamList.Add(v))
                                      .Otherwise(r => { if (r.ToLowerInvariant() != "single")
                                                        {
                                                            throw new ScoreException(builder, $"Unsupported beam type \"{r}\".");
                                                        }
                                                 }));

            var notationsNode = element.GetElement("notations");
            var tupletNode    = notationsNode.GetElement("tuplet");

            tupletNode.IfAttribute("type").HasValue(new Dictionary <string, TupletType> {
                { "start", TupletType.Start },
                { "stop", TupletType.Stop },
            }).Then(v => builder.Tuplet = v);
            tupletNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                { "above", VerticalPlacement.Above },
                { "below", VerticalPlacement.Below },
            }).Then(v => builder.TupletPlacement = v);

            notationsNode.IfElement("fermata").Exists().Then(() => builder.HasFermataSign = true);
            notationsNode.IfElement("sound").Exists().Then(e => e.IfAttribute("dynamics").HasValue <int>().Then(v => state.CurrentDynamics = v));

            notationsNode.IfHasElement("dynamics").Then(d =>
            {
                var dir = new Direction();
                d.IfAttribute("default-y").HasValue <int>().Then(v =>
                {
                    dir.DefaultYPosition = v;
                    dir.Placement        = DirectionPlacementType.Custom;
                });
                d.IfAttribute("placement").HasValue(new Dictionary <string, DirectionPlacementType>
                {
                    { "above", DirectionPlacementType.Above },
                    { "below", DirectionPlacementType.Below }
                }).Then(v =>
                {
                    if (dir.Placement != DirectionPlacementType.Custom)
                    {
                        dir.Placement = v;
                    }
                });
                foreach (XElement dynamicsType in d.Elements())
                {
                    dir.Text = dynamicsType.Name.LocalName;
                }
                staff.Elements.Add(dir);
            });

            notationsNode.IfHasElement("articulations").Then(d =>
            {
                d.IfElement("staccato").HasAnyValue().Then(() => builder.Articulation = ArticulationType.Staccato);
                d.IfElement("accent").HasAnyValue().Then(() => builder.Articulation   = ArticulationType.Accent);
                d.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                    { "above", VerticalPlacement.Above },
                    { "below", VerticalPlacement.Below },
                }).Then(v => builder.ArticulationPlacement = v);
            });

            var ornamentsNode = notationsNode.GetElement("ornaments");

            ornamentsNode.GetElement("trill-mark").IfAttribute("placement").HasValue(new Dictionary <string, NoteTrillMark> {
                { "above", NoteTrillMark.Above },
                { "below", NoteTrillMark.Below }
            }).Then(v => builder.TrillMark = v);
            ornamentsNode.IfElement("tremolo").HasValue <int>().Then(v => builder.TremoloLevel = v);

            var invMordentNode = ornamentsNode
                                 .IfElement("inverted-mordent")
                                 .Exists()
                                 .Then(e => builder.Mordent = new Mordent()
            {
                IsInverted = true
            })
                                 .AndReturnResult();

            invMordentNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                { "above", VerticalPlacement.Above },
                { "below", VerticalPlacement.Below }
            }).Then(v => builder.Mordent.Placement = v);
            invMordentNode.IfAttribute("default-x").HasValue <double>().Then(v => builder.Mordent.DefaultXPosition = v);
            invMordentNode.IfAttribute("default-y").HasValue <double>().Then(v => builder.Mordent.DefaultYPosition = v);

            foreach (var slurNode in notationsNode?.Elements().Where(e => e.Name == "slur") ?? new XElement[] { })
            {
                var slur = new Slur();
                builder.Slurs.Add(slur);
                slurNode.IfAttribute("number").HasValue <int>().Then(v => slur.Number = v);
                slurNode.IfAttribute("type").HasValue(new Dictionary <string, NoteSlurType> {
                    { "start", NoteSlurType.Start },
                    { "stop", NoteSlurType.Stop }
                }).Then(v => slur.Type = v);
                slurNode.IfAttribute("placement").HasValue(new Dictionary <string, VerticalPlacement> {
                    { "above", VerticalPlacement.Above },
                    { "below", VerticalPlacement.Below }
                }).Then(v => slur.Placement = v);
                slurNode.IfAttribute("default-x").HasValue <double>().Then(v => slur.DefaultXPosition = v);
                slurNode.IfAttribute("default-y").HasValue <double>().Then(v => slur.DefaultYPosition = v);
                slurNode.IfAttribute("bezier-x").HasValue <double>().Then(v => slur.BezierX           = v);
                slurNode.IfAttribute("bezier-y").HasValue <double>().Then(v => slur.BezierY           = v);
            }

            foreach (var lNode in element.Elements().Where(n => n.Name == "lyric"))
            {
                //There can be more than one lyrics in one <lyrics> tag. Add lyrics to list once syllable type and text is set.
                //Then reset these tags so the next <syllabic> tag starts another lyric.
                Lyrics          lyricsInstance    = new Lyrics();
                Lyrics.Syllable syllable          = new Lyrics.Syllable();
                bool            isSylabicSet      = false;
                bool            isTextSet         = false;
                var             defaultYattribute = lNode.Attributes().FirstOrDefault(a => a.Name == "default-y");
                if (defaultYattribute != null)
                {
                    lyricsInstance.DefaultYPosition = UsefulMath.TryParse(defaultYattribute.Value);
                }

                foreach (XElement lyricAttribute in lNode.Elements())
                {
                    if (lyricAttribute.Name == "syllabic")
                    {
                        if (lyricAttribute.Value == "begin")
                        {
                            syllable.Type = SyllableType.Begin;
                        }
                        else if (lyricAttribute.Value == "middle")
                        {
                            syllable.Type = SyllableType.Middle;
                        }
                        else if (lyricAttribute.Value == "end")
                        {
                            syllable.Type = SyllableType.End;
                        }
                        else if (lyricAttribute.Value == "single")
                        {
                            syllable.Type = SyllableType.Single;
                        }
                        isSylabicSet = true;
                    }
                    else if (lyricAttribute.Name == "text")
                    {
                        syllable.Text = lyricAttribute.Value;
                        isTextSet     = true;
                    }
                    else if (lyricAttribute.Name == "elision")
                    {
                        syllable.ElisionMark = lyricAttribute.Value;
                    }

                    if (isSylabicSet && isTextSet)
                    {
                        lyricsInstance.Syllables.Add(syllable);
                        syllable     = new Lyrics.Syllable();
                        isSylabicSet = false;
                        isTextSet    = false;
                    }
                }

                builder.Lyrics.Add(lyricsInstance);
            }

            if (builder.BeamList.Count == 0)
            {
                builder.BeamList.Add(NoteBeamType.Single);
            }

            var noteOrRest = builder.Build();

            var correctStaff = noteOrRest.Staff ?? staff;

            correctStaff.Elements.Add(noteOrRest);
        }
Esempio n. 15
0
        /// <summary>
        /// Performs rebeaming with simple rules
        /// </summary>
        /// <param name="notes">Notes to rebeam</param>
        /// <param name="hookDirectionAlgorithm">Algorithm for determining hook direction in beams</param>
        /// <returns>Rebeamed notes</returns>
        public IEnumerable <NoteOrRest> Rebeam(IEnumerable <NoteOrRest> notes, HookDirectionAlgorithm hookDirectionAlgorithm = HookDirectionAlgorithm.ProductionCandidate)
        {
            Note previousNote = null;
            Note currentNote  = null;
            Note nextNote     = null;
            var  noteArray    = notes.ToArray();

            for (int i = 0; i < noteArray.Length; i++)
            {
                previousNote = i == 0 ? null : noteArray[i - 1] as Note;
                currentNote  = noteArray[i] as Note;
                nextNote     = i == noteArray.Length - 1 ? null : noteArray[i + 1] as Note;

                currentNote.BeamList.Clear();
                var numberOfBeams = currentNote.BaseDuration > RhythmicDuration.Eighth ? 0 : UsefulMath.Log2((int)currentNote.BaseDuration.Denominator) - 2;
                var numberOfBeamsOnPreviousNote = previousNote == null || previousNote.BaseDuration > RhythmicDuration.Eighth ?
                                                  0 : UsefulMath.Log2((int)previousNote.BaseDuration.Denominator) - 2;
                var numberOfBeamsOnNextNote = nextNote == null || nextNote.BaseDuration > RhythmicDuration.Eighth ?
                                              0 : UsefulMath.Log2((int)nextNote.BaseDuration.Denominator) - 2;

                for (var b = 0; b < numberOfBeams; b++)
                {
                    if (previousNote == null)
                    {
                        if (nextNote != null && numberOfBeamsOnNextNote < b + 1)
                        {
                            currentNote.BeamList.Add(DetermineHookDirection(notes.ToList(), currentNote, hookDirectionAlgorithm));
                        }
                        else
                        {
                            currentNote.BeamList.Add(NoteBeamType.Start);
                        }
                    }
                    else if (nextNote == null)
                    {
                        if (previousNote != null && numberOfBeamsOnPreviousNote < b + 1)
                        {
                            currentNote.BeamList.Add(DetermineHookDirection(notes.ToList(), currentNote, hookDirectionAlgorithm));
                        }
                        else
                        {
                            currentNote.BeamList.Add(NoteBeamType.End);
                        }
                    }
                    else
                    {
                        if (numberOfBeamsOnPreviousNote >= b + 1 && numberOfBeamsOnNextNote >= b + 1)
                        {
                            currentNote.BeamList.Add(NoteBeamType.Continue);
                        }
                        else if (numberOfBeamsOnPreviousNote < b + 1 && numberOfBeamsOnNextNote < b + 1)
                        {
                            currentNote.BeamList.Add(DetermineHookDirection(notes.ToList(), currentNote, hookDirectionAlgorithm));
                        }
                        else if (numberOfBeamsOnPreviousNote < b + 1)
                        {
                            currentNote.BeamList.Add(NoteBeamType.Start);
                        }
                        else if (numberOfBeamsOnNextNote < b + 1)
                        {
                            currentNote.BeamList.Add(NoteBeamType.End);
                        }
                    }
                }
            }
            return(notes);
        }