grame-cncm / faust

Functional programming language for signal processing and sound synthesis
http://faust.grame.fr
Other
2.58k stars 322 forks source link

MIDI NOTE-OFF does not release button #173

Closed jkbd closed 6 years ago

jkbd commented 6 years ago

The following FAUST code example does not behave as I expect:

import("stdfaust.lib");
gate = button("key[midi:keyon 37]");
process = os.osc(440) * gate;

If I compile with faust2jack -midi $FILE and click on the Gtk-Button, there is a MIDI NOTE-OFF sent when I release the button. If I send a MIDI NOTE-ON event to the program, the button locks in down-state and gate holds the value 1. MIDI NOTE-OFF is ignored. Is this the intended behaviour?

faust --version gives Version 2.5.31. I build it on Arch Linux from the AUR faust-git one hour ago.

sletz commented 6 years ago

As explained here: http://faust.grame.fr/news/2016/01/14/controlling-with-midi.html

[midi:keyon key] in a slider or bargraph will register the UI element’s state-variable to be driven by MIDI note-on velocity (an integer between 0 and 127) of the specified key between 0 and 127. When used with a button or checkbox, 1 will be mapped to 127, 0 will be mapped to 0,

So when the button is released a keyon with a velocity of 0 (white is actually the same as a key off) is sent. If you want the same behavior when using en external control, use:

import("stdfaust.lib");
gate = button("key[midi:keyon 37][midi:keyoff 37]");
process = os.osc(440) * gate;
jkbd commented 6 years ago

Thank you for your quick response. I had read the documentation and also had tried your suggestion but it does not work.

Again, let gate = button("key[midi:keyon 37]"); then aseqdump reads: (left mouse button down)

128:0  Note on  0, note 37, velocity 127

(left mouse button up)

128:0  Note off  0, note 37

as expected and documented.

Now gate = button("key[midi:keyon 37][midi:keyoff 37]"); results in: (left mouse button down)

128:0  Note off  0, note 37, velocity 127
128:0  Note on  0, note 37, velocity 127

(left mouse button up)

128:0  Note off  0, note 37, velocity 0
128:0  Note off  0, note 37

This is what I expect from the given documentation but it does not help.

With 1 external MIDI Note on (with velocity v) event sent to the input of the FAUST-generated program (as in the second example), I record at the output:

128:0  Note off  0, note 37, velocity (v-1)
128:0  Note off  0, note 37, velocity 127
128:0  Note on  0, note 37, velocity 127

The corresponding Note off sent on release does not produce output. It will not change the state of the pressed button nor will it change the value of gate. In all of my tests the Note off velocity (v-1) seems to match with the input Note on velocity v, which seems strange to me.

Is this a typo in Controlling with MIDI (marked bold)?

[midi:keyoff key] in a slider or bargraph will register the UI element’s state-variable to be driven by MIDI note-on velocity ...

Shouldn't it read

driven by MIDI note-off velocity

? The same text is in the Faust Quick Reference.

sletz commented 6 years ago

1) doc fixed

2) what are you actually trying to to?

3) The MidiUI code is there if you want to trace, test and debug : https://github.com/grame-cncm/faust/blob/master-dev/architecture/faust/gui/MidiUI.h

jkbd commented 6 years ago

Thank you! I try to build a physically informed tonewheel organ. Creating polyphonic instruments is not a good fit, because

I'm am looking for authenticity and not for computational performance. It's just for fun and initially I did not plan to dive into the C++ code and write a new FAUST-architecture file.

sletz commented 6 years ago

Thegate = button("key[midi:keyon 37][midi:keyoff 37]"); kind of code works here on OS X using faust2caqt and MidiKeys (http://www.manyetas.com/creed/midikeys.html) as a virtual keyboard.

I'm suspecting a keyOn with velocity = 0 is actually a keyOff issue. I've just fixed and possible issue here: https://github.com/grame-cncm/faust/commit/b23591d9838b7d4baa67af47385d8bff01b91fa1

Can you check again with this correction?

jkbd commented 6 years ago

I tested the new version

$ pacman -Qi faust-git | grep Version
Version                  : 2:2.5.31.r9677.b23591d98-1

with a virtual JACK MIDI keyboard (Cadence-XY Controller) and it does work! I checked a hardware keyboard and it works. But with a Akai LPD8 controller it does not. It produces MIDI NOTE OFF with velocity 127 (as documented above -- I just overlooked that fact). It seems that this is valid for a MIDI specification compliant device and only few devices use this feature to denote e.g. the release time.

I'm not sure about your code change. NOTE ON with velocity of 0 is valid. I think it would be good to have the corresponding NOTE OFF result in 0 independent of its velocity.

Thank you very much for your help so far.

sletz commented 6 years ago

OK. I did several things:

import("stdfaust.lib");
gate = button("key[midi:key 37]");
process = os.osc(440) * gate;

and it should work as expected. To be tested in https://github.com/grame-cncm/faust/commit/b23591d9838b7d4baa67af47385d8bff01b91fa1

Please report if it works for your with the different keyboards you are using.

jkbd commented 6 years ago

I like your solution to add a new metadata key.

import("stdfaust.lib");
gate = button("key[midi:key 69]"); // A4
process = os.osc(440) * gate;

again build and started with

$ faust2jack -midi example.dsp
$ ./example
  1. If I press the button audio output is correct. No MIDI is send from MIDI output.

  2. If I send MIDI Note on, channel 0, note 69, velocity 100 nothing happens. Same with Note off, channel 0, note 69, velocity 0. Nothing means no button-state change, no audio and no midi output.

Version is 0cff1b9c406c2d29df24456f7b44d841130ded7e. I tripple-checked everything.

Are you sure your changes are online in the master-dev branch? In my local copy your change has not been reverted after a git pull.

sletz commented 6 years ago

Sorry commit SHAKey was wrong: get the latest here: https://github.com/grame-cncm/faust/commit/4ab6869499be86b67b0c29df39f02ae007dd4111

jkbd commented 6 years ago

No problem! Testing the example as given above:

  1. Button sends correct MIDI on mouse down and release.

  2. Sending Note on, channel 0, note 69, velocity 100 results in MIDI event output and correct audio output. The velocity of the sent through output event is fixed at 127. This might be intended.

  3. MIDI Note off, channel 0, note 69, velocity 0 as well as Note off, channel 0, note 69, velocity 127 result in gate == 0.

  4. The button does not change it's visible state with MIDI interaction.

This works for me. Thank you very much! I would be happy to help you with testing 4. until it is complete from a usability point-of-view. Otherwise you could close this issue.

sletz commented 6 years ago

4 is a limitation of the current GTK based GUI. You may use the QT based tools like that correctly change the button state:

faust2jaqt -midi example.dsp