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