Release 1.1

This commit is contained in:
DataHoarder 2018-02-05 19:18:27 +00:00
parent cb436b036b
commit 5a7e4f133e
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
4 changed files with 332 additions and 13 deletions

11
CHANGES Normal file
View file

@ -0,0 +1,11 @@
1.1
Added CHANGES file.
Added reference documentation.
New include file gaborator/version.h.
1.0
Initial release

View file

@ -21,7 +21,8 @@ Velasco, Holighaus, Dörfler, and Grill, described in the papers
<i><a href="http://www.univie.ac.at/nonstatgab/pdf_files/dohogrve11_amsart.pdf">
Constructing an invertible constant-Q transform with nonstationary Gabor frames, 2011</a></i>
and <i><a href="http://www.univie.ac.at/nonstatgab/pdf_files/dogrhove12_amsart.pdf">
A Framework for invertible, real-time constant-Q transforms, 2012</a></i>.
A Framework for invertible, real-time constant-Q transforms, 2012</a></i>,
using Gaussian bandpass filters and an efficient multi-rate architecture.
</p>
<p>The Gaborator is written in C++11 and runs on POSIX systems such as
@ -33,11 +34,13 @@ License, version 3, and is also available for commercial licensing.
See the file <a href="LICENSE">LICENSE</a> for details.</p>
<h2>Release Notes</h2>
<p>This is the first public release of the Gaborator library. It
includes the core spectrum analysis, resynthesis, and spectrogram
rendering code, and some examples of how to use it.</p>
<p>Some features that have been implemented but are not yet ready for
<p>This is still an early release, and API changes are expected.</p>
<p>The distribution includes the core spectrum analysis, resynthesis, and
spectrogram rendering code, along with some example code and
reference documentation.
Some features that have been implemented but are not yet ready for
release have been omitted, for example the support for parallel
analysis and synthesis using multiple CPU cores. Also, the current API
still lacks functions for convenient row- or column-wise access to
@ -46,17 +49,11 @@ access the coefficients is the apply() method, which iterates over
the entire coefficient set in an indeterminate order.
</p>
<p>This initial release also still lacks reference documentation
formally defining the public library API. Until such documentation is
released, only the functions used in the example code should be
considered part of the API. All other functions are subject to change
or removal without notice.</p>
<h2>Example Code</h2>
<p>The following examples demonstrate the use of the library for a
couple of different applications. They are presented in a "literate
programming" style, with the code embedded in the explanatory
text rather than the other way around.
programming" style, with the code embedded in the commentary
rather than the other way around.
Concatenating the code fragments in each example yields a complete C++
program, which can also be found as a <code>.cc</code> file in
the <code>examples/</code> directory.</p>
@ -65,6 +62,16 @@ the <code>examples/</code> directory.</p>
<li><a href="filter.html">Example 2: Frequency-Domain Filtering</a></li>
</ul>
<h2>Reference Documentation</h2>
<p>The following documents define the public library API.
Any classes and functions not listed here
should be considered private and are subject to change or
deletion without notice.</p>
<ul>
<li><a href="ref/gaborator_h.html">Spectrum analysis and synthesis: <code>gaborator.h</code></a></li>
<li><a href="ref/render_h.html">Spectrogram rendering: <code>render.h</code></a></li>
</ul>
<h2>Contact</h2>
<p>For more information, email the author at info@gaborator.com.</p>

229
doc/ref/gaborator_h.html Normal file
View file

@ -0,0 +1,229 @@
<!DOCTYPE html>
<!--
Copyright (C) 2018 Andreas Gustafsson. This file is part of
the Gaborator library source distribution. See the file LICENSE at
the top level of the distribution for license information.
-->
<html>
<head>
<link rel="stylesheet" href="../doc.css" type="text/css" />
<title>Gaborator reference: gaborator.h</title>
</head>
<body>
<h1>Gaborator reference: <code>gaborator.h</code></h1>
<h2><code>class gaborator::parameters</code></h2>
<p>A <code>parameters</code> object holds a set
of spectrum analysis parameters.</p>
<h3>Constructor</h3>
<pre>
gaborator::parameters::parameters(unsigned int bands_per_octave,
double ff_min,
double ff_ref = 1.0)
</pre>
<dl>
<dt><code>bands_per_octave</code></dt>
<dd>The number of frequency bands per octave.
Values from 6 to 192 (inclusive) are supported. Values outside
this range may not work, or may cause degraded performance.</dd>
<dt><code>ff_min</code></dt>
<dd>The lower limit of the analysis frequency range, in units of the
sample rate. The analysis filter bank will have no bandpass filters
with a center frequency lower than <code>ff_min</code>.
Values from 0.001 to 0.13 are supported.</dd>
<dt><code>ff_ref</code></dt>
<dd>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 <code>ff_ref</code>. If <code>ff_ref</code>
falls outside the frequency range of the filter bank, this
works as if the range were extended to include
<code>ff_ref</code>. Must be positive. A typical value
when analyzing music is <code>440.0 / fs</code>, where <code>fs</code>
is the sample rate.
</dd>
</dl>
<h3>Comparison</h3>
<p>
Comparison operators are provided for compatibility with
standard container classes. The ordering is arbitrary but consistent.
</p>
<pre>
bool gaborator::parameters::operator<(const gaborator::parameters &amp;rhs) const
bool gaborator::parameters::operator==(const gaborator::parameters &amp;rhs) const
</pre>
<h2><code>template&lt;class T&gt; class gaborator::coefs</code></h2>
<p>
A <code>coefs</code> 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
<code>analyzer::analyze()</code>. The template argument <code>T</code>
must match that of the <code>analyzer</code> (usually <code>float</code>).
</p>
<h3>Constructor</h3>
<pre>
gaborator::coefs::coefs(gaborator::analyzer &amp;a)
</pre>
<p>
Construct an empty set of coefficients for use with the spectrum
analyzer <code>a</code>. This represents a signal that is zero
at all points in time.
</p>
<h2><code>template&lt;class T&gt; class gaborator::analyzer</code></h2>
<p>
The <code>analyzer</code> object performs spectrum analysis and/or resynthesis
according to the given parameters. The template argument <code>T</code> is
the floating-point type to use for the calculations. This is typically <code>float</code>;
alternatively, <code>double</code> can be used for increased accuracy at the
expense of speed and memory consumption.</p>
<h3>Constructor</h3>
<pre>
gaborator::analyzer::analyzer(const gaborator::parameters &amp;params)
</pre>
<dl>
<dt><code>params</code></dt>
<dd>The spectrum analysis parameters.
</dl>
<h3>Analysis and synthesis</h3>
<pre>
void
gaborator::analyzer::analyze(const T *signal,
int64_t t0,
int64_t t1,
gaborator::coefs&lt;T&gt; &amp;coefs)
</pre>
<p>Spectrum analyze the samples at <code>*signal</code> and add the
resulting coefficients to <code>coefs</code>.
<dl>
<dt><code>signal</code></dt>
<dd>The signal samples to analyze, beginning with the sample from time <code>t0</code>,
and numbering <code>t1 - t0</code> in all.
<dt><code>t0</code></dt>
<dd>The point in time when the sample at <code>signal[0]</code> 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 &plusmn;10<sup>8</sup> samples, so using
large time values should be avoided when they are not necessary because
of the length of the track.
</dd>
<dt><code>t1</code></dt>
<dd>The point in time of the sample one past the
end of the array of samples at <code>signal</code>,
in samples.
</dd>
<dt><code>coefs</code></dt><dd>The coefficient object that the results of the
spectrum analysis are added to.
</dl>
<p>If the <code>coefs</code> 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 <code>analyze()</code> 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
<code>analyze(first_131072_samples, 0, 131072, coefs)</code>,
<code>analyze(next_131072_samples, 131072, 262144, coefs)</code>,
etc.
</p>
<pre>
void
gaborator::analyzer::synthesize(const gaborator::coefs&lt;T&gt; &amp;coefs,
uint64_t t0,
uint64_t t1,
T *signal)
</pre>
<p>Synthesize signal samples from the coefficients <code>coef</code> and store
them at <code>*signal</code>.
</p>
<dl>
<dt><code>coefs</code></dt><dd>The coefficients to synthesize the signal from.</dd>
<dt><code>t0</code></dt>
<dd>The point in time of the first sample to synthesize,
in samples, using the same time scale as in <code>analyze()</code>.</dd>
<dt><code>t0</code></dt>
<dd>The point in time of the sample one past the last one to synthesize.</dd>
<dt><code>signal</code></dt>
<dd>The synthesized signal samples will be written here,
beginning with the sample from time <code>t0</code>,
and numbering <code>t1 - t0</code> in all.</dd>
</dl>
<p>The time range <code>t0</code>...<code>t1</code>
may extend outside the range analyzed using <code>analyze()</code>,
in which case the signal is assumed to be zero in the un-analyzed range.</p>
<h3>Frequency Band Numbering</h3>
<p>The frequency bands of the analysis filter bank are numbered by
nonnegative integers that increase towards lower (sic) frequencies.
There is a number of <i>bandpass bands</i> corresponding to the
logarithmically spaced bandpass analysis filters, from near f<sub>s</sub>/2 to
near <code>fmin</code>, and a single <i>lowpass band</i> containing the
residual signal from frequencies below <code>fmin</code>.
The numbering can be examined using the following methods:
</p>
<pre>
int gaborator::analyzer::bandpass_bands_begin()
</pre>
<p>
Return the smallest valid bandpass band number, corresponding to the highest-frequency
bandpass filter.</p>
<pre>
int gaborator::analyzer::bandpass_bands_end()
</pre>
<p>
Return the bandpass band number one past the highest valid bandpass band number,
corresponding to one past the lowest-frequency bandpass filter.</p>
<pre>
int gaborator::analyzer::band_lowpass()
</pre>
<p>
Return the band number of the lowpass band.</p>
<h3>Iterating Over the Coefficients</h3>
<pre>
template &lt;class T, class F&gt;
void gaborator::apply(const gaborator::analyzer&lt;T&gt; &amp;a,
const gaborator::coefs&lt;T&gt; &amp;c,
F f)
</pre>
<p>
Apply the function <code>f</code> to each coefficient in the coefficient set <code>c</code>.
</p>
<dl>
<dt><code>a</code></dt>
<dd>The spectrum analyzer that produced the coefficients <code>c</code></dd>
<dt><code>c</code></dt>
<dd>A set of spectrogram coefficients</dd>
<dt><code>f</code></dt>
<dd>A function to apply to each coefficient in <code>c</code></dd>
</dl>
<p>The function <code>f</code> should have the following signature:
<pre>
void f(std::complex&lt;float&gt; &amp;coef, int band, int64_t t)
</pre>
<dl>
<dt><code>coef</code></dt>
<dd>A reference to a single complex coefficient. This may be read and
optionally modified in-place.</dd>
<dt><code>band</code></dt>
<dd>The band number of the frequency band the coefficient <code>coef</code> pertains to.
This may correspond to either a bandpass band or the lowpass band.</dd>
<dt><code>t</code></dt>
<dd>The point in time the coefficient <code>coef</code> pertains to, in samples</dd>
</dl>
</body>
</html>

72
doc/ref/render_h.html Normal file
View file

@ -0,0 +1,72 @@
<!DOCTYPE html>
<!--
Copyright (C) 2018 Andreas Gustafsson. This file is part of
the Gaborator library source distribution. See the file LICENSE at
the top level of the distribution for license information.
-->
<html>
<head>
<link rel="stylesheet" href="../doc.css" type="text/css" />
<title>Gaborator reference: render.h</title>
</head>
<body>
<h1>Gaborator reference: <code>render.h</code></h1>
<h3>Spectrogram Rendering with Power-of-Two Scaling</h3>
<pre>
template &lt;class OI, class T&gt;
void render_p2scale(const analyzer&lt;T&gt; &amp;a,
const coefs&lt;T&gt; &amp;c,
int64_t xorigin, int64_t yorigin,
int64_t xi0, int64_t xi1, int xe,
int64_t yi0, int64_t yi1, int ye,
OI output)
</pre>
<p>Render a rectangular array of pixel values representing signal
signal amplitudes in time-frequency space, optionally scaling up or
down by powers of two.
</p>
<dl>
<dt><code>a</code></dt>
<dd>The spectrum analyzer that produced the coefficients <code>c</code></dd>
<dt><code>c</code></dt>
<dd>A set of spectrogram coefficients to render</dd>
<dt><code>xorigin</code></dt>
<dd>The point in time corresponding to pixel X coordinate 0, in samples</dd>
<dt><code>yorigin</code></dt>
<dd>The band number of the frequency band corresponding to pixel Y coordinate 0</dd>
<dt><code>xi0</code></dt>
<dd>The X coordinate of the first pixel to render</dd>
<dt><code>xi1</code></dt>
<dd>The X coordinate one past the last pixel to render</dd>
<dt><code>xe</code></dt>
<dd>The horizontal scaling exponent. One horizontal pixel corresponds to 2<sup>xe</sup> signal samples.</dd>
<dt><code>yi0</code></dt>
<dd>The Y coordinate of the first pixel to render</dd>
<dt><code>yi1</code></dt>
<dd>The Y coordinate one past the last pixel to render</dd>
<dt><code>ye</code></dt>
<dd>The vertical scaling exponent. One vertical pixel corresponds to 2<sup>ye</sup> frequency bands.</dd>
<dt><code>output</code></dt>
<dd>A random access iterator through which the output
pixel amplitude values will be written. This is
typically a <code>float *</code>. A total of
<code>(xi1 - xi0) * (yi1 - yi0))</code> values will be written.
</dd>
</dl>
<h3>Utility Functions</h3>
<pre>
template &lt;class T&gt;
unsigned int float2pixel_8bit(T amp)
</pre>
<p>Convert a normalized amplitude value to a 8-bit greyscale pixel value.</p>
<dl>
<dt><code>amp</code></dt>
<dd>A floating point value representing a signal amplitude, nominally ranging from 0 to 1</dd>
</dl>
<p>Returns an pixel value ranging from 0 to 255 (inclusive), nominally
using the sRGB gamma.</p>
</body>
</html>