Files
uj-mastering-master/README.md
T
Mikkeli Matlock 7bdf465799 Add pluggable metrics architecture with LUFS
Introduce a Metric ABC (compute on worker thread, render on GUI thread)
with a METRICS registry, and refactor the analysis pipeline around it.
RMS power (ported), raw waveform, and BS.1770 LUFS (via pyloudnorm) ship
as the initial three; new metrics drop in by appending to METRICS.

- metrics.py: Metric ABC + RMSPowerMetric, WaveformMetric (locked to
  +/-1.1 y-range for float headroom), LUFSMetric (short-term 3 s window
  + integrated value, with streaming-target reference line).
- plot_control_widget.py: metric selector dropdown + Refresh Plot button
  (moved out of FontControlWidget).
- analysis_results_manager.py: AnalysisResult caches the AudioFile and a
  per-metric data dict; new MetricComputeWorker runs metric switches off
  the GUI thread via metricComputeStarted/metricReady/metricComputeError
  signals, so LUFS on a 12-minute track no longer stalls the UI.
- main.py: all redraw paths funnel through one _render_or_request helper;
  stale-result guards keep slow computes from overwriting fresh selections.
- plotting_engine.py removed (metadata text moved onto AnalysisResult;
  figure construction lives in each Metric).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-30 00:42:45 +09:00

2.5 KiB

uj-mastering-master

Custom mastering toolkit providing visual metrics for evaluating audio masterings. Developed with Claude Code assistance.

Features

Current

  • PyQt5 GUI: drag-and-drop or file-dialog ingest of .mp3, .wav, .flac
  • RMS power analysis on a 10 s rolling window with adaptive colour scale
  • BPM detection via librosa
  • CJK-safe font system with custom fonts loaded from fonts/ (gitignored), system fallbacks, and a live font selector
  • Background analysis thread so the UI stays responsive
  • Embedded matplotlib canvas with auto-regenerated plots on font change

Roadmap

See CLAUDE.md for the full development roadmap. Near-term: dynamic range, plot-style controls, interactive axis controls.

Quick start

This project uses uv. With uv installed:

uv sync
uv run ujm

uv run ujm is the only supported entry point — it boots the GUI.

Logging flags

uv run ujm --log-level DEBUG       # ERROR | WARN | INFO | DEBUG | TRACE
uv run ujm --log-file               # also write audio_analysis.log

Fonts

Drop .ttf / .otf / .ttc files into fonts/ to get them in the font selector. The directory is gitignored to avoid bundling licensed font data. See CJK_FONTS.md for details.

Dependencies

librosa, numpy, matplotlib, mutagen, pyloudnorm, PyQt5 — all pinned through uv.lock. Python 3.10+.

Architecture

Module Responsibility
main.py MainWindow + the ujm entry point
analysis_results_manager.py Background QThread worker, result + metric-data cache
master_core.py AudioFile: librosa loading, RMS rolling window, BPM
metrics.py Pluggable Metric ABC + registry (RMS Power, Waveform, …)
audio_visualization_widget.py Embedded FigureCanvasQTAgg host
font_manager.py Custom + system CJK font discovery, matplotlib/Qt config
font_control_widget.py Font picker + size slider
plot_control_widget.py Metric selector + refresh-plot button
logger_setup.py CLI log-level parsing + custom TRACE level
setup_fonts.py Diagnostic utility (run standalone)

Adding a metric

Subclass Metric in metrics.py, implement compute(audio_file) -> data (the heavy part, runs on the worker thread) and render(data, file_path) -> Figure (cheap, runs on the GUI thread). Register the instance in the METRICS dict at the bottom of the file — it shows up in the dropdown automatically.