projectlosangeles commited on
Commit
45a2559
·
verified ·
1 Parent(s): 0a69bcf

Upload 6 files

Browse files
Files changed (6) hide show
  1. TMIDIX.py +0 -0
  2. app.py +451 -0
  3. midi_to_colab_audio.py +0 -0
  4. packages.txt +1 -0
  5. requirements.txt +10 -0
  6. x_transformer_2_3_1.py +0 -0
TMIDIX.py ADDED
The diff for this file is too large to render. See raw diff
 
app.py ADDED
@@ -0,0 +1,451 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #=================================================================================
2
+ # https://huggingface.co/spaces/projectlosangeles/Orpheus-Masked-Pitches-Inpainter
3
+ #=================================================================================
4
+
5
+ print('=' * 70)
6
+ print('Orpheus Masked Pitches Inpainter Gradio App')
7
+ print('=' * 70)
8
+
9
+ import os
10
+
11
+ os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "1"
12
+ os.environ['USE_FLASH_ATTENTION'] = '1'
13
+
14
+ import time as reqtime
15
+ from pytz import timezone
16
+
17
+ import torch
18
+
19
+ torch.set_float32_matmul_precision('high')
20
+ torch.backends.cuda.matmul.allow_tf32 = True
21
+ torch.backends.cudnn.allow_tf32 = True
22
+ torch.backends.cuda.enable_mem_efficient_sdp(True)
23
+ torch.backends.cuda.enable_math_sdp(True)
24
+ torch.backends.cuda.enable_flash_sdp(True)
25
+ torch.backends.cuda.enable_cudnn_sdp(True)
26
+
27
+ import spaces
28
+ import gradio as gr
29
+
30
+ from x_transformer_2_3_1 import *
31
+
32
+ import datetime
33
+ import random
34
+ import tqdm
35
+
36
+ from midi_to_colab_audio import midi_to_colab_audio
37
+ import TMIDIX
38
+
39
+ import matplotlib.pyplot as plt
40
+
41
+ from huggingface_hub import hf_hub_download
42
+
43
+ # =================================================================================================
44
+
45
+ print('=' * 70)
46
+ print('Loading models...')
47
+ print('=' * 70)
48
+ print('Loading chords texturing model...')
49
+ print('=' * 70)
50
+
51
+ SEQ_LEN = 2048
52
+ PAD_IDX = 721
53
+ DEVICE = 'cuda'
54
+
55
+ tex_model = TransformerWrapper(
56
+ num_tokens = PAD_IDX+1,
57
+ max_seq_len = SEQ_LEN,
58
+ attn_layers = Decoder(dim = 2048,
59
+ depth = 12,
60
+ heads = 16,
61
+ rotary_pos_emb = True,
62
+ attn_flash = True
63
+ )
64
+ )
65
+
66
+ tex_model = AutoregressiveWrapper(tex_model, ignore_index=PAD_IDX)
67
+
68
+ tex_model.to(DEVICE)
69
+ print('=' * 70)
70
+
71
+ print('Loading model checkpoint...')
72
+
73
+ checkpoint = hf_hub_download(
74
+ repo_id='asigalov61/Chordified-Piano-Transformer',
75
+ filename='Chordified_Piano_Transformer_Texturing_Trained_Model_18092_steps_0.7058_loss_0.7977_acc.pth'
76
+ )
77
+
78
+ tex_model.load_state_dict(torch.load(checkpoint, map_location=DEVICE, weights_only=True))
79
+
80
+ tex_model.eval()
81
+
82
+ tex_model = torch.compile(tex_model)
83
+
84
+ print('=' * 70)
85
+ print('Done!')
86
+ print('=' * 70)
87
+
88
+ # =================================================================================================
89
+
90
+ print('Loading chords progressions model...')
91
+ print('=' * 70)
92
+
93
+ SEQ_LEN = 380
94
+ PAD_IDX = 324
95
+ DEVICE = 'cuda'
96
+
97
+ prg_model = TransformerWrapper(
98
+ num_tokens = PAD_IDX+1,
99
+ max_seq_len = SEQ_LEN,
100
+ attn_layers = Decoder(dim = 2048,
101
+ depth = 6,
102
+ heads = 16,
103
+ rotary_pos_emb = True,
104
+ attn_flash = True
105
+ )
106
+ )
107
+
108
+ prg_model = AutoregressiveWrapper(prg_model, ignore_index=PAD_IDX)
109
+
110
+ prg_model.to(DEVICE)
111
+ print('=' * 70)
112
+
113
+ print('Loading model checkpoint...')
114
+
115
+ checkpoint = hf_hub_download(
116
+ repo_id='asigalov61/Chordified-Piano-Transformer',
117
+ filename='Chordified_Piano_Transformer_Chords_Progressions_Trained_Model_3569_steps_1.8604_loss_0.4727_acc.pth'
118
+ )
119
+
120
+ prg_model.load_state_dict(torch.load(checkpoint, map_location=DEVICE, weights_only=True))
121
+
122
+ prg_model.eval()
123
+
124
+ prg_model = torch.compile(prg_model)
125
+
126
+ print('=' * 70)
127
+
128
+ # =================================================================================================
129
+
130
+ dtype = torch.bfloat16
131
+
132
+ ctx = torch.amp.autocast(device_type=DEVICE, dtype=dtype)
133
+
134
+ print('Done!')
135
+ print('=' * 70)
136
+
137
+ # =================================================================================================
138
+
139
+ print('Loading SoundFont...')
140
+
141
+ SOUNDFONT_PATH = hf_hub_download(repo_id='projectlosangeles/soundfonts4u',
142
+ repo_type='dataset',
143
+ filename='SGM-v2.01-YamahaGrand-Guit-Bass-v2.7.sf2'
144
+ )
145
+
146
+ print('Done!')
147
+ print('=' * 70)
148
+
149
+ # =================================================================================================
150
+
151
+ @spaces.GPU
152
+ def generate_chords(chords,
153
+ input_temperature,
154
+ input_top_p_value
155
+ ):
156
+
157
+ print('*' * 70)
158
+ print('Generating chords progression...')
159
+
160
+ chords = [321] + chords + [322]
161
+
162
+ x = torch.LongTensor([chords] * 256).to(DEVICE)
163
+
164
+ with ctx:
165
+ out = prg_model.generate(x,
166
+ 380-len(chords),
167
+ temperature=input_temperature,
168
+ filter_logits_fn=top_p,
169
+ filter_kwargs={'thres': input_top_p_value},
170
+ eos_token=323,
171
+ return_prime=False,
172
+ verbose=True
173
+ )
174
+
175
+ out = out.tolist()
176
+
177
+ good_outs = []
178
+
179
+ for o in out:
180
+ if len(set(o)) >= len(chords):
181
+ good_outs.append(o)
182
+
183
+ if len(good_outs) > 0:
184
+ cho_prg = sorted(good_outs, key=lambda x: -len(set(x)))[0]
185
+
186
+ else:
187
+ cho_prg = sorted(out, key=lambda x: -len(set(x)))[0]
188
+
189
+ cho_prg = [c for c in cho_prg if 0 <= c < 321]
190
+
191
+ ncho = [0, 89, 178, 233, 267, 288, 301, 309, 314, 317, 319, 320]
192
+
193
+ inp_cho_prg = [c+140 if c not in ncho else ncho.index(c)+128 for c in cho_prg]
194
+
195
+ print('Done!')
196
+ print('*' * 70)
197
+ print('Number of good chords progressions:', len(good_outs))
198
+ print('*' * 70)
199
+ print('Texturing selected generated chords progression...')
200
+
201
+ x = torch.LongTensor([718] + inp_cho_prg + [719]).to(DEVICE)
202
+
203
+ with ctx:
204
+ out = tex_model.generate(x,
205
+ 2048-len(cho_prg)+2,
206
+ temperature=input_temperature,
207
+ filter_logits_fn=top_p,
208
+ filter_kwargs={'thres': input_top_p_value},
209
+ eos_token=720,
210
+ return_prime=False,
211
+ verbose=True
212
+ )
213
+
214
+ score = out.tolist()
215
+
216
+ print('Done!')
217
+ print('=' * 70)
218
+
219
+ return cho_prg, score
220
+
221
+ # =================================================================================================
222
+
223
+ def tokens_to_escore_notes(tokens):
224
+
225
+ song_f = []
226
+
227
+ time = 0
228
+ dur = 1
229
+ vel = 90
230
+ pitch = 60
231
+ channel = 0
232
+ patch = 0
233
+
234
+ patches = [0] * 16
235
+
236
+ for m in tokens:
237
+
238
+ if 0 <= m < 128:
239
+ time += m
240
+
241
+ elif 461 < m < 589:
242
+ pitch = (m-461)
243
+
244
+ elif 589 < m < 717:
245
+ dur = (m-589)
246
+ song_f.append(['note', time, dur, 0, pitch, max(40, pitch), 0])
247
+
248
+ return song_f
249
+
250
+ # =================================================================================================
251
+
252
+ def Generate_Chords(input_example,
253
+ input_chords,
254
+ input_temperature,
255
+ input_top_p_value
256
+ ):
257
+
258
+ print('=' * 70)
259
+ print('Req start time: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now(PDT)))
260
+ start_time = reqtime.time()
261
+
262
+ print('=' * 70)
263
+ print('Input example:', input_example)
264
+ print('Input chords:', input_chords)
265
+ print('Req model temp:', input_temperature)
266
+ print('Req top_k value:', input_top_p_value)
267
+ print('=' * 70)
268
+
269
+ if input_chords is not None:
270
+ chords = []
271
+
272
+ for c in input_chords:
273
+ cho = [int(t) for t in c.split('-')]
274
+ chords.append(TMIDIX.ALL_CHORDS_SORTED.index(cho))
275
+
276
+ else:
277
+ if input_example == 'Blue Bird':
278
+ chords = blue_bird
279
+
280
+ elif input_example == 'Come To My Window':
281
+ chords = come_to_my_window
282
+
283
+ else:
284
+ chords = sharing_the_night_together
285
+
286
+ print('There are', len(chords), 'chords')
287
+ print('Sample chords:', chords[:5])
288
+ print('=' * 70)
289
+
290
+ #===============================================================================
291
+
292
+ print('Sample chords', chords[:2])
293
+ print('=' * 70)
294
+ print('Generating...')
295
+
296
+ cho_prg, score = generate_chords(chords,
297
+ input_temperature,
298
+ input_top_p_value
299
+ )
300
+
301
+ final_chords = [TMIDIX.ALL_CHORDS_SORTED[c] for c in cho_prg]
302
+ final_score = tokens_to_escore_notes(score)
303
+
304
+ final_score = TMIDIX.remove_duplicate_pitches_from_escore_notes(final_score)
305
+
306
+ final_score = TMIDIX.fix_escore_notes_durations(final_score,
307
+ min_notes_gap=0
308
+ )
309
+
310
+ final_score = TMIDIX.humanize_velocities_in_escore_notes(final_score)
311
+
312
+ #===============================================================================
313
+ print('Rendering results...')
314
+ print('=' * 70)
315
+
316
+ now = datetime.datetime.now(PDT)
317
+ ms4 = now.strftime("%f")[:4]
318
+
319
+ fn1 = (
320
+ 'Orpheus-Masked-Pitches-Inpainter-Composition-'
321
+ + now.strftime(f"%Y-%m-%d-%H-%M-%S-{ms4}")
322
+ )
323
+
324
+ output_score, patches, overflow_patches = TMIDIX.patch_enhanced_score_notes(final_score)
325
+
326
+ detailed_stats = TMIDIX.Tegridy_ms_SONG_to_MIDI_Converter(output_score,
327
+ output_signature = 'Orpheus Masked Pitches Inpainter',
328
+ output_file_name = fn1,
329
+ track_name='Project Los Angeles',
330
+ list_of_MIDI_patches=patches,
331
+ timings_multiplier=32
332
+ )
333
+
334
+ new_fn = fn1+'.mid'
335
+
336
+
337
+ audio = midi_to_colab_audio(new_fn,
338
+ soundfont_path=SOUNDFONT_PATH,
339
+ sample_rate=16000,
340
+ output_for_gradio=True
341
+ )
342
+
343
+ print('Done!')
344
+ print('=' * 70)
345
+
346
+ #========================================================
347
+
348
+ output_gen_chords = '\n'.join(str(c) for c in final_chords)
349
+ output_midi = str(new_fn)
350
+ output_audio = (16000, audio)
351
+
352
+ output_plot = TMIDIX.plot_ms_SONG(output_score,
353
+ timings_multiplier=32,
354
+ plot_title=output_midi,
355
+ return_plt=True
356
+ )
357
+
358
+ print('Output gen chords:', output_gen_chords[:3])
359
+ print('=' * 70)
360
+
361
+
362
+ #========================================================
363
+
364
+ print('-' * 70)
365
+ print('Req end time: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now(PDT)))
366
+ print('-' * 70)
367
+ print('Req execution time:', (reqtime.time() - start_time), 'sec')
368
+
369
+ return output_gen_chords, output_audio, output_plot, output_midi
370
+
371
+ # =================================================================================================
372
+
373
+ chords_labels = []
374
+
375
+ for c in TMIDIX.ALL_CHORDS_SORTED:
376
+
377
+ cho = '-'.join([str(t) for t in c])
378
+
379
+ chords_labels.append(cho)
380
+
381
+ # =================================================================================================
382
+
383
+ blue_bird = [89, 301, 314, 317, 114, 280, 110, 318, 194, 221, 320, 187, 270, 191, 303, 162,
384
+ 298, 178, 181, 308, 267, 283, 94, 104, 96, 272, 215, 288, 296, 105, 102, 144,
385
+ 91, 284, 273, 227, 316, 164, 189, 147, 281, 268, 179, 186, 213, 159, 165, 92,
386
+ 188, 150, 218, 112, 309, 285, 302, 217, 290, 306, 148, 1, 310, 4, 289, 0, 307,
387
+ 119, 212, 117, 233, 254, 34, 3, 180, 319]
388
+
389
+ come_to_my_window = [16, 0, 13, 216, 309, 178, 194, 301, 192, 317, 320, 1, 191, 89, 319, 314, 288,
390
+ 267, 195, 282, 280, 183, 18, 14, 181, 179, 215, 303, 184, 213, 306, 37, 272,
391
+ 310, 34, 228, 212, 312, 227, 97, 308]
392
+
393
+ sharing_the_night_together = [267, 270, 281, 314, 148, 280, 146, 102, 233, 316, 283, 320, 10, 104, 235, 117,
394
+ 89, 91, 256, 285, 21, 159, 112, 264, 301, 238, 303, 0, 263, 94, 144, 110, 153,
395
+ 103, 106, 170, 95, 171, 119, 268, 90, 108, 114, 317, 306, 136, 134, 254, 307,
396
+ 302, 31, 284, 319, 258, 243, 272]
397
+
398
+ # =================================================================================================
399
+
400
+ PDT = timezone('US/Pacific')
401
+
402
+ print('=' * 70)
403
+ print('App start time: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now(PDT)))
404
+ print('=' * 70)
405
+
406
+ soundfont = "SGM-v2.01-YamahaGrand-Guit-Bass-v2.7.sf2"
407
+
408
+ app = gr.Blocks()
409
+ with app:
410
+ gr.Markdown("<h1 style='text-align: left; margin-bottom: 1rem'>Orpheus Masked Pitches Inpainter</h1>")
411
+ gr.Markdown("<h1 style='text-align: left; margin-bottom: 1rem'>Generate and texture unique chords progressions</h1>")
412
+
413
+ gr.Markdown("## Select example chords progression or create your own")
414
+
415
+ input_example = gr.Dropdown(label="Example chords progressions",
416
+ choices=['Blue Bird', 'Come To My Window', 'Sharing The Night Together'],
417
+ value='Blue Bird',
418
+ info='NOTE: Selecting custom chords below will override example selection'
419
+ )
420
+
421
+ input_chords = gr.Dropdown(label="Desired chords to generate",
422
+ choices=chords_labels,
423
+ value=None,
424
+ multiselect=True,
425
+ info='NOTE: Selected chords will be introduced into generated chords progression in order of selection'
426
+ )
427
+ input_temperature = gr.Slider(0.1, 1.0, value=0.9, step=0.01, label="Model temperature")
428
+ input_top_p_value = gr.Slider(0.1, 1.0, value=0.96, step=0.01, label="Model sampling top_p value")
429
+
430
+ run_btn = gr.Button("generate", variant="primary")
431
+
432
+ gr.Markdown("## Generation results")
433
+
434
+ output_gen_chords = gr.Textbox(label="Generated chords list", lines=7)
435
+ output_audio = gr.Audio(label="Output MIDI audio", format="mp3", elem_id="midi_audio")
436
+ output_plot = gr.Plot(label="Output MIDI score plot")
437
+ output_midi = gr.File(label="Output MIDI file", file_types=[".mid"])
438
+
439
+ run_event = run_btn.click(Generate_Chords,
440
+ [input_example,
441
+ input_chords,
442
+ input_temperature,
443
+ input_top_p_value
444
+ ],
445
+ [output_gen_chords,
446
+ output_audio,
447
+ output_plot,
448
+ output_midi
449
+ ])
450
+
451
+ app.launch(mcp_server=True)
midi_to_colab_audio.py ADDED
The diff for this file is too large to render. See raw diff
 
packages.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ fluidsynth
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ tqdm
2
+ numpy
3
+ scikit-learn
4
+ matplotlib
5
+ gradio
6
+ hf-transfer
7
+ huggingface_hub
8
+ torch
9
+ einops
10
+ einx
x_transformer_2_3_1.py ADDED
The diff for this file is too large to render. See raw diff