Skip to content

Commit

Permalink
Merge branch 'playback-tempo' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
melanchall committed Feb 13, 2025
2 parents 20e4547 + 48042a2 commit fe3b16f
Show file tree
Hide file tree
Showing 26 changed files with 2,090 additions and 193 deletions.
35 changes: 34 additions & 1 deletion DryWetMidi.Tests/Common/RedBlackTree/RedBlackTreeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using Melanchall.DryWetMidi.Common;
using System.Drawing;
using Melanchall.DryWetMidi.Tests.Multimedia;

namespace Melanchall.DryWetMidi.Tests.Common
{
Expand All @@ -31,6 +30,8 @@ public bool Equals(KeyValue other) =>
public void Enumerate_Empty()
{
var tree = new RedBlackTree<int, int>();
Assert.AreEqual(0, tree.Count, "Invalid initial count.");

var enumerated = tree.ToArray();

CollectionAssert.IsEmpty(enumerated, "Enumerated collection is not empty.");
Expand All @@ -43,6 +44,8 @@ public void Enumerate([Values(0, 1, 2, 3, 4, 5, 10, 100, 1000, 10000)] int count
var data = Enumerable.Range(0, count).Select(_ => random.Next(1000)).ToArray();

var tree = new RedBlackTree<int, int>(data, d => d);
Assert.AreEqual(count, tree.Count, "Invalid initial count.");

var enumerated = tree.ToArray();

CollectionAssert.AreEqual(
Expand All @@ -56,10 +59,13 @@ public void InsertOne([Values(0, 10, 40, -2, 1000, 12, 2, 9, 11)] int value)
{
var data = new[] { 2, 3, 1, 1, 10, 100, 50, 45, 0 };
var tree = new RedBlackTree<int, int>(data, d => d);
Assert.AreEqual(data.Length, tree.Count, "Invalid initial count.");

CheckAscendingOrder(tree.ToArray());

tree.Add(value, value);
Assert.AreEqual(data.Length + 1, tree.Count, "Invalid count after add.");

CheckAscendingOrder(tree.ToArray());
}

Expand All @@ -68,14 +74,17 @@ public void InsertMultiple()
{
var data = new[] { 2, 3, 1, 1, 10, 100, 50, 45, 0 }.ToList();
var tree = new RedBlackTree<int, int>(data, d => d);
Assert.AreEqual(data.Count, tree.Count, "Invalid initial count.");

CheckAscendingOrder(tree.ToArray());

var dataToAdd = new[] { 0, 10, 40, -2, 1000, 12, 2, 9, 11 };
var count = data.Count;

foreach (var d in dataToAdd)
{
tree.Add(d, d);
Assert.AreEqual(++count, tree.Count, $"Invalid count after {d} addition.");
CheckAscendingOrder(tree.ToArray());
}
}
Expand All @@ -85,10 +94,13 @@ public void DeleteOne([Values(500, 100, 2, 4, 6, 9, 10, 700, 701, 702, 45, 44, 4
{
var data = Enumerable.Range(0, 1000).ToList();
var tree = new RedBlackTree<int, int>(data, d => d);
Assert.AreEqual(data.Count, tree.Count, "Invalid initial count.");

CheckAscendingOrder(tree.ToArray());

tree.Delete(tree.GetFirstNode(value));
Assert.AreEqual(data.Count - 1, tree.Count, "Invalid count after deletion.");

CheckAscendingOrder(tree.ToArray());
}

Expand All @@ -97,18 +109,39 @@ public void DeleteMultiple()
{
var data = Enumerable.Range(0, 1000).ToList();
var tree = new RedBlackTree<int, int>(data, d => d);
Assert.AreEqual(data.Count, tree.Count, "Invalid initial count.");

CheckAscendingOrder(tree.ToArray());

var dataToDelete = new[] { 500, 100, 2, 4, 6, 9, 10, 700, 701, 702, 45, 44, 43 };
var count = data.Count;

foreach (var d in dataToDelete)
{
tree.Delete(tree.GetFirstNode(d));
Assert.AreEqual(--count, tree.Count, $"Invalid count after {d} deletion.");

CheckAscendingOrder(tree.ToArray());
}
}

[Test]
public void DeleteNonExisting()
{
var data = Enumerable.Range(0, 1000).ToList();
var tree = new RedBlackTree<int, int>(data, d => d);
Assert.AreEqual(data.Count, tree.Count, "Invalid initial count.");

CheckAscendingOrder(tree.ToArray());

var nodeToDelete = tree.GetFirstNode(500);
tree.Delete(nodeToDelete);
Assert.AreEqual(data.Count - 1, tree.Count, $"Invalid count after first deletion.");

tree.Delete(nodeToDelete);
Assert.AreEqual(data.Count - 1, tree.Count, $"Invalid count after second deletion.");
}

[Test]
public void GetNextNode([Values(1, 2, 4, 8, 16, 32, 64, 128, 10, 100, 1000)] int count)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Melanchall.DryWetMidi.Core;
using Melanchall.DryWetMidi.Interaction;
using NUnit.Framework;
using System;
using System.Collections.Generic;

namespace Melanchall.DryWetMidi.Tests.Interaction
{
[TestFixture]
public sealed partial class TempoMapManagingUtilitiesTests
{
#region Test methods

[Test]
public void ManageTempoMap_EmptyFile_NoException() =>
Assert.DoesNotThrow(() => new MidiFile().ManageTempoMap());

[Test]
public void ManageTempoMap_EmptyTrackChunksCollection_NoException() =>
Assert.DoesNotThrow(() => new List<TrackChunk>().ManageTempoMap(new TicksPerQuarterNoteTimeDivision()));

[Test]
public void ManageTempoMap_EmptyTrackChunksCollection_Exception() =>
Assert.Throws<ArgumentOutOfRangeException>(() => Array.Empty<TrackChunk>().ManageTempoMap(new TicksPerQuarterNoteTimeDivision()));

[Test]
public void ManageTempoMap_EmptyEventsCollectionsCollection_NoException() =>
Assert.DoesNotThrow(() => new List<EventsCollection>().ManageTempoMap(new TicksPerQuarterNoteTimeDivision()));

[Test]
public void ManageTempoMap_EmptyEventsCollectionsCollection_Exception() =>
Assert.Throws<ArgumentOutOfRangeException>(() => Array.Empty<EventsCollection>().ManageTempoMap(new TicksPerQuarterNoteTimeDivision()));

#endregion
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using System.Linq;

namespace Melanchall.DryWetMidi.Tests.Interaction
Expand Down Expand Up @@ -577,6 +578,48 @@ public void ChangeCollection_ChangeAndChangeSame()
Assert.AreEqual(15, changedObject.OldTime, "Invalid old time of changed object.");
}

[Test]
public void ChangeCollection_RemoveAddChangeSame()
{
var objectToChange = new TimedEvent(new TextEvent("C"), 15);

var collection = new ObservableTimedObjectsCollection(new ITimedObject[]
{
new TimedEvent(new TextEvent("B"), 20),
new Note((SevenBitNumber)90, 100, 10),
new TimedEvent(new TextEvent("A"), 5),
objectToChange,
});

var eventsArgs = new List<ObservableTimedObjectsCollectionChangedEventArgs>();
collection.CollectionChanged += (_, e) => eventsArgs.Add(e);

collection.ChangeCollection(() =>
{
collection.Remove(objectToChange);
collection.Add(objectToChange);
collection.ChangeObject(objectToChange, obj => obj.Time = 20);
});

Assert.AreEqual(1, eventsArgs.Count, "Invalid events args count.");

var eventArgs = eventsArgs.Single();

CheckCollectionIsNullOrEmpty(eventArgs.RemovedObjects, "There are removed objects.");
CheckCollectionIsNullOrEmpty(eventArgs.AddedObjects, "There are added objects.");

var changedObjects = eventArgs.ChangedObjects;
CollectionAssert.AreEqual(new[] { objectToChange }, changedObjects.Select(o => o.TimedObject), "Invalid changed objects.");

var changedObject = eventArgs.ChangedObjects.Single();
MidiAsserts.AreEqual(
new TimedEvent(new TextEvent("C"), 20),
changedObject.TimedObject,
"Invalid changed object");
Assert.AreEqual(15, changedObject.OldTime, "Invalid old time of changed object.");

}

#endregion

#region Private methods
Expand Down
2 changes: 1 addition & 1 deletion DryWetMidi.Tests/Interaction/ValueLine/ValueLineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ public void SetValue_NonDefault_AtStart_Default_AtStart(bool checkValueChangesFi
valueChangeTime1: 0,
value2: defaultValue,
valueChangeTime2: 0,
expectedValueChanges: new[] { new ValueChange<string>(0, defaultValue) },
expectedValueChanges: Array.Empty<ValueChange<string>>(),
expectedValueAtStart: defaultValue,
expectedValueBeforeFirstChange: defaultValue,
expectedValueAtFirstChange: defaultValue,
Expand Down
7 changes: 5 additions & 2 deletions DryWetMidi.Tests/Multimedia/Playback/PlaybackTests.Asserts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ private void CheckPlayback(
ICollection<ReceivedEvent> expectedReceivedEvents,
Action<Playback> setupPlayback = null,
Action<Playback> afterStart = null,
int? repeatsCount = null)
int? repeatsCount = null,
Action<Playback> additionalChecks = null)
{
var outputDevice = useOutputDevice
? (IOutputDevice)OutputDevice.GetByName(SendReceiveUtilities.DeviceToTestOnName)
Expand All @@ -60,7 +61,7 @@ private void CheckPlayback(
if (useOutputDevice)
SendReceiveUtilities.WarmUpDevice((OutputDevice)outputDevice);

outputDevice.EventSent += (_, e) => receivedEvents.Add(new ReceivedEvent(e.Event, stopwatch.Elapsed));
outputDevice.EventSent += (_, e) => receivedEvents.Add(new ReceivedEvent(e.Event.Clone(), stopwatch.Elapsed));

using (var playback = createPlayback(outputDevice))
{
Expand Down Expand Up @@ -113,6 +114,8 @@ private void CheckPlayback(
sendReceiveTimeDelta: useOutputDevice
? SendReceiveUtilities.MaximumEventSendReceiveDelay
: TimeSpan.FromMilliseconds(10));

additionalChecks?.Invoke(playback);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ public void EventPlayed_AllEventsTypes()
.Select(type => type == typeof(UnknownMetaEvent)
? new UnknownMetaEvent(0)
: (MidiEvent)Activator.CreateInstance(type, true))
.Select(midiEvent => new EventToSend(midiEvent, TimeSpan.FromMilliseconds(delay)))
.Select(midiEvent =>
{
if (midiEvent is SetTempoEvent)
midiEvent = new SetTempoEvent(500001);

return new EventToSend(midiEvent, TimeSpan.FromMilliseconds(delay));
})
.ToArray();

CheckEventPlayedEvent(
Expand Down
Loading

0 comments on commit fe3b16f

Please sign in to comment.