Пример #1
0
 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
Пример #2
0
 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
Пример #3
0
class MidiOutFile(MidiOutStream):


    """
    MidiOutFile is an eventhandler that subclasses MidiOutStream.
    """


    def __init__(self, raw_out=''):

        self.raw_out = RawOutstreamFile(raw_out)
        super(MidiOutFile, self).__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([MTC, 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(SEQUENCE_NUMBER, 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(SPECIFIC, data)
Пример #4
0
    def __init__(self, raw_out=''):

        self.raw_out = RawOutstreamFile(raw_out)
        super(MidiOutFile, self).__init__(self)
Пример #5
0
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)
Пример #6
0
    def __init__(self, raw_out=''):

        self.raw_out = RawOutstreamFile(raw_out)
        MidiOutStream.__init__(self)
Пример #7
0
    def __init__(self, raw_out=''):

        self.raw_out = RawOutstreamFile(raw_out)
        MidiOutStream.__init__(self)
Пример #8
0
    def __init__(self, raw_out='', channels=None):

        self.raw_out = RawOutstreamFile(raw_out)
        self.channels= channels
        MidiOutStream.__init__(self)
Пример #9
0
class MidiOutFile(MidiOutStream):
    """
    MidiOutFile is an eventhandler that subclasses MidiOutStream.
    Note that some of the methods here overwrite (or even implement) the
    methods inherited from MidiOutStrem (some of them are not implemented
    there but only defined).

    Parameters
    ----------
    raw_out : str, optional. Default: ''
        the file name of the file to be written. May contain a path
        to a folder / directory as well.

    Attributes
    ----------
    raw_out : RawOutstreamFile object
        this is used to write a MIDI file to the disk.
    """
    def __init__(self, raw_out=''):
        self.raw_out = RawOutstreamFile(raw_out)
        MidiOutStream.__init__(self)

    def write(self):
        """
        calls the write() function of the RawOutstreamFiel object
        that was created on init of this MidiOutFile instance.
        """
        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.

        Parameters
        ----------
        slc :
            slice of an event.
        """
        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):
        """
        (0x40 = 64)

        Parameters
        ----------
        channel : number, optional. Default: 0
            the MIDI channel number. Possible range is 0-15

        note : hex number, optional. Default: 0x40
            the MIDI note number.

        velocity : hex number, optional. Default: 0x40
            the note velocity, possible range is 0-127 (0x00 - 0x7F)

#        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):
        """
        Parameters
        ----------
        channel : number
            the MIDI channel number, possible values: 0-15

         patch : number
             the patch number (instrument/sound), possible values: 0-127

#       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):
        """
        Parameters
        ----------
        channel : number

        value : number
            the pitch bend controller value. Note that this doesn't
            tell straight away by what amount the pitch is bent (e.g. in
            cents = 100th part of a semi-tone). CHECK this!

#        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):
        """
        Quarter-frame messages.

        Parameters
        ----------
        msg_type : number
            range is 0-7

        values : number
            range is 0-15

#        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):
        """

        Parameters
        ----------
        format : number, optional. Default: 0
            the type of MIDI file, possible is: 0, 1, 2

        nTracks : number, optional. Default: 1
            number of tracks in the MIDI file.

        division : number, optional. Default: 96
            the timing division in PPQ.

#        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 (in WHAT?)
        bew(format, 2)
        bew(nTracks, 2)
        bew(division, 2)

    def eof(self):
        """
        End of file. No more events to be processed.
        Calls `write()`.
        """
        # just write the file then.
        self.write()

    #####################
    ## meta events

    def meta_slice(self, meta_type, data_slice):
        """
        Writes a meta event. Whatever that is.

        Parameters
        ----------
        meta_type :

        data_slice :

        """

        # EDIT: added try / except for debugging purposes! TG
        #        try:
        #            slc = fromBytes([META_EVENT, meta_type]) + \
        #                    writeVar(len(data_slice)) +  data_slice
        #
        #            self.event_slice(slc)
        #        except:
        #            pass

        # Original code:
        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 : str
        """
        self.meta_slice(TEXT, text)

    def copyright(self, text):
        """
        Copyright notice
        text : str
        """
        self.meta_slice(COPYRIGHT, text)

    def sequence_name(self, text):
        """
        Sequence/track name
        text : str
        """
        self.meta_slice(SEQUENCE_NAME, text)

    def instrument_name(self, text):
        """
        text : str
        """
        self.meta_slice(INSTRUMENT_NAME, text)

    def lyric(self, text):
        """
        text : str
        """
        self.meta_slice(LYRIC, text)

    def marker(self, text):
        """
        text : str
        """
        self.meta_slice(MARKER, text)

    def cuepoint(self, text):
        """
        text : str
        """
        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):
        """
        Parameters
        ----------
        nn : number
            the numerator of the notated time signature. The
            number of beats that make up a full measure.

        dd : number
            represents the denominator of the notated time signature
            but NOT as the written number itself. It is

        cc : number
            number of MIDI clocks in a metronome click

        bb : number
            the number of notated 32nd notes in a MIDI quarter note
            (24 MIDI clocks)

#        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)
Пример #10
0
class MidiOutFile(MidiOutStream):
    """
    MidiOutFile is an eventhandler that subclasses MidiOutStream.
    Note that some of the methods here overwrite (or even implement) the
    methods inherited from MidiOutStrem (some of them are not implemented
    there but only defined).

    Parameters
    ----------
    raw_out : str, optional. Default: ''
        the file name of the file to be written. May contain a path
        to a folder / directory as well.

    Attributes
    ----------
    raw_out : RawOutstreamFile object
        this is used to write a MIDI file to the disk.
    """

    def __init__(self, raw_out=''):
        self.raw_out = RawOutstreamFile(raw_out)
        MidiOutStream.__init__(self)

    def write(self):
        """
        calls the write() function of the RawOutstreamFiel object
        that was created on init of this MidiOutFile instance.
        """
        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.

        Parameters
        ----------
        slc :
            slice of an event.
        """
        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):
        """
        (0x40 = 64)

        Parameters
        ----------
        channel : number, optional. Default: 0
            the MIDI channel number. Possible range is 0-15

        note : hex number, optional. Default: 0x40
            the MIDI note number.

        velocity : hex number, optional. Default: 0x40
            the note velocity, possible range is 0-127 (0x00 - 0x7F)

#        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):
        """
        Parameters
        ----------
        channel : number
            the MIDI channel number, possible values: 0-15

         patch : number
             the patch number (instrument/sound), possible values: 0-127

#       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):
        """
        Parameters
        ----------
        channel : number

        value : number
            the pitch bend controller value. Note that this doesn't
            tell straight away by what amount the pitch is bent (e.g. in
            cents = 100th part of a semi-tone). CHECK this!

#        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):
        """
        Quarter-frame messages.

        Parameters
        ----------
        msg_type : number
            range is 0-7

        values : number
            range is 0-15

#        msg_type: 0-7
#        values: 0-15
        """
        value = (msg_type << 4) + values
        self.event_slice(fromBytes([MTC, 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):
        """

        Parameters
        ----------
        format : number, optional. Default: 0
            the type of MIDI file, possible is: 0, 1, 2

        nTracks : number, optional. Default: 1
            number of tracks in the MIDI file.

        division : number, optional. Default: 96
            the timing division in PPQ.

#        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 (in WHAT?)
        bew(format, 2)
        bew(nTracks, 2)
        bew(division, 2)

    def eof(self):
        """
        End of file. No more events to be processed.
        Calls `write()`.
        """
        # just write the file then.
        self.write()


    #####################
    ## meta events

    def meta_slice(self, meta_type, data_slice):
        """
        Writes a meta event. Whatever that is.

        Parameters
        ----------
        meta_type :

        data_slice :

        """

        # EDIT: added try / except for debugging purposes! TG
#        try:
#            slc = fromBytes([META_EVENT, meta_type]) + \
#                    writeVar(len(data_slice)) +  data_slice
#
#            self.event_slice(slc)
#        except:
#            pass

        # Original code:
        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 : str
        """
        self.meta_slice(TEXT, text)

    def copyright(self, text):
        """
        Copyright notice
        text : str
        """
        self.meta_slice(COPYRIGHT, text)

    def sequence_name(self, text):
        """
        Sequence/track name
        text : str
        """
        self.meta_slice(SEQUENCE_NAME, text)

    def instrument_name(self, text):
        """
        text : str
        """
        self.meta_slice(INSTRUMENT_NAME, text)

    def lyric(self, text):
        """
        text : str
        """
        self.meta_slice(LYRIC, text)

    def marker(self, text):
        """
        text : str
        """
        self.meta_slice(MARKER, text)

    def cuepoint(self, text):
        """
        text : str
        """
        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):
        """
        Parameters
        ----------
        nn : number
            the numerator of the notated time signature. The
            number of beats that make up a full measure.

        dd : number
            represents the denominator of the notated time signature
            but NOT as the written number itself. It is

        cc : number
            number of MIDI clocks in a metronome click

        bb : number
            the number of notated 32nd notes in a MIDI quarter note
            (24 MIDI clocks)

#        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)