This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 2.9 kB View raw
1#!/usr/bin/env python 2""" 3Usage: flp_to_json.py <input_flp_file> <output_json_file> 4""" 5 6from pathlib import Path 7from docopt import docopt 8import pyflp 9import json 10 11 12def clip_type(clip) -> str: 13 if hasattr(clip, "pattern"): 14 return "pattern" 15 elif hasattr(clip, "channel"): 16 return "channel" 17 18 19def clip_name(clip) -> str: 20 if clip_type(clip) == "pattern": 21 return clip.pattern.name 22 elif clip_type(clip) == "channel": 23 return clip.channel.name 24 else: 25 return "" 26 27 28def key_to_midi_pitch(note: str) -> int: 29 letter = note[0] 30 if len(note) == 3: 31 sharp = True 32 octave = int(note[2]) 33 else: 34 sharp = False 35 octave = int(note[1]) 36 37 letter_delta = {"C": -9, "D": -7, "E": -5, "F": -4, "G": -2, "A": 0, "B": 2}.get( 38 letter, 0 39 ) 40 return 81 + 12 * (octave - 4) + letter_delta + int(sharp) 41 42 43def note_data(note): 44 return { 45 "key": note.key, 46 "pitch": key_to_midi_pitch(note.key), 47 "length": note.length, 48 "velocity": note.velocity, 49 } 50 51 52def clip_data(clip): 53 if clip_type(clip) == "pattern": 54 pat = clip.pattern 55 return { 56 "notes": {note.position: note_data(note) for note in pat.notes}, 57 "values": {}, 58 "length": pat.length, 59 } 60 elif clip_type(clip) == "channel": 61 chan = clip.channel 62 if isinstance(chan, pyflp.channel.Automation): 63 return { 64 "notes": {}, 65 "values": {point.position: point.value for point in chan}, 66 "length": chan.length, 67 } 68 return { 69 "notes": {}, 70 "values": {}, 71 "length": chan.length, 72 } 73 return { 74 "notes": {}, 75 "values": {}, 76 "length": 0, 77 } 78 79 80def track_name(track) -> str: 81 if track.name: 82 return track.name 83 84 clips_names = [clip_name(clip) for clip in track if clip_name(clip)] 85 if not clips_names: 86 return "" 87 88 return clips_names[0] 89 90 91def serialize_track(track): 92 out = {} 93 for clip in track: 94 out[clip.position] = { 95 "length": clip.length, 96 "name": clip_name(clip), 97 "data": clip_data(clip), 98 } 99 100 return out 101 102 103def main(): 104 args = docopt(__doc__) 105 project = pyflp.parse(args["<input_flp_file>"]) 106 107 out = { 108 "info": {"name": project.title, "bpm": project.tempo}, 109 "arrangements": {}, 110 } 111 112 for a in project.arrangements: 113 out["arrangements"][a.name] = { 114 "tracks": { 115 track_name(track): serialize_track(track) for track in a.tracks 116 }, 117 "markers": { 118 marker.position: marker.name for marker in a.timemarkers 119 }, 120 } 121 122 Path(args["<output_json_file>"]).write_text(json.dumps(out, indent=4)) 123 124 125# end 126 127 128if __name__ == "__main__": 129 main()