eloigil6 Claude Opus 4.8 commited on
Commit
b97956f
·
1 Parent(s): 946690f

Cap continuation generation at 28s to stay in musicgen's 30s window

Browse files

musicgen is trained on 30s clips, so a single shot longer than ~30s degrades its tail into noise. Each continuation prepended the OVERLAP_S seed and then generated a full 30s of NEW audio (seed + 30 = 31-32s total), pushing the tail past the training window — the source of the 'weird noise', and why shrinking the seed kept helping. Now a continuation generates only MAX_GEN_S - OVERLAP_S new seconds so the whole shot stays <=28s (env LOFINITY_MAX_GEN_S, default 28). The first chunk is unchanged (text-only, exactly 30s, already clean). Side effect: long tapes are slightly shorter — each continuation adds ~27s of clean audio instead of 30s of partly-degraded — so 60s->~57s, 90s->~84s.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files changed (1) hide show
  1. app.py +9 -1
app.py CHANGED
@@ -80,6 +80,10 @@ MUSICGEN_MODEL = os.getenv("LOFINITY_MUSICGEN", "facebook/musicgen-medium")
80
  # tokens (~41s at 50 tok/s), so a 2s seed + 30s of new audio (~1600 tokens) fits.
81
  CHUNK_S = 30 # length of each musicgen single-shot
82
  OVERLAP_S = float(os.getenv("LOFINITY_OVERLAP_S", "2")) # seconds of tail fed back as the continuation seed; shorter leans more on the text prompt
 
 
 
 
83
  SEAM_S = 0.4 # equal-power crossfade at each stitch, to hide the join
84
  # the lengths the tape-length slider offers; the API snaps any value to one
85
  ALLOWED_SECONDS = (30, 60, 90)
@@ -372,6 +376,10 @@ def musicgen_engine(music_prompt: str, seconds: int = CHUNK_S, progress_cb=None)
372
  processor, model, device = load_musicgen()
373
  rate = model.config.audio_encoder.sampling_rate
374
  overlap = int(OVERLAP_S * rate)
 
 
 
 
375
  rounds = max(0, round(seconds / CHUNK_S) - 1) # 30->0, 60->1, 90->2
376
  total = rounds + 1
377
 
@@ -399,7 +407,7 @@ def musicgen_engine(music_prompt: str, seconds: int = CHUNK_S, progress_cb=None)
399
  progress_cb(1, total)
400
  base_rms = _rms(track)
401
  for i in range(rounds):
402
- out = shot(dev, seed=track[-overlap:]) # continue from the last 6s
403
  fresh = _match_rms(out[overlap:], base_rms) # drop the re-encoded seed
404
  track = _stitch(track, fresh, rate)
405
  if progress_cb:
 
80
  # tokens (~41s at 50 tok/s), so a 2s seed + 30s of new audio (~1600 tokens) fits.
81
  CHUNK_S = 30 # length of each musicgen single-shot
82
  OVERLAP_S = float(os.getenv("LOFINITY_OVERLAP_S", "2")) # seconds of tail fed back as the continuation seed; shorter leans more on the text prompt
83
+ # musicgen is trained on 30s clips, so a single shot longer than ~30s degrades
84
+ # its tail into noise. A continuation prepends the seed THEN generates, so cap its
85
+ # total output (seed + new) at MAX_GEN_S to stay inside that window. Env-tunable.
86
+ MAX_GEN_S = float(os.getenv("LOFINITY_MAX_GEN_S", "28"))
87
  SEAM_S = 0.4 # equal-power crossfade at each stitch, to hide the join
88
  # the lengths the tape-length slider offers; the API snaps any value to one
89
  ALLOWED_SECONDS = (30, 60, 90)
 
376
  processor, model, device = load_musicgen()
377
  rate = model.config.audio_encoder.sampling_rate
378
  overlap = int(OVERLAP_S * rate)
379
+ # a continuation prepends the OVERLAP_S seed, so it may generate only
380
+ # MAX_GEN_S - OVERLAP_S NEW seconds to keep the whole shot inside musicgen's
381
+ # ~30s training window — generating past it is what turns the tail to noise
382
+ cont_new_s = max(1.0, MAX_GEN_S - OVERLAP_S)
383
  rounds = max(0, round(seconds / CHUNK_S) - 1) # 30->0, 60->1, 90->2
384
  total = rounds + 1
385
 
 
407
  progress_cb(1, total)
408
  base_rms = _rms(track)
409
  for i in range(rounds):
410
+ out = shot(dev, seed=track[-overlap:], new_s=cont_new_s) # capped continuation
411
  fresh = _match_rms(out[overlap:], base_rms) # drop the re-encoded seed
412
  track = _stitch(track, fresh, rate)
413
  if progress_cb: