Programming with MIDI in Python | Responding to MIDI Messages

แชร์
ฝัง
  • เผยแพร่เมื่อ 13 ก.ย. 2024

ความคิดเห็น • 43

  • @carltonkess862
    @carltonkess862 ปีที่แล้ว +1

    So glad I found this, thanks for the presentation!

  • @germanpuerto99
    @germanpuerto99 ปีที่แล้ว +2

    Very good video man! I'm starting a software for midi instruments, and this video is a good introduction.

    • @mochreach
      @mochreach  ปีที่แล้ว

      Thanks very much, I'm glad it was useful!

  • @jimgoodinmusic
    @jimgoodinmusic 8 หลายเดือนก่อน

    really great - very good walkthrough of using Python to do this as well as the previous video you did sending messages. Thank you for explaining so well and sharing your knowledge! I have licked and subscribed

  • @stephen285
    @stephen285 ปีที่แล้ว +2

    AWESOME - very much appreciated Mo! This is going to be so helpful when I start to drive animations in blender with inbound midi data triggers. One questions comes to mind, so the current midi connector to blender (addroutes) has a horrible limitation, and that is if you want to use incoming note numbers as triggers you are limited to one note per channel, thus a total of 16 notes as can be used as discrete inbound triggers. However, I can use python/rtmidi in blender and make my own script connector - So I want to create a python script with an evaluation clause that gets processed on inbound messages "if midi note number = x" do a thing. My question is - what is the best way to evaluate 88 possible conditions on inbound note numbers? a giant 88 deep nested if else statement? I'm concerned about speed, if processing is in nano seconds great, but if it's milli seconds it may be a problem. Is there a way to load an array into memory so it process's faster. What are your thoughts? Greatly appreciate the help.

    • @mochreach
      @mochreach  ปีที่แล้ว

      You're very welcome! How complex is the function that you want to perform when a note is pressed? If you're only varying some parameters, colours or something, I'd probably make a dictionary with note numbers as keys and the data as values. If you want to perform more complex operations and you're using python >= 3.10, you could use structural pattern matching (peps.python.org/pep-0636/) otherwise a big if else statement will be fine. All options are going to be very fast, not likely to be the bottle neck. If you're wanting to do fast array operations, take a look at numpy.

  • @abominablemusic
    @abominablemusic หลายเดือนก่อน

    Hi, enjoying these python MIDI videos. Do you know if these libraries work via Jupyter/Colab running in a browser? I'd imagine they can't see the ports in these container-type environments. Cheers

    • @mochreach
      @mochreach  หลายเดือนก่อน +1

      They'll work with a jupyter notebook that's running locally, but for Colab, the MIDI data isn't forwarded from the host machine to your client machine via WebMIDI. Glad you're enjoying the videos, thanks for watching!

    • @abominablemusic
      @abominablemusic หลายเดือนก่อน

      @@mochreach cheers!

  • @acebone2
    @acebone2 ปีที่แล้ว

    Thanks - this is very instructive.
    In your code you have the following lines:
    # convert the command integer to a hex so it's easier to read
    command = hex(msg[0])
    print(f"{command} {msg[1:]}\t| dt = {dt:.2f}")
    I've never worked with MIDI on the codelevel before, and I am just curious: Is it just a personal preference that you find eg. 0x90 easier to read than 144 - or is there a more technical reason for this?

    • @mochreach
      @mochreach  ปีที่แล้ว +2

      Thanks @acebone2! The hex is generally easier to read because you can see the value of both bytes, this is useful for certain messages like note on. If you have 0x9A the 9 refers to the midi message type (note on) and the A is the channel (A=10 in hex, which is channel 11, as they start at 0 not 1). In decimal, you can't see this as easily as its 154, and it's not obvious what the message type and channel are. Does that make sense?

    • @acebone2
      @acebone2 ปีที่แล้ว

      @@mochreach it makes perfect sense, thanks!

  • @CraszyAsce
    @CraszyAsce ปีที่แล้ว +1

    I’d like to reprogram my ddj-400 controller functions with python. I can only imagine the possibilities but ChatGPT tells me it’s possible. It’d be cool to see you try to code with this library on a DJ controller

    • @mochreach
      @mochreach  ปีที่แล้ว

      I'm not familiar with the ddj-400, but from a quick look at the manual, you can use it as a midi controller, so you could get it to send MIDI messages to your computer. Is there anything in particular you're trying to do?

  • @adnanhyder2564
    @adnanhyder2564 ปีที่แล้ว

    Great video! Really liked how you explained the basics. I wanted to ask, I'm making a project using the PyQt5, mido, and Rtmidi libraries respectively. I want to use my piano as an input device. Can I do that?

    • @mochreach
      @mochreach  ปีที่แล้ว

      Thanks! Yes you can, so long as you can send MIDI from it. You should be able to handle it using Mido, it's a bit higher level than Rtmidi and is a bit nicer to use. You'll probably need to listen for MIDI messages on a separate thread from your UI, either explicitly of using async, and then passing it it to the front end. Is that the kind of thing you're trying to do?

    • @adnanhyder2564
      @adnanhyder2564 ปีที่แล้ว

      well @@mochreach, my plan was to make a small program like Synthesia, instead the only the difference is that I will be using my midi keyboard as an input device. For instance, when a key is pressed on my midi keyboard, the same key should be highlighted on the PyQt5 GUI. I am actually trying to do this but I'm facing problems. If you could help me that would be pretty cool lol

    • @mochreach
      @mochreach  ปีที่แล้ว +1

      That sounds like it should be feasible, I'll help if I can. What's the issue?

    • @adnanhyder2564
      @adnanhyder2564 ปีที่แล้ว

      ​@@mochreach The issue is that I can't seem to get my midi keyboard to send an input signal to the GUI. Now, I don't claim to be a professional at this, but I really want this to work. I wanted to ask, how do I send input from my midi keyboard to my pyqt5 GUI? How would you do it?

    • @mochreach
      @mochreach  ปีที่แล้ว +1

      I'm not familiar with PyQT5, but from a quick look at the docs, I think I'd respond to an event generated in response to detecting a note in from Mido. See this Stack Overflow post for more info: stackoverflow.com/a/55554690 The gist is that you can "emit" signals from arbitrary code that can be detected by elements in the UI. This is a pretty common pattern in UI programming. Hopefully that helps.

  • @stephen285
    @stephen285 ปีที่แล้ว

    Hi Mo was wondering if you could briefly explain a call back? if you know what that means and how it differs from standard midi in?

    • @mochreach
      @mochreach  ปีที่แล้ว

      Hi Stephen, a callback is a function that you give as an argument to another function. Generally, the callback is ran whenever specific events occur. For example, in Javascript, you might provide a callback to a function that handles touch events or other types of input. When that event is triggered, your callback is ran in response. What's the context you're being asked for a callback?

  • @user-hs9vo5hy8o
    @user-hs9vo5hy8o ปีที่แล้ว

    Hello Sir, I met a question. I use VMPK as a virtual MIDI editor and then use loopMIDI to create a new virtual port and have the VMPK connect to this port. But I can't find this port in python right now. The output of the "midi_in.get_ports()" code is empty. Hope you could help me!!!

    • @mochreach
      @mochreach  ปีที่แล้ว

      Sorry Tig, I've never experienced this. Could there be something similar to this that's going on? github.com/thestk/rtmidi/issues/208

  • @megistus9546
    @megistus9546 ปีที่แล้ว

    Great video -- thanks for making this stuff accessible to non-programmers :) Just wanted to ask -- is get_message() supposed to work with sysex raw midi messages? - it doesn't seem to print anything when receiving sysex, whereas MIDI notes show up fine.

    • @mochreach
      @mochreach  ปีที่แล้ว +1

      Hi @Megistus, and thanks! By default, I think that sysex messages are filtered out. There is a method called `ignore_types`, and you can use that to change what's being filtered. Here's a link to the docs: spotlightkid.github.io/python-rtmidi/rtmidi.html?highlight=sysex#rtmidi.MidiIn.ignore_types

    • @megistus9546
      @megistus9546 ปีที่แล้ว

      @@mochreach brilliant, thanks so much :)

    • @mochreach
      @mochreach  ปีที่แล้ว

      You're welcome!

  • @SiggeSvahn
    @SiggeSvahn 8 หลายเดือนก่อน

    I am failing to receive MIDI DUMP in the language PureBasic from my hardware synth. Have you had any luck doing that in Python?

    • @mochreach
      @mochreach  8 หลายเดือนก่อน +1

      Hi @SiggeSvahn, sorry I don't have any experience with either PureBasic or a MIDI Dump from a hardware synth. Are you trying to load a particular dump file with midi data in it?

    • @SiggeSvahn
      @SiggeSvahn 8 หลายเดือนก่อน

      @@mochreach That is correct.

    • @mochreach
      @mochreach  8 หลายเดือนก่อน +1

      @SiggeSvahn Sorry I thought I had replied to this! No idea about PureBasic, but you could try process the file using the mido Python library: mido.readthedocs.io/en/latest/

  • @stephen285
    @stephen285 ปีที่แล้ว

    fyi - so this works great in a vs code terminal, I'm getting data, everything is glorious! But I'm having to fight this in blender, it appears to work and hook on, I get the correct response to midi_in.open_port(0) but when I get to the part where I launch the while loop it crashes blender. Ive also tried running it as a script in blender rather than in an interactive python console but it crashes the same way. I'm fairly new to blender so it may be I'm missing something - I'll keep you posted- if you have any ideas please let me know. I'm studying up on your dictionary suggestion

    • @mochreach
      @mochreach  ปีที่แล้ว

      Glad you've got it working. I think that the while loop is probably crashing the application because it's blocking the main thread. I'm not totally sure what the solution is, it might be to use the multiprocessing module, or perhaps the answer is here: docs.blender.org/api/current/info_gotcha.html#help-my-script-crashes-blender. You could also explore async/await, but it runs an event loop not unlike the while loop. I also found this module: www.jpfep.net/pages/addmidi/ not sure if it helps.

  • @iagobeuller
    @iagobeuller ปีที่แล้ว

    How to solve the latency?

    • @mochreach
      @mochreach  ปีที่แล้ว

      I haven't noticed much latency when I've been testing it. How long is the sleep in your `while` loop?

    • @iagobeuller
      @iagobeuller ปีที่แล้ว

      @@mochreach I didn't use any sleep/wait:
      def main():
      midi_out = rtmidi.MidiOut()
      midi_in = rtmidi.MidiIn()
      print("Out:", midi_out.get_ports(), "
      In:", midi_in.get_ports())
      midi_out.open_port(0)
      midi_in.open_port(0)
      custom_velocity = 127
      with midi_out:
      with midi_in:
      while True:
      midi_msg = midi_in.get_message()
      if midi_msg:
      note, dt = midi_msg
      if custom_velocity:
      note[2] = custom_velocity
      midi_out.send_message(note)

  • @rolfjohansen5376
    @rolfjohansen5376 ปีที่แล้ว

    I am currently progging in MIDO for Python , should I make use of your rtMidi system instead or maybe try to mix them?

    • @mochreach
      @mochreach  ปีที่แล้ว +2

      They're both good in different ways. rtmidi is much lower level, it allows you to control things precisely, but it's harder and more verbose to do basic things. Mido abstracts away lots of the more complex things and makes it easier to do things correctly. Generally, I would use Mido for most things, but rtmidi is much better for getting an understanding of how midi works and when you need total control.

    • @rolfjohansen5376
      @rolfjohansen5376 ปีที่แล้ว

      @@mochreach exellent , thanks

  • @77377
    @77377 ปีที่แล้ว

    subscriiibed!