Audacity 3.2.0
EBUR128.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3Audacity: A Digital Audio Editor
4
5EBUR128.cpp
6
7Max Maisel
8
9***********************************************************************/
10
11#include "EBUR128.h"
12#include <cstring>
13
14EBUR128::EBUR128(double rate, size_t channels)
15 : mChannelCount{ channels }
16 , mRate{ rate }
17 , mBlockSize( ceil(0.4 * mRate) ) // 400 ms blocks
18 , mBlockOverlap( ceil(0.1 * mRate) ) // 100 ms overlap
19{
23 for(size_t channel = 0; channel < mChannelCount; ++channel)
25
26 memset(mLoudnessHist.get(), 0, HIST_BIN_COUNT*sizeof(long int));
27 for(size_t channel = 0; channel < mChannelCount; ++channel)
28 {
29 mWeightingFilter[channel][0].Reset();
30 mWeightingFilter[channel][1].Reset();
31 }
32}
33
34// fs: sample rate
35// returns array of two Biquads
36//
37// EBU R128 parameter sampling rate adaption after
38// Mansbridge, Stuart, Saoirse Finn, and Joshua D. Reiss.
39// "Implementation and Evaluation of Autonomous Multi-track Fader Control."
40// Paper presented at the 132nd Audio Engineering Society Convention,
41// Budapest, Hungary, 2012."
43{
44 ArrayOf<Biquad> pBiquad(size_t(2), true);
45
46 //
47 // HSF pre filter
48 //
49 double db = 3.999843853973347;
50 double f0 = 1681.974450955533;
51 double Q = 0.7071752369554196;
52 double K = tan(M_PI * f0 / fs);
53
54 double Vh = pow(10.0, db / 20.0);
55 double Vb = pow(Vh, 0.4996667741545416);
56
57 double a0 = 1.0 + K / Q + K * K;
58
59 pBiquad[0].fNumerCoeffs[Biquad::B0] = (Vh + Vb * K / Q + K * K) / a0;
60 pBiquad[0].fNumerCoeffs[Biquad::B1] = 2.0 * (K * K - Vh) / a0;
61 pBiquad[0].fNumerCoeffs[Biquad::B2] = (Vh - Vb * K / Q + K * K) / a0;
62
63 pBiquad[0].fDenomCoeffs[Biquad::A1] = 2.0 * (K * K - 1.0) / a0;
64 pBiquad[0].fDenomCoeffs[Biquad::A2] = (1.0 - K / Q + K * K) / a0;
65
66 //
67 // HPF weighting filter
68 //
69 f0 = 38.13547087602444;
70 Q = 0.5003270373238773;
71 K = tan(M_PI * f0 / fs);
72
73 pBiquad[1].fNumerCoeffs[Biquad::B0] = 1.0;
74 pBiquad[1].fNumerCoeffs[Biquad::B1] = -2.0;
75 pBiquad[1].fNumerCoeffs[Biquad::B2] = 1.0;
76
77 pBiquad[1].fDenomCoeffs[Biquad::A1] = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K);
78 pBiquad[1].fDenomCoeffs[Biquad::A2] = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K);
79
80 return pBiquad;
81}
82
83void EBUR128::ProcessSampleFromChannel(float x_in, size_t channel) const
84{
85 double value;
86 value = mWeightingFilter[channel][0].ProcessOne(x_in);
87 value = mWeightingFilter[channel][1].ProcessOne(value);
88 if(channel == 0)
89 mBlockRingBuffer[mBlockRingPos] = value * value;
90 else
91 {
92 // Add the power of additional channels to the power of first channel.
93 // As a result, stereo tracks appear about 3 LUFS louder, as specified.
94 mBlockRingBuffer[mBlockRingPos] += value * value;
95 }
96}
97
99{
102
104 {
105 // A new full block of samples was submitted.
108 }
109 // Close the ring.
111 mBlockRingPos = 0;
112 ++mSampleCount;
113}
114
116{
117 // EBU R128: z_i = mean square without root
118
119 // Calculate Gamma_R from histogram.
120 double sum_v;
121 long int sum_c;
122 HistogramSums(0, sum_v, sum_c);
123
124 // Handle incomplete block if no non-zero block was found.
125 if(sum_c == 0)
126 {
128 HistogramSums(0, sum_v, sum_c);
129 }
130
131 // Histogram values are simplified log(x^2) immediate values
132 // without -0.691 + 10*(...) to safe computing power. This is
133 // possible because they will cancel out anyway.
134 // The -1 in the line below is the -10 LUFS from the EBU R128
135 // specification without the scaling factor of 10.
136 double Gamma_R = log10(sum_v/sum_c) - 1;
137 size_t idx_R = round((Gamma_R - GAMMA_A) * double(HIST_BIN_COUNT) / -GAMMA_A - 1);
138
139 // Apply Gamma_R threshold and calculate gated loudness (extent).
140 HistogramSums(idx_R+1, sum_v, sum_c);
141 if(sum_c == 0)
142 // Silence was processed.
143 return 0;
144 // LUFS is defined as -0.691 dB + 10*log10(sum(channels))
145 return 0.8529037031 * sum_v / sum_c;
146}
147
148void
149EBUR128::HistogramSums(size_t start_idx, double& sum_v, long int& sum_c) const
150{
151 double val;
152 sum_v = 0;
153 sum_c = 0;
154 for(size_t i = start_idx; i < HIST_BIN_COUNT; ++i)
155 {
156 val = -GAMMA_A / double(HIST_BIN_COUNT) * (i+1) + GAMMA_A;
157 sum_v += pow(10, val) * mLoudnessHist[i];
158 sum_c += mLoudnessHist[i];
159 }
160}
161
167void EBUR128::AddBlockToHistogram(size_t validLen)
168{
169 // Reset mBlockRingSize to full state to avoid overflow.
170 // The actual value of mBlockRingSize does not matter
171 // since this is only used to detect if blocks are complete (>= mBlockSize).
173
174 size_t idx;
175 double blockVal = 0;
176 for(size_t i = 0; i < validLen; ++i)
177 blockVal += mBlockRingBuffer[i];
178
179 // Histogram values are simplified log10() immediate values
180 // without -0.691 + 10*(...) to safe computing power. This is
181 // possible because these constant cancel out anyway during the
182 // following processing steps.
183 blockVal = log10(blockVal/double(validLen));
184 // log(blockVal) is within ]-inf, 1]
185 idx = round((blockVal - GAMMA_A) * double(HIST_BIN_COUNT) / -GAMMA_A - 1);
186
187 // idx is within ]-inf, HIST_BIN_COUNT-1], discard indices below 0
188 // as they are below the EBU R128 absolute threshold anyway.
189 if(idx < HIST_BIN_COUNT)
190 ++mLoudnessHist[idx];
191}
#define M_PI
Definition: Distortion.cpp:22
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:59
ArrayOf< long int > mLoudnessHist
Definition: EBUR128.h:43
size_t mBlockRingPos
Definition: EBUR128.h:46
const size_t mChannelCount
Definition: EBUR128.h:48
static constexpr double GAMMA_A
EBU R128 absolute threshold.
Definition: EBUR128.h:42
void ProcessSampleFromChannel(float x_in, size_t channel) const
Definition: EBUR128.cpp:83
void AddBlockToHistogram(size_t validLen)
Definition: EBUR128.cpp:167
void HistogramSums(size_t start_idx, double &sum_v, long int &sum_c) const
Definition: EBUR128.cpp:149
size_t mBlockRingSize
Definition: EBUR128.h:47
static constexpr size_t HIST_BIN_COUNT
Definition: EBUR128.h:40
static ArrayOf< Biquad > CalcWeightingFilter(double fs)
Definition: EBUR128.cpp:42
double IntegrativeLoudness()
Definition: EBUR128.cpp:115
EBUR128(double rate, size_t channels)
Definition: EBUR128.cpp:14
const size_t mBlockSize
Definition: EBUR128.h:50
void NextSample()
Definition: EBUR128.cpp:98
const double mRate
Definition: EBUR128.h:49
size_t mSampleCount
Definition: EBUR128.h:45
Doubles mBlockRingBuffer
Definition: EBUR128.h:44
ArrayOf< ArrayOf< Biquad > > mWeightingFilter
Definition: EBUR128.h:57
const size_t mBlockOverlap
Definition: EBUR128.h:51
fastfloat_really_inline void round(adjusted_mantissa &am, callback cb) noexcept
Definition: fast_float.h:2512
@ A1
Denominator coefficient indices.
Definition: Biquad.h:29
@ A2
Definition: Biquad.h:29
@ B1
Definition: Biquad.h:27
@ B2
Definition: Biquad.h:27
@ B0
Numerator coefficient indices.
Definition: Biquad.h:27