Skip to content

Commit

Permalink
Added Pitch Bend and Polyphonic Aftertouch
Browse files Browse the repository at this point in the history
  • Loading branch information
MicroTransactionsMatterToo committed Aug 24, 2017
1 parent ea8e9a1 commit 9de0569
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 5 deletions.
2 changes: 2 additions & 0 deletions docs/structure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This documentation covers the internal representations of MIDI constructs, such
.. autoclass:: Header

.. autoclass:: Event
:members:
:private-members:

.. autoclass:: Track

Expand Down
195 changes: 191 additions & 4 deletions midisnake/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,107 @@
}


def _decode_leftright(data: int) -> str:
if data > 64:
return "right"
elif data < 64:
return "left"
elif data == 127:
return "center"
else:
raise ValueError("Balance value {} was outside of valid range of 0-127".format(data))


midi_controls = {
0x00: {
"name": "Bank Select",
"byteorder": "big"
},
0x01: {
"name": "Modulation Wheel",
"byteorder": "big"
},
0x02: {
"name": "Breath Control",
"byteorder": "big"
},
0x03: {
"name": "undefined",
"byteorder": "big"
},
0x04: {
"name": "Foot Controller",
"byteorder": "big"
},
0x05: {
"name": "Portamento Time",
"byteorder": "big"
},
0x06: {
"name": "Data Entry",
"byteorder": "big"
},
0x07: {
"name": "Channel Volume",
"byteorder": "big"
},
0x08: {
"name": "Balance",
"byteorder": "big",
"decoder": _decode_leftright
},
0x09: {
"name": "undefined",
"byteorder": "big"
},
0x0A: {
"name": "Pan",
"byteorder": "big",
"decoder": _decode_leftright
},
0x0B: {
"name": "Expression",
"byteorder": "big"
},
0x0C: {
"name": "Effect Controller 1",
"byteorder": "big"
},
0x0D: {
"name": "Effect Controller 2",
"byteorder": "big"
},
0x0E: {
"name": "General Purpose",
"byteorder": "big"
},
0x0F: {
"name": "General Purpose",
"byteorder": "big"
},
0x10: {
"name": "General Purpose",
"byteorder": "big"
},
0x11: {
"name": "General Purpose",
"byteorder": "big"
},
0x12: {
"name": "General Purpose",
"byteorder": "big"
},
0x13: {
"name": "General Purpose",
"byteorder": "big"
}
}


def get_note_name(data: int) -> str:
"""
Converts a MIDI note value to a note name.
Args:
"""Converts a MIDI note value to a note name.
Arguments:
data (int): Note value
Returns:
Expand All @@ -54,6 +151,20 @@ def get_note_name(data: int) -> str:


class NoteOn(Event):
"""MIDI NoteOn event
Notes:
Subclasses the :class:`midisnake.structure.Event` metaclass
Attributes:
event_name (str): Name of Event
indicator_byte (int): Byte that indicates the MIDI Event type
note_number (int): MIDI note number, between 0 and 127
note_name (str): Musical note name, as returned by :func:`get_note_name`
note_velocity (int): Volume, between 0 and 127
channel_number (int): MIDI Channel number
raw_data (int): Initial data from MIDI file
"""
event_name = "NoteOn"
indicator_byte = 0x90

Expand All @@ -64,15 +175,32 @@ class NoteOn(Event):

channel_number = None # type: int

raw_data = None # type: int

def _process(self, data: int):
data_array = bytearray.fromhex(hex(data)[2:])
self.channel_number = data_array[0] & 0x0F
self.note_number = data_array[1]
self.note_name = get_note_name(data_array[1])
self.note_velocity = data_array[2]
self.raw_data = data


class NoteOff(Event):
"""MIDI NoteOff event
Notes:
Subclasses the :class:`midisnake.structure.Event` metaclass
Attributes:
event_name (str): Name of Event
indicator_byte (int): Byte that indicates the MIDI Event type
note_number (int): MIDI note number, between 0 and 127
note_name (str): Musical note name, as returned by :func:`get_note_name`
note_velocity (int): Volume, between 0 and 127
channel_number (int): MIDI Channel number
raw_data (int): Initial data from MIDI file
"""
event_name = "NoteOff"
indicator_byte = 0x80

Expand All @@ -83,9 +211,68 @@ class NoteOff(Event):

channel_number = None # type: int

raw_data = None # type: int

def _process(self, data: int):
data_array = bytearray.fromhex(hex(data)[2:])
self.channel_number = data_array[0] & 0x0F
self.note_number = data_array[1]
self.note_name = get_note_name(data_array[1])
self.note_velocity = data_array[2]
self.note_velocity = data_array[2]
self.raw_data = data


class PolyphonicAftertouch(Event):
"""MIDI PolyPhonic Aftertouch
Notes:
Subclasses the :class:`midisnake.structure.Event` metaclass
Attributes:
event_name (str): Name of Event
indicator_byte (int): Byte that indicates the MIDI Event type
pressure (int): Polyphonic Pressure, between 0 and 16383
channel_number (int): MIDI Channel number
raw_data (int): Initial data from MIDI file
"""
event_name = "Polyphonic Aftertouch"
indicator_byte = 0xA0

pressure = None # type: int
note_number = None # type: int
note_name = None # type: str

channel_number = None # type: int

raw_data = None # type: int

def _process(self, data: int):
data_array = bytearray.fromhex(hex(data)[2:])
self.channel_number = data_array[0] & 0x0F
self.note_number = data_array[1]
self.note_name = get_note_name(data_array[1])
self.pressure = data_array[2]
self.raw_data = data


class PitchBend(Event):
"""MIDI Pitch Bend
Notes:
Subclasses the :class:`midisnake.structure.Event` metaclass
"""
event_name = "Pitch Bend"
indicator_byte = 0xE0

bend_amount = None # type: int

channel_number = None # type: int

raw_data = None # type: int
def _process(self, data: int):
data_array = bytearray.fromhex(hex(data)[2:])
self.channel_number = data_array[0] & 0x0F
self.bend_amount = (data_array[2] << 7) & data_array[1]
self.raw_data = data
7 changes: 6 additions & 1 deletion midisnake/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ class Header:

class Event(metaclass=ABCMeta): # pramga: no
"""
Metaclass representing a MIDI Event. Subclasses must implement the `process` function
Metaclass representing a MIDI Event. Subclasses must implement the :func:`~_process` function
Attributes:
event_name (str): Name of event
indicator_byte (int): Byte that indicates the MIDI Event type
raw_data (int): Initial data from MIDI file
"""
event_name = None # type: str
indicator_byte = None # type: int
Expand Down

0 comments on commit 9de0569

Please sign in to comment.