= decibel

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

== Overview

:db-amplitude: image:db-amplitude-graph.png[alt="440Hz Phase Increments", width=450, role=right]

{db-amplitude}The decibel (dB) is a unit used to measure the relative signal level difference between two signals. It is a logarithmic scale that expresses the relationship between two signal root-power amplitudes or power levels. Here, we are concerned with amplitudes.

For amplitudes gain, the relationship is given by:

```
20 log10(out/in) = dB
```

where `out` represents the output amplitude, while in represents the `input` amplitude.

The decibel scale is expressed as the base 10 logarithm of the ratio between two amplitudes. For instance, a ratio of 2:1 (two times) corresponds to a 6 dB increase, while a ratio of 10:1 (ten times) corresponds to a 20 dB increase. In contrast, a ratio of 1:2 (one half) corresponds to a -6 dB decrease, whereas a ratio of 1:10 (one tenth) corresponds to a -20 dB decrease.

Decibel is non-linear and operates on the logarithmic domain. The `decibel` class is perfectly suitable for dynamics processing (e.g. compressors and limiters and envelopes). Q provides fast `decibel` computations using fast math functions and lookup tables for converting to and from scalars.

== Include

```c++
#include <q/support/decibel.hpp>
```

== Declaration

```c++
struct decibel_unit;

struct decibel : _unspecified_base_type_
{
   using base_type = _unspecified_base_type_;
   using base_type::base_type;
   using unit_type = decibel_unit;
};

// Free functions
double               lin_double(decibel db);
constexpr float      lin_float(decibel db);
inline decibel       approx_db(float val);
decibel              lin_to_db(double val);

// Literals
inline namespace literals
{
   constexpr decibel operator "" _dB(unsigned long long int val);
   constexpr decibel operator "" _dB(long double val);
}
```

== Expressions

`decibel` is a model of `{Unit}`. In addition to valid expressions for `{Unit}`, `decibel` allows these expressions.

=== Notation

`d`      :: Object of type `decibel`.
`v`      :: Linear floating point value.
`0.0`    :: A floating point literal number.
`0`      :: An integer literal number.

=== Constructor

Take note that the `{Unit}` concept already has a constructor from a floating point value that handles direct construction such as:

```c++
auto db = decibel{6.0}; // 6 dB
```

WARNING: This constructor was used in previous versions of the library to convert linear to decibels, which can be confusing. This version ought to have corrected this nonintuitive semantics, but this is a disruptive change that will alter the semantics of all existing code without warning. In order to avoid further confusion, we will mark this constructor as deleted for the time being, making it a hard error to alert users upgrading to this library version.

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

=== Conversions

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

| `lin_float(d)`     | Convert `decibel` to a linear value.       | `float`
| `lin_double(d)`    | Convert `decibel` to a linear value.       | `double`
| `lin_to_db(v)`     | Convert a linear value `v` to `decibel`.   | `decibel`
| `approx_db(v)`     | Faster approximate conversion from
                       a linear value `v` to `decibel`.           | `decibel`
|===

The free function `lin_to_db` can be used to indirectly construct and return a `decibel` object from a linear value. The `lin_to_db` function performs linear to `decibel` conversion. Example:

```c+
auto db = lin_to_db(2.0);  // 6 dB
```

In addition to `lin_to_db`, `approx_db` is another free function that performs linear to `decibel` conversion. It is a faster, but less accurate conversion function from a linear value to `decibel`.

`lin_float` and `lin_double` convert `decibel` to a linear value with `float` and `double` results, respectively.

=== Literals

If you need to create `decibel` from numeric constants, it is preferrable to use `decibel` literals instead. Example:

```c++
auto db = -6_dB;
```

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

| `0.0_dB`        | Returns 0.0 dB.
| `0_dB`          | Returns 0.0 dB.
|===

Take note that `0.0` and `0` stand for any floating point, and integer numeric literals.

TIP: Unless you have a conflicting usage for the *`_dB`* literal, it is generally safe to bring its namespace into scope using the *`using namespace cycfi::q::literals`* directive anywhere in a cpp file.

