Vansh Chugh commited on
Commit
3f552af
·
1 Parent(s): d6d11f2

initial deploy

Browse files
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ .DS_Store
4
+ .venv/
5
+ MMT-repo/
6
+ _outputs/
README.md CHANGED
@@ -1,13 +1,21 @@
1
  ---
2
  title: MMT
3
- emoji: 🏆
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 6.20.0
8
- python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
1
  ---
2
  title: MMT
3
+ emoji: 🛤️
4
  colorFrom: blue
5
  colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 5.28.0
8
+ python_version: '3.11'
9
  app_file: app.py
10
  pinned: false
11
+ license: mit
12
  ---
13
 
14
+ # Multitrack Music Transformer (HARP)
15
+
16
+ HARP wrapper around the official implementation of "Multitrack Music Transformer" (ICASSP 2023).
17
+ Generates symbolic multi-instrument music — optionally continuing from an uploaded MIDI seed, or
18
+ unconditioned if none is given.
19
+
20
+ - Paper: https://arxiv.org/abs/2207.06983
21
+ - Code: https://github.com/salu133445/mmt
SOURCES.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # Sources — MMT
2
+
3
+ - Source repo: https://github.com/salu133445/mmt.git
4
+ - Paper: https://arxiv.org/abs/2207.06983
5
+ - Hardware: undetermined, started on cpu-basic — run `probe_space.py --resize` once app.py is deployed to decide gpu vs cpu
app.py ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+
3
+ sys.stdout.reconfigure(line_buffering=True)
4
+
5
+ try:
6
+ import spaces
7
+ except ImportError:
8
+ # keep @spaces.GPU usable as a no-op; ZeroGPU requires this exact name.
9
+ class spaces:
10
+ class GPU:
11
+ def __init__(self, func=None, duration=60):
12
+ self.func = func
13
+
14
+ def __call__(self, *args, **kwargs):
15
+ if self.func is not None:
16
+ return self.func(*args, **kwargs)
17
+ func = args[0]
18
+ return func
19
+
20
+
21
+ from pathlib import Path
22
+
23
+ # mmt/ keeps the original repo's bare intra-package imports (`import utils`,
24
+ # `import representation`), so it needs to be on sys.path directly rather
25
+ # than imported as a "mmt.*" package.
26
+ sys.path.insert(0, str(Path(__file__).parent / "mmt"))
27
+
28
+ import gradio as gr
29
+ import muspy
30
+ import numpy as np
31
+ import torch
32
+ from pyharp import ModelCard, build_endpoint, get_default_path
33
+
34
+ import music_x_transformers
35
+ import representation
36
+ import utils as mmt_utils
37
+
38
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
39
+ CKPT_DIR = Path(__file__).parent / "checkpoint"
40
+
41
+ train_args = mmt_utils.load_json(CKPT_DIR / "train-args.json")
42
+ encoding = representation.get_encoding()
43
+
44
+
45
+ def load_model():
46
+ """Build the model on CPU and load the sod/ape checkpoint weights. Stays on
47
+ CPU here even if GPU hardware is available -- ZeroGPU only allows touching
48
+ CUDA from inside an @spaces.GPU call, not at module load time."""
49
+ m = music_x_transformers.MusicXTransformer(
50
+ dim=train_args["dim"],
51
+ encoding=encoding,
52
+ depth=train_args["layers"],
53
+ heads=train_args["heads"],
54
+ max_seq_len=train_args["max_seq_len"],
55
+ max_beat=train_args["max_beat"],
56
+ rotary_pos_emb=train_args["rel_pos_emb"],
57
+ use_abs_pos_emb=train_args["abs_pos_emb"],
58
+ emb_dropout=train_args["dropout"],
59
+ attn_dropout=train_args["dropout"],
60
+ ff_dropout=train_args["dropout"],
61
+ )
62
+ state_dict = torch.load(
63
+ CKPT_DIR / "checkpoints" / "best_model.pt", map_location="cpu"
64
+ )
65
+ m.load_state_dict(state_dict)
66
+ m.eval()
67
+ return m
68
+
69
+
70
+ # Checkpoint is small (~80MB) and lives in the Space repo, so load it
71
+ # synchronously at startup rather than in a background thread.
72
+ model = load_model()
73
+ model_ready = False # has the model been moved onto DEVICE yet?
74
+
75
+ # Fetch upfront so failures show in logs, not after a request.
76
+ muspy.download_musescore_soundfont()
77
+
78
+
79
+ def encode_seed(midi_path, encoding, max_beat):
80
+ """Turn an uploaded MIDI file into the token prefix the model continues
81
+ from. Mirrors mmt/convert_sod.py's resolution-adjustment step and
82
+ mmt/dataset.py's max_beat trim, since generate.py normally gets both for
83
+ free from the preprocessed dataset it reads conditioning prefixes from."""
84
+ music = muspy.read(midi_path)
85
+ music.adjust_resolution(encoding["resolution"])
86
+ for track in music:
87
+ for note in track:
88
+ if note.duration == 0:
89
+ note.duration = 1
90
+ music.remove_duplicate()
91
+
92
+ notes = representation.extract_notes(music, encoding["resolution"])
93
+ if len(notes) == 0:
94
+ raise gr.Error("No usable notes found in the uploaded MIDI (check instruments are General MIDI, non-drum).")
95
+ n_beats = notes[-1, 0] + 1
96
+ if n_beats > max_beat:
97
+ notes = notes[notes[:, 0] < max_beat]
98
+
99
+ codes = representation.encode_notes(notes, encoding)
100
+ return codes[:-1] # drop the trailing EOS row so generation continues instead of stopping immediately
101
+
102
+
103
+ @spaces.GPU
104
+ @torch.inference_mode()
105
+ def process_fn(input_midi_path, generation_length, temperature, focus):
106
+ """Generate a multi-instrument continuation of an uploaded MIDI seed, or an
107
+ unconditioned sample if no seed is given, and return it as MIDI + a rendered
108
+ audio preview."""
109
+ global model, model_ready
110
+ if not model_ready:
111
+ model = model.to(DEVICE)
112
+ model_ready = True
113
+
114
+ sos = encoding["type_code_map"]["start-of-song"]
115
+ eos = encoding["type_code_map"]["end-of-song"]
116
+
117
+ if input_midi_path:
118
+ prefix_codes = encode_seed(input_midi_path, encoding, train_args["max_beat"])
119
+ tgt_start = torch.tensor(prefix_codes, dtype=torch.long, device=DEVICE).unsqueeze(0)
120
+ else:
121
+ tgt_start = torch.zeros((1, 1, 6), dtype=torch.long, device=DEVICE)
122
+ tgt_start[:, 0, 0] = sos
123
+
124
+ generated = model.generate(
125
+ tgt_start,
126
+ int(generation_length),
127
+ eos_token=eos,
128
+ temperature=temperature,
129
+ filter_logits_fn="top_k",
130
+ filter_thres=focus,
131
+ monotonicity_dim=("type", "beat"),
132
+ )
133
+ full_codes = torch.cat((tgt_start, generated), 1)[0].cpu().numpy()
134
+
135
+ music = representation.decode(full_codes, encoding)
136
+
137
+ midi_path = get_default_path(ext=".mid")
138
+ music.write(midi_path)
139
+
140
+ audio_path = get_default_path(ext=".wav")
141
+ music.write(audio_path) # uses the MuseScore General soundfont muspy fetches on first use
142
+
143
+ return midi_path, audio_path
144
+
145
+
146
+ model_card = ModelCard(
147
+ name="Multitrack Music Transformer",
148
+ description=(
149
+ "Generates symbolic multi-instrument music. Upload a MIDI seed to continue it, "
150
+ "or leave it empty for an unconditioned generation. Trained on the Symbolic "
151
+ "Orchestral Database (SOD)."
152
+ ),
153
+ author="Hao-Wen Dong, Ke Chen, Shlomo Dubnov, Julian McAuley, Taylor Berg-Kirkpatrick",
154
+ tags=["symbolic-music", "midi", "multitrack", "transformer"],
155
+ )
156
+
157
+
158
+ with gr.Blocks() as demo:
159
+ input_components = [
160
+ gr.File(
161
+ type="filepath",
162
+ label="Seed MIDI (optional)",
163
+ file_types=[".mid", ".midi"],
164
+ ).harp_required(False),
165
+ gr.Slider(
166
+ minimum=64,
167
+ maximum=1024,
168
+ step=64,
169
+ value=1024,
170
+ label="Generation Length",
171
+ info="Number of musical events to generate (default: 1024, per repo config)",
172
+ ),
173
+ gr.Slider(
174
+ minimum=0.1,
175
+ maximum=2.0,
176
+ step=0.1,
177
+ value=1.0,
178
+ label="Randomness",
179
+ info="Sampling temperature -- higher wanders more (default: 1.0, per repo config)",
180
+ ),
181
+ gr.Slider(
182
+ minimum=0.5,
183
+ maximum=0.99,
184
+ step=0.01,
185
+ value=0.9,
186
+ label="Focus",
187
+ info="Higher keeps only the most likely notes; lower allows more variety (default: 0.9, per repo config)",
188
+ ),
189
+ ]
190
+ output_components = [
191
+ gr.File(
192
+ label="Generated MIDI",
193
+ file_types=[".mid", ".midi"],
194
+ ).set_info("The generated multi-instrument MIDI."),
195
+ gr.Audio(
196
+ type="filepath",
197
+ label="Audio Preview",
198
+ ).set_info("A synthesized audio preview of the generated MIDI."),
199
+ ]
200
+
201
+ build_endpoint(
202
+ model_card=model_card,
203
+ input_components=input_components,
204
+ output_components=output_components,
205
+ process_fn=process_fn,
206
+ )
207
+
208
+ if __name__ == "__main__":
209
+ demo.queue().launch(pwa=True)
checkpoint/checkpoints/best_model.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7c24d1ba5b4e6dbeb346b24734c0f7d0b15f3d3c417490f6d106f49d2f000673
3
+ size 79821244
checkpoint/train-args.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"dataset": "sod", "train_names": "data/sod/processed/train-names.txt", "valid_names": "data/sod/processed/valid-names.txt", "in_dir": "data/sod/processed/notes", "out_dir": "/data/herman/workspace/mtmt/exp/sod/ape", "batch_size": 8, "use_csv": false, "aug": true, "max_seq_len": 1024, "max_beat": 256, "dim": 512, "layers": 6, "heads": 8, "dropout": 0.2, "abs_pos_emb": true, "rel_pos_emb": false, "steps": 200000, "valid_steps": 1000, "early_stopping": true, "early_stopping_tolerance": 20, "learning_rate": 0.0005, "lr_warmup_steps": 5000, "lr_decay_steps": 100000, "lr_decay_multiplier": 0.1, "grad_norm_clip": 1.0, "gpu": 7, "jobs": 8, "quiet": false}
mmt/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ """MMT model."""
mmt/encoding.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"resolution": 24, "max_beat": 1024, "max_duration": 384, "dimensions": ["type", "beat", "position", "pitch", "duration", "instrument"], "n_tokens": [5, 1026, 25, 129, 25, 65], "type_code_map": {"start-of-song": 0, "instrument": 1, "start-of-notes": 2, "note": 3, "end-of-song": 4}, "beat_code_map": {"0": 1, "1": 2, "2": 3, "3": 4, "4": 5, "5": 6, "6": 7, "7": 8, "8": 9, "9": 10, "10": 11, "11": 12, "12": 13, "13": 14, "14": 15, "15": 16, "16": 17, "17": 18, "18": 19, "19": 20, "20": 21, "21": 22, "22": 23, "23": 24, "24": 25, "25": 26, "26": 27, "27": 28, "28": 29, "29": 30, "30": 31, "31": 32, "32": 33, "33": 34, "34": 35, "35": 36, "36": 37, "37": 38, "38": 39, "39": 40, "40": 41, "41": 42, "42": 43, "43": 44, "44": 45, "45": 46, "46": 47, "47": 48, "48": 49, "49": 50, "50": 51, "51": 52, "52": 53, "53": 54, "54": 55, "55": 56, "56": 57, "57": 58, "58": 59, "59": 60, "60": 61, "61": 62, "62": 63, "63": 64, "64": 65, "65": 66, "66": 67, "67": 68, "68": 69, "69": 70, "70": 71, "71": 72, "72": 73, "73": 74, "74": 75, "75": 76, "76": 77, "77": 78, "78": 79, "79": 80, "80": 81, "81": 82, "82": 83, "83": 84, "84": 85, "85": 86, "86": 87, "87": 88, "88": 89, "89": 90, "90": 91, "91": 92, "92": 93, "93": 94, "94": 95, "95": 96, "96": 97, "97": 98, "98": 99, "99": 100, "100": 101, "101": 102, "102": 103, "103": 104, "104": 105, "105": 106, "106": 107, "107": 108, "108": 109, "109": 110, "110": 111, "111": 112, "112": 113, "113": 114, "114": 115, "115": 116, "116": 117, "117": 118, "118": 119, "119": 120, "120": 121, "121": 122, "122": 123, "123": 124, "124": 125, "125": 126, "126": 127, "127": 128, "128": 129, "129": 130, "130": 131, "131": 132, "132": 133, "133": 134, "134": 135, "135": 136, "136": 137, "137": 138, "138": 139, "139": 140, "140": 141, "141": 142, "142": 143, "143": 144, "144": 145, "145": 146, "146": 147, "147": 148, "148": 149, "149": 150, "150": 151, "151": 152, "152": 153, "153": 154, "154": 155, "155": 156, "156": 157, "157": 158, "158": 159, "159": 160, "160": 161, "161": 162, "162": 163, "163": 164, "164": 165, "165": 166, "166": 167, "167": 168, "168": 169, "169": 170, "170": 171, "171": 172, "172": 173, "173": 174, "174": 175, "175": 176, "176": 177, "177": 178, "178": 179, "179": 180, "180": 181, "181": 182, "182": 183, "183": 184, "184": 185, "185": 186, "186": 187, "187": 188, "188": 189, "189": 190, "190": 191, "191": 192, "192": 193, "193": 194, "194": 195, "195": 196, "196": 197, "197": 198, "198": 199, "199": 200, "200": 201, "201": 202, "202": 203, "203": 204, "204": 205, "205": 206, "206": 207, "207": 208, "208": 209, "209": 210, "210": 211, "211": 212, "212": 213, "213": 214, "214": 215, "215": 216, "216": 217, "217": 218, "218": 219, "219": 220, "220": 221, "221": 222, "222": 223, "223": 224, "224": 225, "225": 226, "226": 227, "227": 228, "228": 229, "229": 230, "230": 231, "231": 232, "232": 233, "233": 234, "234": 235, "235": 236, "236": 237, "237": 238, "238": 239, "239": 240, "240": 241, "241": 242, "242": 243, "243": 244, "244": 245, "245": 246, "246": 247, "247": 248, "248": 249, "249": 250, "250": 251, "251": 252, "252": 253, "253": 254, "254": 255, "255": 256, "256": 257, "257": 258, "258": 259, "259": 260, "260": 261, "261": 262, "262": 263, "263": 264, "264": 265, "265": 266, "266": 267, "267": 268, "268": 269, "269": 270, "270": 271, "271": 272, "272": 273, "273": 274, "274": 275, "275": 276, "276": 277, "277": 278, "278": 279, "279": 280, "280": 281, "281": 282, "282": 283, "283": 284, "284": 285, "285": 286, "286": 287, "287": 288, "288": 289, "289": 290, "290": 291, "291": 292, "292": 293, "293": 294, "294": 295, "295": 296, "296": 297, "297": 298, "298": 299, "299": 300, "300": 301, "301": 302, "302": 303, "303": 304, "304": 305, "305": 306, "306": 307, "307": 308, "308": 309, "309": 310, "310": 311, "311": 312, "312": 313, "313": 314, "314": 315, "315": 316, "316": 317, "317": 318, "318": 319, "319": 320, "320": 321, "321": 322, "322": 323, "323": 324, "324": 325, "325": 326, "326": 327, "327": 328, "328": 329, "329": 330, "330": 331, "331": 332, "332": 333, "333": 334, "334": 335, "335": 336, "336": 337, "337": 338, "338": 339, "339": 340, "340": 341, "341": 342, "342": 343, "343": 344, "344": 345, "345": 346, "346": 347, "347": 348, "348": 349, "349": 350, "350": 351, "351": 352, "352": 353, "353": 354, "354": 355, "355": 356, "356": 357, "357": 358, "358": 359, "359": 360, "360": 361, "361": 362, "362": 363, "363": 364, "364": 365, "365": 366, "366": 367, "367": 368, "368": 369, "369": 370, "370": 371, "371": 372, "372": 373, "373": 374, "374": 375, "375": 376, "376": 377, "377": 378, "378": 379, "379": 380, "380": 381, "381": 382, "382": 383, "383": 384, "384": 385, "385": 386, "386": 387, "387": 388, "388": 389, "389": 390, "390": 391, "391": 392, "392": 393, "393": 394, "394": 395, "395": 396, "396": 397, "397": 398, "398": 399, "399": 400, "400": 401, "401": 402, "402": 403, "403": 404, "404": 405, "405": 406, "406": 407, "407": 408, "408": 409, "409": 410, "410": 411, "411": 412, "412": 413, "413": 414, "414": 415, "415": 416, "416": 417, "417": 418, "418": 419, "419": 420, "420": 421, "421": 422, "422": 423, "423": 424, "424": 425, "425": 426, "426": 427, "427": 428, "428": 429, "429": 430, "430": 431, "431": 432, "432": 433, "433": 434, "434": 435, "435": 436, "436": 437, "437": 438, "438": 439, "439": 440, "440": 441, "441": 442, "442": 443, "443": 444, "444": 445, "445": 446, "446": 447, "447": 448, "448": 449, "449": 450, "450": 451, "451": 452, "452": 453, "453": 454, "454": 455, "455": 456, "456": 457, "457": 458, "458": 459, "459": 460, "460": 461, "461": 462, "462": 463, "463": 464, "464": 465, "465": 466, "466": 467, "467": 468, "468": 469, "469": 470, "470": 471, "471": 472, "472": 473, "473": 474, "474": 475, "475": 476, "476": 477, "477": 478, "478": 479, "479": 480, "480": 481, "481": 482, "482": 483, "483": 484, "484": 485, "485": 486, "486": 487, "487": 488, "488": 489, "489": 490, "490": 491, "491": 492, "492": 493, "493": 494, "494": 495, "495": 496, "496": 497, "497": 498, "498": 499, "499": 500, "500": 501, "501": 502, "502": 503, "503": 504, "504": 505, "505": 506, "506": 507, "507": 508, "508": 509, "509": 510, "510": 511, "511": 512, "512": 513, "513": 514, "514": 515, "515": 516, "516": 517, "517": 518, "518": 519, "519": 520, "520": 521, "521": 522, "522": 523, "523": 524, "524": 525, "525": 526, "526": 527, "527": 528, "528": 529, "529": 530, "530": 531, "531": 532, "532": 533, "533": 534, "534": 535, "535": 536, "536": 537, "537": 538, "538": 539, "539": 540, "540": 541, "541": 542, "542": 543, "543": 544, "544": 545, "545": 546, "546": 547, "547": 548, "548": 549, "549": 550, "550": 551, "551": 552, "552": 553, "553": 554, "554": 555, "555": 556, "556": 557, "557": 558, "558": 559, "559": 560, "560": 561, "561": 562, "562": 563, "563": 564, "564": 565, "565": 566, "566": 567, "567": 568, "568": 569, "569": 570, "570": 571, "571": 572, "572": 573, "573": 574, "574": 575, "575": 576, "576": 577, "577": 578, "578": 579, "579": 580, "580": 581, "581": 582, "582": 583, "583": 584, "584": 585, "585": 586, "586": 587, "587": 588, "588": 589, "589": 590, "590": 591, "591": 592, "592": 593, "593": 594, "594": 595, "595": 596, "596": 597, "597": 598, "598": 599, "599": 600, "600": 601, "601": 602, "602": 603, "603": 604, "604": 605, "605": 606, "606": 607, "607": 608, "608": 609, "609": 610, "610": 611, "611": 612, "612": 613, "613": 614, "614": 615, "615": 616, "616": 617, "617": 618, "618": 619, "619": 620, "620": 621, "621": 622, "622": 623, "623": 624, "624": 625, "625": 626, "626": 627, "627": 628, "628": 629, "629": 630, "630": 631, "631": 632, "632": 633, "633": 634, "634": 635, "635": 636, "636": 637, "637": 638, "638": 639, "639": 640, "640": 641, "641": 642, "642": 643, "643": 644, "644": 645, "645": 646, "646": 647, "647": 648, "648": 649, "649": 650, "650": 651, "651": 652, "652": 653, "653": 654, "654": 655, "655": 656, "656": 657, "657": 658, "658": 659, "659": 660, "660": 661, "661": 662, "662": 663, "663": 664, "664": 665, "665": 666, "666": 667, "667": 668, "668": 669, "669": 670, "670": 671, "671": 672, "672": 673, "673": 674, "674": 675, "675": 676, "676": 677, "677": 678, "678": 679, "679": 680, "680": 681, "681": 682, "682": 683, "683": 684, "684": 685, "685": 686, "686": 687, "687": 688, "688": 689, "689": 690, "690": 691, "691": 692, "692": 693, "693": 694, "694": 695, "695": 696, "696": 697, "697": 698, "698": 699, "699": 700, "700": 701, "701": 702, "702": 703, "703": 704, "704": 705, "705": 706, "706": 707, "707": 708, "708": 709, "709": 710, "710": 711, "711": 712, "712": 713, "713": 714, "714": 715, "715": 716, "716": 717, "717": 718, "718": 719, "719": 720, "720": 721, "721": 722, "722": 723, "723": 724, "724": 725, "725": 726, "726": 727, "727": 728, "728": 729, "729": 730, "730": 731, "731": 732, "732": 733, "733": 734, "734": 735, "735": 736, "736": 737, "737": 738, "738": 739, "739": 740, "740": 741, "741": 742, "742": 743, "743": 744, "744": 745, "745": 746, "746": 747, "747": 748, "748": 749, "749": 750, "750": 751, "751": 752, "752": 753, "753": 754, "754": 755, "755": 756, "756": 757, "757": 758, "758": 759, "759": 760, "760": 761, "761": 762, "762": 763, "763": 764, "764": 765, "765": 766, "766": 767, "767": 768, "768": 769, "769": 770, "770": 771, "771": 772, "772": 773, "773": 774, "774": 775, "775": 776, "776": 777, "777": 778, "778": 779, "779": 780, "780": 781, "781": 782, "782": 783, "783": 784, "784": 785, "785": 786, "786": 787, "787": 788, "788": 789, "789": 790, "790": 791, "791": 792, "792": 793, "793": 794, "794": 795, "795": 796, "796": 797, "797": 798, "798": 799, "799": 800, "800": 801, "801": 802, "802": 803, "803": 804, "804": 805, "805": 806, "806": 807, "807": 808, "808": 809, "809": 810, "810": 811, "811": 812, "812": 813, "813": 814, "814": 815, "815": 816, "816": 817, "817": 818, "818": 819, "819": 820, "820": 821, "821": 822, "822": 823, "823": 824, "824": 825, "825": 826, "826": 827, "827": 828, "828": 829, "829": 830, "830": 831, "831": 832, "832": 833, "833": 834, "834": 835, "835": 836, "836": 837, "837": 838, "838": 839, "839": 840, "840": 841, "841": 842, "842": 843, "843": 844, "844": 845, "845": 846, "846": 847, "847": 848, "848": 849, "849": 850, "850": 851, "851": 852, "852": 853, "853": 854, "854": 855, "855": 856, "856": 857, "857": 858, "858": 859, "859": 860, "860": 861, "861": 862, "862": 863, "863": 864, "864": 865, "865": 866, "866": 867, "867": 868, "868": 869, "869": 870, "870": 871, "871": 872, "872": 873, "873": 874, "874": 875, "875": 876, "876": 877, "877": 878, "878": 879, "879": 880, "880": 881, "881": 882, "882": 883, "883": 884, "884": 885, "885": 886, "886": 887, "887": 888, "888": 889, "889": 890, "890": 891, "891": 892, "892": 893, "893": 894, "894": 895, "895": 896, "896": 897, "897": 898, "898": 899, "899": 900, "900": 901, "901": 902, "902": 903, "903": 904, "904": 905, "905": 906, "906": 907, "907": 908, "908": 909, "909": 910, "910": 911, "911": 912, "912": 913, "913": 914, "914": 915, "915": 916, "916": 917, "917": 918, "918": 919, "919": 920, "920": 921, "921": 922, "922": 923, "923": 924, "924": 925, "925": 926, "926": 927, "927": 928, "928": 929, "929": 930, "930": 931, "931": 932, "932": 933, "933": 934, "934": 935, "935": 936, "936": 937, "937": 938, "938": 939, "939": 940, "940": 941, "941": 942, "942": 943, "943": 944, "944": 945, "945": 946, "946": 947, "947": 948, "948": 949, "949": 950, "950": 951, "951": 952, "952": 953, "953": 954, "954": 955, "955": 956, "956": 957, "957": 958, "958": 959, "959": 960, "960": 961, "961": 962, "962": 963, "963": 964, "964": 965, "965": 966, "966": 967, "967": 968, "968": 969, "969": 970, "970": 971, "971": 972, "972": 973, "973": 974, "974": 975, "975": 976, "976": 977, "977": 978, "978": 979, "979": 980, "980": 981, "981": 982, "982": 983, "983": 984, "984": 985, "985": 986, "986": 987, "987": 988, "988": 989, "989": 990, "990": 991, "991": 992, "992": 993, "993": 994, "994": 995, "995": 996, "996": 997, "997": 998, "998": 999, "999": 1000, "1000": 1001, "1001": 1002, "1002": 1003, "1003": 1004, "1004": 1005, "1005": 1006, "1006": 1007, "1007": 1008, "1008": 1009, "1009": 1010, "1010": 1011, "1011": 1012, "1012": 1013, "1013": 1014, "1014": 1015, "1015": 1016, "1016": 1017, "1017": 1018, "1018": 1019, "1019": 1020, "1020": 1021, "1021": 1022, "1022": 1023, "1023": 1024, "1024": 1025, "null": 0}, "position_code_map": {"0": 1, "1": 2, "2": 3, "3": 4, "4": 5, "5": 6, "6": 7, "7": 8, "8": 9, "9": 10, "10": 11, "11": 12, "12": 13, "13": 14, "14": 15, "15": 16, "16": 17, "17": 18, "18": 19, "19": 20, "20": 21, "21": 22, "22": 23, "23": 24, "null": 0}, "pitch_code_map": {"0": 1, "1": 2, "2": 3, "3": 4, "4": 5, "5": 6, "6": 7, "7": 8, "8": 9, "9": 10, "10": 11, "11": 12, "12": 13, "13": 14, "14": 15, "15": 16, "16": 17, "17": 18, "18": 19, "19": 20, "20": 21, "21": 22, "22": 23, "23": 24, "24": 25, "25": 26, "26": 27, "27": 28, "28": 29, "29": 30, "30": 31, "31": 32, "32": 33, "33": 34, "34": 35, "35": 36, "36": 37, "37": 38, "38": 39, "39": 40, "40": 41, "41": 42, "42": 43, "43": 44, "44": 45, "45": 46, "46": 47, "47": 48, "48": 49, "49": 50, "50": 51, "51": 52, "52": 53, "53": 54, "54": 55, "55": 56, "56": 57, "57": 58, "58": 59, "59": 60, "60": 61, "61": 62, "62": 63, "63": 64, "64": 65, "65": 66, "66": 67, "67": 68, "68": 69, "69": 70, "70": 71, "71": 72, "72": 73, "73": 74, "74": 75, "75": 76, "76": 77, "77": 78, "78": 79, "79": 80, "80": 81, "81": 82, "82": 83, "83": 84, "84": 85, "85": 86, "86": 87, "87": 88, "88": 89, "89": 90, "90": 91, "91": 92, "92": 93, "93": 94, "94": 95, "95": 96, "96": 97, "97": 98, "98": 99, "99": 100, "100": 101, "101": 102, "102": 103, "103": 104, "104": 105, "105": 106, "106": 107, "107": 108, "108": 109, "109": 110, "110": 111, "111": 112, "112": 113, "113": 114, "114": 115, "115": 116, "116": 117, "117": 118, "118": 119, "119": 120, "120": 121, "121": 122, "122": 123, "123": 124, "124": 125, "125": 126, "126": 127, "127": 128, "null": 0}, "duration_code_map": {"0": 1, "1": 1, "2": 2, "3": 3, "4": 3, "5": 3, "6": 3, "7": 3, "8": 4, "9": 4, "10": 4, "11": 4, "12": 4, "13": 4, "14": 5, "15": 5, "16": 6, "17": 6, "18": 7, "19": 7, "20": 8, "21": 9, "22": 9, "23": 10, "24": 10, "25": 10, "26": 10, "27": 10, "28": 11, "29": 11, "30": 11, "31": 11, "32": 11, "33": 11, "34": 12, "35": 12, "36": 12, "37": 12, "38": 12, "39": 13, "40": 13, "41": 13, "42": 14, "43": 14, "44": 14, "45": 14, "46": 15, "47": 15, "48": 15, "49": 15, "50": 15, "51": 15, "52": 15, "53": 15, "54": 15, "55": 16, "56": 16, "57": 16, "58": 16, "59": 16, "60": 16, "61": 16, "62": 16, "63": 16, "64": 16, "65": 16, "66": 16, "67": 17, "68": 17, "69": 17, "70": 17, "71": 17, "72": 17, "73": 17, "74": 17, "75": 17, "76": 17, "77": 17, "78": 17, "79": 18, "80": 18, "81": 18, "82": 18, "83": 18, "84": 18, "85": 18, "86": 18, "87": 18, "88": 18, "89": 18, "90": 18, "91": 19, "92": 19, "93": 19, "94": 19, "95": 19, "96": 19, "97": 19, "98": 19, "99": 19, "100": 19, "101": 19, "102": 19, "103": 19, "104": 19, "105": 19, "106": 19, "107": 19, "108": 19, "109": 20, "110": 20, "111": 20, "112": 20, "113": 20, "114": 20, "115": 20, "116": 20, "117": 20, "118": 20, "119": 20, "120": 20, "121": 20, "122": 20, "123": 20, "124": 20, "125": 20, "126": 20, "127": 20, "128": 20, "129": 20, "130": 20, "131": 20, "132": 20, "133": 21, "134": 21, "135": 21, "136": 21, "137": 21, "138": 21, "139": 21, "140": 21, "141": 21, "142": 21, "143": 21, "144": 21, "145": 21, "146": 21, "147": 21, "148": 21, "149": 21, "150": 21, "151": 21, "152": 21, "153": 21, "154": 21, "155": 21, "156": 21, "157": 22, "158": 22, "159": 22, "160": 22, "161": 22, "162": 22, "163": 22, "164": 22, "165": 22, "166": 22, "167": 22, "168": 22, "169": 22, "170": 22, "171": 22, "172": 22, "173": 22, "174": 22, "175": 22, "176": 22, "177": 22, "178": 22, "179": 22, "180": 22, "181": 23, "182": 23, "183": 23, "184": 23, "185": 23, "186": 23, "187": 23, "188": 23, "189": 23, "190": 23, "191": 23, "192": 23, "193": 23, "194": 23, "195": 23, "196": 23, "197": 23, "198": 23, "199": 23, "200": 23, "201": 23, "202": 23, "203": 23, "204": 23, "205": 23, "206": 23, "207": 23, "208": 23, "209": 23, "210": 23, "211": 23, "212": 23, "213": 23, "214": 23, "215": 23, "216": 23, "217": 23, "218": 23, "219": 23, "220": 23, "221": 23, "222": 23, "223": 23, "224": 23, "225": 23, "226": 23, "227": 23, "228": 23, "229": 23, "230": 23, "231": 23, "232": 23, "233": 23, "234": 23, "235": 23, "236": 23, "237": 23, "238": 23, "239": 23, "240": 23, "241": 23, "242": 23, "243": 23, "244": 23, "245": 23, "246": 23, "247": 23, "248": 23, "249": 23, "250": 23, "251": 23, "252": 23, "253": 23, "254": 23, "255": 23, "256": 23, "257": 23, "258": 23, "259": 23, "260": 23, "261": 23, "262": 23, "263": 23, "264": 23, "265": 23, "266": 23, "267": 23, "268": 23, "269": 23, "270": 23, "271": 23, "272": 23, "273": 23, "274": 23, "275": 23, "276": 23, "277": 23, "278": 23, "279": 23, "280": 23, "281": 23, "282": 23, "283": 23, "284": 23, "285": 23, "286": 23, "287": 23, "288": 23, "289": 24, "290": 24, "291": 24, "292": 24, "293": 24, "294": 24, "295": 24, "296": 24, "297": 24, "298": 24, "299": 24, "300": 24, "301": 24, "302": 24, "303": 24, "304": 24, "305": 24, "306": 24, "307": 24, "308": 24, "309": 24, "310": 24, "311": 24, "312": 24, "313": 24, "314": 24, "315": 24, "316": 24, "317": 24, "318": 24, "319": 24, "320": 24, "321": 24, "322": 24, "323": 24, "324": 24, "325": 24, "326": 24, "327": 24, "328": 24, "329": 24, "330": 24, "331": 24, "332": 24, "333": 24, "334": 24, "335": 24, "336": 24, "337": 24, "338": 24, "339": 24, "340": 24, "341": 24, "342": 24, "343": 24, "344": 24, "345": 24, "346": 24, "347": 24, "348": 24, "349": 24, "350": 24, "351": 24, "352": 24, "353": 24, "354": 24, "355": 24, "356": 24, "357": 24, "358": 24, "359": 24, "360": 24, "361": 24, "362": 24, "363": 24, "364": 24, "365": 24, "366": 24, "367": 24, "368": 24, "369": 24, "370": 24, "371": 24, "372": 24, "373": 24, "374": 24, "375": 24, "376": 24, "377": 24, "378": 24, "379": 24, "380": 24, "381": 24, "382": 24, "383": 24, "384": 24, "null": 0}, "instrument_code_map": {"piano": 1, "electric-piano": 2, "harpsichord": 3, "clavinet": 4, "celesta": 5, "glockenspiel": 6, "music-box": 7, "vibraphone": 8, "marimba": 9, "xylophone": 10, "tubular-bells": 11, "dulcimer": 12, "organ": 13, "church-organ": 14, "accordion": 15, "harmonica": 16, "bandoneon": 17, "nylon-string-guitar": 18, "steel-string-guitar": 19, "electric-guitar": 20, "bass": 21, "electric-bass": 22, "slap-bass": 23, "synth-bass": 24, "violin": 25, "viola": 26, "cello": 27, "contrabass": 28, "harp": 29, "timpani": 30, "strings": 31, "synth-strings": 32, "voices": 33, "orchestra-hit": 34, "trumpet": 35, "trombone": 36, "tuba": 37, "horn": 38, "brasses": 39, "synth-brasses": 40, "soprano-saxophone": 41, "alto-saxophone": 42, "tenor-saxophone": 43, "baritone-saxophone": 44, "oboe": 45, "english-horn": 46, "bassoon": 47, "clarinet": 48, "piccolo": 49, "flute": 50, "recorder": 51, "pan-flute": 52, "ocarina": 53, "lead": 54, "pad": 55, "sitar": 56, "banjo": 57, "shamisen": 58, "koto": 59, "kalimba": 60, "bag-pipe": 61, "shehnai": 62, "melodic-tom": 63, "synth-drums": 64, "null": 0}, "code_type_map": {"0": "start-of-song", "1": "instrument", "2": "start-of-notes", "3": "note", "4": "end-of-song"}, "code_beat_map": {"1": 0, "2": 1, "3": 2, "4": 3, "5": 4, "6": 5, "7": 6, "8": 7, "9": 8, "10": 9, "11": 10, "12": 11, "13": 12, "14": 13, "15": 14, "16": 15, "17": 16, "18": 17, "19": 18, "20": 19, "21": 20, "22": 21, "23": 22, "24": 23, "25": 24, "26": 25, "27": 26, "28": 27, "29": 28, "30": 29, "31": 30, "32": 31, "33": 32, "34": 33, "35": 34, "36": 35, "37": 36, "38": 37, "39": 38, "40": 39, "41": 40, "42": 41, "43": 42, "44": 43, "45": 44, "46": 45, "47": 46, "48": 47, "49": 48, "50": 49, "51": 50, "52": 51, "53": 52, "54": 53, "55": 54, "56": 55, "57": 56, "58": 57, "59": 58, "60": 59, "61": 60, "62": 61, "63": 62, "64": 63, "65": 64, "66": 65, "67": 66, "68": 67, "69": 68, "70": 69, "71": 70, "72": 71, "73": 72, "74": 73, "75": 74, "76": 75, "77": 76, "78": 77, "79": 78, "80": 79, "81": 80, "82": 81, "83": 82, "84": 83, "85": 84, "86": 85, "87": 86, "88": 87, "89": 88, "90": 89, "91": 90, "92": 91, "93": 92, "94": 93, "95": 94, "96": 95, "97": 96, "98": 97, "99": 98, "100": 99, "101": 100, "102": 101, "103": 102, "104": 103, "105": 104, "106": 105, "107": 106, "108": 107, "109": 108, "110": 109, "111": 110, "112": 111, "113": 112, "114": 113, "115": 114, "116": 115, "117": 116, "118": 117, "119": 118, "120": 119, "121": 120, "122": 121, "123": 122, "124": 123, "125": 124, "126": 125, "127": 126, "128": 127, "129": 128, "130": 129, "131": 130, "132": 131, "133": 132, "134": 133, "135": 134, "136": 135, "137": 136, "138": 137, "139": 138, "140": 139, "141": 140, "142": 141, "143": 142, "144": 143, "145": 144, "146": 145, "147": 146, "148": 147, "149": 148, "150": 149, "151": 150, "152": 151, "153": 152, "154": 153, "155": 154, "156": 155, "157": 156, "158": 157, "159": 158, "160": 159, "161": 160, "162": 161, "163": 162, "164": 163, "165": 164, "166": 165, "167": 166, "168": 167, "169": 168, "170": 169, "171": 170, "172": 171, "173": 172, "174": 173, "175": 174, "176": 175, "177": 176, "178": 177, "179": 178, "180": 179, "181": 180, "182": 181, "183": 182, "184": 183, "185": 184, "186": 185, "187": 186, "188": 187, "189": 188, "190": 189, "191": 190, "192": 191, "193": 192, "194": 193, "195": 194, "196": 195, "197": 196, "198": 197, "199": 198, "200": 199, "201": 200, "202": 201, "203": 202, "204": 203, "205": 204, "206": 205, "207": 206, "208": 207, "209": 208, "210": 209, "211": 210, "212": 211, "213": 212, "214": 213, "215": 214, "216": 215, "217": 216, "218": 217, "219": 218, "220": 219, "221": 220, "222": 221, "223": 222, "224": 223, "225": 224, "226": 225, "227": 226, "228": 227, "229": 228, "230": 229, "231": 230, "232": 231, "233": 232, "234": 233, "235": 234, "236": 235, "237": 236, "238": 237, "239": 238, "240": 239, "241": 240, "242": 241, "243": 242, "244": 243, "245": 244, "246": 245, "247": 246, "248": 247, "249": 248, "250": 249, "251": 250, "252": 251, "253": 252, "254": 253, "255": 254, "256": 255, "257": 256, "258": 257, "259": 258, "260": 259, "261": 260, "262": 261, "263": 262, "264": 263, "265": 264, "266": 265, "267": 266, "268": 267, "269": 268, "270": 269, "271": 270, "272": 271, "273": 272, "274": 273, "275": 274, "276": 275, "277": 276, "278": 277, "279": 278, "280": 279, "281": 280, "282": 281, "283": 282, "284": 283, "285": 284, "286": 285, "287": 286, "288": 287, "289": 288, "290": 289, "291": 290, "292": 291, "293": 292, "294": 293, "295": 294, "296": 295, "297": 296, "298": 297, "299": 298, "300": 299, "301": 300, "302": 301, "303": 302, "304": 303, "305": 304, "306": 305, "307": 306, "308": 307, "309": 308, "310": 309, "311": 310, "312": 311, "313": 312, "314": 313, "315": 314, "316": 315, "317": 316, "318": 317, "319": 318, "320": 319, "321": 320, "322": 321, "323": 322, "324": 323, "325": 324, "326": 325, "327": 326, "328": 327, "329": 328, "330": 329, "331": 330, "332": 331, "333": 332, "334": 333, "335": 334, "336": 335, "337": 336, "338": 337, "339": 338, "340": 339, "341": 340, "342": 341, "343": 342, "344": 343, "345": 344, "346": 345, "347": 346, "348": 347, "349": 348, "350": 349, "351": 350, "352": 351, "353": 352, "354": 353, "355": 354, "356": 355, "357": 356, "358": 357, "359": 358, "360": 359, "361": 360, "362": 361, "363": 362, "364": 363, "365": 364, "366": 365, "367": 366, "368": 367, "369": 368, "370": 369, "371": 370, "372": 371, "373": 372, "374": 373, "375": 374, "376": 375, "377": 376, "378": 377, "379": 378, "380": 379, "381": 380, "382": 381, "383": 382, "384": 383, "385": 384, "386": 385, "387": 386, "388": 387, "389": 388, "390": 389, "391": 390, "392": 391, "393": 392, "394": 393, "395": 394, "396": 395, "397": 396, "398": 397, "399": 398, "400": 399, "401": 400, "402": 401, "403": 402, "404": 403, "405": 404, "406": 405, "407": 406, "408": 407, "409": 408, "410": 409, "411": 410, "412": 411, "413": 412, "414": 413, "415": 414, "416": 415, "417": 416, "418": 417, "419": 418, "420": 419, "421": 420, "422": 421, "423": 422, "424": 423, "425": 424, "426": 425, "427": 426, "428": 427, "429": 428, "430": 429, "431": 430, "432": 431, "433": 432, "434": 433, "435": 434, "436": 435, "437": 436, "438": 437, "439": 438, "440": 439, "441": 440, "442": 441, "443": 442, "444": 443, "445": 444, "446": 445, "447": 446, "448": 447, "449": 448, "450": 449, "451": 450, "452": 451, "453": 452, "454": 453, "455": 454, "456": 455, "457": 456, "458": 457, "459": 458, "460": 459, "461": 460, "462": 461, "463": 462, "464": 463, "465": 464, "466": 465, "467": 466, "468": 467, "469": 468, "470": 469, "471": 470, "472": 471, "473": 472, "474": 473, "475": 474, "476": 475, "477": 476, "478": 477, "479": 478, "480": 479, "481": 480, "482": 481, "483": 482, "484": 483, "485": 484, "486": 485, "487": 486, "488": 487, "489": 488, "490": 489, "491": 490, "492": 491, "493": 492, "494": 493, "495": 494, "496": 495, "497": 496, "498": 497, "499": 498, "500": 499, "501": 500, "502": 501, "503": 502, "504": 503, "505": 504, "506": 505, "507": 506, "508": 507, "509": 508, "510": 509, "511": 510, "512": 511, "513": 512, "514": 513, "515": 514, "516": 515, "517": 516, "518": 517, "519": 518, "520": 519, "521": 520, "522": 521, "523": 522, "524": 523, "525": 524, "526": 525, "527": 526, "528": 527, "529": 528, "530": 529, "531": 530, "532": 531, "533": 532, "534": 533, "535": 534, "536": 535, "537": 536, "538": 537, "539": 538, "540": 539, "541": 540, "542": 541, "543": 542, "544": 543, "545": 544, "546": 545, "547": 546, "548": 547, "549": 548, "550": 549, "551": 550, "552": 551, "553": 552, "554": 553, "555": 554, "556": 555, "557": 556, "558": 557, "559": 558, "560": 559, "561": 560, "562": 561, "563": 562, "564": 563, "565": 564, "566": 565, "567": 566, "568": 567, "569": 568, "570": 569, "571": 570, "572": 571, "573": 572, "574": 573, "575": 574, "576": 575, "577": 576, "578": 577, "579": 578, "580": 579, "581": 580, "582": 581, "583": 582, "584": 583, "585": 584, "586": 585, "587": 586, "588": 587, "589": 588, "590": 589, "591": 590, "592": 591, "593": 592, "594": 593, "595": 594, "596": 595, "597": 596, "598": 597, "599": 598, "600": 599, "601": 600, "602": 601, "603": 602, "604": 603, "605": 604, "606": 605, "607": 606, "608": 607, "609": 608, "610": 609, "611": 610, "612": 611, "613": 612, "614": 613, "615": 614, "616": 615, "617": 616, "618": 617, "619": 618, "620": 619, "621": 620, "622": 621, "623": 622, "624": 623, "625": 624, "626": 625, "627": 626, "628": 627, "629": 628, "630": 629, "631": 630, "632": 631, "633": 632, "634": 633, "635": 634, "636": 635, "637": 636, "638": 637, "639": 638, "640": 639, "641": 640, "642": 641, "643": 642, "644": 643, "645": 644, "646": 645, "647": 646, "648": 647, "649": 648, "650": 649, "651": 650, "652": 651, "653": 652, "654": 653, "655": 654, "656": 655, "657": 656, "658": 657, "659": 658, "660": 659, "661": 660, "662": 661, "663": 662, "664": 663, "665": 664, "666": 665, "667": 666, "668": 667, "669": 668, "670": 669, "671": 670, "672": 671, "673": 672, "674": 673, "675": 674, "676": 675, "677": 676, "678": 677, "679": 678, "680": 679, "681": 680, "682": 681, "683": 682, "684": 683, "685": 684, "686": 685, "687": 686, "688": 687, "689": 688, "690": 689, "691": 690, "692": 691, "693": 692, "694": 693, "695": 694, "696": 695, "697": 696, "698": 697, "699": 698, "700": 699, "701": 700, "702": 701, "703": 702, "704": 703, "705": 704, "706": 705, "707": 706, "708": 707, "709": 708, "710": 709, "711": 710, "712": 711, "713": 712, "714": 713, "715": 714, "716": 715, "717": 716, "718": 717, "719": 718, "720": 719, "721": 720, "722": 721, "723": 722, "724": 723, "725": 724, "726": 725, "727": 726, "728": 727, "729": 728, "730": 729, "731": 730, "732": 731, "733": 732, "734": 733, "735": 734, "736": 735, "737": 736, "738": 737, "739": 738, "740": 739, "741": 740, "742": 741, "743": 742, "744": 743, "745": 744, "746": 745, "747": 746, "748": 747, "749": 748, "750": 749, "751": 750, "752": 751, "753": 752, "754": 753, "755": 754, "756": 755, "757": 756, "758": 757, "759": 758, "760": 759, "761": 760, "762": 761, "763": 762, "764": 763, "765": 764, "766": 765, "767": 766, "768": 767, "769": 768, "770": 769, "771": 770, "772": 771, "773": 772, "774": 773, "775": 774, "776": 775, "777": 776, "778": 777, "779": 778, "780": 779, "781": 780, "782": 781, "783": 782, "784": 783, "785": 784, "786": 785, "787": 786, "788": 787, "789": 788, "790": 789, "791": 790, "792": 791, "793": 792, "794": 793, "795": 794, "796": 795, "797": 796, "798": 797, "799": 798, "800": 799, "801": 800, "802": 801, "803": 802, "804": 803, "805": 804, "806": 805, "807": 806, "808": 807, "809": 808, "810": 809, "811": 810, "812": 811, "813": 812, "814": 813, "815": 814, "816": 815, "817": 816, "818": 817, "819": 818, "820": 819, "821": 820, "822": 821, "823": 822, "824": 823, "825": 824, "826": 825, "827": 826, "828": 827, "829": 828, "830": 829, "831": 830, "832": 831, "833": 832, "834": 833, "835": 834, "836": 835, "837": 836, "838": 837, "839": 838, "840": 839, "841": 840, "842": 841, "843": 842, "844": 843, "845": 844, "846": 845, "847": 846, "848": 847, "849": 848, "850": 849, "851": 850, "852": 851, "853": 852, "854": 853, "855": 854, "856": 855, "857": 856, "858": 857, "859": 858, "860": 859, "861": 860, "862": 861, "863": 862, "864": 863, "865": 864, "866": 865, "867": 866, "868": 867, "869": 868, "870": 869, "871": 870, "872": 871, "873": 872, "874": 873, "875": 874, "876": 875, "877": 876, "878": 877, "879": 878, "880": 879, "881": 880, "882": 881, "883": 882, "884": 883, "885": 884, "886": 885, "887": 886, "888": 887, "889": 888, "890": 889, "891": 890, "892": 891, "893": 892, "894": 893, "895": 894, "896": 895, "897": 896, "898": 897, "899": 898, "900": 899, "901": 900, "902": 901, "903": 902, "904": 903, "905": 904, "906": 905, "907": 906, "908": 907, "909": 908, "910": 909, "911": 910, "912": 911, "913": 912, "914": 913, "915": 914, "916": 915, "917": 916, "918": 917, "919": 918, "920": 919, "921": 920, "922": 921, "923": 922, "924": 923, "925": 924, "926": 925, "927": 926, "928": 927, "929": 928, "930": 929, "931": 930, "932": 931, "933": 932, "934": 933, "935": 934, "936": 935, "937": 936, "938": 937, "939": 938, "940": 939, "941": 940, "942": 941, "943": 942, "944": 943, "945": 944, "946": 945, "947": 946, "948": 947, "949": 948, "950": 949, "951": 950, "952": 951, "953": 952, "954": 953, "955": 954, "956": 955, "957": 956, "958": 957, "959": 958, "960": 959, "961": 960, "962": 961, "963": 962, "964": 963, "965": 964, "966": 965, "967": 966, "968": 967, "969": 968, "970": 969, "971": 970, "972": 971, "973": 972, "974": 973, "975": 974, "976": 975, "977": 976, "978": 977, "979": 978, "980": 979, "981": 980, "982": 981, "983": 982, "984": 983, "985": 984, "986": 985, "987": 986, "988": 987, "989": 988, "990": 989, "991": 990, "992": 991, "993": 992, "994": 993, "995": 994, "996": 995, "997": 996, "998": 997, "999": 998, "1000": 999, "1001": 1000, "1002": 1001, "1003": 1002, "1004": 1003, "1005": 1004, "1006": 1005, "1007": 1006, "1008": 1007, "1009": 1008, "1010": 1009, "1011": 1010, "1012": 1011, "1013": 1012, "1014": 1013, "1015": 1014, "1016": 1015, "1017": 1016, "1018": 1017, "1019": 1018, "1020": 1019, "1021": 1020, "1022": 1021, "1023": 1022, "1024": 1023, "1025": 1024, "0": null}, "code_position_map": {"1": 0, "2": 1, "3": 2, "4": 3, "5": 4, "6": 5, "7": 6, "8": 7, "9": 8, "10": 9, "11": 10, "12": 11, "13": 12, "14": 13, "15": 14, "16": 15, "17": 16, "18": 17, "19": 18, "20": 19, "21": 20, "22": 21, "23": 22, "24": 23, "0": null}, "code_pitch_map": {"1": 0, "2": 1, "3": 2, "4": 3, "5": 4, "6": 5, "7": 6, "8": 7, "9": 8, "10": 9, "11": 10, "12": 11, "13": 12, "14": 13, "15": 14, "16": 15, "17": 16, "18": 17, "19": 18, "20": 19, "21": 20, "22": 21, "23": 22, "24": 23, "25": 24, "26": 25, "27": 26, "28": 27, "29": 28, "30": 29, "31": 30, "32": 31, "33": 32, "34": 33, "35": 34, "36": 35, "37": 36, "38": 37, "39": 38, "40": 39, "41": 40, "42": 41, "43": 42, "44": 43, "45": 44, "46": 45, "47": 46, "48": 47, "49": 48, "50": 49, "51": 50, "52": 51, "53": 52, "54": 53, "55": 54, "56": 55, "57": 56, "58": 57, "59": 58, "60": 59, "61": 60, "62": 61, "63": 62, "64": 63, "65": 64, "66": 65, "67": 66, "68": 67, "69": 68, "70": 69, "71": 70, "72": 71, "73": 72, "74": 73, "75": 74, "76": 75, "77": 76, "78": 77, "79": 78, "80": 79, "81": 80, "82": 81, "83": 82, "84": 83, "85": 84, "86": 85, "87": 86, "88": 87, "89": 88, "90": 89, "91": 90, "92": 91, "93": 92, "94": 93, "95": 94, "96": 95, "97": 96, "98": 97, "99": 98, "100": 99, "101": 100, "102": 101, "103": 102, "104": 103, "105": 104, "106": 105, "107": 106, "108": 107, "109": 108, "110": 109, "111": 110, "112": 111, "113": 112, "114": 113, "115": 114, "116": 115, "117": 116, "118": 117, "119": 118, "120": 119, "121": 120, "122": 121, "123": 122, "124": 123, "125": 124, "126": 125, "127": 126, "128": 127, "0": null}, "code_duration_map": {"1": 1, "2": 2, "3": 3, "4": 12, "5": 15, "6": 16, "7": 18, "8": 20, "9": 21, "10": 24, "11": 30, "12": 36, "13": 40, "14": 42, "15": 48, "16": 60, "17": 72, "18": 84, "19": 96, "20": 120, "21": 144, "22": 168, "23": 192, "24": 384}, "code_instrument_map": {"1": "piano", "2": "electric-piano", "3": "harpsichord", "4": "clavinet", "5": "celesta", "6": "glockenspiel", "7": "music-box", "8": "vibraphone", "9": "marimba", "10": "xylophone", "11": "tubular-bells", "12": "dulcimer", "13": "organ", "14": "church-organ", "15": "accordion", "16": "harmonica", "17": "bandoneon", "18": "nylon-string-guitar", "19": "steel-string-guitar", "20": "electric-guitar", "21": "bass", "22": "electric-bass", "23": "slap-bass", "24": "synth-bass", "25": "violin", "26": "viola", "27": "cello", "28": "contrabass", "29": "harp", "30": "timpani", "31": "strings", "32": "synth-strings", "33": "voices", "34": "orchestra-hit", "35": "trumpet", "36": "trombone", "37": "tuba", "38": "horn", "39": "brasses", "40": "synth-brasses", "41": "soprano-saxophone", "42": "alto-saxophone", "43": "tenor-saxophone", "44": "baritone-saxophone", "45": "oboe", "46": "english-horn", "47": "bassoon", "48": "clarinet", "49": "piccolo", "50": "flute", "51": "recorder", "52": "pan-flute", "53": "ocarina", "54": "lead", "55": "pad", "56": "sitar", "57": "banjo", "58": "shamisen", "59": "koto", "60": "kalimba", "61": "bag-pipe", "62": "shehnai", "63": "melodic-tom", "64": "synth-drums", "0": null}, "program_instrument_map": {"0": "piano", "1": "piano", "2": "piano", "3": "piano", "4": "electric-piano", "5": "electric-piano", "6": "harpsichord", "7": "clavinet", "8": "celesta", "9": "glockenspiel", "10": "music-box", "11": "vibraphone", "12": "marimba", "13": "xylophone", "14": "tubular-bells", "15": "dulcimer", "16": "organ", "17": "organ", "18": "organ", "19": "church-organ", "20": "organ", "21": "accordion", "22": "harmonica", "23": "bandoneon", "24": "nylon-string-guitar", "25": "steel-string-guitar", "26": "electric-guitar", "27": "electric-guitar", "28": "electric-guitar", "29": "electric-guitar", "30": "electric-guitar", "31": "electric-guitar", "32": "bass", "33": "electric-bass", "34": "electric-bass", "35": "electric-bass", "36": "slap-bass", "37": "slap-bass", "38": "synth-bass", "39": "synth-bass", "40": "violin", "41": "viola", "42": "cello", "43": "contrabass", "44": "strings", "45": "strings", "46": "harp", "47": "timpani", "48": "strings", "49": "strings", "50": "synth-strings", "51": "synth-strings", "52": "voices", "53": "voices", "54": "voices", "55": "orchestra-hit", "56": "trumpet", "57": "trombone", "58": "tuba", "59": "trumpet", "60": "horn", "61": "brasses", "62": "synth-brasses", "63": "synth-brasses", "64": "soprano-saxophone", "65": "alto-saxophone", "66": "tenor-saxophone", "67": "baritone-saxophone", "68": "oboe", "69": "english-horn", "70": "bassoon", "71": "clarinet", "72": "piccolo", "73": "flute", "74": "recorder", "75": "pan-flute", "76": null, "77": null, "78": null, "79": "ocarina", "80": "lead", "81": "lead", "82": "lead", "83": "lead", "84": "lead", "85": "lead", "86": "lead", "87": "lead", "88": "pad", "89": "pad", "90": "pad", "91": "pad", "92": "pad", "93": "pad", "94": "pad", "95": "pad", "96": null, "97": null, "98": null, "99": null, "100": null, "101": null, "102": null, "103": null, "104": "sitar", "105": "banjo", "106": "shamisen", "107": "koto", "108": "kalimba", "109": "bag-pipe", "110": "violin", "111": "shehnai", "112": null, "113": null, "114": null, "115": null, "116": null, "117": "melodic-tom", "118": "synth-drums", "119": "synth-drums", "120": null, "121": null, "122": null, "123": null, "124": null, "125": null, "126": null, "127": null, "128": null}, "instrument_program_map": {"piano": 0, "electric-piano": 4, "harpsichord": 6, "clavinet": 7, "celesta": 8, "glockenspiel": 9, "music-box": 10, "vibraphone": 11, "marimba": 12, "xylophone": 13, "tubular-bells": 14, "dulcimer": 15, "organ": 16, "church-organ": 19, "accordion": 21, "harmonica": 22, "bandoneon": 23, "nylon-string-guitar": 24, "steel-string-guitar": 25, "electric-guitar": 26, "bass": 32, "electric-bass": 33, "slap-bass": 36, "synth-bass": 38, "violin": 40, "viola": 41, "cello": 42, "contrabass": 43, "harp": 46, "timpani": 47, "strings": 49, "synth-strings": 50, "voices": 52, "orchestra-hit": 55, "trumpet": 56, "trombone": 57, "tuba": 58, "horn": 60, "brasses": 61, "synth-brasses": 62, "soprano-saxophone": 64, "alto-saxophone": 65, "tenor-saxophone": 66, "baritone-saxophone": 67, "oboe": 68, "english-horn": 69, "bassoon": 70, "clarinet": 71, "piccolo": 72, "flute": 73, "recorder": 74, "pan-flute": 75, "ocarina": 79, "lead": 80, "pad": 88, "sitar": 104, "banjo": 105, "shamisen": 106, "koto": 107, "kalimba": 108, "bag-pipe": 109, "shehnai": 111, "melodic-tom": 117, "synth-drums": 118}}
mmt/music_x_transformers.py ADDED
@@ -0,0 +1,579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import logging
3
+ import pathlib
4
+ import pprint
5
+ import sys
6
+
7
+ import torch
8
+ import torch.nn.functional as F
9
+ from einops import repeat
10
+ from torch import nn
11
+ from x_transformers.autoregressive_wrapper import (
12
+ ENTMAX_ALPHA,
13
+ entmax,
14
+ exists,
15
+ top_a,
16
+ top_k,
17
+ top_p,
18
+ )
19
+ from x_transformers.x_transformers import (
20
+ AbsolutePositionalEmbedding,
21
+ AttentionLayers,
22
+ Decoder,
23
+ TokenEmbedding,
24
+ always,
25
+ default,
26
+ exists,
27
+ )
28
+
29
+ import representation
30
+ import utils
31
+
32
+
33
+ @utils.resolve_paths
34
+ def parse_args(args=None, namespace=None):
35
+ """Parse command-line arguments."""
36
+ parser = argparse.ArgumentParser()
37
+ parser.add_argument(
38
+ "-d",
39
+ "--dataset",
40
+ choices=("sod", "lmd"),
41
+ required=True,
42
+ help="dataset key",
43
+ )
44
+ parser.add_argument(
45
+ "-i", "--in_dir", type=pathlib.Path, help="input data directory"
46
+ )
47
+ parser.add_argument(
48
+ "-q", "--quiet", action="store_true", help="show warnings only"
49
+ )
50
+ return parser.parse_args(args=args, namespace=namespace)
51
+
52
+
53
+ class MusicTransformerWrapper(nn.Module):
54
+ def __init__(
55
+ self,
56
+ *,
57
+ encoding,
58
+ max_seq_len,
59
+ attn_layers,
60
+ emb_dim=None,
61
+ max_beat=None,
62
+ max_mem_len=0.0,
63
+ shift_mem_down=0,
64
+ emb_dropout=0.0,
65
+ num_memory_tokens=None,
66
+ tie_embedding=False,
67
+ use_abs_pos_emb=True,
68
+ l2norm_embed=False,
69
+ ):
70
+ super().__init__()
71
+ assert isinstance(
72
+ attn_layers, AttentionLayers
73
+ ), "attention layers must be one of Encoder or Decoder"
74
+
75
+ dim = attn_layers.dim
76
+ emb_dim = default(emb_dim, dim)
77
+
78
+ self.max_seq_len = max_seq_len
79
+ self.max_mem_len = max_mem_len
80
+ self.shift_mem_down = shift_mem_down
81
+
82
+ n_tokens = encoding["n_tokens"]
83
+ if max_beat is not None:
84
+ beat_dim = encoding["dimensions"].index("beat")
85
+ n_tokens[beat_dim] = max_beat + 1
86
+
87
+ self.l2norm_embed = l2norm_embed
88
+ self.token_emb = nn.ModuleList(
89
+ [
90
+ TokenEmbedding(emb_dim, n, l2norm_embed=l2norm_embed)
91
+ for n in n_tokens
92
+ ]
93
+ )
94
+ self.pos_emb = (
95
+ AbsolutePositionalEmbedding(
96
+ emb_dim, max_seq_len, l2norm_embed=l2norm_embed
97
+ )
98
+ if (use_abs_pos_emb and not attn_layers.has_pos_emb)
99
+ else always(0)
100
+ )
101
+
102
+ self.emb_dropout = nn.Dropout(emb_dropout)
103
+
104
+ self.project_emb = (
105
+ nn.Linear(emb_dim, dim) if emb_dim != dim else nn.Identity()
106
+ )
107
+ self.attn_layers = attn_layers
108
+ self.norm = nn.LayerNorm(dim)
109
+
110
+ self.init_()
111
+
112
+ self.to_logits = (
113
+ nn.ModuleList([nn.Linear(dim, n) for n in n_tokens])
114
+ if not tie_embedding
115
+ else [lambda t: t @ emb.weight.t() for emb in self.token_emb]
116
+ )
117
+
118
+ # memory tokens (like [cls]) from Memory Transformers paper
119
+ num_memory_tokens = default(num_memory_tokens, 0)
120
+ self.num_memory_tokens = num_memory_tokens
121
+ if num_memory_tokens > 0:
122
+ self.memory_tokens = nn.Parameter(
123
+ torch.randn(num_memory_tokens, dim)
124
+ )
125
+
126
+ def init_(self):
127
+ if self.l2norm_embed:
128
+ for emb in self.token_emb:
129
+ nn.init.normal_(emb.emb.weight, std=1e-5)
130
+ nn.init.normal_(self.pos_emb.emb.weight, std=1e-5)
131
+ return
132
+
133
+ for emb in self.token_emb:
134
+ nn.init.kaiming_normal_(emb.emb.weight)
135
+
136
+ def forward(
137
+ self,
138
+ x, # shape : (b, n , d)
139
+ return_embeddings=False,
140
+ mask=None,
141
+ return_mems=False,
142
+ return_attn=False,
143
+ mems=None,
144
+ **kwargs,
145
+ ):
146
+ b, _, _ = x.shape
147
+ num_mem = self.num_memory_tokens
148
+
149
+ x = sum(
150
+ emb(x[..., i]) for i, emb in enumerate(self.token_emb)
151
+ ) + self.pos_emb(x)
152
+ x = self.emb_dropout(x)
153
+
154
+ x = self.project_emb(x)
155
+
156
+ if num_mem > 0:
157
+ mem = repeat(self.memory_tokens, "n d -> b n d", b=b)
158
+ x = torch.cat((mem, x), dim=1)
159
+
160
+ # auto-handle masking after appending memory tokens
161
+ if exists(mask):
162
+ mask = F.pad(mask, (num_mem, 0), value=True)
163
+
164
+ if self.shift_mem_down and exists(mems):
165
+ mems_l, mems_r = (
166
+ mems[: self.shift_mem_down],
167
+ mems[self.shift_mem_down :],
168
+ )
169
+ mems = [*mems_r, *mems_l]
170
+
171
+ x, intermediates = self.attn_layers(
172
+ x, mask=mask, mems=mems, return_hiddens=True, **kwargs
173
+ )
174
+ x = self.norm(x)
175
+
176
+ mem, x = x[:, :num_mem], x[:, num_mem:]
177
+
178
+ out = (
179
+ [to_logit(x) for to_logit in self.to_logits]
180
+ if not return_embeddings
181
+ else x
182
+ )
183
+
184
+ if return_mems:
185
+ hiddens = intermediates.hiddens
186
+ new_mems = (
187
+ list(
188
+ map(
189
+ lambda pair: torch.cat(pair, dim=-2),
190
+ zip(mems, hiddens),
191
+ )
192
+ )
193
+ if exists(mems)
194
+ else hiddens
195
+ )
196
+ new_mems = list(
197
+ map(
198
+ lambda t: t[..., -self.max_mem_len :, :].detach(), new_mems
199
+ )
200
+ )
201
+ return out, new_mems
202
+
203
+ if return_attn:
204
+ attn_maps = list(
205
+ map(
206
+ lambda t: t.post_softmax_attn,
207
+ intermediates.attn_intermediates,
208
+ )
209
+ )
210
+ return out, attn_maps
211
+
212
+ return out
213
+
214
+
215
+ def sample(logits, kind, threshold, temperature, min_p_pow, min_p_ratio):
216
+ """Sample from the logits with a specific sampling strategy."""
217
+ if kind == "top_k":
218
+ probs = F.softmax(top_k(logits, thres=threshold) / temperature, dim=-1)
219
+ elif kind == "top_p":
220
+ probs = F.softmax(top_p(logits, thres=threshold) / temperature, dim=-1)
221
+ elif kind == "top_a":
222
+ probs = F.softmax(
223
+ top_a(logits, min_p_pow=min_p_pow, min_p_ratio=min_p_ratio)
224
+ / temperature,
225
+ dim=-1,
226
+ )
227
+ elif kind == "entmax":
228
+ probs = entmax(logits / temperature, alpha=ENTMAX_ALPHA, dim=-1)
229
+ else:
230
+ raise ValueError(f"Unknown sampling strategy: {kind}")
231
+
232
+ return torch.multinomial(probs, 1)
233
+
234
+
235
+ class MusicAutoregressiveWrapper(nn.Module):
236
+ def __init__(self, net, encoding, ignore_index=-100, pad_value=0):
237
+ super().__init__()
238
+ self.pad_value = pad_value
239
+ self.ignore_index = ignore_index
240
+
241
+ self.net = net
242
+ self.max_seq_len = net.max_seq_len
243
+
244
+ # Get the type codes
245
+ self.sos_type_code = encoding["type_code_map"]["start-of-song"]
246
+ self.eos_type_code = encoding["type_code_map"]["end-of-song"]
247
+ self.son_type_code = encoding["type_code_map"]["start-of-notes"]
248
+ self.instrument_type_code = encoding["type_code_map"]["instrument"]
249
+ self.note_type_code = encoding["type_code_map"]["note"]
250
+
251
+ # Get the dimension indices
252
+ self.dimensions = {
253
+ key: encoding["dimensions"].index(key)
254
+ for key in (
255
+ "type",
256
+ "beat",
257
+ "position",
258
+ "pitch",
259
+ "duration",
260
+ "instrument",
261
+ )
262
+ }
263
+ assert self.dimensions["type"] == 0
264
+
265
+ @torch.no_grad()
266
+ def generate(
267
+ self,
268
+ start_tokens, # shape : (b, n, d)
269
+ seq_len,
270
+ eos_token=None,
271
+ temperature=1.0, # int or list of int
272
+ filter_logits_fn="top_k", # str or list of str
273
+ filter_thres=0.9, # int or list of int
274
+ min_p_pow=2.0,
275
+ min_p_ratio=0.02,
276
+ monotonicity_dim=None,
277
+ return_attn=False,
278
+ **kwargs,
279
+ ):
280
+ _, t, dim = start_tokens.shape
281
+
282
+ if isinstance(temperature, (float, int)):
283
+ temperature = [temperature] * dim
284
+ elif len(temperature) == 1:
285
+ temperature = temperature * dim
286
+ else:
287
+ assert (
288
+ len(temperature) == dim
289
+ ), f"`temperature` must be of length {dim}"
290
+
291
+ if isinstance(filter_logits_fn, str):
292
+ filter_logits_fn = [filter_logits_fn] * dim
293
+ elif len(filter_logits_fn) == 1:
294
+ filter_logits_fn = filter_logits_fn * dim
295
+ else:
296
+ assert (
297
+ len(filter_logits_fn) == dim
298
+ ), f"`filter_logits_fn` must be of length {dim}"
299
+
300
+ if isinstance(filter_thres, (float, int)):
301
+ filter_thres = [filter_thres] * dim
302
+ elif len(filter_thres) == 1:
303
+ filter_thres = filter_thres * dim
304
+ else:
305
+ assert (
306
+ len(filter_thres) == dim
307
+ ), f"`filter_thres` must be of length {dim}"
308
+
309
+ if isinstance(monotonicity_dim, str):
310
+ monotonicity_dim = [self.dimensions[monotonicity_dim]]
311
+ else:
312
+ monotonicity_dim = [self.dimensions[d] for d in monotonicity_dim]
313
+
314
+ was_training = self.net.training
315
+ num_dims = len(start_tokens.shape)
316
+
317
+ if num_dims == 2:
318
+ start_tokens = start_tokens[None, :, :]
319
+
320
+ self.net.eval()
321
+ out = start_tokens
322
+ mask = kwargs.pop("mask", None)
323
+
324
+ if mask is None:
325
+ mask = torch.ones(
326
+ (out.shape[0], out.shape[1]),
327
+ dtype=torch.bool,
328
+ device=out.device,
329
+ )
330
+
331
+ if monotonicity_dim is not None:
332
+ current_values = {
333
+ d: torch.max(start_tokens[:, :, d], 1)[0]
334
+ for d in monotonicity_dim
335
+ }
336
+ else:
337
+ current_values = None
338
+
339
+ instrument_dim = self.dimensions["instrument"]
340
+ type_dim = self.dimensions["type"]
341
+ for _ in range(seq_len):
342
+ x = out[:, -self.max_seq_len :]
343
+ mask = mask[:, -self.max_seq_len :]
344
+
345
+ if return_attn:
346
+ logits, attn = self.net(
347
+ x, mask=mask, return_attn=True, **kwargs
348
+ )
349
+ logits = [l[:, -1, :] for l in logits]
350
+ else:
351
+ logits = [
352
+ l[:, -1, :] for l in self.net(x, mask=mask, **kwargs)
353
+ ]
354
+
355
+ # Enforce monotonicity
356
+ if monotonicity_dim is not None and 0 in monotonicity_dim:
357
+ for i, v in enumerate(current_values[0]):
358
+ logits[0][i, :v] = -float("inf")
359
+
360
+ # Filter out sos token
361
+ logits[0][type_dim, 0] = -float("inf")
362
+
363
+ # Sample from the logits
364
+ sample_type = sample(
365
+ logits[0],
366
+ filter_logits_fn[0],
367
+ filter_thres[0],
368
+ temperature[0],
369
+ min_p_pow,
370
+ min_p_ratio,
371
+ )
372
+
373
+ # Update current values
374
+ if monotonicity_dim is not None and 0 in monotonicity_dim:
375
+ current_values[0] = torch.maximum(
376
+ current_values[0], sample_type.reshape(-1)
377
+ )
378
+
379
+ # Iterate after each sample
380
+ samples = [[s_type] for s_type in sample_type]
381
+ for idx, s_type in enumerate(sample_type):
382
+ # A start-of-song, end-of-song or start-of-notes code
383
+ if s_type in (
384
+ self.sos_type_code,
385
+ self.eos_type_code,
386
+ self.son_type_code,
387
+ ):
388
+ samples[idx] += [torch.zeros_like(s_type)] * (
389
+ len(logits) - 1
390
+ )
391
+ # An instrument code
392
+ elif s_type == self.instrument_type_code:
393
+ samples[idx] += [torch.zeros_like(s_type)] * (
394
+ len(logits) - 2
395
+ )
396
+ logits[instrument_dim][:, 0] = -float("inf") # avoid none
397
+ sampled = sample(
398
+ logits[instrument_dim][idx : idx + 1],
399
+ filter_logits_fn[instrument_dim],
400
+ filter_thres[instrument_dim],
401
+ temperature[instrument_dim],
402
+ min_p_pow,
403
+ min_p_ratio,
404
+ )[0]
405
+ samples[idx].append(sampled)
406
+ # A note code
407
+ elif s_type == self.note_type_code:
408
+ for d in range(1, dim):
409
+ # Enforce monotonicity
410
+ if (
411
+ monotonicity_dim is not None
412
+ and d in monotonicity_dim
413
+ ):
414
+ logits[d][idx, : current_values[d][idx]] = -float(
415
+ "inf"
416
+ )
417
+
418
+ # Sample from the logits
419
+ logits[d][:, 0] = -float("inf") # avoid none
420
+ sampled = sample(
421
+ logits[d][idx : idx + 1],
422
+ filter_logits_fn[d],
423
+ filter_thres[d],
424
+ temperature[d],
425
+ min_p_pow,
426
+ min_p_ratio,
427
+ )[0]
428
+ samples[idx].append(sampled)
429
+
430
+ # Update current values
431
+ if (
432
+ monotonicity_dim is not None
433
+ and d in monotonicity_dim
434
+ ):
435
+ current_values[d][idx] = torch.max(
436
+ current_values[d][idx], sampled
437
+ )[0]
438
+ else:
439
+ raise ValueError(f"Unknown event type code: {s_type}")
440
+
441
+ stacked = torch.stack(
442
+ [torch.cat(s).expand(1, -1) for s in samples], 0
443
+ )
444
+ out = torch.cat((out, stacked), dim=1)
445
+ mask = F.pad(mask, (0, 1), value=True)
446
+
447
+ if exists(eos_token):
448
+ is_eos_tokens = out[..., 0] == eos_token
449
+
450
+ # Mask out everything after the eos tokens
451
+ if is_eos_tokens.any(dim=1).all():
452
+ for i, is_eos_token in enumerate(is_eos_tokens):
453
+ idx = torch.argmax(is_eos_token.byte())
454
+ out[i, idx + 1 :] = self.pad_value
455
+ break
456
+
457
+ out = out[:, t:]
458
+
459
+ if num_dims == 1:
460
+ out = out.squeeze(0)
461
+
462
+ self.net.train(was_training)
463
+
464
+ if return_attn:
465
+ return out, attn
466
+
467
+ return out
468
+
469
+ def forward(self, x, return_list=False, **kwargs):
470
+ xi = x[:, :-1]
471
+ xo = x[:, 1:]
472
+
473
+ # help auto-solve a frequent area of confusion around input masks in auto-regressive
474
+ # if user supplies a mask that is only off by one from the source sequence, resolve it for them
475
+ mask = kwargs.get("mask", None)
476
+ if mask is not None and mask.shape[1] == x.shape[1]:
477
+ mask = mask[:, :-1]
478
+ kwargs["mask"] = mask
479
+
480
+ out = self.net(xi, **kwargs)
481
+ losses = [
482
+ F.cross_entropy(
483
+ out[i].transpose(1, 2),
484
+ xo[..., i],
485
+ ignore_index=self.ignore_index,
486
+ )
487
+ for i in range(len(out))
488
+ ]
489
+ loss = sum(losses)
490
+
491
+ if return_list:
492
+ return loss, losses
493
+ return loss
494
+
495
+
496
+ class MusicXTransformer(nn.Module):
497
+ def __init__(self, *, dim, encoding, **kwargs):
498
+ super().__init__()
499
+ assert "dim" not in kwargs, "dimension must be set with `dim` keyword"
500
+ transformer_kwargs = {
501
+ "max_seq_len": kwargs.pop("max_seq_len"),
502
+ "max_beat": kwargs.pop("max_beat"),
503
+ "emb_dropout": kwargs.pop("emb_dropout", 0),
504
+ "use_abs_pos_emb": kwargs.pop("use_abs_pos_emb", True),
505
+ }
506
+ self.decoder = MusicTransformerWrapper(
507
+ encoding=encoding,
508
+ attn_layers=Decoder(dim=dim, **kwargs),
509
+ **transformer_kwargs,
510
+ )
511
+ self.decoder = MusicAutoregressiveWrapper(
512
+ self.decoder, encoding=encoding
513
+ )
514
+
515
+ @torch.no_grad()
516
+ def generate(self, seq_in, seq_len, **kwargs):
517
+ return self.decoder.generate(seq_in, seq_len, **kwargs)
518
+
519
+ def forward(self, seq, mask=None, **kwargs):
520
+ return self.decoder(seq, mask=mask, **kwargs)
521
+
522
+
523
+ def main():
524
+ """Main function."""
525
+ # Parse the command-line arguments
526
+ args = parse_args()
527
+
528
+ # Set default arguments
529
+ if args.dataset is not None:
530
+ if args.in_dir is None:
531
+ args.in_dir = pathlib.Path(f"data/{args.dataset}/processed/notes")
532
+
533
+ # Set up the logger
534
+ logging.basicConfig(
535
+ stream=sys.stdout,
536
+ level=logging.ERROR if args.quiet else logging.INFO,
537
+ format="%(levelname)-8s %(message)s",
538
+ )
539
+
540
+ # Log arguments
541
+ logging.info(f"Using arguments:\n{pprint.pformat(vars(args))}")
542
+
543
+ # Load the encoding
544
+ encoding = representation.load_encoding(args.in_dir / "encoding.json")
545
+
546
+ # Create the model
547
+ model = MusicXTransformer(
548
+ dim=128,
549
+ encoding=encoding,
550
+ depth=3,
551
+ heads=4,
552
+ max_seq_len=1024,
553
+ max_beat=256,
554
+ rel_pos_bias=True, # relative positional bias
555
+ rotary_pos_emb=True, # rotary positional encoding
556
+ emb_dropout=0.1,
557
+ attn_dropout=0.1,
558
+ ff_dropout=0.1,
559
+ )
560
+
561
+ # Summarize the model
562
+ n_parameters = sum(p.numel() for p in model.parameters())
563
+ n_trainables = sum(
564
+ p.numel() for p in model.parameters() if p.requires_grad
565
+ )
566
+ print(f"Number of parameters: {n_parameters}")
567
+ print(f"Number of trainable parameters: {n_trainables}")
568
+
569
+ # Create test data
570
+ seq = torch.randint(0, 4, (1, 1024, 6))
571
+ mask = torch.ones((1, 1024)).bool()
572
+
573
+ # Pass test data through the model
574
+ loss = model(seq, mask=mask)
575
+ loss.backward()
576
+
577
+
578
+ if __name__ == "__main__":
579
+ main()
mmt/representation.py ADDED
@@ -0,0 +1,756 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Representation utilities."""
2
+ import pathlib
3
+ import pprint
4
+
5
+ import muspy
6
+ import numpy as np
7
+ import pretty_midi
8
+
9
+ import utils
10
+
11
+ # Configuration
12
+ RESOLUTION = 12
13
+ MAX_BEAT = 1024
14
+ MAX_DURATION = 384 # Remember to modify known durations as well!
15
+
16
+ # Dimensions
17
+ # (NOTE: "type" must be the first dimension!)
18
+ # (NOTE: Remember to modify N_TOKENS as well!)
19
+ DIMENSIONS = ["type", "beat", "position", "pitch", "duration", "instrument"]
20
+ assert DIMENSIONS[0] == "type"
21
+
22
+ # Type
23
+ TYPE_CODE_MAP = {
24
+ "start-of-song": 0,
25
+ "instrument": 1,
26
+ "start-of-notes": 2,
27
+ "note": 3,
28
+ "end-of-song": 4,
29
+ }
30
+ CODE_TYPE_MAP = utils.inverse_dict(TYPE_CODE_MAP)
31
+
32
+ # Beat
33
+ BEAT_CODE_MAP = {i: i + 1 for i in range(MAX_BEAT + 1)}
34
+ BEAT_CODE_MAP[None] = 0
35
+ CODE_BEAT_MAP = utils.inverse_dict(BEAT_CODE_MAP)
36
+
37
+ # Position
38
+ POSITION_CODE_MAP = {i: i + 1 for i in range(RESOLUTION)}
39
+ POSITION_CODE_MAP[None] = 0
40
+ CODE_POSITION_MAP = utils.inverse_dict(POSITION_CODE_MAP)
41
+
42
+ # Pitch
43
+ PITCH_CODE_MAP = {i: i + 1 for i in range(128)}
44
+ PITCH_CODE_MAP[None] = 0
45
+ CODE_PITCH_MAP = utils.inverse_dict(PITCH_CODE_MAP)
46
+
47
+ # Duration
48
+ KNOWN_DURATIONS = [
49
+ 1,
50
+ 2,
51
+ 3,
52
+ 4,
53
+ 5,
54
+ 6,
55
+ 7,
56
+ 8,
57
+ 9,
58
+ 10,
59
+ 11,
60
+ 12,
61
+ 15,
62
+ 16,
63
+ 18,
64
+ 20,
65
+ 21,
66
+ 24,
67
+ 30,
68
+ 36,
69
+ 40,
70
+ 42,
71
+ 48,
72
+ 60,
73
+ 72,
74
+ 84,
75
+ 96,
76
+ 120,
77
+ 144,
78
+ 168,
79
+ 192,
80
+ 384,
81
+ ]
82
+ DURATION_CODE_MAP = {
83
+ i: int(np.argmin(np.abs(np.array(KNOWN_DURATIONS) - i))) + 1
84
+ for i in range(MAX_DURATION + 1)
85
+ }
86
+ DURATION_CODE_MAP[None] = 0
87
+ CODE_DURATION_MAP = {
88
+ i + 1: duration for i, duration in enumerate(KNOWN_DURATIONS)
89
+ }
90
+
91
+ # Instrument
92
+ PROGRAM_INSTRUMENT_MAP = {
93
+ # Pianos
94
+ 0: "piano",
95
+ 1: "piano",
96
+ 2: "piano",
97
+ 3: "piano",
98
+ 4: "electric-piano",
99
+ 5: "electric-piano",
100
+ 6: "harpsichord",
101
+ 7: "clavinet",
102
+ # Chromatic Percussion
103
+ 8: "celesta",
104
+ 9: "glockenspiel",
105
+ 10: "music-box",
106
+ 11: "vibraphone",
107
+ 12: "marimba",
108
+ 13: "xylophone",
109
+ 14: "tubular-bells",
110
+ 15: "dulcimer",
111
+ # Organs
112
+ 16: "organ",
113
+ 17: "organ",
114
+ 18: "organ",
115
+ 19: "church-organ",
116
+ 20: "organ",
117
+ 21: "accordion",
118
+ 22: "harmonica",
119
+ 23: "bandoneon",
120
+ # Guitars
121
+ 24: "nylon-string-guitar",
122
+ 25: "steel-string-guitar",
123
+ 26: "electric-guitar",
124
+ 27: "electric-guitar",
125
+ 28: "electric-guitar",
126
+ 29: "electric-guitar",
127
+ 30: "electric-guitar",
128
+ 31: "electric-guitar",
129
+ # Basses
130
+ 32: "bass",
131
+ 33: "electric-bass",
132
+ 34: "electric-bass",
133
+ 35: "electric-bass",
134
+ 36: "slap-bass",
135
+ 37: "slap-bass",
136
+ 38: "synth-bass",
137
+ 39: "synth-bass",
138
+ # Strings
139
+ 40: "violin",
140
+ 41: "viola",
141
+ 42: "cello",
142
+ 43: "contrabass",
143
+ 44: "strings",
144
+ 45: "strings",
145
+ 46: "harp",
146
+ 47: "timpani",
147
+ # Ensemble
148
+ 48: "strings",
149
+ 49: "strings",
150
+ 50: "synth-strings",
151
+ 51: "synth-strings",
152
+ 52: "voices",
153
+ 53: "voices",
154
+ 54: "voices",
155
+ 55: "orchestra-hit",
156
+ # Brass
157
+ 56: "trumpet",
158
+ 57: "trombone",
159
+ 58: "tuba",
160
+ 59: "trumpet",
161
+ 60: "horn",
162
+ 61: "brasses",
163
+ 62: "synth-brasses",
164
+ 63: "synth-brasses",
165
+ # Reed
166
+ 64: "soprano-saxophone",
167
+ 65: "alto-saxophone",
168
+ 66: "tenor-saxophone",
169
+ 67: "baritone-saxophone",
170
+ 68: "oboe",
171
+ 69: "english-horn",
172
+ 70: "bassoon",
173
+ 71: "clarinet",
174
+ # Pipe
175
+ 72: "piccolo",
176
+ 73: "flute",
177
+ 74: "recorder",
178
+ 75: "pan-flute",
179
+ 76: None,
180
+ 77: None,
181
+ 78: None,
182
+ 79: "ocarina",
183
+ # Synth Lead
184
+ 80: "lead",
185
+ 81: "lead",
186
+ 82: "lead",
187
+ 83: "lead",
188
+ 84: "lead",
189
+ 85: "lead",
190
+ 86: "lead",
191
+ 87: "lead",
192
+ # Synth Pad
193
+ 88: "pad",
194
+ 89: "pad",
195
+ 90: "pad",
196
+ 91: "pad",
197
+ 92: "pad",
198
+ 93: "pad",
199
+ 94: "pad",
200
+ 95: "pad",
201
+ # Synth Effects
202
+ 96: None,
203
+ 97: None,
204
+ 98: None,
205
+ 99: None,
206
+ 100: None,
207
+ 101: None,
208
+ 102: None,
209
+ 103: None,
210
+ # Ethnic
211
+ 104: "sitar",
212
+ 105: "banjo",
213
+ 106: "shamisen",
214
+ 107: "koto",
215
+ 108: "kalimba",
216
+ 109: "bag-pipe",
217
+ 110: "violin",
218
+ 111: "shehnai",
219
+ # Percussive
220
+ 112: None,
221
+ 113: None,
222
+ 114: None,
223
+ 115: None,
224
+ 116: None,
225
+ 117: "melodic-tom",
226
+ 118: "synth-drums",
227
+ 119: "synth-drums",
228
+ # Sound effects
229
+ 120: None,
230
+ 121: None,
231
+ 122: None,
232
+ 123: None,
233
+ 124: None,
234
+ 125: None,
235
+ 126: None,
236
+ 127: None,
237
+ }
238
+ INSTRUMENT_PROGRAM_MAP = {
239
+ # Pianos
240
+ "piano": 0,
241
+ "electric-piano": 4,
242
+ "harpsichord": 6,
243
+ "clavinet": 7,
244
+ # Chromatic Percussion
245
+ "celesta": 8,
246
+ "glockenspiel": 9,
247
+ "music-box": 10,
248
+ "vibraphone": 11,
249
+ "marimba": 12,
250
+ "xylophone": 13,
251
+ "tubular-bells": 14,
252
+ "dulcimer": 15,
253
+ # Organs
254
+ "organ": 16,
255
+ "church-organ": 19,
256
+ "accordion": 21,
257
+ "harmonica": 22,
258
+ "bandoneon": 23,
259
+ # Guitars
260
+ "nylon-string-guitar": 24,
261
+ "steel-string-guitar": 25,
262
+ "electric-guitar": 26,
263
+ # Basses
264
+ "bass": 32,
265
+ "electric-bass": 33,
266
+ "slap-bass": 36,
267
+ "synth-bass": 38,
268
+ # Strings
269
+ "violin": 40,
270
+ "viola": 41,
271
+ "cello": 42,
272
+ "contrabass": 43,
273
+ "harp": 46,
274
+ "timpani": 47,
275
+ # Ensemble
276
+ "strings": 49,
277
+ "synth-strings": 50,
278
+ "voices": 52,
279
+ "orchestra-hit": 55,
280
+ # Brass
281
+ "trumpet": 56,
282
+ "trombone": 57,
283
+ "tuba": 58,
284
+ "horn": 60,
285
+ "brasses": 61,
286
+ "synth-brasses": 62,
287
+ # Reed
288
+ "soprano-saxophone": 64,
289
+ "alto-saxophone": 65,
290
+ "tenor-saxophone": 66,
291
+ "baritone-saxophone": 67,
292
+ "oboe": 68,
293
+ "english-horn": 69,
294
+ "bassoon": 70,
295
+ "clarinet": 71,
296
+ # Pipe
297
+ "piccolo": 72,
298
+ "flute": 73,
299
+ "recorder": 74,
300
+ "pan-flute": 75,
301
+ "ocarina": 79,
302
+ # Synth Lead
303
+ "lead": 80,
304
+ # Synth Pad
305
+ "pad": 88,
306
+ # Ethnic
307
+ "sitar": 104,
308
+ "banjo": 105,
309
+ "shamisen": 106,
310
+ "koto": 107,
311
+ "kalimba": 108,
312
+ "bag-pipe": 109,
313
+ "shehnai": 111,
314
+ # Percussive
315
+ "melodic-tom": 117,
316
+ "synth-drums": 118,
317
+ }
318
+ KNOWN_PROGRAMS = list(
319
+ k for k, v in PROGRAM_INSTRUMENT_MAP.items() if v is not None
320
+ )
321
+ KNOWN_INSTRUMENTS = list(dict.fromkeys(INSTRUMENT_PROGRAM_MAP.keys()))
322
+ INSTRUMENT_CODE_MAP = {
323
+ instrument: i + 1 for i, instrument in enumerate(KNOWN_INSTRUMENTS)
324
+ }
325
+ INSTRUMENT_CODE_MAP[None] = 0
326
+ CODE_INSTRUMENT_MAP = utils.inverse_dict(INSTRUMENT_CODE_MAP)
327
+
328
+ N_TOKENS = [
329
+ max(TYPE_CODE_MAP.values()) + 1,
330
+ max(BEAT_CODE_MAP.values()) + 1,
331
+ max(POSITION_CODE_MAP.values()) + 1,
332
+ max(PITCH_CODE_MAP.values()) + 1,
333
+ max(DURATION_CODE_MAP.values()) + 1,
334
+ max(INSTRUMENT_CODE_MAP.values()) + 1,
335
+ ]
336
+
337
+
338
+ def get_encoding():
339
+ """Return the encoding configurations."""
340
+ return {
341
+ "resolution": RESOLUTION,
342
+ "max_beat": MAX_BEAT,
343
+ "max_duration": MAX_DURATION,
344
+ "dimensions": DIMENSIONS,
345
+ "n_tokens": N_TOKENS,
346
+ "type_code_map": TYPE_CODE_MAP,
347
+ "beat_code_map": BEAT_CODE_MAP,
348
+ "position_code_map": POSITION_CODE_MAP,
349
+ "pitch_code_map": PITCH_CODE_MAP,
350
+ "duration_code_map": DURATION_CODE_MAP,
351
+ "instrument_code_map": INSTRUMENT_CODE_MAP,
352
+ "code_type_map": CODE_TYPE_MAP,
353
+ "code_beat_map": CODE_BEAT_MAP,
354
+ "code_position_map": CODE_POSITION_MAP,
355
+ "code_pitch_map": CODE_PITCH_MAP,
356
+ "code_duration_map": CODE_DURATION_MAP,
357
+ "code_instrument_map": CODE_INSTRUMENT_MAP,
358
+ "program_instrument_map": PROGRAM_INSTRUMENT_MAP,
359
+ "instrument_program_map": INSTRUMENT_PROGRAM_MAP,
360
+ }
361
+
362
+
363
+ def load_encoding(filename):
364
+ """Load encoding configurations from a JSON file."""
365
+ encoding = utils.load_json(filename)
366
+ for key in (
367
+ "code_type_map",
368
+ "code_beat_map",
369
+ "code_position_map",
370
+ "code_duration_map",
371
+ "code_pitch_map",
372
+ "code_instrument_map",
373
+ "beat_code_map",
374
+ "position_code_map",
375
+ "duration_code_map",
376
+ "pitch_code_map",
377
+ "program_instrument_map",
378
+ ):
379
+ encoding[key] = {
380
+ int(k) if k != "null" else None: v
381
+ for k, v in encoding[key].items()
382
+ }
383
+ return encoding
384
+
385
+
386
+ def extract_notes(music, resolution):
387
+ """Return a MusPy music object as a note sequence.
388
+
389
+ Each row of the output is a note specified as follows.
390
+
391
+ (beat, position, pitch, duration, program)
392
+
393
+ """
394
+ # Check resolution
395
+ assert music.resolution == resolution
396
+
397
+ # Extract notes
398
+ notes = []
399
+ for track in music:
400
+ if track.is_drum or track.program not in KNOWN_PROGRAMS:
401
+ continue
402
+ for note in track:
403
+ beat, position = divmod(note.time, resolution)
404
+ notes.append(
405
+ (beat, position, note.pitch, note.duration, track.program)
406
+ )
407
+
408
+ # Deduplicate and sort the notes
409
+ notes = sorted(set(notes))
410
+
411
+ return np.array(notes)
412
+
413
+
414
+ def encode_notes(notes, encoding):
415
+ """Encode a note sequence into a sequence of codes.
416
+
417
+ Each row of the input is a note specified as follows.
418
+
419
+ (beat, position, pitch, duration, program)
420
+
421
+ Each row of the output is encoded as follows.
422
+
423
+ (event_type, beat, position, pitch, duration, instrument)
424
+
425
+ """
426
+ # Get variables
427
+ max_beat = encoding["max_beat"]
428
+ max_duration = encoding["max_duration"]
429
+
430
+ # Get maps
431
+ type_code_map = encoding["type_code_map"]
432
+ beat_code_map = encoding["beat_code_map"]
433
+ position_code_map = encoding["position_code_map"]
434
+ pitch_code_map = encoding["pitch_code_map"]
435
+ duration_code_map = encoding["duration_code_map"]
436
+ instrument_code_map = encoding["instrument_code_map"]
437
+ program_instrument_map = encoding["program_instrument_map"]
438
+
439
+ # Get the dimension indices
440
+ beat_dim = encoding["dimensions"].index("beat")
441
+ position_dim = encoding["dimensions"].index("position")
442
+ pitch_dim = encoding["dimensions"].index("pitch")
443
+ duration_dim = encoding["dimensions"].index("duration")
444
+ instrument_dim = encoding["dimensions"].index("instrument")
445
+
446
+ # Start the codes with an SOS row
447
+ codes = [(type_code_map["start-of-song"], 0, 0, 0, 0, 0)]
448
+
449
+ # Extract instruments
450
+ instruments = set(program_instrument_map[note[-1]] for note in notes)
451
+
452
+ # Encode the instruments
453
+ instrument_codes = []
454
+ for instrument in instruments:
455
+ # Skip unknown instruments
456
+ if instrument is None:
457
+ continue
458
+ row = [type_code_map["instrument"], 0, 0, 0, 0, 0]
459
+ row[instrument_dim] = instrument_code_map[instrument]
460
+ instrument_codes.append(row)
461
+
462
+ # Sort the instruments and append them to the code sequence
463
+ instrument_codes.sort()
464
+ codes.extend(instrument_codes)
465
+
466
+ # Encode the notes
467
+ codes.append((type_code_map["start-of-notes"], 0, 0, 0, 0, 0))
468
+ for beat, position, pitch, duration, program in notes:
469
+ # Skip if max_beat has reached
470
+ if beat > max_beat:
471
+ continue
472
+ # Skip unknown instruments
473
+ instrument = program_instrument_map[program]
474
+ if instrument is None:
475
+ continue
476
+ # Encode the note
477
+ row = [type_code_map["note"], 0, 0, 0, 0, 0]
478
+ row[beat_dim] = beat_code_map[beat]
479
+ row[position_dim] = position_code_map[position]
480
+ row[pitch_dim] = pitch_code_map[pitch]
481
+ row[duration_dim] = duration_code_map[min(duration, max_duration)]
482
+ row[instrument_dim] = instrument_code_map[instrument]
483
+ codes.append(row)
484
+
485
+ # End the codes with an EOS row
486
+ codes.append((type_code_map["end-of-song"], 0, 0, 0, 0, 0))
487
+
488
+ return np.array(codes)
489
+
490
+
491
+ def encode(music, encoding):
492
+ """Encode a MusPy music object into a sequence of codes.
493
+
494
+ Each row of the input is encoded as follows.
495
+
496
+ (event_type, beat, position, pitch, duration, instrument)
497
+
498
+ Each row of the output is a note specified as follows.
499
+
500
+ (beat, position, pitch, duration, program)
501
+
502
+ """
503
+ # Extract notes
504
+ notes = extract_notes(music, encoding["resolution"])
505
+
506
+ # Encode the notes
507
+ codes = encode_notes(notes, encoding)
508
+
509
+ return codes
510
+
511
+
512
+ def decode_notes(codes, encoding):
513
+ """Decode codes into a note sequence.
514
+
515
+ Each row of the input is encoded as follows.
516
+
517
+ (event_type, beat, position, pitch, duration, instrument)
518
+
519
+ """
520
+ # Get variables and maps
521
+ code_type_map = encoding["code_type_map"]
522
+ code_beat_map = encoding["code_beat_map"]
523
+ code_position_map = encoding["code_position_map"]
524
+ code_pitch_map = encoding["code_pitch_map"]
525
+ code_duration_map = encoding["code_duration_map"]
526
+ code_instrument_map = encoding["code_instrument_map"]
527
+ instrument_program_map = encoding["instrument_program_map"]
528
+
529
+ # Get the dimension indices
530
+ beat_dim = encoding["dimensions"].index("beat")
531
+ position_dim = encoding["dimensions"].index("position")
532
+ pitch_dim = encoding["dimensions"].index("pitch")
533
+ duration_dim = encoding["dimensions"].index("duration")
534
+ instrument_dim = encoding["dimensions"].index("instrument")
535
+
536
+ # Decode the codes into a sequence of notes
537
+ notes = []
538
+ for row in codes:
539
+ event_type = code_type_map[int(row[0])]
540
+ if event_type in ("start-of-song", "instrument", "start-of-notes"):
541
+ continue
542
+ elif event_type == "end-of-song":
543
+ break
544
+ elif event_type == "note":
545
+ beat = code_beat_map[int(row[beat_dim])]
546
+ position = code_position_map[int(row[position_dim])]
547
+ pitch = code_pitch_map[int(row[pitch_dim])]
548
+ duration = code_duration_map[int(row[duration_dim])]
549
+ instrument = code_instrument_map[int(row[instrument_dim])]
550
+ program = instrument_program_map[instrument]
551
+ notes.append((beat, position, pitch, duration, program))
552
+ else:
553
+ raise ValueError("Unknown event type.")
554
+
555
+ return notes
556
+
557
+
558
+ def reconstruct(notes, resolution):
559
+ """Reconstruct a note sequence to a MusPy Music object."""
560
+ # Construct the MusPy Music object
561
+ music = muspy.Music(resolution=resolution, tempos=[muspy.Tempo(0, 100)])
562
+
563
+ # Append the tracks
564
+ programs = sorted(set(note[-1] for note in notes))
565
+ for program in programs:
566
+ music.tracks.append(muspy.Track(program))
567
+
568
+ # Append the notes
569
+ for beat, position, pitch, duration, program in notes:
570
+ time = beat * resolution + position
571
+ track_idx = programs.index(program)
572
+ music[track_idx].notes.append(muspy.Note(time, pitch, duration))
573
+
574
+ return music
575
+
576
+
577
+ def decode(codes, encoding):
578
+ """Decode codes into a MusPy Music object.
579
+
580
+ Each row of the input is encoded as follows.
581
+
582
+ (event_type, beat, position, pitch, duration, instrument)
583
+
584
+ """
585
+ # Get resolution
586
+ resolution = encoding["resolution"]
587
+
588
+ # Decode codes into a note sequence
589
+ notes = decode_notes(codes, encoding)
590
+
591
+ # Reconstruct the music object
592
+ music = reconstruct(notes, resolution)
593
+
594
+ return music
595
+
596
+
597
+ def dump(data, encoding):
598
+ """Decode the codes and dump as a string."""
599
+ # Get maps
600
+ code_type_map = encoding["code_type_map"]
601
+ code_beat_map = encoding["code_beat_map"]
602
+ code_position_map = encoding["code_position_map"]
603
+ code_pitch_map = encoding["code_pitch_map"]
604
+ code_duration_map = encoding["code_duration_map"]
605
+ code_instrument_map = encoding["code_instrument_map"]
606
+
607
+ # Get the dimension indices
608
+ beat_dim = encoding["dimensions"].index("beat")
609
+ position_dim = encoding["dimensions"].index("position")
610
+ pitch_dim = encoding["dimensions"].index("pitch")
611
+ duration_dim = encoding["dimensions"].index("duration")
612
+ instrument_dim = encoding["dimensions"].index("instrument")
613
+
614
+ # Iterate over the rows
615
+ lines = []
616
+ for row in data:
617
+ event_type = code_type_map[int(row[0])]
618
+ if event_type == "start-of-song":
619
+ lines.append("Start of song")
620
+ elif event_type == "end-of-song":
621
+ lines.append("End of song")
622
+ elif event_type == "instrument":
623
+ instrument = code_instrument_map[int(row[instrument_dim])]
624
+ lines.append(f"Instrument: {instrument}")
625
+ elif event_type == "start-of-notes":
626
+ lines.append("Start of notes")
627
+ elif event_type == "note":
628
+ beat = code_beat_map[int(row[beat_dim])]
629
+ position = code_position_map[int(row[position_dim])]
630
+ pitch = pretty_midi.note_number_to_name(
631
+ code_pitch_map[int(row[pitch_dim])]
632
+ )
633
+ duration = code_duration_map[int(row[duration_dim])]
634
+ instrument = code_instrument_map[int(row[instrument_dim])]
635
+ lines.append(
636
+ f"Note: beat={beat}, position={position}, pitch={pitch}, "
637
+ f"duration={duration}, instrument={instrument}"
638
+ )
639
+ else:
640
+ raise ValueError(f"Unknown event type: {event_type}")
641
+
642
+ return "\n".join(lines)
643
+
644
+
645
+ def save_txt(filename, data, encoding):
646
+ """Dump the codes into a TXT file."""
647
+ with open(filename, "w") as f:
648
+ f.write(dump(data, encoding))
649
+
650
+
651
+ def save_csv_notes(filename, data):
652
+ """Save the representation as a CSV file."""
653
+ assert data.shape[1] == 5
654
+ np.savetxt(
655
+ filename,
656
+ data,
657
+ fmt="%d",
658
+ delimiter=",",
659
+ header="beat,position,pitch,duration,program",
660
+ comments="",
661
+ )
662
+
663
+
664
+ def save_csv_codes(filename, data):
665
+ """Save the representation as a CSV file."""
666
+ assert data.shape[1] == 6
667
+ np.savetxt(
668
+ filename,
669
+ data,
670
+ fmt="%d",
671
+ delimiter=",",
672
+ header="type,beat,position,pitch,duration,instrument",
673
+ comments="",
674
+ )
675
+
676
+
677
+ def main():
678
+ """Main function."""
679
+ # Get the encoding
680
+ encoding = get_encoding()
681
+
682
+ # Save the encoding
683
+ filename = pathlib.Path(__file__).parent / "encoding.json"
684
+ utils.save_json(filename, encoding)
685
+
686
+ # Load encoding
687
+ encoding = load_encoding(filename)
688
+
689
+ # Print the maps
690
+ print(f"{' Maps ':=^40}")
691
+ for key, value in encoding.items():
692
+ if key in (
693
+ "instrument_code_map",
694
+ "code_instrument_map",
695
+ "program_instrument_map",
696
+ "instrument_program_map",
697
+ ):
698
+ print("-" * 40)
699
+ print(f"{key}:")
700
+ pprint.pprint(value, indent=2)
701
+
702
+ # Print the variables
703
+ print(f"{' Variables ':=^40}")
704
+ print(f"resolution: {encoding['resolution']}")
705
+ print(f"max_beat: {encoding['max_beat']}")
706
+ print(f"max_duration: {encoding['max_duration']}")
707
+
708
+ # Print the number of tokens
709
+ print(f"{' Number of tokens ':=^40}")
710
+ keys = ("type", "beat", "position", "pitch", "duration", "instrument")
711
+ for key, value in zip(keys, N_TOKENS):
712
+ print(f"{key}: {value}")
713
+
714
+ # Print an example
715
+ print(f"{'Example':=^40}")
716
+ codes = np.array(
717
+ (
718
+ (0, 0, 0, 0, 0, 0),
719
+ (1, 0, 0, 0, 0, 3),
720
+ (1, 0, 0, 0, 0, 33),
721
+ (2, 0, 0, 0, 0, 0),
722
+ (3, 1, 1, 49, 15, 3),
723
+ (3, 1, 1, 61, 15, 3),
724
+ (3, 1, 1, 65, 15, 3),
725
+ (3, 1, 1, 68, 10, 33),
726
+ (3, 1, 1, 68, 15, 3),
727
+ (3, 2, 1, 68, 10, 33),
728
+ (3, 3, 1, 68, 10, 33),
729
+ (3, 4, 1, 61, 10, 33),
730
+ (3, 4, 1, 61, 15, 3),
731
+ (3, 4, 1, 65, 4, 33),
732
+ (3, 4, 1, 65, 10, 3),
733
+ (3, 4, 1, 68, 10, 3),
734
+ (3, 4, 1, 73, 10, 3),
735
+ (3, 4, 13, 63, 4, 33),
736
+ (4, 0, 0, 0, 0, 0),
737
+ ),
738
+ int,
739
+ )
740
+ print(f"Codes:\n{codes}")
741
+
742
+ print("-" * 40)
743
+ print(f"Decoded:\n{dump(codes, encoding)}")
744
+
745
+ music = decode(codes, encoding)
746
+ print("-" * 40)
747
+ print(f"Decoded music:\n{music}")
748
+
749
+ encoded = encode(music, encoding)
750
+ print("-" * 40)
751
+ print(f"Encoded:\n{encoded}")
752
+ assert np.all(codes == encoded)
753
+
754
+
755
+ if __name__ == "__main__":
756
+ main()
mmt/utils.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Utility functions."""
2
+ import json
3
+ import pathlib
4
+ import warnings
5
+
6
+ import numpy as np
7
+
8
+
9
+ def save_args(filename, args):
10
+ """Save the command-line arguments."""
11
+ args_dict = {}
12
+ for key, value in vars(args).items():
13
+ if isinstance(value, pathlib.Path):
14
+ args_dict[key] = str(value)
15
+ else:
16
+ args_dict[key] = value
17
+ save_json(filename, args_dict)
18
+
19
+
20
+ def inverse_dict(d):
21
+ """Return the inverse dictionary."""
22
+ return {v: k for k, v in d.items()}
23
+
24
+
25
+ def save_txt(filename, data):
26
+ """Save a list to a TXT file."""
27
+ with open(filename, "w", encoding="utf8") as f:
28
+ for item in data:
29
+ f.write(f"{item}\n")
30
+
31
+
32
+ def load_txt(filename):
33
+ """Load a TXT file as a list."""
34
+ with open(filename, encoding="utf8") as f:
35
+ return [line.strip() for line in f]
36
+
37
+
38
+ def save_json(filename, data):
39
+ """Save data as a JSON file."""
40
+ with open(filename, "w", encoding="utf8") as f:
41
+ json.dump(data, f)
42
+
43
+
44
+ def load_json(filename):
45
+ """Load data from a JSON file."""
46
+ with open(filename, encoding="utf8") as f:
47
+ return json.load(f)
48
+
49
+
50
+ def save_csv(filename, data, header=""):
51
+ """Save data as a CSV file."""
52
+ np.savetxt(
53
+ filename, data, fmt="%d", delimiter=",", header=header, comments=""
54
+ )
55
+
56
+
57
+ def load_csv(filename, skiprows=1):
58
+ """Load data from a CSV file."""
59
+ return np.loadtxt(filename, dtype=int, delimiter=",", skiprows=skiprows)
60
+
61
+
62
+ def ignore_exceptions(func):
63
+ """Decorator that ignores all errors and warnings."""
64
+
65
+ def inner(*args, **kwargs):
66
+ with warnings.catch_warnings():
67
+ warnings.simplefilter("ignore")
68
+ try:
69
+ return func(*args, **kwargs)
70
+ except Exception:
71
+ return None
72
+
73
+ return inner
74
+
75
+
76
+ def resolve_paths(func):
77
+ """Decorator that resolves all paths."""
78
+
79
+ def inner(*args, **kwargs):
80
+ parsed = func(*args, **kwargs)
81
+ for key in vars(parsed).keys():
82
+ if isinstance(getattr(parsed, key), pathlib.Path):
83
+ setattr(
84
+ parsed, key, getattr(parsed, key).expanduser().resolve()
85
+ )
86
+ return parsed
87
+
88
+ return inner
model.json ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "MMT",
3
+ "package_dir": "mmt",
4
+ "entry_point": ["representation", "music_x_transformers"],
5
+ "checkpoint": {
6
+ "location": "committed directly to Space repo at checkpoints/sod-ape/",
7
+ "structure": "train-args.json + checkpoints/best_model.pt, preserving the exact relative layout mmt/generate.py expects (train_args = utils.load_json(out_dir / 'train-args.json'); model.load_state_dict(torch.load(out_dir / 'checkpoints' / 'best_model.pt'))",
8
+ "size_mb": 80,
9
+ "source": "sod/ape/ from the README's Pretrained Models SharePoint link"
10
+ }
11
+ }
packages.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ fluidsynth
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ git+https://github.com/TEAMuP-dev/pyharp.git@develop
2
+ # model-specific deps below:
3
+ torch==2.8.0
4
+ torchaudio==2.8.0
5
+ x-transformers==0.25.9
6
+ einops
7
+ muspy
8
+ pretty_midi
9
+ numpy