public void CanBuildBareScoreWithSkeletonMusicXml() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(Path.Combine("Assets", "Bare_Score_With_Skeleton.musicxml"), FileMode.Open, FileAccess.Read)); var score = builder.Build(); AssertScoreIsEmpty(score); }
public void CanBuildMultiVoiceGrandStaffExcerptMusicXml() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(Path.Combine("Assets", "Multi_Voice_Grand_Staff_Excerpt.musicxml"), FileMode.Open, FileAccess.Read)); var score = builder.Build(); score.Parts.Should().ContainSingle(); score.Parts.First().Staves.Should().HaveCount(2); var treble = score.Parts.First().Staves.First().Elements; var bass = score.Parts.First().Staves[1].Elements; treble.Should().HaveCount(6); treble[0][0].Pitch.Should().Be("C5".ToPitch()); treble[0][0].Voice.Should().Be(2); treble[0][1].Pitch.Should().Be("F5".ToPitch()); treble[0][1].Voice.Should().Be(2); treble[0][2].Pitch.Should().Be("Bb5".ToPitch()); treble[0][2].Voice.Should().Be(1); treble[1][0].Pitch.Should().Be("Ab5".ToPitch()); treble[1][0].Voice.Should().Be(1); treble[2][0].Pitch.Should().Be("Bb4".ToPitch()); treble[2][0].Voice.Should().Be(2); treble[2][1].Pitch.Should().Be("F5".ToPitch()); treble[2][1].Voice.Should().Be(1); treble[3][0].Pitch.Should().Be("Bb4".ToPitch()); treble[3][0].Voice.Should().Be(2); treble[3][1].Pitch.Should().Be("Ab5".ToPitch()); treble[3][1].Voice.Should().Be(1); treble[4][0].Pitch.Should().Be("G5".ToPitch()); treble[4][0].Voice.Should().Be(1); treble[5][0].Pitch.Should().Be("Gb4".ToPitch()); treble[5][0].Voice.Should().Be(2); treble[5][1].Pitch.Should().Be("C5".ToPitch()); treble[5][1].Voice.Should().Be(2); treble[5][2].Pitch.Should().Be("Eb5".ToPitch()); treble[5][2].Voice.Should().Be(1); bass.Should().HaveCount(8); bass[0][0].Pitch.Should().Be("F3".ToPitch()); bass[0][0].Voice.Should().Be(5); bass[1][0].Pitch.Should().Be("Eb3".ToPitch()); bass[1][0].Voice.Should().Be(5); bass[2][0].Pitch.Should().Be("D3".ToPitch()); bass[2][0].Voice.Should().Be(5); bass[3][0].Pitch.Should().Be("Bb2".ToPitch()); bass[3][0].Voice.Should().Be(5); bass[4][0].Pitch.Should().Be("Eb3".ToPitch()); bass[4][0].Voice.Should().Be(5); bass[5][0].Pitch.Should().Be("D3".ToPitch()); bass[5][0].Voice.Should().Be(5); bass[6][0].Pitch.Should().Be("Eb3".ToPitch()); bass[6][0].Voice.Should().Be(5); bass[7][0].Pitch.Should().Be("A2".ToPitch()); bass[7][0].Voice.Should().Be(5); }
public void CanPlayArpeggiatedDefault() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(EtudeNo1ScoreFilePath, FileMode.Open, FileAccess.Read)); var score = builder.Build(); var interpreter = new Interpreter.Interpreter(); interpreter.SetScore(score, EtudeNo1ScoreFilePath); interpreter.SeekMeasure(21); var playedPitches = new List <byte>(); interpreter.Output += (IPianoEvent e) => { if (e is NotePress press) { playedPitches.Add(press.Pitch); } }; playedPitches.Should().BeEmpty(); interpreter.Input(new NotePress() { Pitch = "D6".ToPitch(), Velocity = 100 }); playedPitches.Should().BeEquivalentTo(new byte[] { "C4".ToPitch() }); interpreter.Input(new NotePress() { Pitch = "E6".ToPitch(), Velocity = 100 }); playedPitches.Should().BeEquivalentTo(new byte[] { "C4".ToPitch(), "E4".ToPitch() }); interpreter.Input(new NotePress() { Pitch = "F6".ToPitch(), Velocity = 100 }); playedPitches.Should().BeEquivalentTo(new byte[] { "C4".ToPitch(), "E4".ToPitch(), "G4".ToPitch() }); interpreter.Input(new NotePress() { Pitch = "G6".ToPitch(), Velocity = 100 }); playedPitches.Should().BeEquivalentTo(new byte[] { "C4".ToPitch(), "E4".ToPitch(), "G4".ToPitch(), "C5".ToPitch() }); }
public void CanPlaySequenceOfThreeNotes() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(EtudeNo1ScoreFilePath, FileMode.Open, FileAccess.Read)); var score = builder.Build(); var outputs = new List <IPianoEvent>(); var interpreter = new Interpreter.Interpreter(); interpreter.SetScore(score, EtudeNo1ScoreFilePath); interpreter.SeekMeasure(1); interpreter.Output += (IPianoEvent e) => { outputs.Add(e); }; var notePress1 = new NotePress() { Pitch = "C5".ToPitch(), Velocity = 65 }; var notePress2 = new NotePress() { Pitch = "D5".ToPitch(), Velocity = 65 }; var notePress3 = new NotePress() { Pitch = "E5".ToPitch(), Velocity = 65 }; interpreter.Input(notePress1); outputs.Should().Contain(new NotePress() { Pitch = "C4".ToPitch(), Velocity = notePress1.Velocity }); interpreter.Input(notePress2); outputs.Should().Contain(new NotePress() { Pitch = "D4".ToPitch(), Velocity = notePress2.Velocity }); interpreter.Input(notePress3); outputs.Should().Contain(new NotePress() { Pitch = "E4".ToPitch(), Velocity = notePress3.Velocity }); }
public void CanPlayPedals() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(EtudeNo1ScoreFilePath, FileMode.Open, FileAccess.Read)); var score = builder.Build(); var interpreter = new Interpreter.Interpreter(); interpreter.SetScore(score, EtudeNo1ScoreFilePath); interpreter.SeekMeasure(0); var pedalChanges = new List <PedalChange>(); interpreter.Output += (IPianoEvent e) => { if (e is PedalChange pedal) { pedalChanges.Add(pedal); } }; pedalChanges.Should().BeEmpty(); var sustainPedalChange = new PedalChange() { Pedal = PedalKind.Sustain, Position = 28 }; var sostenutoPedalChange = new PedalChange() { Pedal = PedalKind.Sostenuto, Position = 28 }; var unaCordaPedalChange = new PedalChange() { Pedal = PedalKind.UnaCorda, Position = 28 }; interpreter.Input(sustainPedalChange); pedalChanges.Should().BeEquivalentTo(new PedalChange[] { sustainPedalChange }); interpreter.Input(sostenutoPedalChange); pedalChanges.Should().BeEquivalentTo(new PedalChange[] { sustainPedalChange, sostenutoPedalChange }); interpreter.Input(unaCordaPedalChange); pedalChanges.Should().BeEquivalentTo(new PedalChange[] { sustainPedalChange, unaCordaPedalChange }); }
public void CanPlayAndReleaseNote() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(EtudeNo1ScoreFilePath, FileMode.Open, FileAccess.Read)); var score = builder.Build(); var outputs = new List <IPianoEvent>(); var interpreter = new Interpreter.Interpreter(); interpreter.SetScore(score, EtudeNo1ScoreFilePath); interpreter.SeekMeasure(1); interpreter.Output += (IPianoEvent e) => { outputs.Add(e); }; var notePress = new NotePress() { Pitch = "C5".ToPitch(), Velocity = 65 }; interpreter.Input(notePress); outputs.Should().Contain(new NotePress() { Pitch = "C4".ToPitch(), Velocity = notePress.Velocity }); var noteRelease = new NoteRelease() { Pitch = "C5".ToPitch() }; interpreter.Input(noteRelease); outputs.Should().Contain(new NoteRelease() { Pitch = "C4".ToPitch() }); }
public void CanPlayChordOutOfOrder() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(EtudeNo1ScoreFilePath, FileMode.Open, FileAccess.Read)); var score = builder.Build(); var outputs = new List <IPianoEvent>(); var interpreter = new Interpreter.Interpreter(); interpreter.SetScore(score, EtudeNo1ScoreFilePath); interpreter.SeekMeasure(3); interpreter.Output += (IPianoEvent e) => { outputs.Add(e); }; var notePress1 = new NotePress() { Pitch = "C5".ToPitch(), Velocity = 100 }; var notePress2 = new NotePress() { Pitch = "D5".ToPitch(), Velocity = 101 }; var notePress3 = new NotePress() { Pitch = "E5".ToPitch(), Velocity = 102 }; var notePress4 = new NotePress() { Pitch = "F5".ToPitch(), Velocity = 103 }; interpreter.Input(notePress3); outputs.Should().BeEmpty(); interpreter.Input(notePress2); outputs.Should().BeEmpty(); interpreter.Input(notePress4); outputs.Should().BeEmpty(); interpreter.Input(notePress1); outputs.Should().Contain(new NotePress() { Pitch = "G3".ToPitch(), Velocity = notePress3.Velocity }); outputs.Should().Contain(new NotePress() { Pitch = "C4".ToPitch(), Velocity = notePress4.Velocity }); outputs.Should().Contain(new NotePress() { Pitch = "E3".ToPitch(), Velocity = notePress2.Velocity }); outputs.Should().Contain(new NotePress() { Pitch = "C3".ToPitch(), Velocity = notePress1.Velocity }); }
public void CanBuildFullIdentificationMusicXml() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(Path.Combine("Assets", "Full_Identification.musicxml"), FileMode.Open, FileAccess.Read)); var score = builder.Build(); score.Info.WorkTitle.Should().Be("Work Title"); score.Info.WorkNumber.Should().Be("Work Number"); score.Info.MovementTitle.Should().Be("Movement Title"); score.Info.MovementNumber.Should().Be("Movement Number"); score.Info.Source.Should().Be("Source Description"); score.Info.Creators.Should().BeEquivalentTo(new ScoreCreator[] { new ScoreCreator() { Type = "creator-key-a", Name = "creator value a", }, new ScoreCreator() { Type = "creator-key-b", Name = "creator value b", }, new ScoreCreator() { Type = "creator-key-c", Name = "", /* No XML value */ }, new ScoreCreator() { Type = "", /* No creator type specified */ Name = "Ludwig van Beethoven", } }); score.Info.Rights.Should().BeEquivalentTo(new ScoreRights[] { new ScoreRights() { Type = "", Content = "Sample Copyright", }, new ScoreRights() { Type = "rights-key-a", Content = "rights value a", }, new ScoreRights() { Type = "rights-key-b", Content = "rights value b", }, }); score.Info.EncodingSoftware.Should().BeEquivalentTo(new string[] { "Finale 2012 for Windows", "Dolet Light for Finale 2012" }); score.Info.EncodingDates.Should().BeEquivalentTo(new DateTime[] { DateTime.Parse("2012-09-06"), DateTime.Parse("2012-09-09"), }); score.Info.Credits.Should().BeEquivalentTo(new string[] { "Etude No. 1", "Alan Turing", }); score.Info.Misc.Should().BeEquivalentTo(new ScoreMisc[] { new ScoreMisc() { Key = "", Value = "Misc value without key" }, new ScoreMisc() { Key = "misc-key-1", Value = "Misc value 1" }, new ScoreMisc() { Key = "misc-key-2", Value = "Misc value 2" }, }); }
public void CanConvertSamePitchSlursToTies() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(Path.Combine("Assets", "Slurs_To_Ties.musicxml"), FileMode.Open, FileAccess.Read)); var score = builder.Build(); score.Parts.Should().ContainSingle(); score.Parts.First().Staves.Should().HaveCount(1); var staff = score.Parts.First().Staves.First(); staff.Elements[0][0].Should().BeEquivalentTo(new Element() { Pitch = "C5".ToPitch(), IsChordChild = false, Measure = 1, Staff = 1, Voice = 1, Duration = 128m, Notations = new INotation[] { new Tie() { Type = StartStopContinue.Start, Number = 1 } }, NotatedPitch = "C5" }); staff.Elements[0][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Start, Number = 1 }); staff.Elements[1][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Stop, Number = 1 }); staff.Elements[2][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Start, Number = 1 }); staff.Elements[3][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Stop, Number = 1 }); staff.Elements[3][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Start, Number = 1 }); staff.Elements[4][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Stop, Number = 1 }); staff.Elements[5][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Start, Number = 1 }); staff.Elements[6][0].Notations.Should().ContainEquivalentOf(new Tie() { Type = StartStopContinue.Stop, Number = 1 }); }
public void CanBuildFullFeaturedSingleStaffMusicXml() { var builder = new ScoreBuilder.ScoreBuilder(new FileStream(Path.Combine("Assets", "Etude_No._1.musicxml"), FileMode.Open, FileAccess.Read)); var score = builder.Build(); score.Parts.Should().ContainSingle(); score.Parts.First().Staves.Should().HaveCount(1); var staff = score.Parts.First().Staves.First(); staff.Elements[0].Should().BeEquivalentTo(new Element() { Pitch = "C4".ToPitch(), IsChordChild = false, Measure = 1, Staff = 1, Voice = 1, Duration = 384m, NotatedPitch = "C4" }); var noteWithTrill = staff.Elements.SelectMany(x => x.Where(y => y.Notations.OfType <Trill>().Count() > 0) ).First(); noteWithTrill.Measure.Should().Be(13); noteWithTrill.Pitch.Should().Be("G4".ToPitch()); var noteWithTurn = staff.Elements.SelectMany(x => x.Where(y => y.Notations.OfType <Turn>().Count() > 0) ).First(); noteWithTurn.Measure.Should().Be(14); noteWithTurn.Notations[0].As <Turn>().IsInverted = false; noteWithTurn.Pitch.Should().Be("A4".ToPitch()); var noteWithInvertedTurn = staff.Elements.SelectMany(x => x.Where(y => y.Notations.OfType <Turn>().Count() > 0) ).ElementAt(1); noteWithInvertedTurn.Measure.Should().Be(15); noteWithInvertedTurn.Notations[0].As <Turn>().IsInverted = true; noteWithInvertedTurn.Pitch.Should().Be("B4".ToPitch()); var noteWithMordent = staff.Elements.SelectMany(x => x.Where(y => y.Notations.OfType <Mordent>().Count() > 0) ).First(); noteWithMordent.Measure.Should().Be(16); noteWithMordent.Notations[0].As <Mordent>().IsInverted = false; noteWithMordent.Pitch.Should().Be("C5".ToPitch()); var noteWithInvertedMordent = staff.Elements.SelectMany(x => x.Where(y => y.Notations.OfType <Mordent>().Count() > 0) ).ElementAt(1); noteWithInvertedMordent.Measure.Should().Be(17); noteWithInvertedMordent.Notations[0].As <Mordent>().IsInverted = true; noteWithInvertedMordent.Pitch.Should().Be("D5".ToPitch()); var graceNote = staff.Elements.SelectMany(x => x.Where(y => y.IsGraceNote)).First(); graceNote.Measure.Should().Be(18); graceNote.Pitch.Should().Be("D4".ToPitch()); var arpeggiatedGroups = staff.Elements.Where(x => x.Where(y => y.Notations.OfType <Arpeggiate>().Count() > 0).Count() > 0 ).ToArray(); var arpeggiatedDefault = arpeggiatedGroups[0].ToArray(); arpeggiatedGroups.Should().HaveCount(3); arpeggiatedDefault[0].Measure.Should().Be(21); arpeggiatedDefault[0].Pitch.Should().Be("C4".ToPitch()); arpeggiatedDefault[1].Pitch.Should().Be("E4".ToPitch()); arpeggiatedDefault[2].Pitch.Should().Be("G4".ToPitch()); arpeggiatedDefault[3].Pitch.Should().Be("C5".ToPitch()); var arpeggiatedUp = arpeggiatedGroups[1].ToArray(); arpeggiatedUp[0].Measure.Should().Be(22); arpeggiatedUp[0].Pitch.Should().Be("D4".ToPitch()); arpeggiatedUp[1].Pitch.Should().Be("F4".ToPitch()); arpeggiatedUp[2].Pitch.Should().Be("A4".ToPitch()); arpeggiatedUp[3].Pitch.Should().Be("D5".ToPitch()); var arpeggiatedDown = arpeggiatedGroups[2].ToArray(); arpeggiatedDown[0].Measure.Should().Be(23); arpeggiatedDown[0].Pitch.Should().Be("E4".ToPitch()); arpeggiatedDown[1].Pitch.Should().Be("G4".ToPitch()); arpeggiatedDown[2].Pitch.Should().Be("B4".ToPitch()); arpeggiatedDown[3].Pitch.Should().Be("E5".ToPitch()); var measureWithVoices = staff.Elements.Where(x => x.Where(y => y.Measure == 26).Count() > 0 ).ToArray(); measureWithVoices.Should().HaveCount(4); measureWithVoices[0][0].Pitch.Should().Be("D4".ToPitch()); measureWithVoices[0][0].Voice.Should().Be(3); measureWithVoices[0][1].Pitch.Should().Be("A4".ToPitch()); measureWithVoices[0][1].Voice.Should().Be(2); measureWithVoices[0][2].Pitch.Should().Be("E5".ToPitch()); measureWithVoices[0][2].Voice.Should().Be(1); measureWithVoices[1][0].Pitch.Should().Be("F4".ToPitch()); measureWithVoices[1][0].Voice.Should().Be(3); measureWithVoices[2][0].Pitch.Should().Be("D4".ToPitch()); measureWithVoices[2][0].Voice.Should().Be(3); measureWithVoices[2][1].Pitch.Should().Be("C5".ToPitch()); measureWithVoices[2][1].Voice.Should().Be(2); measureWithVoices[3][0].Pitch.Should().Be("F4".ToPitch()); measureWithVoices[3][0].Voice.Should().Be(3); }