PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

115 lines
4.0KB

  1. # -*- coding: utf-8 -*-
  2. import rtmidi
  3. import random
  4. # ------------------------------------------------------------------------------
  5. class Midi:
  6. InvalidType = 0x00 # For notifying errors
  7. NoteOff = 0x80 # Note Off
  8. NoteOn = 0x90 # Note On
  9. AfterTouchPoly = 0xA0 # Polyphonic AfterTouch
  10. ControlChange = 0xB0 # Control Change / Channel Mode
  11. ProgramChange = 0xC0 # Program Change
  12. AfterTouchChannel = 0xD0 # Channel (monophonic) AfterTouch
  13. PitchBend = 0xE0 # Pitch Bend
  14. SystemExclusive = 0xF0 # System Exclusive
  15. TimeCodeQuarterFrame = 0xF1 # System Common - MIDI Time Code Quarter Frame
  16. SongPosition = 0xF2 # System Common - Song Position Pointer
  17. SongSelect = 0xF3 # System Common - Song Select
  18. TuneRequest = 0xF6 # System Common - Tune Request
  19. Clock = 0xF8 # System Real Time - Timing Clock
  20. Start = 0xFA # System Real Time - Start
  21. Continue = 0xFB # System Real Time - Continue
  22. Stop = 0xFC # System Real Time - Stop
  23. ActiveSensing = 0xFE # System Real Time - Active Sensing
  24. SystemReset = 0xFF # System Real Time - System Reset
  25. @staticmethod
  26. def getChannel(statusByte):
  27. return statusByte & 0x0f;
  28. @staticmethod
  29. def getType(statusByte):
  30. if statusByte >= 0xf0:
  31. # System messages
  32. return statusByte
  33. else:
  34. # Channel messages
  35. return statusByte & 0xf0;
  36. # ------------------------------------------------------------------------------
  37. class MidiInterface:
  38. def __init__(self, listenerCallback = None):
  39. self.input = rtmidi.MidiIn()
  40. self.output = rtmidi.MidiOut()
  41. self.listenerCallback = listenerCallback
  42. self.ports = self.getAvailablePorts()
  43. self.port = self.connect(self.choosePorts())
  44. # --------------------------------------------------------------------------
  45. def handleMidiInput(self, message, timestamp):
  46. midiData = message[0]
  47. if self.listenerCallback:
  48. self.listenerCallback(midiData)
  49. def send(self, message):
  50. print('Sending', message)
  51. self.output.send_message(message)
  52. # --------------------------------------------------------------------------
  53. def getAvailablePorts(self):
  54. return {
  55. 'input' : self.input.get_ports(),
  56. 'output': self.output.get_ports(),
  57. }
  58. def choosePorts(self):
  59. return {
  60. 'input' : self.choosePort(self.ports['input'], 'input'),
  61. 'output': self.choosePort(self.ports['output'], 'output')
  62. }
  63. def choosePort(self, ports, direction):
  64. if not ports:
  65. print('No MIDI ports available, bailing out.')
  66. return None
  67. if len(ports) == 1:
  68. return {
  69. 'id': 0,
  70. 'name': ports[0]
  71. }
  72. else:
  73. # Give a choice
  74. print('Multiple %s ports available, please make a choice:' % direction)
  75. choices = dict()
  76. for port, i in zip(ports, range(0, len(ports))):
  77. choices[i] = port
  78. print(' [%d]' % i, port)
  79. choiceIndex = int(input('-> '))
  80. return {
  81. 'id': choiceIndex,
  82. 'name': choices[choiceIndex]
  83. }
  84. # --------------------------------------------------------------------------
  85. def connect(self, ports):
  86. if not ports:
  87. return None
  88. print('Connecting input to %s' % ports['input']['name'])
  89. print('Connecting output to %s' % ports['output']['name'])
  90. self.input.set_callback(self.handleMidiInput)
  91. self.input.open_port(ports['input']['id'])
  92. self.output.open_port(ports['output']['id'])
  93. return ports