This commit is contained in:
Steven Dan
2025-12-11 09:43:42 +08:00
commit d8b2974133
1822 changed files with 280037 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
.. raw:: latex
\newpage
.. _api_reference_section:
API Reference
#############
This section provides a comprehensive guide to the DSP components, their integration into the DSP pipeline, and the run-time control mechanisms.
It also includes an overview of high-level pipeline design principles.
.. toctree::
:maxdepth: 1
stages/index
modules/index
integration/index
pipeline_design

View File

@@ -0,0 +1,7 @@
.. _dsp_control:
#######
Control
#######
.. doxygenfile:: adsp_control.h

View File

@@ -0,0 +1,60 @@
.. _run_time_control_helper_section:
========================
Control Helper Functions
========================
Most DSP Stages have fixed point control parameters. To aid conversion
from typical tuning units (e.g. decibels) to the correct fixed point
format, the helper functions below have been provided.
.. _biquad_helpers:
Biquad helpers
==============
.. doxygenfile:: control/biquad.h
DRC helpers
===========
.. doxygenfunction:: calc_alpha
.. doxygenfunction:: calculate_peak_threshold
.. doxygenfunction:: calculate_rms_threshold
.. doxygenfunction:: rms_compressor_slope_from_ratio
.. doxygenfunction:: peak_expander_slope_from_ratio
.. doxygenfunction:: qxx_to_db
.. doxygenfunction:: qxx_to_db_pow
.. doxygenfile:: control/drc.h
Graphic EQ helpers
==================
.. doxygenfunction:: adsp_graphic_eq_10b_init
.. doxygenfunction:: geq_db_to_gain
Reverb helpers
==============
.. doxygenfile:: control/reverb.h
.. doxygenfile:: control/reverb_plate.h
Signal chain helpers
====================
.. doxygenfile:: control/signal_chain.h

View File

@@ -0,0 +1,15 @@
.. _dsp_integration_control:
Integration and Control
========================
This section covers the API necessary to integrate the generated DSP pipeline into your application, both data and control-wise.
It will introduce the API necessary for converting from high-level DSP parameters, to the ones that can be sent to the DSP pipeline.
.. toctree::
:maxdepth: 1
pipeline
module
control
helpers

View File

@@ -0,0 +1,5 @@
######
Module
######
.. doxygenfile:: adsp_module.h

View File

@@ -0,0 +1,5 @@
########
Pipeline
########
.. doxygenfile:: adsp_pipeline.h

View File

@@ -0,0 +1,169 @@
.. _biquad_filters:
##############
Biquad Filters
##############
.. _Biquad:
=============
Single Biquad
=============
A second order biquadratic filter, which can be used to implement many common second order filters.
The filter had been implemented in the direct form 1, and uses the xcore.ai vector unit to
calculate the 5 filter taps in a single instruction.
Coefficients are stored in Q1.30 format to benefit from the vector unit, allowing for a filter
coefficient range of ``[-2, 1.999]``. For some high gain biquads (e.g. high shelf filters), the
numerator coefficients may exceed this range. If this is the case, the numerator coefficients only
should be right-shifted until they fit within the range (the denominator coefficients cannot become
larger than 2.0 without the poles exceeding the unit circle). The shift should be passed into the API,
and the output signal from the biquad will then have a left-shift applied. This is equivalent to
reducing the overall signal level in the biquad, then returning to unity gain afterwards.
The ``state`` should be initialised to ``0``. The ``state`` and ``coeffs`` must be word-aligned.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_biquad
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.biquad.biquad
:noindex:
.. automethod:: process
:noindex:
.. automethod:: update_coeffs
:noindex:
.. automethod:: reset_state
:noindex:
.. _BiquadSlew:
=====================
Single Slewing Biquad
=====================
This is similar to `Biquad`_, but when the target coefficients are updated it slew the applied
coefficients towards the new values. This can be used for real time adjustable filter control.
If the left-shift of the coefficients changes, this is managed by the ``biquad_slew_t`` object:
.. doxygenstruct:: biquad_slew_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
Filtering the samples can be carried out using ``adsp_biquad``:
.. code-block:: C
for (int j=0; i < n_samples; i++){
adsp_biquad_slew_coeffs(&slew_state, states, 1);
for (int i=0; i < n_chans; i++){
samp_out[i, j] = adsp_biquad(samp_in[i, j], slew_state.active_coeffs, states[i], slew_state.lsh);
}
}
.. doxygenfunction:: adsp_biquad_slew_coeffs
See also :c:func:`adsp_biquad_slew_init` and :c:func:`adsp_biquad_slew_update_coeffs`.
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.biquad.biquad_slew
:noindex:
.. automethod:: process
:noindex:
.. automethod:: update_coeffs
:noindex:
.. automethod:: reset_state
:noindex:
.. _CascadedBiquads:
================
Cascaded Biquads
================
The cascaded biquad module is equivalent to 8 individual biquad filters connected in series. It
can be used to implement a simple parametric equaliser or high-order Butterworth filters,
implemented as cascaded second order sections.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_cascaded_biquads_8b
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.cascaded_biquads.cascaded_biquads_8
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _CascadedBiquads16:
===================
Cascaded Biquads 16
===================
This extends the CascadedBiquads class to have 16 cascaded filters. However,
The 8 filter C implementation should still be used.
.. tab:: C API
See :ref:`CascadedBiquads`.
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.cascaded_biquads.cascaded_biquads_16
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:

View File

@@ -0,0 +1,497 @@
.. _drc:
#####################
Dynamic Range Control
#####################
Dynamic Range Control (DRC) in audio digital signal processing (DSP) refers to the automatic adjustment of an audio
signal's amplitude to reduce its dynamic range - the difference between the loudest and quietest parts of the audio.
They include compressors, limiters and clippers, as well as the envelope detectors used to detect the signal level.
========================
Attack and Release Times
========================
Nearly all DRC modules feature an attack and release time to control the
responsiveness of the module to changes in signal level. Attack and
release times converted from seconds to alpha coefficients for use in
the the exponential moving average calculation. The shorter the attack or release time, the bigger the alpha. Large
alpha will result in the envelope becoming more reactive to the input samples. Small alpha values will give more
smoothed behaviour. The difference between the input level and the current envelope or gain determines whether the
attack or release alpha is used.
==================
Envelope Detectors
==================
Envelope detectors run an exponential moving average (EMA) of the
incoming signal. They are used as a part of the most DRC components.
They can also be used to implement VU meters and level detectors.
They feature `attack and release times`_ to control the responsiveness
of the envelope detector.
The C struct below is used for all the envelope detector implementations.
.. doxygenstruct:: env_detector_t
:members:
.. _EnvelopeDetectorPeak:
----------------------
Peak Envelope Detector
----------------------
A peak-based envelope detector will run its EMA using the absolute value of the input sample.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_env_detector_peak
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.envelope_detector_peak
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _EnvelopeDetectorRMS:
---------------------
RMS Envelope Detector
---------------------
An RMS-based envelope detector will run its EMA using the square of the
input sample. It returns the mean² in order to avoid a square root.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_env_detector_rms
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.envelope_detector_rms
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _Clipper:
=======
Clipper
=======
A clipper limits the signal to a specified threshold. It is applied
instantaneously, so has no attack or release times.
.. doxygentypedef:: clipper_t
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_clipper
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.clipper
:noindex:
.. automethod:: process
:noindex:
========
Limiters
========
Limiters will reduce the amplitude of a signal when the signal envelope
is greater than the desired threshold. This is similar behaviour to a compressor
with an infinite ratio.
A limiter will run an internal envelope detector to get the signal
envelope, then compare it to the threshold. If the envelope is greater than the
threshold, the applied gain will be reduced. If the envelope is below
the threshold, unity gain will be applied. The gain is run through an EMA
to avoid abrupt changes. The same `attack and release times`_ are used
for the envelope detector and the gain smoothing.
The C struct below is used for all the limiter implementations.
.. doxygenstruct:: limiter_t
:members:
.. _LimiterPeak:
------------
Peak Limiter
------------
A peak limiter uses the :ref:`EnvelopeDetectorPeak` to get an envelope.
When envelope is above the threshold, the new gain is calculated as
``threshold / envelope``.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_limiter_peak
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.limiter_peak
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _HardLimiterPeak:
-----------------
Hard Peak Limiter
-----------------
A hard peak limiter is similar to a :ref:`LimiterPeak`, but will clip
the output if it's still above the threshold after the peak limiter.
This can be useful for a final output limiter before truncating any
headroom bits.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_hard_limiter_peak
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.hard_limiter_peak
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _LimiterRMS:
-----------
RMS Limiter
-----------
A RMS limiter uses the :ref:`EnvelopeDetectorRMS` to calculate an envelope.
When envelope is above the threshold, the new gain is calculated as
``sqrt(threshold / envelope)``.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_limiter_rms
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.limiter_rms
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
===========
Compressors
===========
A compressor will attenuate the signal when the envelope is greater than the
threshold. The input/output relationship above the threshold is defined
by the compressor ``ratio``.
As with a limiter, the compressor runs an internal envelope detector
to get the signal envelope, then compares it to the threshold. If the
envelope is greater than the threshold, the gain will be proportionally reduced
by the ``ratio``, such that it is greater than the threshold by a smaller amount.
If the envelope is below the threshold, unity gain will be applied.
The gain is then run through an EMA to avoid abrupt changes, before being
applied.
The ``ratio`` defines the input/output gradient in the logarithmic domain.
For example, a ratio of 2 will reduce the output gain by 0.5 dB for every
1 dB the envelope is over the threshold.
A ratio of 1 will apply no compression.
To avoid converting the envelope to the logarithmic domain for the gain
calculation, the ratio is converted to the ``slope`` as
``(1 - 1 / ratio) / 2`` . The gain can then be calculated as an
exponential in the linear domain.
The C structs below are used for all the compressors implementations.
.. doxygenstruct:: compressor_t
:members:
.. doxygenstruct:: compressor_stereo_t
:members:
.. _CompressorRMS:
--------------
RMS Compressor
--------------
The RMS compressor uses the :ref:`EnvelopeDetectorRMS` to calculate an
envelope.
When the envelope is above the threshold, the new gain is calculated as
``(threshold / envelope) ^ slope``.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_compressor_rms
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.compressor_rms
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _CompressorSidechain:
------------------------
Sidechain RMS Compressor
------------------------
The sidechain RMS compressor calculates the envelope of one signal and
uses it to compress another signal.
It takes two signals: *detect* and *input*. The envelope of the *detect* signal
is calculated using an internal :ref:`EnvelopeDetectorRMS`.
The gain is calculated in the same way as a :ref:`CompressorRMS`, but the
gain is then applied to the *input* sample.
This can be used to reduce the level of the *input* signal when the
*detect* signal gets above the threshold.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_compressor_rms_sidechain
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.compressor_rms_sidechain_mono
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _CompressorSidechainStereo:
-------------------------------
Stereo Sidechain RMS Compressor
-------------------------------
The stereo sidechain RMS compressor expands the :ref:`CompressorSidechain` to take 2
input and 2 detection channels. The envelope of each detection channel is taken, and
the maximum of the envelopes is used to calculate the compression to apply to the
input channels.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_compressor_rms_sidechain_stereo
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.compressor_rms_sidechain_stereo
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
=========
Expanders
=========
An expander attenuates a signal when the envelope is below the threshold.
This increases the dynamic range of the signal, and can be used to
attenuate quiet signals, such as low level noise.
Like limiters and compressors, an expander will run an internal envelope
detector to calculate the envelope and compare it to the threshold.
If the envelope is below the threshold, the applied gain will be reduced.
If the envelope is greater than the threshold, unity gain will be applied.
The gain is run through an EMA to avoid abrupt changes.
The same `attack and release times`_ are used for the envelope detector
and the gain smoothing. In an expander, the attack time is defined as the
speed at which the gain returns to unity after the signal has been
below the threshold.
.. _NoiseGate:
----------
Noise Gate
----------
A noise gate uses the :ref:`EnvelopeDetectorPeak` to calculate the
envelope of the input signal.
When the envelope is below the threshold, a gain of 0 is applied to
the input signal. Otherwise, unity gain is applied.
.. doxygentypedef:: noise_gate_t
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_noise_gate
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.noise_gate
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. _NoiseSuppressorExpander:
-------------------------
Noise Suppressor/Expander
-------------------------
A basic expander can also be used as a noise suppressor.
It uses the :ref:`EnvelopeDetectorPeak` to calculate the envelope of the
input signal.
When the envelope is below the threshold, the gain of the signal is
reduced according to the ratio. Otherwise, unity gain is applied.
Like a compressor, the ``ratio`` defines the input/output gradient in
the logarithmic domain.
For example, a ratio of 2 will reduce the output gain by 0.5 dB for every
1 dB the envelope is below the threshold.
A ratio of 1 will apply no gain changes.
To avoid converting the envelope to the logarithmic domain for the gain
calculation, the ratio is converted to the ``slope`` as
``(1 - ratio)``. The gain can then be calculated as an
exponential in the linear domain.
For speed, some parameters such as ``inv_threshold`` are computed at
initialisation to simplify run-time computation.
.. doxygenstruct:: noise_suppressor_expander_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_noise_suppressor_expander
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.drc.noise_suppressor_expander
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:

View File

@@ -0,0 +1,139 @@
.. _fir:
###############################
Finite Impulse Response Filters
###############################
Finite impulse response (FIR) filters allow the use of arbitrary filters
with a finite number of taps. This library does not provide FIR filter
design tools, but allows for coefficients to be imported from other design
tools, such as `SciPy/filter_design`_.
.. _FirDirect:
==========
FIR Direct
==========
The direct FIR implements the filter as a convolution in the time domain.
This library uses FIR ``filter_fir_s32`` implementation from ``lib_xcore_math`` to run on xcore.
More information on implementation can be found in `XCORE Math Library`_ documentation.
.. autoclass:: audio_dsp.dsp.fir.fir_direct
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. automethod:: check_coeff_scaling
:noindex:
.. _FirBlockTD:
=====================
Block Time Domain FIR
=====================
The block time domain FIR implements the filter as a convolution in the time domain, but with a block size
optimized for execution on the vector-unit of xcore.ai. The advantage with this one is it is over twice
the efficiency of the lib_xcore_math implementation. This block will generate C code for the block time domain FIR
filter.
More information on implementation can be found in
`AN02027: Efficient computation of FIR filters on the XCORE <https://www.xmos.com/application-notes/>`_.
.. note::
The block time domain FIR filter is not currently implemented as a DSP Stage, so cannot be
used with the DSP pipeline tool yet.
.. tab:: Autogenerator
.. only:: latex
.. rubric:: Autogenerator
.. autofunction:: audio_dsp.dsp.td_block_fir.generate_td_fir
:noindex:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: td_block_fir_data_init
.. doxygenfunction:: td_block_fir_add_data
.. doxygenfunction:: td_block_fir_compute
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.td_block_fir.fir_block_td
:noindex:
.. automethod:: process_frame
:noindex:
.. automethod:: reset_state
:noindex:
.. _FirBlockFD:
==========================
Block Frequency Domain FIR
==========================
This implementation is a frequency-domain implementation resulting in a lower algorithmic
complexity than the time-domain versions. This will achieve the highest taps per second possible
with the xcore. The main cost to using this implementation is the memory requirements double
compared to the previous two time-domain versions. This block will generate C code for the block
frequency domain FIR filter.
More information on implementation can be found in
`AN02027: Efficient computation of FIR filters on the XCORE <https://www.xmos.com/application-notes/>`_.
.. note::
The block time domain FIR filter is not currently implemented as a DSP Stage, so cannot be
used with the DSP pipeline tool yet.
.. tab:: Autogenerator
.. only:: latex
.. rubric:: Autogenerator
.. autofunction:: audio_dsp.dsp.fd_block_fir.generate_fd_fir
:noindex:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: fd_block_fir_data_init
.. doxygenfunction:: fd_block_fir_add_data
.. doxygenfunction:: fd_block_fir_compute
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.fd_block_fir.fir_block_fd
:noindex:
.. automethod:: process_frame
:noindex:
.. automethod:: reset_state
:noindex:

View File

@@ -0,0 +1,45 @@
.. _geq:
==================
Graphic Equalisers
==================
.. _GraphicEq10b:
=========================
10 Band Graphic Equaliser
=========================
The graphic EQ module creates a 10 band equaliser, with octave spaced
center frequencies. This can be used to
The equaliser is implemented as a set of parallel 4th order bandpass
filters, with a gain controlling the level of each parallel branch.
The center frequencies are:
[32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000].
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_graphic_eq_10b
See also :c:func:`adsp_graphic_eq_10b_init`.
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.graphic_eq.graphic_eq_10_band
:noindex:
.. automethod:: process
:noindex:
.. autoproperty:: gains_db
:noindex:

View File

@@ -0,0 +1,30 @@
.. raw:: latex
\newpage
.. _dsp_modules_section:
DSP Modules
===========
In lib_audio_dsp, DSP modules are the lower level functions and APIs.
These can be used directly without the pipeline building tool. The
documentation also includes more implementation details about the DSP
algorithms. It includes topics such as C and Python APIs,
providing more detailed view of the DSP modules.
Each DSP module has been implemented in floating point Python, fixed
point int32 Python and fixed point int32 C, with optimisations for xcore.
The Python and C fixed point implementations aim to be bit exact with
each other, allowing for Python prototyping of DSP pipelines.
.. toctree::
:maxdepth: 1
biquads.rst
drc.rst
fir.rst
graphic_eq.rst
reverb.rst
signal_chain.rst
more_python.rst

View File

@@ -0,0 +1,43 @@
########################
Python module base class
########################
All the Python DSP modules are based on a common base class.
In order to keep the documentation short, all Python classes in the
previous sections only had the ``process`` method described, and control
methods where necessary.
This section provides the user with a more in-depth information of the
Python API, which may be useful when adding custom DSP modules.
Some classes overload the base class APIs where they require different
input data types or dimensions. However, they will all have the
attributes and methods described below.
The process methods can be split into 2 groups:
1) ``process`` is a 64b floating point implementation
2) ``process_xcore`` is a 32b fixed-point implementation, with the aim of
being bit exact with the C/assembly implementation.
The ``process_xcore`` methods can be used to simulate the xcore
implementation precision and the noise floor. The Python ``process_xcore``
implementations have very similar accuracy to the xcore
C ``adsp_*`` implementations (subject to the module and implementation).
Python simulation methods tend to be slower as Python has a limited support
for the fixed point processing. Bit exactness is not always possible
for modules that use 32b float operations, as the rounding of these can
differ between C libraries.
There are 3 layers of ``process`` functions:
1) ``process`` operates for a single sample on a single channel
2) ``process_channels`` operates on all channels for a single sample
3) ``process_frame`` operates on all samples and channels for a single frame.
A DSP module may overload one or all of these, depending if it operates
sample-wise, channel-wise or frame-wise. It is expected that
``process_frame`` will be called by higher level DSP Stages.
.. autoclass:: audio_dsp.dsp.generic.dsp_block
:members:
:noindex:

View File

@@ -0,0 +1,173 @@
.. _reverb:
######
Reverb
######
.. _ReverbRoom:
===========
Reverb Room
===========
The room reverb module imitates the reflections of a room. The algorithm is a
Schroeder style reverberation, based on `Freeverb by Jezar at Dreampoint <https://www.dsprelated.com/freebooks/pasp/Freeverb.html>`_.
It consists of the wet predelay, 8 parallel comb filters fed into 4 series all-pass filters,
with a wet and dry microphone control to set the effect level.
For more details on the algorithm, see `Physical Audio Signal Processing
<https://www.dsprelated.com/freebooks/pasp/Freeverb.html>`_ by Julius Smith.
.. doxygenstruct:: reverb_room_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_reverb_room
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.reverb.reverb_room
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. automethod:: set_wet_dry_mix
:noindex:
.. automethod:: set_pre_gain
:noindex:
.. automethod:: set_wet_gain
:noindex:
.. automethod:: set_dry_gain
:noindex:
.. automethod:: set_decay
:noindex:
.. automethod:: set_damping
:noindex:
.. automethod:: set_room_size
:noindex:
.. _ReverbRoomStereo:
==================
Reverb Room Stereo
==================
The stereo room reverb module extends the mono :ref:`ReverbRoom` by adding a second
set of comb and all-pass filters in parallel, and mixing the output of the
two networks. Varying the mix of the networks changes the stereo width of
the effect.
For more details on the algorithm, see `Physical Audio Signal Processing
<https://www.dsprelated.com/freebooks/pasp/Freeverb.html>`_ by Julius Smith.
.. doxygenstruct:: reverb_room_st_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_reverb_room_st
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.reverb_stereo.reverb_room_stereo
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. automethod:: set_wet_dry_mix
:noindex:
.. autoproperty:: wet_db
:noindex:
.. autoproperty:: dry_db
:noindex:
.. autoproperty:: decay
:noindex:
.. autoproperty:: damping
:noindex:
.. _ReverbPlateStereo:
===================
Reverb Plate Stereo
===================
The plate reverb module imitates the reflections of a plate reverb,
which has more early reflections than the room reverb. The algorithm is
based on Dattorro's 1997 paper. This reverb consists of 4 allpass
filters for input diffusion, followed by a figure of 8 reverb tank of
allpasses, low-pass filters, and delays. The output is taken from
multiple taps in the delay lines to get a desirable echo density.
The left and right output can be mixed with various widths.
For more details on the algorithm, see
`Effect Design, Part 1: Reverberator and Other Filters
<https://aes2.org/publications/elibrary-page/?id=10160>`_ by Jon Dattorro.
.. doxygenstruct:: reverb_plate_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_reverb_plate
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.reverb_plate.reverb_plate_stereo
:noindex:
.. automethod:: process
:noindex:
.. automethod:: reset_state
:noindex:
.. automethod:: set_wet_dry_mix
:noindex:

View File

@@ -0,0 +1,332 @@
.. _signal_chain:
#######################
Signal Chain Components
#######################
Signal chain components includes DSP modules for:
* combining signals, such as subtracting, adding, and mixing
* forks for splitting signals
* basic gain components, such as fixed gain, volume control, and mute
* basic delay buffers.
.. _Adder:
=====
Adder
=====
The adder will add samples from N inputs together.
It will round and saturate the result to the Q0.31 range.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_adder
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.adder
:noindex:
.. automethod:: process_channels
:noindex:
.. _Subtractor:
==========
Subtractor
==========
The subtractor will subtract one sample from another, then round and saturate the difference to Q0.31 range.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_subtractor
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.subtractor
:noindex:
.. automethod:: process_channels
:noindex:
.. _FixedGain:
==========
Fixed Gain
==========
This module applies a fixed gain to a sample, with rounding and saturation to Q0.31 range.
The gain must be in ``Q_GAIN`` format.
.. doxygendefine:: Q_GAIN
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_fixed_gain
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.fixed_gain
:noindex:
.. automethod:: process
:noindex:
.. _Mixer:
=====
Mixer
=====
The mixer applies a gain to all N channels of input samples and adds them together.
The sum is rounded and saturated to Q0.31 range. The gain must be in ``Q_GAIN`` format.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_mixer
An alternative way to implement a mixer is to multiply-accumulate the
input samples into a 64-bit word, then saturate it to a 32-bit word using:
.. doxygenfunction:: adsp_saturate_32b
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.mixer
:noindex:
.. automethod:: process_channels
:noindex:
.. _VolumeControl:
==============
Volume Control
==============
The volume control allows safe real-time gain adjustments with minimal
artifacts.
When the target gain is changed, a slew is used to move from the
current gain to the target gain.
This allows smooth gain change and no clicks in the output signal.
The mute API allows the user to safely mute the signal by setting the
target gain to ``0``, with the slew ensuring no pops or clicks.
Unmuting will restore the pre-mute target gain.
The new gain can be set while muted, but will not take effect until
unmute is called.
There are separate APIs for process, setting the gain, muting and
unmuting so that volume control can easily be implemented into the
control system.
The slew is applied as an exponential of the difference between the
target and current gain.
For run-time efficiency, instead of an EMA-style alpha, the difference
is right shifted by the ``slew_shift`` parameter. The relation between
``slew_shift`` and time is further discussed in the Python class
documentation.
.. doxygenstruct:: volume_control_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_volume_control
.. doxygenfunction:: adsp_volume_control_set_gain
.. doxygenfunction:: adsp_volume_control_mute
.. doxygenfunction:: adsp_volume_control_unmute
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.volume_control
:noindex:
.. automethod:: process
:noindex:
.. automethod:: set_gain
:noindex:
.. automethod:: mute
:noindex:
.. automethod:: unmute
:noindex:
.. _Delay:
=====
Delay
=====
The delay module uses a memory buffer to return a sample after a specified
time period.
The returned samples will be delayed by a specified value.
The ``max_delay`` is set at initialisation, and sets the amount of
memory used by the buffers. It cannot be changed at runtime.
The current ``delay`` value can be changed at runtime within the range
``[0, max_delay]``
.. doxygenstruct:: delay_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_delay
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.delay
:noindex:
.. automethod:: process_channels
:noindex:
.. automethod:: reset_state
:noindex:
.. automethod:: set_delay
:noindex:
.. _SwitchSlew:
================
Switch with slew
================
The slewing switch module uses a cosine crossfade when moving switch
position in order to avoid clicks.
.. doxygenstruct:: switch_slew_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_switch_slew
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.switch_slew
:noindex:
.. automethod:: process_channels
:noindex:
.. automethod:: move_switch
:noindex:
.. _Crossfader:
==========
Crossfader
==========
The crossfader mixes between two sets of inputs.
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_crossfader
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
Only a slewing crossfader Python API is provided.
====================
Crossfader with slew
====================
The crossfader mixes between two sets of inputs, with slew applied to the
gains when they are changed.
.. doxygenstruct:: crossfader_slew_t
:members:
.. tab:: C API
.. only:: latex
.. rubric:: C API
.. doxygenfunction:: adsp_crossfader_slew
.. tab:: Python API
.. only:: latex
.. rubric:: Python API
.. autoclass:: audio_dsp.dsp.signal_chain.crossfader
:noindex:
.. automethod:: process_channels
:noindex:

View File

@@ -0,0 +1,15 @@
.. _pipeline_design_api:
Pipeline Design API
###################
This page describes the C and Python APIs that will be needed when using the pipeline design utility.
When designing a pipeline first create an instance of ``Pipeline``, add threads to it with ``Pipeline.add_thread()``. Then add DSP stages such as ``Biquad`` using ``CompositeStage.stage()``.
The pipeline can be visualised in a `Jupyter Notebook`_ using ``Pipeline.draw()`` and the xcore source code for the pipeline can be generated using ``generate_dsp_main()``.
.. contents::
:local:
:class: this-will-duplicate-information-and-it-is-still-useful-here
.. include:: gen/audio_dsp.design.inc

View File

@@ -0,0 +1,27 @@
.. _dsp_stages_section:
DSP Stages
==========
DSP stages are high level blocks for use in the Python DSP
pipeline tool. Each Stage has a Python and C implementation, allowing
pipelines to be rapidly prototyped in Python before being easily
deployed to hardware in C. The audio performance of both implementations
is equivalent.
Most stages have parameters that can be changed at runtime, and the
available parameters are outlined in the documentation.
All the DSP stages can be imported into a Python file using:
.. code-block:: console
from audio_dsp.stages import *
The following DSP stages are available for use in the Python DSP pipeline design.
.. toctree::
:glob:
:maxdepth: 2
gen/*