Skip to content

Commit 0780ebf

Browse files
committed
Change playback's objects on the fly (#78)
1 parent 4bbd57c commit 0780ebf

28 files changed

+11222
-428
lines changed
Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
using NUnit.Framework;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System;
5+
using Melanchall.DryWetMidi.Common;
6+
using System.Drawing;
7+
using Melanchall.DryWetMidi.Tests.Multimedia;
8+
9+
namespace Melanchall.DryWetMidi.Tests.Common
10+
{
11+
[TestFixture]
12+
public sealed class RedBlackTreeTests
13+
{
14+
private sealed class KeyValue : IEquatable<KeyValue>
15+
{
16+
public KeyValue(int key, string value)
17+
{
18+
Key = key;
19+
Value = value;
20+
}
21+
22+
public int Key { get; set; }
23+
24+
public string Value { get; set; }
25+
26+
public bool Equals(KeyValue other) =>
27+
ReferenceEquals(this, other);
28+
}
29+
30+
[Test]
31+
public void Enumerate_Empty()
32+
{
33+
var tree = new RedBlackTree<int, int>();
34+
var enumerated = tree.ToArray();
35+
36+
CollectionAssert.IsEmpty(enumerated, "Enumerated collection is not empty.");
37+
}
38+
39+
[Test]
40+
public void Enumerate([Values(0, 1, 2, 3, 4, 5, 10, 100, 1000, 10000)] int count)
41+
{
42+
var random = DryWetMidi.Common.Random.Instance;
43+
var data = Enumerable.Range(0, count).Select(_ => random.Next(1000)).ToArray();
44+
45+
var tree = new RedBlackTree<int, int>(data, d => d);
46+
var enumerated = tree.ToArray();
47+
48+
CollectionAssert.AreEqual(
49+
data.OrderBy(d => d).ToArray(),
50+
enumerated,
51+
"Enumerated collection is invalid.");
52+
}
53+
54+
[Test]
55+
public void InsertOne([Values(0, 10, 40, -2, 1000, 12, 2, 9, 11)] int value)
56+
{
57+
var data = new[] { 2, 3, 1, 1, 10, 100, 50, 45, 0 };
58+
var tree = new RedBlackTree<int, int>(data, d => d);
59+
60+
CheckAscendingOrder(tree.ToArray());
61+
62+
tree.Add(value, value);
63+
CheckAscendingOrder(tree.ToArray());
64+
}
65+
66+
[Test]
67+
public void InsertMultiple()
68+
{
69+
var data = new[] { 2, 3, 1, 1, 10, 100, 50, 45, 0 }.ToList();
70+
var tree = new RedBlackTree<int, int>(data, d => d);
71+
72+
CheckAscendingOrder(tree.ToArray());
73+
74+
var dataToAdd = new[] { 0, 10, 40, -2, 1000, 12, 2, 9, 11 };
75+
76+
foreach (var d in dataToAdd)
77+
{
78+
tree.Add(d, d);
79+
CheckAscendingOrder(tree.ToArray());
80+
}
81+
}
82+
83+
[Test]
84+
public void DeleteOne([Values(500, 100, 2, 4, 6, 9, 10, 700, 701, 702, 45, 44, 43)] int value)
85+
{
86+
var data = Enumerable.Range(0, 1000).ToList();
87+
var tree = new RedBlackTree<int, int>(data, d => d);
88+
89+
CheckAscendingOrder(tree.ToArray());
90+
91+
tree.Delete(tree.GetFirstNode(value));
92+
CheckAscendingOrder(tree.ToArray());
93+
}
94+
95+
[Test]
96+
public void DeleteMultiple()
97+
{
98+
var data = Enumerable.Range(0, 1000).ToList();
99+
var tree = new RedBlackTree<int, int>(data, d => d);
100+
101+
CheckAscendingOrder(tree.ToArray());
102+
103+
var dataToDelete = new[] { 500, 100, 2, 4, 6, 9, 10, 700, 701, 702, 45, 44, 43 };
104+
105+
foreach (var d in dataToDelete)
106+
{
107+
tree.Delete(tree.GetFirstNode(d));
108+
CheckAscendingOrder(tree.ToArray());
109+
}
110+
}
111+
112+
[Test]
113+
public void GetNextNode([Values(1, 2, 4, 8, 16, 32, 64, 128, 10, 100, 1000)] int count)
114+
{
115+
var data = Enumerable.Range(0, count).ToArray();
116+
var tree = new RedBlackTree<int, int>(data, d => d);
117+
118+
for (var i = 0; i < data.Length; i++)
119+
{
120+
var node = tree.GetFirstNode(i);
121+
var values = EnumerateViaGetNextNode(tree, node).ToArray();
122+
CheckAscendingOrder(values);
123+
}
124+
}
125+
126+
[Test]
127+
public void GetPreviousNode([Values(1, 2, 4, 8, 16, 32, 64, 128, 10, 100, 1000)] int count)
128+
{
129+
var data = Enumerable.Range(0, count).ToArray();
130+
var tree = new RedBlackTree<int, int>(data, d => d);
131+
132+
for (var i = 0; i < data.Length; i++)
133+
{
134+
var node = tree.GetFirstNode(i);
135+
var values = EnumerateViaGetPreviousNode(tree, node).ToArray();
136+
CheckDescendingOrder(values);
137+
}
138+
}
139+
140+
[Test]
141+
public void GetValues()
142+
{
143+
var aValue = new KeyValue(1, "A");
144+
var bValue = new KeyValue(2, "B");
145+
var cValue = new KeyValue(3, "C");
146+
var dValue = new KeyValue(-3, "D");
147+
var eValue = new KeyValue(1, "E");
148+
var fValue = new KeyValue(0, "F");
149+
var gValue = new KeyValue(10, "G");
150+
var hValue = new KeyValue(1, "H");
151+
var iValue = new KeyValue(2, "I");
152+
153+
var data = new[]
154+
{
155+
aValue,
156+
bValue,
157+
cValue,
158+
dValue,
159+
eValue,
160+
fValue,
161+
gValue,
162+
hValue,
163+
iValue,
164+
};
165+
var tree = new RedBlackTree<int, KeyValue>(data, d => d.Key);
166+
167+
var values1 = tree.GetValues(1);
168+
CollectionAssert.AreEqual(new[] { aValue, eValue, hValue }, values1, "Invalid values by key 1.");
169+
170+
var values2 = tree.GetValues(2);
171+
CollectionAssert.AreEqual(new[] { bValue, iValue }, values2, "Invalid values by key 2.");
172+
173+
var values3 = tree.GetValues(3);
174+
CollectionAssert.AreEqual(new[] { cValue }, values3, "Invalid values by key 3.");
175+
}
176+
177+
[Test]
178+
public void Clone([Values(1, 2, 4, 8, 16, 32, 64, 128, 10, 100, 1000, 10000)] int count)
179+
{
180+
var data = Enumerable.Range(0, count).ToArray();
181+
182+
var tree = new RedBlackTree<int, int>(data, d => d);
183+
var treeElements = tree.ToArray();
184+
185+
var treeClone = tree.Clone();
186+
var treeCloneElements = treeClone.ToArray();
187+
188+
CollectionAssert.AreEqual(data, treeElements, "Original tree elements are invalid.");
189+
CollectionAssert.AreEqual(data, treeCloneElements, "Tree clone elements are invalid.");
190+
CollectionAssert.AreEqual(treeElements, treeCloneElements, "Tree clone elements aren't equal to original ones.");
191+
192+
var treeNodes = tree.EnumerateNodes().ToArray();
193+
var treeCloneNodes = treeClone.EnumerateNodes().ToArray();
194+
var nodesIntersection = treeNodes.Intersect(treeCloneNodes).ToArray();
195+
CollectionAssert.IsEmpty(nodesIntersection, "There are the same nodes.");
196+
}
197+
198+
[Test]
199+
public void GetLastNodeBelowThreshold_NoRepeats([Values(1, 2, 4, 8, 16, 32, 64, 128)] int count)
200+
{
201+
var data = Enumerable.Range(0, count).ToArray();
202+
var tree = new RedBlackTree<int, int>(data, d => d);
203+
204+
for (var i = 0; i < count; i++)
205+
{
206+
var result = tree.GetLastNodeBelowThreshold(i);
207+
if (i == 0)
208+
Assert.IsNull(result, $"Invalid result for {i}.");
209+
else
210+
Assert.AreEqual(i - 1, result.Key, $"Invalid result for {i}.");
211+
}
212+
}
213+
214+
[Test]
215+
public void GetLastNodeBelowThreshold_Repeats()
216+
{
217+
var tree = new RedBlackTree<int, int>(new[] { 1, 1, 2, 2, 2, 3, 4, 4, 4, 5 }, d => d);
218+
219+
var result = tree.GetLastNodeBelowThreshold(1);
220+
Assert.IsNull(result, "Invalid result for 1.");
221+
222+
void Check(int threshold, int expectedResult, int[] expectedPreviousValues)
223+
{
224+
var node = tree.GetLastNodeBelowThreshold(threshold);
225+
var previousValues = EnumerateViaGetPreviousNode(tree, node).ToArray();
226+
Assert.AreEqual(expectedResult, node.Value, $"Invalid result for {threshold}.");
227+
CollectionAssert.AreEqual(
228+
expectedPreviousValues,
229+
previousValues,
230+
$"Invalid previous values list for {threshold}.");
231+
}
232+
233+
Check(2, 1, new[] { 1, 1 });
234+
Check(3, 2, new[] { 2, 2, 2, 1, 1 });
235+
Check(4, 3, new[] { 3, 2, 2, 2, 1, 1 });
236+
Check(5, 4, new[] { 4, 4, 4, 3, 2, 2, 2, 1, 1 });
237+
Check(6, 5, new[] { 5, 4, 4, 4, 3, 2, 2, 2, 1, 1 });
238+
Check(10, 5, new[] { 5, 4, 4, 4, 3, 2, 2, 2, 1, 1 });
239+
}
240+
241+
[Test]
242+
public void GetLastNodeBelowThreshold_InMiddle()
243+
{
244+
var tree = new RedBlackTree<int, int>(new[] { 0, 5500 }, d => d);
245+
246+
var result = tree.GetLastNodeBelowThreshold(700);
247+
}
248+
249+
private static IEnumerable<TValue> EnumerateViaGetNextNode<TKey, TValue>(RedBlackTree<TKey, TValue> tree, RedBlackTreeNode<TKey, TValue> node)
250+
where TKey : IComparable<TKey>
251+
where TValue : IEquatable<TValue>
252+
{
253+
do
254+
{
255+
yield return node.Value;
256+
}
257+
while ((node = tree.GetNextNode(node)) != null);
258+
}
259+
260+
private static IEnumerable<int> EnumerateViaGetPreviousNode(RedBlackTree<int, int> tree, RedBlackTreeNode<int, int> node)
261+
{
262+
do
263+
{
264+
yield return node.Value;
265+
}
266+
while ((node = tree.GetPreviousNode(node)) != null);
267+
}
268+
269+
private static void CheckAscendingOrder(int[] values)
270+
{
271+
for (var i = 0; i < values.Length - 1; i++)
272+
{
273+
Assert.GreaterOrEqual(values[i + 1], values[i], $"Ascending order is broken on index {i}.");
274+
}
275+
}
276+
277+
private static void CheckDescendingOrder(int[] values)
278+
{
279+
for (var i = 0; i < values.Length - 1; i++)
280+
{
281+
Assert.LessOrEqual(values[i + 1], values[i], $"Descending order is broken on index {i}.");
282+
}
283+
}
284+
}
285+
}

DryWetMidi.Tests/Interaction/Chords/ChordsManagingUtilitiesTests.ProcessChords.ChordDetectionSettings.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,8 +518,9 @@ public void ProcessChords_DetectionSettings_EventsCollection_WithoutPredicate_No
518518
action: c =>
519519
{
520520
var note = ((CustomChord)c).Notes.First();
521-
((CustomTimedEvent)note.TimedNoteOnEvent).Time = 10;
522-
((CustomTimedEvent)note.TimedNoteOffEvent).Time = 10;
521+
((CustomTimedEvent)note.GetTimedNoteOnEvent()).Time = 10;
522+
((CustomTimedEvent)note.GetTimedNoteOffEvent()).Time = 10;
523+
note.Time = 10;
523524
},
524525
expectedMidiEvents: new MidiEvent[]
525526
{

0 commit comments

Comments
 (0)