def btime_from_ctime(self, clock_time): tempo_ctime = self.clock_times[mal_misc.binary_search( self.clock_times, clock_time, not_found="force_lower")] tempo = self.t_changes_ctimes[tempo_ctime] tempo_start = self.clock_time_to_beat_time[tempo_ctime] clock_delta = clock_time - tempo_ctime return tempo_start + clock_delta * tempo / 60
def ctime_from_btime(self, beat_time): tempo_btime = self.beat_times[mal_misc.binary_search( self.beat_times, beat_time, not_found="force_lower")] tempo = self.t_changes_btimes[tempo_btime] tempo_start = self.beat_time_to_clock_time[tempo_btime] beat_delta = beat_time - tempo_btime return tempo_start + beat_delta * 60 / tempo
def get_sounding_pitches(self, attack_time, dur=0, min_attack_time=0, min_dur=0): sounding_pitches = set() end_time = attack_time + dur times = list(self.data.keys()) i = mal_misc.binary_search(times, end_time) while i is not None: try: time = times[i] except IndexError: i -= 1 continue i -= 1 notes = self.data[time] break_out = False for note in reversed(notes): if dur > 0 and note.attack_time >= end_time: continue elif note.attack_time > end_time: continue if note.attack_time < min_attack_time: break_out = True break if note.attack_time + note.dur <= attack_time: continue if note.dur >= min_dur: sounding_pitches.add(note.pitch) if i < 0 or break_out: break return list(sorted(sounding_pitches))
def get_prev_n_notes( self, n, time, min_attack_time=0, stop_at_rest=False, include_start_time=False, ): """Like get_prev_n_pitches, but returns Note objects. If notes are attacked earlier than min_attack_time, None will be returned instead. Or, if stop_at_rest is True, then instead of any pitches earlier than the first rest, None will be returned instead. """ attack_times = list(self.data.keys()) i = mal_misc.binary_search(attack_times, time) out_notes = [] if n <= 0: return out_notes while i is not None: i -= 1 if i < 0: break attack_time = attack_times[i] if attack_time == time and not include_start_time: continue notes = self.data[attack_time] break_out = False for note in reversed(notes): if note.attack_time < min_attack_time: break_out = True break if (stop_at_rest and note.attack_time + note.dur < last_attack_time): break_out = True break out_notes.insert(0, note) last_attack_time = note.attack_time if len(out_notes) == n: break_out = True break if break_out: break for j in range(n - len(out_notes)): out_notes.insert(0, None) return out_notes
def get_prev_n_pitches( self, n, time, min_attack_time=0, stop_at_rest=False, include_start_time=False, ): """Returns previous n pitches (attacked before time). If pitches are attacked earlier than min_attack_time, -1 will be returned instead. Or, if stop_at_rest is True, then instead of any pitches earlier than the first rest, -1 will be returned in place. """ attack_times = list(self.data.keys()) i = mal_misc.binary_search(attack_times, time, not_found="force_upper") pitches = [] if n <= 0: return pitches while i is not None: i -= 1 if i < 0: break attack_time = last_attack_time = attack_times[i] if attack_time == time and not include_start_time: continue notes = self.data[attack_time] break_out = False for note in reversed(notes): if note.attack_time < min_attack_time: break_out = True break if (stop_at_rest and note.attack_time + note.dur < last_attack_time): break_out = True break pitches.insert(0, note.pitch) last_attack_time = note.attack_time if len(pitches) == n: break_out = True break if break_out: break for i in range(n - len(pitches)): pitches.insert(0, -1) return pitches