Region loudness normalization/analysis #8777

This commit is contained in:
Robin Gareus 2021-07-20 01:31:48 +02:00
parent a22fe3cdc8
commit 5a9fde4a0b
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
4 changed files with 58 additions and 3 deletions

View File

@ -18,6 +18,7 @@
#include "ardour/analysis_graph.h"
#include "ardour/progress.h"
#include "ardour/route.h"
#include "ardour/session.h"
@ -54,7 +55,13 @@ AnalysisGraph::~AnalysisGraph ()
}
void
AnalysisGraph::analyze_region (boost::shared_ptr<AudioRegion> region)
AnalysisGraph::analyze_region (boost::shared_ptr<AudioRegion> region, bool raw)
{
analyze_region (region.get(), raw, (ARDOUR::Progress*)0);
}
void
AnalysisGraph::analyze_region (AudioRegion const* region, bool raw, ARDOUR::Progress* p)
{
int n_channels = region->n_channels();
if (n_channels == 0 || n_channels > _max_chunksize) {
@ -81,7 +88,11 @@ AnalysisGraph::analyze_region (boost::shared_ptr<AudioRegion> region)
samplecnt_t n = 0;
for (unsigned int channel = 0; channel < region->n_channels(); ++channel) {
memset (_buf, 0, chunk * sizeof (Sample));
n = region->read_at (_buf, _mixbuf, _gainbuf, region->position() + x, chunk, channel);
if (raw) {
n = region->read_raw_internal (_buf, region->start() + x, chunk, channel);
} else {
n = region->read_at (_buf, _mixbuf, _gainbuf, region->position() + x, chunk, channel);
}
ConstProcessContext<Sample> context (_buf, n, 1);
if (n < _max_chunksize) {
context().set_flag (ProcessContext<Sample>::EndOfInput);
@ -99,6 +110,12 @@ AnalysisGraph::analyze_region (boost::shared_ptr<AudioRegion> region)
if (_canceled) {
return;
}
if (p) {
p->set_progress (_samples_read / (float) _samples_end);
if (p->cancelled ()) {
return;
}
}
}
_results.insert (std::make_pair (region->name(), analyser->result ()));
}

View File

@ -38,12 +38,16 @@ namespace AudioGrapher {
}
namespace ARDOUR {
class Progress;
class LIBARDOUR_API AnalysisGraph {
public:
AnalysisGraph (ARDOUR::Session*);
~AnalysisGraph ();
void analyze_region (boost::shared_ptr<ARDOUR::AudioRegion>);
void analyze_region (ARDOUR::AudioRegion const*, bool raw = false, ARDOUR::Progress* = 0);
void analyze_region (boost::shared_ptr<ARDOUR::AudioRegion>, bool raw = false);
void analyze_range (boost::shared_ptr<ARDOUR::Route>, boost::shared_ptr<ARDOUR::AudioPlaylist>, const std::list<AudioRange>&);
const AnalysisResults& results () const { return _results; }

View File

@ -92,6 +92,8 @@ class LIBARDOUR_API AudioRegion : public Region
*/
double rms (Progress* p = 0) const;
bool loudness (float& tp, float& i, float& s, float& m, Progress* p = 0) const;
bool envelope_active () const { return _envelope_active; }
bool fade_in_active () const { return _fade_in_active; }
bool fade_out_active () const { return _fade_out_active; }

View File

@ -41,6 +41,7 @@
#include "evoral/Curve.h"
#include "ardour/analysis_graph.h"
#include "ardour/audioregion.h"
#include "ardour/session.h"
#include "ardour/dB.h"
@ -1470,6 +1471,37 @@ AudioRegion::rms (Progress* p) const
return sqrt (2. * rms / (double)(total * n_chan));
}
bool
AudioRegion::loudness (float& tp, float& i, float& s, float& m, Progress* p) const
{
ARDOUR::AnalysisGraph ag (&_session);
tp = i = s = m = -200;
ag.set_total_samples (_length);
ag.analyze_region (this, true, p);
if (p && p->cancelled ()) {
return false;
}
AnalysisResults const& ar (ag.results ());
if (ar.size() != 1) {
return false;
}
ExportAnalysisPtr eap (ar.begin ()->second);
if (eap->have_dbtp) {
tp = eap->truepeak;
}
if (eap->have_loudness) {
i = eap->integrated_loudness;
s = eap->max_loudness_short;
m = eap->max_loudness_momentary;
}
return eap->have_dbtp || eap->have_loudness;
}
/** Normalize using a given maximum amplitude and target, so that region
* _scale_amplitude becomes target / max_amplitude.
*/