X-Git-Url: https://scm.cri.minesparis.psl.eu/git/minwii.git/blobdiff_plain/346a9b8e1fcfe30629f0d1ee4675e9e8f89890cf..4c4732c6ed8cb0aaa70fb2d4c6e5a958868c5349:/src/mxmMidi/MidiOutFile.py diff --git a/src/mxmMidi/MidiOutFile.py b/src/mxmMidi/MidiOutFile.py deleted file mode 100644 index a39bc9f..0000000 --- a/src/mxmMidi/MidiOutFile.py +++ /dev/null @@ -1,448 +0,0 @@ -# -*- 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() \ No newline at end of file