audacia/src/effects/EBUR128.h
Max Maisel 17ef5b1c75 Fix two bugs in loudness effect (#410)
* Calculate loudness for short or silent selections as well.

In case of selections shorter than 400ms (one momentary loudness block),
take what we have got and divide only be the actual length.

Abort loudness normalization silently if the selected audio is all
silent.

* Fix loudness effect bug when selection includes a gap.

If the selected audio in a track contained a gap between two clips,
an incorrect amount of samples was processed.
2020-01-24 18:04:19 +00:00

60 lines
1.5 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
EBUR128.h
Max Maisel
***********************************************************************/
#ifndef __EBUR128_H__
#define __EBUR128_H__
#include "Biquad.h"
#include "MemoryX.h"
#include "SampleFormat.h"
/// \brief Implements EBU-R128 loudness measurement.
class EBUR128
{
public:
EBUR128(double rate, size_t channels);
EBUR128(const EBUR128&) = delete;
EBUR128(EBUR128&&) = delete;
~EBUR128() = default;
static ArrayOf<Biquad> CalcWeightingFilter(double fs);
void Initialize();
void ProcessSampleFromChannel(float x_in, size_t channel);
void NextSample();
double IntegrativeLoudness();
inline double IntegrativeLoudnessToLUFS(double loudness)
{ return 10 * log10(loudness); }
private:
void HistogramSums(size_t start_idx, double& sum_v, long int& sum_c);
void AddBlockToHistogram(size_t validLen);
static const size_t HIST_BIN_COUNT = 65536;
/// EBU R128 absolute threshold
static constexpr double GAMMA_A = (-70.0 + 0.691) / 10.0;
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;
/// 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)
ArrayOf<ArrayOf<Biquad>> mWeightingFilter;
};
#endif