imported midi.py module after python3 port, stripped most of the write part.

This commit is contained in:
Jean-Francois Dockes 2018-02-22 09:50:45 +01:00
parent e72bac02c3
commit 5c80488465
2 changed files with 28 additions and 136 deletions

View File

@ -17,7 +17,7 @@ except:
pass pass
try: try:
from midi import midi import rclmidi as midi
except: except:
print("RECFILTERROR HELPERNOTFOUND python:midi") print("RECFILTERROR HELPERNOTFOUND python:midi")
sys.exit(1); sys.exit(1);

View File

@ -1,13 +1,34 @@
# The MIT License (MIT)
# Copyright (c) 2013 Giles F. Hall
# https://github.com/vishnubob/python-midi/blob/master/LICENSE
# Modifications: Copyright (c) 2012-2018 J.F. Dockes
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
from __future__ import print_function from __future__ import print_function
import sys import sys
import six
import copy
import time
from io import BytesIO
from struct import unpack, pack from struct import unpack, pack
from math import sqrt import six
def debug(s): def debug(s):
print("%s"%s, file=sys.stderr) print("%s"%s, file=sys.stderr)
@ -113,9 +134,6 @@ class Event(object):
""" sort order """ """ sort order """
self.order = None self.order = None
def copy(self):
return copy.deepcopy(self)
def is_event(cls, statusmsg): def is_event(cls, statusmsg):
return (cls.statusmsg == (statusmsg & 0xF0)) return (cls.statusmsg == (statusmsg & 0xF0))
is_event = classmethod(is_event) is_event = classmethod(is_event)
@ -140,12 +158,6 @@ class Event(object):
rtick = self.tick - tempo.tick rtick = self.tick - tempo.tick
self.msdelay = int((rtick * tempo.mpt) + tempo.msdelay) self.msdelay = int((rtick * tempo.mpt) + tempo.msdelay)
def encode(self, delta=0, running=False):
encstr = ''
if not running:
encstr += chr((self.statusmsg & 0xF0) | (0x0F & self.channel))
return self.encode_tick(delta=delta) + encstr + self.encode_data()
def decode(self, tick, statusmsg, track, runningstatus=b''): def decode(self, tick, statusmsg, track, runningstatus=b''):
assert(self.is_event(statusmsg)) assert(self.is_event(statusmsg))
self.tick = tick self.tick = tick
@ -159,14 +171,9 @@ class Event(object):
for x in range(remainder)]) for x in range(remainder)])
self.decode_data() self.decode_data()
def encode_tick(self, delta=0):
return write_varlen(self.tick + delta)
def decode_data(self): def decode_data(self):
pass pass
def encode_data(self):
return self.data
""" """
MetaEvent is a special subclass of Event that is not meant to MetaEvent is a special subclass of Event that is not meant to
@ -187,14 +194,6 @@ class MetaEvent(Event):
return (cls.metacommand == metacmd) return (cls.metacommand == metacmd)
is_meta_event = classmethod(is_meta_event) is_meta_event = classmethod(is_meta_event)
def encode(self, delta=0, running=False):
tick = self.encode_tick(delta=delta)
data = self.encode_data()
datalen = bytes([len(data)])
smsg = bytes([self.statusmsg])
mcmd = bytes([self.metacommand])
return bytes.join(b'', (tick, smsg, mcmd, datalen, data))
def decode(self, tick, command, track): def decode(self, tick, command, track):
assert(self.is_meta_event(command)) assert(self.is_meta_event(command))
self.tick = tick self.tick = tick
@ -206,8 +205,6 @@ class MetaEvent(Event):
for x in range(len)]) for x in range(len)])
self.decode_data() self.decode_data()
def encode_data(self):
return self.data
""" """
EventFactory is a singleton that you should not instantiate. It is EventFactory is a singleton that you should not instantiate. It is
@ -285,8 +282,6 @@ class NoteEvent(Event):
self.pitch = ord(self.data[0]) self.pitch = ord(self.data[0])
self.velocity = ord(self.data[1]) self.velocity = ord(self.data[1])
def encode_data(self):
return chr(self.pitch) + chr(self.velocity)
class NoteOnEvent(NoteEvent): class NoteOnEvent(NoteEvent):
statusmsg = 0x90 statusmsg = 0x90
@ -326,8 +321,6 @@ class ControlChangeEvent(Event):
self.control = ord(self.data[0]) self.control = ord(self.data[0])
self.value = ord(self.data[1]) self.value = ord(self.data[1])
def encode_data(self):
return chr(self.contorl) + chr(self.value)
class ProgramChangeEvent(Event): class ProgramChangeEvent(Event):
statusmsg = 0xC0 statusmsg = 0xC0
@ -345,8 +338,6 @@ class ProgramChangeEvent(Event):
else: else:
self.value = ord(self.data[0]) self.value = ord(self.data[0])
def encode_data(self):
return chr(self.value)
class ChannelAfterTouchEvent(Event): class ChannelAfterTouchEvent(Event):
statusmsg = 0xD0 statusmsg = 0xD0
@ -378,11 +369,6 @@ class PitchWheelEvent(Event):
second = ord(self.data[1]) second = ord(self.data[1])
self.value = ((second << 7) | first) - 0x2000 self.value = ((second << 7) | first) - 0x2000
def encode_data(self):
value = self.value + 0x2000
first = chr(value & 0xFF)
second = chr((value >> 7) & 0xFF)
return first + second
class SysExEvent(Event): class SysExEvent(Event):
statusmsg = 0xF0 statusmsg = 0xF0
@ -526,11 +512,6 @@ class SetTempoEvent(MetaEvent):
self.tempo = float(6e7) / self.mpqn self.tempo = float(6e7) / self.mpqn
def encode_data(self):
self.mpqgn = int(float(6e7) / self.tempo)
return chr((self.mpqn & 0xFF0000) >> 16) + \
chr((self.mpqn & 0xFF00) >> 8) + \
chr((self.mpqn & 0xFF))
class SmpteOffsetEvent(MetaEvent): class SmpteOffsetEvent(MetaEvent):
name = 'SMPTE Offset' name = 'SMPTE Offset'
@ -564,12 +545,6 @@ class TimeSignatureEvent(MetaEvent):
self.metronome = ord(self.data[2]) self.metronome = ord(self.data[2])
self.thirtyseconds = ord(self.data[3]) self.thirtyseconds = ord(self.data[3])
def encode_data(self):
return chr(self.numerator) + \
chr(int(sqrt(self.denominator))) + \
chr(self.metronome) + \
chr(self.thirtyseconds)
class KeySignatureEvent(MetaEvent): class KeySignatureEvent(MetaEvent):
name = 'Key Signature' name = 'Key Signature'
@ -865,47 +840,6 @@ class EventStream(object):
tempo = self.tempomap.get_tempo(self.endoftrack.tick) tempo = self.tempomap.get_tempo(self.endoftrack.tick)
self.endoftrack.adjust_msdelay(tempo) self.endoftrack.adjust_msdelay(tempo)
class EventStreamWriter(object):
def __init__(self, midistream, output):
if isinstance(output, str):
output = open(output, 'w')
self.output = output
self.midistream = midistream
self.write_file_header()
for track in self.midistream:
self.write_track(track)
def write(cls, midistream, output):
cls(midistream, output)
write = classmethod(write)
def write_file_header(self):
# First four bytes are MIDI header
packdata = pack(">LHHH", 6,
self.midistream.format,
self.midistream.trackcount,
self.midistream.resolution)
self.output.write('MThd%s' % packdata)
def write_track_header(self, trklen):
self.output.write('MTrk%s' % pack(">L", trklen))
def write_track(self, track):
buf = ''
track = copy.copy(track)
track.sort()
last_tick = delta = 0
smsg = 0
chn = 0
for event in track:
running = ((smsg == event.statusmsg) and (chn == event.channel))
buf += event.encode(delta=-last_tick, running=running)
last_tick = event.tick
smsg = event.statusmsg
chn = event.channel
self.write_track_header(len(buf))
self.output.write(buf)
class EventStreamReader(object): class EventStreamReader(object):
def __init__(self, instream, outstream): def __init__(self, instream, outstream):
self.eventfactory = None self.eventfactory = None
@ -989,46 +923,4 @@ def read_varlen(data):
value += chr value += chr
return value return value
def write_varlen(value):
chr1 = chr(value & 0x7F)
value >>= 7
if value:
chr2 = chr((value & 0x7F) | 0x80)
value >>= 7
if value:
chr3 = chr((value & 0x7F) | 0x80)
value >>= 7
if value:
chr4 = chr((value & 0x7F) | 0x80)
res = chr4 + chr3 + chr2 + chr1
else:
res = chr3 + chr2 + chr1
else:
res = chr2 + chr1
else:
res = chr1
return res
def test_varlen():
for value in range(0x0FFFFFFF):
if not (value % 0xFFFF):
print("%s" % hex(value))
datum = write_varlen(value)
newvalue = read_varlen(iter(datum))
if value != newvalue:
hexstr = bytes.join(b'', map(hex, map(ord, datum)))
print("%s != %s (hex: %s)" % (value, newvalue, hexstr))
def new_stream(tempo=120, resolution=480, format=1):
stream = EventStream()
stream.format = format
stream.resolution = resolution
stream.add_track()
tempoev = SetTempoEvent()
tempoev.tempo = tempo
tempoev.tick = 0
stream.add_event(tempoev)
return stream
read_midifile = EventStreamReader.read read_midifile = EventStreamReader.read
write_midifile = EventStreamWriter.write