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
ff_min
ff_min
falls between the two lowest
frequency bandpass filters.
Values from 0.001 to 0.13 are supported.ff_ref
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
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 callinganalyzer::analyze()
. The template argumentT
must match that of theanalyzer
(usuallyfloat
).Constructor
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 argumentT
is the floating-point type to use for the calculations. This is typicallyfloat
; alternatively,double
can be used for increased accuracy at the expense of speed and memory consumption.Constructor
gaborator::analyzer::analyzer(const gaborator::parameters ¶ms)
params
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
t0
,
and numbering t1 - t0
in all.
t0
signal[0]
was taken,
in samples. By convention, this is 0 for the first sample in
the audio track, 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
signal
,
in samples.
coefs
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 parts, by making multiple calls
to analyze()
with non-overlapping ranges that together
cover the entire signal. For efficiency, the ranges should preferably
be large and aligned on multiples of a large powers of two, 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
t0
analyze()
.t0
signal
t0
,
and numbering t1 - t0
in all.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.
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 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.
int 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 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-side worst-cased 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
c
c
f
c
,
with the call signature
void f(std::complex<float> &coef, int band, int64_t t)
coef
band
coef
pertains to.
This may be either a bandpass band or the lowpass band.t
coef
pertains to, in samplestemplate <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.