# Gaborator reference: `gaborator.h`

## Spectrum Analysis Parameters

A `parameters` object holds a set of parameters that determine the frequency range and resolution of the spectrum analysis.

    class parameters {

### Constructor

    parameters(unsigned int bands_per_octave,
               double ff_min,
               double ff_ref = 1.0);

`bands_per_octave`
  The number of frequency bands per octave. Values from 4 to 384 (inclusive) are supported.
`ff_min`
  The lower limit of the analysis frequency range, in units of the sample rate. The analysis filter bank will extend low enough in frequency that `ff_min` falls between the two lowest frequency bandpass filters. Values from 0.001 to 0.13 are supported.
`ff_ref`
  The reference frequency, in units of the sample rate. This allows fine-tuning of the analysis and synthesis filter banks such that the center frequency of one of the filters is aligned with `ff_ref`. If `ff_ref` falls outside the frequency range of the bandpass filter bank, this works as if the range were extended to include `ff_ref`. Must be positive. A typical value when analyzing music is `440.0 / fs`, where `fs` is the sample rate in Hz.

### Comparison

Comparison operators are provided for compatibility with standard container classes. The ordering is arbitrary but consistent.

    bool operator<(const parameters &rhs) const;
    bool operator==(const parameters &rhs) const;

    };

## Spectrogram Coefficients

    template<class T> class analyzer;

A `coefs` object stores a set of spectrogram coefficients. It is a dynamic data structure and will be automatically grown to accommodate new time ranges, for example as newly recorded audio is analyzed. The template argument `T` must match that of the `analyzer` (usually `float`). The template argument `C` is the data type used to store each coefficient value; there is usually no need to specify it explicitly as it will default to `std::complex<T>`.

    template<class T, class C = std::complex<T>>
    class coefs {

### Constructor

    coefs(analyzer<T> &a);

Construct an empty set of coefficients for use with the spectrum analyzer `a`. This represents a signal that is zero at all points in time.

    };

## Spectrum Analyzer

The `analyzer` object performs spectrum analysis and/or resynthesis according to the given parameters. The template argument `T` is the floating-point type to use for the calculations. This is typically `float`; alternatively, `double` can be used for increased accuracy at the expense of speed and memory consumption.

    template<class T>
    class analyzer {

### Constructor

    analyzer(const parameters &params);

`params`
  The spectrum analysis parameters.

### Analysis and synthesis

    void
    analyze(const T *signal,
            int64_t t0,
            int64_t t1,
            coefs<T> &coefs) const;

Spectrum analyze the samples at `*signal` and add the resulting coefficients to `coefs`.

`signal`
  The signal samples to analyze, beginning with the sample from time `t0` and ending with the last sample before time `t1`, for a total of `t1 - t0` samples.
`t0`
  The point in time when the sample at `signal[0]` was taken, in samples. For example, when analyzing an audio recording, this is typically 0 for the first sample in the recording, but this reference point is arbitrary, and negative times are valid. Accuracy begins to successively decrease outside the range of about ±108 samples, so using large time values should be avoided when they are not necessary because of the length of the track.
`t1`
  The point in time of the sample one past the end of the array of samples at `signal`, in samples.
`coefs`
  The coefficient object that the results of the spectrum analysis are added to.

If the `coefs` object already contains some coefficients, the new coefficients are summed to those already present. Because the analysis is a linear operation, this allows a signal to be analyzed in blocks, by making multiple calls to `analyze()` with non-overlapping ranges that together cover the entire signal. For efficiency, the blocks should be large, as in `analyze(first_131072_samples, 0, 131072, coefs)`, `analyze(next_131072_samples, 131072, 262144, coefs)`, etc.

    void
    synthesize(const coefs<T> &coefs,
               uint64_t t0,
               uint64_t t1,
               T *signal) const;

Synthesize signal samples from the coefficients `coef` and store them at `*signal`.

`coefs`
  The coefficients to synthesize the signal from.
`t0`
  The point in time of the first sample to synthesize, in samples, using the same time scale as in `analyze()`.
`t1`
  The point in time of the sample one past the last one to synthesize.
`signal`
  The synthesized signal samples will be written here, beginning with the sample from time `t0` and and ending with the last sample before time `t1`, for a total of `t1 - t0` samples.

The time range `t0`...`t1` may extend outside the range analyzed using `analyze()`, in which case the signal is assumed to be zero in the un-analyzed range.

A signal may be synthesized in blocks by making multiple calls to `analyze()` with different sample ranges. For efficiency, the blocks should be large, and each `t0` should be multiple of a large power of two.

### Frequency Band Numbering

The frequency bands of the analysis filter bank are numbered by nonnegative integers that increase towards lower (sic) frequencies. There is a number of bandpass bands corresponding to the logarithmically spaced bandpass analysis filters, from near 0.5 (half the sample rate) to near fmin, and a single lowpass band containing the residual signal from frequencies below fmin. The numbering can be examined using the following methods:

    int bandpass_bands_begin() const;

Return the smallest valid bandpass band number, corresponding to the highest-frequency bandpass filter.

    int bandpass_bands_end() const;

Return the bandpass band number one past the highest valid bandpass band number, corresponding to one past the lowest-frequency bandpass filter.

    int band_lowpass() const;

Return the band number of the lowpass band.

    int band_ref() const;

Return the band number corresponding to the reference frequency `ff_ref`. If `ff_ref` falls within the frequency range of the bandpass filter bank, this will be a valid bandpass band number, otherwise it will not.

    double band_ff(int band) const;

Return the center frequency of band number band, in units of the sampling frequency.

### Support

    double analysis_support() const;

Returns the one-sided worst-case time domain support of any of the analysis filters. When calling `analyze()` with a sample at time t, only spectrogram coefficients within the time range t ± support will be significantly changed. Coefficients outside the range may change, but the changes will sufficiently small that they may be ignored without significantly reducing accuracy.

    double synthesis_support() const;

Returns the one-sided worst-case time domain support of any of the reconstruction filters. When calling `synthesize()` to synthesize a sample at time t, the sample will only be significantly affected by spectrogram coefficients in the time range t ± support. Coefficients outside the range may be used in the synthesis, but substituting zeroes for the actual coefficient values will not significantly reduce accuracy.

    };

## Functions

### Iterating Over Existing Coefficients

    template <class T, class F, class C0, class... CI>
    void process(F f,
                 int b0,
                 int b1,
                 int64_t t0,
                 int64_t t1,
                 coefs<T, C0> &coefs0,
                 coefs<T, CI>&... coefsi);

Process one or more coefficient sets `coefs0`... by applying the function `f` to each coefficient present in `coefs0`, in an indeterminate order.

This can be optionally limited to coefficients whose band number b and sample time t satisfy `b0` ≤ b < `b1` and `t0` ≤ t < `t1`. To process every coefficient present in `coefs0`, pass `INT_MIN, INT_MAX, INT64_MIN, INT64_MAX` for the arguments `b0`, `b1`, `t0`, and `t1`, respectively.

The function `f` should have the call signature

      template<class T>
      void f(int b, int64_t t, std::complex<T> &c0, std::complex<T> &ci...);

  where

  `b`
    The band number of the frequency band the coefficients `c0` and `ci...` pertain to. This may be either a bandpass band or the lowpass band.
  `t`
    The point in time the coefficients `c0` and `ci...` pertain to, in samples
  `c0`
    A reference to a complex coefficient from `coefs0`
  `ci...`
    Optional references to complex coefficients from the additional coefficient sets `coefsi...`.

The function `f` may read and/or modify each of the coefficients passed through `c0` and each `ci...`.

The first coefficient set `c0` is a special case when it comes to the treatment of missing values. Coefficients missing from `c0` will not be iterated over at all, but when a coefficient is iterated over and is missing from one of the additional coefficient sets `ci...`, it will be automatically created and initialized to zero in that additional coefficient set.

Note: The template parameters `C0` and `CI`... exist to support the processing of coefficient sets containing data of types other than `std::complex<T>`, which is not currently part of the documented API. In typical use, there is no need to specify them when calling `apply()` because the template parameter list can be deduced, but if they are expicitly specified, they should all be `std::complex<T>`.

### Creating New Coefficients

    template <class T, class F, class C0, class... CI>
    void fill(F f,
              int b0,
              int b1,
              int64_t t0,
              int64_t t1,
              coefs<T, C0> &coefs0,
              coefs<T, CI>&... coefsi);

Fill a region of the time-frequency plane with coefficients and apply the function `f` to each.

This works like `process()` except that it is not limited to processing coefficients that already exist in `coefs0`; instead, any missing coefficients in `coefs0` as well as any of the `coefsi`... are created and initialized to zero before `f` is called.

The `t0` and `t1` arguments must specify an explicit, bounded time range — they must not be given as INT64_MIN and/or INT64_MAX as that would mean creating coefficients for an an astronomically large time range, requiring a correspondingly astronomical amount of memory.

### Forgetting Coefficients

    template <class T>
    void forget_before(const analyzer<T> &a,
                       coefs<T> &c,
                       int64_t limit);

Allow the coefficients for points in time before `limit` (a time in units of samples) to be forgotten. Streaming applications can use this to free memory used by coefficients that are no longer needed. Coefficients that have been forgotten will read as zero. This does not guarantee that all coefficients before `limit` are forgotten, only that ones for `limit` or later are not, and that the amount of memory consumed by any remaining coefficients before `limit` is bounded.

### Legacy API For Iterating Over Existing Coefficients

Prior to version 1.5, the only way to iterate over coefficients was the `apply()` function. It is similar to `process()`, except that it

- requires an additional `analyzer` argument,
- takes arguments in a different order,
- applies a function `f` taking arguments in a different order,
- does not support restricting the processing to a range of band numbers,
- only supports iterating over a single coefficient set, and
- provides default values for t0 and t1.

In new code, `process()` is preferred.

    template <class T, class F>
    void apply(const analyzer<T> &a,
               coefs<T> &c,
               F f,
               int64_t t0 = INT64_MIN,
               int64_t t1 = INT64_MAX);

Apply the function `f` to each coefficient in the coefficient set `c` for points in time t that satisfy `t0` ≤ t < `t1`. If the `t0` and `t1` arguments are omitted, `f` is applied to every coefficient.

`a`
  The spectrum analyzer that produced the coefficients `c`
`c`
  A set of spectrogram coefficients
`f`
  A function to apply to each coefficient in `c`, with the call signature

      template<class T>
      void f(std::complex<T> &coef, int band, int64_t t);

  `coef`
    A reference to a single complex coefficient. This may be read and/or modified.
  `band`
    The band number of the frequency band the coefficient `coef0` pertains to. This may be either a bandpass band or the lowpass band.
  `t`
    The point in time the coefficient `c0` pertains to, in samples
  `t0`
    When not `INT64_MIN`, only apply `f` to the coefficients for time ≥ `t0`
  `t1`
    When not `INT64_MAX`, only apply `f` to the coefficients for time < `t1`