harp-dev commited on
Commit
653006d
·
verified ·
1 Parent(s): eb9ef09

Reduce this to the HARP deployment, dropping the standalone demo UI

Browse files
Files changed (4) hide show
  1. app.py +8 -471
  2. scratch/convert_to_wav.sh +0 -1
  3. scratch/separate_folder.sh +0 -1
  4. setup.py +0 -42
app.py CHANGED
@@ -54,8 +54,6 @@ def load_audio(file):
54
  return to_output(sig)
55
 
56
 
57
- def load_example_audio():
58
- return load_audio("./assets/example.wav")
59
 
60
  from torch_pitch_shift import pitch_shift, get_fast_shifts
61
  def shift_pitch(signal, interval: int):
@@ -109,24 +107,6 @@ def new_vampnet_mask(self,
109
  mask = mask.to(self.device)
110
  return mask[:, :, :]
111
 
112
- @spaces.GPU
113
- def mask_preview(periodic_p, n_mask_codebooks, onset_mask_width, dropout):
114
- # make a mask preview
115
- codes = torch.zeros((1, 14, 80)).to(device)
116
- mask = interface.build_mask(
117
- codes,
118
- periodic_prompt=periodic_p,
119
- # onset_mask_width=onset_mask_width,
120
- _dropout=dropout,
121
- upper_codebook_mask=n_mask_codebooks,
122
- )
123
- # mask = mask.cpu().numpy()
124
- import matplotlib.pyplot as plt
125
- plt.clf()
126
- interface.visualize_codes(mask)
127
- plt.title("mask preview")
128
- plt.savefig("scratch/mask-prev.png")
129
- return "scratch/mask-prev.png"
130
 
131
 
132
  @spaces.GPU
@@ -314,44 +294,6 @@ def vamp(input_audio,
314
  api=False,
315
  )
316
 
317
- @spaces.GPU
318
- def api_vamp(input_audio,
319
- sampletemp, top_p,
320
- periodic_p,
321
- dropout,
322
- stretch_factor,
323
- onset_mask_width,
324
- typical_filtering,
325
- typical_mass,
326
- typical_min_tokens,
327
- seed,
328
- model_choice,
329
- n_mask_codebooks,
330
- pitch_shift_amt,
331
- sample_cutoff,
332
- sampling_steps,
333
- beat_mask_ms, num_feedback_steps):
334
- return _vamp_internal(
335
- seed=seed,
336
- input_audio=input_audio,
337
- model_choice=model_choice,
338
- pitch_shift_amt=pitch_shift_amt,
339
- periodic_p=periodic_p,
340
- n_mask_codebooks=n_mask_codebooks,
341
- onset_mask_width=onset_mask_width,
342
- dropout=dropout,
343
- sampletemp=sampletemp,
344
- typical_filtering=typical_filtering,
345
- typical_mass=typical_mass,
346
- typical_min_tokens=typical_min_tokens,
347
- top_p=top_p,
348
- sample_cutoff=sample_cutoff,
349
- stretch_factor=stretch_factor,
350
- sampling_steps=sampling_steps,
351
- beat_mask_ms=beat_mask_ms,
352
- num_feedback_steps=num_feedback_steps,
353
- api=True,
354
- )
355
 
356
  @spaces.GPU
357
  def harp_vamp(input_audio, sampletemp, periodic_p, dropout, n_mask_codebooks, model_choice, stretch_factor):
@@ -409,412 +351,11 @@ def harp_vamp(input_audio, sampletemp, periodic_p, dropout, n_mask_codebooks, mo
409
 
410
  if __name__ == "__main__":
411
  with gr.Blocks() as demo:
412
- with gr.Row():
413
- with gr.Column():
414
- manual_audio_upload = gr.File(
415
- label=f"upload some audio (will be randomly trimmed to max of 100s)",
416
- file_types=["audio"]
417
- )
418
- load_example_audio_button = gr.Button("or load example audio")
419
-
420
- input_audio = gr.Audio(
421
- label="input audio",
422
- interactive=False,
423
- type="numpy",
424
- ).set_info((
425
- "The audio to rework. The model fills in what it masks out, so the "
426
- "result keeps the character of this recording."
427
- ))
428
-
429
- # audio_mask = gr.Audio(
430
- # label="audio mask (listen to this to hear the mask hints)",
431
- # interactive=False,
432
- # type="numpy",
433
- # )
434
-
435
- # connect widgets
436
- load_example_audio_button.click(
437
- fn=load_example_audio,
438
- inputs=[],
439
- outputs=[ input_audio]
440
- )
441
-
442
- manual_audio_upload.change(
443
- fn=load_audio,
444
- inputs=[manual_audio_upload],
445
- outputs=[ input_audio]
446
- )
447
-
448
-
449
- # mask settings
450
- with gr.Column():
451
- with gr.Accordion("manual controls", open=True):
452
- periodic_p = gr.Slider(
453
- label="periodic prompt",
454
- minimum=0,
455
- maximum=13,
456
- step=1,
457
- value=7,
458
- info=(
459
- "How much of the original is kept as a guide. Low values keep more "
460
- "and stay closer to the input; high values free the model to depart "
461
- "from it."
462
- ),
463
- )
464
-
465
- onset_mask_width = gr.Slider(
466
- label="onset mask width",
467
- minimum=0,
468
- maximum=100,
469
- step=1,
470
- value=0, visible=True,
471
- info=(
472
- "Widens the guide around note onsets, so attacks survive. One step "
473
- "is about 10 milliseconds, and it multiplies with the periodic "
474
- "prompt. Not shown in the mask preview."
475
- )
476
- )
477
-
478
- beat_mask_ms = gr.Slider(
479
- label="beat mask width (ms)",
480
- minimum=0,
481
- maximum=200,
482
- step=1,
483
- value=0,
484
- visible=True,
485
- info=(
486
- "Widens the guide around detected beats, which holds the groove in "
487
- "place. Not shown in the mask preview."
488
- )
489
- )
490
-
491
- n_mask_codebooks = gr.Slider(
492
- label="compression prompt ",
493
- value=3,
494
- minimum=1,
495
- maximum=14,
496
- step=1,
497
- info=(
498
- "Keeps only the coarsest detail of the original, discarding fine "
499
- "timbre. Raise it for a looser reinterpretation."
500
- ),
501
- )
502
-
503
- dropout = gr.Slider(
504
- label="mask dropout",
505
- minimum=0.0,
506
- maximum=1.0,
507
- step=0.01,
508
- value=0.0,
509
- info=(
510
- "Randomly drops parts of the guide, which loosens the result "
511
- "without changing the overall amount kept."
512
- )
513
- )
514
-
515
- num_feedback_steps = gr.Slider(
516
- label="feedback steps",
517
- minimum=1,
518
- maximum=8,
519
- step=1,
520
- value=1,
521
- info=(
522
- "Runs the output back through the model this many times. More "
523
- "passes transfer timbre and rhythm better and take proportionally "
524
- "longer."
525
- )
526
- )
527
-
528
- preset_dropdown = gr.Dropdown(
529
- label="preset",
530
- choices=["timbre transfer", "small variation", "small variation (follow beat)", "medium variation", "medium variation (follow beat)", "large variation", "large variation (follow beat)", "unconditional"],
531
- value="medium variation",
532
- info="Loads a set of the controls below that is known to work together."
533
- )
534
- def change_preset(preset_dropdown):
535
- if preset_dropdown == "timbre transfer":
536
- periodic_p = 2
537
- n_mask_codebooks = 1
538
- onset_mask_width = 0
539
- dropout = 0.0
540
- beat_mask_ms = 0
541
- elif preset_dropdown == "small variation":
542
- periodic_p = 5
543
- n_mask_codebooks = 4
544
- onset_mask_width = 0
545
- dropout = 0.0
546
- beat_mask_ms = 0
547
- elif preset_dropdown == "small variation (follow beat)":
548
- periodic_p = 7
549
- n_mask_codebooks = 4
550
- onset_mask_width = 0
551
- dropout = 0.0
552
- beat_mask_ms = 50
553
- elif preset_dropdown == "medium variation":
554
- periodic_p = 7
555
- n_mask_codebooks = 4
556
- onset_mask_width = 0
557
- dropout = 0.0
558
- beat_mask_ms = 0
559
- elif preset_dropdown == "medium variation (follow beat)":
560
- periodic_p = 13
561
- n_mask_codebooks = 4
562
- onset_mask_width = 0
563
- dropout = 0.0
564
- beat_mask_ms = 50
565
- elif preset_dropdown == "large variation":
566
- periodic_p = 13
567
- n_mask_codebooks = 4
568
- onset_mask_width = 0
569
- dropout = 0.2
570
- beat_mask_ms = 0
571
- elif preset_dropdown == "large variation (follow beat)":
572
- periodic_p = 0
573
- n_mask_codebooks = 4
574
- onset_mask_width = 0
575
- dropout = 0.0
576
- beat_mask_ms=80
577
- elif preset_dropdown == "unconditional":
578
- periodic_p=0
579
- n_mask_codebooks=1
580
- onset_mask_width=0
581
- dropout=0.0
582
- return periodic_p, n_mask_codebooks, onset_mask_width, dropout, beat_mask_ms
583
- preset_dropdown.change(
584
- fn=change_preset,
585
- inputs=[preset_dropdown],
586
- outputs=[periodic_p, n_mask_codebooks, onset_mask_width, dropout, beat_mask_ms]
587
- )
588
- # preset_dropdown.change(
589
-
590
-
591
- maskimg = gr.Image(
592
- label="mask image",
593
- interactive=False,
594
- type="filepath"
595
- )
596
-
597
- with gr.Accordion("extras ", open=False):
598
- pitch_shift_amt = gr.Slider(
599
- label="pitch shift amount (semitones)",
600
- minimum=-12,
601
- maximum=12,
602
- step=1,
603
- value=0,
604
- info="Shifts the input before processing. Twelve is one octave.",
605
- )
606
-
607
- stretch_factor = gr.Slider(
608
- label="time stretch factor",
609
- minimum=0,
610
- maximum=8,
611
- step=1,
612
- value=1,
613
- info=(
614
- "Stretches the input before processing. Values above one slow it "
615
- "down."
616
- ),
617
- )
618
-
619
-
620
-
621
-
622
- with gr.Accordion("sampling settings", open=False):
623
- sampletemp = gr.Slider(
624
- label="sample temperature",
625
- minimum=0.1,
626
- maximum=10.0,
627
- value=1.0,
628
- step=0.001,
629
- info=(
630
- "How adventurous the choices are. Higher values wander further and "
631
- "can lose the beat."
632
- )
633
- )
634
-
635
- top_p = gr.Slider(
636
- label="top p (0.0 = off)",
637
- minimum=0.0,
638
- maximum=1.0,
639
- value=0.0,
640
- info=(
641
- "Restricts choices to the most likely ones. Lower values are safer "
642
- "and more repetitive."
643
- )
644
- )
645
- typical_filtering = gr.Checkbox(
646
- label="typical filtering ",
647
- value=True,
648
- info=(
649
- "An alternative to top p that keeps choices of average likelihood, "
650
- "avoiding both the safest and the strangest."
651
- )
652
- )
653
- typical_mass = gr.Slider(
654
- label="typical mass",
655
- minimum=0.01,
656
- maximum=0.99,
657
- value=0.15,
658
- info=(
659
- "How much of the likely range to sample from when typical filtering "
660
- "is on. Values between 0.1 and 0.5 are the useful range."
661
- )
662
- )
663
- typical_min_tokens = gr.Slider(
664
- label="typical min tokens",
665
- minimum=1,
666
- maximum=256,
667
- step=1,
668
- value=64,
669
- info=(
670
- "The fewest choices typical filtering will leave open. Values "
671
- "between 1 and 256 are the useful range."
672
- )
673
- )
674
- sample_cutoff = gr.Slider(
675
- label="sample cutoff",
676
- minimum=0.0,
677
- maximum=1.0,
678
- value=1.0,
679
- step=0.01,
680
- info=(
681
- "Stops sampling early, leaving later detail to the decoder. Lower "
682
- "values are smoother and less detailed."
683
- )
684
- )
685
- sampling_steps = gr.Slider(
686
- label="sampling steps",
687
- minimum=1,
688
- maximum=128,
689
- step=1,
690
- value=36,
691
- info="More steps give a more considered result and take longer."
692
- )
693
-
694
-
695
-
696
- seed = gr.Number(
697
- label="seed (0 for random)",
698
- value=0,
699
- precision=0,
700
- info=(
701
- "Fixes the result, so the same seed and settings give the same "
702
- "output."
703
- ),
704
- )
705
-
706
-
707
- # mask settings
708
- with gr.Column():
709
-
710
- model_choice = gr.Dropdown(
711
- label="model choice",
712
- choices=list(interface.available_models()),
713
- value=init_model_choice,
714
- visible=True,
715
- info=(
716
- "Which fine-tune to use. Each was trained on different material, "
717
- "named in the model card."
718
- )
719
- )
720
-
721
-
722
- vamp_button = gr.Button("generate (vamp)!!!")
723
-
724
-
725
- audio_outs = []
726
- use_as_input_btns = []
727
- for i in range(2):
728
- with gr.Column():
729
- audio_outs.append(gr.Audio(
730
- label=f"output audio {i+1}",
731
- interactive=False,
732
- type="numpy"
733
- ))
734
- use_as_input_btns.append(
735
- gr.Button(f"use as input (feedback)")
736
- )
737
-
738
- thank_you = gr.Markdown("")
739
-
740
- # download all the outputs
741
- # download = gr.File(type="filepath", label="download outputs")
742
-
743
-
744
- # mask preview change
745
- for widget in (
746
- periodic_p, n_mask_codebooks,
747
- onset_mask_width, dropout
748
- ):
749
- widget.change(
750
- fn=mask_preview,
751
- inputs=[periodic_p, n_mask_codebooks,
752
- onset_mask_width, dropout],
753
- outputs=[maskimg]
754
- )
755
-
756
-
757
- _inputs = [
758
- input_audio,
759
- sampletemp,
760
- top_p,
761
- periodic_p,
762
- dropout,
763
- stretch_factor,
764
- onset_mask_width,
765
- typical_filtering,
766
- typical_mass,
767
- typical_min_tokens,
768
- seed,
769
- model_choice,
770
- n_mask_codebooks,
771
- pitch_shift_amt,
772
- sample_cutoff,
773
- sampling_steps,
774
- beat_mask_ms,
775
- num_feedback_steps
776
- ]
777
-
778
- # connect widgets
779
- vamp_button.click(
780
- fn=vamp,
781
- inputs=_inputs,
782
- outputs=[audio_outs[0], audio_outs[1], maskimg],
783
- )
784
-
785
- api_vamp_button = gr.Button("api vamp", visible=True)
786
- api_vamp_button.click(
787
- fn=api_vamp,
788
- inputs=[input_audio,
789
- sampletemp, top_p,
790
- periodic_p,
791
- dropout,
792
- stretch_factor,
793
- onset_mask_width,
794
- typical_filtering,
795
- typical_mass,
796
- typical_min_tokens,
797
- seed,
798
- model_choice,
799
- n_mask_codebooks,
800
- pitch_shift_amt,
801
- sample_cutoff,
802
- sampling_steps,
803
- beat_mask_ms,
804
- num_feedback_steps
805
- ],
806
- outputs=[audio_outs[0], audio_outs[1]],
807
- api_name="vamp"
808
- )
809
-
810
-
811
  #NEW: HARP endpoint (new PyHARP API)
812
  harp_model_card = ModelCard(
813
  name="VampNet",
814
  description=(
815
- (
816
- (
817
- "Generates new audio by remixing and extending your input, filling in "
818
  "the blanks to create a coherent continuation in the same style. "
819
  "Available models include: cat10: fine-tuned on expressive cat sounds; "
820
  "lazaro-ros-sep: percussion extracted from the Lázaro Ros discography, "
@@ -825,9 +366,7 @@ if __name__ == "__main__":
825
  "format it came in with but no stereo image. Repository: "
826
  "https://github.com/hugofloresgarcia/vampnet Paper: "
827
  "https://arxiv.org/abs/2307.04686"
828
- )
829
- )
830
- ),
831
  author="Hugo Flores Garcia, Prem Seetharaman, Rithesh Kumar, Bryan Pardo",
832
  tags=[Subcategory.INFILLING, SampleRate(44100), Channels(1), 'sound', 'generation']
833
  )
@@ -858,14 +397,12 @@ if __name__ == "__main__":
858
  gr.JSON(label="Generated Labels"),
859
  ]
860
 
861
- with gr.Row():
862
- gr.Markdown("### VST / HARP Plugin Controls")
863
- harp_app = build_endpoint(
864
- model_card=harp_model_card,
865
- input_components=harp_input_components,
866
- output_components=harp_output_components,
867
- process_fn=harp_vamp
868
- )
869
 
870
  try:
871
  demo.queue()
 
54
  return to_output(sig)
55
 
56
 
 
 
57
 
58
  from torch_pitch_shift import pitch_shift, get_fast_shifts
59
  def shift_pitch(signal, interval: int):
 
107
  mask = mask.to(self.device)
108
  return mask[:, :, :]
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
 
111
 
112
  @spaces.GPU
 
294
  api=False,
295
  )
296
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
 
298
  @spaces.GPU
299
  def harp_vamp(input_audio, sampletemp, periodic_p, dropout, n_mask_codebooks, model_choice, stretch_factor):
 
351
 
352
  if __name__ == "__main__":
353
  with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  #NEW: HARP endpoint (new PyHARP API)
355
  harp_model_card = ModelCard(
356
  name="VampNet",
357
  description=(
358
+ "Generates new audio by remixing and extending your input, filling in "
 
 
359
  "the blanks to create a coherent continuation in the same style. "
360
  "Available models include: cat10: fine-tuned on expressive cat sounds; "
361
  "lazaro-ros-sep: percussion extracted from the Lázaro Ros discography, "
 
366
  "format it came in with but no stereo image. Repository: "
367
  "https://github.com/hugofloresgarcia/vampnet Paper: "
368
  "https://arxiv.org/abs/2307.04686"
369
+ ),
 
 
370
  author="Hugo Flores Garcia, Prem Seetharaman, Rithesh Kumar, Bryan Pardo",
371
  tags=[Subcategory.INFILLING, SampleRate(44100), Channels(1), 'sound', 'generation']
372
  )
 
397
  gr.JSON(label="Generated Labels"),
398
  ]
399
 
400
+ build_endpoint(
401
+ model_card=harp_model_card,
402
+ input_components=harp_input_components,
403
+ output_components=harp_output_components,
404
+ process_fn=harp_vamp,
405
+ )
 
 
406
 
407
  try:
408
  demo.queue()
scratch/convert_to_wav.sh DELETED
@@ -1 +0,0 @@
1
- for f in *.mp3; do ffmpeg -i "$f" "${f%.mp3}.wav"; done
 
 
scratch/separate_folder.sh DELETED
@@ -1 +0,0 @@
1
- for f in *.mp3; do demucs "$f" --two-stems=vocals; done
 
 
setup.py DELETED
@@ -1,42 +0,0 @@
1
- from setuptools import find_packages
2
- from setuptools import setup
3
-
4
- with open("README.md") as f:
5
- long_description = f.read()
6
-
7
- setup(
8
- name="vampnet",
9
- version="0.0.1",
10
- classifiers=[
11
- "Intended Audience :: Developers",
12
- "Natural Language :: English",
13
- "Programming Language :: Python :: 3.7",
14
- "Topic :: Artistic Software",
15
- "Topic :: Multimedia",
16
- "Topic :: Multimedia :: Sound/Audio",
17
- "Topic :: Multimedia :: Sound/Audio :: Editors",
18
- "Topic :: Software Development :: Libraries",
19
- ],
20
- description="Generative Music Modeling.",
21
- long_description=long_description,
22
- long_description_content_type="text/markdown",
23
- author="Hugo Flores García, Prem Seetharaman",
24
- author_email="hugggofloresgarcia@gmail.com",
25
- url="https://github.com/hugofloresgarcia/vampnet",
26
- license="MIT",
27
- packages=find_packages(),
28
- install_requires=[
29
- "torch==2.4.1",
30
- "argbind>=0.3.2",
31
- "numpy==1.23",
32
- "wavebeat @ git+https://github.com/hugofloresgarcia/wavebeat",
33
- "lac @ git+https://github.com/hugofloresgarcia/lac.git",
34
- "descript-audiotools @ git+https://github.com/hugofloresgarcia/audiotools.git",
35
- "gradio",
36
- "loralib",
37
- "torch_pitch_shift",
38
- "plotly",
39
- "pydantic==2.10.6",
40
- "spaces",
41
- ],
42
- )