MIDI to physical keypress
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
MIDI to physical keypress
Hi, I'm not a coder, nor do I see any examples of people mapping midi inputs to keypresses. If someone could give me a quick example script, that would be much appreciated. I assume that FreePIE can emulate physical keypresses, because I've tried a couple other programs that convert MIDI to keypresses, but their outputs weren't detected by the game I want to play with the controller. Thanks much!
-
- Cross Eyed!
- Posts: 197
- Joined: Mon Mar 02, 2015 3:58 pm
Re: MIDI to physical keypress
It has been a while since I have used a MIDI device and I do not have one at the ready. What is worse, mine was rather unstandard...
Could you please run this script and write down what values are sent when you press and release a key on your instrument (or when you do whatever else to send a note and stop it)?
Could you please run this script and write down what values are sent when you press and release a key on your instrument (or when you do whatever else to send a note and stop it)?
Code: Select all
def update():
diagnostics.watch(midi[0].data.channel);
diagnostics.watch(midi[0].data.status);
diagnostics.watch(midi[0].data.buffer[0]);
diagnostics.watch(midi[0].data.buffer[1]);
if starting:
midi[0].update += update
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
Re: MIDI to physical keypress
Thanks for the assistance! I have an MPD218, so it's pads. I get the following:Jabberwock wrote:It has been a while since I have used a MIDI device and I do not have one at the ready. What is worse, mine was rather unstandard...
Could you please run this script and write down what values are sent when you press and release a key on your instrument (or when you do whatever else to send a note and stop it)?
Code: Select all
def update(): diagnostics.watch(midi[0].data.channel); diagnostics.watch(midi[0].data.status); diagnostics.watch(midi[0].data.buffer[0]); diagnostics.watch(midi[0].data.buffer[1]); if starting: midi[0].update += update
midi[0].data.channel 9
midi[0].data.status NoteOn
midi[0].data.buffer[0] (different numerical value for each pad)
midi[0].data.buffer[1] 127 (I have it set to always send full velocity so this value is constant)
-
- Petrif-Eyed
- Posts: 2166
- Joined: Mon Jun 22, 2009 8:36 am
- Location: Stockholm, Sweden
Re: MIDI to physical keypress
Something like this could work, not tested!moxanthia wrote:Thanks for the assistance! I have an MPD218, so it's pads. I get the following:Jabberwock wrote:It has been a while since I have used a MIDI device and I do not have one at the ready. What is worse, mine was rather unstandard...
Could you please run this script and write down what values are sent when you press and release a key on your instrument (or when you do whatever else to send a note and stop it)?
Code: Select all
def update(): diagnostics.watch(midi[0].data.channel); diagnostics.watch(midi[0].data.status); diagnostics.watch(midi[0].data.buffer[0]); diagnostics.watch(midi[0].data.buffer[1]); if starting: midi[0].update += update
midi[0].data.channel 9
midi[0].data.status NoteOn
midi[0].data.buffer[0] (different numerical value for each pad)
midi[0].data.buffer[1] 127 (I have it set to always send full velocity so this value is constant)
Code: Select all
def update():
keyboard.setKey(keyMapping[midi[0].data.buffer[0]], midi[0].data.status == MidiStatus.NoteOn)
if starting:
keyMapping = {0: Key.A, 1: Key.Space}
midi[0].update += update
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
Re: MIDI to physical keypress
Okay, so I would test this out, but for some reason FreePIE only detected my midi input the very first time I ran it. Other software still detects my input though.CyberVillain wrote:Something like this could work, not tested!moxanthia wrote:Thanks for the assistance! I have an MPD218, so it's pads. I get the following:Jabberwock wrote:It has been a while since I have used a MIDI device and I do not have one at the ready. What is worse, mine was rather unstandard...
Could you please run this script and write down what values are sent when you press and release a key on your instrument (or when you do whatever else to send a note and stop it)?
Code: Select all
def update(): diagnostics.watch(midi[0].data.channel); diagnostics.watch(midi[0].data.status); diagnostics.watch(midi[0].data.buffer[0]); diagnostics.watch(midi[0].data.buffer[1]); if starting: midi[0].update += update
midi[0].data.channel 9
midi[0].data.status NoteOn
midi[0].data.buffer[0] (different numerical value for each pad)
midi[0].data.buffer[1] 127 (I have it set to always send full velocity so this value is constant)
Pad = 0 maps to Key A and Pad = 1 to spaceCode: Select all
def update(): keyboard.setKey(keyMapping[midi[0].data.buffer[0]], midi[0].data.status == MidiStatus.NoteOn) if starting: keyMapping = {0: Key.A, 1: Key.Space} midi[0].update += update
-
- Cross Eyed!
- Posts: 197
- Joined: Mon Mar 02, 2015 3:58 pm
Re: MIDI to physical keypress
I am not sure if it is the case, but you might have the same issue as I did: the instrument sends a NoteOn signal, but never sends a NoteOff (which is, as I understand, rather unorthodox from the MIDI point of view). That means that detecting NoteOn (as CyberVillain's script does) might not be very helpful, as that state simply remains, only the notes change. Actually, it was one of the reasons I do not have a physical MIDI device any more: I have torn out the old board and replaced it with an Arduino...
However, not all hope is lost, if all you want to do is just detect the exact moment the note is sent and you do not care how long it lasts, which is rather reasonable for drum pads. If you run the script on MIDI updates, you might just send a momentary keypress, i.e. the key will be pressed only in the frame (single script execution) directly after an MIDI update. The issue is that it means the key is pressed for a VERY short time, which might not be enough for your purposes. Here is a quick and dirty script (of course you need to replace the relevant entries in the keyMapping dictionary):
If the keypresses are too short to be detected by the target app, you would need to zero the midipressed variable not immediately, but after some predefined time. It must be long enough to be detected, but also short enough to detect repeated hits of the same pad.
However, not all hope is lost, if all you want to do is just detect the exact moment the note is sent and you do not care how long it lasts, which is rather reasonable for drum pads. If you run the script on MIDI updates, you might just send a momentary keypress, i.e. the key will be pressed only in the frame (single script execution) directly after an MIDI update. The issue is that it means the key is pressed for a VERY short time, which might not be enough for your purposes. Here is a quick and dirty script (of course you need to replace the relevant entries in the keyMapping dictionary):
Code: Select all
def update():
global midipressed
midipressed = midi[0].data.buffer[0]
if starting:
midi[0].update += update
keyMapping = {49: Key.A, 51: Key.Space}
midipressed = 0
for mapping, keyName in keyMapping.items():
keyboard.setKey(keyName, mapping == midipressed)
midipressed = 0
-
- Petrif-Eyed
- Posts: 2166
- Joined: Mon Jun 22, 2009 8:36 am
- Location: Stockholm, Sweden
Re: MIDI to physical keypress
There is also a built in mechanic to send keypresses for a short timeperiod
keyboard.setPressed
keyboard.setPressed
-
- Cross Eyed!
- Posts: 197
- Joined: Mon Mar 02, 2015 3:58 pm
Re: MIDI to physical keypress
I forgot about that... Then it gets even simpler:
I have tested it with a virtual MIDI device and it seems to work.
Code: Select all
def update():
keyboard.setPressed(keyMapping[midi[0].data.buffer[0]])
if starting:
keyMapping = {24: Key.A, 25: Key.B, 26: Key.C}
midi[0].update += update
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
Re: MIDI to physical keypress
The problem is that FreePIE won't even give me any information in the Watch window with the first script you gave me for figuring out values. It worked the first time I ran it, so I was able to send you the results, but now nothing works. I've tried reconnecting the controller and rebooting, but I know that it isn't the connection that's a problem because other MIDI software still works flawlessly. FreePIE doesn't seem to have a setting for MIDI configuration, but it did just automatically work at first so I'm not sure what happened.Jabberwock wrote:I am not sure if it is the case, but you might have the same issue as I did: the instrument sends a NoteOn signal, but never sends a NoteOff (which is, as I understand, rather unorthodox from the MIDI point of view). That means that detecting NoteOn (as CyberVillain's script does) might not be very helpful, as that state simply remains, only the notes change. Actually, it was one of the reasons I do not have a physical MIDI device any more: I have torn out the old board and replaced it with an Arduino...
However, not all hope is lost, if all you want to do is just detect the exact moment the note is sent and you do not care how long it lasts, which is rather reasonable for drum pads. If you run the script on MIDI updates, you might just send a momentary keypress, i.e. the key will be pressed only in the frame (single script execution) directly after an MIDI update. The issue is that it means the key is pressed for a VERY short time, which might not be enough for your purposes. Here is a quick and dirty script (of course you need to replace the relevant entries in the keyMapping dictionary):
If the keypresses are too short to be detected by the target app, you would need to zero the midipressed variable not immediately, but after some predefined time. It must be long enough to be detected, but also short enough to detect repeated hits of the same pad.Code: Select all
def update(): global midipressed midipressed = midi[0].data.buffer[0] if starting: midi[0].update += update keyMapping = {49: Key.A, 51: Key.Space} midipressed = 0 for mapping, keyName in keyMapping.items(): keyboard.setKey(keyName, mapping == midipressed) midipressed = 0
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
Re: MIDI to physical keypress
Okay, still not sure about why FreePIE doesn't detect MIDI on my PC, but I just tested out my laptop and everything works fine with the first script CyberVillain posted. Thanks for both of your assistance! Hopefully, I can figure out the issue with my PC. I'll try reinstalling FreePIE for starters.
Edit: Reinstalling didn't help sadly.
Edit: Reinstalling didn't help sadly.
-
- Cross Eyed!
- Posts: 197
- Joined: Mon Mar 02, 2015 3:58 pm
Re: MIDI to physical keypress
Check your MIDI inputs. FreePIE does not let you select one, so possibly something else (e.g. a virtual MIDI port) gets selected as an input. I usually use MidiOX to see what is going with MIDI. The only problem is that when I use MidiOX and another MIDI program together with virtual loop software, Windows might report a feedback and I need to reboot to get everything in order.
If CyberVillain's script works, then your instrument behaves as it should and sends a NoteOff message.
If CyberVillain's script works, then your instrument behaves as it should and sends a NoteOff message.
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
Re: MIDI to physical keypress
MIDIOX did indeed have a virtual input show up, so I removed it and now everything works fine. Thanks for the help!Jabberwock wrote:Check your MIDI inputs. FreePIE does not let you select one, so possibly something else (e.g. a virtual MIDI port) gets selected as an input. I usually use MidiOX to see what is going with MIDI. The only problem is that when I use MidiOX and another MIDI program together with virtual loop software, Windows might report a feedback and I need to reboot to get everything in order.
If CyberVillain's script works, then your instrument behaves as it should and sends a NoteOff message.
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
Re: MIDI to physical keypress
Actually I've run into another problem. I thought that setPressed would keep the mapped key pressed down, but it seems to instead be repeatedly pressing the key which doesn't work for my purposes.
-
- Cross Eyed!
- Posts: 197
- Joined: Mon Mar 02, 2015 3:58 pm
Re: MIDI to physical keypress
setPressed, as CyberVillain mentioned above, is only for momentary key press (but it should fire only once, on MIDI update). setKey (or setKeyDown/Up) is for toggling the key state.
-
- One Eyed Hopeful
- Posts: 8
- Joined: Wed Nov 27, 2019 6:06 pm
Re: MIDI to physical keypress
So if I use setKeyDown with NoteOn and setKeyUp with NoteOff, it should keep the key pressed down until I let off the pad right? I tried that and it still only sends a single keypress. The pad sends NoteOn and NoteOff if pressed quickly, but if I hold it down it sends NoteOn, PloyphonicAftertouch(for the entire period that it is held down), and then NoteOff.Jabberwock wrote:setPressed, as CyberVillain mentioned above, is only for momentary key press (but it should fire only once, on MIDI update). setKey (or setKeyDown/Up) is for toggling the key state.
-
- Cross Eyed!
- Posts: 197
- Joined: Mon Mar 02, 2015 3:58 pm
Re: MIDI to physical keypress
How are you checking the keypresses? Notepad etc. might not be too good, as they register keypresses differently. To be sure, you might first try driving virtual controller buttons with vJoy if you have it installed (if not, then it might not be worth it).
To isolate the problem, I would try to change and watch a variable each time setkeyUp is used. That way you would know how many times it is executed and when. If it is not and the key is not held down, something else is going on.
To isolate the problem, I would try to change and watch a variable each time setkeyUp is used. That way you would know how many times it is executed and when. If it is not and the key is not held down, something else is going on.