prepare region RMS (loudness) normalization
authorRobin Gareus <robin@gareus.org>
Sun, 24 Jul 2016 18:28:56 +0000 (20:28 +0200)
committerRobin Gareus <robin@gareus.org>
Sun, 24 Jul 2016 18:30:23 +0000 (20:30 +0200)
libs/ardour/ardour/audioregion.h
libs/ardour/audioregion.cc

index c3003e587bba29b9dbaaaa7e0d5c843da0af12fe..d25cf0e421112b48bd1f6bdf1a5709534af2237a 100644 (file)
@@ -82,8 +82,17 @@ class LIBARDOUR_API AudioRegion : public Region
        gain_t scale_amplitude() const { return _scale_amplitude; }
 
        void normalize (float, float target_in_dB = 0.0f);
+
+       /** @return the maximum (linear) amplitude of the region, or a -ve
+        *  number if the Progress object reports that the process was cancelled.
+        */
        double maximum_amplitude (Progress* p = 0) const;
 
+       /** @return the maximum (rms) signal power of the region, or a -1
+        *  if the Progress object reports that the process was cancelled.
+        */
+       double rms (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; }
index 391dcfb2d381bb6802688607b05d3a63b119d143..873d4119d45e505c0dbb36ce1c4381e418ec20f5 100644 (file)
@@ -1402,9 +1402,6 @@ AudioRegion::set_scale_amplitude (gain_t g)
        send_change (PropertyChange (Properties::scale_amplitude));
 }
 
-/** @return the maximum (linear) amplitude of the region, or a -ve
- *  number if the Progress object reports that the process was cancelled.
- */
 double
 AudioRegion::maximum_amplitude (Progress* p) const
 {
@@ -1444,6 +1441,45 @@ AudioRegion::maximum_amplitude (Progress* p) const
        return maxamp;
 }
 
+double
+AudioRegion::rms (Progress* p) const
+{
+       framepos_t fpos = _start;
+       framepos_t const fend = _start + _length;
+       uint32_t const n_chan = n_channels ();
+       double rms = 0;
+
+       framecnt_t const blocksize = 64 * 1024;
+       Sample buf[blocksize];
+
+       framecnt_t total = 0;
+
+       if (n_chan == 0) {
+               return 0;
+       }
+
+       while (fpos < fend) {
+               framecnt_t const to_read = min (fend - fpos, blocksize);
+               total += to_read;
+               for (uint32_t c = 0; c < n_chan; ++c) {
+                       if (read_raw_internal (buf, fpos, to_read, c) != to_read) {
+                               return 0;
+                       }
+                       for (framepos_t i = 0; i < to_read; ++i) {
+                               rms += buf[i] * buf[i];
+                       }
+                       fpos += to_read;
+                       if (p) {
+                               p->set_progress (float (fpos - _start) / _length);
+                               if (p->cancelled ()) {
+                                       return -1;
+                               }
+                       }
+               }
+       }
+       return sqrt (rms / (double)(total * n_chan));
+}
+
 /** Normalize using a given maximum amplitude and target, so that region
  *  _scale_amplitude becomes target / max_amplitude.
  */