def managed_transition_helper(track1, track2, state, xfade=0, itrim1=0.0, otrim1=0.0, itrim2=0.0, maxlen=None, mode='equal_power', audition_hack=False): """Manage the transition from one track to another Most of the parameters should be provided by keyword (in Py3, there'd be * after state). state: State mapping - cursor position etc is maintained here xfade: Number of tatums/segments to crossfade over itrim1: Initial trim of first track - ignored unless starting fresh otrim1: Trim end of first track - all these are floating-point seconds itrim2: Trim beginning of second track maxlen: If set, mix duration will be capped to this (protect against over-long transition) mode: Either equal_power or linear audition_hack: If set, cursor position will be reduced by the fade length. Yep, it's a hack. """ if "cursor" not in state: state["cursor"] = 0 log.info("Cursor NOT IN STATE.") else: log.info(state) for track in (track1, track2): loudness = track.analysis.loudness track.gain = db_2_volume(loudness) # NOTE: All values are floating-point seconds, save xfade which is a number # of tatums/segments (assumed to be at average length). t1start = first_viable(track1) + itrim1 t1end = last_viable(track1) - otrim1 t2start = first_viable(track2) + itrim2 # offset between start and first theoretical beat. t2offset = lead_in(track2) if xfade == 0: # Ensure that we always crossfade at least a little bit fade = 0.0001 # Don't allow difference between track start and first beat to prevent hard transition. t2offset = 0 else: # The crossfade is defined based on the tempo at the end # of the song, and we fade across X tatums/segments. avg_duration = avg_end_duration(track1) fade = avg_duration * xfade if audition_hack: log.debug(state['cursor']) state['cursor'] -= fade log.debug("Audition hack") log.debug(state['cursor']) playback_end = t1end - fade - t2offset playback_duration = playback_end - state['cursor'] mix_duration = t1end - playback_end log.info(mix_duration) if maxlen is not None: # Protect from xfade longer than second track. while mix_duration > maxlen: # Chop half a second at a time (not sure why, but let's maintain it for now) mix_duration -= .5 playback_end += .5 playback_duration += .5 pb1 = pb(track1, state['cursor'], playback_duration) pb2 = cf((track1, track2), (playback_end - .01, t2start), mix_duration, mode=mode) state['cursor'] = mix_duration + t2start return [pb1, pb2]
def managed_transition(track1, track2, xfade=0, otrim=0.0, itrim=0.0): state = {"cursor": track1.analysis.duration - 6.0 - float(otrim)} ret = managed_transition_helper(track1, track2, state, xfade=int(xfade), otrim1=float(otrim), itrim2=float(itrim), maxlen=float(track2.analysis.duration), audition_hack=True, ) ret.append(pb(track2, state['cursor'], 6)) print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") print(ret) return ret
def format_track(track, itrim=0.0, otrim=0.0, fadeout=5): playback = pb(track, itrim, track.analysis.duration - otrim) fade = fo(track, track.analysis.duration - otrim, fadeout) return [playback, fade]