add midi fnord
This commit is contained in:
		
							parent
							
								
									8ed4510a4e
								
							
						
					
					
						commit
						5d93efa09c
					
				
					 45 changed files with 3061 additions and 0 deletions
				
			
		
							
								
								
									
										25
									
								
								projekte/soundz/midifnord/example_print_channel_0.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								projekte/soundz/midifnord/example_print_channel_0.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
import sys
 | 
			
		||||
sys.path.append("midi")
 | 
			
		||||
from MidiOutStream import MidiOutStream
 | 
			
		||||
from MidiInFile import MidiInFile
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
This prints all note on events on midi channel 0
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Transposer(MidiOutStream):
 | 
			
		||||
    
 | 
			
		||||
    "Transposes all notes by 1 octave"
 | 
			
		||||
    
 | 
			
		||||
    def note_on(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
        if channel == 0:
 | 
			
		||||
            print channel, note, velocity, self.rel_time()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
event_handler = Transposer()
 | 
			
		||||
 | 
			
		||||
in_file = 'nevergoingtoU.mid'
 | 
			
		||||
midi_in = MidiInFile(event_handler, in_file)
 | 
			
		||||
midi_in.read()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										217
									
								
								projekte/soundz/midifnord/midi/DataTypeConverters.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										217
									
								
								projekte/soundz/midifnord/midi/DataTypeConverters.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,217 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
from struct import pack, unpack
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
This module contains functions for reading and writing the special data types
 | 
			
		||||
that a midi file contains.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
nibbles are four bits. A byte consists of two nibles.
 | 
			
		||||
hiBits==0xF0, loBits==0x0F Especially used for setting
 | 
			
		||||
channel and event in 1. byte of musical midi events
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def getNibbles(byte):
 | 
			
		||||
    """
 | 
			
		||||
    Returns hi and lo bits in a byte as a tuple
 | 
			
		||||
    >>> getNibbles(142)
 | 
			
		||||
    (8, 14)
 | 
			
		||||
    
 | 
			
		||||
    Asserts byte value in byte range
 | 
			
		||||
    >>> getNibbles(256)
 | 
			
		||||
    Traceback (most recent call last):
 | 
			
		||||
        ...
 | 
			
		||||
    ValueError: Byte value out of range 0-255: 256
 | 
			
		||||
    """
 | 
			
		||||
    if not 0 <= byte <= 255:
 | 
			
		||||
        raise ValueError('Byte value out of range 0-255: %s' % byte)
 | 
			
		||||
    return (byte >> 4 & 0xF, byte & 0xF)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def setNibbles(hiNibble, loNibble):
 | 
			
		||||
    """
 | 
			
		||||
    Returns byte with value set according to hi and lo bits
 | 
			
		||||
    Asserts hiNibble and loNibble in range(16)
 | 
			
		||||
    >>> setNibbles(8, 14)
 | 
			
		||||
    142
 | 
			
		||||
    
 | 
			
		||||
    >>> setNibbles(8, 16)
 | 
			
		||||
    Traceback (most recent call last):
 | 
			
		||||
        ...
 | 
			
		||||
    ValueError: Nible value out of range 0-15: (8, 16)
 | 
			
		||||
    """
 | 
			
		||||
    if not (0 <= hiNibble <= 15) or not (0 <= loNibble <= 15):
 | 
			
		||||
        raise ValueError('Nible value out of range 0-15: (%s, %s)' % (hiNibble, loNibble))
 | 
			
		||||
    return (hiNibble << 4) + loNibble
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def readBew(value):
 | 
			
		||||
    """
 | 
			
		||||
    Reads string as big endian word, (asserts len(value) in [1,2,4])
 | 
			
		||||
    >>> readBew('aáâã')
 | 
			
		||||
    1642193635L
 | 
			
		||||
    >>> readBew('aá')
 | 
			
		||||
    25057
 | 
			
		||||
    """
 | 
			
		||||
    return unpack('>%s' % {1:'B', 2:'H', 4:'L'}[len(value)], value)[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def writeBew(value, length):
 | 
			
		||||
    """
 | 
			
		||||
    Write int as big endian formatted string, (asserts length in [1,2,4])
 | 
			
		||||
    Difficult to print the result in doctest, so I do a simple roundabout test.
 | 
			
		||||
    >>> readBew(writeBew(25057, 2))
 | 
			
		||||
    25057
 | 
			
		||||
    >>> readBew(writeBew(1642193635L, 4))
 | 
			
		||||
    1642193635L
 | 
			
		||||
    """
 | 
			
		||||
    return pack('>%s' % {1:'B', 2:'H', 4:'L'}[length], value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Variable Length Data (varlen) is a data format sprayed liberally throughout
 | 
			
		||||
a midi file. It can be anywhere from 1 to 4 bytes long.
 | 
			
		||||
If the 8'th bit is set in a byte another byte follows. The value is stored
 | 
			
		||||
in the lowest 7 bits of each byte. So max value is 4x7 bits = 28 bits.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def readVar(value):
 | 
			
		||||
    """
 | 
			
		||||
    Converts varlength format to integer. Just pass it 0 or more chars that
 | 
			
		||||
    might be a varlen and it will only use the relevant chars.
 | 
			
		||||
    use varLen(readVar(value)) to see how many bytes the integer value takes.
 | 
			
		||||
    asserts len(value) >= 0
 | 
			
		||||
    >>> readVar('€@')
 | 
			
		||||
    64
 | 
			
		||||
    >>> readVar('áâãa')
 | 
			
		||||
    205042145
 | 
			
		||||
    """
 | 
			
		||||
    sum = 0
 | 
			
		||||
    for byte in unpack('%sB' % len(value), value):
 | 
			
		||||
        sum = (sum << 7) + (byte & 0x7F)
 | 
			
		||||
        if not 0x80 & byte: break # stop after last byte
 | 
			
		||||
    return sum
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def varLen(value):
 | 
			
		||||
    """
 | 
			
		||||
    Returns the the number of bytes an integer will be when
 | 
			
		||||
    converted to varlength
 | 
			
		||||
    """
 | 
			
		||||
    if value <= 127:
 | 
			
		||||
        return 1
 | 
			
		||||
    elif value <= 16383:
 | 
			
		||||
        return 2
 | 
			
		||||
    elif value <= 2097151:
 | 
			
		||||
        return 3
 | 
			
		||||
    else:
 | 
			
		||||
        return 4
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def writeVar(value):
 | 
			
		||||
    "Converts an integer to varlength format"
 | 
			
		||||
    sevens = to_n_bits(value, varLen(value))
 | 
			
		||||
    for i in range(len(sevens)-1):
 | 
			
		||||
        sevens[i] = sevens[i] | 0x80
 | 
			
		||||
    return fromBytes(sevens)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_n_bits(value, length=1, nbits=7):
 | 
			
		||||
    "returns the integer value as a sequence of nbits bytes"
 | 
			
		||||
    bytes = [(value >> (i*nbits)) & 0x7F for i in range(length)]
 | 
			
		||||
    bytes.reverse()
 | 
			
		||||
    return bytes
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def toBytes(value):
 | 
			
		||||
    "Turns a string into a list of byte values"
 | 
			
		||||
    return unpack('%sB' % len(value), value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def fromBytes(value):
 | 
			
		||||
    "Turns a list of bytes into a string"
 | 
			
		||||
    if not value:
 | 
			
		||||
        return ''
 | 
			
		||||
    return pack('%sB' % len(value), *value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
#    print to7bits(0, 3)
 | 
			
		||||
#    print to7bits(127, 3)
 | 
			
		||||
#    print to7bits(255, 3)
 | 
			
		||||
#    print to7bits(65536, 3)
 | 
			
		||||
 | 
			
		||||
    # simple test cases
 | 
			
		||||
    
 | 
			
		||||
#    print 'getHiLoHex', getNibbles(16)
 | 
			
		||||
#    print 'setHiLoHex', setNibbles(1,0)
 | 
			
		||||
#    
 | 
			
		||||
#    print 'readBew', readBew('aáâã')
 | 
			
		||||
#    print 'writeBew', writeBew(1642193635, 4)
 | 
			
		||||
#
 | 
			
		||||
#    print 'varLen', varLen(1)
 | 
			
		||||
#
 | 
			
		||||
    print 'readVar', readVar('€@')
 | 
			
		||||
    print 'writeVar', writeVar(8192)
 | 
			
		||||
    
 | 
			
		||||
    print 'readVar', readVar('áâãa')
 | 
			
		||||
    print 'writeVar', writeVar(205058401)
 | 
			
		||||
#    
 | 
			
		||||
#    vartest = '\x82\xF7\x80\x00'
 | 
			
		||||
#    print 'toBytes', toBytes(vartest)
 | 
			
		||||
#    print 'fromBytes', fromBytes([48, 49, 50,])
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
#    instr = '\xFF\xFF\xFF\x00'
 | 
			
		||||
#    print 'readVar', readVar(instr)
 | 
			
		||||
#    inst2 = 268435455
 | 
			
		||||
#    print inst2
 | 
			
		||||
#    print writeVar(inst2)
 | 
			
		||||
#    print writeVar(readVar(instr))
 | 
			
		||||
 | 
			
		||||
    s1 = 0x00000000
 | 
			
		||||
    print '%08X -' % s1, '00',  writeVar(s1)
 | 
			
		||||
    s2 = 0x00000040
 | 
			
		||||
    print '%08X -' % s2, '40',  writeVar(s2)
 | 
			
		||||
    s3 = 0x0000007F
 | 
			
		||||
    print '%08X -' % s3, '7F',  writeVar(s3)
 | 
			
		||||
    s4 = 0x00000080
 | 
			
		||||
    print '%08X -' % s4, '81 00',  writeVar(s4)
 | 
			
		||||
    s5 = 0x00002000
 | 
			
		||||
    print '%08X -' % s5, 'C0 00',  writeVar(s5)
 | 
			
		||||
    s6 = 0x00003FFF
 | 
			
		||||
    print '%08X -' % s6, 'FF 7F',  writeVar(s6)
 | 
			
		||||
    s7 = 0x00004000
 | 
			
		||||
    print '%08X -' % s7, '81 80 00',  writeVar(s7)
 | 
			
		||||
    s8 = 0x00100000
 | 
			
		||||
    print '%08X -' % s8, 'C0 80 00',  writeVar(s8)
 | 
			
		||||
    s9 = 0x001FFFFF
 | 
			
		||||
    print '%08X -' % s9, 'FF FF 7F',  writeVar(s9)
 | 
			
		||||
    s10 = 0x00200000
 | 
			
		||||
    print '%08X -' % s10, '81 80 80 00', writeVar(s10)
 | 
			
		||||
    s11 = 0x08000000
 | 
			
		||||
    print '%08X -' % s11, 'C0 80 80 00', writeVar(s11)
 | 
			
		||||
    s12 = 0x0FFFFFFF
 | 
			
		||||
    print '%08X -' % s12, 'FF FF FF 7F', writeVar(s12)
 | 
			
		||||
              
 | 
			
		||||
              
 | 
			
		||||
              
 | 
			
		||||
             
 | 
			
		||||
             
 | 
			
		||||
             
 | 
			
		||||
           
 | 
			
		||||
           
 | 
			
		||||
           
 | 
			
		||||
          
 | 
			
		||||
          
 | 
			
		||||
          
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/DataTypeConverters.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/DataTypeConverters.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										287
									
								
								projekte/soundz/midifnord/midi/EventDispatcher.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								projekte/soundz/midifnord/midi/EventDispatcher.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,287 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
# std library
 | 
			
		||||
from struct import unpack
 | 
			
		||||
 | 
			
		||||
# custom
 | 
			
		||||
from DataTypeConverters import readBew, readVar, varLen, toBytes
 | 
			
		||||
 | 
			
		||||
# uhh I don't really like this, but there are so many constants to 
 | 
			
		||||
# import otherwise
 | 
			
		||||
from constants import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EventDispatcher:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __init__(self, outstream):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        The event dispatcher generates events on the outstream.
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        # internal values, don't mess with 'em directly
 | 
			
		||||
        self.outstream = outstream
 | 
			
		||||
        
 | 
			
		||||
        # public flags
 | 
			
		||||
 | 
			
		||||
        # A note_on with a velocity of 0x00 is actually the same as a 
 | 
			
		||||
        # note_off with a velocity of 0x40. When 
 | 
			
		||||
        # "convert_zero_velocity" is set, the zero velocity note_on's 
 | 
			
		||||
        # automatically gets converted into note_off's. This is a less 
 | 
			
		||||
        # suprising behaviour for those that are not into the intimate 
 | 
			
		||||
        # details of the midi spec.
 | 
			
		||||
        self.convert_zero_velocity = 1
 | 
			
		||||
        
 | 
			
		||||
        # If dispatch_continuos_controllers is true, continuos 
 | 
			
		||||
        # controllers gets dispatched to their defined handlers. Else 
 | 
			
		||||
        # they just trigger the "continuous_controller" event handler.
 | 
			
		||||
        self.dispatch_continuos_controllers = 1 # NOT IMPLEMENTED YET
 | 
			
		||||
        
 | 
			
		||||
        # If dispatch_meta_events is true, meta events get's dispatched 
 | 
			
		||||
        # to their defined events. Else they all they trigger the 
 | 
			
		||||
        # "meta_event" handler.
 | 
			
		||||
        self.dispatch_meta_events = 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def header(self, format, nTracks, division):
 | 
			
		||||
        "Triggers the header event"
 | 
			
		||||
        self.outstream.header(format, nTracks, division)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def start_of_track(self, current_track):
 | 
			
		||||
        "Triggers the start of track event"
 | 
			
		||||
        
 | 
			
		||||
        # I do this twice so that users can overwrite the 
 | 
			
		||||
        # start_of_track event handler without worrying whether the 
 | 
			
		||||
        # track number is updated correctly.
 | 
			
		||||
        self.outstream.set_current_track(current_track)
 | 
			
		||||
        self.outstream.start_of_track(current_track)
 | 
			
		||||
        
 | 
			
		||||
    
 | 
			
		||||
    def sysex_event(self, data):
 | 
			
		||||
        "Dispatcher for sysex events"
 | 
			
		||||
        self.outstream.sysex_event(data)
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    def eof(self):
 | 
			
		||||
        "End of file!"
 | 
			
		||||
        self.outstream.eof()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def update_time(self, new_time=0, relative=1):
 | 
			
		||||
        "Updates relative/absolute time."
 | 
			
		||||
        self.outstream.update_time(new_time, relative)
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
    def reset_time(self):
 | 
			
		||||
        "Updates relative/absolute time."
 | 
			
		||||
        self.outstream.reset_time()
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
    # Event dispatchers for similar types of events
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    def channel_messages(self, hi_nible, channel, data):
 | 
			
		||||
    
 | 
			
		||||
        "Dispatches channel messages"
 | 
			
		||||
        
 | 
			
		||||
        stream = self.outstream
 | 
			
		||||
        data = toBytes(data)
 | 
			
		||||
        
 | 
			
		||||
        if (NOTE_ON & 0xF0) == hi_nible:
 | 
			
		||||
            note, velocity = data
 | 
			
		||||
            # note_on with velocity 0x00 are same as note 
 | 
			
		||||
            # off with velocity 0x40 according to spec!
 | 
			
		||||
            if velocity==0 and self.convert_zero_velocity:
 | 
			
		||||
                stream.note_off(channel, note, 0x40)
 | 
			
		||||
            else:
 | 
			
		||||
                stream.note_on(channel, note, velocity)
 | 
			
		||||
        
 | 
			
		||||
        elif (NOTE_OFF & 0xF0) == hi_nible:
 | 
			
		||||
            note, velocity = data
 | 
			
		||||
            stream.note_off(channel, note, velocity)
 | 
			
		||||
        
 | 
			
		||||
        elif (AFTERTOUCH & 0xF0) == hi_nible:
 | 
			
		||||
            note, velocity = data
 | 
			
		||||
            stream.aftertouch(channel, note, velocity)
 | 
			
		||||
        
 | 
			
		||||
        elif (CONTINUOUS_CONTROLLER & 0xF0) == hi_nible:
 | 
			
		||||
            controller, value = data
 | 
			
		||||
            # A lot of the cc's are defined, so we trigger those directly
 | 
			
		||||
            if self.dispatch_continuos_controllers:
 | 
			
		||||
                self.continuous_controllers(channel, controller, value)
 | 
			
		||||
            else:
 | 
			
		||||
                stream.continuous_controller(channel, controller, value)
 | 
			
		||||
            
 | 
			
		||||
        elif (PATCH_CHANGE & 0xF0) == hi_nible:
 | 
			
		||||
            program = data[0]
 | 
			
		||||
            stream.patch_change(channel, program)
 | 
			
		||||
            
 | 
			
		||||
        elif (CHANNEL_PRESSURE & 0xF0) == hi_nible:
 | 
			
		||||
            pressure = data[0]
 | 
			
		||||
            stream.channel_pressure(channel, pressure)
 | 
			
		||||
            
 | 
			
		||||
        elif (PITCH_BEND & 0xF0) == hi_nible:
 | 
			
		||||
            hibyte, lobyte = data
 | 
			
		||||
            value = (hibyte<<7) + lobyte
 | 
			
		||||
            stream.pitch_bend(channel, value)
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
 | 
			
		||||
            raise ValueError, 'Illegal channel message!'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def continuous_controllers(self, channel, controller, value):
 | 
			
		||||
    
 | 
			
		||||
        "Dispatches channel messages"
 | 
			
		||||
 | 
			
		||||
        stream = self.outstream
 | 
			
		||||
        
 | 
			
		||||
        # I am not really shure if I ought to dispatch continuous controllers
 | 
			
		||||
        # There's so many of them that it can clutter up the OutStream 
 | 
			
		||||
        # classes.
 | 
			
		||||
        
 | 
			
		||||
        # So I just trigger the default event handler
 | 
			
		||||
        stream.continuous_controller(channel, controller, value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def system_commons(self, common_type, common_data):
 | 
			
		||||
    
 | 
			
		||||
        "Dispatches system common messages"
 | 
			
		||||
        
 | 
			
		||||
        stream = self.outstream
 | 
			
		||||
        
 | 
			
		||||
        # MTC Midi time code Quarter value
 | 
			
		||||
        if common_type == MTC:
 | 
			
		||||
            data = readBew(common_data)
 | 
			
		||||
            msg_type = (data & 0x07) >> 4
 | 
			
		||||
            values = (data & 0x0F)
 | 
			
		||||
            stream.midi_time_code(msg_type, values)
 | 
			
		||||
        
 | 
			
		||||
        elif common_type == SONG_POSITION_POINTER:
 | 
			
		||||
            hibyte, lobyte = toBytes(common_data)
 | 
			
		||||
            value = (hibyte<<7) + lobyte
 | 
			
		||||
            stream.song_position_pointer(value)
 | 
			
		||||
 | 
			
		||||
        elif common_type == SONG_SELECT:
 | 
			
		||||
            data = readBew(common_data)
 | 
			
		||||
            stream.song_select(data)
 | 
			
		||||
 | 
			
		||||
        elif common_type == TUNING_REQUEST:
 | 
			
		||||
            # no data then
 | 
			
		||||
            stream.tuning_request(time=None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def meta_event(self, meta_type, data):
 | 
			
		||||
        
 | 
			
		||||
        "Dispatches meta events"
 | 
			
		||||
        
 | 
			
		||||
        stream = self.outstream
 | 
			
		||||
        
 | 
			
		||||
        # SEQUENCE_NUMBER = 0x00 (00 02 ss ss (seq-number))
 | 
			
		||||
        if meta_type == SEQUENCE_NUMBER:
 | 
			
		||||
            number = readBew(data)
 | 
			
		||||
            stream.sequence_number(number)
 | 
			
		||||
        
 | 
			
		||||
        # TEXT = 0x01 (01 len text...)
 | 
			
		||||
        elif meta_type == TEXT:
 | 
			
		||||
            stream.text(data)
 | 
			
		||||
        
 | 
			
		||||
        # COPYRIGHT = 0x02 (02 len text...)
 | 
			
		||||
        elif meta_type == COPYRIGHT:
 | 
			
		||||
            stream.copyright(data)
 | 
			
		||||
        
 | 
			
		||||
        # SEQUENCE_NAME = 0x03 (03 len text...)
 | 
			
		||||
        elif meta_type == SEQUENCE_NAME:
 | 
			
		||||
            stream.sequence_name(data)
 | 
			
		||||
        
 | 
			
		||||
        # INSTRUMENT_NAME = 0x04 (04 len text...)
 | 
			
		||||
        elif meta_type == INSTRUMENT_NAME:
 | 
			
		||||
            stream.instrument_name(data)
 | 
			
		||||
        
 | 
			
		||||
        # LYRIC = 0x05 (05 len text...)
 | 
			
		||||
        elif meta_type == LYRIC:
 | 
			
		||||
            stream.lyric(data)
 | 
			
		||||
        
 | 
			
		||||
        # MARKER = 0x06 (06 len text...)
 | 
			
		||||
        elif meta_type == MARKER:
 | 
			
		||||
            stream.marker(data)
 | 
			
		||||
        
 | 
			
		||||
        # CUEPOINT = 0x07 (07 len text...)
 | 
			
		||||
        elif meta_type == CUEPOINT:
 | 
			
		||||
            stream.cuepoint(data)
 | 
			
		||||
        
 | 
			
		||||
        # PROGRAM_NAME = 0x08 (05 len text...)
 | 
			
		||||
        elif meta_type == PROGRAM_NAME:
 | 
			
		||||
            stream.program_name(data)
 | 
			
		||||
        
 | 
			
		||||
        # DEVICE_NAME = 0x09 (09 len text...)
 | 
			
		||||
        elif meta_type == DEVICE_NAME:
 | 
			
		||||
            stream.device_name(data)
 | 
			
		||||
        
 | 
			
		||||
        # MIDI_CH_PREFIX = 0x20 (20 01 channel)
 | 
			
		||||
        elif meta_type == MIDI_CH_PREFIX:
 | 
			
		||||
            channel = readBew(data)
 | 
			
		||||
            stream.midi_ch_prefix(channel)
 | 
			
		||||
        
 | 
			
		||||
        # MIDI_PORT  = 0x21 (21 01 port (legacy stuff))
 | 
			
		||||
        elif meta_type == MIDI_PORT:
 | 
			
		||||
            port = readBew(data)
 | 
			
		||||
            stream.midi_port(port)
 | 
			
		||||
        
 | 
			
		||||
        # END_OFF_TRACK = 0x2F (2F 00)
 | 
			
		||||
        elif meta_type == END_OF_TRACK:
 | 
			
		||||
            stream.end_of_track()
 | 
			
		||||
        
 | 
			
		||||
        # TEMPO = 0x51 (51 03 tt tt tt (tempo in us/quarternote))
 | 
			
		||||
        elif meta_type == TEMPO:
 | 
			
		||||
            b1, b2, b3 = toBytes(data)
 | 
			
		||||
            # uses 3 bytes to represent time between quarter 
 | 
			
		||||
            # notes in microseconds
 | 
			
		||||
            stream.tempo((b1<<16) + (b2<<8) + b3)
 | 
			
		||||
        
 | 
			
		||||
        # SMTP_OFFSET = 0x54 (54 05 hh mm ss ff xx)
 | 
			
		||||
        elif meta_type == SMTP_OFFSET:
 | 
			
		||||
            hour, minute, second, frame, framePart = toBytes(data)
 | 
			
		||||
            stream.smtp_offset(
 | 
			
		||||
                    hour, minute, second, frame, framePart)
 | 
			
		||||
        
 | 
			
		||||
        # TIME_SIGNATURE = 0x58 (58 04 nn dd cc bb)
 | 
			
		||||
        elif meta_type == TIME_SIGNATURE:
 | 
			
		||||
            nn, dd, cc, bb = toBytes(data)
 | 
			
		||||
            stream.time_signature(nn, dd, cc, bb)
 | 
			
		||||
        
 | 
			
		||||
        # KEY_SIGNATURE = 0x59 (59 02 sf mi)
 | 
			
		||||
        elif meta_type == KEY_SIGNATURE:
 | 
			
		||||
            sf, mi = toBytes(data)
 | 
			
		||||
            stream.key_signature(sf, mi)
 | 
			
		||||
        
 | 
			
		||||
        # SPECIFIC = 0x7F (Sequencer specific event)
 | 
			
		||||
        elif meta_type == SPECIFIC:
 | 
			
		||||
            meta_data = toBytes(data)
 | 
			
		||||
            stream.sequencer_specific(meta_data)
 | 
			
		||||
        
 | 
			
		||||
        # Handles any undefined meta events
 | 
			
		||||
        else: # undefined meta type
 | 
			
		||||
            meta_data = toBytes(data)
 | 
			
		||||
            stream.meta_event(meta_type, meta_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    from MidiToText import MidiToText
 | 
			
		||||
    
 | 
			
		||||
    outstream = MidiToText()
 | 
			
		||||
    dispatcher = EventDispatcher(outstream)
 | 
			
		||||
    dispatcher.channel_messages(NOTE_ON, 0x00, '\x40\x40')
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/EventDispatcher.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/EventDispatcher.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										192
									
								
								projekte/soundz/midifnord/midi/MidiFileParser.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								projekte/soundz/midifnord/midi/MidiFileParser.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,192 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
# std library
 | 
			
		||||
from struct import unpack
 | 
			
		||||
 | 
			
		||||
# uhh I don't really like this, but there are so many constants to 
 | 
			
		||||
# import otherwise
 | 
			
		||||
from constants import *
 | 
			
		||||
 | 
			
		||||
from EventDispatcher import EventDispatcher
 | 
			
		||||
 | 
			
		||||
class MidiFileParser:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    The MidiFileParser is the lowest level parser that see the data as 
 | 
			
		||||
    midi data. It generates events that gets triggered on the outstream.
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, raw_in, outstream):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        raw_data is the raw content of a midi file as a string.
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        # internal values, don't mess with 'em directly
 | 
			
		||||
        self.raw_in = raw_in
 | 
			
		||||
        self.dispatch = EventDispatcher(outstream)
 | 
			
		||||
 | 
			
		||||
        # Used to keep track of stuff
 | 
			
		||||
        self._running_status = None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def parseMThdChunk(self):
 | 
			
		||||
        
 | 
			
		||||
        "Parses the header chunk"
 | 
			
		||||
        
 | 
			
		||||
        raw_in = self.raw_in
 | 
			
		||||
 | 
			
		||||
        header_chunk_type = raw_in.nextSlice(4)
 | 
			
		||||
        header_chunk_zise = raw_in.readBew(4)
 | 
			
		||||
 | 
			
		||||
        # check if it is a proper midi file
 | 
			
		||||
        if header_chunk_type != 'MThd':
 | 
			
		||||
            raise TypeError, "It is not a valid midi file!"
 | 
			
		||||
 | 
			
		||||
        # Header values are at fixed locations, so no reason to be clever
 | 
			
		||||
        self.format = raw_in.readBew(2)
 | 
			
		||||
        self.nTracks = raw_in.readBew(2)
 | 
			
		||||
        self.division = raw_in.readBew(2)
 | 
			
		||||
        
 | 
			
		||||
        # Theoretically a header larger than 6 bytes can exist
 | 
			
		||||
        # but no one has seen one in the wild
 | 
			
		||||
        # But correctly ignore unknown data if it is though
 | 
			
		||||
        if header_chunk_zise > 6:
 | 
			
		||||
            raw_in.moveCursor(header_chunk_zise-6)
 | 
			
		||||
 | 
			
		||||
        # call the header event handler on the stream
 | 
			
		||||
        self.dispatch.header(self.format, self.nTracks, self.division)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def parseMTrkChunk(self):
 | 
			
		||||
        
 | 
			
		||||
        "Parses a track chunk. This is the most important part of the parser."
 | 
			
		||||
        
 | 
			
		||||
        # set time to 0 at start of a track
 | 
			
		||||
        self.dispatch.reset_time()
 | 
			
		||||
        
 | 
			
		||||
        dispatch = self.dispatch
 | 
			
		||||
        raw_in = self.raw_in
 | 
			
		||||
        
 | 
			
		||||
        # Trigger event at the start of a track
 | 
			
		||||
        dispatch.start_of_track(self._current_track)
 | 
			
		||||
        # position cursor after track header
 | 
			
		||||
        raw_in.moveCursor(4)
 | 
			
		||||
        # unsigned long is 4 bytes
 | 
			
		||||
        tracklength = raw_in.readBew(4)
 | 
			
		||||
        track_endposition = raw_in.getCursor() + tracklength # absolute position!
 | 
			
		||||
 | 
			
		||||
        while raw_in.getCursor() < track_endposition:
 | 
			
		||||
        
 | 
			
		||||
            # find relative time of the event
 | 
			
		||||
            time = raw_in.readVarLen()
 | 
			
		||||
            dispatch.update_time(time)
 | 
			
		||||
            
 | 
			
		||||
            # be aware of running status!!!!
 | 
			
		||||
            peak_ahead = raw_in.readBew(move_cursor=0)
 | 
			
		||||
            if (peak_ahead & 0x80): 
 | 
			
		||||
                # the status byte has the high bit set, so it
 | 
			
		||||
                # was not running data but proper status byte
 | 
			
		||||
                status = self._running_status = raw_in.readBew()
 | 
			
		||||
            else:
 | 
			
		||||
                # use that darn running status
 | 
			
		||||
                status = self._running_status
 | 
			
		||||
                # could it be illegal data ?? Do we need to test for that?
 | 
			
		||||
                # I need more example midi files to be shure.
 | 
			
		||||
                
 | 
			
		||||
                # Also, while I am almost certain that no realtime 
 | 
			
		||||
                # messages will pop up in a midi file, I might need to 
 | 
			
		||||
                # change my mind later.
 | 
			
		||||
 | 
			
		||||
            # we need to look at nibbles here
 | 
			
		||||
            hi_nible, lo_nible = status & 0xF0, status & 0x0F
 | 
			
		||||
            
 | 
			
		||||
            # match up with events
 | 
			
		||||
 | 
			
		||||
            # Is it a meta_event ??
 | 
			
		||||
            # these only exists in midi files, not in transmitted midi data
 | 
			
		||||
            # In transmitted data META_EVENT (0xFF) is a system reset
 | 
			
		||||
            if status == META_EVENT:
 | 
			
		||||
                meta_type = raw_in.readBew()
 | 
			
		||||
                meta_length = raw_in.readVarLen()
 | 
			
		||||
                meta_data = raw_in.nextSlice(meta_length)
 | 
			
		||||
                dispatch.meta_event(meta_type, meta_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            # Is it a sysex_event ??
 | 
			
		||||
            elif status == SYSTEM_EXCLUSIVE:
 | 
			
		||||
                # ignore sysex events
 | 
			
		||||
                sysex_length = raw_in.readVarLen()
 | 
			
		||||
                # don't read sysex terminator
 | 
			
		||||
                sysex_data = raw_in.nextSlice(sysex_length-1)
 | 
			
		||||
                # only read last data byte if it is a sysex terminator
 | 
			
		||||
                # It should allways be there, but better safe than sorry
 | 
			
		||||
                if raw_in.readBew(move_cursor=0) == END_OFF_EXCLUSIVE:
 | 
			
		||||
                    eo_sysex = raw_in.readBew()
 | 
			
		||||
                dispatch.sysex_event(sysex_data)
 | 
			
		||||
                # the sysex code has not been properly tested, and might be fishy!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            # is it a system common event?
 | 
			
		||||
            elif hi_nible == 0xF0: # Hi bits are set then
 | 
			
		||||
                data_sizes = {
 | 
			
		||||
                    MTC:1,
 | 
			
		||||
                    SONG_POSITION_POINTER:2,
 | 
			
		||||
                    SONG_SELECT:1,
 | 
			
		||||
                }
 | 
			
		||||
                data_size = data_sizes.get(hi_nible, 0)
 | 
			
		||||
                common_data = raw_in.nextSlice(data_size)
 | 
			
		||||
                common_type = lo_nible
 | 
			
		||||
                dispatch.system_common(common_type, common_data)
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            # Oh! Then it must be a midi event (channel voice message)
 | 
			
		||||
            else:
 | 
			
		||||
                data_sizes = {
 | 
			
		||||
                    PATCH_CHANGE:1,
 | 
			
		||||
                    CHANNEL_PRESSURE:1,
 | 
			
		||||
                    NOTE_OFF:2,
 | 
			
		||||
                    NOTE_ON:2,
 | 
			
		||||
                    AFTERTOUCH:2,
 | 
			
		||||
                    CONTINUOUS_CONTROLLER:2,
 | 
			
		||||
                    PITCH_BEND:2,
 | 
			
		||||
                }
 | 
			
		||||
                data_size = data_sizes.get(hi_nible, 0)
 | 
			
		||||
                channel_data = raw_in.nextSlice(data_size)
 | 
			
		||||
                event_type, channel = hi_nible, lo_nible
 | 
			
		||||
                dispatch.channel_messages(event_type, channel, channel_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def parseMTrkChunks(self):
 | 
			
		||||
        "Parses all track chunks."
 | 
			
		||||
        for t in range(self.nTracks):
 | 
			
		||||
            self._current_track = t
 | 
			
		||||
            self.parseMTrkChunk() # this is where it's at!
 | 
			
		||||
        self.dispatch.eof()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    # get data
 | 
			
		||||
    test_file = 'test/midifiles/minimal.mid'
 | 
			
		||||
    test_file = 'test/midifiles/cubase-minimal.mid'
 | 
			
		||||
    test_file = 'test/midifiles/Lola.mid'
 | 
			
		||||
#    f = open(test_file, 'rb')
 | 
			
		||||
#    raw_data = f.read()
 | 
			
		||||
#    f.close()
 | 
			
		||||
#    
 | 
			
		||||
#    
 | 
			
		||||
#    # do parsing
 | 
			
		||||
    from MidiToText import MidiToText
 | 
			
		||||
    from RawInstreamFile import RawInstreamFile
 | 
			
		||||
 | 
			
		||||
    midi_in = MidiFileParser(RawInstreamFile(test_file), MidiToText())
 | 
			
		||||
    midi_in.parseMThdChunk()
 | 
			
		||||
    midi_in.parseMTrkChunks()
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiFileParser.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiFileParser.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										55
									
								
								projekte/soundz/midifnord/midi/MidiInFile.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								projekte/soundz/midifnord/midi/MidiInFile.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
from RawInstreamFile import RawInstreamFile
 | 
			
		||||
from MidiFileParser import MidiFileParser
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MidiInFile:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    Parses a midi file, and triggers the midi events on the outStream 
 | 
			
		||||
    object.
 | 
			
		||||
    
 | 
			
		||||
    Get example data from a minimal midi file, generated with cubase.
 | 
			
		||||
    >>> test_file = 'C:/Documents and Settings/maxm/Desktop/temp/midi/src/midi/tests/midifiles/minimal-cubase-type0.mid'
 | 
			
		||||
    
 | 
			
		||||
    Do parsing, and generate events with MidiToText,
 | 
			
		||||
    so we can see what a minimal midi file contains
 | 
			
		||||
    >>> from MidiToText import MidiToText
 | 
			
		||||
    >>> midi_in = MidiInFile(MidiToText(), test_file)
 | 
			
		||||
    >>> midi_in.read()
 | 
			
		||||
    format: 0, nTracks: 1, division: 480
 | 
			
		||||
    ----------------------------------
 | 
			
		||||
    <BLANKLINE>
 | 
			
		||||
    Start - track #0
 | 
			
		||||
    sequence_name: Type 0
 | 
			
		||||
    tempo: 500000
 | 
			
		||||
    time_signature: 4 2 24 8
 | 
			
		||||
    note_on  - ch:00,  note:48,  vel:64 time:0
 | 
			
		||||
    note_off - ch:00,  note:48,  vel:40 time:480
 | 
			
		||||
    End of track
 | 
			
		||||
    <BLANKLINE>
 | 
			
		||||
    End of file
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, outStream, infile):
 | 
			
		||||
        # these could also have been mixins, would that be better? Nah!
 | 
			
		||||
        self.raw_in = RawInstreamFile(infile)
 | 
			
		||||
        self.parser = MidiFileParser(self.raw_in, outStream)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def read(self):
 | 
			
		||||
        "Start parsing the file"
 | 
			
		||||
        p = self.parser
 | 
			
		||||
        p.parseMThdChunk()
 | 
			
		||||
        p.parseMTrkChunks()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def setData(self, data=''):
 | 
			
		||||
        "Sets the data from a plain string"
 | 
			
		||||
        self.raw_in.setData(data)
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiInFile.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiInFile.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										52
									
								
								projekte/soundz/midifnord/midi/MidiInStream.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								projekte/soundz/midifnord/midi/MidiInStream.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
from MidiOutStream import MidiOutStream
 | 
			
		||||
 | 
			
		||||
class MidiInStream:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Takes midi events from the midi input and calls the apropriate
 | 
			
		||||
    method in the eventhandler object
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, midiOutStream, device):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        Sets a default output stream, and sets the device from where
 | 
			
		||||
        the input comes
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        if midiOutStream is None:
 | 
			
		||||
            self.midiOutStream = MidiOutStream()
 | 
			
		||||
        else:
 | 
			
		||||
            self.midiOutStream = midiOutStream
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def close(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        Stop the MidiInstream
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def read(self, time=0):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        Start the MidiInstream.
 | 
			
		||||
 | 
			
		||||
        "time" sets timer to specific start value.
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def resetTimer(self, time=0):
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        Resets the timer, probably a good idea if there is some kind
 | 
			
		||||
        of looping going on
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										448
									
								
								projekte/soundz/midifnord/midi/MidiOutFile.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										448
									
								
								projekte/soundz/midifnord/midi/MidiOutFile.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,448 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
from MidiOutStream import MidiOutStream
 | 
			
		||||
from RawOutstreamFile import RawOutstreamFile
 | 
			
		||||
 | 
			
		||||
from constants import *
 | 
			
		||||
from DataTypeConverters import fromBytes, writeVar
 | 
			
		||||
 | 
			
		||||
class MidiOutFile(MidiOutStream):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    MidiOutFile is an eventhandler that subclasses MidiOutStream.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __init__(self, raw_out=''):
 | 
			
		||||
 | 
			
		||||
        self.raw_out = RawOutstreamFile(raw_out)
 | 
			
		||||
        MidiOutStream.__init__(self)
 | 
			
		||||
        
 | 
			
		||||
    
 | 
			
		||||
    def write(self):
 | 
			
		||||
        self.raw_out.write()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def event_slice(self, slc):
 | 
			
		||||
        """
 | 
			
		||||
        Writes the slice of an event to the current track. Correctly 
 | 
			
		||||
        inserting a varlen timestamp too.
 | 
			
		||||
        """
 | 
			
		||||
        trk = self._current_track_buffer
 | 
			
		||||
        trk.writeVarLen(self.rel_time())
 | 
			
		||||
        trk.writeSlice(slc)
 | 
			
		||||
        
 | 
			
		||||
    
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Midi events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_on(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        note, velocity: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        slc = fromBytes([NOTE_ON + channel, note, velocity])
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_off(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        note, velocity: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        slc = fromBytes([NOTE_OFF + channel, note, velocity])
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def aftertouch(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        note, velocity: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        slc = fromBytes([AFTERTOUCH + channel, note, velocity])
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def continuous_controller(self, channel, controller, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        controller, value: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        slc = fromBytes([CONTINUOUS_CONTROLLER + channel, controller, value])
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
        # These should probably be implemented
 | 
			
		||||
        # http://users.argonet.co.uk/users/lenny/midi/tech/spec.html#ctrlnums
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def patch_change(self, channel, patch):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        patch: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        slc = fromBytes([PATCH_CHANGE + channel, patch])
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def channel_pressure(self, channel, pressure):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        pressure: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        slc = fromBytes([CHANNEL_PRESSURE + channel, pressure])
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def pitch_bend(self, channel, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        value: 0-16383
 | 
			
		||||
        """
 | 
			
		||||
        msb = (value>>7) & 0xFF
 | 
			
		||||
        lsb = value & 0xFF
 | 
			
		||||
        slc = fromBytes([PITCH_BEND + channel, msb, lsb])
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## System Exclusive
 | 
			
		||||
 | 
			
		||||
#    def sysex_slice(sysex_type, data):
 | 
			
		||||
#        ""
 | 
			
		||||
#        sysex_len = writeVar(len(data)+1)
 | 
			
		||||
#        self.event_slice(SYSTEM_EXCLUSIVE + sysex_len + data + END_OFF_EXCLUSIVE)
 | 
			
		||||
#
 | 
			
		||||
    def system_exclusive(self, data):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        data: list of values in range(128)
 | 
			
		||||
        """
 | 
			
		||||
        sysex_len = writeVar(len(data)+1)
 | 
			
		||||
        self.event_slice(chr(SYSTEM_EXCLUSIVE) + sysex_len + data + chr(END_OFF_EXCLUSIVE))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Common events
 | 
			
		||||
 | 
			
		||||
    def midi_time_code(self, msg_type, values):
 | 
			
		||||
        """
 | 
			
		||||
        msg_type: 0-7
 | 
			
		||||
        values: 0-15
 | 
			
		||||
        """
 | 
			
		||||
        value = (msg_type<<4) + values
 | 
			
		||||
        self.event_slice(fromBytes([MIDI_TIME_CODE, value]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_position_pointer(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: 0-16383
 | 
			
		||||
        """
 | 
			
		||||
        lsb = (value & 0x7F)
 | 
			
		||||
        msb = (value >> 7) & 0x7F
 | 
			
		||||
        self.event_slice(fromBytes([SONG_POSITION_POINTER, lsb, msb]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_select(self, songNumber):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        songNumber: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        self.event_slice(fromBytes([SONG_SELECT, songNumber]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tuning_request(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        self.event_slice(chr(TUNING_REQUEST))
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
    #########################
 | 
			
		||||
    # header does not really belong here. But anyhoo!!!
 | 
			
		||||
    
 | 
			
		||||
    def header(self, format=0, nTracks=1, division=96):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        format: type of midi file in [0,1,2]
 | 
			
		||||
        nTracks: number of tracks. 1 track for type 0 file
 | 
			
		||||
        division: timing division ie. 96 ppq.
 | 
			
		||||
        
 | 
			
		||||
        """        
 | 
			
		||||
        raw = self.raw_out
 | 
			
		||||
        raw.writeSlice('MThd')
 | 
			
		||||
        bew = raw.writeBew
 | 
			
		||||
        bew(6, 4) # header size
 | 
			
		||||
        bew(format, 2)
 | 
			
		||||
        bew(nTracks, 2)
 | 
			
		||||
        bew(division, 2)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def eof(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        End of file. No more events to be processed.
 | 
			
		||||
        """
 | 
			
		||||
        # just write the file then.
 | 
			
		||||
        self.write()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## meta events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def meta_slice(self, meta_type, data_slice):
 | 
			
		||||
        "Writes a meta event"
 | 
			
		||||
        slc = fromBytes([META_EVENT, meta_type]) + \
 | 
			
		||||
                         writeVar(len(data_slice)) +  data_slice
 | 
			
		||||
        self.event_slice(slc)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def meta_event(self, meta_type, data):
 | 
			
		||||
        """
 | 
			
		||||
        Handles any undefined meta events
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(meta_type, fromBytes(data))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def start_of_track(self, n_track=0):
 | 
			
		||||
        """
 | 
			
		||||
        n_track: number of track
 | 
			
		||||
        """
 | 
			
		||||
        self._current_track_buffer = RawOutstreamFile()
 | 
			
		||||
        self.reset_time()
 | 
			
		||||
        self._current_track += 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def end_of_track(self):
 | 
			
		||||
        """
 | 
			
		||||
        Writes the track to the buffer.
 | 
			
		||||
        """
 | 
			
		||||
        raw = self.raw_out
 | 
			
		||||
        raw.writeSlice(TRACK_HEADER)
 | 
			
		||||
        track_data = self._current_track_buffer.getvalue()
 | 
			
		||||
        # wee need to know size of track data.
 | 
			
		||||
        eot_slice = writeVar(self.rel_time()) + fromBytes([META_EVENT, END_OF_TRACK, 0])
 | 
			
		||||
        raw.writeBew(len(track_data)+len(eot_slice), 4)
 | 
			
		||||
        # then write
 | 
			
		||||
        raw.writeSlice(track_data)
 | 
			
		||||
        raw.writeSlice(eot_slice)
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_number(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: 0-65535
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(meta_type, writeBew(value, 2))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def text(self, text):
 | 
			
		||||
        """
 | 
			
		||||
        Text event
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(TEXT, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def copyright(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        Copyright notice
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(COPYRIGHT, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_name(self, text):
 | 
			
		||||
        """
 | 
			
		||||
        Sequence/track name
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(SEQUENCE_NAME, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def instrument_name(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(INSTRUMENT_NAME, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def lyric(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(LYRIC, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def marker(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(MARKER, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def cuepoint(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(CUEPOINT, text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_ch_prefix(self, channel):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: midi channel for subsequent data
 | 
			
		||||
        (deprecated in the spec)
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(MIDI_CH_PREFIX, chr(channel))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_port(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: Midi port (deprecated in the spec)
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(MIDI_CH_PREFIX, chr(value))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tempo(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: 0-2097151
 | 
			
		||||
        tempo in us/quarternote
 | 
			
		||||
        (to calculate value from bpm: int(60,000,000.00 / BPM))
 | 
			
		||||
        """
 | 
			
		||||
        hb, mb, lb = (value>>16 & 0xff), (value>>8 & 0xff), (value & 0xff)
 | 
			
		||||
        self.meta_slice(TEMPO, fromBytes([hb, mb, lb]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def smtp_offset(self, hour, minute, second, frame, framePart):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        hour,
 | 
			
		||||
        minute,
 | 
			
		||||
        second: 3 bytes specifying the hour (0-23), minutes (0-59) and 
 | 
			
		||||
                seconds (0-59), respectively. The hour should be 
 | 
			
		||||
                encoded with the SMPTE format, just as it is in MIDI 
 | 
			
		||||
                Time Code.
 | 
			
		||||
        frame: A byte specifying the number of frames per second (one 
 | 
			
		||||
               of : 24, 25, 29, 30).
 | 
			
		||||
        framePart: A byte specifying the number of fractional frames, 
 | 
			
		||||
                   in 100ths of a frame (even in SMPTE-based tracks 
 | 
			
		||||
                   using a different frame subdivision, defined in the 
 | 
			
		||||
                   MThd chunk).
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(SMTP_OFFSET, fromBytes([hour, minute, second, frame, framePart]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def time_signature(self, nn, dd, cc, bb):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        nn: Numerator of the signature as notated on sheet music
 | 
			
		||||
        dd: Denominator of the signature as notated on sheet music
 | 
			
		||||
            The denominator is a negative power of 2: 2 = quarter 
 | 
			
		||||
            note, 3 = eighth, etc.
 | 
			
		||||
        cc: The number of MIDI clocks in a metronome click
 | 
			
		||||
        bb: The number of notated 32nd notes in a MIDI quarter note 
 | 
			
		||||
            (24 MIDI clocks)        
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(TIME_SIGNATURE, fromBytes([nn, dd, cc, bb]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def key_signature(self, sf, mi):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        sf: is a byte specifying the number of flats (-ve) or sharps 
 | 
			
		||||
            (+ve) that identifies the key signature (-7 = 7 flats, -1 
 | 
			
		||||
            = 1 flat, 0 = key of C, 1 = 1 sharp, etc).
 | 
			
		||||
        mi: is a byte specifying a major (0) or minor (1) key.
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(KEY_SIGNATURE, fromBytes([sf, mi]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequencer_specific(self, data):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        data: The data as byte values
 | 
			
		||||
        """
 | 
			
		||||
        self.meta_slice(SEQUENCER_SPECIFIC, data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#    #####################
 | 
			
		||||
#    ## realtime events
 | 
			
		||||
 | 
			
		||||
#    These are of no use in a midi file, so they are ignored!!!
 | 
			
		||||
 | 
			
		||||
#    def timing_clock(self):
 | 
			
		||||
#    def song_start(self):
 | 
			
		||||
#    def song_stop(self):
 | 
			
		||||
#    def song_continue(self):
 | 
			
		||||
#    def active_sensing(self):
 | 
			
		||||
#    def system_reset(self):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    out_file = 'test/midifiles/midiout.mid'
 | 
			
		||||
    midi = MidiOutFile(out_file)
 | 
			
		||||
 | 
			
		||||
#format: 0, nTracks: 1, division: 480
 | 
			
		||||
#----------------------------------
 | 
			
		||||
#
 | 
			
		||||
#Start - track #0
 | 
			
		||||
#sequence_name: Type 0
 | 
			
		||||
#tempo: 500000
 | 
			
		||||
#time_signature: 4 2 24 8
 | 
			
		||||
#note_on  - ch:00,  note:48,  vel:64 time:0
 | 
			
		||||
#note_off - ch:00,  note:48,  vel:40 time:480
 | 
			
		||||
#End of track
 | 
			
		||||
#
 | 
			
		||||
#End of file
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    midi.header(0, 1, 480)
 | 
			
		||||
    
 | 
			
		||||
    midi.start_of_track()
 | 
			
		||||
    midi.sequence_name('Type 0')
 | 
			
		||||
    midi.tempo(750000)
 | 
			
		||||
    midi.time_signature(4, 2, 24, 8)
 | 
			
		||||
    ch = 0
 | 
			
		||||
    for i in range(127):
 | 
			
		||||
        midi.note_on(ch, i, 0x64)
 | 
			
		||||
        midi.update_time(96)
 | 
			
		||||
        midi.note_off(ch, i, 0x40)
 | 
			
		||||
        midi.update_time(0)
 | 
			
		||||
    
 | 
			
		||||
    midi.update_time(0)
 | 
			
		||||
    midi.end_of_track()
 | 
			
		||||
    
 | 
			
		||||
    midi.eof() # currently optional, should it do the write instead of write??
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    midi.write()
 | 
			
		||||
							
								
								
									
										471
									
								
								projekte/soundz/midifnord/midi/MidiOutStream.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										471
									
								
								projekte/soundz/midifnord/midi/MidiOutStream.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,471 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
class MidiOutStream:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    MidiOutstream is Basically an eventhandler. It is the most central
 | 
			
		||||
    class in the Midi library. You use it both for writing events to
 | 
			
		||||
    an output stream, and as an event handler for an input stream.
 | 
			
		||||
 | 
			
		||||
    This makes it extremely easy to take input from one stream and
 | 
			
		||||
    send it to another. Ie. if you want to read a Midi file, do some
 | 
			
		||||
    processing, and send it to a midiport.
 | 
			
		||||
 | 
			
		||||
    All time values are in absolute values from the opening of a
 | 
			
		||||
    stream. To calculate time values, please use the MidiTime and
 | 
			
		||||
    MidiDeltaTime classes.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        
 | 
			
		||||
        # the time is rather global, so it needs to be stored 
 | 
			
		||||
        # here. Otherwise there would be no really simple way to 
 | 
			
		||||
        # calculate it. The alternative would be to have each event 
 | 
			
		||||
        # handler do it. That sucks even worse!
 | 
			
		||||
        self._absolute_time = 0
 | 
			
		||||
        self._relative_time = 0
 | 
			
		||||
        self._current_track = 0
 | 
			
		||||
        self._running_status = None
 | 
			
		||||
 | 
			
		||||
    # time handling event handlers. They should be overwritten with care
 | 
			
		||||
 | 
			
		||||
    def update_time(self, new_time=0, relative=1):
 | 
			
		||||
        """
 | 
			
		||||
        Updates the time, if relative is true, new_time is relative, 
 | 
			
		||||
        else it's absolute.
 | 
			
		||||
        """
 | 
			
		||||
        if relative:
 | 
			
		||||
            self._relative_time = new_time
 | 
			
		||||
            self._absolute_time += new_time
 | 
			
		||||
        else:
 | 
			
		||||
            self._relative_time = new_time - self._absolute_time
 | 
			
		||||
            self._absolute_time = new_time
 | 
			
		||||
 | 
			
		||||
    def reset_time(self):
 | 
			
		||||
        """
 | 
			
		||||
        reset time to 0
 | 
			
		||||
        """
 | 
			
		||||
        self._relative_time = 0
 | 
			
		||||
        self._absolute_time = 0
 | 
			
		||||
        
 | 
			
		||||
    def rel_time(self):
 | 
			
		||||
        "Returns the relative time"
 | 
			
		||||
        return self._relative_time
 | 
			
		||||
 | 
			
		||||
    def abs_time(self):
 | 
			
		||||
        "Returns the absolute time"
 | 
			
		||||
        return self._absolute_time
 | 
			
		||||
 | 
			
		||||
    # running status methods
 | 
			
		||||
    
 | 
			
		||||
    def reset_run_stat(self):
 | 
			
		||||
        "Invalidates the running status"
 | 
			
		||||
        self._running_status = None
 | 
			
		||||
 | 
			
		||||
    def set_run_stat(self, new_status):
 | 
			
		||||
        "Set the new running status"
 | 
			
		||||
        self._running_status = new_status
 | 
			
		||||
 | 
			
		||||
    def get_run_stat(self):
 | 
			
		||||
        "Set the new running status"
 | 
			
		||||
        return self._running_status
 | 
			
		||||
 | 
			
		||||
    # track handling event handlers
 | 
			
		||||
    
 | 
			
		||||
    def set_current_track(self, new_track):
 | 
			
		||||
        "Sets the current track number"
 | 
			
		||||
        self._current_track = new_track
 | 
			
		||||
    
 | 
			
		||||
    def get_current_track(self):
 | 
			
		||||
        "Returns the current track number"
 | 
			
		||||
        return self._current_track
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Midi events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def channel_message(self, message_type, channel, data):
 | 
			
		||||
        """The default event handler for channel messages"""
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_on(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        note, velocity: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_off(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        note, velocity: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def aftertouch(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        note, velocity: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def continuous_controller(self, channel, controller, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        controller, value: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def patch_change(self, channel, patch):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        patch: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def channel_pressure(self, channel, pressure):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        pressure: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def pitch_bend(self, channel, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: 0-15
 | 
			
		||||
        value: 0-16383
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## System Exclusive
 | 
			
		||||
 | 
			
		||||
    def system_exclusive(self, data):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        data: list of values in range(128)
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Common events
 | 
			
		||||
 | 
			
		||||
    def song_position_pointer(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: 0-16383
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_select(self, songNumber):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        songNumber: 0-127
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tuning_request(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
    def midi_time_code(self, msg_type, values):
 | 
			
		||||
        """
 | 
			
		||||
        msg_type: 0-7
 | 
			
		||||
        values: 0-15
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #########################
 | 
			
		||||
    # header does not really belong here. But anyhoo!!!
 | 
			
		||||
    
 | 
			
		||||
    def header(self, format=0, nTracks=1, division=96):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        format: type of midi file in [1,2]
 | 
			
		||||
        nTracks: number of tracks
 | 
			
		||||
        division: timing division
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def eof(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        End of file. No more events to be processed.
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## meta events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def meta_event(self, meta_type, data):
 | 
			
		||||
        
 | 
			
		||||
        """
 | 
			
		||||
        Handles any undefined meta events
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def start_of_track(self, n_track=0):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        n_track: number of track
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def end_of_track(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        n_track: number of track
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_number(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: 0-16383
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def text(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        Text event
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def copyright(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        Copyright notice
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_name(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        Sequence/track name
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def instrument_name(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def lyric(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def marker(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def cuepoint(self, text):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        text: string
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_ch_prefix(self, channel):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        channel: midi channel for subsequent data (deprecated in the spec)
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_port(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: Midi port (deprecated in the spec)
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tempo(self, value):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        value: 0-2097151
 | 
			
		||||
        tempo in us/quarternote
 | 
			
		||||
        (to calculate value from bpm: int(60,000,000.00 / BPM))
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def smtp_offset(self, hour, minute, second, frame, framePart):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        hour,
 | 
			
		||||
        minute,
 | 
			
		||||
        second: 3 bytes specifying the hour (0-23), minutes (0-59) and 
 | 
			
		||||
                seconds (0-59), respectively. The hour should be 
 | 
			
		||||
                encoded with the SMPTE format, just as it is in MIDI 
 | 
			
		||||
                Time Code.
 | 
			
		||||
        frame: A byte specifying the number of frames per second (one 
 | 
			
		||||
               of : 24, 25, 29, 30).
 | 
			
		||||
        framePart: A byte specifying the number of fractional frames, 
 | 
			
		||||
                   in 100ths of a frame (even in SMPTE-based tracks 
 | 
			
		||||
                   using a different frame subdivision, defined in the 
 | 
			
		||||
                   MThd chunk).
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def time_signature(self, nn, dd, cc, bb):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        nn: Numerator of the signature as notated on sheet music
 | 
			
		||||
        dd: Denominator of the signature as notated on sheet music
 | 
			
		||||
            The denominator is a negative power of 2: 2 = quarter 
 | 
			
		||||
            note, 3 = eighth, etc.
 | 
			
		||||
        cc: The number of MIDI clocks in a metronome click
 | 
			
		||||
        bb: The number of notated 32nd notes in a MIDI quarter note 
 | 
			
		||||
            (24 MIDI clocks)        
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def key_signature(self, sf, mi):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        sf: is a byte specifying the number of flats (-ve) or sharps 
 | 
			
		||||
            (+ve) that identifies the key signature (-7 = 7 flats, -1 
 | 
			
		||||
            = 1 flat, 0 = key of C, 1 = 1 sharp, etc).
 | 
			
		||||
        mi: is a byte specifying a major (0) or minor (1) key.
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequencer_specific(self, data):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        data: The data as byte values
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## realtime events
 | 
			
		||||
 | 
			
		||||
    def timing_clock(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_start(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_stop(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_continue(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def active_sensing(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def system_reset(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        No values passed
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    midiOut = MidiOutStream()
 | 
			
		||||
    midiOut.update_time(0,0)
 | 
			
		||||
    midiOut.note_on(0, 63, 127)
 | 
			
		||||
    midiOut.note_off(0, 63, 127)
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiOutStream.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiOutStream.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										179
									
								
								projekte/soundz/midifnord/midi/MidiToText.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								projekte/soundz/midifnord/midi/MidiToText.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,179 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
from MidiOutStream import MidiOutStream
 | 
			
		||||
class MidiToText(MidiOutStream):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    This class renders a midi file as text. It is mostly used for debugging
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    #############################
 | 
			
		||||
    # channel events
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    def channel_message(self, message_type, channel, data):
 | 
			
		||||
        """The default event handler for channel messages"""
 | 
			
		||||
        print 'message_type:%X, channel:%X, data size:%X' % (message_type, channel, len(data))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_on(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
        print 'note_on  - ch:%02X,  note:%02X,  vel:%02X time:%s' % (channel, note, velocity, self.rel_time())
 | 
			
		||||
 | 
			
		||||
    def note_off(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
        print 'note_off - ch:%02X,  note:%02X,  vel:%02X time:%s' % (channel, note, velocity, self.rel_time())
 | 
			
		||||
 | 
			
		||||
    def aftertouch(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
        print 'aftertouch', channel, note, velocity
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def continuous_controller(self, channel, controller, value):
 | 
			
		||||
        print 'controller - ch: %02X, cont: #%02X, value: %02X' % (channel, controller, value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def patch_change(self, channel, patch):
 | 
			
		||||
        print 'patch_change - ch:%02X, patch:%02X' % (channel, patch)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def channel_pressure(self, channel, pressure):
 | 
			
		||||
        print 'channel_pressure', channel, pressure
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def pitch_bend(self, channel, value):
 | 
			
		||||
        print 'pitch_bend ch:%s, value:%s' % (channel, value)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Common events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def system_exclusive(self, data):
 | 
			
		||||
        print 'system_exclusive - data size: %s' % len(date)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_position_pointer(self, value):
 | 
			
		||||
        print 'song_position_pointer: %s' % value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_select(self, songNumber):
 | 
			
		||||
        print 'song_select: %s' % songNumber
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tuning_request(self):
 | 
			
		||||
        print 'tuning_request'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_time_code(self, msg_type, values):
 | 
			
		||||
        print 'midi_time_code - msg_type: %s, values: %s' % (msg_type, values)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #########################
 | 
			
		||||
    # header does not really belong here. But anyhoo!!!
 | 
			
		||||
 | 
			
		||||
    def header(self, format=0, nTracks=1, division=96):
 | 
			
		||||
        print 'format: %s, nTracks: %s, division: %s' % (format, nTracks, division)
 | 
			
		||||
        print '----------------------------------'
 | 
			
		||||
        print ''
 | 
			
		||||
 | 
			
		||||
    def eof(self):
 | 
			
		||||
        print 'End of file'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def start_of_track(self, n_track=0):
 | 
			
		||||
        print 'Start - track #%s' % n_track
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def end_of_track(self):
 | 
			
		||||
        print 'End of track'
 | 
			
		||||
        print ''
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    ###############
 | 
			
		||||
    # sysex event
 | 
			
		||||
 | 
			
		||||
    def sysex_event(self, data):
 | 
			
		||||
        print 'sysex_event - datasize: %X' % len(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## meta events
 | 
			
		||||
 | 
			
		||||
    def meta_event(self, meta_type, data):
 | 
			
		||||
        print 'undefined_meta_event:', meta_type, len(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_number(self, value):
 | 
			
		||||
        print 'sequence_number', number
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def text(self, text):
 | 
			
		||||
        print 'text', text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def copyright(self, text):
 | 
			
		||||
        print 'copyright', text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_name(self, text):
 | 
			
		||||
        print 'sequence_name:', text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def instrument_name(self, text):
 | 
			
		||||
        print 'instrument_name:', text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def lyric(self, text):
 | 
			
		||||
        print 'lyric', text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def marker(self, text):
 | 
			
		||||
        print 'marker', text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def cuepoint(self, text):
 | 
			
		||||
        print 'cuepoint', text
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_ch_prefix(self, channel):
 | 
			
		||||
        print 'midi_ch_prefix', channel
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_port(self, value):
 | 
			
		||||
        print 'midi_port:', value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tempo(self, value):
 | 
			
		||||
        print 'tempo:', value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def smtp_offset(self, hour, minute, second, frame, framePart):
 | 
			
		||||
        print 'smtp_offset', hour, minute, second, frame, framePart
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def time_signature(self, nn, dd, cc, bb):
 | 
			
		||||
        print 'time_signature:', nn, dd, cc, bb
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def key_signature(self, sf, mi):
 | 
			
		||||
        print 'key_signature', sf, mi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequencer_specific(self, data):
 | 
			
		||||
        print 'sequencer_specific', len(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    # get data
 | 
			
		||||
    test_file = 'test/midifiles/minimal.mid'
 | 
			
		||||
    f = open(test_file, 'rb')
 | 
			
		||||
    
 | 
			
		||||
    # do parsing
 | 
			
		||||
    from MidiInFile import MidiInFile
 | 
			
		||||
    midiIn = MidiInFile(MidiToText(), f)
 | 
			
		||||
    midiIn.read()
 | 
			
		||||
    f.close()
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiToText.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/MidiToText.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										108
									
								
								projekte/soundz/midifnord/midi/RawInstreamFile.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								projekte/soundz/midifnord/midi/RawInstreamFile.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
# standard library imports
 | 
			
		||||
from types import StringType
 | 
			
		||||
from struct import unpack
 | 
			
		||||
 | 
			
		||||
# custom import
 | 
			
		||||
from DataTypeConverters import readBew, readVar, varLen
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RawInstreamFile:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    It parses and reads data from an input file. It takes care of big 
 | 
			
		||||
    endianess, and keeps track of the cursor position. The midi parser 
 | 
			
		||||
    only reads from this object. Never directly from the file.
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    def __init__(self, infile=''):
 | 
			
		||||
        """ 
 | 
			
		||||
        If 'file' is a string we assume it is a path and read from 
 | 
			
		||||
        that file.
 | 
			
		||||
        If it is a file descriptor we read from the file, but we don't 
 | 
			
		||||
        close it.
 | 
			
		||||
        Midi files are usually pretty small, so it should be safe to 
 | 
			
		||||
        copy them into memory.
 | 
			
		||||
        """
 | 
			
		||||
        if infile:
 | 
			
		||||
            if isinstance(infile, StringType):
 | 
			
		||||
                infile = open(infile, 'rb')
 | 
			
		||||
                self.data = infile.read()
 | 
			
		||||
                infile.close()
 | 
			
		||||
            else:
 | 
			
		||||
                # don't close the f
 | 
			
		||||
                self.data = infile.read()
 | 
			
		||||
        else:
 | 
			
		||||
            self.data = ''
 | 
			
		||||
        # start at beginning ;-)
 | 
			
		||||
        self.cursor = 0
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # setting up data manually
 | 
			
		||||
    
 | 
			
		||||
    def setData(self, data=''):
 | 
			
		||||
        "Sets the data from a string."
 | 
			
		||||
        self.data = data
 | 
			
		||||
    
 | 
			
		||||
    # cursor operations
 | 
			
		||||
 | 
			
		||||
    def setCursor(self, position=0):
 | 
			
		||||
        "Sets the absolute position if the cursor"
 | 
			
		||||
        self.cursor = position
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def getCursor(self):
 | 
			
		||||
        "Returns the value of the cursor"
 | 
			
		||||
        return self.cursor
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
    def moveCursor(self, relative_position=0):
 | 
			
		||||
        "Moves the cursor to a new relative position"
 | 
			
		||||
        self.cursor += relative_position
 | 
			
		||||
 | 
			
		||||
    # native data reading functions
 | 
			
		||||
        
 | 
			
		||||
    def nextSlice(self, length, move_cursor=1):
 | 
			
		||||
        "Reads the next text slice from the raw data, with length"
 | 
			
		||||
        c = self.cursor
 | 
			
		||||
        slc = self.data[c:c+length]
 | 
			
		||||
        if move_cursor:
 | 
			
		||||
            self.moveCursor(length)
 | 
			
		||||
        return slc
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
    def readBew(self, n_bytes=1, move_cursor=1):
 | 
			
		||||
        """
 | 
			
		||||
        Reads n bytes of date from the current cursor position.
 | 
			
		||||
        Moves cursor if move_cursor is true
 | 
			
		||||
        """
 | 
			
		||||
        return readBew(self.nextSlice(n_bytes, move_cursor))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def readVarLen(self):
 | 
			
		||||
        """
 | 
			
		||||
        Reads a variable length value from the current cursor position.
 | 
			
		||||
        Moves cursor if move_cursor is true
 | 
			
		||||
        """
 | 
			
		||||
        MAX_VARLEN = 4 # Max value varlen can be
 | 
			
		||||
        var = readVar(self.nextSlice(MAX_VARLEN, 0))
 | 
			
		||||
        # only move cursor the actual bytes in varlen
 | 
			
		||||
        self.moveCursor(varLen(var))
 | 
			
		||||
        return var
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    test_file = 'test/midifiles/minimal.mid'
 | 
			
		||||
    fis = RawInstreamFile(test_file)
 | 
			
		||||
    print fis.nextSlice(len(fis.data))
 | 
			
		||||
 | 
			
		||||
    test_file = 'test/midifiles/cubase-minimal.mid'
 | 
			
		||||
    cubase_minimal = open(test_file, 'rb')
 | 
			
		||||
    fis2 = RawInstreamFile(cubase_minimal)
 | 
			
		||||
    print fis2.nextSlice(len(fis2.data))
 | 
			
		||||
    cubase_minimal.close()
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/RawInstreamFile.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/RawInstreamFile.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										69
									
								
								projekte/soundz/midifnord/midi/RawOutstreamFile.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								projekte/soundz/midifnord/midi/RawOutstreamFile.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,69 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
# standard library imports
 | 
			
		||||
import sys
 | 
			
		||||
from types import StringType
 | 
			
		||||
from struct import unpack
 | 
			
		||||
from cStringIO import StringIO
 | 
			
		||||
 | 
			
		||||
# custom import
 | 
			
		||||
from DataTypeConverters import writeBew, writeVar, fromBytes
 | 
			
		||||
 | 
			
		||||
class RawOutstreamFile:
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
    
 | 
			
		||||
    Writes a midi file to disk.
 | 
			
		||||
    
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, outfile=''):
 | 
			
		||||
        self.buffer = StringIO()
 | 
			
		||||
        self.outfile = outfile
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    # native data reading functions
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def writeSlice(self, str_slice):
 | 
			
		||||
        "Writes the next text slice to the raw data"
 | 
			
		||||
        self.buffer.write(str_slice)
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
    def writeBew(self, value, length=1):
 | 
			
		||||
        "Writes a value to the file as big endian word"
 | 
			
		||||
        self.writeSlice(writeBew(value, length))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def writeVarLen(self, value):
 | 
			
		||||
        "Writes a variable length word to the file"
 | 
			
		||||
        var = self.writeSlice(writeVar(value))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def write(self):
 | 
			
		||||
        "Writes to disc"
 | 
			
		||||
        if self.outfile:
 | 
			
		||||
            if isinstance(self.outfile, StringType):
 | 
			
		||||
                outfile = open(self.outfile, 'wb')
 | 
			
		||||
                outfile.write(self.getvalue())
 | 
			
		||||
                outfile.close()
 | 
			
		||||
            else:
 | 
			
		||||
                self.outfile.write(self.getvalue())
 | 
			
		||||
        else:
 | 
			
		||||
            sys.stdout.write(self.getvalue())
 | 
			
		||||
                
 | 
			
		||||
    def getvalue(self):
 | 
			
		||||
        return self.buffer.getvalue()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    out_file = 'test/midifiles/midiout.mid'
 | 
			
		||||
    out_file = ''
 | 
			
		||||
    rawOut = RawOutstreamFile(out_file)
 | 
			
		||||
    rawOut.writeSlice('MThd')
 | 
			
		||||
    rawOut.writeBew(6, 4)
 | 
			
		||||
    rawOut.writeBew(1, 2)
 | 
			
		||||
    rawOut.writeBew(2, 2)
 | 
			
		||||
    rawOut.writeBew(15360, 2)
 | 
			
		||||
    rawOut.write()
 | 
			
		||||
							
								
								
									
										6
									
								
								projekte/soundz/midifnord/midi/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								projekte/soundz/midifnord/midi/__init__.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
#import MidiOutStream
 | 
			
		||||
#import MidiInStream
 | 
			
		||||
#import MidiInFile
 | 
			
		||||
#import MidiToText
 | 
			
		||||
							
								
								
									
										45
									
								
								projekte/soundz/midifnord/midi/changes.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								projekte/soundz/midifnord/midi/changes.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,45 @@
 | 
			
		|||
------------------------------------------------------------------------
 | 
			
		||||
r409 | maxm | 2006-01-05 16:37:29 +0100 (to, 05 jan 2006) | 1 line
 | 
			
		||||
 | 
			
		||||
Made RawOutstreamFile.py write to std out if no outfile is given.
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r403 | maxm | 2006-01-05 13:34:11 +0100 (to, 05 jan 2006) | 1 line
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r402 | maxm | 2006-01-05 13:33:56 +0100 (to, 05 jan 2006) | 1 line
 | 
			
		||||
 | 
			
		||||
- Fixed minor bugs, added coding headers
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r401 | maxm | 2006-01-01 23:09:17 +0100 (s_, 01 jan 2006) | 1 line
 | 
			
		||||
 | 
			
		||||
Fixed sysex dispathcer bug.
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r268 | maxm | 2005-02-04 12:26:59 +0100 (fr, 04 feb 2005) | 1 line
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r128 | maxm | 2004-12-18 14:05:27 +0100 (l_, 18 dec 2004) | 1 line
 | 
			
		||||
 | 
			
		||||
Fixed bug when using relative time
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r15 | maxm | 2004-03-09 15:01:41 +0100 (ti, 09 mar 2004) | 1 line
 | 
			
		||||
 | 
			
		||||
made a copy to meta folder
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r13 | maxm | 2004-03-09 09:17:23 +0100 (ti, 09 mar 2004) | 1 line
 | 
			
		||||
 | 
			
		||||
Deleted .pyc files
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r12 | maxm | 2004-03-09 09:15:54 +0100 (ti, 09 mar 2004) | 1 line
 | 
			
		||||
 | 
			
		||||
Removed file/folder
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r3 | maxm | 2004-03-08 23:16:25 +0100 (ma, 08 mar 2004) | 1 line
 | 
			
		||||
 | 
			
		||||
Adde midi
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
r1 | maxm | 2004-03-08 22:49:23 +0100 (ma, 08 mar 2004) | 1 line
 | 
			
		||||
 | 
			
		||||
Initial Import
 | 
			
		||||
------------------------------------------------------------------------
 | 
			
		||||
							
								
								
									
										210
									
								
								projekte/soundz/midifnord/midi/constants.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								projekte/soundz/midifnord/midi/constants.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,210 @@
 | 
			
		|||
# -*- coding: ISO-8859-1 -*-
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
## Definitions of the different midi events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
## Midi channel events (The most usual events)
 | 
			
		||||
## also called "Channel Voice Messages"
 | 
			
		||||
 | 
			
		||||
NOTE_OFF = 0x80
 | 
			
		||||
# 1000cccc 0nnnnnnn 0vvvvvvv (channel, note, velocity)
 | 
			
		||||
 | 
			
		||||
NOTE_ON = 0x90
 | 
			
		||||
# 1001cccc 0nnnnnnn 0vvvvvvv (channel, note, velocity)
 | 
			
		||||
 | 
			
		||||
AFTERTOUCH = 0xA0
 | 
			
		||||
# 1010cccc 0nnnnnnn 0vvvvvvv (channel, note, velocity)
 | 
			
		||||
 | 
			
		||||
CONTINUOUS_CONTROLLER = 0xB0 # see Channel Mode Messages!!!
 | 
			
		||||
# 1011cccc 0ccccccc 0vvvvvvv (channel, controller, value)
 | 
			
		||||
 | 
			
		||||
PATCH_CHANGE = 0xC0
 | 
			
		||||
# 1100cccc 0ppppppp (channel, program)
 | 
			
		||||
 | 
			
		||||
CHANNEL_PRESSURE = 0xD0
 | 
			
		||||
# 1101cccc 0ppppppp (channel, pressure)
 | 
			
		||||
 | 
			
		||||
PITCH_BEND = 0xE0
 | 
			
		||||
# 1110cccc 0vvvvvvv 0wwwwwww (channel, value-lo, value-hi)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
##  Channel Mode Messages (Continuous Controller)
 | 
			
		||||
##  They share a status byte.
 | 
			
		||||
##  The controller makes the difference here
 | 
			
		||||
 | 
			
		||||
# High resolution continuous controllers (MSB)
 | 
			
		||||
 | 
			
		||||
BANK_SELECT = 0x00
 | 
			
		||||
MODULATION_WHEEL = 0x01
 | 
			
		||||
BREATH_CONTROLLER = 0x02
 | 
			
		||||
FOOT_CONTROLLER = 0x04
 | 
			
		||||
PORTAMENTO_TIME = 0x05
 | 
			
		||||
DATA_ENTRY = 0x06
 | 
			
		||||
CHANNEL_VOLUME = 0x07
 | 
			
		||||
BALANCE = 0x08
 | 
			
		||||
PAN = 0x0A
 | 
			
		||||
EXPRESSION_CONTROLLER = 0x0B
 | 
			
		||||
EFFECT_CONTROL_1 = 0x0C
 | 
			
		||||
EFFECT_CONTROL_2 = 0x0D
 | 
			
		||||
GEN_PURPOSE_CONTROLLER_1 = 0x10
 | 
			
		||||
GEN_PURPOSE_CONTROLLER_2 = 0x11
 | 
			
		||||
GEN_PURPOSE_CONTROLLER_3 = 0x12
 | 
			
		||||
GEN_PURPOSE_CONTROLLER_4 = 0x13
 | 
			
		||||
 | 
			
		||||
# High resolution continuous controllers (LSB)
 | 
			
		||||
 | 
			
		||||
BANK_SELECT = 0x20
 | 
			
		||||
MODULATION_WHEEL = 0x21
 | 
			
		||||
BREATH_CONTROLLER = 0x22
 | 
			
		||||
FOOT_CONTROLLER = 0x24
 | 
			
		||||
PORTAMENTO_TIME = 0x25
 | 
			
		||||
DATA_ENTRY = 0x26
 | 
			
		||||
CHANNEL_VOLUME = 0x27
 | 
			
		||||
BALANCE = 0x28
 | 
			
		||||
PAN = 0x2A
 | 
			
		||||
EXPRESSION_CONTROLLER = 0x2B
 | 
			
		||||
EFFECT_CONTROL_1 = 0x2C
 | 
			
		||||
EFFECT_CONTROL_2 = 0x2D
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_1 = 0x30
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_2 = 0x31
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_3 = 0x32
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_4 = 0x33
 | 
			
		||||
 | 
			
		||||
# Switches
 | 
			
		||||
 | 
			
		||||
SUSTAIN_ONOFF = 0x40
 | 
			
		||||
PORTAMENTO_ONOFF = 0x41
 | 
			
		||||
SOSTENUTO_ONOFF = 0x42
 | 
			
		||||
SOFT_PEDAL_ONOFF = 0x43
 | 
			
		||||
LEGATO_ONOFF = 0x44
 | 
			
		||||
HOLD_2_ONOFF = 0x45
 | 
			
		||||
 | 
			
		||||
# Low resolution continuous controllers
 | 
			
		||||
 | 
			
		||||
SOUND_CONTROLLER_1 = 0x46                  # (TG: Sound Variation;   FX: Exciter On/Off)
 | 
			
		||||
SOUND_CONTROLLER_2 = 0x47                  # (TG: Harmonic Content;   FX: Compressor On/Off)
 | 
			
		||||
SOUND_CONTROLLER_3 = 0x48                  # (TG: Release Time;   FX: Distortion On/Off)
 | 
			
		||||
SOUND_CONTROLLER_4 = 0x49                  # (TG: Attack Time;   FX: EQ On/Off)
 | 
			
		||||
SOUND_CONTROLLER_5 = 0x4A                  # (TG: Brightness;   FX: Expander On/Off)75	SOUND_CONTROLLER_6   (TG: Undefined;   FX: Reverb OnOff)
 | 
			
		||||
SOUND_CONTROLLER_7 = 0x4C                  # (TG: Undefined;   FX: Delay OnOff)
 | 
			
		||||
SOUND_CONTROLLER_8 = 0x4D                  # (TG: Undefined;   FX: Pitch Transpose OnOff)
 | 
			
		||||
SOUND_CONTROLLER_9 = 0x4E                  # (TG: Undefined;   FX: Flange/Chorus OnOff)
 | 
			
		||||
SOUND_CONTROLLER_10 = 0x4F                 # (TG: Undefined;   FX: Special Effects OnOff)
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_5 = 0x50
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_6 = 0x51
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_7 = 0x52
 | 
			
		||||
GENERAL_PURPOSE_CONTROLLER_8 = 0x53
 | 
			
		||||
PORTAMENTO_CONTROL = 0x54                  # (PTC)   (0vvvvvvv is the source Note number)   (Detail)
 | 
			
		||||
EFFECTS_1 = 0x5B                           # (Ext. Effects Depth)
 | 
			
		||||
EFFECTS_2 = 0x5C                           # (Tremelo Depth)
 | 
			
		||||
EFFECTS_3 = 0x5D                           # (Chorus Depth)
 | 
			
		||||
EFFECTS_4 = 0x5E                           # (Celeste Depth)
 | 
			
		||||
EFFECTS_5 = 0x5F                           # (Phaser Depth)
 | 
			
		||||
DATA_INCREMENT = 0x60                      # (0vvvvvvv is n/a; use 0)
 | 
			
		||||
DATA_DECREMENT = 0x61                      # (0vvvvvvv is n/a; use 0)
 | 
			
		||||
NON_REGISTERED_PARAMETER_NUMBER = 0x62     # (LSB)
 | 
			
		||||
NON_REGISTERED_PARAMETER_NUMBER = 0x63     # (MSB)
 | 
			
		||||
REGISTERED_PARAMETER_NUMBER = 0x64         # (LSB)
 | 
			
		||||
REGISTERED_PARAMETER_NUMBER = 0x65         # (MSB)
 | 
			
		||||
 | 
			
		||||
# Channel Mode messages - (Detail)
 | 
			
		||||
 | 
			
		||||
ALL_SOUND_OFF = 0x78
 | 
			
		||||
RESET_ALL_CONTROLLERS = 0x79
 | 
			
		||||
LOCAL_CONTROL_ONOFF = 0x7A
 | 
			
		||||
ALL_NOTES_OFF = 0x7B
 | 
			
		||||
OMNI_MODE_OFF = 0x7C          # (also causes ANO)
 | 
			
		||||
OMNI_MODE_ON = 0x7D           # (also causes ANO)
 | 
			
		||||
MONO_MODE_ON = 0x7E           # (Poly Off; also causes ANO)
 | 
			
		||||
POLY_MODE_ON = 0x7F           # (Mono Off; also causes ANO)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
## System Common Messages, for all channels
 | 
			
		||||
 | 
			
		||||
SYSTEM_EXCLUSIVE = 0xF0
 | 
			
		||||
# 11110000 0iiiiiii 0ddddddd ... 11110111
 | 
			
		||||
 | 
			
		||||
MTC = 0xF1 # MIDI Time Code Quarter Frame
 | 
			
		||||
# 11110001
 | 
			
		||||
 | 
			
		||||
SONG_POSITION_POINTER = 0xF2
 | 
			
		||||
# 11110010 0vvvvvvv 0wwwwwww (lo-position, hi-position)
 | 
			
		||||
 | 
			
		||||
SONG_SELECT = 0xF3
 | 
			
		||||
# 11110011 0sssssss (songnumber)
 | 
			
		||||
 | 
			
		||||
#UNDEFINED = 0xF4
 | 
			
		||||
## 11110100
 | 
			
		||||
 | 
			
		||||
#UNDEFINED = 0xF5
 | 
			
		||||
## 11110101
 | 
			
		||||
 | 
			
		||||
TUNING_REQUEST = 0xF6
 | 
			
		||||
# 11110110
 | 
			
		||||
 | 
			
		||||
END_OFF_EXCLUSIVE = 0xF7 # terminator
 | 
			
		||||
# 11110111 # End of system exclusive
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
## Midifile meta-events
 | 
			
		||||
 | 
			
		||||
SEQUENCE_NUMBER = 0x00      # 00 02 ss ss (seq-number)
 | 
			
		||||
TEXT            = 0x01      # 01 len text...
 | 
			
		||||
COPYRIGHT       = 0x02      # 02 len text...
 | 
			
		||||
SEQUENCE_NAME   = 0x03      # 03 len text...
 | 
			
		||||
INSTRUMENT_NAME = 0x04      # 04 len text...
 | 
			
		||||
LYRIC           = 0x05      # 05 len text...
 | 
			
		||||
MARKER          = 0x06      # 06 len text...
 | 
			
		||||
CUEPOINT        = 0x07      # 07 len text...
 | 
			
		||||
PROGRAM_NAME    = 0x08      # 08 len text...
 | 
			
		||||
DEVICE_NAME     = 0x09      # 09 len text...
 | 
			
		||||
 | 
			
		||||
MIDI_CH_PREFIX  = 0x20      # MIDI channel prefix assignment (unofficial)
 | 
			
		||||
 | 
			
		||||
MIDI_PORT       = 0x21      # 21 01 port, legacy stuff but still used
 | 
			
		||||
END_OF_TRACK    = 0x2F      # 2f 00
 | 
			
		||||
TEMPO           = 0x51      # 51 03 tt tt tt (tempo in us/quarternote)
 | 
			
		||||
SMTP_OFFSET     = 0x54      # 54 05 hh mm ss ff xx
 | 
			
		||||
TIME_SIGNATURE  = 0x58      # 58 04 nn dd cc bb
 | 
			
		||||
KEY_SIGNATURE   = 0x59      # ??? len text...
 | 
			
		||||
SPECIFIC        = 0x7F      # Sequencer specific event
 | 
			
		||||
 | 
			
		||||
FILE_HEADER     = 'MThd'
 | 
			
		||||
TRACK_HEADER    = 'MTrk'
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
## System Realtime messages
 | 
			
		||||
## I don't supose these are to be found in midi files?!
 | 
			
		||||
 | 
			
		||||
TIMING_CLOCK   = 0xF8
 | 
			
		||||
# undefined    = 0xF9
 | 
			
		||||
SONG_START     = 0xFA
 | 
			
		||||
SONG_CONTINUE  = 0xFB
 | 
			
		||||
SONG_STOP      = 0xFC
 | 
			
		||||
# undefined    = 0xFD
 | 
			
		||||
ACTIVE_SENSING = 0xFE
 | 
			
		||||
SYSTEM_RESET   = 0xFF
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
## META EVENT, it is used only in midi files.
 | 
			
		||||
## In transmitted data it means system reset!!!
 | 
			
		||||
 | 
			
		||||
META_EVENT     = 0xFF
 | 
			
		||||
# 11111111
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###################################################
 | 
			
		||||
## Helper functions
 | 
			
		||||
 | 
			
		||||
def is_status(byte):
 | 
			
		||||
    return (byte & 0x80) == 0x80 # 1000 0000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/constants.pyc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/constants.pyc
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										29
									
								
								projekte/soundz/midifnord/midi/example_mimimal_type0.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								projekte/soundz/midifnord/midi/example_mimimal_type0.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
from MidiOutFile import MidiOutFile
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
This is an example of the smallest possible type 0 midi file, where 
 | 
			
		||||
all the midi events are in the same track.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
out_file = 'midiout/minimal_type0.mid'
 | 
			
		||||
midi = MidiOutFile(out_file)
 | 
			
		||||
 | 
			
		||||
# non optional midi framework
 | 
			
		||||
midi.header()
 | 
			
		||||
midi.start_of_track() 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# musical events
 | 
			
		||||
 | 
			
		||||
midi.update_time(0)
 | 
			
		||||
midi.note_on(channel=0, note=0x40)
 | 
			
		||||
 | 
			
		||||
midi.update_time(192)
 | 
			
		||||
midi.note_off(channel=0, note=0x40)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# non optional midi framework
 | 
			
		||||
midi.update_time(0)
 | 
			
		||||
midi.end_of_track()
 | 
			
		||||
 | 
			
		||||
midi.eof()
 | 
			
		||||
							
								
								
									
										23
									
								
								projekte/soundz/midifnord/midi/example_print_channel_0.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								projekte/soundz/midifnord/midi/example_print_channel_0.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
from MidiOutStream import MidiOutStream
 | 
			
		||||
from MidiInFile import MidiInFile
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
This prints all note on events on midi channel 0
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Transposer(MidiOutStream):
 | 
			
		||||
    
 | 
			
		||||
    "Transposes all notes by 1 octave"
 | 
			
		||||
    
 | 
			
		||||
    def note_on(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
        if channel == 0:
 | 
			
		||||
            print channel, note, velocity, self.rel_time()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
event_handler = Transposer()
 | 
			
		||||
 | 
			
		||||
in_file = 'midiout/minimal_type0.mid'
 | 
			
		||||
midi_in = MidiInFile(event_handler, in_file)
 | 
			
		||||
midi_in.read()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								projekte/soundz/midifnord/midi/example_print_events.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								projekte/soundz/midifnord/midi/example_print_events.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
from MidiToText import MidiToText
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
This is an example that uses the MidiToText eventhandler. When an 
 | 
			
		||||
event is triggered on it, it prints the event to the console.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
midi = MidiToText()
 | 
			
		||||
 | 
			
		||||
# non optional midi framework
 | 
			
		||||
midi.header()
 | 
			
		||||
midi.start_of_track() 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# musical events
 | 
			
		||||
 | 
			
		||||
midi.update_time(0)
 | 
			
		||||
midi.note_on(channel=0, note=0x40)
 | 
			
		||||
 | 
			
		||||
midi.update_time(192)
 | 
			
		||||
midi.note_off(channel=0, note=0x40)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# non optional midi framework
 | 
			
		||||
midi.update_time(0)
 | 
			
		||||
midi.end_of_track() # not optional!
 | 
			
		||||
 | 
			
		||||
midi.eof()
 | 
			
		||||
							
								
								
									
										19
									
								
								projekte/soundz/midifnord/midi/example_print_file.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								projekte/soundz/midifnord/midi/example_print_file.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
"""
 | 
			
		||||
This is an example that uses the MidiToText eventhandler. When an 
 | 
			
		||||
event is triggered on it, it prints the event to the console.
 | 
			
		||||
 | 
			
		||||
It gets the events from the MidiInFile.
 | 
			
		||||
 | 
			
		||||
So it prints all the events from the infile to the console. great for 
 | 
			
		||||
debugging :-s
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# get data
 | 
			
		||||
test_file = 'test/midifiles/minimal-cubase-type0.mid'
 | 
			
		||||
 | 
			
		||||
# do parsing
 | 
			
		||||
from MidiInFile import MidiInFile
 | 
			
		||||
from MidiToText import MidiToText # the event handler
 | 
			
		||||
midiIn = MidiInFile(MidiToText(), test_file)
 | 
			
		||||
midiIn.read()
 | 
			
		||||
							
								
								
									
										40
									
								
								projekte/soundz/midifnord/midi/example_transpose_octave.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								projekte/soundz/midifnord/midi/example_transpose_octave.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
from MidiOutFile import MidiOutFile
 | 
			
		||||
from MidiInFile import MidiInFile
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
This is an example of the smallest possible type 0 midi file, where 
 | 
			
		||||
all the midi events are in the same track.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Transposer(MidiOutFile):
 | 
			
		||||
    
 | 
			
		||||
    "Transposes all notes by 1 octave"
 | 
			
		||||
    
 | 
			
		||||
    def _transp(self, ch, note):
 | 
			
		||||
        if ch != 9: # not the drums!
 | 
			
		||||
            note += 12
 | 
			
		||||
            if note > 127:
 | 
			
		||||
                note = 127
 | 
			
		||||
        return note
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_on(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
        note = self._transp(channel, note)
 | 
			
		||||
        MidiOutFile.note_on(self, channel, note, velocity)
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
    def note_off(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
        note = self._transp(channel, note)
 | 
			
		||||
        MidiOutFile.note_off(self, channel, note, velocity)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
out_file = 'midiout/transposed.mid'
 | 
			
		||||
midi_out = Transposer(out_file)
 | 
			
		||||
 | 
			
		||||
#in_file = 'midiout/minimal_type0.mid'
 | 
			
		||||
#in_file = 'test/midifiles/Lola.mid'
 | 
			
		||||
in_file = 'test/midifiles/tennessee_waltz.mid'
 | 
			
		||||
midi_in = MidiInFile(midi_out, in_file)
 | 
			
		||||
midi_in.read()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,76 @@
 | 
			
		|||
class EventDispatcherBase:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def __init__(self, outstream):
 | 
			
		||||
        """
 | 
			
		||||
        The event dispatcher generates events on the outstream. This 
 | 
			
		||||
        is the base implementation. It is more like an interface for 
 | 
			
		||||
        how the EventDispatcher. It has the methods that are used by 
 | 
			
		||||
        the Midi Parser.
 | 
			
		||||
        """
 | 
			
		||||
        # internal values, don't mess with 'em directly
 | 
			
		||||
        self.outstream = outstream
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def eof(self):
 | 
			
		||||
        "End of file!"
 | 
			
		||||
        self.outstream.eof()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def update_time(self, new_time=0, relative=1):
 | 
			
		||||
        "Updates relative/absolute time."
 | 
			
		||||
        self.outstream.update_time(new_time, relative)
 | 
			
		||||
 | 
			
		||||
    # 'official' midi events
 | 
			
		||||
 | 
			
		||||
    def header(self, format, nTracks, division):
 | 
			
		||||
        "Triggers the header event"
 | 
			
		||||
        self.outstream.header(format, nTracks, division)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def start_of_track(self, current_track):
 | 
			
		||||
        "Triggers the start of track event"
 | 
			
		||||
        
 | 
			
		||||
        # I do this twice so that users can overwrite the 
 | 
			
		||||
        # start_of_track event handler without worrying whether the 
 | 
			
		||||
        # track number is updated correctly.
 | 
			
		||||
        self.outstream.set_current_track(current_track)
 | 
			
		||||
        self.outstream.start_of_track(current_track)
 | 
			
		||||
 | 
			
		||||
    # Event dispatchers for midi events
 | 
			
		||||
 | 
			
		||||
    def channel_messages(self, hi_nible, channel, data):
 | 
			
		||||
        "Dispatches channel messages"
 | 
			
		||||
        self.outstream.channel_message(hi_nible, channel, data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def continuous_controllers(self, channel, controller, value):
 | 
			
		||||
        "Dispatches channel messages"
 | 
			
		||||
        self.outstream.continuous_controller(channel, controller, value)
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    def system_commons(self, common_type, common_data):
 | 
			
		||||
        "Dispatches system common messages"
 | 
			
		||||
        self.outstream.system_common(common_type, common_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def meta_event(self, meta_type, data):
 | 
			
		||||
        "Dispatches meta events"
 | 
			
		||||
        self.outstream.meta_event(meta_type, data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sysex_events(self, data):
 | 
			
		||||
        "Dispatcher for sysex events"
 | 
			
		||||
        self.outstream.sysex_event(data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    from MidiToText import MidiToText
 | 
			
		||||
    from constants import NOTE_ON
 | 
			
		||||
    
 | 
			
		||||
    outstream = MidiToText()
 | 
			
		||||
    dispatcher = EventDispatcherBase(outstream)
 | 
			
		||||
    dispatcher.channel_messages(NOTE_ON, 0x00, '\x40\x40')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,182 @@
 | 
			
		|||
from MidiOutStream import MidiOutStream
 | 
			
		||||
 | 
			
		||||
class MidiOutPassThrough(MidiOutStream):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    This class i mainly used for testing the event dispatcher. The 
 | 
			
		||||
    methods just returns the passed parameters as a tupple.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Midi channel events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_on(self, channel, note, velocity, time=None):
 | 
			
		||||
        return channel, note, velocity, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def note_off(self, channel, note, velocity, time=None):
 | 
			
		||||
        return channel, note, velocity, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def aftertouch(self, channel, note, velocity, time=None):
 | 
			
		||||
        return channel, note, velocity, time
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
    def continuous_controller(self, channel, controller, value, time=None):
 | 
			
		||||
        return channel, controller, value, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def patch_change(self, channel, patch, time=None):
 | 
			
		||||
        return channel, patch, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def channel_pressure(self, channel, pressure, time=None):
 | 
			
		||||
        return channel, pressure, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## defined continuous controller events
 | 
			
		||||
    
 | 
			
		||||
#    def cc_
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Common events
 | 
			
		||||
 | 
			
		||||
    def system_exclusive(self, data, time=None):
 | 
			
		||||
        return data, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_position_pointer(self, hiPos, loPos, time=None):
 | 
			
		||||
        return hiPos, loPos, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_select(self, songNumber, time=None):
 | 
			
		||||
        return songNumber, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tuning_request(self, time=None):
 | 
			
		||||
        return time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #########################
 | 
			
		||||
    # header does not really belong here. But anyhoo!!!
 | 
			
		||||
    
 | 
			
		||||
    def header(self, format, nTracks, division):
 | 
			
		||||
        return format, nTracks, division
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def eof(self):
 | 
			
		||||
        return 'eof'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## meta events
 | 
			
		||||
 | 
			
		||||
    def start_of_track(self, n_track=0):
 | 
			
		||||
        return n_track
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def end_of_track(self, n_track=0, time=None):
 | 
			
		||||
        return n_track, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_number(self, hiVal, loVal, time=None):
 | 
			
		||||
        return hiVal, loVal, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def text(self, text, time=None):
 | 
			
		||||
        return text, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def copyright(self, text, time=None):
 | 
			
		||||
        return text, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequence_name(self, text, time=None):
 | 
			
		||||
        return text, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def instrument_name(self, text, time=None):
 | 
			
		||||
        return text, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def lyric(self, text, time=None):
 | 
			
		||||
        return text, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def marker(self, text, time=None):
 | 
			
		||||
        return text, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def cuepoint(self, text, time=None):
 | 
			
		||||
        return text, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def midi_port(self, value, time=None):
 | 
			
		||||
        return value, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tempo(self, value, time=None):
 | 
			
		||||
        return value, time
 | 
			
		||||
 | 
			
		||||
    def smtp_offset(self, hour, minute, second, frame, framePart, time=None):
 | 
			
		||||
        return hour, minute, second, frame, framePart, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def time_signature(self, nn, dd, cc, bb, time=None):
 | 
			
		||||
        return nn, dd, cc, bb, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def key_signature(self, sf, mi, time=None):
 | 
			
		||||
        return sf, mi, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def sequencer_specific(self, data, time=None):
 | 
			
		||||
        return data, time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## realtime events
 | 
			
		||||
 | 
			
		||||
    def timing_clock(self, time=None):
 | 
			
		||||
        return time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_start(self, time=None):
 | 
			
		||||
        return time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_stop(self, time=None):
 | 
			
		||||
        return time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def song_continue(self, time=None):
 | 
			
		||||
        return time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def active_sensing(self, time=None):
 | 
			
		||||
        return time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def system_reset(self, time=None):
 | 
			
		||||
        return time
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    midiOut = MidiOutStream()
 | 
			
		||||
    midiOut.note_on(0, 63, 127, 0)
 | 
			
		||||
    midiOut.note_off(0, 63, 127, 384)
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										135
									
								
								projekte/soundz/midifnord/midi/experimental/MidiOutStreamBase.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								projekte/soundz/midifnord/midi/experimental/MidiOutStreamBase.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,135 @@
 | 
			
		|||
class MidiOutStreamBase:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    MidiOutStreamBase is Basically an eventhandler. It is the most central
 | 
			
		||||
    class in the Midi library. You use it both for writing events to
 | 
			
		||||
    an output stream, and as an event handler for an input stream.
 | 
			
		||||
 | 
			
		||||
    This makes it extremely easy to take input from one stream and
 | 
			
		||||
    send it to another. Ie. if you want to read a Midi file, do some
 | 
			
		||||
    processing, and send it to a midiport.
 | 
			
		||||
 | 
			
		||||
    All time values are in absolute values from the opening of a
 | 
			
		||||
    stream. To calculate time values, please use the MidiTime and
 | 
			
		||||
    MidiDeltaTime classes.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        
 | 
			
		||||
        # the time is rather global, so it needs to be stored 
 | 
			
		||||
        # here. Otherwise there would be no really simple way to 
 | 
			
		||||
        # calculate it. The alternative would be to have each event 
 | 
			
		||||
        # handler do it. That sucks even worse!
 | 
			
		||||
        self._absolute_time = 0
 | 
			
		||||
        self._relative_time = 0
 | 
			
		||||
        self._current_track = 0
 | 
			
		||||
 | 
			
		||||
    # time handling event handlers. They should overwritten with care
 | 
			
		||||
 | 
			
		||||
    def update_time(self, new_time=0, relative=1):
 | 
			
		||||
        """
 | 
			
		||||
        Updates the time, if relative is true, new_time is relative, 
 | 
			
		||||
        else it's absolute.
 | 
			
		||||
        """
 | 
			
		||||
        if relative:
 | 
			
		||||
            self._relative_time = new_time
 | 
			
		||||
            self._absolute_time += new_time
 | 
			
		||||
        else:
 | 
			
		||||
            self._absolute_time = new_time
 | 
			
		||||
            self._relative_time = new_time - self._absolute_time
 | 
			
		||||
 | 
			
		||||
    def rel_time(self):
 | 
			
		||||
        "Returns the relative time"
 | 
			
		||||
        return self._relative_time
 | 
			
		||||
 | 
			
		||||
    def abs_time(self):
 | 
			
		||||
        "Returns the absolute time"
 | 
			
		||||
        return self._absolute_time
 | 
			
		||||
 | 
			
		||||
    # track handling event handlers
 | 
			
		||||
    
 | 
			
		||||
    def set_current_track(self, new_track):
 | 
			
		||||
        "Sets the current track number"
 | 
			
		||||
        self._current_track = new_track
 | 
			
		||||
    
 | 
			
		||||
    def get_current_track(self):
 | 
			
		||||
        "Returns the current track number"
 | 
			
		||||
        return self._current_track
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Midi events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def channel_message(self, message_type, channel, data):
 | 
			
		||||
        """The default event handler for channel messages"""
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## Common events
 | 
			
		||||
 | 
			
		||||
    def system_exclusive(self, data):
 | 
			
		||||
 | 
			
		||||
        """The default event handler for system_exclusive messages"""
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def system_common(self, common_type, common_data):
 | 
			
		||||
 | 
			
		||||
        """The default event handler for system common messages"""
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #########################
 | 
			
		||||
    # header does not really belong here. But anyhoo!!!
 | 
			
		||||
    
 | 
			
		||||
    def header(self, format, nTracks, division):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        format: type of midi file in [1,2]
 | 
			
		||||
        nTracks: number of tracks
 | 
			
		||||
        division: timing division
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def start_of_track(self, n_track=0):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        n_track: number of track
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def eof(self):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        End of file. No more events to be processed.
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    #####################
 | 
			
		||||
    ## meta events
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def meta_event(self, meta_type, data, time):
 | 
			
		||||
        
 | 
			
		||||
        """The default event handler for meta_events"""
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    midiOut = MidiOutStreamBase()
 | 
			
		||||
    midiOut.update_time(0,0)
 | 
			
		||||
    midiOut.note_on(0, 63, 127)
 | 
			
		||||
    midiOut.note_off(0, 63, 127)
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										1
									
								
								projekte/soundz/midifnord/midi/experimental/readme.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								projekte/soundz/midifnord/midi/experimental/readme.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
Stuff that I am just playing around with
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/midiout/minimal_type0.mid
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/midiout/minimal_type0.mid
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/midiout/transposed.mid
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/midiout/transposed.mid
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										50
									
								
								projekte/soundz/midifnord/midi/readme.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								projekte/soundz/midifnord/midi/readme.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
This is the documentation for the midi package
 | 
			
		||||
==============================================
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The modules follows the following naming convention:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MidiIn<StreamType>.py
 | 
			
		||||
---------------------
 | 
			
		||||
 | 
			
		||||
The MidiIn modules reads midi content for a specific type of stream. Ie. a file or a midi port. It then generates events and triggers them on a MidiOutStream.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MidiOut<StreamType>.py
 | 
			
		||||
----------------------
 | 
			
		||||
 | 
			
		||||
The MidiOut modules are event handlers, that reacts to events generated by a a Midi in module.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MidiInBase.py
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
The base class for input streams.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
MidiOutBase.py
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
The base class for the output streams.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Internal modules
 | 
			
		||||
================
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
DataTypeConverters.py
 | 
			
		||||
---------------------
 | 
			
		||||
 | 
			
		||||
A collection of functions that converts the special data types used in midi files to and from strings.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
constants.py
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
A collection of constants from the midi spec.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/test/midifiles/midiout.mid
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/test/midifiles/midiout.mid
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/test/midifiles/minimal.mid
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/midi/test/midifiles/minimal.mid
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										26
									
								
								projekte/soundz/midifnord/midi/test/midifiles/minimal.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								projekte/soundz/midifnord/midi/test/midifiles/minimal.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
MThd | Format=1 | # of Tracks=2 | Division=15360
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Track #0 ******************************************
 | 
			
		||||
    Time       Event
 | 
			
		||||
    
 | 
			
		||||
   1: 1:  0 |Time Sig    |  4/4      | MIDI-clocks\click=24 | 32nds\quarter=8
 | 
			
		||||
            |Tempo       | BPM=120   | micros\quarter=500000
 | 
			
		||||
 101: 1:  0 |End of track| 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Track #1 ******************************************
 | 
			
		||||
    Time       Event
 | 
			
		||||
    
 | 
			
		||||
   1: 1:  0 |Track Name  | len=7     |
 | 
			
		||||
            0x53 0x79 0x6E 0x74 0x68 0x20 0x31 <Synth 1>
 | 
			
		||||
            |Instrument  | len=7     |
 | 
			
		||||
            0x53 0x79 0x6E 0x74 0x68 0x20 0x31 <Synth 1>
 | 
			
		||||
            |On Note     | chan= 1   | pitch=C 1         | vol=127
 | 
			
		||||
   2: 1:  0 |Off Note    | chan= 1   | pitch=c 1         | vol=0
 | 
			
		||||
 101: 1:  0 |End of track| 
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,54 @@
 | 
			
		|||
4D 54 68 64         MThd
 | 
			
		||||
00 00 00 06         len:    6
 | 
			
		||||
00 01               Type:   1
 | 
			
		||||
00 02               tracks: 2
 | 
			
		||||
3C 00               tempo:  15360
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
4D 54 72 6B         MTrk
 | 
			
		||||
00 00 00 16         len: 22
 | 
			
		||||
 | 
			
		||||
00                  time
 | 
			
		||||
    FF 58 04        Time Signature
 | 
			
		||||
    04 02 18 08     4/4 24 8
 | 
			
		||||
    
 | 
			
		||||
00                  time
 | 
			
		||||
    FF 51 03        TEMPO:
 | 
			
		||||
    07 A1 20        500.000 mySec
 | 
			
		||||
 | 
			
		||||
82 F7 80 00         time  ## oh bugger, it's buggy.
 | 
			
		||||
    FF 2F 00        End Of Track
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
4D 54 72 6B         MTrk
 | 
			
		||||
00 00 00 2C         len: 44
 | 
			
		||||
 | 
			
		||||
00                  time
 | 
			
		||||
    FF 03           Sequence/Track Name
 | 
			
		||||
    07              len: 7
 | 
			
		||||
    53 79 6E 74
 | 
			
		||||
    68 20 31        'Synth 1'
 | 
			
		||||
 | 
			
		||||
00                  time
 | 
			
		||||
    FF 04           Instrument
 | 
			
		||||
    07              len: 7
 | 
			
		||||
    53 79 6E 74
 | 
			
		||||
    68 20 31        'Synth 1'
 | 
			
		||||
 | 
			
		||||
00                  time
 | 
			
		||||
    FF 21 01        Midi port
 | 
			
		||||
    04              Port #5
 | 
			
		||||
 | 
			
		||||
00                  time
 | 
			
		||||
    90 24 7F        Note ON
 | 
			
		||||
    83 E0 00        Note OFF
 | 
			
		||||
    
 | 
			
		||||
00                  time
 | 
			
		||||
    80 24 00        Note OFF
 | 
			
		||||
 | 
			
		||||
00 82 F3 A0        
 | 
			
		||||
 | 
			
		||||
00
 | 
			
		||||
    FF 2F 00        End Of Track
 | 
			
		||||
							
								
								
									
										7
									
								
								projekte/soundz/midifnord/midi/test/midifiles/readme.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								projekte/soundz/midifnord/midi/test/midifiles/readme.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
These files are used for testing the midi package
 | 
			
		||||
=================================================
 | 
			
		||||
 | 
			
		||||
minimal.mid
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
A minimal working midifile. Plays a one bar "middle C" at 120 bpm. The absolute simplest file I could get to play in midi devices.
 | 
			
		||||
							
								
								
									
										3
									
								
								projekte/soundz/midifnord/midi/test/readme.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								projekte/soundz/midifnord/midi/test/readme.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
Embarrasingly empty.
 | 
			
		||||
 | 
			
		||||
Why don't you write some tests?
 | 
			
		||||
							
								
								
									
										1
									
								
								projekte/soundz/midifnord/midi/version.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								projekte/soundz/midifnord/midi/version.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
0.1.4
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/nevergoingtoU.mid
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								projekte/soundz/midifnord/nevergoingtoU.mid
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										23
									
								
								projekte/soundz/midifnord/nevergoingtoU.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								projekte/soundz/midifnord/nevergoingtoU.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
import sys
 | 
			
		||||
sys.path.append("midi")
 | 
			
		||||
from MidiOutStream import MidiOutStream
 | 
			
		||||
from MidiInFile import MidiInFile
 | 
			
		||||
 | 
			
		||||
class ArduinoConverter(MidiOutStream):
 | 
			
		||||
    
 | 
			
		||||
  "Convert MIDI stream to some weird format I can actually use"
 | 
			
		||||
    
 | 
			
		||||
  def note_on(self, channel=0, note=0x40, velocity=0x40):
 | 
			
		||||
    if self.get_current_track() == 3 and channel == 0:
 | 
			
		||||
      print note, self.rel_time()
 | 
			
		||||
 | 
			
		||||
  def sysex_event(self, data):
 | 
			
		||||
    "dummy"
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
# get data
 | 
			
		||||
test_file = 'nevergoingtoU.mid'
 | 
			
		||||
# do parsing
 | 
			
		||||
c = ArduinoConverter()
 | 
			
		||||
midiIn = MidiInFile(c, test_file)
 | 
			
		||||
midiIn.read()
 | 
			
		||||
		Reference in a new issue