From 988e8a3294c04be288247f5d96ab8e4b92792f25 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Wed, 27 Jun 2018 18:51:43 -0700 Subject: [PATCH 01/22] enforce strictly increasing values in old_time and new_time --- pretty_midi/pretty_midi.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index bf21759..376335d 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1019,6 +1019,24 @@ def adjust_times(self, original_times, new_times): # Get original downbeat locations (we will use them to determine where # to put the first time signature change) original_downbeats = self.get_downbeats() + + # Test original_times and new_times for monotonicity + # if they are not monotonic, a warning should be given + # and they should be made monotonic with np.maximum.accumulate + def _strictly_increasing(L): + if all(x Date: Thu, 28 Jun 2018 14:37:58 -0700 Subject: [PATCH 02/22] update monotonicity check; move warnings out of fxn --- pretty_midi/pretty_midi.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index 376335d..b00b9c4 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1020,22 +1020,23 @@ def adjust_times(self, original_times, new_times): # to put the first time signature change) original_downbeats = self.get_downbeats() - # Test original_times and new_times for monotonicity - # if they are not monotonic, a warning should be given - # and they should be made monotonic with np.maximum.accumulate - def _strictly_increasing(L): - if all(x 0): + warnings.warn( + "original_times does not monotonically increase, " + "enforcing monotonically increasing event times", + RuntimeWarning) + original_times = np.maximum.accumulate(original_times) + + if not np.all(np.diff(new_times) > 0): + warnings.warn( + "new_times does not monotonically increase, " + "enforcing monotonically increasing event times", + RuntimeWarning) + new_times = np.maximum.accumulate(new_times) # Only include notes within start/end time of the provided times for instrument in self.instruments: From 0e7e5b9a5d4733109512250c690d72abad39b9bb Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 16:05:02 -0700 Subject: [PATCH 03/22] strictly increase original_times, monotonic incr new_times --- pretty_midi/pretty_midi.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index b00b9c4..900e2ad 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1019,25 +1019,28 @@ def adjust_times(self, original_times, new_times): # Get original downbeat locations (we will use them to determine where # to put the first time signature change) original_downbeats = self.get_downbeats() - + # Original_times and new_times should strictly increase. # If they don't, a warning is given and are made monotonic # with np.maximum.accumulate - + if not np.all(np.diff(original_times) > 0): warnings.warn( - "original_times does not monotonically increase, " - "enforcing monotonically increasing event times", + 'original_times must be strictly increasing; ' + 'automatically enforcing this.', RuntimeWarning) original_times = np.maximum.accumulate(original_times) + original_times, unique_idx = np.unique(original_times, + return_index=True) + new_times = original_times[unique_idx] - if not np.all(np.diff(new_times) > 0): + if not np.all(np.diff(new_times) >= 0): warnings.warn( - "new_times does not monotonically increase, " - "enforcing monotonically increasing event times", + 'new_times must be monotonic; ' + 'automatically enforcing this.', RuntimeWarning) new_times = np.maximum.accumulate(new_times) - + # Only include notes within start/end time of the provided times for instrument in self.instruments: instrument.notes = [copy.deepcopy(note) From ac9936b3b04f501c04f0614c2742d6ce6cb6c102 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 16:41:43 -0700 Subject: [PATCH 04/22] remove trailing whitespace for pep8 --- pretty_midi/pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index 900e2ad..a721055 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1030,7 +1030,7 @@ def adjust_times(self, original_times, new_times): 'automatically enforcing this.', RuntimeWarning) original_times = np.maximum.accumulate(original_times) - original_times, unique_idx = np.unique(original_times, + original_times, unique_idx = np.unique(original_times, return_index=True) new_times = original_times[unique_idx] From 2dee3db4c0268a12a311c0066ba8699c7ce67d34 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 16:43:42 -0700 Subject: [PATCH 05/22] update new_times indices if original_times fails check --- pretty_midi/pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index a721055..148d6c9 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1032,7 +1032,7 @@ def adjust_times(self, original_times, new_times): original_times = np.maximum.accumulate(original_times) original_times, unique_idx = np.unique(original_times, return_index=True) - new_times = original_times[unique_idx] + new_times = new_times[unique_idx] if not np.all(np.diff(new_times) >= 0): warnings.warn( From c0c7474939ea62460f988433d0fbe3668129ebc3 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 18:05:49 -0700 Subject: [PATCH 06/22] use np.unique to check and enforce original_time strictly increasing --- pretty_midi/pretty_midi.py | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index 148d6c9..f4d49ec 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1019,28 +1019,19 @@ def adjust_times(self, original_times, new_times): # Get original downbeat locations (we will use them to determine where # to put the first time signature change) original_downbeats = self.get_downbeats() - - # Original_times and new_times should strictly increase. - # If they don't, a warning is given and are made monotonic - # with np.maximum.accumulate - - if not np.all(np.diff(original_times) > 0): - warnings.warn( - 'original_times must be strictly increasing; ' - 'automatically enforcing this.', - RuntimeWarning) - original_times = np.maximum.accumulate(original_times) - original_times, unique_idx = np.unique(original_times, - return_index=True) - new_times = new_times[unique_idx] - - if not np.all(np.diff(new_times) >= 0): - warnings.warn( - 'new_times must be monotonic; ' - 'automatically enforcing this.', - RuntimeWarning) + # original_times should increase strictly and new_times monotonically. + # If they don't, give warning and enforce increasingness. + original_size = original_times.size + original_times, unique_idx = np.unique(original_times, return_index=True) + if ((unique_idx.size != original_size) or + unique_idx != np.arange(unique_idx.size)): + warnings.warn('original_times must be strictly increasing; ' + 'automatically enforcing this.') + new_times = np.array(new_times)[unique_idx] + if not np.all(np.diff(new_times) > 0): + warnings.warn('new_times must be monotonic; ' + 'automatically enforcing this.') new_times = np.maximum.accumulate(new_times) - # Only include notes within start/end time of the provided times for instrument in self.instruments: instrument.notes = [copy.deepcopy(note) From 6e8d88d7a3335f40f4c0aa693a7fd28e34ebb57d Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 19:12:53 -0700 Subject: [PATCH 07/22] fix pep8 formatting issues. --- pretty_midi/pretty_midi.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index f4d49ec..b63b43f 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1022,12 +1022,13 @@ def adjust_times(self, original_times, new_times): # original_times should increase strictly and new_times monotonically. # If they don't, give warning and enforce increasingness. original_size = original_times.size - original_times, unique_idx = np.unique(original_times, return_index=True) - if ((unique_idx.size != original_size) or - unique_idx != np.arange(unique_idx.size)): + original_times, unique_idx = np.unique(original_times, + return_index=True) + if ((unique_idx.size != original_size) or + unique_idx != np.arange(unique_idx.size)): warnings.warn('original_times must be strictly increasing; ' 'automatically enforcing this.') - new_times = np.array(new_times)[unique_idx] + new_times = np.array(new_times)[unique_idx] if not np.all(np.diff(new_times) > 0): warnings.warn('new_times must be monotonic; ' 'automatically enforcing this.') From c524fa152a6a61049de9b6b0a15c7b3c16b02896 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 19:20:14 -0700 Subject: [PATCH 08/22] fix pep8 formatting issues. --- pretty_midi/pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index b63b43f..1f018ee 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1025,7 +1025,7 @@ def adjust_times(self, original_times, new_times): original_times, unique_idx = np.unique(original_times, return_index=True) if ((unique_idx.size != original_size) or - unique_idx != np.arange(unique_idx.size)): + unique_idx != np.arange(unique_idx.size)): warnings.warn('original_times must be strictly increasing; ' 'automatically enforcing this.') new_times = np.array(new_times)[unique_idx] From 87b057643bd678977578c021169706e41ab19cce Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 19:38:38 -0700 Subject: [PATCH 09/22] fix pep8 formatting issues. --- pretty_midi/pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index 1f018ee..947d1d7 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1025,7 +1025,7 @@ def adjust_times(self, original_times, new_times): original_times, unique_idx = np.unique(original_times, return_index=True) if ((unique_idx.size != original_size) or - unique_idx != np.arange(unique_idx.size)): + unique_idx != np.arange(unique_idx.size)): warnings.warn('original_times must be strictly increasing; ' 'automatically enforcing this.') new_times = np.array(new_times)[unique_idx] From 9c8e28a65e184f3dfc6e212402e7192999228860 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 19:51:17 -0700 Subject: [PATCH 10/22] fix pep8 formatting issues. --- pretty_midi/pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index 947d1d7..9cc5ffc 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1021,7 +1021,7 @@ def adjust_times(self, original_times, new_times): original_downbeats = self.get_downbeats() # original_times should increase strictly and new_times monotonically. # If they don't, give warning and enforce increasingness. - original_size = original_times.size + original_size = len(original_times) original_times, unique_idx = np.unique(original_times, return_index=True) if ((unique_idx.size != original_size) or From ca3a2264563932f78966fe59cabfe88ff23f6acf Mon Sep 17 00:00:00 2001 From: areeves87 Date: Thu, 28 Jun 2018 19:56:25 -0700 Subject: [PATCH 11/22] fix pep8 formatting issues. --- pretty_midi/pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index 9cc5ffc..45b7316 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1025,7 +1025,7 @@ def adjust_times(self, original_times, new_times): original_times, unique_idx = np.unique(original_times, return_index=True) if ((unique_idx.size != original_size) or - unique_idx != np.arange(unique_idx.size)): + any(unique_idx != np.arange(unique_idx.size))): warnings.warn('original_times must be strictly increasing; ' 'automatically enforcing this.') new_times = np.array(new_times)[unique_idx] From 69ad544904ca612accaadd6372c460374ffeb91d Mon Sep 17 00:00:00 2001 From: areeves87 Date: Fri, 29 Jun 2018 11:07:43 -0700 Subject: [PATCH 12/22] convert new_times to array before subsetting with unique_idx --- pretty_midi/pretty_midi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index 45b7316..d175697 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1019,8 +1019,8 @@ def adjust_times(self, original_times, new_times): # Get original downbeat locations (we will use them to determine where # to put the first time signature change) original_downbeats = self.get_downbeats() - # original_times should increase strictly and new_times monotonically. - # If they don't, give warning and enforce increasingness. + # Force strict increase in original_times and monotonic in new_times. + # While enforcing, give warning. original_size = len(original_times) original_times, unique_idx = np.unique(original_times, return_index=True) @@ -1028,7 +1028,7 @@ def adjust_times(self, original_times, new_times): any(unique_idx != np.arange(unique_idx.size))): warnings.warn('original_times must be strictly increasing; ' 'automatically enforcing this.') - new_times = np.array(new_times)[unique_idx] + new_times = np.asarray(new_times)[unique_idx] if not np.all(np.diff(new_times) > 0): warnings.warn('new_times must be monotonic; ' 'automatically enforcing this.') From 21af8940876990026dec5cf3fc8c7a91144c9082 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Fri, 29 Jun 2018 14:26:50 -0700 Subject: [PATCH 13/22] so that we test adjust_times with appropriate event times --- tests/test_pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index 36ebc72..aefd141 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -162,7 +162,7 @@ def simple(): assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) pm = simple() - pm.adjust_times([0, 5, 5, 10], [5, 10, 12, 17]) + pm.adjust_times([0, 5, 5, 10], [5, 12, 13, 17]) # Original times [1, 2, 3, 4, 5, 6, 7, 8, 9] expected_starts = [6, 7, 8, 9, 12, 13, 14, 15, 16] assert np.allclose( From 445f9ecea0a6605210d87284431a09a2ce072079 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Fri, 29 Jun 2018 16:23:18 -0700 Subject: [PATCH 14/22] so that test_adjust_times() tests the correct values --- tests/test_pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index aefd141..79112e7 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -164,7 +164,7 @@ def simple(): pm = simple() pm.adjust_times([0, 5, 5, 10], [5, 12, 13, 17]) # Original times [1, 2, 3, 4, 5, 6, 7, 8, 9] - expected_starts = [6, 7, 8, 9, 12, 13, 14, 15, 16] + expected_starts = [6.4, 7.8, 9.2, 10.6, 12.0, 13.0, 14.0, 15.0, 16.0] assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) From 80eb650b0fd56ff207fd8c7f834fe4c0e105ed22 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Mon, 2 Jul 2018 13:42:36 -0700 Subject: [PATCH 15/22] update tests for adjust_times --- pretty_midi/pretty_midi.py | 2 +- tests/test_pretty_midi.py | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index d175697..fba8d99 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1029,7 +1029,7 @@ def adjust_times(self, original_times, new_times): warnings.warn('original_times must be strictly increasing; ' 'automatically enforcing this.') new_times = np.asarray(new_times)[unique_idx] - if not np.all(np.diff(new_times) > 0): + if not np.all(np.diff(new_times) >= 0): warnings.warn('new_times must be monotonic; ' 'automatically enforcing this.') new_times = np.maximum.accumulate(new_times) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index 79112e7..9b645b7 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -162,9 +162,9 @@ def simple(): assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) pm = simple() - pm.adjust_times([0, 5, 5, 10], [5, 12, 13, 17]) + pm.adjust_times([2, 7, 7, 12], [7, 12, 13, 17]) # Original times [1, 2, 3, 4, 5, 6, 7, 8, 9] - expected_starts = [6.4, 7.8, 9.2, 10.6, 12.0, 13.0, 14.0, 15.0, 16.0] + expected_starts = [7, 8, 9, 10, 11, 12, 13, 14] assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) @@ -233,11 +233,9 @@ def simple(): assert np.allclose(expected_tempi, tempi, rtol=.002) # Test that all other events were interpolated as expected - note_starts = [5., 5 + 1/1.1, 7 + .9/(2/1.5), 7 + 1.9/(2/1.5), 8.5 + .5, - 8.5 + 1.5] - note_ends = [5 + .5/1.1, 7 + .4/(2/1.5), 7 + 1.4/(2/1.5), 8.5, 9 + .5, - 10 + .5] - note_pitches = [101, 102, 103, 104, 107, 108, 109] + note_starts = [5.0, 5.909090909090909, 7.125, 8.375, 9.0, 10.0] + note_ends = [5.454545454545454, 6.5, 7.75, 8.5, 9.5, 10.5] + note_pitches = [101, 102, 103, 104, 107, 108] for note, s, e, p in zip(pm.instruments[0].notes, note_starts, note_ends, note_pitches): assert note.start == s From d2628d3beea1bfc302ebddc1de4d8632cf8f12fa Mon Sep 17 00:00:00 2001 From: areeves87 Date: Mon, 2 Jul 2018 13:48:25 -0700 Subject: [PATCH 16/22] comment out some tests in adjust_times --- tests/test_pretty_midi.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index 9b645b7..3267297 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -259,19 +259,19 @@ def simple(): # The first time signature change will be placed at the first interpolated # downbeat location - so, start by computing the location of the first # downbeat after the start of original_times, then interpolate it - first_downbeat_after = .1 + 2*3*60./100. - first_ts_time = 7 + (first_downbeat_after - 3.1)/(2/1.5) - ts_times = [first_ts_time, 8.5, 8.5] - ts_numerators = [3, 4, 6] - for ts, t, n in zip(pm.time_signature_changes, ts_times, ts_numerators): - assert ts.time == t - assert ts.numerator == n - - ks_times = [5., 8.5, 8.5] - ks_keys = [1, 2, 3] - for ks, t, k in zip(pm.key_signature_changes, ks_times, ks_keys): - assert ks.time == t - assert ks.key_number == k +# first_downbeat_after = .1 + 2*3*60./100. +# first_ts_time = 7 + (first_downbeat_after - 3.1)/(2/1.5) +# ts_times = [first_ts_time, 8.5, 8.5] +# ts_numerators = [3, 4, 6] +# for ts, t, n in zip(pm.time_signature_changes, ts_times, ts_numerators): +# assert ts.time == t +# assert ts.numerator == n +# +# ks_times = [5., 8.5, 8.5] +# ks_keys = [1, 2, 3] +# for ks, t, k in zip(pm.key_signature_changes, ks_times, ks_keys): +# assert ks.time == t +# assert ks.key_number == k def test_properly_order_overlapping_notes(): From 27946a5b8058cda07c20ebc7e0ffcec1a2969890 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Tue, 3 Jul 2018 10:19:51 -0700 Subject: [PATCH 17/22] PrettyMIDI.adjust_times enforces strict increase in original_times and monotonic increase in new_times --- tests/test_pretty_midi.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index 3267297..5ab7fc3 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -162,9 +162,9 @@ def simple(): assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) pm = simple() - pm.adjust_times([2, 7, 7, 12], [7, 12, 13, 17]) + pm.adjust_times([0, 5, 5, 10], [7, 12, 13, 17]) # Original times [1, 2, 3, 4, 5, 6, 7, 8, 9] - expected_starts = [7, 8, 9, 10, 11, 12, 13, 14] + expected_starts = [8, 9, 10, 11, 12, 13, 14, 15, 16] assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) @@ -266,12 +266,12 @@ def simple(): # for ts, t, n in zip(pm.time_signature_changes, ts_times, ts_numerators): # assert ts.time == t # assert ts.numerator == n -# -# ks_times = [5., 8.5, 8.5] -# ks_keys = [1, 2, 3] -# for ks, t, k in zip(pm.key_signature_changes, ks_times, ks_keys): -# assert ks.time == t -# assert ks.key_number == k + + ks_times = [5., 8.5, 8.5] + ks_keys = [1, 2, 3] + for ks, t, k in zip(pm.key_signature_changes, ks_times, ks_keys): + assert ks.time == t + assert ks.key_number == k def test_properly_order_overlapping_notes(): From 937e7ac2884ba18d859ff240023ca93d0ed04200 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Tue, 3 Jul 2018 12:19:23 -0700 Subject: [PATCH 18/22] prepare to squash commits --- pretty_midi/pretty_midi.py | 14 ++++++++++++++ tests/test_pretty_midi.py | 12 +++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pretty_midi/pretty_midi.py b/pretty_midi/pretty_midi.py index bf21759..fba8d99 100644 --- a/pretty_midi/pretty_midi.py +++ b/pretty_midi/pretty_midi.py @@ -1019,6 +1019,20 @@ def adjust_times(self, original_times, new_times): # Get original downbeat locations (we will use them to determine where # to put the first time signature change) original_downbeats = self.get_downbeats() + # Force strict increase in original_times and monotonic in new_times. + # While enforcing, give warning. + original_size = len(original_times) + original_times, unique_idx = np.unique(original_times, + return_index=True) + if ((unique_idx.size != original_size) or + any(unique_idx != np.arange(unique_idx.size))): + warnings.warn('original_times must be strictly increasing; ' + 'automatically enforcing this.') + new_times = np.asarray(new_times)[unique_idx] + if not np.all(np.diff(new_times) >= 0): + warnings.warn('new_times must be monotonic; ' + 'automatically enforcing this.') + new_times = np.maximum.accumulate(new_times) # Only include notes within start/end time of the provided times for instrument in self.instruments: instrument.notes = [copy.deepcopy(note) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index 36ebc72..06db9b6 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -162,9 +162,9 @@ def simple(): assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) pm = simple() - pm.adjust_times([0, 5, 5, 10], [5, 10, 12, 17]) + pm.adjust_times([0, 5, 5, 10], [7, 12, 13, 17]) # Original times [1, 2, 3, 4, 5, 6, 7, 8, 9] - expected_starts = [6, 7, 8, 9, 12, 13, 14, 15, 16] + expected_starts = [8, 9, 10, 11, 12, 13, 14, 15, 16] assert np.allclose( [n.start for n in pm.instruments[0].notes], expected_starts) @@ -233,11 +233,9 @@ def simple(): assert np.allclose(expected_tempi, tempi, rtol=.002) # Test that all other events were interpolated as expected - note_starts = [5., 5 + 1/1.1, 7 + .9/(2/1.5), 7 + 1.9/(2/1.5), 8.5 + .5, - 8.5 + 1.5] - note_ends = [5 + .5/1.1, 7 + .4/(2/1.5), 7 + 1.4/(2/1.5), 8.5, 9 + .5, - 10 + .5] - note_pitches = [101, 102, 103, 104, 107, 108, 109] + note_starts = [5.0, 5.909090909090909, 7.125, 8.375, 9.0, 10.0] + note_ends = [5.454545454545454, 6.5, 7.75, 8.5, 9.5, 10.5] + note_pitches = [101, 102, 103, 104, 107, 108] for note, s, e, p in zip(pm.instruments[0].notes, note_starts, note_ends, note_pitches): assert note.start == s From 4bf7dd970d2363aa91fee74e20d8e012fb7660d1 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Tue, 3 Jul 2018 21:02:04 -0700 Subject: [PATCH 19/22] passes all tests --- tests/test_pretty_midi.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index 5ab7fc3..0e2b288 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -213,7 +213,7 @@ def simple(): # Original tempo change times: [0, 6, 8.1, 8.3, 9.3] # Plus tempo changes at each of new_times which are not collapsed # Plus tempo change at 0s by default - expected_times = [0., 5., 6., 8.5, + expected_times = [0., 5., 6, 8.5, 8.5 + (6 - 5.1)*(11 - 8.5)/(10 - 5.1), 8.5 + (8.1 - 5.1)*(11 - 8.5)/(10 - 5.1), 8.5 + (8.3 - 5.1)*(11 - 8.5)/(10 - 5.1), @@ -233,8 +233,18 @@ def simple(): assert np.allclose(expected_tempi, tempi, rtol=.002) # Test that all other events were interpolated as expected - note_starts = [5.0, 5.909090909090909, 7.125, 8.375, 9.0, 10.0] - note_ends = [5.454545454545454, 6.5, 7.75, 8.5, 9.5, 10.5] + note_starts = [5.0, + 5 + 1/1.1, + 6 + .9/(2/2.5), + 6 + 1.9/(2/2.5), + 8.5 + .5, + 8.5 + 1.5] + note_ends = [5 + .5/1.1, + 6 + .4/(2/2.5), + 6 + 1.4/(2/2.5), + 8.5, + 8.5 + 1., + 10 + .5] note_pitches = [101, 102, 103, 104, 107, 108] for note, s, e, p in zip(pm.instruments[0].notes, note_starts, note_ends, note_pitches): @@ -259,13 +269,13 @@ def simple(): # The first time signature change will be placed at the first interpolated # downbeat location - so, start by computing the location of the first # downbeat after the start of original_times, then interpolate it -# first_downbeat_after = .1 + 2*3*60./100. -# first_ts_time = 7 + (first_downbeat_after - 3.1)/(2/1.5) -# ts_times = [first_ts_time, 8.5, 8.5] -# ts_numerators = [3, 4, 6] -# for ts, t, n in zip(pm.time_signature_changes, ts_times, ts_numerators): -# assert ts.time == t -# assert ts.numerator == n + first_downbeat_after = .1 + 2*3*60./100. + first_ts_time = 6. + (first_downbeat_after - 3.1)/(2./2.5) + ts_times = [first_ts_time, 8.5, 8.5] + ts_numerators = [3, 4, 6] + for ts, t, n in zip(pm.time_signature_changes, ts_times, ts_numerators): + assert np.allclose(ts.time, t) + assert ts.numerator == n ks_times = [5., 8.5, 8.5] ks_keys = [1, 2, 3] From 24f584b4e0272c8f5118c2b50ca513c4c4800a58 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Tue, 3 Jul 2018 21:14:03 -0700 Subject: [PATCH 20/22] passes all tests and pep8 --- tests/test_pretty_midi.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index 0e2b288..d38d2e2 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -233,16 +233,16 @@ def simple(): assert np.allclose(expected_tempi, tempi, rtol=.002) # Test that all other events were interpolated as expected - note_starts = [5.0, - 5 + 1/1.1, - 6 + .9/(2/2.5), - 6 + 1.9/(2/2.5), + note_starts = [5.0, + 5 + 1/1.1, + 6 + .9/(2/2.5), + 6 + 1.9/(2/2.5), 8.5 + .5, 8.5 + 1.5] - note_ends = [5 + .5/1.1, - 6 + .4/(2/2.5), - 6 + 1.4/(2/2.5), - 8.5, + note_ends = [5 + .5/1.1, + 6 + .4/(2/2.5), + 6 + 1.4/(2/2.5), + 8.5, 8.5 + 1., 10 + .5] note_pitches = [101, 102, 103, 104, 107, 108] From f471ebda062f0143b5822a5335552f6e173b6ea2 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Tue, 3 Jul 2018 21:27:37 -0700 Subject: [PATCH 21/22] tolerate floating point error in time signature calculation --- tests/test_pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index d38d2e2..db44c30 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -274,7 +274,7 @@ def simple(): ts_times = [first_ts_time, 8.5, 8.5] ts_numerators = [3, 4, 6] for ts, t, n in zip(pm.time_signature_changes, ts_times, ts_numerators): - assert np.allclose(ts.time, t) + assert np.isclose(ts.time, t) assert ts.numerator == n ks_times = [5., 8.5, 8.5] From a20c35848178d42f134842c3fe2cb64cb36bd622 Mon Sep 17 00:00:00 2001 From: areeves87 Date: Sat, 7 Jul 2018 19:13:48 -0700 Subject: [PATCH 22/22] maintain consistent decimal usage --- tests/test_pretty_midi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_pretty_midi.py b/tests/test_pretty_midi.py index db44c30..64fdaa7 100644 --- a/tests/test_pretty_midi.py +++ b/tests/test_pretty_midi.py @@ -213,7 +213,7 @@ def simple(): # Original tempo change times: [0, 6, 8.1, 8.3, 9.3] # Plus tempo changes at each of new_times which are not collapsed # Plus tempo change at 0s by default - expected_times = [0., 5., 6, 8.5, + expected_times = [0., 5., 6., 8.5, 8.5 + (6 - 5.1)*(11 - 8.5)/(10 - 5.1), 8.5 + (8.1 - 5.1)*(11 - 8.5)/(10 - 5.1), 8.5 + (8.3 - 5.1)*(11 - 8.5)/(10 - 5.1),