Class: Wavify::DSP::LoudnessMeter
- Inherits:
-
Object
- Object
- Wavify::DSP::LoudnessMeter
- Defined in:
- lib/wavify/dsp/loudness_meter.rb,
sig/dsp.rbs
Overview
ITU-R BS.1770 integrated loudness meter with EBU-style gating.
Constant Summary collapse
- LOUDNESS_OFFSET =
-0.691
- ABSOLUTE_GATE_LUFS =
-70.0
- RELATIVE_GATE_LU =
-10.0
- BLOCK_SECONDS =
0.4- STEP_SECONDS =
0.1- SHORT_TERM_SECONDS =
3.0- TRUE_PEAK_OVERSAMPLING =
4- TRUE_PEAK_RADIUS =
8
Class Method Summary collapse
-
.integrated(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) ⇒ Float
Measures integrated loudness.
-
.momentary(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) ⇒ Float
Measures the most recent 400 ms loudness window without gating.
-
.short_term(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) ⇒ Float
Measures the most recent 3 second loudness window without gating.
-
.true_peak(samples, sample_rate: nil, channels: nil, format: nil, oversampling: TRUE_PEAK_OVERSAMPLING) ⇒ Float
Estimates inter-sample true peak with windowed-sinc oversampling.
Class Method Details
.integrated(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) ⇒ Float
Measures integrated loudness. Inputs shorter than the BS.1770 400 ms block are treated as a single partial block.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/wavify/dsp/loudness_meter.rb', line 19 def integrated(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) samples, sample_rate, channels, channel_layout = measurement_input( samples, sample_rate: sample_rate, channels: channels, format: format, channel_layout: channel_layout ) return -Float::INFINITY if samples.empty? weighted = k_weight(samples, sample_rate: sample_rate, channels: channels) energies = block_energies( weighted, sample_rate: sample_rate, channels: channels, channel_layout: channel_layout ) absolute_gated = energies.select { |energy| loudness_for_energy(energy) >= ABSOLUTE_GATE_LUFS } return -Float::INFINITY if absolute_gated.empty? relative_gate = loudness_for_energy(mean(absolute_gated)) + RELATIVE_GATE_LU relative_gated = absolute_gated.select { |energy| loudness_for_energy(energy) >= relative_gate } loudness_for_energy(mean(relative_gated)) end |
.momentary(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) ⇒ Float
Measures the most recent 400 ms loudness window without gating.
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/wavify/dsp/loudness_meter.rb', line 45 def momentary(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) window_loudness( samples, seconds: BLOCK_SECONDS, sample_rate: sample_rate, channels: channels, format: format, channel_layout: channel_layout ) end |
.short_term(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) ⇒ Float
Measures the most recent 3 second loudness window without gating.
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/wavify/dsp/loudness_meter.rb', line 57 def short_term(samples, sample_rate: nil, channels: nil, format: nil, channel_layout: nil) window_loudness( samples, seconds: SHORT_TERM_SECONDS, sample_rate: sample_rate, channels: channels, format: format, channel_layout: channel_layout ) end |
.true_peak(samples, sample_rate: nil, channels: nil, format: nil, oversampling: TRUE_PEAK_OVERSAMPLING) ⇒ Float
Estimates inter-sample true peak with windowed-sinc oversampling.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/wavify/dsp/loudness_meter.rb', line 69 def true_peak(samples, sample_rate: nil, channels: nil, format: nil, oversampling: TRUE_PEAK_OVERSAMPLING) samples, _sample_rate, channels, = measurement_input( samples, sample_rate: sample_rate, channels: channels, format: format, channel_layout: nil ) unless [2, 4, 8].include?(oversampling) raise InvalidParameterError, "oversampling must be 2, 4, or 8" end return 0.0 if samples.empty? channel_samples = Array.new(channels) { [] } samples.each_with_index { |sample, index| channel_samples.fetch(index % channels) << sample.to_f } channel_samples.map { |values| oversampled_peak(values, oversampling) }.max || 0.0 end |