= Fast RMS Envelope Follower

include::../../common.adoc[]

== Overview

The Fast RMS Envelope Follower is a variation of the {fast_envelope_follower}. It is a simple composite class that contains a {fast_ave_envelope_follower} member.

image:rms.svg[alt="RMS", width=300, role=right]The signal path is as follows:

1. Square the signal.
2. Apply the fast averaging envelope follower. The moving average filter in the fast averaging envelope follower returns the arithmetic mean of the squared values over its `hold` period.
3. Return the square root the result.

This is embodied in the `fast_rms_envelope_follower` class. Following the fast envelope follower API, the function call operator accepts a floating point sample, transforms it, and returns an envelope, also a floating point.

The `fast_rms_envelope_follower_db` variant works in the dB domain, making it easy to use as an envelope follower for dynamic range effects (compressor, expander, and agc) that already work in the dB domain, so we eliminate a linear to decibel conversion and optimize computation by using division by 2 instead of `sqrt` as an added bonus.

== Response

The plot in Figure 1 below shows the fast RMS envelope follower’s response (envelope: green, signal: blue, absolute value of the signal: dark blue). It may look indistinguishable from the {fast_ave_envelope_follower}'s output, but this detector returns true RMS results.

image::fast-rms-envelope-follower-output.png[alt="Fast RMS envelope follower response", width=750px, align=center, title="Fast RMS envelope follower response", link={imagesdir}/fast-rms-envelope-follower-output.png]

== Include

```c++
#include <q/fx/envelope.hpp>
```

== Declaration

```c++
struct fast_rms_envelope_follower
{
            fast_rms_envelope_follower(duration hold, float sps);
    float   operator()(float s);
};

struct fast_rms_envelope_follower_db : fast_rms_envelope_follower
{
    using fast_rms_envelope_follower::fast_rms_envelope_follower;

    decibel operator()(float s);
};
```

`fast_rms_envelope_follower` essentially follows the same API as {fast_envelope_follower}. The `fast_rms_envelope_follower_db` variant works in the dB domain and returns `decibel` instead of `float`.

== Expressions

=== Notation

`env_t`             :: A `fast_rms_envelope_follower` or `fast_rms_envelope_follower_db`.
`env`, `a`, `b`     :: Objects of type `fast_rms_envelope_follower` or `fast_rms_envelope_follower_db`.
`hold`              :: Object of type `duration`
`sps`               :: Floating point value for samples per second.
`s`                 :: Floating point value for the latest input sample.

=== Constructors and Assignment

[cols="1,1"]
|===
| Expression            | Semantics

| `env_t(hold, sps)`    | Construct a `basic_fast_ave_envelope_follower<div>` given `hold` (hold duration) and `sps` (samples per second).
| `env_t(env)`          | Copy construct from `basic_fast_ave_envelope_follower<div> env`.
| `a = b`               | Assign `b` to `a`.
|===

NOTE: C++ brace initialization may also be used.

`env_t` is just a shortcut notation for any type or alias to a template instantiation of `fast_rms_envelope_follower` or `fast_rms_envelope_follower_db`.

=== Function Call

[cols="1,1,1"]
|===
| Expression        | Semantics                             | Return Type

| `env(s)`          | Process the input sample `s` and
                      return the detected envelope.         | `float`
| `env()`           | Get the latest held value of the
                      `basic_fast_ave_envelope_follower<div>`   | `float`
|===





