`gaborator.h`

`class gaborator::parameters`

A `parameters`

object holds a set
of spectrum analysis parameters.

gaborator::parameters::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 6 to 384 (inclusive) are supported. Values outside this range may not work, or may cause degraded performance.
`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 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 operators are provided for compatibility with standard container classes. The ordering is arbitrary but consistent.

bool gaborator::parameters::operator<(const gaborator::parameters &rhs) const bool gaborator::parameters::operator==(const gaborator::parameters &rhs) const

`template<class T> class gaborator::coefs`

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 as they are analyzed by calling
`analyzer::analyze()`

. The template argument `T`

must match that of the `analyzer`

(usually `float`

).

gaborator::coefs::coefs(gaborator::analyzer &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.

`template<class T> class gaborator::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.

gaborator::analyzer::analyzer(const gaborator::parameters ¶ms)

`params`

- The spectrum analysis parameters.

void gaborator::analyzer::analyze(const T *signal, int64_t t0, int64_t t1, gaborator::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 ±10^{8}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 gaborator::analyzer::synthesize(const gaborator::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.

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 f_{min}, and a single *lowpass band* containing the
residual signal from frequencies below f_{min}.
The numbering can be examined using the following methods:

int gaborator::analyzer::bandpass_bands_begin() const

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

int gaborator::analyzer::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 gaborator::analyzer::band_lowpass() const

Return the band number of the lowpass band.

double gaborator::analyzer::band_ff(int band) const

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

double gaborator::analyzer::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 gaborator::analyzer::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.

template <class T, class F> void gaborator::apply(const gaborator::analyzer<T> &a, const gaborator::coefs<T> &c, F f)

Apply the function `f`

to each coefficient in the coefficient set `c`

.

`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 signaturevoid f(std::complex<float> &coef, int band, int64_t t)

`coef`

- A reference to a single complex coefficient. This may be read and optionally modified in-place.
`band`

- The band number of the frequency band the coefficient
`coef`

pertains to. This may be either a bandpass band or the lowpass band. `t`

- The point in time the coefficient
`coef`

pertains to, in samples

template <class T, class F> void gaborator::apply(const gaborator::analyzer<T> &a, const gaborator::coefs<T> &c, F f, int64_t t0, int64_t t1)

As above, but only apply the function `f`

to the coefficients
for points in time *t* that satisfy *t0 <= t < t1*.

templatevoid gaborator::forget_before(const gaborator::analyzer<T> &a, gaborator::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.