def __make_all_tracks_integer_bar_multiple__(pattern): print ("Making all tracks integer bar length") bar_duration = midiutil.calculate_bar_duration(pattern) print " bar duration", bar_duration orignally_ticks_relative = pattern.tick_relative if pattern.tick_relative: pattern.make_ticks_abs() longest_tick = 0 eot_events = [] for track in pattern: eot_events += midiutil.get_events_from_track(track, "End of Track") eot_events.sort(key=lambda x:x.tick, reverse=True) last_tick = eot_events[0].tick bar_number = int(math.ceil(float(last_tick)/float(bar_duration))) print " number of bars", bar_number tick_length = bar_number * bar_duration for event in eot_events: event.tick = tick_length if orignally_ticks_relative: pattern.make_ticks_rel()
def sample_random_bar(self, tempo=120, channels = [1,2,3], min_notes=0): print self.key, self.scale records = self.db.records_in_key_and_scale(self.key, self.scale) print "Working group size", len(records) result_pattern = midi.Pattern(resolution=480) for channel in channels: track = None loop_count = 0 while track == None: uid = random.choice(records)["id"]; pattern = self.db.pattern(uid) remapper = MidiRemapper("b0rkestra_description.json", pattern) midiutil.pattern_to_resolution(pattern, 480) pattern = remapper.remap_pattern(pattern) track = midiutil.get_track_from_pattern_with_channel(pattern, channel) ##TODO - Get a single bar from the track rather than using the whole track. Then note number checker sould work. if track: track = midiutil.get_bar_from_track(track, 0) note_on_count = len(midiutil.get_events_from_track(track, "Note On")) print "NOTE ONS", note_on_count if note_on_count < min_notes: print ">>>>>>>>>>>>NOT ENOUGH NOTES!!!" track = None continue print self.db.record(uid)["filename"] loop_count += 1 result_pattern.append(track) #result_pattern = midiutil.get_bar_from_pattern(result_pattern, random.choice(range(0,10))) return result_pattern
def __get_track_channel__(track): channels = {} for event in midiutil.get_events_from_track(track, "Note On"): if event.channel in channels: channels[event.channel] += 1 else: channels[event.channel] = 1 if len(channels) == 0: return None main_channel = sorted(channels.items(), key=operator.itemgetter(1))[-1][0] return main_channel
def __name_all_tracks__(pattern): print ("Naming all tracks") for index, track in enumerate(pattern): names = midiutil.get_events_from_track(track, "Track Name") if len(names) == 0: name = "Track "+str(index) name_event = midi.TrackNameEvent(tick=0, text=name) track.insert(0, name_event) print " naming track at index", index, "\""+name+"\"" else: if names[0].text == '': names[0].text = "Track "+str(index) midiutil.remove_events_from_track(track, names[1:])
def __create_range_mapping_for_track__(track, target_channel, lower_note=None, upper_note=None): mapping = {} for event in midiutil.get_events_from_track(track, "Note On"): key = (event.channel, event.pitch) channel = target_channel pitch = event.pitch if lower_note != None: while pitch < lower_note: pitch += 12 if upper_note != None: while pitch > upper_note: pitch -= 12 value = (channel, pitch) mapping[key] = value return mapping
def __find_best_fitting_instrument_for_track(track, description): fit = {} for instrument in description["instruments"]: #if there's an explcit mapping for this instrument then ignore the instrument. #instrument = description["instruments"][instrument] if description["instruments"][instrument].get("input_channel"): continue miss = 0 for event in midiutil.get_events_from_track(track, "Note On"): if description["instruments"][instrument].get("range_min"): if event.pitch < description["instruments"][instrument]["range_min"]: miss += 1 if description["instruments"][instrument].get("range_max"): if event.pitch > description["instruments"][instrument]["range_max"]: miss += 1 fit[instrument] = miss best_instrument = description["instruments"][sorted(fit.items(), key=operator.itemgetter(1))[0][0]] return best_instrument