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.0.tar.gz (15.1 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.0-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: sacrifunk_loudness-0.1.0.tar.gz
  • Upload date:
  • Size: 15.1 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.0.tar.gz
Algorithm Hash digest
SHA256 1f0e7ca54969d043368592baacdf5c1a1544bdb8cee72014819dbf46b51a9832
MD5 851e1598b2e7fd41506e2fb37e348314
BLAKE2b-256 d3c56007cd33ec2ead2663675e909271d3064c59b08801bd2859566ae42121a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for sacrifunk_loudness-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1961b13d314ec6ef4e60b035055af4aaf31aafabccde31fffcfa8383d10dcbbd
MD5 86ed8981f12c809d41d6a699c49e397c
BLAKE2b-256 8051884a0f8711a8affcd29edc43832f018e7d7e8ddb7529ada0f977b72e393e

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