Audacity  3.0.3
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
EBUR128 Class Reference

Implements EBU-R128 loudness measurement. More...

#include <EBUR128.h>

Collaboration diagram for EBUR128:
[legend]

Public Member Functions

 EBUR128 (double rate, size_t channels)
 
 EBUR128 (const EBUR128 &)=delete
 
 EBUR128 (EBUR128 &&)=delete
 
 ~EBUR128 ()=default
 
void Initialize ()
 
void ProcessSampleFromChannel (float x_in, size_t channel)
 
void NextSample ()
 
double IntegrativeLoudness ()
 
double IntegrativeLoudnessToLUFS (double loudness)
 

Static Public Member Functions

static ArrayOf< BiquadCalcWeightingFilter (double fs)
 

Private Member Functions

void HistogramSums (size_t start_idx, double &sum_v, long int &sum_c)
 
void AddBlockToHistogram (size_t validLen)
 

Private Attributes

ArrayOf< long int > mLoudnessHist
 
Doubles mBlockRingBuffer
 
size_t mSampleCount
 
size_t mBlockRingPos
 
size_t mBlockRingSize
 
size_t mBlockSize
 
size_t mBlockOverlap
 
size_t mChannelCount
 
double mRate
 
ArrayOf< ArrayOf< Biquad > > mWeightingFilter
 

Static Private Attributes

static const size_t HIST_BIN_COUNT = 65536
 
static constexpr double GAMMA_A = (-70.0 + 0.691) / 10.0
 EBU R128 absolute threshold. More...
 

Detailed Description

Implements EBU-R128 loudness measurement.

Definition at line 21 of file EBUR128.h.

Constructor & Destructor Documentation

◆ EBUR128() [1/3]

EBUR128::EBUR128 ( double  rate,
size_t  channels 
)

Definition at line 14 of file EBUR128.cpp.

15  : mChannelCount(channels)
16  , mRate(rate)
17 {
18  mBlockSize = ceil(0.4 * mRate); // 400 ms blocks
19  mBlockOverlap = ceil(0.1 * mRate); // 100 ms overlap
23  for(size_t channel = 0; channel < mChannelCount; ++channel)
25 }

References CalcWeightingFilter(), HIST_BIN_COUNT, mBlockOverlap, mBlockRingBuffer, mBlockSize, mChannelCount, mLoudnessHist, mRate, mWeightingFilter, and ArrayOf< X >::reinit().

Here is the call graph for this function:

◆ EBUR128() [2/3]

EBUR128::EBUR128 ( const EBUR128 )
delete

◆ EBUR128() [3/3]

EBUR128::EBUR128 ( EBUR128 &&  )
delete

◆ ~EBUR128()

EBUR128::~EBUR128 ( )
default

Member Function Documentation

◆ AddBlockToHistogram()

void EBUR128::AddBlockToHistogram ( size_t  validLen)
private

Process new full block. Incomplete blocks shall be discarded according to the EBU R128 specification there is usually no need to call this on the last block. However, allow to override the block size if the audio to be processed is shorter than one block.

Definition at line 172 of file EBUR128.cpp.

173 {
174  // Reset mBlockRingSize to full state to avoid overflow.
175  // The actual value of mBlockRingSize does not matter
176  // since this is only used to detect if blocks are complete (>= mBlockSize).
178 
179  size_t idx;
180  double blockVal = 0;
181  for(size_t i = 0; i < validLen; ++i)
182  blockVal += mBlockRingBuffer[i];
183 
184  // Histogram values are simplified log10() immediate values
185  // without -0.691 + 10*(...) to safe computing power. This is
186  // possible because these constant cancel out anyway during the
187  // following processing steps.
188  blockVal = log10(blockVal/double(validLen));
189  // log(blockVal) is within ]-inf, 1]
190  idx = round((blockVal - GAMMA_A) * double(HIST_BIN_COUNT) / -GAMMA_A - 1);
191 
192  // idx is within ]-inf, HIST_BIN_COUNT-1], discard indices below 0
193  // as they are below the EBU R128 absolute threshold anyway.
194  if(idx < HIST_BIN_COUNT)
195  ++mLoudnessHist[idx];
196 }

References GAMMA_A, HIST_BIN_COUNT, mBlockRingBuffer, mBlockRingSize, mBlockSize, and mLoudnessHist.

Referenced by IntegrativeLoudness(), and NextSample().

Here is the caller graph for this function:

◆ CalcWeightingFilter()

ArrayOf< Biquad > EBUR128::CalcWeightingFilter ( double  fs)
static

Definition at line 48 of file EBUR128.cpp.

49 {
50  ArrayOf<Biquad> pBiquad(size_t(2), true);
51 
52  //
53  // HSF pre filter
54  //
55  double db = 3.999843853973347;
56  double f0 = 1681.974450955533;
57  double Q = 0.7071752369554196;
58  double K = tan(M_PI * f0 / fs);
59 
60  double Vh = pow(10.0, db / 20.0);
61  double Vb = pow(Vh, 0.4996667741545416);
62 
63  double a0 = 1.0 + K / Q + K * K;
64 
65  pBiquad[0].fNumerCoeffs[Biquad::B0] = (Vh + Vb * K / Q + K * K) / a0;
66  pBiquad[0].fNumerCoeffs[Biquad::B1] = 2.0 * (K * K - Vh) / a0;
67  pBiquad[0].fNumerCoeffs[Biquad::B2] = (Vh - Vb * K / Q + K * K) / a0;
68 
69  pBiquad[0].fDenomCoeffs[Biquad::A1] = 2.0 * (K * K - 1.0) / a0;
70  pBiquad[0].fDenomCoeffs[Biquad::A2] = (1.0 - K / Q + K * K) / a0;
71 
72  //
73  // HPF weighting filter
74  //
75  f0 = 38.13547087602444;
76  Q = 0.5003270373238773;
77  K = tan(M_PI * f0 / fs);
78 
79  pBiquad[1].fNumerCoeffs[Biquad::B0] = 1.0;
80  pBiquad[1].fNumerCoeffs[Biquad::B1] = -2.0;
81  pBiquad[1].fNumerCoeffs[Biquad::B2] = 1.0;
82 
83  pBiquad[1].fDenomCoeffs[Biquad::A1] = 2.0 * (K * K - 1.0) / (1.0 + K / Q + K * K);
84  pBiquad[1].fDenomCoeffs[Biquad::A2] = (1.0 - K / Q + K * K) / (1.0 + K / Q + K * K);
85 
86  return std::move(pBiquad);
87 }

References Biquad::A1, Biquad::A2, Biquad::B0, Biquad::B1, Biquad::B2, and M_PI.

Referenced by EBUR128().

Here is the caller graph for this function:

◆ HistogramSums()

void EBUR128::HistogramSums ( size_t  start_idx,
double &  sum_v,
long int &  sum_c 
)
private

Definition at line 154 of file EBUR128.cpp.

155 {
156  double val;
157  sum_v = 0;
158  sum_c = 0;
159  for(size_t i = start_idx; i < HIST_BIN_COUNT; ++i)
160  {
161  val = -GAMMA_A / double(HIST_BIN_COUNT) * (i+1) + GAMMA_A;
162  sum_v += pow(10, val) * mLoudnessHist[i];
163  sum_c += mLoudnessHist[i];
164  }
165 }

References GAMMA_A, HIST_BIN_COUNT, and mLoudnessHist.

Referenced by IntegrativeLoudness().

Here is the caller graph for this function:

◆ Initialize()

void EBUR128::Initialize ( )

Definition at line 27 of file EBUR128.cpp.

28 {
29  mSampleCount = 0;
30  mBlockRingPos = 0;
31  mBlockRingSize = 0;
32  memset(mLoudnessHist.get(), 0, HIST_BIN_COUNT*sizeof(long int));
33  for(size_t channel = 0; channel < mChannelCount; ++channel)
34  {
35  mWeightingFilter[channel][0].Reset();
36  mWeightingFilter[channel][1].Reset();
37  }
38 }

References HIST_BIN_COUNT, mBlockRingPos, mBlockRingSize, mChannelCount, mLoudnessHist, mSampleCount, and mWeightingFilter.

◆ IntegrativeLoudness()

double EBUR128::IntegrativeLoudness ( )

Definition at line 121 of file EBUR128.cpp.

122 {
123  // EBU R128: z_i = mean square without root
124 
125  // Calculate Gamma_R from histogram.
126  double sum_v;
127  long int sum_c;
128  HistogramSums(0, sum_v, sum_c);
129 
130  // Handle incomplete block if no non-zero block was found.
131  if(sum_c == 0)
132  {
134  HistogramSums(0, sum_v, sum_c);
135  }
136 
137  // Histogram values are simplified log(x^2) immediate values
138  // without -0.691 + 10*(...) to safe computing power. This is
139  // possible because they will cancel out anyway.
140  // The -1 in the line below is the -10 LUFS from the EBU R128
141  // specification without the scaling factor of 10.
142  double Gamma_R = log10(sum_v/sum_c) - 1;
143  size_t idx_R = round((Gamma_R - GAMMA_A) * double(HIST_BIN_COUNT) / -GAMMA_A - 1);
144 
145  // Apply Gamma_R threshold and calculate gated loudness (extent).
146  HistogramSums(idx_R+1, sum_v, sum_c);
147  if(sum_c == 0)
148  // Silence was processed.
149  return 0;
150  // LUFS is defined as -0.691 dB + 10*log10(sum(channels))
151  return 0.8529037031 * sum_v / sum_c;
152 }

References AddBlockToHistogram(), GAMMA_A, HIST_BIN_COUNT, HistogramSums(), and mBlockRingSize.

Here is the call graph for this function:

◆ IntegrativeLoudnessToLUFS()

double EBUR128::IntegrativeLoudnessToLUFS ( double  loudness)
inline

Definition at line 34 of file EBUR128.h.

35  { return 10 * log10(loudness); }

◆ NextSample()

void EBUR128::NextSample ( )

Definition at line 104 of file EBUR128.cpp.

105 {
106  ++mBlockRingPos;
107  ++mBlockRingSize;
108 
109  if(mBlockRingPos % mBlockOverlap == 0)
110  {
111  // A new full block of samples was submitted.
114  }
115  // Close the ring.
117  mBlockRingPos = 0;
118  ++mSampleCount;
119 }

References AddBlockToHistogram(), mBlockOverlap, mBlockRingPos, mBlockRingSize, mBlockSize, and mSampleCount.

Here is the call graph for this function:

◆ ProcessSampleFromChannel()

void EBUR128::ProcessSampleFromChannel ( float  x_in,
size_t  channel 
)

Definition at line 89 of file EBUR128.cpp.

90 {
91  double value;
92  value = mWeightingFilter[channel][0].ProcessOne(x_in);
93  value = mWeightingFilter[channel][1].ProcessOne(value);
94  if(channel == 0)
95  mBlockRingBuffer[mBlockRingPos] = value * value;
96  else
97  {
98  // Add the power of additional channels to the power of first channel.
99  // As a result, stereo tracks appear about 3 LUFS louder, as specified.
100  mBlockRingBuffer[mBlockRingPos] += value * value;
101  }
102 }

References mBlockRingBuffer, mBlockRingPos, and mWeightingFilter.

Member Data Documentation

◆ GAMMA_A

constexpr double EBUR128::GAMMA_A = (-70.0 + 0.691) / 10.0
staticconstexprprivate

EBU R128 absolute threshold.

Definition at line 43 of file EBUR128.h.

Referenced by AddBlockToHistogram(), HistogramSums(), and IntegrativeLoudness().

◆ HIST_BIN_COUNT

const size_t EBUR128::HIST_BIN_COUNT = 65536
staticprivate

◆ mBlockOverlap

size_t EBUR128::mBlockOverlap
private

Definition at line 50 of file EBUR128.h.

Referenced by EBUR128(), and NextSample().

◆ mBlockRingBuffer

Doubles EBUR128::mBlockRingBuffer
private

Definition at line 45 of file EBUR128.h.

Referenced by AddBlockToHistogram(), EBUR128(), and ProcessSampleFromChannel().

◆ mBlockRingPos

size_t EBUR128::mBlockRingPos
private

Definition at line 47 of file EBUR128.h.

Referenced by Initialize(), NextSample(), and ProcessSampleFromChannel().

◆ mBlockRingSize

size_t EBUR128::mBlockRingSize
private

Definition at line 48 of file EBUR128.h.

Referenced by AddBlockToHistogram(), Initialize(), IntegrativeLoudness(), and NextSample().

◆ mBlockSize

size_t EBUR128::mBlockSize
private

Definition at line 49 of file EBUR128.h.

Referenced by AddBlockToHistogram(), EBUR128(), and NextSample().

◆ mChannelCount

size_t EBUR128::mChannelCount
private

Definition at line 51 of file EBUR128.h.

Referenced by EBUR128(), and Initialize().

◆ mLoudnessHist

ArrayOf<long int> EBUR128::mLoudnessHist
private

Definition at line 44 of file EBUR128.h.

Referenced by AddBlockToHistogram(), EBUR128(), HistogramSums(), and Initialize().

◆ mRate

double EBUR128::mRate
private

Definition at line 52 of file EBUR128.h.

Referenced by EBUR128().

◆ mSampleCount

size_t EBUR128::mSampleCount
private

Definition at line 46 of file EBUR128.h.

Referenced by Initialize(), and NextSample().

◆ mWeightingFilter

ArrayOf<ArrayOf<Biquad> > EBUR128::mWeightingFilter
private

This is be an array of arrays of the type mWeightingFilter[CHANNEL][FILTER] with CHANNEL = LEFT/RIGHT (0/1) and FILTER = HSF/HPF (0/1)

Definition at line 58 of file EBUR128.h.

Referenced by EBUR128(), Initialize(), and ProcessSampleFromChannel().


The documentation for this class was generated from the following files:
EBUR128::mBlockSize
size_t mBlockSize
Definition: EBUR128.h:49
EBUR128::mRate
double mRate
Definition: EBUR128.h:52
EBUR128::mWeightingFilter
ArrayOf< ArrayOf< Biquad > > mWeightingFilter
Definition: EBUR128.h:58
EBUR128::mBlockRingPos
size_t mBlockRingPos
Definition: EBUR128.h:47
ArrayOf::reinit
void reinit(Integral count, bool initialize=false)
Definition: MemoryX.h:57
EBUR128::mSampleCount
size_t mSampleCount
Definition: EBUR128.h:46
EBUR128::mLoudnessHist
ArrayOf< long int > mLoudnessHist
Definition: EBUR128.h:44
EBUR128::CalcWeightingFilter
static ArrayOf< Biquad > CalcWeightingFilter(double fs)
Definition: EBUR128.cpp:48
EBUR128::mChannelCount
size_t mChannelCount
Definition: EBUR128.h:51
Biquad::B1
@ B1
Definition: Biquad.h:27
EBUR128::mBlockOverlap
size_t mBlockOverlap
Definition: EBUR128.h:50
Biquad::A2
@ A2
Definition: Biquad.h:29
Biquad::A1
@ A1
Denominator coefficient indices.
Definition: Biquad.h:29
EBUR128::mBlockRingBuffer
Doubles mBlockRingBuffer
Definition: EBUR128.h:45
Biquad::B0
@ B0
Numerator coefficient indices.
Definition: Biquad.h:27
Biquad::B2
@ B2
Definition: Biquad.h:27
EBUR128::HIST_BIN_COUNT
static const size_t HIST_BIN_COUNT
Definition: EBUR128.h:41
M_PI
#define M_PI
Definition: Distortion.cpp:29
EBUR128::GAMMA_A
static constexpr double GAMMA_A
EBU R128 absolute threshold.
Definition: EBUR128.h:43
EBUR128::HistogramSums
void HistogramSums(size_t start_idx, double &sum_v, long int &sum_c)
Definition: EBUR128.cpp:154
ArrayOf< Biquad >
EBUR128::mBlockRingSize
size_t mBlockRingSize
Definition: EBUR128.h:48
EBUR128::AddBlockToHistogram
void AddBlockToHistogram(size_t validLen)
Definition: EBUR128.cpp:172