christopher@45: # -*- coding: utf-8 -*- christopher@45: """ christopher@45: Created on Sat Mar 21 22:19:52 2015 christopher@45: christopher@45: @author: christopherh christopher@45: """ christopher@45: christopher@45: from midiparser import MidiFile, MidiTrack, DeltaTime, MidiEvent christopher@45: #from RhythmParser import Bar christopher@45: christopher@45: from music_objects import * christopher@45: from basic_functions import * christopher@45: christopher@45: christopher@45: christopher@45: christopher@45: def read_midi_file(filename): christopher@45: """ open and read a MIDI file, return a MidiFile object """ christopher@45: christopher@45: #create a midifile object, open and read a midi file christopher@45: midiFile = MidiFile() christopher@45: midiFile.open(filename, 'rb') christopher@45: midiFile.read() christopher@45: midiFile.close() christopher@45: christopher@45: return midiFile christopher@45: christopher@45: # def get_bars(midiFile, trackindex=1): christopher@45: # """ returns a list of bar objects from a MidiFile object """ christopher@45: christopher@45: # # select a track to extract (default = 1, ignoring dummy track 0) christopher@45: # track = midiFile.tracks[trackindex] christopher@45: # eventIndex = 0 christopher@45: # numNotes = 0 christopher@45: christopher@45: # noteonlist = [] christopher@45: # noteOnFound==True christopher@45: christopher@45: # while noteOnFound==True: christopher@45: # (noteOnIndex, noteOnDelta, noteOnFound) = self.find_event(track, eventIndex, lambda e: e.type == 'NOTE_ON') christopher@45: # noteEvent = track.events[noteOnIndex] christopher@45: # eventIndex = noteOnIndex + 1 christopher@45: christopher@45: christopher@45: #find_event(x.tracks[0], 0, lambda e: (e.type == 'NOTE_ON') | (e.type == 'KEY_SIGNATURE') | (e.type == "TIME_SIGNATURE")) christopher@45: christopher@45: ''' christopher@45: #read midiFile christopher@45: christopher@45: christopher@45: christopher@45: run through selected track getting notes out to build bars christopher@45: christopher@45: ''' christopher@45: christopher@45: christopher@45: christopher@45: def get_bars_from_midi(midiFile): christopher@45: christopher@45: # couple of inner functions to tidy up getting the initial values of christopher@45: # tempo and time signature christopher@45: def get_initial_tempo(timeList): christopher@45: christopher@45: tempo = None christopher@45: i=0 christopher@45: # Find the initial time and tempo: christopher@45: while(tempo == None and i=barEndTime: christopher@45: break christopher@45: christopher@45: if event.type=="TIME_SIGNATURE" and event.time>=barStartTime: christopher@45: timesig = midi_event_to_time_signature(event) christopher@45: event.type = "USED_TIME_SIGNATURE" christopher@45: christopher@45: if timesig==None: christopher@45: if currentTimeSignature==None: christopher@45: timesig = TimeSignature("4/4") christopher@45: else: christopher@45: timesig = currentTimeSignature christopher@45: christopher@45: return timesig christopher@45: christopher@45: def get_tempo(timeList,barStartTime, barEndTime, currentTempo = None): christopher@45: christopher@45: tempo = None christopher@45: i=0 christopher@45: # get first event: christopher@45: while(i=barEndTime: christopher@45: break christopher@45: christopher@45: # run through list until we find the most recent tempo christopher@45: # before the end of the current bar christopher@45: if event.type=="SET_TEMPO" and event.time>=barStartTime: christopher@45: tempo = midi_event_to_qpm_tempo(event) christopher@45: event.type = "USED_TEMPO" christopher@45: christopher@45: if tempo==None: christopher@45: if currentTempo==None: christopher@45: tempo = 120 christopher@45: else: christopher@45: tempo = currentTempo christopher@45: christopher@45: return tempo christopher@45: christopher@45: christopher@45: christopher@45: # get initial time sig and tempo or use defaults christopher@45: timeList = get_time_events(midiFile) christopher@45: christopher@45: # get notes from the midi file (absolute start times from start of file) christopher@45: notesList = get_notes_from_event_list(get_note_events(midiFile)) christopher@45: christopher@45: christopher@45: # get initial tempo and time signature from time list christopher@45: timesig = get_initial_time_signature(timeList) christopher@45: tempo = get_initial_tempo(timeList) christopher@45: christopher@45: christopher@45: christopher@45: christopher@45: # ticks per quarter note: christopher@45: ticksPerQuarter = midiFile.ticksPerQuarterNote christopher@45: #calculate the initial length of a bar in ticks christopher@45: barlength = calculate_bar_ticks(timesig.get_numerator(), timesig.get_denominator(), ticksPerQuarter) christopher@45: # initialise time for start and end of current bar christopher@45: barStartTime = 0 christopher@45: barEndTime = barlength christopher@45: christopher@45: christopher@45: # initialise bars list christopher@45: bars = BarList() christopher@45: noteIndex = 0 christopher@45: christopher@45: note = notesList[0] christopher@45: # run through the notes list, chopping it into bars christopher@45: while noteIndex