Skip to content

Commit

Permalink
Support on-the-fly tempo changes in Playback (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
melanchall committed Feb 6, 2025
1 parent af3cb6b commit 44559f4
Showing 1 changed file with 46 additions and 7 deletions.
53 changes: 46 additions & 7 deletions DryWetMidi/Multimedia/Playback/Playback.DataManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ private void OnObservableTimedObjectsCollectionChanged(object sender, Observable
}
}

// TODO: optimize (see below for add, need to think about remove)
if (maxTime > _duration)
{
_duration = maxTime;
Expand Down Expand Up @@ -190,6 +189,10 @@ private void RemoveTimedObject(ITimedObject timedObject, long oldTime)

RemoveTrackedData(playbackEvent.Event, oldTime);
}

TryRemoveSetTempoEvent(
timedEvent,
oldTime);
}

private void InitializePlaybackEvents(IEnumerable<ITimedObject> timedObjects, TempoMap tempoMap)
Expand Down Expand Up @@ -282,6 +285,29 @@ private NoteId GetNoteId(NoteEvent noteEvent)
return new NoteId(noteEvent.Channel, noteEvent.NoteNumber);
}

private void TryRemoveSetTempoEvent(
TimedEvent timedEvent,
long oldTime)
{
if (timedEvent == null)
return;

var setTempoEvent = timedEvent.Event as SetTempoEvent;
if (setTempoEvent == null)
return;

var valuesChanges = TempoMap.TempoLine.ToArray();
var valueChange = valuesChanges.FirstOrDefault(v => v.Time == oldTime);
if (valueChange == null)
return;


TempoMap.TempoLine.DeleteValues(oldTime, oldTime);

var oldTempo = valueChange.Value;
var newTempo = TempoMap.TempoLine.GetValueAtTime(oldTime);
}

private void PrepareSetTempoEventAdding(
TimedEvent timedEvent,
out TimeSpan? nextTempoTime,
Expand Down Expand Up @@ -359,8 +385,26 @@ private bool TryAddSetTempoEvent(
? _playbackEvents.GetLastNodeBelowThreshold(nextTempoTime.Value)
: null;

//
ScaleTimesAfterTempoChange(
oldTempo,
newTempo,
tempoChangeTime,
nextTempoTime,
firstNodeAfterTempoChange,
nodeBeforeNextTempo);

TempoMap.TempoLine.SetValue(timedEvent.Time, newTempo);
return true;
}

private void ScaleTimesAfterTempoChange(
Tempo oldTempo,
Tempo newTempo,
TimeSpan tempoChangeTime,
TimeSpan? nextTempoTime,
RedBlackTreeNode<TimeSpan, PlaybackEvent> firstNodeAfterTempoChange,
RedBlackTreeNode<TimeSpan, PlaybackEvent> nodeBeforeNextTempo)
{
var scaleFactor = oldTempo.MicrosecondsPerQuarterNote / (double)newTempo.MicrosecondsPerQuarterNote;

var shift = TimeSpan.Zero;
Expand Down Expand Up @@ -399,11 +443,6 @@ private bool TryAddSetTempoEvent(

_clock.SetCurrentTime(currentTime);
}

//

TempoMap.TempoLine.SetValue(timedEvent.Time, newTempo);
return true;
}

private bool TryAddNoteEvent(
Expand Down

0 comments on commit 44559f4

Please sign in to comment.