private Beat GetOrCreateBeat(IXmlNode element, Bar[] bars, bool chord) { int voiceIndex = 0; var voiceNodes = element.GetElementsByTagName("voice"); if (voiceNodes.Length > 0) { voiceIndex = Std.ParseInt(Std.GetNodeValue(voiceNodes[0])) - 1; } var previousBeatWasPulled = _previousBeatWasPulled; _previousBeatWasPulled = false; var staffElement = element.GetElementsByTagName("staff"); int staff = 1; if (staffElement.Length > 0) { staff = Std.ParseInt(Std.GetNodeValue(staffElement[0])); // in case we have a beam with a staff-jump we pull the note to the previous staff if ((_isBeamContinue || previousBeatWasPulled) && _previousBeat.Voice.Bar.Staff.Index != staff - 1) { staff = _previousBeat.Voice.Bar.Staff.Index + 1; _previousBeatWasPulled = true; } var staffId = bars[0].Staff.Track.Index + "-" + staff; if (!_voiceOfStaff.ContainsKey(staffId)) { _voiceOfStaff[staffId] = voiceIndex; } voiceIndex -= _voiceOfStaff[staffId]; } var bar = bars[staff - 1]; Beat beat; var voice = GetOrCreateVoice(bar, voiceIndex); if (chord || (voice.Beats.Count == 1 && voice.IsEmpty)) { beat = voice.Beats[voice.Beats.Count - 1]; } else { beat = new Beat(); voice.AddBeat(beat); } _isBeamContinue = false; _previousBeat = beat; return(beat); }
private void ParseForward(IXmlNode element, Bar[] bars) { var beat = GetOrCreateBeat(element, bars, false); var durationInDivisions = Std.ParseInt(Std.GetNodeValue(element.GetElementsByTagName("duration")[0])); var duration = (durationInDivisions * (int)Duration.Quarter) / (float)_divisionsPerQuarterNote; var durations = new[] { (int)Duration.SixtyFourth, (int)Duration.ThirtySecond, (int)Duration.Sixteenth, (int)Duration.Eighth, (int)Duration.Quarter, (int)Duration.Half, (int)Duration.Whole }; foreach (var d in durations) { if (duration >= d) { beat.Duration = (Duration)d; duration -= d; break; } } if (duration > 0) { // TODO: Handle remaining duration // (additional beats, dotted durations,...) } beat.IsEmpty = false; }
private bool ParseNoteBeat(IXmlNode element, Track track, Bar bar, bool chord, bool isFirstBeat) { int voiceIndex = 0; var voiceNodes = element.GetElementsByTagName("voice"); if (voiceNodes.Length > 0) { voiceIndex = Std.ParseInt(Std.GetNodeValue(voiceNodes[0])) - 1; } Beat beat; var voice = GetOrCreateVoice(bar, voiceIndex); if (chord || (isFirstBeat && voice.Beats.Count == 1)) { beat = voice.Beats[voice.Beats.Count - 1]; } else { beat = new Beat(); voice.AddBeat(beat); } var note = new Note(); beat.AddNote(note); beat.IsEmpty = false; element.IterateChildren(c => { if (c.NodeType == XmlNodeType.Element) { switch (c.LocalName) { case "grace": //var slash = e.GetAttribute("slash"); //var makeTime = Std.ParseInt(e.GetAttribute("make-time")); //var stealTimePrevious = Std.ParseInt(e.GetAttribute("steal-time-previous")); //var stealTimeFollowing = Std.ParseInt(e.GetAttribute("steal-time-following")); beat.GraceType = GraceType.BeforeBeat; beat.Duration = Duration.ThirtySecond; break; case "duration": beat.Duration = (Duration)Std.ParseInt(Std.GetNodeValue(c)); break; case "tie": ParseTied(c, note); break; case "cue": // not supported break; case "instrument": // not supported break; case "type": switch (Std.GetNodeValue(c)) { case "256th": beat.Duration = Duration.TwoHundredFiftySixth; break; case "128th": beat.Duration = Duration.OneHundredTwentyEighth; break; case "breve": beat.Duration = Duration.DoubleWhole; break; case "long": beat.Duration = Duration.QuadrupleWhole; break; case "64th": beat.Duration = Duration.SixtyFourth; break; case "32nd": beat.Duration = Duration.ThirtySecond; break; case "16th": beat.Duration = Duration.Sixteenth; break; case "eighth": beat.Duration = Duration.Eighth; break; case "quarter": beat.Duration = Duration.Quarter; break; case "half": beat.Duration = Duration.Half; break; case "whole": beat.Duration = Duration.Whole; break; } break; case "dot": note.IsStaccato = true; break; case "accidental": ParseAccidental(c, note); break; case "time-modification": ParseTimeModification(c, beat); break; case "stem": // not supported break; case "notehead": if (c.GetAttribute("parentheses") == "yes") { note.IsGhost = true; } break; case "beam": // not supported break; case "notations": ParseNotations(c, beat, note); break; case "lyric": // not supported break; // "full-note" case "chord": chord = true; break; case "pitch": ParsePitch(c, track, beat, note); break; case "unpitched": // TODO: not yet fully supported note.String = 0; note.Fret = 0; break; case "rest": beat.IsEmpty = false; break; } } }); return chord; }
private bool ParseNoteBeat(IXmlNode element, Track track, Bar bar, bool chord, bool isFirstBeat) { int voiceIndex = 0; var voiceNodes = element.GetElementsByTagName("voice"); if (voiceNodes.Count > 0) { voiceIndex = Std.ParseInt(Std.GetNodeValue(voiceNodes[0])) - 1; } Beat beat; var voice = GetOrCreateVoice(bar, voiceIndex); if (chord || (isFirstBeat && voice.Beats.Count == 1)) { beat = voice.Beats[voice.Beats.Count - 1]; } else { beat = new Beat(); voice.AddBeat(beat); } var note = new Note(); beat.AddNote(note); beat.IsEmpty = false; element.IterateChildren(c => { if (c.NodeType == XmlNodeType.Element) { switch (c.LocalName) { case "grace": //var slash = e.GetAttribute("slash"); //var makeTime = Std.ParseInt(e.GetAttribute("make-time")); //var stealTimePrevious = Std.ParseInt(e.GetAttribute("steal-time-previous")); //var stealTimeFollowing = Std.ParseInt(e.GetAttribute("steal-time-following")); beat.GraceType = GraceType.BeforeBeat; beat.Duration = Duration.ThirtySecond; break; case "duration": beat.Duration = (Duration)Std.ParseInt(Std.GetNodeValue(c)); break; case "tie": ParseTied(c, note); break; case "cue": // not supported break; case "instrument": // not supported break; case "type": switch (Std.GetNodeValue(c)) { //case "256th": // break; //case "128th": // break; //case "breve": // break; //case "long": // break; case "64th": beat.Duration = Duration.SixtyFourth; break; case "32nd": beat.Duration = Duration.ThirtySecond; break; case "16th": beat.Duration = Duration.Sixteenth; break; case "eighth": beat.Duration = Duration.Eighth; break; case "quarter": beat.Duration = Duration.Quarter; break; case "half": beat.Duration = Duration.Half; break; case "whole": beat.Duration = Duration.Whole; break; } break; case "dot": note.IsStaccato = true; break; case "accidental": ParseAccidental(c, note); break; case "time-modification": ParseTimeModification(c, beat); break; case "stem": // not supported break; case "notehead": if (c.GetAttribute("parentheses") == "yes") { note.IsGhost = true; } break; case "beam": // not supported break; case "notations": ParseNotations(c, beat, note); break; case "lyric": // not supported break; // "full-note" case "chord": chord = true; break; case "pitch": ParsePitch(c, track, beat, note); break; case "unpitched": // TODO: not yet fully supported note.String = 0; note.Fret = 0; break; case "rest": beat.IsEmpty = false; break; } } }); return(chord); }
private void ParseNoteBeat(IXmlNode element, Bar[] bars) { var chord = element.GetElementsByTagName("chord").Length > 0; var beat = GetOrCreateBeat(element, bars, chord); beat.ChordId = _currentChord; _currentChord = null; var note = new Note(); beat.AddNote(note); beat.IsEmpty = false; beat.Dots = 0; element.IterateChildren(c => { if (c.NodeType == XmlNodeType.Element) { switch (c.LocalName) { case "grace": //var slash = e.GetAttribute("slash"); //var makeTime = Std.ParseInt(e.GetAttribute("make-time")); //var stealTimePrevious = Std.ParseInt(e.GetAttribute("steal-time-previous")); //var stealTimeFollowing = Std.ParseInt(e.GetAttribute("steal-time-following")); beat.GraceType = GraceType.BeforeBeat; beat.Duration = Duration.ThirtySecond; break; case "duration": if (beat.IsRest) { // unit: divisions per quarter note var duration = Std.ParseInt(Std.GetNodeValue(c)); switch (duration) { case 1: beat.Duration = Duration.Whole; break; case 2: beat.Duration = Duration.Half; break; case 4: beat.Duration = Duration.Quarter; break; case 8: beat.Duration = Duration.Eighth; break; case 16: beat.Duration = Duration.Sixteenth; break; case 32: beat.Duration = Duration.ThirtySecond; break; case 64: beat.Duration = Duration.SixtyFourth; break; default: beat.Duration = Duration.Quarter; break; } } break; case "tie": ParseTied(c, note); break; case "cue": // not supported break; case "instrument": // not supported break; case "type": switch (Std.GetNodeValue(c)) { case "256th": case "128th": case "64th": beat.Duration = Duration.SixtyFourth; break; case "32nd": beat.Duration = Duration.ThirtySecond; break; case "16th": beat.Duration = Duration.Sixteenth; break; case "eighth": beat.Duration = Duration.Eighth; break; case "quarter": beat.Duration = Duration.Quarter; break; case "half": beat.Duration = Duration.Half; break; case "long": case "breve": case "whole": beat.Duration = Duration.Whole; break; } if (beat.GraceType != GraceType.None && beat.Duration < Duration.Sixteenth) { beat.Duration = Duration.Eighth; } break; case "dot": beat.Dots++; break; case "accidental": ParseAccidental(c, note); break; case "time-modification": ParseTimeModification(c, beat); break; case "stem": // not supported break; case "notehead": if (c.GetAttribute("parentheses") == "yes") { note.IsGhost = true; } break; case "beam": var beamMode = Std.GetNodeValue(c); if (beamMode == "continue") { _isBeamContinue = true; } break; case "notations": ParseNotations(c, beat, note); break; case "lyric": ParseLyric(c, beat); break; // "full-note" case "pitch": ParsePitch(c, note); break; case "unpitched": ParseUnpitched(c, note); break; case "rest": beat.IsEmpty = false; beat.Notes.Clear(); break; } } }); // check if new note is duplicate on string if (note.IsStringed) { for (int i = 0; i < beat.Notes.Count; i++) { if (beat.Notes[i].String == note.String && beat.Notes[i] != note) { beat.RemoveNote(note); break; } } } }
private void ParseHarmony(IXmlNode element, Track track) { var root = element.GetElementsByTagName("root")[0]; var rootStep = Std.GetNodeValue(root.GetElementsByTagName("root-step")[0]); var kind = Std.GetNodeValue(element.GetElementsByTagName("kind")[0]); var chord = new Chord(); chord.Name = rootStep; // TODO: find proper names for the rest //switch (kind) //{ // // triads // case "major": // break; // case "minor": // chord.Name += "m"; // break; // // Sevenths // case "augmented": // break; // case "diminished": // break; // case "dominant": // break; // case "major-seventh": // chord.Name += "7M"; // break; // case "minor-seventh": // chord.Name += "m7"; // break; // case "diminished-seventh": // break; // case "augmented-seventh": // break; // case "half-diminished": // break; // case "major-minor": // break; // // Sixths // case "major-sixth": // break; // case "minor-sixth": // break; // // Ninths // case "dominant-ninth": // break; // case "major-ninth": // break; // case "minor-ninth": // break; // // 11ths // case "dominant-11th": // break; // case "major-11th": // break; // case "minor-11th": // break; // // 13ths // case "dominant-13th": // break; // case "major-13th": // break; // case "minor-13th": // break; // // Suspended // case "suspended-second": // break; // case "suspended-fourth": // break; // // Functional sixths // case "Neapolitan": // break; // case "Italian": // break; // case "French": // break; // case "German": // break; // // Other // case "pedal": // break; // case "power": // break; // case "Tristan": // break; //} //var degree = element.GetElementsByTagName("degree"); //if (degree.Length > 0) //{ // var degreeValue = Std.GetNodeValue(degree[0].GetElementsByTagName("degree-value")[0]); // var degreeAlter = Std.GetNodeValue(degree[0].GetElementsByTagName("degree-alter")[0]); // var degreeType = Std.GetNodeValue(degree[0].GetElementsByTagName("degree-type")[0]); // if (!string.IsNullOrEmpty(degreeType)) // { // chord.Name += degreeType; // } // if (!string.IsNullOrEmpty(degreeValue)) // { // chord.Name += "#" + degreeValue; // } //} _currentChord = Std.NewGuid(); track.Chords[_currentChord] = chord; }
private bool ParseMeasure(IXmlNode element, Track track, bool isFirstMeasure) { if (element.GetAttribute("implicit") == "yes" && element.GetElementsByTagName("note").Length == 0) { return(false); } var barIndex = 0; if (isFirstMeasure) { _divisionsPerQuarterNote = 0; _trackFirstMeasureNumber = Std.ParseInt(element.GetAttribute("number")); if (_trackFirstMeasureNumber == int.MinValue) { _trackFirstMeasureNumber = 0; } barIndex = 0; } else { barIndex = Std.ParseInt(element.GetAttribute("number")); if (barIndex == int.MinValue) { return(false); } barIndex -= _trackFirstMeasureNumber; } // try to find out the number of staffs required if (isFirstMeasure) { var attributes = element.GetElementsByTagName("attributes"); if (attributes.Length > 0) { var stavesElements = attributes[0].GetElementsByTagName("staves"); if (stavesElements.Length > 0) { var staves = Std.ParseInt(Std.GetNodeValue(stavesElements[0])); track.EnsureStaveCount(staves); } } } // create empty bars to the current index Bar[] bars = new Bar[track.Staves.Count]; MasterBar masterBar = null; for (int b = track.Staves[0].Bars.Count; b <= barIndex; b++) { for (int s = 0; s < track.Staves.Count; s++) { var bar = bars[s] = new Bar(); if (track.Staves[s].Bars.Count > 0) { var previousBar = track.Staves[s].Bars[track.Staves[s].Bars.Count - 1]; bar.Clef = previousBar.Clef; } masterBar = GetOrCreateMasterBar(barIndex); track.AddBarToStaff(s, bar); for (int v = 0; v < _maxVoices; v++) { var emptyVoice = new Voice(); bar.AddVoice(emptyVoice); var emptyBeat = new Beat { IsEmpty = true }; emptyVoice.AddBeat(emptyBeat); } } } var attributesParsed = false; element.IterateChildren(c => { if (c.NodeType == XmlNodeType.Element) { switch (c.LocalName) { case "note": ParseNoteBeat(c, bars); break; case "forward": ParseForward(c, bars); break; case "direction": ParseDirection(c, masterBar); break; case "attributes": if (!attributesParsed) { ParseAttributes(c, bars, masterBar); attributesParsed = true; } break; case "harmony": ParseHarmony(c, track); break; case "sound": // TODO break; case "barline": ParseBarline(c, masterBar); break; } } }); return(true); }