def main(g): # Ensure the BPM is a float, not an integer g['bpm'] = float(g['bpm']) # Convert each gimmick line into a set of BPMs and stops. t = { 'bpms': {0: g['bpm']}, 'stops': {}, } gimmicks = sorted(((str(a), str(b)) for a, b in g['gimmicks'].iteritems()), key=(lambda t: str(t[0]).split('-')[0])) for i, gimmick in enumerate(gimmicks): parse_gimmick(g, t, gimmicks, gimmick, gimmicks[i + 1] if i + 1 < len(gimmicks) else None) # Sort BPMs and stops last_bpm = None rtn = {} for timing in ('bpms', 'stops'): tlist = [] while t[timing]: k = min(t[timing].keys()) v = t[timing].pop(k) if timing == 'bpms' and v == last_bpm: continue tlist.append('%s=%s' % (decimal_from_192nd(k), decimal_from_192nd(v))) if timing == 'bpms': last_bpm = v rtn[timing.upper()] = Timing(','.join(tlist)) return rtn
def parse_gimmick(g, t, gimmicks, gimmick, nextgimmick): beats = gimmick[0] gimmick = gimmick[1].split() # Copy gimmicks if gimmick[0] == 'copy': start, stop = parse_beats(beats, nextgimmick[0] if nextgimmick else None, None) copy_start = float(gimmick[1]) copy_stop = copy_start + stop - start offset = start - copy_start for j, copy_gimmick in enumerate(gimmicks): if (copy_start <= parse_beats(copy_gimmick[0], '0', 0)[0] < copy_stop): parse_gimmick(g, t, gimmicks, add_offset(copy_gimmick, offset), add_offset(gimmicks[j + 1], offset) if j + 1 < len(gimmicks) else None) return # Split the gimmick into its segments try: length, mul, name = gimmick except ValueError: raise ValueError("%s is not of the form 'length mul name'") length = float(Fraction(length)) * 4 mul = float(Fraction(mul.rstrip('x'))) start, stop = parse_beats(beats, nextgimmick[0] if nextgimmick else None, length) full_length = stop - start if 'definitions' in g and name in g['definitions']: definition = g['definitions'][name] elif name in builtin_gimmicks: definition = builtin_gimmicks[name] for timing in ('bpms', 'stops'): if timing in definition: for loc, eq in definition[timing].iteritems(): loc = float(loc) pos = start + length * loc val = eval(eq, { '__builtins__': None, 'mul': mul, 'len': length, 'bpm': g['bpm'], }) while decimal_from_192nd(pos) < decimal_from_192nd(stop): t[timing][pos] = val pos += length if timing == 'bpms': t['bpms'][stop] = g['bpm']