Documentation
¶
Overview ¶
Package normalize measures EBU R128 loudness with ffmpeg's loudnorm filter and builds the matching apply filter for a later encode.
Measure runs an analysis pass and returns integrated loudness, true peak, and loudness range without altering the input. ApplyFilter uses that measurement to build a linear loudnorm filter for transcode.Spec.Filters, so normalization can run in the same encode as the format conversion.
The package reports loudness measurements (LUFS, dBTP, LU), not ReplayGain tag values. Callers choose the target loudness and handle any tag conversion.
Process execution stays in the transcode package; loudnorm filter syntax and JSON parsing live here.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AlbumGainFilter ¶
AlbumGainFilter builds the per-track filter for destructive album normalization. Each track receives the same target-albumIntegrated dB offset, preserving track-to-track loudness differences across the album. Use ApplyFilter for independent track normalization.
It returns anull when either value is not finite (for example a silent album), matching ApplyFilter's silent-input behavior.
func ApplyFilter ¶
ApplyFilter builds the loudnorm filter for a normalizing encode, targeting the given LUFS value. It uses values from a prior Measure pass and enables loudnorm's linear mode. Pass the result through transcode.Spec.Filters to run normalization as part of the encode.
When the measurement is not finite, ApplyFilter returns anull. That keeps silent inputs valid and avoids formatting loudnorm parameters such as measured_I=-Inf, which ffmpeg rejects.
func MeasureAlbum ¶
func MeasureAlbum(ctx context.Context, r *transcode.Runner, inputs []string) (album Loudness, perTrack []Loudness, err error)
MeasureAlbum measures a set of tracks as a group and individually. The album value is the EBU R128 result for the concatenated tracks, including normal gating and energy weighting; it is not an average of per-track LUFS. perTrack follows input order.
Inputs may differ in sample rate and channel layout; each is conformed to a common measurement format before concatenation so the group pass does not fail on a layout mismatch.
Types ¶
type Loudness ¶
type Loudness struct {
IntegratedLUFS float64 // integrated loudness (loudnorm input_i)
TruePeakDBTP float64 // true peak, dBTP (input_tp)
LRA float64 // loudness range, LU (input_lra)
Threshold float64 // relative gate threshold, LUFS (input_thresh)
// Offset is loudnorm's target_offset from the analysis pass. It seeds the
// linear apply pass and is not part of WaxTap's reported measurements.
Offset float64
}
Loudness is an EBU R128 measurement parsed from a loudnorm analysis pass.
func Measure ¶
func Measure(ctx context.Context, r *transcode.Runner, input string, pre []string) (Loudness, error)
Measure runs a loudnorm analysis pass over input and returns its EBU R128 measurement. pre lists audio filters applied before the measurement (e.g. cut filters), so the measured loudness matches the audio that will be encoded. It writes no output file.
func MeasureComplex ¶
func MeasureComplex(ctx context.Context, r *transcode.Runner, input, graph, sink string) (Loudness, error)
MeasureComplex runs a loudnorm analysis pass after a -filter_complex graph. graph must read [0:a:0] and write the named sink label; MeasureComplex appends loudnorm to that label and maps the result to a null output. It writes no output file.
Use it when the pre-processing cannot be expressed as a linear -af chain, such as a multi-segment cut whose atrim/concat graph only fits -filter_complex. The measured loudness then matches the post-cut audio a fused encode will produce. Use Measure for the linear case.