Mina Emadi Claude Sonnet 4.6 commited on
Commit
e38e511
Β·
1 Parent(s): e631a15

Add preset tracks with OGG stems and metadata overrides for key/BPM detection

Browse files

- Add 6 preset tracks as OGG Vorbis (~10x smaller than WAV, no audible quality loss)
- Add metadata.json override system for presets with incorrect MIDI detection
- Fix Sea-to-Sky and Ocean-to-Horizon BPM (90 instead of 95)
- Fix Silver-lining key (D major instead of G major)
- Fix Static-Summer key (A major instead of D major)
- Backend resolves .ogg before .wav for forward/backward compatibility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (45) hide show
  1. .gitattributes +1 -0
  2. backend/models/session.py +2 -0
  3. backend/presets/{sample-track/bass.wav β†’ 274-SUNSPILL/bass.ogg} +2 -2
  4. backend/presets/{sample-track/click_record.wav β†’ 274-SUNSPILL/click_record.ogg} +2 -2
  5. backend/presets/{sample-track/drums.wav β†’ 274-SUNSPILL/drums.ogg} +2 -2
  6. backend/presets/{sample-track/guitar.wav β†’ 274-SUNSPILL/guitar.ogg} +2 -2
  7. backend/presets/{sample-track/MIDI.mid β†’ 274-SUNSPILL/midi.mid} +0 -0
  8. backend/presets/274-SUNSPILL/synth.ogg +3 -0
  9. backend/presets/281-New-Drive/click_record.ogg +3 -0
  10. backend/presets/281-New-Drive/drums.ogg +3 -0
  11. backend/presets/281-New-Drive/guitar.ogg +3 -0
  12. backend/presets/281-New-Drive/midi.mid +0 -0
  13. backend/presets/281-New-Drive/synth.ogg +3 -0
  14. backend/presets/282-Static-Summer/282A- STATIC SUMMER- A- 85.mid +0 -0
  15. backend/presets/282-Static-Summer/click_record.ogg +3 -0
  16. backend/presets/282-Static-Summer/drums.ogg +3 -0
  17. backend/presets/282-Static-Summer/guitar.ogg +3 -0
  18. backend/presets/282-Static-Summer/metadata.json +1 -0
  19. backend/presets/282-Static-Summer/synth.ogg +3 -0
  20. backend/presets/291-Blue-Jazz/click_record.ogg +3 -0
  21. backend/presets/291-Blue-Jazz/drums.ogg +3 -0
  22. backend/presets/291-Blue-Jazz/guitar.ogg +3 -0
  23. backend/presets/291-Blue-Jazz/midi.mid +0 -0
  24. backend/presets/291-Blue-Jazz/synth.ogg +3 -0
  25. backend/presets/292-Silver-lining/Midi.mid +0 -0
  26. backend/presets/292-Silver-lining/click_record.ogg +3 -0
  27. backend/presets/292-Silver-lining/drums.ogg +3 -0
  28. backend/presets/292-Silver-lining/guitar.ogg +3 -0
  29. backend/presets/292-Silver-lining/metadata.json +1 -0
  30. backend/presets/292-Silver-lining/synth.ogg +3 -0
  31. backend/presets/294-Sea-to-Sky/click_record.ogg +3 -0
  32. backend/presets/294-Sea-to-Sky/drums.ogg +3 -0
  33. backend/presets/294-Sea-to-Sky/guitar.ogg +3 -0
  34. backend/presets/294-Sea-to-Sky/metadata.json +1 -0
  35. backend/presets/294-Sea-to-Sky/midi.mid +0 -0
  36. backend/presets/294-Sea-to-Sky/synth.ogg +3 -0
  37. backend/presets/295-Ocean-to-Horizon/click_record.ogg +3 -0
  38. backend/presets/295-Ocean-to-Horizon/drums.ogg +3 -0
  39. backend/presets/295-Ocean-to-Horizon/guitar.ogg +3 -0
  40. backend/presets/295-Ocean-to-Horizon/metadata.json +1 -0
  41. backend/presets/295-Ocean-to-Horizon/midi.mid +0 -0
  42. backend/presets/295-Ocean-to-Horizon/synth.ogg +3 -0
  43. backend/presets/sample-track/synth.wav +0 -3
  44. backend/routers/detection.py +18 -2
  45. backend/routers/presets.py +26 -4
.gitattributes CHANGED
@@ -34,3 +34,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  backend/presets/**/*.wav filter=lfs diff=lfs merge=lfs -text
 
 
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  backend/presets/**/*.wav filter=lfs diff=lfs merge=lfs -text
37
+ backend/presets/**/*.ogg filter=lfs diff=lfs merge=lfs -text
backend/models/session.py CHANGED
@@ -36,6 +36,8 @@ class Session:
36
  original_sr: int = 44100
37
  # Cache for encoded WAV bytes to avoid re-encoding on each request
38
  wav_cache: dict[str, bytes] = field(default_factory=dict)
 
 
39
 
40
 
41
  # In-memory session store
 
36
  original_sr: int = 44100
37
  # Cache for encoded WAV bytes to avoid re-encoding on each request
38
  wav_cache: dict[str, bytes] = field(default_factory=dict)
39
+ # Optional metadata overrides loaded from preset's metadata.json
40
+ preset_metadata: Optional[dict] = None
41
 
42
 
43
  # In-memory session store
backend/presets/{sample-track/bass.wav β†’ 274-SUNSPILL/bass.ogg} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:34d0bf1999390c1846ec635d7d13f719f12235dd0c3b43aff37c978defd20166
3
- size 70893820
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:19e3c525887f1cc0e9fc54e7604b07e273d3d7be5a6b642c7dc155ac7679d7ef
3
+ size 1775218
backend/presets/{sample-track/click_record.wav β†’ 274-SUNSPILL/click_record.ogg} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:436b475a472014349fe08f7acee5916bf17d1ff475471b6f04b45e1cf3f67233
3
- size 70893820
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7c3cda91ce4b648c6a624dcde24994275d8a06ed9575aca33f8ee159229e7ad5
3
+ size 677440
backend/presets/{sample-track/drums.wav β†’ 274-SUNSPILL/drums.ogg} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:536d1b91df21e93ca9f1f1352da5b70f64e6b0b8ac884e7ef794122f63183cfd
3
- size 70893820
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e52f1689c33fc77996692739a8b468f2570523cf83d7ae2f65d9c52b1afa79ef
3
+ size 5849946
backend/presets/{sample-track/guitar.wav β†’ 274-SUNSPILL/guitar.ogg} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:8ed112603fd68bed8a61c290b9ca36fcecee998b085eb283a21e127df0b2bc9e
3
- size 70893820
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:32c4165659d43522bffb3ad4d3f8984fb4139bbac78091d24708ee1520752996
3
+ size 4202989
backend/presets/{sample-track/MIDI.mid β†’ 274-SUNSPILL/midi.mid} RENAMED
File without changes
backend/presets/274-SUNSPILL/synth.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:37fef05c433225778d69ca05e0792504f7bdda87d13b4595787efc20748725bd
3
+ size 4969407
backend/presets/281-New-Drive/click_record.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b57f2056adad41ebdf5c857906087196fac0a15c513e54a12c5e2a5898be63aa
3
+ size 955426
backend/presets/281-New-Drive/drums.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1b225eacde295cb8d5171fa5caac8c009c9dd661f86d9b9dd90e57be2f838698
3
+ size 9873395
backend/presets/281-New-Drive/guitar.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8edfbb3d8d8fb6eca4d332f39e0c0b7f946fd27618da01c730e6136564b80c9e
3
+ size 6052516
backend/presets/281-New-Drive/midi.mid ADDED
Binary file (35.6 kB). View file
 
backend/presets/281-New-Drive/synth.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0d48b8df19153c8dee5f3d8b03e31613506a5f3aaf93d3e51895d3718ee42e3a
3
+ size 3570314
backend/presets/282-Static-Summer/282A- STATIC SUMMER- A- 85.mid ADDED
Binary file (30.7 kB). View file
 
backend/presets/282-Static-Summer/click_record.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:599d74905a741a7acd33931ff89373f469fe98edd27b543e9563472692de3214
3
+ size 1275261
backend/presets/282-Static-Summer/drums.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6175a8ce69bc827eb939da4f9c67fe7d4a1def1118eb3965bda7617b087a3dfa
3
+ size 14258389
backend/presets/282-Static-Summer/guitar.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:010119a51c2078573cfa91e9521cc20b5d0eac0944e710ec993672e01ea1a341
3
+ size 9248029
backend/presets/282-Static-Summer/metadata.json ADDED
@@ -0,0 +1 @@
 
 
1
+ { "key": "A", "mode": "major" }
backend/presets/282-Static-Summer/synth.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7a85e1128abb36af56ef122d5c46935f93defa8883666d05d44059e64e7e0ac0
3
+ size 10177662
backend/presets/291-Blue-Jazz/click_record.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c509be5861393346b9171e4fae7d6da1258dbba01890c91d43b7c026f83ad974
3
+ size 1248321
backend/presets/291-Blue-Jazz/drums.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3d07798a8b0c2087f2cd672f5a111063ded392b1c3151121684228010b80b1e1
3
+ size 17954847
backend/presets/291-Blue-Jazz/guitar.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b68969f1be0e5b77c76f71cc51a58c4f3607a84ea30ad6bb09a5fedfae23235b
3
+ size 7622816
backend/presets/291-Blue-Jazz/midi.mid ADDED
Binary file (34.4 kB). View file
 
backend/presets/291-Blue-Jazz/synth.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e94da4bf9cce3ef54df934286d9c5d043152bdaf655f34f13e653ef37f533404
3
+ size 5147257
backend/presets/292-Silver-lining/Midi.mid ADDED
Binary file (54.4 kB). View file
 
backend/presets/292-Silver-lining/click_record.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:64bcb9637c8f29f2192035fd03f56be5a05cb4e0f8d6fe7d8baddf8a9ad88745
3
+ size 1224237
backend/presets/292-Silver-lining/drums.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1141913045b3a85cfba368d32a748c6bbd83514f48384dd41d3dadb2f849da06
3
+ size 13762812
backend/presets/292-Silver-lining/guitar.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1327a2b61936f78d514a3c528ca604379c69399f6e1d28de8f51f5aa9afcc8ba
3
+ size 6776410
backend/presets/292-Silver-lining/metadata.json ADDED
@@ -0,0 +1 @@
 
 
1
+ { "key": "D", "mode": "major" }
backend/presets/292-Silver-lining/synth.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:28cd6533535ad035391a864687d5f6fe1bbede08e2e6a090b07655be9a6e3cc4
3
+ size 5794283
backend/presets/294-Sea-to-Sky/click_record.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ba642c37eca52f14055a320b3b105bc52b73e711e6c69e036eb24dff05437bbe
3
+ size 1294507
backend/presets/294-Sea-to-Sky/drums.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e66ca65d5e4b034442e8a106b01c32d352a2f723964ad222b3f9cbbee6287b70
3
+ size 11734610
backend/presets/294-Sea-to-Sky/guitar.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:887f057845958f0fccbfb1cb867b16e564ac6dc8b8f59aa407f1b949c6f70185
3
+ size 7145674
backend/presets/294-Sea-to-Sky/metadata.json ADDED
@@ -0,0 +1 @@
 
 
1
+ { "bpm": 90 }
backend/presets/294-Sea-to-Sky/midi.mid ADDED
Binary file (32.5 kB). View file
 
backend/presets/294-Sea-to-Sky/synth.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:924694244bea0ee8e022bf86bedd8516cb4b51b23f579b5c2e18eb111b2cf52c
3
+ size 5323721
backend/presets/295-Ocean-to-Horizon/click_record.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f5d69c2527d02d8f25694149c0c55f7e1b2636fbc09bcd8ae0bd7eadc2c99fd7
3
+ size 1294507
backend/presets/295-Ocean-to-Horizon/drums.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4d97ad6d139174592d9dacbd8c260cc291a5f1a8e0fbe5866b430ff24bf7b167
3
+ size 11734851
backend/presets/295-Ocean-to-Horizon/guitar.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a3c6458920495eec37134e11a514c8983670818de9069d67b02f9a2a7f6e9a5e
3
+ size 7235754
backend/presets/295-Ocean-to-Horizon/metadata.json ADDED
@@ -0,0 +1 @@
 
 
1
+ { "bpm": 90 }
backend/presets/295-Ocean-to-Horizon/midi.mid ADDED
Binary file (28.1 kB). View file
 
backend/presets/295-Ocean-to-Horizon/synth.ogg ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:822c8d86bbb900451978218c0ca657771cb2caa46d1054924bda6ad70ad0c612
3
+ size 4499162
backend/presets/sample-track/synth.wav DELETED
@@ -1,3 +0,0 @@
1
- version https://git-lfs.github.com/spec/v1
2
- oid sha256:ba8a34d85b65a69e09ba0a319136bba8c9d92a6e0fa10e9dc3770d6e26d25a49
3
- size 70893820
 
 
 
 
backend/routers/detection.py CHANGED
@@ -29,11 +29,22 @@ async def detect_bpm_and_key(session_id: str):
29
  if session.full_mix is None:
30
  raise HTTPException(status_code=400, detail="No audio data in session")
31
 
 
 
 
 
 
 
32
  # BPM Detection - prefer MIDI (instant)
33
  bpm_source = "audio"
34
  bpm_result = None
35
 
36
- if session.midi_data is not None:
 
 
 
 
 
37
  # Use MIDI directly - it's exact data
38
  bpm_result = extract_bpm_from_midi(session.midi_data)
39
  bpm_source = "midi"
@@ -63,7 +74,12 @@ async def detect_bpm_and_key(session_id: str):
63
  key_source = "audio"
64
  key_result = None
65
 
66
- if session.midi_data is not None:
 
 
 
 
 
67
  # Use MIDI directly
68
  key_result = extract_key_from_midi(session.midi_data)
69
  if key_result["confidence"] > 0: # Accept any MIDI key result
 
29
  if session.full_mix is None:
30
  raise HTTPException(status_code=400, detail="No audio data in session")
31
 
32
+ # Preset metadata overrides β€” highest priority, skips all detection
33
+ meta = session.preset_metadata or {}
34
+ bpm_override = meta.get("bpm")
35
+ key_override = meta.get("key")
36
+ mode_override = meta.get("mode")
37
+
38
  # BPM Detection - prefer MIDI (instant)
39
  bpm_source = "audio"
40
  bpm_result = None
41
 
42
+ if bpm_override is not None:
43
+ bpm_result = {"bpm": float(bpm_override), "confidence": 1.0}
44
+ bpm_source = "preset"
45
+ print(f"BPM from preset metadata: {bpm_result['bpm']}")
46
+
47
+ elif session.midi_data is not None:
48
  # Use MIDI directly - it's exact data
49
  bpm_result = extract_bpm_from_midi(session.midi_data)
50
  bpm_source = "midi"
 
74
  key_source = "audio"
75
  key_result = None
76
 
77
+ if key_override is not None and mode_override is not None:
78
+ key_result = {"key": key_override, "mode": mode_override, "confidence": 1.0}
79
+ key_source = "preset"
80
+ print(f"Key from preset metadata: {key_result['key']} {key_result['mode']}")
81
+
82
+ elif session.midi_data is not None:
83
  # Use MIDI directly
84
  key_result = extract_key_from_midi(session.midi_data)
85
  if key_result["confidence"] > 0: # Accept any MIDI key result
backend/routers/presets.py CHANGED
@@ -3,6 +3,7 @@
3
  from pathlib import Path
4
 
5
  import io
 
6
  import numpy as np
7
  import soundfile as sf
8
  import mido
@@ -16,6 +17,7 @@ router = APIRouter()
16
 
17
  PRESETS_DIR = Path(__file__).parent.parent / "presets"
18
  STEM_NAMES = ['guitar', 'drums', 'bass', 'synth', 'click_record']
 
19
 
20
 
21
  @router.get("/presets")
@@ -30,9 +32,15 @@ async def list_presets():
30
  @router.get("/preset-stem/{preset_name}/{stem_name}")
31
  async def get_preset_stem_pcm(preset_name: str, stem_name: str):
32
  """Serve a single preset stem as raw int16 PCM β€” stateless, no session created."""
33
- wav_path = PRESETS_DIR / preset_name / f"{stem_name}.wav"
34
- if not wav_path.exists():
 
 
 
 
 
35
  raise HTTPException(status_code=404, detail=f"Stem '{stem_name}' not found in preset '{preset_name}'")
 
36
 
37
  audio, sr = sf.read(str(wav_path))
38
  audio = audio.astype(np.float32)
@@ -66,9 +74,15 @@ async def load_preset(preset_name: str):
66
  sample_rates = []
67
 
68
  for stem_name in STEM_NAMES:
69
- wav_path = preset_dir / f"{stem_name}.wav"
70
- if not wav_path.exists():
 
 
 
 
 
71
  continue
 
72
  audio, sr = sf.read(str(wav_path))
73
  audio = audio.astype(np.float32)
74
  if audio.ndim == 2:
@@ -95,11 +109,19 @@ async def load_preset(preset_name: str):
95
  except Exception as e:
96
  print(f"Warning: could not load MIDI from preset '{preset_name}': {e}")
97
 
 
 
 
 
 
 
 
98
  # Build session
99
  session = create_session()
100
  session.stems = stems
101
  session.original_sr = sample_rates[0]
102
  session.midi_data = midi_data
 
103
 
104
  # Generate mix
105
  max_length = max(len(s.audio) for s in stems.values())
 
3
  from pathlib import Path
4
 
5
  import io
6
+ import json
7
  import numpy as np
8
  import soundfile as sf
9
  import mido
 
17
 
18
  PRESETS_DIR = Path(__file__).parent.parent / "presets"
19
  STEM_NAMES = ['guitar', 'drums', 'bass', 'synth', 'click_record']
20
+ AUDIO_EXTENSIONS = ['.ogg', '.wav'] # prefer OGG, fall back to WAV
21
 
22
 
23
  @router.get("/presets")
 
32
  @router.get("/preset-stem/{preset_name}/{stem_name}")
33
  async def get_preset_stem_pcm(preset_name: str, stem_name: str):
34
  """Serve a single preset stem as raw int16 PCM β€” stateless, no session created."""
35
+ audio_path = None
36
+ for ext in AUDIO_EXTENSIONS:
37
+ candidate = PRESETS_DIR / preset_name / f"{stem_name}{ext}"
38
+ if candidate.exists():
39
+ audio_path = candidate
40
+ break
41
+ if audio_path is None:
42
  raise HTTPException(status_code=404, detail=f"Stem '{stem_name}' not found in preset '{preset_name}'")
43
+ wav_path = audio_path
44
 
45
  audio, sr = sf.read(str(wav_path))
46
  audio = audio.astype(np.float32)
 
74
  sample_rates = []
75
 
76
  for stem_name in STEM_NAMES:
77
+ audio_path = None
78
+ for ext in AUDIO_EXTENSIONS:
79
+ candidate = preset_dir / f"{stem_name}{ext}"
80
+ if candidate.exists():
81
+ audio_path = candidate
82
+ break
83
+ if audio_path is None:
84
  continue
85
+ wav_path = audio_path
86
  audio, sr = sf.read(str(wav_path))
87
  audio = audio.astype(np.float32)
88
  if audio.ndim == 2:
 
109
  except Exception as e:
110
  print(f"Warning: could not load MIDI from preset '{preset_name}': {e}")
111
 
112
+ # Load metadata overrides if present
113
+ preset_metadata = None
114
+ metadata_path = preset_dir / "metadata.json"
115
+ if metadata_path.exists():
116
+ with open(metadata_path) as f:
117
+ preset_metadata = json.load(f)
118
+
119
  # Build session
120
  session = create_session()
121
  session.stems = stems
122
  session.original_sr = sample_rates[0]
123
  session.midi_data = midi_data
124
+ session.preset_metadata = preset_metadata
125
 
126
  # Generate mix
127
  max_length = max(len(s.audio) for s in stems.values())