Skip to main content

ITU-R BS.1770 LUFS + true-peak + crest + LRA analyzer with batch CLI, Markdown report, and optional email send

Project description

sacrifunk-loudness

ITU-R BS.1770 LUFS + true-peak + crest analyzer with a Click CLI, Markdown report renderer, and optional SMTP email send. Drop a folder of WAV bounces at it and get back a JSON dump, a human-readable Markdown report, or an email straight to your inbox.

Why

Streaming-music mastering targets -14 LUFS ±0.5 and True Peak ≤ -1.0 dBTP (Sacrifunk's locked targets — same as Spotify/Apple/Tidal norms). Every bounce out of Logic Pro needs to clear those thresholds before it ships to CD Baby. This tool runs the standard analysis in one command and tells you which tracks pass and which need a second pass.

Install

pip install sacrifunk-loudness

Python 3.10+. Pulls in numpy, scipy, pyloudnorm, and click.

Usage

Single file

sacrifunk-loudness analyze Bounces/Darko_master.wav

Default output is JSON on stdout, summary on stderr.

Folder (recursive)

sacrifunk-loudness analyze Bounces/ --md report.md --json report.json

Custom targets (e.g. broadcast / podcast)

sacrifunk-loudness analyze Bounces/ \
  --target -16 \
  --tolerance 1.0 \
  --tp-limit -2 \
  --crest-min 10 --crest-max 22

Markdown from a saved JSON

sacrifunk-loudness report report.json --output report.md

Email a report

export SMTP_HOST=smtp.gmail.com
export SMTP_USER=info@sacrifunk.com
export SMTP_PASS='app-password-here'
export SMTP_FROM='Ahmed <info@sacrifunk.com>'

sacrifunk-loudness send report.md --to ae@example.com --subject "Genesis 3 — Blues Bang final master"

DSP

Metric Method
Integrated loudness (LUFS) pyloudnorm.Meter — ITU-R BS.1770-4 K-weighted gating
True peak (dBTP) 4× polyphase upsampling via scipy.signal.resample_poly, then 20·log10(max(abs(x)))
Sample peak (dBFS) 20·log10(max(abs(x))) on raw samples
Crest factor (dB) sample_peak_dBFS − 20·log10(RMS)

Mono input is duplicated to stereo before measurement. Int16/Int24/Int32/uint8 WAVs are normalized to [-1, 1] float64.

Sacrifunk defaults

The default AnalysisTargets matches Sacrifunk mastering canon (locked April 22, 2026):

  • LUFS target -14.0 ±0.5
  • True peak ≤ -1.0 dBTP
  • Crest factor 14–18 dB

Override any of these via CLI flags or by passing an AnalysisTargets to analyze_file() / analyze_folder() programmatically.

Library use

from sacrifunk_loudness import analyze_file, analyze_folder, render_markdown, SACRIFUNK_TARGETS

result = analyze_file("Bounces/Darko_master.wav")
print(result.lufs, result.true_peak_dbtp, result.verdict)

results = analyze_folder("Bounces/", SACRIFUNK_TARGETS, recursive=True)
md = render_markdown(results)

SMTP env vars

Var Required Default Notes
SMTP_HOST yes e.g. smtp.gmail.com
SMTP_USER yes full email address
SMTP_PASS yes app password, not your Google login
SMTP_FROM no SMTP_USER From: header
SMTP_PORT no 587 use 465 for SSL providers
SMTP_SECURITY no starttls starttls / ssl / none

Never pass credentials on the command line. send reads them from the environment only.

Development

pip install -e ".[dev]"
pytest -v

Tests use synthetic 1 kHz sine WAVs scaled to known LUFS levels via pyloudnorm — no Sacrifunk workspace dependency.

Roadmap

  • LRA (Loudness Range, EBU R128 gated) — currently summary only.
  • AAC / FLAC / AIFF input via soundfile fallback (today: WAV only via scipy.io.wavfile).
  • HTML report alongside Markdown.
  • --watch mode (chokidar-style folder watch).
  • Optional Telegram digest output for mobile workflows.

The Sacrifunk production stack already runs the analyzer via an n8n cron at _logic_pro_bounce_watch (30s scheduler, Telegram digest to @Sacrifunkbot). A planned follow-up swaps runtime/scripts/wav_quick_analyze.py to a thin from sacrifunk_loudness.analyzer import analyze_file wrapper.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sacrifunk_loudness-0.1.1.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sacrifunk_loudness-0.1.1-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file sacrifunk_loudness-0.1.1.tar.gz.

File metadata

  • Download URL: sacrifunk_loudness-0.1.1.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for sacrifunk_loudness-0.1.1.tar.gz
Algorithm Hash digest
SHA256 48b50a4437b902e3251337c958b37389b93e766e6f2ce34b925962f7a964f098
MD5 23fb8eb03cb7b3f7755295bf732bb8af
BLAKE2b-256 8389a94eaea2e7ab64ef9eb1ada704dc80de4859474197bf9ba41177e2e08095

See more details on using hashes here.

File details

Details for the file sacrifunk_loudness-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for sacrifunk_loudness-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e6fd3ccad42878416087dc47c7dd731e1b125bb790b63776f1c68a75a95ae0d7
MD5 7319208e2b7aaf5641bc54c8d02ec879
BLAKE2b-256 e33266b071705c72dc5727db999721d1a7bf91e8f324368631d0c0638956ea75

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page