From ccaa5919af98db7b5083c1efb95e3b5c8d3d5f09 Mon Sep 17 00:00:00 2001 From: BeratYilmaz-dev Date: Mon, 7 Sep 2026 14:52:55 +0300 Subject: [PATCH] Reset pitch bend to zero at note end --- basic_pitch/note_creation.py | 4 +++- tests/test_note_creation.py | 20 +++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/basic_pitch/note_creation.py b/basic_pitch/note_creation.py index 753f5a18..46dbcbf0 100644 --- a/basic_pitch/note_creation.py +++ b/basic_pitch/note_creation.py @@ -256,7 +256,7 @@ def note_events_to_midi( instrument.notes.append(note) if not pitch_bend: continue - pitch_bend_times = np.linspace(start_time, end_time, len(pitch_bend)) + pitch_bend_times = np.linspace(start_time, end_time, len(pitch_bend), endpoint=False) pitch_bend_midi_ticks = np.round(np.array(pitch_bend) * PITCH_BEND_SCALE / CONTOURS_BINS_PER_SEMITONE).astype( int ) @@ -266,6 +266,8 @@ def note_events_to_midi( pitch_bend_midi_ticks[pitch_bend_midi_ticks < -N_PITCH_BEND_TICKS] = -N_PITCH_BEND_TICKS for pb_time, pb_midi in zip(pitch_bend_times, pitch_bend_midi_ticks): instrument.pitch_bends.append(pretty_midi.PitchBend(pb_midi, pb_time)) + if pitch_bend_midi_ticks[-1] != 0: + instrument.pitch_bends.append(pretty_midi.PitchBend(0, end_time)) mid.instruments.extend(instruments.values()) return mid diff --git a/tests/test_note_creation.py b/tests/test_note_creation.py index 630bec11..d3033dc1 100644 --- a/tests/test_note_creation.py +++ b/tests/test_note_creation.py @@ -15,7 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from basic_pitch.note_creation import drop_overlapping_pitch_bends +from basic_pitch.note_creation import drop_overlapping_pitch_bends, note_events_to_midi def test_drop_overlapping_pitch_bends() -> None: @@ -48,3 +48,21 @@ def test_drop_overlapping_pitch_bends() -> None: ] result = drop_overlapping_pitch_bends(note_events_with_pitch_bends) assert sorted(result) == sorted(expected) + + +def test_note_events_to_midi_pitch_bend_reset() -> None: + note_events = [ + (0.0, 1.0, 60, 1.0, [0, 1]), + (2.0, 3.0, 62, 1.0, None), + ] + mid = note_events_to_midi(note_events) + pitch_bends = mid.instruments[0].pitch_bends + assert len(pitch_bends) > 0 + assert pitch_bends[-1].pitch == 0 + assert pitch_bends[-1].time == 1.0 + + mid_multi = note_events_to_midi(note_events, multiple_pitch_bends=True) + inst_60 = [inst for inst in mid_multi.instruments if any(n.pitch == 60 for n in inst.notes)][0] + assert len(inst_60.pitch_bends) > 0 + assert inst_60.pitch_bends[-1].pitch == 0 + assert inst_60.pitch_bends[-1].time == 1.0