djipco / webmidi

Tame the Web MIDI API. Send and receive MIDI messages with ease. Control instruments with user-friendly functions (playNote, sendPitchBend, etc.). React to MIDI input with simple event listeners (noteon, pitchbend, controlchange, etc.).
Apache License 2.0
1.52k stars 115 forks source link

playNote duration continue to listen after sendAllNotesOff #299

Closed karkovich closed 1 year ago

karkovich commented 1 year ago

Description Playing note for with 2000ms duration. Stop the note manually sendAllNotesOff before the 2000ms( i.e after 1000ms) and Start the note again with the same options (duration === 2000ms) will stop the note after 1000ms (seems like from the previous playNote).

WebMidi.outputs[0].channels[1].playNote("C3", {
            duration: 2000,
            rawAttack: 90,
});

Environment: Specify the environment where you are witnessing the problem:

djipco commented 1 year ago

This is the "normal" behaviour and I can understand the confusion. 😕 Calling sendAllNotesOff() sends a noteoff message to all notes. But it does not prevent scheduled noteoff messages from happening.

When you call playNote() with a duration, the noteoff message is immediately crafted and sent to the MIDI subsystem. Unfortunately for us, the clear() method defined in the Web MIDI API has still not been implemented in Chrome. So, once events are passed off to the MIDI subsystem, they are out of reach.

karkovich commented 1 year ago

First, thanks for you response. Yeah I agree that is the "normal" behaviour. I just wonder if there any way to track/clear them even menually. so, under the hood duration with playNote() is not just an setTimeout, right? does it just some native way to set note duration?

djipco commented 1 year ago

Sorry for the late response. Very busy here. Under the hood, when you call playNote() with a duration, WEBMIDI.js immediately sends the timestamped noteon et noteoff events to be processed by MIDI stack. Once that's done, the scheduled events are out of reach. What you could do is separately send the noteon and subsequent noteoff events. This way, you could decide not to send the noteoff if you so desire.

djipco commented 1 year ago

Since there isn't much else I can do, I will close this issue.