Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FR] Add support for channel pressure (monophonic aftertouch) #7

Closed
SpotlightKid opened this issue Nov 29, 2019 · 14 comments
Closed

[FR] Add support for channel pressure (monophonic aftertouch) #7

SpotlightKid opened this issue Nov 29, 2019 · 14 comments
Assignees
Labels
new feature Feature additions and requests

Comments

@SpotlightKid
Copy link

Aka mono(phonic) aftertouch.

Relevant opcodes:

(Does SFZ not allow channel aftertouch to be mapped to filter resonance?)

NB: the sfizz.h header currently lists a function ambiguously named sfizz_send_aftertouch. I suggest naming this sfizz_send_channel_pressure or at least adding this as an alias, so there is no confusion that this is about handling channel pressure (aka monophonic aftertouch), not poly pressure (aka poly aftertouch).

@SpotlightKid
Copy link
Author

Once support is added to the engine, it can be easily supported in the LV2 plugin with:

diff --git a/lv2/sfizz.c b/lv2/sfizz.c
index 87c0923..df2ccf2 100644
--- a/lv2/sfizz.c
+++ b/lv2/sfizz.c
@@ -434,6 +434,14 @@ sfizz_lv2_process_midi_event(sfizz_plugin_t *self, const LV2_Atom_Event *ev)
                       (int)msg[1],
                       msg[2]);
         break;
+    case LV2_MIDI_CHANNEL_PRESSURE:
+        // lv2_log_note(&self->logger,
+        //              "[process_midi] Received channel pressure %d/%d at time %d\n", msg[0], msg[1], ev->time.frames);
+        sfizz_send_aftertouch(self->synth,
+                      (int)ev->time.frames,
+                      (int)MIDI_CHANNEL(msg[0]) + 1,
+                      (int)msg[1]);
+        break;
     default:
         break;
     }

@paulfd
Copy link
Member

paulfd commented Nov 29, 2019

Thanks! For this particular target I still need LFOs, which would better be implemented against the SFZv2 spec as it is more general. It's on the todo list, after which adding modulation targets from aftertouch events would be quite easy.

On the other hand I really have no hardware to test this, nor did I ever see it used; you have a good example lying somewhere?

@SpotlightKid
Copy link
Author

SpotlightKid commented Nov 29, 2019

Tons of keyboards support channel pressure. Keyboards, which generate polyphonic aftertouch, though, are very rare beasts.

But mono aftertouch is often used by keyboard players to control vibrato, so they don't have to use their other hand on the modulation wheel for that and can play something else with it. Or to add expression by controlling the filter cutoff or volume.

For testing you can just convert an arbitrary Control Change into Channel Pressure. For example, the following Lua script for the Moony.lv2 plugin converts Control Change #1 (modulation) messages into Channel Pressure messages on the same channel:

-- Convert specific Control Change events to MIDI Channel Pressure (aka Mono Aftertouch)

-- 0..15 or set to -1 to apply to events on all channels
local filter_chan = -1
-- which control change number to convert?
local source_cc = 1
-- whether to pass non-CC and other CC events
local pass_other = true


-- NO NEED TO CHANGE ANYTHING BELOW

function cc2channelpressure(self, frames, forge, chan, cc, value)
  if filter_chan == -1 or chan == filter_chan then
    if cc == source_cc then
        forge:time(frames):midi(MIDI.ChannelPressure | chan, value)
    elseif pass_other then
        forge:time(frames):midi(MIDI.Controller | chan, cc, value)
    end
  end
end

-- define a MIDIResponder object to handle note-on and note-off events
local midiR = MIDIResponder({
  [MIDI.Controller] = cc2channelpressure,
}, pass_other)

function run(n, control, notify, seq, forge)
  -- iterate over incoming events
  for frames, atom in seq:foreach() do
    -- call responder for event
    local handled = midiR(frames, forge, atom)
  end
end

@paulfd
Copy link
Member

paulfd commented Dec 1, 2019

Great thanks, I'll use this to test. I have to say though that it's slightly longer term than some more immediate items I'd like to add :)

@SpotlightKid
Copy link
Author

It's also much less important than pitch bend :)

@alcomposer
Copy link
Collaborator

I would be interested in seeing Polyphonic Aftertouch as well. Devices such as the Roli Seaboard support it, as do any devices that support MPE. (The list is growing every day).

I understand that this would be a long term goal.

@paulfd paulfd self-assigned this Dec 3, 2019
@redtide redtide added the new feature Feature additions and requests label Dec 14, 2019
@redtide
Copy link
Member

redtide commented Dec 22, 2019

I would be interested in seeing Polyphonic Aftertouch as well. Devices such as the Roli Seaboard support it, as do any devices that support MPE. (The list is growing every day).

Some Roland electronic drum modules (not sure if others) use it for cymbal choking, so it might be useful also for that (even if maybe with a minimal use of it)

@alcomposer
Copy link
Collaborator

alcomposer commented Dec 25, 2019

Just a correction (of what I said above):

MPE uses monophonic aftertouch, each MIDI channel represents a note. PolyAft is reserved in MPE.

If MPE is tackled, then obviously that would be part of a bigger picture.

However, with standard MIDI (non-MPE) mono or poly aftertouch can be very cool, and expressive.

@sagamusix
Copy link

It's not the scope of this issue, but as the hardware question came up: a relatively inexpensive and recent device that emits Poly Aftertouch messages is the Arturia Microfreak.

@paulfd paulfd added this to the 0.4.0 milestone Apr 2, 2020
@paulfd
Copy link
Member

paulfd commented Apr 9, 2020

@SpotlightKid
Copy link
Author

The extended MIDI CCs seem to add considerable complexity. Tbh, I'm not sure why one would use them or if they ar worth implementing. Obviously they can not be sent via MIDI, so the would just add another way to trigger event handlers via the API, wouldn't they?

Still hoping to see support for at least filter (LFO) and pitch LFO modulation added soon. Is this still on the roadmap for the next release?

@jpcima
Copy link
Collaborator

jpcima commented Jun 13, 2020

The extended CC129 is supposed to be computed according to MIDI, so are most of extended ones listed on the page. The higher CC numbers are supposed to be used by a user interface for implementing custom graphical controls.

The modulations are worked on, but maybe early for a next release.
I think, we had better have at least a next release dedicated to bug fixes, because there were numerous compatibility fixes of existing instruments from the previous release.

@paulfd paulfd modified the milestones: 0.4.0, 0.5.0 Jul 1, 2020
@paulfd paulfd modified the milestones: 0.5.0, 0.6.0 Oct 15, 2020
@paulfd
Copy link
Member

paulfd commented Feb 5, 2021

#630 will implement the basic support, although not the XXXlfo_XXXchanaft opcodes which require internal links in the modulation matrix. These will readily come when said links are implemented :)

@paulfd
Copy link
Member

paulfd commented Apr 4, 2021

Should all be in now !

@paulfd paulfd closed this as completed Apr 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature Feature additions and requests
Projects
None yet
Development

No branches or pull requests

6 participants