-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
eaaf27b
commit 650bcd1
Showing
8 changed files
with
204 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using BaroquenMelody.Library.Composition.Choices; | ||
using BaroquenMelody.Library.Composition.Contexts; | ||
|
||
namespace BaroquenMelody.Library.Composition; | ||
|
||
/// <summary> | ||
/// Represents a chord in a composition. | ||
/// </summary> | ||
/// <param name="Notes"> The notes which make up the chord. </param> | ||
/// <param name="ChordContext"> The previous chord context from which this chord was generated. </param> | ||
/// <param name="ChordChoice"> The chord choice which was used to generate this chord. </param> | ||
internal sealed record Chord( | ||
ISet<Note> Notes, | ||
ChordContext ChordContext, | ||
ChordChoice ChordChoice | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using BaroquenMelody.Library.Composition.Choices; | ||
using BaroquenMelody.Library.Composition.Contexts; | ||
|
||
namespace BaroquenMelody.Library.Composition; | ||
|
||
/// <summary> | ||
/// Represents a note in a composition. | ||
/// </summary> | ||
/// <param name="Pitch"> The pitch of the note. </param> | ||
/// <param name="NoteContext"> The previous note context from which this note was generated. </param> | ||
/// <param name="NoteChoice"> The note choice which was used to generate this note. </param> | ||
internal sealed record Note( | ||
byte Pitch, | ||
NoteContext NoteContext, | ||
NoteChoice NoteChoice | ||
); |
32 changes: 32 additions & 0 deletions
32
src/BaroquenMelody.Library/Extensions/ChordContextExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
using BaroquenMelody.Library.Composition; | ||
using BaroquenMelody.Library.Composition.Choices; | ||
using BaroquenMelody.Library.Composition.Contexts; | ||
|
||
namespace BaroquenMelody.Library.Extensions; | ||
|
||
internal static class ChordContextExtensions | ||
{ | ||
/// <summary> | ||
/// Applies the given <see cref="ChordChoice"/> to the given <see cref="ChordContext"/> to generate the next chord. | ||
/// </summary> | ||
/// <param name="chordContext"> The chord context. </param> | ||
/// <param name="chordChoice"> The chord choice. </param> | ||
/// <returns> The next chord. </returns> | ||
public static Chord ApplyChordChoice(this ChordContext chordContext, ChordChoice chordChoice) | ||
{ | ||
var notes = new HashSet<Note>(); | ||
|
||
foreach (var noteChoice in chordChoice.NoteChoices) | ||
{ | ||
var noteContext = chordContext[noteChoice.Voice]; | ||
|
||
notes.Add(noteContext.ApplyNoteChoice(noteChoice)); | ||
} | ||
|
||
return new Chord( | ||
notes, | ||
chordContext, | ||
chordChoice | ||
); | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/BaroquenMelody.Library/Extensions/NoteContextExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
using BaroquenMelody.Library.Composition; | ||
using BaroquenMelody.Library.Composition.Choices; | ||
using BaroquenMelody.Library.Composition.Contexts; | ||
using BaroquenMelody.Library.Composition.Enums; | ||
|
||
namespace BaroquenMelody.Library.Extensions; | ||
|
||
internal static class NoteContextExtensions | ||
{ | ||
/// <summary> | ||
/// Applies the given <see cref="NoteChoice"/> to the given <see cref="NoteContext"/> to generate the next note. | ||
/// </summary> | ||
/// <param name="noteContext"> The note context. </param> | ||
/// <param name="noteChoice"> The note choice. </param> | ||
/// <returns> The next note. </returns> | ||
/// <exception cref="ArgumentOutOfRangeException"> Thrown when the given <see cref="NoteChoice"/> has an invalid <see cref="NoteMotion"/>. </exception> | ||
public static Note ApplyNoteChoice(this NoteContext noteContext, NoteChoice noteChoice) | ||
{ | ||
var pitch = noteChoice.Motion switch | ||
{ | ||
NoteMotion.Ascending => noteContext.Pitch + noteChoice.PitchChange, | ||
NoteMotion.Descending => noteContext.Pitch - noteChoice.PitchChange, | ||
NoteMotion.Oblique => noteContext.Pitch, | ||
_ => throw new ArgumentOutOfRangeException(nameof(noteChoice)) | ||
}; | ||
|
||
return new Note( | ||
(byte)pitch, | ||
noteContext, | ||
noteChoice | ||
); | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
tests/BaroquenMelody.Library.Tests/Extensions/ChordContextExtensionsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
using BaroquenMelody.Library.Composition; | ||
using BaroquenMelody.Library.Composition.Choices; | ||
using BaroquenMelody.Library.Composition.Contexts; | ||
using BaroquenMelody.Library.Composition.Enums; | ||
using BaroquenMelody.Library.Extensions; | ||
using FluentAssertions; | ||
using NUnit.Framework; | ||
|
||
namespace BaroquenMelody.Library.Tests.Extensions; | ||
|
||
[TestFixture] | ||
internal sealed class ChordContextExtensionsTests | ||
{ | ||
[Test] | ||
public void ApplyChordChoice_ShouldApplyNoteChoicesToChord() | ||
{ | ||
// arrange | ||
var chordContext = new ChordContext(new[] | ||
{ | ||
new NoteContext(Voice.Soprano, 60, NoteMotion.Oblique, NoteSpan.Leap), | ||
new NoteContext(Voice.Alto, 55, NoteMotion.Oblique, NoteSpan.Leap), | ||
new NoteContext(Voice.Tenor, 50, NoteMotion.Oblique, NoteSpan.Leap), | ||
new NoteContext(Voice.Bass, 45, NoteMotion.Oblique, NoteSpan.Leap) | ||
}); | ||
|
||
var chordChoice = new ChordChoice(new HashSet<NoteChoice> | ||
{ | ||
new(Voice.Soprano, NoteMotion.Ascending, 2), | ||
new(Voice.Alto, NoteMotion.Descending, 1), | ||
new(Voice.Tenor, NoteMotion.Oblique, 0), | ||
new(Voice.Bass, NoteMotion.Ascending, 3) | ||
}); | ||
|
||
var expectedNotes = new HashSet<Note> | ||
{ | ||
new(62, chordContext[Voice.Soprano], chordChoice.NoteChoices.First(noteChoice => noteChoice.Voice == Voice.Soprano)), | ||
new(54, chordContext[Voice.Alto], chordChoice.NoteChoices.First(noteChoice => noteChoice.Voice == Voice.Alto)), | ||
new(50, chordContext[Voice.Tenor], chordChoice.NoteChoices.First(noteChoice => noteChoice.Voice == Voice.Tenor)), | ||
new(48, chordContext[Voice.Bass], chordChoice.NoteChoices.First(noteChoice => noteChoice.Voice == Voice.Bass)) | ||
}; | ||
|
||
// act | ||
var resultChord = chordContext.ApplyChordChoice(chordChoice); | ||
|
||
// assert | ||
resultChord.Notes.Should().BeEquivalentTo(expectedNotes); | ||
resultChord.ChordContext.Should().Be(chordContext); | ||
resultChord.ChordChoice.Should().Be(chordChoice); | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
tests/BaroquenMelody.Library.Tests/Extensions/NoteContextExtensionsTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
using BaroquenMelody.Library.Composition.Choices; | ||
using BaroquenMelody.Library.Composition.Contexts; | ||
using BaroquenMelody.Library.Composition.Enums; | ||
using BaroquenMelody.Library.Extensions; | ||
using FluentAssertions; | ||
using NUnit.Framework; | ||
|
||
namespace BaroquenMelody.Library.Tests.Extensions; | ||
|
||
[TestFixture] | ||
internal sealed class NoteContextExtensionsTests | ||
{ | ||
[Test] | ||
[TestCase(60, 2, NoteMotion.Ascending, 62)] | ||
[TestCase(60, 2, NoteMotion.Descending, 58)] | ||
[TestCase(60, 0, NoteMotion.Oblique, 60)] | ||
public void ApplyNoteChoice_ShouldCalculateCorrectPitch( | ||
byte startPitch, | ||
byte pitchChange, | ||
NoteMotion noteMotion, | ||
byte expectedPitch) | ||
{ | ||
// arrange | ||
var noteContext = new NoteContext(Voice.Soprano, startPitch, NoteMotion.Oblique, NoteSpan.None); | ||
var noteChoice = new NoteChoice(Voice.Soprano, noteMotion, pitchChange); | ||
|
||
// act | ||
var resultNote = noteContext.ApplyNoteChoice(noteChoice); | ||
|
||
// assert | ||
resultNote.Pitch.Should().Be(expectedPitch); | ||
resultNote.NoteContext.Should().BeEquivalentTo(noteContext); | ||
resultNote.NoteChoice.Should().BeEquivalentTo(noteChoice); | ||
} | ||
|
||
[Test] | ||
public void ApplyNoteChoice_WithUnsupportedMotion_ShouldThrowArgumentOutOfRangeException() | ||
{ | ||
// arrange | ||
var noteContext = new NoteContext(Voice.Soprano, 60, NoteMotion.Oblique, NoteSpan.None); | ||
var noteChoice = new NoteChoice(Voice.Soprano, (NoteMotion)55, 5); | ||
|
||
// act | ||
var act = () => noteContext.ApplyNoteChoice(noteChoice); | ||
|
||
// assert | ||
act.Should().Throw<ArgumentOutOfRangeException>(); | ||
} | ||
} |