thecollabagepatch commited on
Commit
d96e1a0
Β·
1 Parent(s): 86dd29c

fixing logging

Browse files
Files changed (1) hide show
  1. jam_worker.py +44 -26
jam_worker.py CHANGED
@@ -552,26 +552,25 @@ class JamWorker(threading.Thread):
552
  return self.idx <= (horizon_anchor + self._max_buffer_ahead)
553
 
554
  def _emit_ready(self):
555
- """Emit next chunk(s) if the spool has enough samples. With verbose RMS debug."""
556
 
557
 
558
- QDB_SILENCE = -55.0 # quarter-bar segment considered "near silence" if RMS dBFS below this
559
  EPS = 1e-12
560
 
561
  def rms_dbfs(x: np.ndarray) -> float:
562
- # x: float32 [-1,1]; return single-channel RMS dBFS (mean over channels if stereo)
563
  if x.ndim == 2:
564
  x = x.mean(axis=1)
565
  rms = float(np.sqrt(np.mean(np.square(x)) + EPS))
566
  return 20.0 * np.log10(max(rms, EPS))
567
 
568
  def qbar_rms_dbfs(x: np.ndarray, seg_len: int) -> list[float]:
569
- vals = []
570
  if x.ndim == 2:
571
  mono = x.mean(axis=1)
572
  else:
573
  mono = x
574
  N = mono.shape[0]
 
575
  for i in range(0, N, seg_len):
576
  seg = mono[i:min(i + seg_len, N)]
577
  if seg.size == 0:
@@ -580,32 +579,51 @@ class JamWorker(threading.Thread):
580
  vals.append(20.0 * np.log10(max(r, EPS)))
581
  return vals
582
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
  while True:
584
  start, end = self._bar_clock.bounds_for_chunk(self.idx, self.params.bars_per_chunk)
585
  if end > self._spool_written:
586
- # Not enough audio buffered for the next full chunk
587
- # Debug the readiness gap once per idx
588
- # print(f"[emit idx={self.idx}] need end={end}, have={self._spool_written} (Ξ”={end - self._spool_written})")
589
  break
590
 
591
- # Slice the emitted window (target SR)
592
- loop = self._spool[start:end] # shape: [samples, channels] @ target_sr
593
 
594
- # ---- DEBUG: pre-loudness quarter-bar RMS ----
595
- spb = self._bar_clock.bar_samps # samples per bar @ target_sr
596
- qlen = max(1, spb // 4) # quarter-bar segment length
597
  q_rms_pre = qbar_rms_dbfs(loop, qlen)
598
- # Mark segments that look like near-silence
599
  silent_marks_pre = ["🟒" if v > QDB_SILENCE else "πŸŸ₯" for v in q_rms_pre[:8]]
600
- print(f"[emit idx={self.idx}] pre-LM qRMS dBFS: {['%5.1f'%v for v in q_rms_pre[:8]]} {''.join(silent_marks_pre)}")
601
 
602
- # Loudness match to reference loop (optional)
603
- gain_db_applied = None
604
  if self.params.ref_loop is not None and self.params.loudness_mode != "none":
605
  ref = self.params.ref_loop.as_stereo().resample(self.params.target_sr)
606
  wav = au.Waveform(loop.copy(), int(self.params.target_sr))
607
  try:
608
- matched, gain_db_applied = match_loudness_to_reference(
609
  ref, wav,
610
  method=self.params.loudness_mode,
611
  headroom_db=self.params.headroom_db
@@ -614,13 +632,15 @@ class JamWorker(threading.Thread):
614
  except Exception as e:
615
  print(f"[emit idx={self.idx}] loudness-match ERROR: {e}; proceeding with un-matched audio")
616
 
617
- # ---- DEBUG: post-loudness quarter-bar RMS ----
 
 
618
  q_rms_post = qbar_rms_dbfs(loop, qlen)
619
  silent_marks_post = ["🟒" if v > QDB_SILENCE else "πŸŸ₯" for v in q_rms_post[:8]]
620
- if gain_db_applied is None:
621
- print(f"[emit idx={self.idx}] post-LM qRMS dBFS: {['%5.1f'%v for v in q_rms_post[:8]]} {''.join(silent_marks_post)} (LM: none)")
622
  else:
623
- print(f"[emit idx={self.idx}] post-LM qRMS dBFS: {['%5.1f'%v for v in q_rms_post[:8]]} {''.join(silent_marks_post)} (LM gain {gain_db_applied:+.2f} dB)")
624
 
625
  # Encode & ship
626
  audio_b64, total_samples, channels = wav_bytes_base64(loop, int(self.params.target_sr))
@@ -639,22 +659,19 @@ class JamWorker(threading.Thread):
639
  }
640
  chunk = JamChunk(index=self.idx, audio_base64=audio_b64, metadata=meta)
641
 
642
- # Emit to outbox
643
  with self._cv:
644
  self._outbox[self.idx] = chunk
645
  self._cv.notify_all()
646
 
647
- # ---- DEBUG: boundary bookkeeping ----
648
  print(f"[emit idx={self.idx}] slice [{start}:{end}] (len={end-start}), spool_written={self._spool_written}")
649
-
650
  self.idx += 1
651
 
652
- # If a reseed is queued, install it *right after* we finish a chunk
653
  with self._lock:
654
  if self._pending_token_splice is not None:
655
  spliced = self._coerce_tokens(self._pending_token_splice["tokens"])
656
  try:
657
- self.state.context_tokens = spliced # in-place update
658
  self._pending_token_splice = None
659
  print(f"[emit idx={self.idx}] installed token splice (in-place)")
660
  except Exception:
@@ -673,6 +690,7 @@ class JamWorker(threading.Thread):
673
  self._pending_reseed = None
674
  print(f"[emit idx={self.idx}] performed full reseed")
675
 
 
676
  # ---------- main loop ----------
677
 
678
  def run(self):
 
552
  return self.idx <= (horizon_anchor + self._max_buffer_ahead)
553
 
554
  def _emit_ready(self):
555
+ """Emit next chunk(s) if the spool has enough samples. With robust RMS debug."""
556
 
557
 
558
+ QDB_SILENCE = -55.0
559
  EPS = 1e-12
560
 
561
  def rms_dbfs(x: np.ndarray) -> float:
 
562
  if x.ndim == 2:
563
  x = x.mean(axis=1)
564
  rms = float(np.sqrt(np.mean(np.square(x)) + EPS))
565
  return 20.0 * np.log10(max(rms, EPS))
566
 
567
  def qbar_rms_dbfs(x: np.ndarray, seg_len: int) -> list[float]:
 
568
  if x.ndim == 2:
569
  mono = x.mean(axis=1)
570
  else:
571
  mono = x
572
  N = mono.shape[0]
573
+ vals = []
574
  for i in range(0, N, seg_len):
575
  seg = mono[i:min(i + seg_len, N)]
576
  if seg.size == 0:
 
579
  vals.append(20.0 * np.log10(max(r, EPS)))
580
  return vals
581
 
582
+ def fmt_db_list(vals):
583
+ return ['%5.1f' % v for v in vals[:8]]
584
+
585
+ def extract_gain_db(g):
586
+ # Accept float/int, dict{'gain_db': ...}, tuple/list, or None
587
+ if g is None:
588
+ return None
589
+ if isinstance(g, (int, float)):
590
+ return float(g)
591
+ if isinstance(g, dict):
592
+ for k in ('gain_db', 'gain', 'applied_gain_db'):
593
+ if k in g:
594
+ try:
595
+ return float(g[k])
596
+ except Exception:
597
+ pass
598
+ return None
599
+ if isinstance(g, (list, tuple)) and g:
600
+ try:
601
+ return float(g[0])
602
+ except Exception:
603
+ return None
604
+ return None
605
+
606
  while True:
607
  start, end = self._bar_clock.bounds_for_chunk(self.idx, self.params.bars_per_chunk)
608
  if end > self._spool_written:
 
 
 
609
  break
610
 
611
+ loop = self._spool[start:end]
 
612
 
613
+ # ---- pre-LM diagnostics ----
614
+ spb = self._bar_clock.bar_samps
615
+ qlen = max(1, spb // 4)
616
  q_rms_pre = qbar_rms_dbfs(loop, qlen)
 
617
  silent_marks_pre = ["🟒" if v > QDB_SILENCE else "πŸŸ₯" for v in q_rms_pre[:8]]
618
+ print(f"[emit idx={self.idx}] pre-LM qRMS dBFS: {fmt_db_list(q_rms_pre)} {''.join(silent_marks_pre)}")
619
 
620
+ # Loudness match (optional)
621
+ gain_db_applied_raw = None
622
  if self.params.ref_loop is not None and self.params.loudness_mode != "none":
623
  ref = self.params.ref_loop.as_stereo().resample(self.params.target_sr)
624
  wav = au.Waveform(loop.copy(), int(self.params.target_sr))
625
  try:
626
+ matched, gain_db_applied_raw = match_loudness_to_reference(
627
  ref, wav,
628
  method=self.params.loudness_mode,
629
  headroom_db=self.params.headroom_db
 
632
  except Exception as e:
633
  print(f"[emit idx={self.idx}] loudness-match ERROR: {e}; proceeding with un-matched audio")
634
 
635
+ gain_db = extract_gain_db(gain_db_applied_raw)
636
+
637
+ # ---- post-LM diagnostics ----
638
  q_rms_post = qbar_rms_dbfs(loop, qlen)
639
  silent_marks_post = ["🟒" if v > QDB_SILENCE else "πŸŸ₯" for v in q_rms_post[:8]]
640
+ if gain_db is None:
641
+ print(f"[emit idx={self.idx}] post-LM qRMS dBFS: {fmt_db_list(q_rms_post)} {''.join(silent_marks_post)} (LM: none)")
642
  else:
643
+ print(f"[emit idx={self.idx}] post-LM qRMS dBFS: {fmt_db_list(q_rms_post)} {''.join(silent_marks_post)} (LM gain {gain_db:+.2f} dB)")
644
 
645
  # Encode & ship
646
  audio_b64, total_samples, channels = wav_bytes_base64(loop, int(self.params.target_sr))
 
659
  }
660
  chunk = JamChunk(index=self.idx, audio_base64=audio_b64, metadata=meta)
661
 
 
662
  with self._cv:
663
  self._outbox[self.idx] = chunk
664
  self._cv.notify_all()
665
 
 
666
  print(f"[emit idx={self.idx}] slice [{start}:{end}] (len={end-start}), spool_written={self._spool_written}")
 
667
  self.idx += 1
668
 
669
+ # Apply pending splices/reseeds immediately after a completed emit
670
  with self._lock:
671
  if self._pending_token_splice is not None:
672
  spliced = self._coerce_tokens(self._pending_token_splice["tokens"])
673
  try:
674
+ self.state.context_tokens = spliced
675
  self._pending_token_splice = None
676
  print(f"[emit idx={self.idx}] installed token splice (in-place)")
677
  except Exception:
 
690
  self._pending_reseed = None
691
  print(f"[emit idx={self.idx}] performed full reseed")
692
 
693
+
694
  # ---------- main loop ----------
695
 
696
  def run(self):