BoxOfColors Claude Sonnet 4.6 commited on
Commit
1afc0fb
·
1 Parent(s): 03cbad9

Fix crossfade loudness bump: apply db_boost to overlap as a whole

Browse files

Applying gain to each side independently (old code) caused a ~+3 dB
loudness spike at every segment seam. Equal-power crossfade (cos/sin)
already sums to 1.0 at the midpoint; the boost should be applied to
the blended overlap as a unit, not to each fade arm separately.

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

Files changed (1) hide show
  1. app.py +9 -3
app.py CHANGED
@@ -260,7 +260,12 @@ def _build_segments(total_dur_s: float, window_s: float, crossfade_s: float) ->
260
  def _cf_join(a: np.ndarray, b: np.ndarray,
261
  crossfade_s: float, db_boost: float, sr: int) -> np.ndarray:
262
  """Equal-power crossfade join. Works for both mono (T,) and stereo (C, T) arrays.
263
- Stereo arrays are expected in (channels, samples) layout."""
 
 
 
 
 
264
  stereo = a.ndim == 2
265
  n_a = a.shape[1] if stereo else len(a)
266
  n_b = b.shape[1] if stereo else len(b)
@@ -272,10 +277,11 @@ def _cf_join(a: np.ndarray, b: np.ndarray,
272
  fade_out = np.cos(t * np.pi / 2) # 1 → 0
273
  fade_in = np.sin(t * np.pi / 2) # 0 → 1
274
  if stereo:
275
- overlap = a[:, -cf:] * fade_out * gain + b[:, :cf] * fade_in * gain
 
276
  return np.concatenate([a[:, :-cf], overlap, b[:, cf:]], axis=1)
277
  else:
278
- overlap = a[-cf:] * fade_out * gain + b[:cf] * fade_in * gain
279
  return np.concatenate([a[:-cf], overlap, b[cf:]])
280
 
281
 
 
260
  def _cf_join(a: np.ndarray, b: np.ndarray,
261
  crossfade_s: float, db_boost: float, sr: int) -> np.ndarray:
262
  """Equal-power crossfade join. Works for both mono (T,) and stereo (C, T) arrays.
263
+ Stereo arrays are expected in (channels, samples) layout.
264
+
265
+ db_boost is applied to the overlap region as a whole (after blending), so
266
+ it compensates for the -3 dB equal-power dip without doubling amplitude.
267
+ Applying gain to each side independently (the common mistake) causes a
268
+ +3 dB loudness bump at the seam — this version avoids that."""
269
  stereo = a.ndim == 2
270
  n_a = a.shape[1] if stereo else len(a)
271
  n_b = b.shape[1] if stereo else len(b)
 
277
  fade_out = np.cos(t * np.pi / 2) # 1 → 0
278
  fade_in = np.sin(t * np.pi / 2) # 0 → 1
279
  if stereo:
280
+ # Blend first, then apply boost to the overlap region as a unit
281
+ overlap = (a[:, -cf:] * fade_out + b[:, :cf] * fade_in) * gain
282
  return np.concatenate([a[:, :-cf], overlap, b[:, cf:]], axis=1)
283
  else:
284
+ overlap = (a[-cf:] * fade_out + b[:cf] * fade_in) * gain
285
  return np.concatenate([a[:-cf], overlap, b[cf:]])
286
 
287