/// <summary> /// Draws of performs additional logic at slur end /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY">Y position of element with a slur</param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected override void ProcessSlurEnd(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement) { Point endPoint; var noteheadWidth = element.GetNoteheadWidthPx(renderer); if (slurStartInfo.StartPlacement == VerticalPlacement.Above) { var xShiftConcerningStemDirectionEnd = noteheadWidth / 2; bool hasFlagOrBeam = element.BaseDuration.Denominator > 4; endPoint = new Point(scoreService.CursorPositionX + xShiftConcerningStemDirectionEnd, (element.StemDirection == VerticalDirection.Up ? element.StemEndLocation.Y + (hasFlagOrBeam ? -2 : 0) : notePositionY - 7)); } else if (slurStartInfo.StartPlacement == VerticalPlacement.Below) { var xShiftConcerningStemDirectionEnd = noteheadWidth / 2; endPoint = new Point(scoreService.CursorPositionX + xShiftConcerningStemDirectionEnd, notePositionY + 5); } else { throw new Exception("Unsupported placement type."); } var slurHeight = DetermineSlurHeight(element, slur, slurStartInfo, endPoint); for (int i = 0; i < 3; i++) //Draw a few curves one by one to simulate a curve with variable thickness. It will be replaced by a path in future releases. { var controlPoints = GetBezierControlPoints(slurStartInfo.StartPoint, endPoint, slurStartInfo.StartPlacement, slurHeight + i); renderer.DrawBezier(slurStartInfo.StartPoint, controlPoints.Item1, controlPoints.Item2, endPoint, element); } //DrawSlurFrame(renderer, startPoint, controlPoints.Item1, controlPoints.Item2, endPoint, element); }
/// <summary> /// Draws a slur /// </summary> /// <param name="renderer"></param> /// <param name="slur"></param> /// <param name="element"></param> /// <param name="notePositionY"></param> public void Draw(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY) { VerticalPlacement slurPlacement; if (slur.Placement.HasValue) { slurPlacement = slur.Placement.Value; } else { slurPlacement = element.StemDirection == VerticalDirection.Up ? VerticalPlacement.Below : VerticalPlacement.Above; } if (slur.Type == NoteSlurType.Start) { ProcessSlurStart(renderer, slur, element, notePositionY, GetSlurInfoForWriting(slur.Number), slurPlacement); } if (slur.Type == NoteSlurType.Stop) { var slurInfo = GetSlurInfoForReading(slur.Number); if (slurInfo == null) { return; //There is no slur with that number. MusicXml file might be malformed (like in DWOK tom 1, s. 315, nr 24.xml) } ProcessSlurEnd(renderer, slur, element, notePositionY, slurInfo, slurPlacement); measurementService.Slurs.Remove(slur.Number); } }
/// <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); }
public static Slur CreateSlur(string type) { //create a slur Slur slur = new Slur(); slur.setType(StartStopContinue.fromValue(type)); slur.setNumber(new Integer(1)); return(slur); }
/// <summary> /// Draws of performs additional logic at slur end /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY">Y position of element with a slur</param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected override void ProcessSlurEnd(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement) { var absoluteControlPoint = RelativeToAbsolute(renderer, renderer.TenthsToPixels(slur.BezierStartOrEndPoint), notePositionY); var absoluteEndPoint = RelativeToAbsolute(renderer, renderer.TenthsToPixels(slur.BezierControlPoint), notePositionY); renderer.DrawBezier(slurStartInfo.StartPoint.X, slurStartInfo.StartPoint.Y, slurStartInfo.BezierStartControlPoint.X, slurStartInfo.BezierStartControlPoint.Y, absoluteControlPoint.X, absoluteControlPoint.Y, absoluteEndPoint.X, absoluteEndPoint.Y, element); }
/// <summary> /// Draws or performs additional logic at slur start /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY"></param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected override void ProcessSlurStart(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement) { slurStartInfo.StartPlacement = slurPlacement; slurStartInfo.StartPointStemDirection = element.StemDirection; var polihymniaFix = renderer.LinespacesToPixels(element.GetNoteheadWidthLs(renderer) * 0.5); if (slurPlacement == VerticalPlacement.Above) { bool hasFlagOrBeam = element.BaseDuration.Denominator > 4; //If note has a flag or beam start the slur above the note. If not, start a bit to the right and down. var xShiftConcerningStemDirectionStart = slurStartInfo.StartPointStemDirection == VerticalDirection.Up ? (hasFlagOrBeam ? 5 : 10) : 1; slurStartInfo.StartPoint = new Point(scoreService.CursorPositionX + xShiftConcerningStemDirectionStart + polihymniaFix, element.StemDirection == VerticalDirection.Down ? notePositionY - 7 : element.StemEndLocation.Y + (hasFlagOrBeam ? -3 : 8)); } else { slurStartInfo.StartPoint = new Point(scoreService.CursorPositionX + 3 + polihymniaFix, notePositionY + 5); } }
public DougResponse AddSlur(Command command) { var existingSlur = _slurRepository.GetSlurByText(command.Text); if (existingSlur != null) { return(new DougResponse(DougMessages.SlurAlreadyExists)); } var slur = new Slur(command.Text, command.UserId); _slurRepository.AddSlur(slur); _userRepository.AddCredits(command.UserId, AddSlurCredit); return(new DougResponse(string.Format(DougMessages.GainedCredit, AddSlurCredit))); }
public static string slurToABC(Slur slur) { string resslur = ""; switch (slur.Type) { case "start": resslur = "("; break; case "stop": resslur = ")"; break; } return(resslur); }
private void SetBeam(List <Symbol> symbolList) { switch (_beam) { case "begin": { _slur = new Slur(); _slur.GetList().Add((Note)_symbol); ((Note)_symbol).SetSlur(true); ((Note)_symbol).SetNext(true); } break; case "continue": { _slur.GetList().Add((Note)_symbol); ((Note)_symbol).SetLastNote((Note)symbolList[symbolList.Count - 1]); ((Note)_symbol).SetSlur(true); // ((Note) _symbol).SetLast(true); ((Note)_symbol).SetNext(true); } break; case "end": { Note lastNote = (Note)symbolList[symbolList.Count - 1]; _slur.GetList().Add((Note)_symbol); ((Note)_symbol).SetLastNote(lastNote); ((Note)_symbol).SetSlur(true); ((Note)_symbol).SetLast(true); if (_slur != null) { _slur.Operate(); } } break; default: break; } ((Note)_symbol).SetBeam(_beam); _beam = ""; }
private async Task SendSlurToChannel(Command command, Slur slur) { var users = _userRepository.GetUsers(); var rnd = new Random(); var randomUser = users.ElementAt(rnd.Next(users.Count)).Id; var message = BuildSlurMessage(slur.Text, randomUser, command.GetTargetUserId()); message = _itemEventDispatcher.OnFlaming(command, message); var timestamp = await _slack.BroadcastMessage(message, command.ChannelId); _slurRepository.LogRecentSlur(slur.Id, timestamp); await _slack.AddReaction(DougMessages.UpVote, timestamp, command.ChannelId); await _slack.AddReaction(DougMessages.Downvote, timestamp, command.ChannelId); }
public void AddSlur(Slur slur) { _db.Slurs.Add(slur); }
private Note GetNote(XmlNode noteNode) { var note = new Note(); var typeNode = noteNode.SelectSingleNode("type"); if (typeNode != null) { note.Type = typeNode.InnerText; } var voiceNode = noteNode.SelectSingleNode("voice"); if (voiceNode != null) { note.Voice = Convert.ToInt32(voiceNode.InnerText); } var durationNode = noteNode.SelectSingleNode("duration"); if (durationNode != null) { note.Duration = Convert.ToInt32(durationNode.InnerText); } var accidental = noteNode.SelectSingleNode("accidental"); if (accidental != null) { note.Accidental = accidental.InnerText; } note.Lyric = GetLyric(noteNode); note.Pitch = GetPitch(noteNode); var staffNode = noteNode.SelectSingleNode("staff"); if (staffNode != null) { note.Staff = Convert.ToInt32(staffNode.InnerText); } var chordNode = noteNode.SelectSingleNode("chord"); if (chordNode != null) { note.IsChordTone = true; } var restNode = noteNode.SelectSingleNode("rest"); if (restNode != null) { note.IsRest = true; } var dotNode = noteNode.SelectNodes("dot"); note.DotNumber = dotNode.Count; var slurNode = noteNode.SelectSingleNode("notations").SelectSingleNode("slur"); if (slurNode != null) { Slur slur = new Slur(); slur.Type = slurNode.Attributes["type"].ToString(); slur.Number = Convert.ToInt32(slurNode.Attributes["number"]); slur.Placement = slurNode.Attributes["placement"].ToString(); } return(note); }
private void BuildScoreConvertSameSlurredNotesToTies_RecursiveFixSlurs(Score score, int partIndex, int staffIndex, int elementGroupIndex, int elementIndex, INotation currentElementSlurStartNotation) { var part = score.Parts[partIndex]; var staff = part.Staves[staffIndex]; var elementGroup = staff.Elements[elementGroupIndex]; var element = elementGroup[elementIndex]; var isEndOfElementGroup = elementGroupIndex >= staff.Elements.Length; if (isEndOfElementGroup) { return; } var nextElementGroup = staff.Elements[elementGroupIndex + 1]; var nextElementGroupNoteOfSamePitch = nextElementGroup.FirstOrDefault(nextElement => nextElement.Pitch == element.Pitch); if (nextElementGroupNoteOfSamePitch == null) { return; } /* If the next element group at the same pitch has an ending slur, convert this to a start/stop tie. */ { var nextElementGroupNoteStopSlur = nextElementGroupNoteOfSamePitch.Notations.FirstOrDefault(nextElementNotation => nextElementNotation != null && nextElementNotation is Slur && (nextElementNotation as Slur).Type == StartStopContinue.Stop); if (nextElementGroupNoteStopSlur == null) { /* No issue with two notes of the same pitch being slurred */ return; } else { /* For current element. replace the slur start notation with a tie start notation */ { var newNotations = element.Notations.ToList(); newNotations = (List <INotation>)newNotations.Where(x => x != currentElementSlurStartNotation); newNotations.Add(new Tie() { Type = StartStopContinue.Start, Number = (currentElementSlurStartNotation as Slur).Number, }); element.Notations = newNotations.ToArray(); } /* For next element. replace the slur stop notation with a tie stop notation */ { var newNotations = nextElementGroupNoteOfSamePitch.Notations.ToList(); newNotations = (List <INotation>)newNotations.Where(x => x != nextElementGroupNoteStopSlur); newNotations.Add(new Tie() { Type = StartStopContinue.Stop, Number = (currentElementSlurStartNotation as Slur).Number, }); nextElementGroupNoteOfSamePitch.Notations = newNotations.ToArray(); } } } /* If the next element group at the same pitch has a continuation slur, recursively evaluate this */ { var nextElementGroupNoteContinueSlur = nextElementGroupNoteOfSamePitch.Notations.FirstOrDefault(nextElementNotation => nextElementNotation != null && nextElementNotation is Slur && (nextElementNotation as Slur).Type == StartStopContinue.Stop); if (nextElementGroupNoteContinueSlur == null) { /* No issue with two notes of the same pitch being slurred */ return; } else { /* For current element. replace the slur start notation with a tie start notation */ { var newNotations = element.Notations.ToList(); newNotations = (List <INotation>)newNotations.Where(x => x != currentElementSlurStartNotation); newNotations.Add(new Tie() { Type = StartStopContinue.Start, Number = (currentElementSlurStartNotation as Slur).Number, }); element.Notations = newNotations.ToArray(); } /* For next element. replace the slur stop notation with a tie continue notation */ { var newNotations = nextElementGroupNoteOfSamePitch.Notations.ToList(); newNotations = (List <INotation>)newNotations.Where(x => x != nextElementGroupNoteContinueSlur); newNotations.Add(new Tie() { Type = StartStopContinue.Stop, Number = (currentElementSlurStartNotation as Slur).Number, }); var newStartNotation = new Slur() { Type = StartStopContinue.Start, Number = (currentElementSlurStartNotation as Slur).Number, }; newNotations.Add(newStartNotation); nextElementGroupNoteOfSamePitch.Notations = newNotations.ToArray(); BuildScoreConvertSameSlurredNotesToTies_RecursiveFixSlurs(score, partIndex, staffIndex, elementGroupIndex + 1, elementIndex, newStartNotation); } } } }
/// <summary> /// Draws of performs additional logic at slur end /// </summary> /// <param name="renderer">Score renderer</param> /// <param name="slur">Slur</param> /// <param name="element">Element with a slur</param> /// <param name="notePositionY">Y position of element with a slur</param> /// <param name="slurStartInfo">Information about slur start point</param> /// <param name="slurPlacement">Information about slur placement</param> protected abstract void ProcessSlurEnd(ScoreRendererBase renderer, Slur slur, Note element, double notePositionY, SlurInfo slurStartInfo, VerticalPlacement slurPlacement);
/// <summary> /// Returns true if this strategy type is relevant for drawing a specific slur /// </summary> /// <param name="element">Element with a slur</param> /// <param name="slur">Slur</param> /// <returns>True if this strategy is relevant for rendering a specific slur</returns> public abstract bool IsRelevant(Note element, Slur slur);
/// <summary> /// Returns true if this strategy type is relevant for drawing a specific slur /// </summary> /// <param name="element">Element with a slur</param> /// <param name="slur">Slur</param> /// <returns>True if this strategy is relevant for rendering a specific slur</returns> public override bool IsRelevant(Note element, Slur slur) { return(slur.IsDefinedAsBezierCurve); }
//Read the note public static NoteProperties ReadNote(int notenumber, ScorePartwise.Part.Measure measure) { if (getnoteindex(notenumber, measure) != -1) { Note note = (Note)measure.getNoteOrBackupOrForward().get(getnoteindex(notenumber, measure)); NoteProperties noteprop = new NoteProperties(); noteprop.chord = note.getChord() == new Empty() ? true : false; if (note.getRest() != null) { //MessageBox.Show("Rest Read!"); noteprop.rest = true; try { noteprop.NoteType = note.getType().getValue(); } catch (System.Exception) { noteprop.NoteType = ""; } } else if (note.getPitch() is Pitch) { noteprop.NoteType = note.getType().getValue(); // get the notetype only if it is not a rest noteprop.PitchStep = note.getPitch().getStep().value(); noteprop.Pitchoctave = note.getPitch().getOctave(); if (note.getPitch().getAlter() != null) { noteprop.PitchAlter = note.getPitch().getAlter().floatValue(); } } noteprop.duration = note.getDuration().intValue(); if (note.getTie().size() != 0) { Tie tie = (Tie)note.getTie().get(0); noteprop.TieType = tie.getType().toString(); } noteprop.dot = note.getDot().size() == 0? false:true; noteprop.AccidentalType = note.getAccidental() == null? "":note.getAccidental().getValue().value(); if (note.getTimeModification() != null) { noteprop.TimeModactualnotes = note.getTimeModification().getActualNotes().intValue().ToString(); noteprop.TimeModnormalnotes = note.getTimeModification().getNormalNotes().intValue().ToString(); noteprop.TimeModnormaltype = note.getTimeModification().getNormalType() == null ? "" : note.getTimeModification().getNormalType(); } ///////////////////////////////////COMPLETE ME Beam beam; for (int i = 0; i < note.getBeam().size(); i++) { beam = (Beam)note.getBeam().get(i); noteprop.beamvalue.Add(beam.getValue().value()); noteprop.beamnumber.Add(beam.getNumber()); } if (note.getNotations().size() != 0) { Notations notations = (Notations)note.getNotations().get(0); for (int i = 0; i < notations.getTiedOrSlurOrTuplet().size(); i++) { if (notations.getTiedOrSlurOrTuplet().get(i) is Tied) { Tied tied = (Tied)notations.getTiedOrSlurOrTuplet().get(i); //if(tied.getNumber().intValue()==1) noteprop.TiedType = tied.getType().value(); } if (notations.getTiedOrSlurOrTuplet().get(i) is Slur) { Slur slur = (Slur)notations.getTiedOrSlurOrTuplet().get(i); if (slur.getNumber() == 1) { noteprop.SlurType = slur.getType().value(); } } if (notations.getTiedOrSlurOrTuplet().get(i) is Tuplet) { Tuplet tuplet = (Tuplet)notations.getTiedOrSlurOrTuplet().get(i); noteprop.TupletType = tuplet.getType().value(); //noteprop.TupletNumber = tuplet.getNumber().intValue(); } if (notations.getTiedOrSlurOrTuplet().get(i) is Dynamics) { Dynamics dynamics = (Dynamics)notations.getTiedOrSlurOrTuplet().get(i); javax.xml.bind.JAXBElement x = (javax.xml.bind.JAXBElement)dynamics.getPOrPpOrPpp().get(0); noteprop.dynamic = x.getName().ToString(); } } } if (note.getLyric().size() != 0) { Lyric lyric = (Lyric)note.getLyric().get(0); for (int i = 0; i < lyric.getElisionAndSyllabicAndText().size(); i++) { if (lyric.getElisionAndSyllabicAndText().get(i) is Syllabic) { Syllabic syllabic = (Syllabic)lyric.getElisionAndSyllabicAndText().get(i); noteprop.LyricSyllabic = syllabic.value(); } if (lyric.getElisionAndSyllabicAndText().get(i) is TextElementData) { TextElementData text = (TextElementData)lyric.getElisionAndSyllabicAndText().get(i); noteprop.LyricText = text.getValue(); } } noteprop.LyricEndline = lyric.getEndLine() == null?false:true; } return(noteprop); } return(null); }
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); }