Reference library > FFT > FFTScaleMagnitudes
+FFTScaleMagnitudes
+FFTScaleMagnitudes(input=0, scale={})
+
Randomise phase values.
+ ++
+ Created: + 2024-06-20 + + + +
diff --git a/howto/plotting/index.html b/howto/plotting/index.html index b82f326e..94be2c29 100644 --- a/howto/plotting/index.html +++ b/howto/plotting/index.html @@ -1628,11 +1628,11 @@
BufferPlayer(buffer=None, rate=1.0, loop=0, start_time=None, end_time=None, clock=None)
Plays the contents of the given buffer. start_time/end_time are in seconds. When a clock signal is received, rewinds to the start_time.
+Plays the contents of the given buffer. start_time
/end_time
are in seconds. When a clock
signal is received, rewinds to the start_time
. Set clock
to 0
to prevent the buffer from being triggered immediately.
start_time
/end_time
are in seconds. When a clock
signal is received, rewinds to the start_time
. Set clock
to 0
to prevent the buffer from being triggered immediately.Reference library > FFT > FFTScaleMagnitudes
+FFTScaleMagnitudes(input=0, scale={})
+
Randomise phase values.
+ +start_time
/end_time
are in seconds. When a clock
signal is received, rewinds to the start_time
. Set clock
to 0
to prevent the buffer from being triggered immediately.Reference library > Processors: Panning > SpatialPanner
SpatialPanner(env=None, input=0.0, x=0.0, y=0.0, z=0.0, radius=1.0, algorithm="dbap")
+SpatialPanner(env=None, input=0.0, x=0.0, y=0.0, z=0.0, radius=1.0, use_delays=1.0, algorithm="dbap")
Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported.
@@ -1590,7 +1590,7 @@ SpatialPanner
Last update:
- 2023-12-03
+ 2024-06-20
Created:
diff --git a/planning/EXAMPLES/index.html b/planning/EXAMPLES/index.html
index de6f73c4..e10fbb30 100644
--- a/planning/EXAMPLES/index.html
+++ b/planning/EXAMPLES/index.html
@@ -1604,11 +1604,11 @@ Examples
Last update:
- 2024-02-25
+ 2024-06-20
Created:
- 2024-02-25
+ 2024-06-20
diff --git a/planning/NAMING/index.html b/planning/NAMING/index.html
index c600b72c..bd807900 100644
--- a/planning/NAMING/index.html
+++ b/planning/NAMING/index.html
@@ -1652,11 +1652,11 @@ NODES
Last update:
- 2024-02-25
+ 2024-06-20
Created:
- 2024-02-25
+ 2024-06-20
diff --git a/planning/PLAN/index.html b/planning/PLAN/index.html
index 1dbd1d6b..96449082 100644
--- a/planning/PLAN/index.html
+++ b/planning/PLAN/index.html
@@ -1634,11 +1634,11 @@ PLAN
Last update:
- 2024-02-25
+ 2024-06-20
Created:
- 2024-02-25
+ 2024-06-20
diff --git a/search/search_index.json b/search/search_index.json
index 020ad00e..b80e07fb 100644
--- a/search/search_index.json
+++ b/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"SignalFlow: Explore sound synthesis and DSP with Python","text":"SignalFlow is a sound synthesis framework whose goal is to make it quick and intuitive to explore complex sonic ideas. It has a simple Python API, allowing for rapid prototyping in Jupyter notebooks or on the command-line. It comes with over 100 signal processing classes for creative exploration, from filters and delays to FFT-based spectral processing and Euclidean rhythm generators.
Its core is implemented in efficient C++11, with cross-platform hardware acceleration.
SignalFlow has robust support for macOS and Linux (including Raspberry Pi), and has work-in-progress support for Windows. The overall project is currently in alpha status, and interfaces may change without warning.
"},{"location":"#example","title":"Example","text":"Let's take a look at a minimal SignalFlow example. Here, we create and immediately start the AudioGraph
, construct a stereo sine oscillator with a short envelope, connect the oscillator to the graph's output, and run the graph indefinitely.
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope\noutput.play()\ngraph.wait()\n
This demo shows a few syntactical benefits that SignalFlow provides to make it easy to work with audio:
- The 2-item array of frequency values passed to
SineOscillator
is expanded to create a stereo, 2-channel output. If you passed a 10-item array, the output would have 10 channels. (Read more: Multichannel nodes) - Mathematical operators like
*
can be used to multiply, add, subtract or divide the output of nodes, and creates a new output Node that corresponds to the output of the operation. This example uses an envelope to modulate the amplitude of an oscillator. (Read more: Node operators) - Even through the envelope is mono and the oscillator is stereo, SignalFlow does the right thing and upmixes the envelope's values to create a stereo output, so that the same envelope shape is applied to the L and R channels of the oscillator, before creating a stereo output. This is called \"automatic upmixing\", and is handy when working with multichannel graphs. (Read more: Automatic upmixing)
In subsequent examples, we will skip the import
line and assume you have already imported everything from the signalflow
namespace.
Info
If you want to enforce separation of namespaces, you might want to do something like the below.
import signalflow as sf\n\ngraph = sf.AudioGraph()\nsine = sf.SineOscillator(440)\n...\n
"},{"location":"#overview","title":"Overview","text":"At its core, SignalFlow has a handful of key concepts.
- At the top level is the AudioGraph, which connects to the system's audio input/output hardware.
- The graph comprises of a network of Nodes, each of which performs a single function (for example, generating a cyclical waveform, or filtering an input node). Nodes are connected by input and output relationships: the output of one node may be used to control the frequency of another. As the output of the first node increases, the frequency of the second node increases correspondingly. This modulation is applied on a sample-by-sample basis: all modulation in SignalFlow happens at audio rate.
- Nodes may have multiple inputs, which determine which synthesis properties can be modulated at runtime.
- A node can also have Buffer properties, which contain audio waveform data that can be read and written to, for playback or recording of samples.
- Nodes can be grouped in a Patch, which is a user-defined configuration of nodes. A patch may have one or more named inputs that are defined by the user when creating the patch. Patches can be thought of like voices of a synthesizer. A patch can also be set to automatically remove itself from the graph when a specified node's playback is complete, which is important for automatic memory management.
"},{"location":"#next-steps","title":"Next steps","text":" - Installing SignalFlow
- Example code
"},{"location":"examples/","title":"Examples","text":"For code examples using SignalFlow, see GitHub.
To download the examples
folder locally:
import signalflow_examples\n\nsignalflow_examples.download_examples()\n
"},{"location":"license/","title":"License","text":"SignalFlow is under the MIT license.
This means that you are welcome to use it for any purpose, including commercial usage, but must include the copyright notice above in any copies or derivative works.
Please do let me know what you use it for!
"},{"location":"buffer/","title":"Buffers","text":"A Buffer
is an area of memory that stores single-channel or multi-channel data, which may represent an audio waveform or any other type of signal.
- A Buffer can be created from a sound file, an array of samples, a specified dimension, or the result of a function
- A Buffer can be saved to a sound file
- A Buffer can be passed to a Node or Patch as an input
- Buffer sample access can be performed by get/set/fill methods, or directly as a numpy array
- Buffers can be modified, combined and queried with standard arithmetic operators
- Buffers can be queried for a number of properties, including interpolation modes and total memory usage
- TODO: Different Buffer subclasses exist for specific operations, including
Buffer2D
, WaveshaperBuffer
and EnvelopeBuffer
- TODO: Playing a buffer, including sample rate conversion and interpolation
- TODO: Recording and rendering audio into a Buffer
"},{"location":"buffer/access/","title":"Accessing in memory","text":"The floating-point samples within a SignalFlow Buffer
can be read and written directly from Python.
"},{"location":"buffer/access/#using-get-and-set-methods","title":"Using get and set methods","text":"The get()
and set()
methods can be used to access individual samples, indexed by channel and frame offset.
# Create a 2-channel buffer\nbuf = Buffer(2, 256)\n\n# Set the sample in channel 1 at index 20 to 0.5\nbuf.set(1, 20, 0.5)\n\n# Confirm that the sample is set correctly\nassert buf.get(1, 20) == 0.5\n
"},{"location":"buffer/access/#as-a-numpy-array","title":"As a numpy array","text":"The .data
property of a Buffer
points to a numpy array of shape (num_channels, num_frames)
, which can be used to read or write the buffer's data in real time.
import time\n\n# Create and play a one-second silent buffer\nbuf = Buffer(2, graph.sample_rate)\nplayer = BufferPlayer(buf, loop=True)\nplayer.play()\n\n# Gradually add crackles to the buffer, which will be heard in real-time\nwhile True:\n buf.data[0][np.random.randint(0, graph.sample_rate)] = 1.0\n buf.data[1][np.random.randint(0, graph.sample_rate)] = 1.0\n time.sleep(1)\n
"},{"location":"buffer/access/#filling-a-buffer-with-the-result-of-a-function","title":"Filling a buffer with the result of a function","text":"Just like when creating a buffer, an existing buffer can be filled with the output of a Python function.
\u2192 Next: Arithmetic operators
"},{"location":"buffer/creating/","title":"Creating a Buffer","text":"A Buffer can be created from:
- a sound file
- an array of samples
- a specified dimension
- the result of a function
"},{"location":"buffer/creating/#loading-a-buffer-from-a-sound-file","title":"Loading a buffer from a sound file","text":"To load an audio buffer from a sound file, pass the file path to Buffer's constructor.
# Load and play a buffer\nbuf = Buffer(\"filename.wav\")\nplayer = BufferPlayer(buf)\nplayer.play()\n
The type of the audio file is automatically inferred from the type and contents. Supported formats include wav
, aif
, mp3
, ogg
, flac
, and many other audio formats.
Interally, file I/O is handled by libsndfile
. For a full list of supported files, see the libsndfile documentation.
"},{"location":"buffer/creating/#creating-a-buffer-from-an-array-of-samples","title":"Creating a buffer from an array of samples","text":"To create and initialise a buffer from an existing array of samples, pass the array to Buffer's constructor. Both native Python arrays and numpy
arrays are supported.
Note that audio samples should always range between -1.0
and 1.0
to avoid distortion.
# Initialise a buffer from a native 1D array containing a sawtooth wave\nsamples = [(n % 100) / 100 - 0.5 for n in range(44100)]\nbuf = Buffer(samples)\nplayer = BufferPlayer(buf)\nplayer.play()\n
If the array is 1D, a mono buffer will be created. If the array is 2D, a multichannel buffer will be created.
# Initialise a buffer from a numpy 2D array containing a stereo sine wave\nimport numpy as np\n\nt = np.linspace(0, 1, 44100)\nstereo = np.array([np.sin(220 * t * np.pi * 2),\n np.sin(225 * t * np.pi * 2)])\nbuf = Buffer(stereo * 0.1)\nplayer = BufferPlayer(buf)\nplayer.play()\n
"},{"location":"buffer/creating/#creating-an-empty-buffer","title":"Creating an empty buffer","text":"An empty buffer can be initialised by specifying its dimensions. All samples will be initialised to zero.
# Create an empty buffer with 2 channels containing 44100 samples each.\nbuf = Buffer(2, 44100)\n
"},{"location":"buffer/creating/#initialising-a-buffer-with-the-result-of-a-function","title":"Initialising a buffer with the result of a function","text":"A buffer can also be populated with the result of a Python function, which takes a single argument containing the index of the frame to be filled.
# Create a buffer containing a 440Hz ping\nimport numpy as np\nbuf = Buffer(1, graph.sample_rate,\n lambda frame: np.sin(frame * 440 * np.pi * 2 / graph.sample_rate) * (1 - frame / graph.sample_rate))\nplayer = BufferPlayer(buf)\nplayer.play()\n
\u2192 Next: Saving and exporting a buffer
"},{"location":"buffer/exporting/","title":"Saving and exporting a buffer","text":""},{"location":"buffer/exporting/#saving-to-a-sound-file","title":"Saving to a sound file","text":"To export a buffer's audio contents to a sound file, use the save()
method:
import numpy as np\nbuf = Buffer(np.sin(np.linspace(0, 1, graph.sample_rate) * 440 * np.pi * 2))\nbuf.save(\"buffer.wav\")\n
The output format will be automatically detected from the filename extension. Supported formats are presently wav
, aif
and flac
.
\u2192 Next: Passing a buffer as an input to a node or patch
"},{"location":"buffer/input/","title":"Passing a buffer as an input to a node or patch","text":"See:
- Node: Buffer inputs
- Patch: Buffer inputs
\u2192 Next: Accessing a buffer's data in memory
"},{"location":"buffer/operators/","title":"Arithmetic operators","text":"Buffers, like nodes, can be manipulated using Python's standard arithmetic operators.
For example, to attenuate a buffer, it can be multiplied by a constant value. A new Buffer
object is returned, with the same dimensions as the original, scaled by the coefficient.
input_buffer = Buffer(\"input.wav\")\nscaled_buffer = input_buffer * 0.5\n# `scaled_buffer` now contains an attenuated version of `input_buffer`\n
Below is a full list of operators supported by SignalFlow Buffer
objects.
Operator Node class +
Add -
Subtract *
Multiply /
Divide \u2192 Next: Buffer properties
"},{"location":"buffer/properties/","title":"Buffer properties","text":"A Buffer
has a number of read-only properties which can be used to query its status at a given moment in time.
Property Type Description num_frames int The number of frames (samples) in the buffer. channels int The number of channels in the buffer. sample_rate int The sample rate of the buffer. duration float The duration of the buffer, in seconds. filename str If the buffer has been loaded from/saved to a file, the absolute path to the file. interpolation_mode str The interpolation mode of the buffer. [LINK]"},{"location":"graph/","title":"The AudioGraph","text":"AudioGraph
is the global audio processing system that schedules and performs audio processing. It is comprised of an interconnected network of Node and Patch objects, which audio flows through.
Each time a new block of audio is requested by the system audio I/O layer, the AudioGraph
object is responsible for traversing the tree of nodes and generating new samples by calling each Node
's process
method.
Why 'Graph'?
You may be more familiar with \"graph\" being used to mean a data visualisation. In signal processing and discrete mathematics, the term \"graph\" is also used to denote a system of nodes related by connections. Read more: Graph Theory Basics (Lumen Learning).
\u2192 Next: Creating the graph
"},{"location":"graph/config/","title":"The AudioGraph","text":""},{"location":"graph/config/#graph-configuration","title":"Graph configuration","text":"There are a number of graph configuration parameters that can be used to change the global behaviour of the audio system. This can be done programmatically, via a config file, or via environmental variables.
Parameter Description output_backend_name The name of the audio output backend to use, which can be one of: jack
, alsa
, pulseaudio
, coreaudio
, wasapi
, dummy
. Defaults to the first of these found on the system. Typically only required for Linux. output_device_name The name of the audio output device to use. This must precisely match the device's name in your system. If not found, DeviceNotFoundException
is thrown when instantiating the graph. output_buffer_size The size of the hardware output audio buffer, in samples. A larger buffer reduces the chance of buffer overflows and glitches, but at the cost of higher latency. Note that this config option merely specifies the preferred output buffer size, which may not be available in the system hardware. To check the actual buffer size used by the AudioGraph, query graph.output_buffer_size
after instantiation. input_device_name The name of the input device to use. input_buffer_size The size of the hardware input audio buffer. sample_rate The audio sample rate to use. cpu_usage_limit Imposes a hard limit on the CPU usage permitted by SignalFlow. If the estimated (single-core) CPU usage exceeds this value, no more nodes or patches can be created until it returns to below the limit. Floating-point value between 0..1, where 0.5 means 50% CPU."},{"location":"graph/config/#configuring-the-graph-programmatically","title":"Configuring the graph programmatically","text":"To specify an alternative config, create and populate an AudioGraphConfig
object before the graph is started:
config = AudioGraphConfig()\nconfig.output_device_name = \"MacBook Pro Speakers\"\nconfig.sample_rate = 44100\nconfig.output_buffer_size = 2048\n\ngraph = AudioGraph(config)\n
"},{"location":"graph/config/#configuring-the-graph-via-signalflowconfig","title":"Configuring the graph via ~/.signalflow/config","text":"To specify a configuration that is used by all future SignalFlow sessions, create a file ~/.signalflow/config
, containing one or more of the \"Graph configuration\" fields listed above.
For example:
[audio]\nsample_rate = 48000\noutput_buffer_size = 256\ninput_buffer_size = 256\noutput_device_name = \"MacBook Pro Speakers\"\ninput_device_name = \"MacBook Pro Microphone\"\n
All fields are optional.
A quick and easy way to edit your config, or create a new config file, is by using the signalflow
command-line utility:
signalflow configure\n
This will use your default $EDITOR
to open the configuration, or pico
if no editor is specified.
"},{"location":"graph/config/#configuring-the-graph-via-environmental-variables","title":"Configuring the graph via environmental variables","text":"SignalFlow config can also be set by setting an environmental variable in your shell. Variable names are identical to the upper-case version of the config string, prefixed with SIGNALFLOW_
. For example:
export SIGNALFLOW_OUTPUT_DEVICE_NAME=\"MacBook Pro Speakers\"\nexport SIGNALFLOW_OUTPUT_BUFFER_SIZE=1024\n
"},{"location":"graph/config/#printing-the-current-config","title":"Printing the current config","text":"To print the current configuration to stdout:
graph.config.print()\n
\u2192 Next: Graph status and properties
"},{"location":"graph/creating/","title":"The AudioGraph","text":""},{"location":"graph/creating/#creating-the-graph","title":"Creating the graph","text":"Creating the graph is simple: graph = AudioGraph()
By default, a new AudioGraph
immediately connects to the system's default audio hardware device (via the integrated libsoundio
library), using the system's default sample rate and buffer size.
Info
Note that the AudioGraph is a singleton object: only one AudioGraph can be created, which is shared globally.
To prevent the graph from starting instantly (for example, if you want to use the graph in offline mode), pass start=False
to the constructor.
To configure graph playback or recording parameters, see AudioGraph: Configuration.
\u2192 Next: Graph configuration
"},{"location":"graph/properties/","title":"The AudioGraph","text":""},{"location":"graph/properties/#status-and-properties","title":"Status and properties","text":"A number of methods are provided to query the graph's current status and properties.
"},{"location":"graph/properties/#status","title":"Status","text":"Querying graph.status
returns a one-line description of the number of nodes and patches in the graph, and the estimated CPU and RAM usage:
>>> graph.status\nAudioGraph: 235 active nodes, 6 patches, 13.95% CPU usage, 34.91MB memory usage\n
To automatically poll and print the graph's status periodically, call graph.poll(interval)
, where interval
is in seconds:
>>> graph.poll(1)\nAudioGraph: 118 active nodes, 3 patches, 7.09% CPU usage, 34.91MB memory usage\nAudioGraph: 118 active nodes, 3 patches, 7.16% CPU usage, 34.91MB memory usage\nAudioGraph: 40 active nodes, 1 patch, 2.60% CPU usage, 34.91MB memory usage\n
To stop polling, call graph.poll(0)
.
"},{"location":"graph/properties/#structure","title":"Structure","text":"Querying graph.structure
returns a multi-line string describing every Node in the graph, their parameter values, and their connectivity structure.
>>> graph.structure\n * audioout-soundio\n input0:\n * linear-panner\n pan: 0.000000\n input:\n * multiply\n input1: 0.251189\n input0:\n * sine\n frequency: 440.000000\n
"},{"location":"graph/properties/#other-graph-properties","title":"Other graph properties","text":" graph.node_count
(int): Returns the current number of Nodes in the graph (including within patches) graph.patch_count
(int): Returns the current number of Patches in the graph cpu_usage
(float): Returns the current CPU usage, between 0.0 (0%) and 1.0 (100%). CPU usage can be lowered by increasing the output buffer size. memory_usage
(int): Returns the current RAM usage, in bytes. This is typically mostly used by waveform data in Buffers. num_output_channels
(int): Returns the graph's current output channel count, which is typically identical to the number of channels supported by the audio output device. output_buffer_size
(int): Returns the current hardware output buffer size, in bytes.
\u2192 Next: Recording graph output
"},{"location":"graph/recording/","title":"The AudioGraph","text":""},{"location":"graph/recording/#recording-the-audio-output-of-the-graph","title":"Recording the audio output of the graph","text":"Convenience methods are provided to make it easy to record the global audio output when rendering audio in real-time:
graph.start_recording(\"filename.wav\")\n...\ngraph.stop_recording()\n
To record output in formats other than the default stereo, start_recording
takes a num_channels
argument that can be used to specify an alternative channel count.
Note
At present, only .wav is supported as an output format for global audio recordings.
"},{"location":"graph/recording/#offline-non-real-time-rendering","title":"Offline (non-real-time) rendering","text":"It is also possible to perform non-real-time rendering of a synthesis graph, by synthesizing audio output to a Buffer
which can then be saved to disk:
# Create an AudioGraph with a dummy output device\ngraph = AudioGraph(output_device=AudioOut_Dummy(2))\n\n# Create a buffer that will be used to store the audio output\nbuffer = Buffer(2, graph.sample_rate * 4)\n\n# Create a synthesis graph to render\nfreq = SawLFO(1, 200, 400)\nsine = SineOscillator([freq, freq+10])\ngraph.play(sine)\n\n# Render to the buffer. Non-real-time, so happens instantaneously.\n# Note that the graph renders as many samples as needed to fill the buffer.\ngraph.render_to_buffer(buffer)\n\n# Write the buffer contents to a file\nbuffer.save(\"output.wav\")\n\n# Finally, tear down the buffer\ngraph.destroy()\n
\u2192 Next: Clearing and stopping the graph
"},{"location":"graph/stopping/","title":"The AudioGraph","text":""},{"location":"graph/stopping/#clearing-and-stopping-the-graph","title":"Clearing and stopping the graph","text":"To clear all nodes and patches from the graph but leave it running for further audio synthesis:
>>> graph.clear()\n
To stop the graph and pause audio I/O:
>>> graph.stop()\n
To permanently destroy the graph:
>>> graph.destroy()\n
"},{"location":"howto/","title":"Howto","text":"Warning
This documentation is a work-in-progress and may have sections that are missing or incomplete.
Tutorials on common tasks with SignalFlow.
"},{"location":"howto/midi/","title":"Howto: MIDI control","text":""},{"location":"howto/plotting/","title":"Howto: Plotting and visualisation","text":"The output of a SignalFlow AudioGraph can be plotted using the popular matplotlib plotting library.
To install the library: pip install matplotlib
import matplotlib.pyplot as plt\nimport numpy as np\nfrom signalflow import *\n\nconfig = AudioGraphConfig()\nconfig.output_buffer_size = 4096\ngraph = AudioGraph(output_device=AudioOut_Dummy(buffer_size=2048),\n config=config)\n\nosc = SawOscillator(500)\nosc.play()\nbuf = graph.render_to_new_buffer(4410)\n\n#--------------------------------------------------------------------------------\n# Plot graphs\n#--------------------------------------------------------------------------------\nfig, axs = plt.subplots(nrows=2, figsize=(12, 5), dpi=200)\naxs[0].plot(buf.data[0])\naxs[1].magnitude_spectrum(buf.data[0], Fs=graph.sample_rate)\n\nplt.show()\n
"},{"location":"howto/plotting/#output","title":"Output","text":""},{"location":"installation/","title":"Getting started","text":""},{"location":"installation/#requirements","title":"Requirements","text":"SignalFlow supports macOS, Linux (including Raspberry Pi), and has alpha support for Windows.
"},{"location":"installation/#installation","title":"Installation","text":""},{"location":"installation/#macos","title":"macOS","text":"If you're new to Python or getting started from scratch:
macOS: Easy install with Visual Studio Code
If you are an existing Python user and confident with the command line:
macOS: Install from the command line
"},{"location":"installation/#linux","title":"Linux","text":"Linux: Install from the command line
"},{"location":"installation/#examples","title":"Examples","text":"Several example scripts are included within the repo, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
"},{"location":"installation/command-line-generic/","title":"Command line generic","text":""},{"location":"installation/command-line-generic/#1-set-up-a-virtual-environment","title":"1. Set up a virtual environment","text":"Creating a new virtual environment for SignalFlow minimises the chances of conflict with other local Python installs.
python3 -m venv signalflow-env\nsource signalflow-env/bin/activate\n
"},{"location":"installation/command-line-generic/#2-install-signalflow","title":"2. Install SignalFlow","text":"Installing SignalFlow with pip
:
pip3 install signalflow\n
If the installation succeeds, you should see Successfully installed signalflow
.
"},{"location":"installation/command-line-generic/#3-line-test","title":"3. Line test","text":"The installation of SignalFlow includes a command-line tool, signalflow
, that can be used to test and configure the framework. Check that the installation has succeeded by playing a test tone through your default system audio output:
This may take a few seconds to run for the first time. To exit the test, press Ctrl-C (^C
).
signalflow test\n
"},{"location":"installation/command-line-generic/#4-hello-world","title":"4. Hello, world","text":"In your text editor, create a new .py
file containing the below code:
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope * 0.1\noutput.play()\ngraph.wait()\n
When you run the script, you should hear a short stereo \"ping\".
"},{"location":"installation/command-line-generic/#5-optional-interactive-notebooks-in-jupyter","title":"5. (Optional) Interactive notebooks in Jupyter","text":"A nice way to experiment with SignalFlow is by using Jupyter interactive notebooks.
Install Jupyter and register this virtual environment as a Jupyter kernel:
pip3 install jupyter\npython3 -m ipykernel install --name signalflow-env\n
Open a Jupyter notebook:
jupyter notebook\n
"},{"location":"installation/next-steps/","title":"Next steps","text":""},{"location":"installation/next-steps/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"installation/linux/","title":"Installation on Linux","text":"Linux: Install from the command line
"},{"location":"installation/linux/buttons/","title":"Buttons","text":"Linux: Install from the command line
"},{"location":"installation/linux/command-line/","title":"SignalFlow: Command-line installation for Linux","text":"SignalFlow currently supports Linux x86_64 and Raspberry Pi.
These instructions assume you have a working version of Python 3.8+.
"},{"location":"installation/linux/command-line/#1-set-up-a-virtual-environment","title":"1. Set up a virtual environment","text":"Creating a new virtual environment for SignalFlow minimises the chances of conflict with other local Python installs.
python3 -m venv signalflow-env\nsource signalflow-env/bin/activate\n
"},{"location":"installation/linux/command-line/#2-install-signalflow","title":"2. Install SignalFlow","text":"Installing SignalFlow with pip
:
pip3 install signalflow\n
If the installation succeeds, you should see Successfully installed signalflow
.
"},{"location":"installation/linux/command-line/#3-line-test","title":"3. Line test","text":"The installation of SignalFlow includes a command-line tool, signalflow
, that can be used to test and configure the framework. Check that the installation has succeeded by playing a test tone through your default system audio output:
This may take a few seconds to run for the first time. To exit the test, press Ctrl-C (^C
).
signalflow test\n
"},{"location":"installation/linux/command-line/#4-hello-world","title":"4. Hello, world","text":"In your text editor, create a new .py
file containing the below code:
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope * 0.1\noutput.play()\ngraph.wait()\n
When you run the script, you should hear a short stereo \"ping\".
"},{"location":"installation/linux/command-line/#5-optional-interactive-notebooks-in-jupyter","title":"5. (Optional) Interactive notebooks in Jupyter","text":"A nice way to experiment with SignalFlow is by using Jupyter interactive notebooks.
Install Jupyter and register this virtual environment as a Jupyter kernel:
pip3 install jupyter\npython3 -m ipykernel install --name signalflow-env\n
Open a Jupyter notebook:
jupyter notebook\n
"},{"location":"installation/linux/command-line/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"installation/macos/","title":"Installation on macOS","text":"If you're new to Python or getting started from scratch:
macOS: Easy install with Visual Studio Code
If you are an existing Python user and confident with the command line:
macOS: Install from the command line
"},{"location":"installation/macos/buttons/","title":"Buttons","text":"If you're new to Python or getting started from scratch:
macOS: Easy install with Visual Studio Code
If you are an existing Python user and confident with the command line:
macOS: Install from the command line
"},{"location":"installation/macos/command-line/","title":"SignalFlow: Command-line installation for macOS","text":"These instructions assume you have a working version of Python 3.8+, installed either via Homebrew or from Python.org.
"},{"location":"installation/macos/command-line/#1-set-up-a-virtual-environment","title":"1. Set up a virtual environment","text":"Creating a new virtual environment for SignalFlow minimises the chances of conflict with other local Python installs.
python3 -m venv signalflow-env\nsource signalflow-env/bin/activate\n
"},{"location":"installation/macos/command-line/#2-install-signalflow","title":"2. Install SignalFlow","text":"Installing SignalFlow with pip
:
pip3 install signalflow\n
If the installation succeeds, you should see Successfully installed signalflow
.
"},{"location":"installation/macos/command-line/#3-line-test","title":"3. Line test","text":"The installation of SignalFlow includes a command-line tool, signalflow
, that can be used to test and configure the framework. Check that the installation has succeeded by playing a test tone through your default system audio output:
This may take a few seconds to run for the first time. To exit the test, press Ctrl-C (^C
).
signalflow test\n
"},{"location":"installation/macos/command-line/#4-hello-world","title":"4. Hello, world","text":"In your text editor, create a new .py
file containing the below code:
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope * 0.1\noutput.play()\ngraph.wait()\n
When you run the script, you should hear a short stereo \"ping\".
"},{"location":"installation/macos/command-line/#5-optional-interactive-notebooks-in-jupyter","title":"5. (Optional) Interactive notebooks in Jupyter","text":"A nice way to experiment with SignalFlow is by using Jupyter interactive notebooks.
Install Jupyter and register this virtual environment as a Jupyter kernel:
pip3 install jupyter\npython3 -m ipykernel install --name signalflow-env\n
Open a Jupyter notebook:
jupyter notebook\n
"},{"location":"installation/macos/command-line/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"installation/macos/easy/","title":"SignalFlow: Easy install for macOS","text":"The simplest way to start exploring SignalFlow is with the free Visual Studio Code editor. Visual Studio Code can edit interactive \"Jupyter\" notebooks, which allow you to run and modify blocks of Python code in real-time, which is a great way to experiment live with audio synthesis.
You'll only need to do this installation process once. Once setup, experimenting with SignalFlow is as simple as opening Visual Studio Code.
"},{"location":"installation/macos/easy/#1-install-python","title":"1. Install Python","text":"Download and install the latest version of Python (currently 3.12).
Download Python
"},{"location":"installation/macos/easy/#2-download-and-install-visual-studio-code","title":"2. Download and install Visual Studio Code","text":"Download and install the latest version of Visual Studio Code.
Download Visual Studio Code
Once installed, open Applications
and run Visual Studio Code
.
"},{"location":"installation/macos/easy/#3-install-the-python-and-jupyter-extensions","title":"3. Install the Python and Jupyter extensions","text":"Visual Studio Code requires extensions to be installed to handle Python and Jupyter files.
In Visual Studio Code, select the Extensions
icon from in the far-left column (or press \u21e7\u2318X
), and install the Python
and Jupyter
extensions by searching for their names and clicking \"Install\" on each.
Once installation has finished, close the Extensions
tab.
"},{"location":"installation/macos/easy/#4-create-a-new-workspace","title":"4. Create a new workspace","text":"In Visual Studio code, create a new folder to contain your new SignalFlow project:
- Select
File \u2192 Open Folder...
- Select
New Folder
, and pick a name for your new project folder
Where to put your workspace
You can store your project workspace anywhere on your drive. The workspace can hold multiple notebooks, audio files, etc.
Trusted workspaces
If Visual Studio asks \"Do you trust the authors of the files in this folder?\", select \"Yes, I trust the authors\". This is a security mechanism to protect you against untrusted third-party code.
"},{"location":"installation/macos/easy/#5-create-a-notebook","title":"5. Create a notebook","text":"Select File \u2192 New File...
(^\u2325\u2318N
), and select Jupyter Notebook
. You should see the screen layout change to display an empty black text block (in Jupyter parlance, a \"cell\").
"},{"location":"installation/macos/easy/#6-create-a-python-virtual-environment-to-use","title":"6. Create a Python virtual environment to use","text":"Click the button marked Select Kernel
in the top right.
- Select
Python Environments...
- Select
Create Python Environment
- Select
Venv
- Finally, select the version of Python you just installed (
3.12.x
).
Multiple versions of Python?
If you already have one or more versions of Python installed, any version from Python 3.8 upwards is fine.
Visual Studio Code will launch into some activity, in which it is installing necessary libraries and creating a Python \"virtual environment\", which is an isolated area of the filesystem containing all the packages needed for this working space. Working in different virtual environments for different projects is good practice to minimise the likelihood of conflicts and disruptions.
When the setup is complete, the button in the top right should change to say .venv (Python 3.12.x)
.
Info
New notebooks created within this workspace will share the same Python virtual environment.
"},{"location":"installation/macos/easy/#7-install-signalflow","title":"7. Install SignalFlow","text":"In the first block, copy and paste the below:
%pip install signalflow\n
To run the cell, press ^\u21b5
(control-enter). After a minute, you should see some output saying Successfully installed signalflow
.
Running cells with '.venv' requires the ipykernel package.
If you are given a prompt that the ipykernel
package is required, press \"Install\" to install the package.
You're now all set to start writing code!
"},{"location":"installation/macos/easy/#8-start-writing-code","title":"8. Start writing code","text":"In a Jupyter interactive notebook, you can write and run multi-line blocks of Python code. Press enter
to edit the cell, delete its contents, and paste the below.
print(\"Hello\")\nprint(\"world!\")\n
Press ^\u21b5
(control-enter) to run the cell. You should see \"Hello world!\" appear below the cell.
Keyboard shortcuts
- Navigate between cells with the arrow keys
- Press
enter
to begin editing a cell, and escape
to end editing and move to select mode - In select mode, use
b
to add a cell after the current cell, and a
to add a cell before it - To evaluate a cell and move on to the next cell, use
\u21e7\u21b5
(shift-enter)
"},{"location":"installation/macos/easy/#9-signalflow-import-the-library-and-start-audio-processing","title":"9. SignalFlow: Import the library and start audio processing","text":"Clear the first cell, and replace it with:
from signalflow import *\n
Run the cell with ^\u21b5
. This command imports all of the SignalFlow commands and classes, and only needs to be run once per session.
Create a new cell by pressing b
, and in the new cell, run:
graph = AudioGraph()\n
This will create and start a new global audio processing graph, using the system's default audio output. You should see the name of the audio device printed to the notebook.
This also needs to be run once per session. In fact, only one global AudioGraph
object can be created.
"},{"location":"installation/macos/easy/#10-signalflow-make-some-sound","title":"10. SignalFlow: Make some sound","text":"We're finally ready to make some noise!
In a new cell, copy and paste the below:
sine = SineOscillator(440)\npanner = StereoPanner(sine, 0.0)\noutput = panner * 0.1\noutput.play()\n
This will create a simple sine wave oscillator, pan it over a stereo pair, attenuate it, and play it from the system's audio output. Hopefully you should now hear a tone playing from your speaker or headphones.
One of the benefits of coding interactively is that you can modify the parameters of a synthesis network while it is running. In a new cell, try modifying the frequency
property of the oscillator:
sine.frequency = 880\n
You should hear it increase in pitch. Try changing the value to something different and re-running the cell.
The pan
property of StereoPanner
controls its position in the stereo field from left to right, and can range from -1
to 1
:
panner.pan = -1\n
Finally, to stop the playback:
output.stop()\n
"},{"location":"installation/macos/easy/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"library/","title":"Node reference library","text":""},{"location":"library/#analysis","title":"Analysis","text":" - CrossCorrelate: Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample.
- NearestNeighbour: Nearest Neighbour.
- OnsetDetector: Simple time-domain onset detector. Outputs an impulse when an onset is detected in the input. Maintains short-time and long-time averages. An onset is registered when the short-time average is threshold x the long-time average. min_interval is the minimum interval between onsets, in seconds.
- VampAnalysis: Feature extraction using the Vamp plugin toolkit.
"},{"location":"library/#buffer","title":"Buffer","text":" - BeatCutter: Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities.
- BufferLooper: Read and write from a buffer concurrently, with controllable overdub.
- BufferPlayer: Plays the contents of the given buffer. start_time/end_time are in seconds. When a clock signal is received, rewinds to the start_time.
- BufferRecorder: Records the input to a buffer. feedback controls overdub.
- FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
- FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
- SegmentPlayer: Trigger segments of a buffer at the given onset positions.
"},{"location":"library/#buffer-granulation","title":"Buffer: Granulation","text":" - SegmentedGranulator: Segmented Granulator.
- Granulator: Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. If
wrap
is true, grain playback can wrap around the end/start of the buffer.
"},{"location":"library/#control","title":"Control","text":" - MouseX: Outputs the normalised cursor X position, from 0 to 1. Currently only supported on macOS.
- MouseY: Outputs the normalised cursor Y position, from 0 to 1. Currently only supported on macOS.
- MouseDown: Outputs 1 if the left mouse button is down, 0 otherwise. Currently only supported on macOS.
"},{"location":"library/#envelope","title":"Envelope","text":" - ADSREnvelope: Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero.
- ASREnvelope: Attack-sustain-release envelope.
- DetectSilence: Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete.
- Envelope: Generic envelope constructor, given an array of levels, times and curves.
- Line: Line segment with the given start/end values, and duration (in seconds). If loop is true, repeats indefinitely. Retriggers on a clock signal.
- RectangularEnvelope: Rectangular envelope with the given sustain duration.
"},{"location":"library/#fft","title":"FFT","text":" - FFTContinuousPhaseVocoder: Continuous phase vocoder. Requires an FFT* input.
- FFTConvolve: Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
- FFTContrast: FFT Contrast. Requires an FFT* input.
- FFTMagnitudePhaseArray: Fixed mag/phase array.
- FFTRandomPhase: Randomise phase values.
- FFTTransform: Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input.
- FFT: Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output.
- FFTFindPeaks: Find peaks in the FFT magnitude spectrum. Requires an FFT* input.
- IFFT: Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output.
- FFTLPF: FFT-based brick wall low pass filter. Requires an FFT* input.
- FFTNoiseGate: FFT-based noise gate. Requires an FFT* input.
- FFTPhaseVocoder: Phase vocoder. Requires an FFT* input.
- FFTTonality: Tonality filter. Requires an FFT* input.
- FFTZeroPhase: Remove phase information from a frequency-domain input. Requires an FFT* input.
"},{"location":"library/#operators","title":"Operators","text":" - Add: Add each sample of a to each sample of b. Can also be written as a + b
- AmplitudeToDecibels: Map a linear amplitude value to decibels.
- DecibelsToAmplitude: DecibelsToAmplitude
- ChannelArray: Takes an array of inputs and spreads them across multiple channels of output.
- ChannelCrossfade: Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output.
- ChannelMixer: Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels.
- ChannelSelect: Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step.
- Equal: Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b
- NotEqual: Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b
- GreaterThan: Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b
- GreaterThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b
- LessThan: Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b
- LessThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b
- Modulo: Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b
- Abs: Outputs the absolute value of a, per sample. Can also be written as abs(a)
- If: Outputs value_if_true for each non-zero value of a, value_if_false for all other values.
- Divide: Divide each sample of a by each sample of b. Can also be written as a / b
- FrequencyToMidiNote: Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output.
- MidiNoteToFrequency: Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input.
- Multiply: Multiply each sample of a by each sample of b. Can also be written as a * b
- Pow: Outputs a to the power of b, per sample. Can also be written as a ** b
- RoundToScale: Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named)
- Round: Round the input to the nearest integer value.
- ScaleLinExp: Scales the input from a linear range (between a and b) to an exponential range (between c and d).
- ScaleLinLin: Scales the input from a linear range (between a and b) to a linear range (between c and d).
- Subtract: Subtract each sample of b from each sample of a. Can also be written as a - b
- Sum: Sums the output of all of the input nodes, by sample.
- TimeShift: TimeShift
- Sin: Outputs sin(a), per sample.
- Cos: Outputs cos(a), per sample.
- Tan: Outputs tan(a), per sample.
- Tanh: Outputs tanh(a), per sample. Can be used as a soft clipper.
"},{"location":"library/#oscillators","title":"Oscillators","text":" - Impulse: Produces a value of 1 at the given
frequency
, with output of 0 at all other times. If frequency is 0, produces a single impulse. - SawLFO: Produces a sawtooth LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SawOscillator: Produces a (non-band-limited) sawtooth wave, with the given
frequency
and phase
offset. When a reset
or trigger is received, resets the phase to zero. - SineLFO: Produces a sinusoidal LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SineOscillator: Produces a sine wave at the given
frequency
. - SquareLFO: Produces a pulse wave LFO with the given
frequency
and pulse width
, ranging from min
to max
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - SquareOscillator: Produces a pulse wave with the given
frequency
and pulse width
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - TriangleLFO: Produces a triangle LFO with the given
frequency
and phase
offset, ranging from min
to max
. - TriangleOscillator: Produces a triangle wave with the given
frequency
. - Wavetable: Plays the wavetable stored in buffer at the given
frequency
and phase
offset. sync
can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing. - Wavetable2D: Wavetable2D
"},{"location":"library/#processors","title":"Processors","text":" - Clip: Clip the input to
min
/max
. - Fold: Fold the input beyond
min
/max
, reflecting the excess back. - Smooth: Smooth the input with a given smoothing coefficient. When
smooth
= 0, applies no smoothing. - WetDry: Takes
wet
and dry
inputs, and outputs a mix determined by wetness
. - Wrap: Wrap the input beyond
min
/max
.
"},{"location":"library/#processors-delays","title":"Processors: Delays","text":" - AllpassDelay: All-pass delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - CombDelay: Comb delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - OneTapDelay: Single-tap delay line.
delay_time
must be less than or equal to max_delay_time
. - Stutter: Stutters the input whenever a trigger is received on
clock
. Generates stutter_count
repeats, with duration of stutter_time
.
"},{"location":"library/#processors-distortion","title":"Processors: Distortion","text":" - Resample: Resampler and bit crusher.
sample_rate
is in Hz, bit_rate
is an integer between 0 and 16. - SampleAndHold: Samples and holds the input each time a trigger is received on
clock
. - Squiz: Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler.
- WaveShaper: Applies wave-shaping as described in the WaveShaperBuffer
buffer
.
"},{"location":"library/#processors-dynamics","title":"Processors: Dynamics","text":" - Compressor: Dynamic range compression, with optional
sidechain
input. When the input amplitude is above threshold
, compresses the amplitude with the given ratio
, following the given attack_time
and release_time
in seconds. - Gate: Outputs the input value when it is above the given
threshold
, otherwise zero. - Maximiser: Gain maximiser.
- RMS: Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size.
"},{"location":"library/#processors-filters","title":"Processors: Filters","text":" - BiquadFilter: Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter.
- DCFilter: Remove low-frequency and DC content from a signal.
- EQ: Three-band EQ.
- MoogVCF: Moog ladder low-pass filter.
- SVFilter: State variable filter.
filter_type
can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. resonance
should be between [0..1]
.
"},{"location":"library/#processors-panning","title":"Processors: Panning","text":" - AzimuthPanner: Pan input around an equally-spaced ring of
num_channels
speakers. pan
is the pan position from -1..+1, where 0 = centre front. width
is the source's width, where 1.0 spans exactly between an adjacent pair of channels. - ChannelPanner: Pan the input between a linear series of channels, where
pan
0 = channel 0, 1 = channel 1, etc. No wrapping is applied. - SpatialPanner: Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported.
- StereoBalance: Takes a stereo input and rebalances it, where
balance
of 0
is unchanged, -1
is hard left, and 1
is hard right. - StereoPanner: Pans a mono input to a stereo output.
pan
should be between -1 (hard left) to +1 (hard right), with 0 = centre. - StereoWidth: Reduces the width of a stereo signal. When
width
= 1, input is unchanged. When width
= 0, outputs a pair of identical channels both containing L+R.
"},{"location":"library/#sequencing","title":"Sequencing","text":" - ClockDivider: When given a
clock
input (e.g., an Impulse), divides the clock by the given factor
. factor must be an integer greater than or equal to 1. - Counter: Count upwards from
min
to max
, driven by clock
. - Euclidean: Euclidean rhythm as described by Toussaint, with
sequence_length
(n) and num_events
(k), driven by clock
. - FlipFlop: Flips from 0/1 on each
clock
. - ImpulseSequence: Each time a
clock
or trigger is received, outputs the next value in sequence
. At all other times, outputs zero. - Index: Outputs the value in
list
corresponding to index
. - Latch: Initially outputs 0. When a trigger is received at
set
, outputs 1. When a trigger is subsequently received at reset
, outputs 0, until the next set
. - Sequence: Outputs the elements in
sequence
, incrementing position on each clock
.
"},{"location":"library/#stochastic","title":"Stochastic","text":" - Logistic: Logistic noise.
- PinkNoise: Pink noise, with specified low/high cutoffs.
- RandomBrownian: Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick.
- RandomChoice: Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick.
- RandomCoin: Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick.
- RandomExponentialDist: Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick.
- RandomExponential: Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick.
- RandomGaussian: Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick.
- RandomImpulseSequence: Generates a random sequence of 0/1 bits with the given length, and the given probability each each bit = 1. The position of the sequence is incremented on each clock signal. explore and generate are trigger inputs which cause the sequence to mutate and re-generate respectively.
- RandomImpulse: Generate random impulses at the given frequency, with either uniform or poisson distribution.
- RandomUniform: Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick.
- WhiteNoise: Generates whitenoise between min/max. If frequency is zero, generates at audio rate. For frequencies lower than audio rate, interpolate applies linear interpolation between values, and random_interval specifies whether new random values should be equally-spaced or randomly-spaced.
"},{"location":"library/analysis/","title":"Analysis","text":"Reference library > Analysis
"},{"location":"library/analysis/#analysis","title":"Analysis","text":" - CrossCorrelate: Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample.
- NearestNeighbour: Nearest Neighbour.
- OnsetDetector: Simple time-domain onset detector. Outputs an impulse when an onset is detected in the input. Maintains short-time and long-time averages. An onset is registered when the short-time average is threshold x the long-time average. min_interval is the minimum interval between onsets, in seconds.
- VampAnalysis: Feature extraction using the Vamp plugin toolkit.
"},{"location":"library/analysis/crosscorrelate/","title":"CrossCorrelate node documentation","text":"Reference library > Analysis > CrossCorrelate
"},{"location":"library/analysis/crosscorrelate/#crosscorrelate","title":"CrossCorrelate","text":"CrossCorrelate(input=None, buffer=None, hop_size=0)\n
Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample.
"},{"location":"library/analysis/nearestneighbour/","title":"NearestNeighbour node documentation","text":"Reference library > Analysis > NearestNeighbour
"},{"location":"library/analysis/nearestneighbour/#nearestneighbour","title":"NearestNeighbour","text":"NearestNeighbour(buffer=None, target=0.0)\n
Nearest Neighbour.
"},{"location":"library/analysis/onsetdetector/","title":"OnsetDetector node documentation","text":"Reference library > Analysis > OnsetDetector
"},{"location":"library/analysis/onsetdetector/#onsetdetector","title":"OnsetDetector","text":"OnsetDetector(input=0.0, threshold=2.0, min_interval=0.1)\n
Simple time-domain onset detector. Outputs an impulse when an onset is detected in the input. Maintains short-time and long-time averages. An onset is registered when the short-time average is threshold x the long-time average. min_interval is the minimum interval between onsets, in seconds.
"},{"location":"library/analysis/vampanalysis/","title":"VampAnalysis node documentation","text":"Reference library > Analysis > VampAnalysis
"},{"location":"library/analysis/vampanalysis/#vampanalysis","title":"VampAnalysis","text":"VampAnalysis(input=0.0, plugin_id=\"vamp-example-plugins:spectralcentroid:linearcentroid\")\n
Feature extraction using the Vamp plugin toolkit.
"},{"location":"library/buffer/","title":"Buffer","text":"Reference library > Buffer
"},{"location":"library/buffer/#buffer","title":"Buffer","text":" - BeatCutter: Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities.
- BufferLooper: Read and write from a buffer concurrently, with controllable overdub.
- BufferPlayer: Plays the contents of the given buffer. start_time/end_time are in seconds. When a clock signal is received, rewinds to the start_time.
- BufferRecorder: Records the input to a buffer. feedback controls overdub.
- FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
- FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
- SegmentPlayer: Trigger segments of a buffer at the given onset positions.
"},{"location":"library/buffer/beatcutter/","title":"BeatCutter node documentation","text":"Reference library > Buffer > BeatCutter
"},{"location":"library/buffer/beatcutter/#beatcutter","title":"BeatCutter","text":"BeatCutter(buffer=None, segment_count=8, stutter_probability=0.0, stutter_count=1, jump_probability=0.0, duty_cycle=1.0, rate=1.0, segment_rate=1.0)\n
Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities.
"},{"location":"library/buffer/bufferlooper/","title":"BufferLooper node documentation","text":"Reference library > Buffer > BufferLooper
"},{"location":"library/buffer/bufferlooper/#bufferlooper","title":"BufferLooper","text":"BufferLooper(buffer=None, input=0.0, feedback=0.0, loop_playback=false, loop_record=false)\n
Read and write from a buffer concurrently, with controllable overdub.
"},{"location":"library/buffer/bufferplayer/","title":"BufferPlayer node documentation","text":"Reference library > Buffer > BufferPlayer
"},{"location":"library/buffer/bufferplayer/#bufferplayer","title":"BufferPlayer","text":"BufferPlayer(buffer=None, rate=1.0, loop=0, start_time=None, end_time=None, clock=None)\n
Plays the contents of the given buffer. start_time/end_time are in seconds. When a clock signal is received, rewinds to the start_time.
"},{"location":"library/buffer/bufferrecorder/","title":"BufferRecorder node documentation","text":"Reference library > Buffer > BufferRecorder
"},{"location":"library/buffer/bufferrecorder/#bufferrecorder","title":"BufferRecorder","text":"BufferRecorder(buffer=None, input=0.0, feedback=0.0, loop=false)\n
Records the input to a buffer. feedback controls overdub.
"},{"location":"library/buffer/feedbackbufferreader/","title":"FeedbackBufferReader node documentation","text":"Reference library > Buffer > FeedbackBufferReader
"},{"location":"library/buffer/feedbackbufferreader/#feedbackbufferreader","title":"FeedbackBufferReader","text":"FeedbackBufferReader(buffer=None)\n
Counterpart to FeedbackBufferWriter.
"},{"location":"library/buffer/feedbackbufferwriter/","title":"FeedbackBufferWriter node documentation","text":"Reference library > Buffer > FeedbackBufferWriter
"},{"location":"library/buffer/feedbackbufferwriter/#feedbackbufferwriter","title":"FeedbackBufferWriter","text":"FeedbackBufferWriter(buffer=None, input=0.0, delay_time=0.1)\n
Counterpart to FeedbackBufferReader.
"},{"location":"library/buffer/grainsegments/","title":"GrainSegments node documentation","text":"Reference library > Buffer > GrainSegments
"},{"location":"library/buffer/grainsegments/#grainsegments","title":"GrainSegments","text":"GrainSegments(buffer=None, clock=0, target=0, offsets={}, values={}, durations={})\n
GrainSegments
"},{"location":"library/buffer/granulation/","title":"Index","text":"Reference library > Buffer: Granulation
"},{"location":"library/buffer/granulation/#buffer-granulation","title":"Buffer: Granulation","text":" - SegmentedGranulator: Segmented Granulator.
- Granulator: Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. If
wrap
is true, grain playback can wrap around the end/start of the buffer.
"},{"location":"library/buffer/granulation/granulator/","title":"Granulator node documentation","text":"Reference library > Buffer: Granulation > Granulator
"},{"location":"library/buffer/granulation/granulator/#granulator","title":"Granulator","text":"Granulator(buffer=None, clock=0, pos=0, duration=0.1, pan=0.0, rate=1.0, max_grains=2048, wrap=false)\n
Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. If wrap
is true, grain playback can wrap around the end/start of the buffer.
"},{"location":"library/buffer/granulation/segmentedgranulator/","title":"SegmentedGranulator node documentation","text":"Reference library > Buffer: Granulation > SegmentedGranulator
"},{"location":"library/buffer/granulation/segmentedgranulator/#segmentedgranulator","title":"SegmentedGranulator","text":"SegmentedGranulator(buffer=None, onset_times={}, durations={}, index=0.0, rate=1.0, clock=0, max_grains=2048)\n
Segmented Granulator.
"},{"location":"library/buffer/granulator/","title":"Granulator node documentation","text":"Reference library > Buffer > Granulator
"},{"location":"library/buffer/granulator/#granulator","title":"Granulator","text":"Granulator(buffer=None, clock=0, pos=0, duration=0.1, pan=0.0, rate=1.0, max_grains=2048)\n
Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo.
"},{"location":"library/buffer/segmentplayer/","title":"SegmentPlayer node documentation","text":"Reference library > Buffer > SegmentPlayer
"},{"location":"library/buffer/segmentplayer/#segmentplayer","title":"SegmentPlayer","text":"SegmentPlayer(buffer=None, onsets={}, index=None, rate=1.0, clock=None)\n
Trigger segments of a buffer at the given onset positions.
"},{"location":"library/control/","title":"Control","text":"Reference library > Control
"},{"location":"library/control/#control","title":"Control","text":" - MouseX: Outputs the normalised cursor X position, from 0 to 1. Currently only supported on macOS.
- MouseY: Outputs the normalised cursor Y position, from 0 to 1. Currently only supported on macOS.
- MouseDown: Outputs 1 if the left mouse button is down, 0 otherwise. Currently only supported on macOS.
"},{"location":"library/control/mousedown/","title":"MouseDown node documentation","text":"Reference library > Control > MouseDown
"},{"location":"library/control/mousedown/#mousedown","title":"MouseDown","text":"MouseDown(button_index=0)\n
Outputs 1 if the left mouse button is down, 0 otherwise. Currently only supported on macOS.
"},{"location":"library/control/mousedown/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# When the left mouse button is clicked, as detected by MouseDown(), an LFO is \n# applied to the oscillator's frequency.\n#-------------------------------------------------------------------------------\nlfo = SineLFO(5, 100, 600)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
#-------------------------------------------------------------------------------\n# A simple wobbling synthesiser controlled using the mouse. When the mouse is \n# clicked, as detected by MouseDown(), an LFO is activated and affects the \n# oscillator's frequency. MouseX position changes the rate of the LFO. MouseY \n# position changes the upper frequency limit, affecting pitch.\n#-------------------------------------------------------------------------------\nrate = MouseX() * 10\nupper_limit = MouseY() * 1500\nlfo = SineLFO(rate, 100, upper_limit)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
"},{"location":"library/control/mousex/","title":"MouseX node documentation","text":"Reference library > Control > MouseX
"},{"location":"library/control/mousex/#mousex","title":"MouseX","text":"MouseX()\n
Outputs the normalised cursor X position, from 0 to 1. Currently only supported on macOS.
"},{"location":"library/control/mousex/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using the MouseX position to change the rate of an LFO, which is modulating an\n# oscillator's frequency.\n#-------------------------------------------------------------------------------\nlfo_rate = MouseX() * 10\nfrequency = SineLFO(lfo_rate, 100, 600)\nosc = TriangleOscillator(frequency)\nosc.play()\n
#-------------------------------------------------------------------------------\n# A simple wobbling synthesiser controlled using the mouse. When the mouse is \n# clicked, as detected by MouseDown(), an LFO is activated and affects the \n# oscillator's frequency. MouseX position changes the rate of the LFO. MouseY \n# position changes the upper frequency limit, affecting pitch.\n#-------------------------------------------------------------------------------\nrate = MouseX() * 10\nupper_limit = MouseY() * 1500\nlfo = SineLFO(rate, 100, upper_limit)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
"},{"location":"library/control/mousey/","title":"MouseY node documentation","text":"Reference library > Control > MouseY
"},{"location":"library/control/mousey/#mousey","title":"MouseY","text":"MouseY()\n
Outputs the normalised cursor Y position, from 0 to 1. Currently only supported on macOS.
"},{"location":"library/control/mousey/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using the MouseY position to change the frequency of an oscillator.\n#-------------------------------------------------------------------------------\nfrequency = MouseY() * 1000\nosc = TriangleOscillator(frequency)\nosc.play()\n
#-------------------------------------------------------------------------------\n# A simple wobbling synthesiser controlled using the mouse. When the mouse is \n# clicked, as detected by MouseDown(), an LFO is activated and affects the \n# oscillator's frequency. MouseX position changes the rate of the LFO. MouseY \n# position changes the upper frequency limit, affecting pitch.\n#-------------------------------------------------------------------------------\nrate = MouseX() * 10\nupper_limit = MouseY() * 1500\nlfo = SineLFO(rate, 100, upper_limit)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
"},{"location":"library/envelope/","title":"Envelope","text":"Reference library > Envelope
"},{"location":"library/envelope/#envelope","title":"Envelope","text":" - ADSREnvelope: Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero.
- ASREnvelope: Attack-sustain-release envelope.
- DetectSilence: Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete.
- Envelope: Generic envelope constructor, given an array of levels, times and curves.
- Line: Line segment with the given start/end values, and duration (in seconds). If loop is true, repeats indefinitely. Retriggers on a clock signal.
- RectangularEnvelope: Rectangular envelope with the given sustain duration.
"},{"location":"library/envelope/adsrenvelope/","title":"ADSREnvelope node documentation","text":"Reference library > Envelope > ADSREnvelope
"},{"location":"library/envelope/adsrenvelope/#adsrenvelope","title":"ADSREnvelope","text":"ADSREnvelope(attack=0.1, decay=0.1, sustain=0.5, release=0.1, gate=0)\n
Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero.
"},{"location":"library/envelope/asrenvelope/","title":"ASREnvelope node documentation","text":"Reference library > Envelope > ASREnvelope
"},{"location":"library/envelope/asrenvelope/#asrenvelope","title":"ASREnvelope","text":"ASREnvelope(attack=0.1, sustain=0.5, release=0.1, curve=1.0, clock=None)\n
Attack-sustain-release envelope.
"},{"location":"library/envelope/asrenvelope/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using an ASR Envelope to shape a square wave oscillator\n#-------------------------------------------------------------------------------\nosc = SquareOscillator(500)\nenvelope = ASREnvelope(0.1, 0.0, 0.5)\noutput = osc * envelope\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using ASREnvelope to shape the sound of an oscillator over time.\n# The Line node generates a continuously-changing value which we use as the \n# release time.\n#-------------------------------------------------------------------------------\nclock = Impulse(8.0)\nCMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8\nFMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8\narpeggios = CMaj7 + FMaj9\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nrelease = Line(0.1, 0.5, 6, True)\nenvelope = ASREnvelope(attack=0.0, \n sustain=0.0, \n release=release, \n curve=1.0, \n clock=clock)\nvoice = oscillator * envelope\n\npan = SineLFO(0.1667, -1.0, 1.0)\noutput = StereoPanner(voice, pan)\noutput.play()\n
"},{"location":"library/envelope/detectsilence/","title":"DetectSilence node documentation","text":"Reference library > Envelope > DetectSilence
"},{"location":"library/envelope/detectsilence/#detectsilence","title":"DetectSilence","text":"DetectSilence(input=None, threshold=0.00001)\n
Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete.
"},{"location":"library/envelope/envelope/","title":"Envelope node documentation","text":"Reference library > Envelope > Envelope
"},{"location":"library/envelope/envelope/#envelope","title":"Envelope","text":"Envelope(levels=std::vector<NodeRef> ( ), times=std::vector<NodeRef> ( ), curves=std::vector<NodeRef> ( ), clock=None, loop=false)\n
Generic envelope constructor, given an array of levels, times and curves.
"},{"location":"library/envelope/line/","title":"Line node documentation","text":"Reference library > Envelope > Line
"},{"location":"library/envelope/line/#line","title":"Line","text":"Line(start=0.0, end=1.0, time=1.0, loop=0, clock=None)\n
Line segment with the given start/end values, and duration (in seconds). If loop is true, repeats indefinitely. Retriggers on a clock signal.
"},{"location":"library/envelope/line/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using a line to control the gain of an oscillator, emulating a sidechain \n# ducking effect.\n#-------------------------------------------------------------------------------\nclock = Impulse(frequency=1.0)\nline = Line(0.0, 0.5, 0.5, False, clock)\nosc = SawOscillator(200)\noutput = StereoPanner(osc * line)\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using Line to repeatedly alter the release value of an envelope applied to the\n# main synth voice, in time with the music.\n#-------------------------------------------------------------------------------\nclock = Impulse(8.0)\nCMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8\nFMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8\narpeggios = CMaj7 + FMaj9\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nrelease = Line(0.1, 0.5, 6, True)\nenvelope = ASREnvelope(0.0, 0.0, release, 1.0, clock)\nvoice = oscillator * envelope\n\npan = SineLFO(0.1667, -1.0, 1.0)\noutput = StereoPanner(voice, pan)\noutput.play()\n
"},{"location":"library/envelope/rectangularenvelope/","title":"RectangularEnvelope node documentation","text":"Reference library > Envelope > RectangularEnvelope
"},{"location":"library/envelope/rectangularenvelope/#rectangularenvelope","title":"RectangularEnvelope","text":"RectangularEnvelope(sustain_duration=1.0, clock=None)\n
Rectangular envelope with the given sustain duration.
"},{"location":"library/fft/","title":"FFT","text":"Reference library > FFT
"},{"location":"library/fft/#fft","title":"FFT","text":" - FFTContinuousPhaseVocoder: Continuous phase vocoder. Requires an FFT* input.
- FFTConvolve: Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
- FFTContrast: FFT Contrast. Requires an FFT* input.
- FFTMagnitudePhaseArray: Fixed mag/phase array.
- FFTRandomPhase: Randomise phase values.
- FFTTransform: Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input.
- FFT: Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output.
- FFTFindPeaks: Find peaks in the FFT magnitude spectrum. Requires an FFT* input.
- IFFT: Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output.
- FFTLPF: FFT-based brick wall low pass filter. Requires an FFT* input.
- FFTNoiseGate: FFT-based noise gate. Requires an FFT* input.
- FFTPhaseVocoder: Phase vocoder. Requires an FFT* input.
- FFTTonality: Tonality filter. Requires an FFT* input.
- FFTZeroPhase: Remove phase information from a frequency-domain input. Requires an FFT* input.
"},{"location":"library/fft/fft/","title":"FFT node documentation","text":"Reference library > FFT > FFT
"},{"location":"library/fft/fft/#fft","title":"FFT","text":"FFT(input=0.0, fft_size=SIGNALFLOW_DEFAULT_FFT_SIZE, hop_size=SIGNALFLOW_DEFAULT_FFT_HOP_SIZE, window_size=0, do_window=true)\n
Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output.
"},{"location":"library/fft/fftcontinuousphasevocoder/","title":"FFTContinuousPhaseVocoder node documentation","text":"Reference library > FFT > FFTContinuousPhaseVocoder
"},{"location":"library/fft/fftcontinuousphasevocoder/#fftcontinuousphasevocoder","title":"FFTContinuousPhaseVocoder","text":"FFTContinuousPhaseVocoder(input=None, rate=1.0)\n
Continuous phase vocoder. Requires an FFT* input.
"},{"location":"library/fft/fftcontrast/","title":"FFTContrast node documentation","text":"Reference library > FFT > FFTContrast
"},{"location":"library/fft/fftcontrast/#fftcontrast","title":"FFTContrast","text":"FFTContrast(input=0, contrast=1)\n
FFT Contrast. Requires an FFT* input.
"},{"location":"library/fft/fftconvolve/","title":"FFTConvolve node documentation","text":"Reference library > FFT > FFTConvolve
"},{"location":"library/fft/fftconvolve/#fftconvolve","title":"FFTConvolve","text":"FFTConvolve(input=None, buffer=None)\n
Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
"},{"location":"library/fft/fftfindpeaks/","title":"FFTFindPeaks node documentation","text":"Reference library > FFT > FFTFindPeaks
"},{"location":"library/fft/fftfindpeaks/#fftfindpeaks","title":"FFTFindPeaks","text":"FFTFindPeaks(input=0, prominence=1, threshold=0.000001, count=SIGNALFLOW_MAX_CHANNELS, interpolate=true)\n
Find peaks in the FFT magnitude spectrum. Requires an FFT* input.
"},{"location":"library/fft/fftflipspectrum/","title":"FFTFlipSpectrum node documentation","text":"Reference library > FFT > FFTFlipSpectrum
"},{"location":"library/fft/fftflipspectrum/#fftflipspectrum","title":"FFTFlipSpectrum","text":"FFTFlipSpectrum(input=0, flip=0, rotate=0)\n
Flips the FFT magnitude spectrum in the X axis. Requires an FFT* input.
"},{"location":"library/fft/fftlpf/","title":"FFTLPF node documentation","text":"Reference library > FFT > FFTLPF
"},{"location":"library/fft/fftlpf/#fftlpf","title":"FFTLPF","text":"FFTLPF(input=0, frequency=2000)\n
FFT-based brick wall low pass filter. Requires an FFT* input.
"},{"location":"library/fft/fftmagnitudephasearray/","title":"FFTMagnitudePhaseArray node documentation","text":"Reference library > FFT > FFTMagnitudePhaseArray
"},{"location":"library/fft/fftmagnitudephasearray/#fftmagnitudephasearray","title":"FFTMagnitudePhaseArray","text":"FFTMagnitudePhaseArray(input=0, magnitudes={}, phases={})\n
Fixed mag/phase array.
"},{"location":"library/fft/fftnoisegate/","title":"FFTNoiseGate node documentation","text":"Reference library > FFT > FFTNoiseGate
"},{"location":"library/fft/fftnoisegate/#fftnoisegate","title":"FFTNoiseGate","text":"FFTNoiseGate(input=0, threshold=0.5, invert=0.0)\n
FFT-based noise gate. Requires an FFT* input.
"},{"location":"library/fft/fftphasevocoder/","title":"FFTPhaseVocoder node documentation","text":"Reference library > FFT > FFTPhaseVocoder
"},{"location":"library/fft/fftphasevocoder/#fftphasevocoder","title":"FFTPhaseVocoder","text":"FFTPhaseVocoder(input=None)\n
Phase vocoder. Requires an FFT* input.
"},{"location":"library/fft/fftrandomphase/","title":"FFTRandomPhase node documentation","text":"Reference library > FFT > FFTRandomPhase
"},{"location":"library/fft/fftrandomphase/#fftrandomphase","title":"FFTRandomPhase","text":"FFTRandomPhase(input=0, level=1.0)\n
Randomise phase values.
"},{"location":"library/fft/ffttonality/","title":"FFTTonality node documentation","text":"Reference library > FFT > FFTTonality
"},{"location":"library/fft/ffttonality/#ffttonality","title":"FFTTonality","text":"FFTTonality(input=0, level=0.5, smoothing=0.9)\n
Tonality filter. Requires an FFT* input.
"},{"location":"library/fft/ffttransform/","title":"FFTTransform node documentation","text":"Reference library > FFT > FFTTransform
"},{"location":"library/fft/ffttransform/#ffttransform","title":"FFTTransform","text":"FFTTransform(input=0, flip=0, rotate=0)\n
Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input.
"},{"location":"library/fft/fftzerophase/","title":"FFTZeroPhase node documentation","text":"Reference library > FFT > FFTZeroPhase
"},{"location":"library/fft/fftzerophase/#fftzerophase","title":"FFTZeroPhase","text":"FFTZeroPhase(input=0)\n
Remove phase information from a frequency-domain input. Requires an FFT* input.
"},{"location":"library/fft/ifft/","title":"IFFT node documentation","text":"Reference library > FFT > IFFT
"},{"location":"library/fft/ifft/#ifft","title":"IFFT","text":"IFFT(input=None, do_window=false)\n
Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output.
"},{"location":"library/operators/","title":"Operators","text":"Reference library > Operators
"},{"location":"library/operators/#operators","title":"Operators","text":" - Add: Add each sample of a to each sample of b. Can also be written as a + b
- AmplitudeToDecibels: Map a linear amplitude value to decibels.
- DecibelsToAmplitude: DecibelsToAmplitude
- ChannelArray: Takes an array of inputs and spreads them across multiple channels of output.
- ChannelCrossfade: Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output.
- ChannelMixer: Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels.
- ChannelSelect: Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step.
- Equal: Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b
- NotEqual: Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b
- GreaterThan: Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b
- GreaterThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b
- LessThan: Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b
- LessThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b
- Modulo: Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b
- Abs: Outputs the absolute value of a, per sample. Can also be written as abs(a)
- If: Outputs value_if_true for each non-zero value of a, value_if_false for all other values.
- Divide: Divide each sample of a by each sample of b. Can also be written as a / b
- FrequencyToMidiNote: Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output.
- MidiNoteToFrequency: Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input.
- Multiply: Multiply each sample of a by each sample of b. Can also be written as a * b
- Pow: Outputs a to the power of b, per sample. Can also be written as a ** b
- RoundToScale: Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named)
- Round: Round the input to the nearest integer value.
- ScaleLinExp: Scales the input from a linear range (between a and b) to an exponential range (between c and d).
- ScaleLinLin: Scales the input from a linear range (between a and b) to a linear range (between c and d).
- Subtract: Subtract each sample of b from each sample of a. Can also be written as a - b
- Sum: Sums the output of all of the input nodes, by sample.
- TimeShift: TimeShift
- Sin: Outputs sin(a), per sample.
- Cos: Outputs cos(a), per sample.
- Tan: Outputs tan(a), per sample.
- Tanh: Outputs tanh(a), per sample. Can be used as a soft clipper.
"},{"location":"library/operators/abs/","title":"Abs node documentation","text":"Reference library > Operators > Abs
"},{"location":"library/operators/abs/#abs","title":"Abs","text":"Abs(a=0)\n
Outputs the absolute value of a, per sample. Can also be written as abs(a)
"},{"location":"library/operators/add/","title":"Add node documentation","text":"Reference library > Operators > Add
"},{"location":"library/operators/add/#add","title":"Add","text":"Add(a=0, b=0)\n
Add each sample of a to each sample of b. Can also be written as a + b
"},{"location":"library/operators/amplitudetodecibels/","title":"AmplitudeToDecibels node documentation","text":"Reference library > Operators > AmplitudeToDecibels
"},{"location":"library/operators/amplitudetodecibels/#amplitudetodecibels","title":"AmplitudeToDecibels","text":"AmplitudeToDecibels(a=0)\n
Map a linear amplitude value to decibels.
"},{"location":"library/operators/channelarray/","title":"ChannelArray node documentation","text":"Reference library > Operators > ChannelArray
"},{"location":"library/operators/channelarray/#channelarray","title":"ChannelArray","text":"ChannelArray()\n
Takes an array of inputs and spreads them across multiple channels of output.
"},{"location":"library/operators/channelarray/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using ChannelArray to pan a low tone to the left and a high tone to the right.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\npanned = ChannelArray([low, high]) * 0.3\npanned.play()\n
"},{"location":"library/operators/channelcrossfade/","title":"ChannelCrossfade node documentation","text":"Reference library > Operators > ChannelCrossfade
"},{"location":"library/operators/channelcrossfade/#channelcrossfade","title":"ChannelCrossfade","text":"ChannelCrossfade(input=None, index=None, num_output_channels=1)\n
Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output.
"},{"location":"library/operators/channelmixer/","title":"ChannelMixer node documentation","text":"Reference library > Operators > ChannelMixer
"},{"location":"library/operators/channelmixer/#channelmixer","title":"ChannelMixer","text":"ChannelMixer(num_channels=1, input=0, amplitude_compensation=true)\n
Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels.
"},{"location":"library/operators/channelselect/","title":"ChannelSelect node documentation","text":"Reference library > Operators > ChannelSelect
"},{"location":"library/operators/channelselect/#channelselect","title":"ChannelSelect","text":"ChannelSelect(input=None, offset=0, maximum=0, step=1)\n
Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step.
"},{"location":"library/operators/cos/","title":"Cos node documentation","text":"Reference library > Operators > Cos
"},{"location":"library/operators/cos/#cos","title":"Cos","text":"Cos(a=0)\n
Outputs cos(a), per sample.
"},{"location":"library/operators/decibelstoamplitude/","title":"DecibelsToAmplitude node documentation","text":"Reference library > Operators > DecibelsToAmplitude
"},{"location":"library/operators/decibelstoamplitude/#decibelstoamplitude","title":"DecibelsToAmplitude","text":"DecibelsToAmplitude(a=0)\n
DecibelsToAmplitude
"},{"location":"library/operators/divide/","title":"Divide node documentation","text":"Reference library > Operators > Divide
"},{"location":"library/operators/divide/#divide","title":"Divide","text":"Divide(a=1, b=1)\n
Divide each sample of a by each sample of b. Can also be written as a / b
"},{"location":"library/operators/equal/","title":"Equal node documentation","text":"Reference library > Operators > Equal
"},{"location":"library/operators/equal/#equal","title":"Equal","text":"Equal(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b
"},{"location":"library/operators/frequencytomidinote/","title":"FrequencyToMidiNote node documentation","text":"Reference library > Operators > FrequencyToMidiNote
"},{"location":"library/operators/frequencytomidinote/#frequencytomidinote","title":"FrequencyToMidiNote","text":"FrequencyToMidiNote(a=0)\n
Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output.
"},{"location":"library/operators/greaterthan/","title":"GreaterThan node documentation","text":"Reference library > Operators > GreaterThan
"},{"location":"library/operators/greaterthan/#greaterthan","title":"GreaterThan","text":"GreaterThan(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b
"},{"location":"library/operators/greaterthanorequal/","title":"GreaterThanOrEqual node documentation","text":"Reference library > Operators > GreaterThanOrEqual
"},{"location":"library/operators/greaterthanorequal/#greaterthanorequal","title":"GreaterThanOrEqual","text":"GreaterThanOrEqual(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b
"},{"location":"library/operators/if/","title":"If node documentation","text":"Reference library > Operators > If
"},{"location":"library/operators/if/#if","title":"If","text":"If(a=0, value_if_true=0, value_if_false=0)\n
Outputs value_if_true for each non-zero value of a, value_if_false for all other values.
"},{"location":"library/operators/lessthan/","title":"LessThan node documentation","text":"Reference library > Operators > LessThan
"},{"location":"library/operators/lessthan/#lessthan","title":"LessThan","text":"LessThan(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b
"},{"location":"library/operators/lessthanorequal/","title":"LessThanOrEqual node documentation","text":"Reference library > Operators > LessThanOrEqual
"},{"location":"library/operators/lessthanorequal/#lessthanorequal","title":"LessThanOrEqual","text":"LessThanOrEqual(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b
"},{"location":"library/operators/midinotetofrequency/","title":"MidiNoteToFrequency node documentation","text":"Reference library > Operators > MidiNoteToFrequency
"},{"location":"library/operators/midinotetofrequency/#midinotetofrequency","title":"MidiNoteToFrequency","text":"MidiNoteToFrequency(a=0)\n
Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input.
"},{"location":"library/operators/modulo/","title":"Modulo node documentation","text":"Reference library > Operators > Modulo
"},{"location":"library/operators/modulo/#modulo","title":"Modulo","text":"Modulo(a=0, b=0)\n
Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b
"},{"location":"library/operators/multiply/","title":"Multiply node documentation","text":"Reference library > Operators > Multiply
"},{"location":"library/operators/multiply/#multiply","title":"Multiply","text":"Multiply(a=1.0, b=1.0)\n
Multiply each sample of a by each sample of b. Can also be written as a * b
"},{"location":"library/operators/notequal/","title":"NotEqual node documentation","text":"Reference library > Operators > NotEqual
"},{"location":"library/operators/notequal/#notequal","title":"NotEqual","text":"NotEqual(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b
"},{"location":"library/operators/pow/","title":"Pow node documentation","text":"Reference library > Operators > Pow
"},{"location":"library/operators/pow/#pow","title":"Pow","text":"Pow(a=0, b=0)\n
Outputs a to the power of b, per sample. Can also be written as a ** b
"},{"location":"library/operators/round/","title":"Round node documentation","text":"Reference library > Operators > Round
"},{"location":"library/operators/round/#round","title":"Round","text":"Round(a=0)\n
Round the input to the nearest integer value.
"},{"location":"library/operators/roundtoscale/","title":"RoundToScale node documentation","text":"Reference library > Operators > RoundToScale
"},{"location":"library/operators/roundtoscale/#roundtoscale","title":"RoundToScale","text":"RoundToScale(a=0)\n
Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named)
"},{"location":"library/operators/scalelinexp/","title":"ScaleLinExp node documentation","text":"Reference library > Operators > ScaleLinExp
"},{"location":"library/operators/scalelinexp/#scalelinexp","title":"ScaleLinExp","text":"ScaleLinExp(input=0, a=0, b=1, c=1, d=10)\n
Scales the input from a linear range (between a and b) to an exponential range (between c and d).
"},{"location":"library/operators/scalelinlin/","title":"ScaleLinLin node documentation","text":"Reference library > Operators > ScaleLinLin
"},{"location":"library/operators/scalelinlin/#scalelinlin","title":"ScaleLinLin","text":"ScaleLinLin(input=0, a=0, b=1, c=1, d=10)\n
Scales the input from a linear range (between a and b) to a linear range (between c and d).
"},{"location":"library/operators/sin/","title":"Sin node documentation","text":"Reference library > Operators > Sin
"},{"location":"library/operators/sin/#sin","title":"Sin","text":"Sin(a=0)\n
Outputs sin(a), per sample.
"},{"location":"library/operators/subtract/","title":"Subtract node documentation","text":"Reference library > Operators > Subtract
"},{"location":"library/operators/subtract/#subtract","title":"Subtract","text":"Subtract(a=0, b=0)\n
Subtract each sample of b from each sample of a. Can also be written as a - b
"},{"location":"library/operators/sum/","title":"Sum node documentation","text":"Reference library > Operators > Sum
"},{"location":"library/operators/sum/#sum","title":"Sum","text":"Sum()\n
Sums the output of all of the input nodes, by sample.
"},{"location":"library/operators/tan/","title":"Tan node documentation","text":"Reference library > Operators > Tan
"},{"location":"library/operators/tan/#tan","title":"Tan","text":"Tan(a=0)\n
Outputs tan(a), per sample.
"},{"location":"library/operators/tanh/","title":"Tanh node documentation","text":"Reference library > Operators > Tanh
"},{"location":"library/operators/tanh/#tanh","title":"Tanh","text":"Tanh(a=0)\n
Outputs tanh(a), per sample. Can be used as a soft clipper.
"},{"location":"library/operators/timeshift/","title":"TimeShift node documentation","text":"Reference library > Operators > TimeShift
"},{"location":"library/operators/timeshift/#timeshift","title":"TimeShift","text":"TimeShift(a=0)\n
TimeShift
"},{"location":"library/oscillators/","title":"Oscillators","text":"Reference library > Oscillators
"},{"location":"library/oscillators/#oscillators","title":"Oscillators","text":" - Impulse: Produces a value of 1 at the given
frequency
, with output of 0 at all other times. If frequency is 0, produces a single impulse. - SawLFO: Produces a sawtooth LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SawOscillator: Produces a (non-band-limited) sawtooth wave, with the given
frequency
and phase
offset. When a reset
or trigger is received, resets the phase to zero. - SineLFO: Produces a sinusoidal LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SineOscillator: Produces a sine wave at the given
frequency
. - SquareLFO: Produces a pulse wave LFO with the given
frequency
and pulse width
, ranging from min
to max
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - SquareOscillator: Produces a pulse wave with the given
frequency
and pulse width
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - TriangleLFO: Produces a triangle LFO with the given
frequency
and phase
offset, ranging from min
to max
. - TriangleOscillator: Produces a triangle wave with the given
frequency
. - Wavetable: Plays the wavetable stored in buffer at the given
frequency
and phase
offset. sync
can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing. - Wavetable2D: Wavetable2D
"},{"location":"library/oscillators/constant/","title":"Constant node documentation","text":"Reference library > Oscillators > Constant
"},{"location":"library/oscillators/constant/#constant","title":"Constant","text":"Constant(value=0)\n
Produces a constant value.
"},{"location":"library/oscillators/impulse/","title":"Impulse node documentation","text":"Reference library > Oscillators > Impulse
"},{"location":"library/oscillators/impulse/#impulse","title":"Impulse","text":"Impulse(frequency=1.0)\n
Produces a value of 1 at the given frequency
, with output of 0 at all other times. If frequency is 0, produces a single impulse.
"},{"location":"library/oscillators/impulse/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using an Impulse node as a clock to trigger an envelope once per second.\n#-------------------------------------------------------------------------------\nclock = Impulse(1.0)\nosc = TriangleOscillator(250)\nenvelope = ASREnvelope(0.01, 0.0, 0.5, 1.0, clock)\noutput = StereoPanner(osc * envelope)\noutput.play()\n
"},{"location":"library/oscillators/sawlfo/","title":"SawLFO node documentation","text":"Reference library > Oscillators > SawLFO
"},{"location":"library/oscillators/sawlfo/#sawlfo","title":"SawLFO","text":"SawLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0)\n
Produces a sawtooth LFO at the given frequency
and phase
offset, with output ranging from min
to max
.
"},{"location":"library/oscillators/sawlfo/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Siren effect, using a sawtooth LFO to modulate a sinewave's frequency\n#-------------------------------------------------------------------------------\nlfo = SawLFO(1, 200, 1000)\nsine = SineOscillator(lfo)\noutput = StereoPanner(sine) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/sawoscillator/","title":"SawOscillator node documentation","text":"Reference library > Oscillators > SawOscillator
"},{"location":"library/oscillators/sawoscillator/#sawoscillator","title":"SawOscillator","text":"SawOscillator(frequency=440, phase_offset=None, reset=None)\n
Produces a (non-band-limited) sawtooth wave, with the given frequency
and phase
offset. When a reset
or trigger is received, resets the phase to zero.
"},{"location":"library/oscillators/sawoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple saw wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\nsaw = SawOscillator(440)\nenvelope = ASREnvelope(0.05, 0.1, 0.5)\noutput = StereoPanner(saw * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/sinelfo/","title":"SineLFO node documentation","text":"Reference library > Oscillators > SineLFO
"},{"location":"library/oscillators/sinelfo/#sinelfo","title":"SineLFO","text":"SineLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0)\n
Produces a sinusoidal LFO at the given frequency
and phase
offset, with output ranging from min
to max
.
"},{"location":"library/oscillators/sinelfo/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Siren effect, using a sinewave LFO to modulate a sawtooth's frequency\n#-------------------------------------------------------------------------------\nlfo = SineLFO(1, 200, 1000)\nsaw = SawOscillator(lfo)\noutput = StereoPanner(saw) * 0.3\noutput.play()\n
"},{"location":"library/oscillators/sineoscillator/","title":"SineOscillator node documentation","text":"Reference library > Oscillators > SineOscillator
"},{"location":"library/oscillators/sineoscillator/#sineoscillator","title":"SineOscillator","text":"SineOscillator(frequency=440, phase_offset=None, reset=None)\n
Produces a sine wave at the given frequency
.
"},{"location":"library/oscillators/sineoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple sine wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\nsine = SineOscillator(440)\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = StereoPanner(sine * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/squarelfo/","title":"SquareLFO node documentation","text":"Reference library > Oscillators > SquareLFO
"},{"location":"library/oscillators/squarelfo/#squarelfo","title":"SquareLFO","text":"SquareLFO(frequency=1.0, min=0.0, max=1.0, width=0.5, phase=0.0)\n
Produces a pulse wave LFO with the given frequency
and pulse width
, ranging from min
to max
, where width
of 0.5
is a square wave and other values produce a rectangular wave.
"},{"location":"library/oscillators/squarelfo/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Alarm effect, using a pulse wave LFO to modulate a sinewave's frequency\n#-------------------------------------------------------------------------------\nlfo = SquareLFO(1, 200, 400)\nsine = SineOscillator(lfo)\noutput = StereoPanner(sine) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/squareoscillator/","title":"SquareOscillator node documentation","text":"Reference library > Oscillators > SquareOscillator
"},{"location":"library/oscillators/squareoscillator/#squareoscillator","title":"SquareOscillator","text":"SquareOscillator(frequency=440, width=0.5)\n
Produces a pulse wave with the given frequency
and pulse width
, where width
of 0.5
is a square wave and other values produce a rectangular wave.
"},{"location":"library/oscillators/squareoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple square wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\nsquare = SquareOscillator(440)\nenvelope = ASREnvelope(0, 0.1, 0.5)\noutput = StereoPanner(square * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/trianglelfo/","title":"TriangleLFO node documentation","text":"Reference library > Oscillators > TriangleLFO
"},{"location":"library/oscillators/trianglelfo/#trianglelfo","title":"TriangleLFO","text":"TriangleLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0)\n
Produces a triangle LFO with the given frequency
and phase
offset, ranging from min
to max
.
"},{"location":"library/oscillators/trianglelfo/#examples","title":"Examples","text":"#-----------------------------------------------------------------------------------\n# Pacman ghost sound, using a triangle wave LFO to modulate a sine wave's frequency\n#-----------------------------------------------------------------------------------\nlfo = TriangleLFO(3, 200, 900)\nsine = SineOscillator(lfo)\noutput = StereoPanner(sine) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/triangleoscillator/","title":"TriangleOscillator node documentation","text":"Reference library > Oscillators > TriangleOscillator
"},{"location":"library/oscillators/triangleoscillator/#triangleoscillator","title":"TriangleOscillator","text":"TriangleOscillator(frequency=440)\n
Produces a triangle wave with the given frequency
.
"},{"location":"library/oscillators/triangleoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple triangle wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\ntri = TriangleOscillator(440)\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = StereoPanner(tri * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/wavetable/","title":"Wavetable node documentation","text":"Reference library > Oscillators > Wavetable
"},{"location":"library/oscillators/wavetable/#wavetable","title":"Wavetable","text":"Wavetable(buffer=None, frequency=440, phase_offset=0, sync=0, phase_map=None)\n
Plays the wavetable stored in buffer at the given frequency
and phase
offset. sync
can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing.
"},{"location":"library/oscillators/wavetable2d/","title":"Wavetable2D node documentation","text":"Reference library > Oscillators > Wavetable2D
"},{"location":"library/oscillators/wavetable2d/#wavetable2d","title":"Wavetable2D","text":"Wavetable2D(buffer=None, frequency=440, crossfade=0.0, phase_offset=0.0, sync=0)\n
Wavetable2D
"},{"location":"library/processors/","title":"Processors","text":"Reference library > Processors
"},{"location":"library/processors/#processors","title":"Processors","text":" - Clip: Clip the input to
min
/max
. - Fold: Fold the input beyond
min
/max
, reflecting the excess back. - Smooth: Smooth the input with a given smoothing coefficient. When
smooth
= 0, applies no smoothing. - WetDry: Takes
wet
and dry
inputs, and outputs a mix determined by wetness
. - Wrap: Wrap the input beyond
min
/max
.
"},{"location":"library/processors/clip/","title":"Clip node documentation","text":"Reference library > Processors > Clip
"},{"location":"library/processors/clip/#clip","title":"Clip","text":"Clip(input=None, min=-1.0, max=1.0)\n
Clip the input to min
/max
.
"},{"location":"library/processors/delays/","title":"Processors: Delays","text":"Reference library > Processors: Delays
"},{"location":"library/processors/delays/#processors-delays","title":"Processors: Delays","text":" - AllpassDelay: All-pass delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - CombDelay: Comb delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - OneTapDelay: Single-tap delay line.
delay_time
must be less than or equal to max_delay_time
. - Stutter: Stutters the input whenever a trigger is received on
clock
. Generates stutter_count
repeats, with duration of stutter_time
.
"},{"location":"library/processors/delays/allpassdelay/","title":"AllpassDelay node documentation","text":"Reference library > Processors: Delays > AllpassDelay
"},{"location":"library/processors/delays/allpassdelay/#allpassdelay","title":"AllpassDelay","text":"AllpassDelay(input=0.0, delay_time=0.1, feedback=0.5, max_delay_time=0.5)\n
All-pass delay, with feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
.
"},{"location":"library/processors/delays/allpassdelay/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using AllpassDelay to add a delay effect to a simple melodic sequence.\n# The original oscillator can be heard in the left channel.\n# The delay effect can be heard in the right channel.\n#-------------------------------------------------------------------------------\nclock = Impulse(1.0)\nsequence = Sequence([ 60, 62, 64, 65, 67, 69, 71, 72 ], clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nenvelope = ASREnvelope(0, 0.2, 0.3, 1.0, clock)\nvoice = oscillator * envelope\ndelayed = AllpassDelay(input=voice, \n delay_time=0.4, \n feedback=0.8)\n\noutput = ChannelArray([ voice, delayed ]) * 0.75\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using AllpassDelay to add a dreamy atmosphere to synth arpeggios\n#-------------------------------------------------------------------------------\nclock = Impulse(3.5)\nAm7 = [ 67, 64, 60, 57 ] * 4\nD7 = [ 62, 66, 69, 72] * 4\narpeggios = Am7 + D7\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SquareOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope\nfiltered = SVFilter(voice, \"low_pass\", 4000, 0.3)\ndelayed = AllpassDelay(input=filtered, \n delay_time=0.15, \n feedback=0.8)\n\npan = TriangleLFO(0.1, -1.0, 1.0)\noutput = StereoPanner(delayed, pan) * 0.5\noutput.play()\n
"},{"location":"library/processors/delays/combdelay/","title":"CombDelay node documentation","text":"Reference library > Processors: Delays > CombDelay
"},{"location":"library/processors/delays/combdelay/#combdelay","title":"CombDelay","text":"CombDelay(input=0.0, delay_time=0.1, feedback=0.5, max_delay_time=0.5)\n
Comb delay, with feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
.
"},{"location":"library/processors/delays/combdelay/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using CombDelay to change the character of a saw wave oscillator.\n#-------------------------------------------------------------------------------\nclock = Impulse(4)\narpeggio = [60, 62, 64, 66, 68, 70,\n 72, 70, 68, 66, 64, 62]\nsequence = Sequence(arpeggio, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SawOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope\ncomb = CombDelay(input=voice, \n delay_time=0.09, \n feedback=0.6, \n max_delay_time=0.9)\n\noutput = StereoPanner(comb) * 0.5\noutput.play()\n
"},{"location":"library/processors/delays/onetapdelay/","title":"OneTapDelay node documentation","text":"Reference library > Processors: Delays > OneTapDelay
"},{"location":"library/processors/delays/onetapdelay/#onetapdelay","title":"OneTapDelay","text":"OneTapDelay(input=0.0, delay_time=0.1, max_delay_time=0.5)\n
Single-tap delay line. delay_time
must be less than or equal to max_delay_time
.
"},{"location":"library/processors/delays/onetapdelay/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using OneTapDelay to create a delay effect with no feedback.\n# The original sound is heard in the left channel, and the delayed sound in the\n# right channel.\n#-------------------------------------------------------------------------------\nclock = Impulse(1)\noscillator = TriangleOscillator(440)\nenvelope = ASREnvelope(0.001, 0, 0.3, 1.0, clock)\nvoice = oscillator * envelope\ndelayed = OneTapDelay(voice, 0.25) * 0.5\noutput = ChannelArray([voice, delayed]) * 0.5\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using OneTapDelay to bring controlled rhythmic interest to a melodic sequence\n#-------------------------------------------------------------------------------\nclock = Impulse(3.5)\nDm = [ 62, 65, 69 ] * 2\nBdim = [ 59, 62, 65 ] * 2\nGm = [55, 58, 62 ] * 2\nBb = [77, 74, 70 ]\nA = [ 76, 73, 69 ]\n\narpeggios = Dm + Bdim + Gm + Bb + A\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SquareOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope\nfiltered = SVFilter(voice, \"low_pass\", 4000, 0.3)\ndelayed = filtered + OneTapDelay(filtered, 0.4) * 0.5\n\noutput = StereoPanner(delayed) * 0.3\noutput.play()\n
"},{"location":"library/processors/delays/stutter/","title":"Stutter node documentation","text":"Reference library > Processors: Delays > Stutter
"},{"location":"library/processors/delays/stutter/#stutter","title":"Stutter","text":"Stutter(input=0.0, stutter_time=0.1, stutter_count=1, clock=None, max_stutter_time=1.0)\n
Stutters the input whenever a trigger is received on clock
. Generates stutter_count
repeats, with duration of stutter_time
.
"},{"location":"library/processors/distortion/","title":"Processors: Distortion","text":"Reference library > Processors: Distortion
"},{"location":"library/processors/distortion/#processors-distortion","title":"Processors: Distortion","text":" - Resample: Resampler and bit crusher.
sample_rate
is in Hz, bit_rate
is an integer between 0 and 16. - SampleAndHold: Samples and holds the input each time a trigger is received on
clock
. - Squiz: Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler.
- WaveShaper: Applies wave-shaping as described in the WaveShaperBuffer
buffer
.
"},{"location":"library/processors/distortion/resample/","title":"Resample node documentation","text":"Reference library > Processors: Distortion > Resample
"},{"location":"library/processors/distortion/resample/#resample","title":"Resample","text":"Resample(input=0, sample_rate=44100, bit_rate=16)\n
Resampler and bit crusher. sample_rate
is in Hz, bit_rate
is an integer between 0 and 16.
"},{"location":"library/processors/distortion/resample/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using Resample to distort a sine wave.\n#-------------------------------------------------------------------------------\nsine = SineOscillator(440)\ncrushed = Resample(sine, 11025, 4)\noutput = StereoPanner(crushed) * 0.3\noutput.play()\n
"},{"location":"library/processors/distortion/sampleandhold/","title":"SampleAndHold node documentation","text":"Reference library > Processors: Distortion > SampleAndHold
"},{"location":"library/processors/distortion/sampleandhold/#sampleandhold","title":"SampleAndHold","text":"SampleAndHold(input=None, clock=None)\n
Samples and holds the input each time a trigger is received on clock
.
"},{"location":"library/processors/distortion/squiz/","title":"Squiz node documentation","text":"Reference library > Processors: Distortion > Squiz
"},{"location":"library/processors/distortion/squiz/#squiz","title":"Squiz","text":"Squiz(input=0.0, rate=2.0, chunk_size=1)\n
Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler.
"},{"location":"library/processors/distortion/waveshaper/","title":"WaveShaper node documentation","text":"Reference library > Processors: Distortion > WaveShaper
"},{"location":"library/processors/distortion/waveshaper/#waveshaper","title":"WaveShaper","text":"WaveShaper(input=0.0, buffer=None)\n
Applies wave-shaping as described in the WaveShaperBuffer buffer
.
"},{"location":"library/processors/distortion/waveshaper/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Create a waveshaper buffer that silences any samples with amplitude < 0.5\n#-------------------------------------------------------------------------------\nbuf = WaveShaperBuffer(lambda n: 0 if abs(n) < 0.5 else n)\nsine = SineOscillator(120)\nwaveshaper = WaveShaper(sine, buf)\nattenuated = waveshaper * 0.1\nattenuated.play()\n
#-------------------------------------------------------------------------------\n# Create a range of different waveshaper buffers, and iterate through them.\n#-------------------------------------------------------------------------------\nimport time\nimport math\nimport random\n\nsin_buf = WaveShaperBuffer(lambda n: math.sin(n * math.pi / 2))\ncos_buf = WaveShaperBuffer(lambda n: math.cos(n * math.pi / 2))\ntan_buf = WaveShaperBuffer(lambda n: math.tan(n * math.pi / 2))\ntanh_buf = WaveShaperBuffer(lambda n: math.tanh(n * 20))\nsinx_buf = WaveShaperBuffer(lambda n: math.sin(256 * n * math.pi / 2))\ninvert_buf = WaveShaperBuffer(lambda n: 1 - n if n > 0 else -1 - n)\nnoise_buf = WaveShaperBuffer(lambda n: random.uniform(0, n))\nbufs = [sin_buf, cos_buf, tan_buf, tanh_buf, sinx_buf, invert_buf, noise_buf]\n\nsine = SineOscillator(120)\nwaveshaper = WaveShaper(sine, sin_buf)\nattenuated = waveshaper * 0.1\nattenuated.play()\n\nfor buf in bufs:\n waveshaper.set_buffer(\"buffer\", buf)\n time.sleep(1.0)\n\nattenuated.stop()\n
"},{"location":"library/processors/dynamics/","title":"Processors: Dynamics","text":"Reference library > Processors: Dynamics
"},{"location":"library/processors/dynamics/#processors-dynamics","title":"Processors: Dynamics","text":" - Compressor: Dynamic range compression, with optional
sidechain
input. When the input amplitude is above threshold
, compresses the amplitude with the given ratio
, following the given attack_time
and release_time
in seconds. - Gate: Outputs the input value when it is above the given
threshold
, otherwise zero. - Maximiser: Gain maximiser.
- RMS: Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size.
"},{"location":"library/processors/dynamics/compressor/","title":"Compressor node documentation","text":"Reference library > Processors: Dynamics > Compressor
"},{"location":"library/processors/dynamics/compressor/#compressor","title":"Compressor","text":"Compressor(input=0.0, threshold=0.1, ratio=2, attack_time=0.01, release_time=0.1, sidechain=None)\n
Dynamic range compression, with optional sidechain
input. When the input amplitude is above threshold
, compresses the amplitude with the given ratio
, following the given attack_time
and release_time
in seconds.
"},{"location":"library/processors/dynamics/gate/","title":"Gate node documentation","text":"Reference library > Processors: Dynamics > Gate
"},{"location":"library/processors/dynamics/gate/#gate","title":"Gate","text":"Gate(input=0.0, threshold=0.1)\n
Outputs the input value when it is above the given threshold
, otherwise zero.
"},{"location":"library/processors/dynamics/maximiser/","title":"Maximiser node documentation","text":"Reference library > Processors: Dynamics > Maximiser
"},{"location":"library/processors/dynamics/maximiser/#maximiser","title":"Maximiser","text":"Maximiser(input=0.0, ceiling=0.5, attack_time=1.0, release_time=1.0)\n
Gain maximiser.
"},{"location":"library/processors/dynamics/rms/","title":"RMS node documentation","text":"Reference library > Processors: Dynamics > RMS
"},{"location":"library/processors/dynamics/rms/#rms","title":"RMS","text":"RMS(input=0.0)\n
Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size.
"},{"location":"library/processors/filters/","title":"Processors: Filters","text":"Reference library > Processors: Filters
"},{"location":"library/processors/filters/#processors-filters","title":"Processors: Filters","text":" - BiquadFilter: Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter.
- DCFilter: Remove low-frequency and DC content from a signal.
- EQ: Three-band EQ.
- MoogVCF: Moog ladder low-pass filter.
- SVFilter: State variable filter.
filter_type
can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. resonance
should be between [0..1]
.
"},{"location":"library/processors/filters/biquadfilter/","title":"BiquadFilter node documentation","text":"Reference library > Processors: Filters > BiquadFilter
"},{"location":"library/processors/filters/biquadfilter/#biquadfilter","title":"BiquadFilter","text":"BiquadFilter(input=0.0, filter_type=SIGNALFLOW_FILTER_TYPE_LOW_PASS, cutoff=440, resonance=0.0, peak_gain=0.0)\n
Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter.
"},{"location":"library/processors/filters/dcfilter/","title":"DCFilter node documentation","text":"Reference library > Processors: Filters > DCFilter
"},{"location":"library/processors/filters/dcfilter/#dcfilter","title":"DCFilter","text":"DCFilter(input=0.0)\n
Remove low-frequency and DC content from a signal.
"},{"location":"library/processors/filters/eq/","title":"EQ node documentation","text":"Reference library > Processors: Filters > EQ
"},{"location":"library/processors/filters/eq/#eq","title":"EQ","text":"EQ(input=0.0, low_gain=1.0, mid_gain=1.0, high_gain=1.0, low_freq=500, high_freq=5000)\n
Three-band EQ.
"},{"location":"library/processors/filters/eq/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using EQ to shape white noise. The low band (below 500Hz) is reduced. The mid\n# band is boosted. The high band (above 2000Hz) is reduced drastically.\n#-------------------------------------------------------------------------------\nnoise = WhiteNoise()\neq = EQ(input=noise, \n low_gain=0.0, \n mid_gain=1.5, \n high_gain=0.2, \n low_freq=1000, \n high_freq=2000)\noutput = StereoPanner(eq) * 0.5\noutput.play()\n
"},{"location":"library/processors/filters/moogvcf/","title":"MoogVCF node documentation","text":"Reference library > Processors: Filters > MoogVCF
"},{"location":"library/processors/filters/moogvcf/#moogvcf","title":"MoogVCF","text":"MoogVCF(input=0.0, cutoff=200.0, resonance=0.0)\n
Moog ladder low-pass filter.
"},{"location":"library/processors/filters/svfilter/","title":"SVFilter node documentation","text":"Reference library > Processors: Filters > SVFilter
"},{"location":"library/processors/filters/svfilter/#svfilter","title":"SVFilter","text":"SVFilter(input=0.0, filter_type=SIGNALFLOW_FILTER_TYPE_LOW_PASS, cutoff=440, resonance=0.0)\n
State variable filter. filter_type
can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. resonance
should be between [0..1]
.
"},{"location":"library/processors/filters/svfilter/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using SVFilter as a low-pass filter on white noise.\n#-------------------------------------------------------------------------------\nnoise = WhiteNoise()\nfiltered = SVFilter(input=noise,\n filter_type=\"low_pass\", \n cutoff=1000, \n resonance=0.6)\noutput = StereoPanner(filtered)\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using SVFilter as a low-pass filter to reduce the harshness of a square wave\n# oscillator.\n#-------------------------------------------------------------------------------\nclock = Impulse(3.5)\nAm7 = [ 67, 64, 60, 57 ] * 4\nD7 = [ 62, 66, 69, 72] * 4\narpeggios = Am7 + D7\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SquareOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope \nfiltered = SVFilter(input=voice,\n filter_type= \"low_pass\", \n cutoff=4000, \n resonance=0.3)\ndelayed = AllpassDelay(filtered, 0.15, 0.8, 0.5)\n\npan = TriangleLFO(0.1, -1.0, 1.0)\noutput = StereoPanner(delayed, pan) * 0.3\noutput.play()\n
"},{"location":"library/processors/fold/","title":"Fold node documentation","text":"Reference library > Processors > Fold
"},{"location":"library/processors/fold/#fold","title":"Fold","text":"Fold(input=None, min=-1.0, max=1.0)\n
Fold the input beyond min
/max
, reflecting the excess back.
"},{"location":"library/processors/panning/","title":"Processors: Panning","text":"Reference library > Processors: Panning
"},{"location":"library/processors/panning/#processors-panning","title":"Processors: Panning","text":" - AzimuthPanner: Pan input around an equally-spaced ring of
num_channels
speakers. pan
is the pan position from -1..+1, where 0 = centre front. width
is the source's width, where 1.0 spans exactly between an adjacent pair of channels. - ChannelPanner: Pan the input between a linear series of channels, where
pan
0 = channel 0, 1 = channel 1, etc. No wrapping is applied. - SpatialPanner: Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported.
- StereoBalance: Takes a stereo input and rebalances it, where
balance
of 0
is unchanged, -1
is hard left, and 1
is hard right. - StereoPanner: Pans a mono input to a stereo output.
pan
should be between -1 (hard left) to +1 (hard right), with 0 = centre. - StereoWidth: Reduces the width of a stereo signal. When
width
= 1, input is unchanged. When width
= 0, outputs a pair of identical channels both containing L+R.
"},{"location":"library/processors/panning/azimuthpanner/","title":"AzimuthPanner node documentation","text":"Reference library > Processors: Panning > AzimuthPanner
"},{"location":"library/processors/panning/azimuthpanner/#azimuthpanner","title":"AzimuthPanner","text":"AzimuthPanner(num_channels=2, input=0, pan=0.0, width=1.0)\n
Pan input around an equally-spaced ring of num_channels
speakers. pan
is the pan position from -1..+1, where 0 = centre front. width
is the source's width, where 1.0 spans exactly between an adjacent pair of channels.
"},{"location":"library/processors/panning/channelpanner/","title":"ChannelPanner node documentation","text":"Reference library > Processors: Panning > ChannelPanner
"},{"location":"library/processors/panning/channelpanner/#channelpanner","title":"ChannelPanner","text":"ChannelPanner(num_channels=2, input=0, pan=0.0, width=1.0)\n
Pan the input between a linear series of channels, where pan
0 = channel 0, 1 = channel 1, etc. No wrapping is applied.
"},{"location":"library/processors/panning/spatialpanner/","title":"SpatialPanner node documentation","text":"Reference library > Processors: Panning > SpatialPanner
"},{"location":"library/processors/panning/spatialpanner/#spatialpanner","title":"SpatialPanner","text":"SpatialPanner(env=None, input=0.0, x=0.0, y=0.0, z=0.0, radius=1.0, algorithm=\"dbap\")\n
Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported.
"},{"location":"library/processors/panning/stereobalance/","title":"StereoBalance node documentation","text":"Reference library > Processors: Panning > StereoBalance
"},{"location":"library/processors/panning/stereobalance/#stereobalance","title":"StereoBalance","text":"StereoBalance(input=0, balance=0)\n
Takes a stereo input and rebalances it, where balance
of 0
is unchanged, -1
is hard left, and 1
is hard right.
"},{"location":"library/processors/panning/stereobalance/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Demonstrating the effects of StereoBalance. First a low tone is assigned to \n# the left channel and a high tone is assigned to the right channel.\n# Setting StereoBalance's balance value to 0.0 will mean both tones are heard \n# equally. A value of -1.0 will result in only the left channel being heard. \n# A value of 1.0 will result in only the right channel being heard.\n# In this example, an LFO is modulating the balance value between -1.0 and 1.0.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\npanned = ChannelArray([low, high])\nbalanced = StereoBalance(panned, TriangleLFO(0.2, -1, 1)) * 0.5\nbalanced.play()\n
"},{"location":"library/processors/panning/stereopanner/","title":"StereoPanner node documentation","text":"Reference library > Processors: Panning > StereoPanner
"},{"location":"library/processors/panning/stereopanner/#stereopanner","title":"StereoPanner","text":"StereoPanner(input=0, pan=0.0)\n
Pans a mono input to a stereo output. pan
should be between -1 (hard left) to +1 (hard right), with 0 = centre.
"},{"location":"library/processors/panning/stereopanner/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using StereoPanner to pan a low pitch to the left and a high pitch to the\n# right.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\n\nleft = StereoPanner(low, -0.8)\nright = StereoPanner(high, 0.8)\n\noutput = (left + right) * 0.5\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using StereoPanner to repeatedly pan an arpeggiating oscillator between the \n# left and right channels.\n#-------------------------------------------------------------------------------\nclock = Impulse(8.0)\nCMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8\nFMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8\narpeggios = CMaj7 + FMaj9\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nrelease = Line(0.1, 0.5, 12, True)\nenvelope = ASREnvelope(0.0, 0.0, release, 1.0, clock)\nvoice = oscillator * envelope\n\npan = SineLFO(0.1667, -1.0, 1.0)\noutput = StereoPanner(voice, pan)\noutput.play()\n
"},{"location":"library/processors/panning/stereowidth/","title":"StereoWidth node documentation","text":"Reference library > Processors: Panning > StereoWidth
"},{"location":"library/processors/panning/stereowidth/#stereowidth","title":"StereoWidth","text":"StereoWidth(input=0, width=1)\n
Reduces the width of a stereo signal. When width
= 1, input is unchanged. When width
= 0, outputs a pair of identical channels both containing L+R.
"},{"location":"library/processors/panning/stereowidth/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using StereoWidth to continuously alter the width of a stereo signal.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\npanned = ChannelArray([low, high])\nwidth = StereoWidth(panned, TriangleLFO(0.5, 0, 1)) * 0.3\nwidth.play()\n
"},{"location":"library/processors/smooth/","title":"Smooth node documentation","text":"Reference library > Processors > Smooth
"},{"location":"library/processors/smooth/#smooth","title":"Smooth","text":"Smooth(input=None, smooth=0.99)\n
Smooth the input with a given smoothing coefficient. When smooth
= 0, applies no smoothing.
"},{"location":"library/processors/wetdry/","title":"WetDry node documentation","text":"Reference library > Processors > WetDry
"},{"location":"library/processors/wetdry/#wetdry","title":"WetDry","text":"WetDry(dry_input=None, wet_input=None, wetness=0.0)\n
Takes wet
and dry
inputs, and outputs a mix determined by wetness
.
"},{"location":"library/processors/wrap/","title":"Wrap node documentation","text":"Reference library > Processors > Wrap
"},{"location":"library/processors/wrap/#wrap","title":"Wrap","text":"Wrap(input=None, min=-1.0, max=1.0)\n
Wrap the input beyond min
/max
.
"},{"location":"library/sequencing/","title":"Sequencing","text":"Reference library > Sequencing
"},{"location":"library/sequencing/#sequencing","title":"Sequencing","text":" - ClockDivider: When given a
clock
input (e.g., an Impulse), divides the clock by the given factor
. factor must be an integer greater than or equal to 1. - Counter: Count upwards from
min
to max
, driven by clock
. - Euclidean: Euclidean rhythm as described by Toussaint, with
sequence_length
(n) and num_events
(k), driven by clock
. - FlipFlop: Flips from 0/1 on each
clock
. - ImpulseSequence: Each time a
clock
or trigger is received, outputs the next value in sequence
. At all other times, outputs zero. - Index: Outputs the value in
list
corresponding to index
. - Latch: Initially outputs 0. When a trigger is received at
set
, outputs 1. When a trigger is subsequently received at reset
, outputs 0, until the next set
. - Sequence: Outputs the elements in
sequence
, incrementing position on each clock
.
"},{"location":"library/sequencing/clockdivider/","title":"ClockDivider node documentation","text":"Reference library > Sequencing > ClockDivider
"},{"location":"library/sequencing/clockdivider/#clockdivider","title":"ClockDivider","text":"ClockDivider(clock=0, factor=1)\n
When given a clock
input (e.g., an Impulse), divides the clock by the given factor
. factor must be an integer greater than or equal to 1.
"},{"location":"library/sequencing/clockdivider/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using a ClockDivider to create rhythms related to the main clock. Here the \n# oscillator panned left is heard on every tick of the clock. The oscillator \n# panned right is heard every 3 ticks of the clock.\n#-------------------------------------------------------------------------------\nclock = Impulse(2.0)\ndivided_clock = ClockDivider(clock, 3)\n\noscillator_a = TriangleOscillator(220)\noscillator_b = TriangleOscillator(440)\n\nenvelope_a = ASREnvelope(0.01, 0.0, 0.25, 1.0, clock)\nenvelope_b = ASREnvelope(0.01, 0.0, 0.5, 1.0, divided_clock)\n\nvoice_a = oscillator_a * envelope_a * 0.5\nvoice_b = oscillator_b * envelope_b * 0.5\n\nleft = StereoPanner(voice_a, -0.75)\nright = StereoPanner(voice_b, 0.75)\n\nleft.play()\nright.play()\n
"},{"location":"library/sequencing/counter/","title":"Counter node documentation","text":"Reference library > Sequencing > Counter
"},{"location":"library/sequencing/counter/#counter","title":"Counter","text":"Counter(clock=0, min=0, max=2147483647)\n
Count upwards from min
to max
, driven by clock
.
"},{"location":"library/sequencing/euclidean/","title":"Euclidean node documentation","text":"Reference library > Sequencing > Euclidean
"},{"location":"library/sequencing/euclidean/#euclidean","title":"Euclidean","text":"Euclidean(clock=0, sequence_length=0, num_events=0)\n
Euclidean rhythm as described by Toussaint, with sequence_length
(n) and num_events
(k), driven by clock
.
"},{"location":"library/sequencing/flipflop/","title":"FlipFlop node documentation","text":"Reference library > Sequencing > FlipFlop
"},{"location":"library/sequencing/flipflop/#flipflop","title":"FlipFlop","text":"FlipFlop(clock=0)\n
Flips from 0/1 on each clock
.
"},{"location":"library/sequencing/impulsesequence/","title":"ImpulseSequence node documentation","text":"Reference library > Sequencing > ImpulseSequence
"},{"location":"library/sequencing/impulsesequence/#impulsesequence","title":"ImpulseSequence","text":"ImpulseSequence(sequence=std::vector<int> ( ), clock=None)\n
Each time a clock
or trigger is received, outputs the next value in sequence
. At all other times, outputs zero.
"},{"location":"library/sequencing/index/","title":"Index node documentation","text":"Reference library > Sequencing > Index
"},{"location":"library/sequencing/index/#index","title":"Index","text":"Index(list={}, index=0)\n
Outputs the value in list
corresponding to index
.
"},{"location":"library/sequencing/latch/","title":"Latch node documentation","text":"Reference library > Sequencing > Latch
"},{"location":"library/sequencing/latch/#latch","title":"Latch","text":"Latch(set=0, reset=0)\n
Initially outputs 0. When a trigger is received at set
, outputs 1. When a trigger is subsequently received at reset
, outputs 0, until the next set
.
"},{"location":"library/sequencing/sequence/","title":"Sequence node documentation","text":"Reference library > Sequencing > Sequence
"},{"location":"library/sequencing/sequence/#sequence","title":"Sequence","text":"Sequence(sequence=std::vector<float> ( ), clock=None)\n
Outputs the elements in sequence
, incrementing position on each clock
.
"},{"location":"library/sequencing/sequence/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Creating a sequence using the MIDI note values of a C Major scale, starting on\n# middle C.\n#-------------------------------------------------------------------------------\nclock = Impulse(2.0)\nsequence = Sequence([ 60, 62, 64, 65, 67, 69, 71, 72 ], clock)\nfrequency = MidiNoteToFrequency(sequence)\noscillator = TriangleOscillator(frequency)\noscillator.play()\n
"},{"location":"library/stochastic/","title":"Stochastic","text":"Reference library > Stochastic
"},{"location":"library/stochastic/#stochastic","title":"Stochastic","text":" - Logistic: Logistic noise.
- PinkNoise: Pink noise, with specified low/high cutoffs.
- RandomBrownian: Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick.
- RandomChoice: Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick.
- RandomCoin: Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick.
- RandomExponentialDist: Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick.
- RandomExponential: Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick.
- RandomGaussian: Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick.
- RandomImpulseSequence: Generates a random sequence of 0/1 bits with the given length, and the given probability each each bit = 1. The position of the sequence is incremented on each clock signal. explore and generate are trigger inputs which cause the sequence to mutate and re-generate respectively.
- RandomImpulse: Generate random impulses at the given frequency, with either uniform or poisson distribution.
- RandomUniform: Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick.
- WhiteNoise: Generates whitenoise between min/max. If frequency is zero, generates at audio rate. For frequencies lower than audio rate, interpolate applies linear interpolation between values, and random_interval specifies whether new random values should be equally-spaced or randomly-spaced.
"},{"location":"library/stochastic/logistic/","title":"Logistic node documentation","text":"Reference library > Stochastic > Logistic
"},{"location":"library/stochastic/logistic/#logistic","title":"Logistic","text":"Logistic(chaos=3.7, frequency=0.0)\n
Logistic noise.
"},{"location":"library/stochastic/pinknoise/","title":"PinkNoise node documentation","text":"Reference library > Stochastic > PinkNoise
"},{"location":"library/stochastic/pinknoise/#pinknoise","title":"PinkNoise","text":"PinkNoise(low_cutoff=20.0, high_cutoff=20000.0, reset=None)\n
Pink noise, with specified low/high cutoffs.
"},{"location":"library/stochastic/randombrownian/","title":"RandomBrownian node documentation","text":"Reference library > Stochastic > RandomBrownian
"},{"location":"library/stochastic/randombrownian/#randombrownian","title":"RandomBrownian","text":"RandomBrownian(min=-1.0, max=1.0, delta=0.01, clock=None, reset=None)\n
Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick.
"},{"location":"library/stochastic/randomchoice/","title":"RandomChoice node documentation","text":"Reference library > Stochastic > RandomChoice
"},{"location":"library/stochastic/randomchoice/#randomchoice","title":"RandomChoice","text":"RandomChoice(values=std::vector<float> ( ), clock=None, reset=None)\n
Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomcoin/","title":"RandomCoin node documentation","text":"Reference library > Stochastic > RandomCoin
"},{"location":"library/stochastic/randomcoin/#randomcoin","title":"RandomCoin","text":"RandomCoin(probability=0.5, clock=None, reset=None)\n
Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomexponential/","title":"RandomExponential node documentation","text":"Reference library > Stochastic > RandomExponential
"},{"location":"library/stochastic/randomexponential/#randomexponential","title":"RandomExponential","text":"RandomExponential(min=0.001, max=1.0, clock=None, reset=None)\n
Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomexponentialdist/","title":"RandomExponentialDist node documentation","text":"Reference library > Stochastic > RandomExponentialDist
"},{"location":"library/stochastic/randomexponentialdist/#randomexponentialdist","title":"RandomExponentialDist","text":"RandomExponentialDist(scale=0.0, clock=None, reset=None)\n
Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomgaussian/","title":"RandomGaussian node documentation","text":"Reference library > Stochastic > RandomGaussian
"},{"location":"library/stochastic/randomgaussian/#randomgaussian","title":"RandomGaussian","text":"RandomGaussian(mean=0.0, sigma=0.0, clock=None, reset=None)\n
Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomimpulse/","title":"RandomImpulse node documentation","text":"Reference library > Stochastic > RandomImpulse
"},{"location":"library/stochastic/randomimpulse/#randomimpulse","title":"RandomImpulse","text":"RandomImpulse(frequency=1.0, distribution=SIGNALFLOW_EVENT_DISTRIBUTION_UNIFORM, reset=None)\n
Generate random impulses at the given frequency, with either uniform or poisson distribution.
"},{"location":"library/stochastic/randomimpulsesequence/","title":"RandomImpulseSequence node documentation","text":"Reference library > Stochastic > RandomImpulseSequence
"},{"location":"library/stochastic/randomimpulsesequence/#randomimpulsesequence","title":"RandomImpulseSequence","text":"RandomImpulseSequence(probability=0.5, length=8, clock=None, explore=None, generate=None, reset=None)\n
Generates a random sequence of 0/1 bits with the given length, and the given probability each each bit = 1. The position of the sequence is incremented on each clock signal. explore and generate are trigger inputs which cause the sequence to mutate and re-generate respectively.
"},{"location":"library/stochastic/randomuniform/","title":"RandomUniform node documentation","text":"Reference library > Stochastic > RandomUniform
"},{"location":"library/stochastic/randomuniform/#randomuniform","title":"RandomUniform","text":"RandomUniform(min=0.0, max=1.0, clock=None, reset=None)\n
Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/whitenoise/","title":"WhiteNoise node documentation","text":"Reference library > Stochastic > WhiteNoise
"},{"location":"library/stochastic/whitenoise/#whitenoise","title":"WhiteNoise","text":"WhiteNoise(frequency=0.0, min=-1.0, max=1.0, interpolate=true, random_interval=true, reset=None)\n
Generates whitenoise between min/max. If frequency is zero, generates at audio rate. For frequencies lower than audio rate, interpolate applies linear interpolation between values, and random_interval specifies whether new random values should be equally-spaced or randomly-spaced.
"},{"location":"library/stochastic/whitenoise/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using white noise to control the pitch of an oscillator.\n# A new pitch is determined once every second. Interpolation is turned off so \n# that the oscillator jumps to the new pitch instead of smoothly moving to it.\n# Random interval is turned off so that pitch changes occur at a regular rate.\n#-------------------------------------------------------------------------------\nfrequency = WhiteNoise( frequency=1,\n min=100, \n max=1000, \n interpolate=False, \n random_interval=False)\noscillator = SineOscillator(frequency)\noutput = StereoPanner(oscillator) * 0.5\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using white noise to simulate the sound of wind.\n# White noise is generated at audio rate and passed into a band-pass filter.\n# The cutoff of the filter is controlled by another white noise generator, which\n# generates a new value between 100 and 300 at randomly-spaced intervals every \n# second, and smoothly interpolates between these values.\n#-------------------------------------------------------------------------------\nnoise = WhiteNoise()\ncutoff = WhiteNoise(1, 100, 300, True, True)\nfiltered = SVFilter(input=noise,\n filter_type= \"band_pass\", \n cutoff=cutoff,\n resonance=0.8)\noutput = StereoPanner(filtered) * 0.5\noutput.play()\n
"},{"location":"node/","title":"Nodes","text":"A Node
object is an audio processing unit that performs one single function. For example, a Node's role may be to synthesize a waveform, read from a buffer, or take two input Nodes and sum their values.
- Nodes are played and stopped by connecting them to the AudioGraph
- A node has one or more audio-rate inputs, which can be modulated by other nodes \u2014 for example, a filter node has inputs for
cutoff
and resonance
- Some nodes can be triggered with trigger inputs \u2014 for example, to restart playback, or set the position of an envelope
- Some nodes can be used to play back the contents of buffer inputs, or can use buffer data as a source of modulation \u2014 for example, the
Granulator
node plays grains of audio from one buffer, and takes another buffer to shape the envelope of each grain - The output of multiple nodes can be combined and modulated with use of the standard Python operators (
+
, -
, *
, %
, etc) - The output of a node can be mono (single-channel) or multichannel
- A Node's status and output can be examined by querying its properties
- Some Nodes generate unpredictable stochastic output, which can be controlled via its internal random number generator
- Details of how to create a new Node type are detailed in Developing a new Node class
For an overview of every type of Node available in SignalFlow, see the Node Reference Library
\u2192 Next: Node playback
"},{"location":"node/developing/","title":"Nodes","text":""},{"location":"node/developing/#developing-new-node-classes","title":"Developing new Node classes","text":"See CONTRIBUTING.md
"},{"location":"node/inputs/","title":"Nodes","text":""},{"location":"node/inputs/#node-inputs","title":"Node inputs","text":"A node has three different classes of input:
- Audio-rate inputs: Takes the output of another node as an input, for continuous modulation of synthesis parameters
- Trigger inputs: Used to trigger discrete control events \u2014 for example, restarting buffer playback
- Buffer inputs: Used to pass the contents of an audio buffer to a node \u2014 for example, as a source of audio samples, or an envelope shape
"},{"location":"node/inputs/#audio-rate-inputs","title":"Audio-rate inputs","text":"Virtually every node has one or more audio-rate inputs. Put simply, an audio-rate input is the output of another node. Let's look at a short example:
lfo = SineLFO()\nsignal = SquareOscillator(frequency=200, width=lfo)\n
In this case, we are passing the output of a SineLFO
as the pulse width of a SquareOscillator
. This is an audio-rate input.
Although it's not obvious, the frequency
parameter is also an audio-rate input. Any constant value (such as the 200
here) is behind the scenes implemented as a Constant
node, which continuously outputs the value at an audio rate.
All audio-rate inputs can be modified just like a normal Python property. For example:
signal.frequency = TriangleOscillator(0.5, 100, 1000)\n
"},{"location":"node/inputs/#variable-input-nodes","title":"Variable input nodes","text":"Some nodes have a variable number of inputs, which can change over the Node's lifetime. For example, Sum()
takes an arbitrary number of input Nodes, and generates an output which is the sum of all of its inputs.
For variable-input nodes such as this, audio-rate inputs are added with add_input()
, and can be removed with remove_input()
.
a = Constant(1)\nb = Constant(2)\nc = Constant(3)\nsum = Sum()\nsum.add_input(a)\nsum.add_input(b)\nsum.add_input(c)\n# sum will now generate an output of 6.0\n
It is possible to check whether a Node object takes variable inputs by querying node.has_variable_inputs
.
"},{"location":"node/inputs/#triggers","title":"Triggers","text":"When working with sequencing and timing, it is often useful be able to trigger discrete events within a node. This is where trigger inputs come in handy.
There are two different ways to handle trigger inputs:
- by calling the
trigger()
method on a Node
- by passing a Node to an input that corresponds to an audio-rate trigger
"},{"location":"node/inputs/#calling-trigger","title":"Calling trigger()","text":"To generate trigger events at arbitrary times, call node.trigger()
. For example:
freq_env = Line(10000, 100, 0.5)\nsine = SineOscillator(freq_env)\nsine.play()\nwhile True:\n freq_env.trigger()\n graph.wait(1)\n
This is useful because it can be done outside the audio thread. For example, trigger()
could be called each time a MIDI note event is received.
The trigger()
method takes an optional name
parameter, which is used by Node
classes containing more than one type of trigger. This example uses the set_position
trigger of BufferPlayer
to seek to a new location in the sample every second.
buffer = Buffer(\"../audio/stereo-count.wav\")\nplayer = BufferPlayer(buffer, loop=True)\nplayer.play()\nwhile True:\n player.trigger(\"set_position\", random_uniform(0, buffer.duration))\n graph.wait(1)\n
Note
Because the trigger
method happens outside the audio thread, it will take effect at the start of the next audio block. This means that, if you are running at 44.1kHz with an audio buffer size of 1024 samples, this could introduce a latency of up to 1024/44100 = 0.023s
. For time-critical events like drum triggers, this can be minimised by reducing the hardware output buffer size.
This constraint also means that only one event can be triggered per audio block. To trigger events at a faster rate than the hardware buffer size allows, see Audio-rate triggers below.
"},{"location":"node/inputs/#audio-rate-triggers","title":"Audio-rate triggers","text":"It is often desirable to trigger events using the audio-rate output of another Node object as a source of trigger events, to give sample-level precision in timing. Most nodes that support trigger
inputs can also be triggered by a corresponding audio-rate input.
Triggers happen at zero-crossings \u2014 that is, when the output of the node passes above zero (i.e., from <= 0
to >0
). For example, to create a clock with an oscillating tempo to re-trigger buffer playback:
clock = Impulse(SineLFO(0.2, 1, 10))\nbuffer = Buffer(\"examples/audio/stereo-count.wav\")\nplayer = BufferPlayer(buffer, loop=True, clock=clock)\nplayer.play()\n
This can be used to your advantage with the boolean operator nodes.
on_the_right = MouseX() > 0.5\nenvelope = ASREnvelope(0, 0, 0.5, clock=on_the_right)\nsquare = SquareOscillator(100)\noutput = envelope * square * 0.1\noutput.play()\n
TODO: Should the name of the trigger() event always be identical to the trigger input name? So clock
for envelopes, buffer player, etc...?
"},{"location":"node/inputs/#buffer-inputs","title":"Buffer inputs","text":"The third type of input supported by nodes is the buffer. Nodes often take buffer inputs as sources of audio samples. They are also useful as sources of envelope shape data (for example, to shape the grains of a Granulator), or general control data (for example, recording motion patterns from a MouseX
input).
buffer = Buffer(\"audio/stereo-count.wav\")\nplayer = BufferPlayer(buffer, loop=True)\n
A buffer input cannot be set using the same property shorthand as audio-rate inputs; instead, the set_buffer
method should be used.
new_buffer = Buffer(\"audio/example.wav\")\nplayer.set_buffer(\"buffer\", new_buffer)\n
TODO: Should this be set_input
for consistency with Patch?
"},{"location":"node/inputs/#enumerating-a-nodes-inputs","title":"Enumerating a node's inputs","text":"To list the potential and actual inputs of a node, the .inputs
property returns a dict
of key-value pairs:
>>> player.inputs\n{\n 'clock': <signalflow.Impulse at 0x107778eb0>,\n 'end_time': None,\n 'loop': <signalflow.Constant at 0x12a4cd4b0>,\n 'rate': <signalflow.Constant at 0x12a4cd330>,\n 'start_time': None\n}\n
Any constant-valued inputs are wrapped inside a special Constant
node class. The value contained by a Constant
can be accessed with its .value
property.
"},{"location":"node/inputs/#playerinputsratevalue-10","title":">>> player.inputs[\"rate\"].value\n1.0\n
","text":"\u2192 Next: Operators
"},{"location":"node/multichannel/","title":"Nodes","text":""},{"location":"node/multichannel/#multichannel-nodes","title":"Multichannel nodes","text":"When passing a value to audio-rate input of a Node, the signal is by default monophonic (single-channel). For example, SquareOscillator(440)
generates a 1-channel output.
It is possible to generate multi-channel output by passing an array of values in the place of a constant. For example, SquareOscillator([440, 880])
generates stereo output with a different frequency in the L and R channels.
There is no limit to the number of channels that can be generated by a node. For example, SquareOscillator(list(100 + 50 * n for n in range(100)))
will create a node with 100-channel output, each with its own frequency.
>>> sq = SquareOscillator([100 + 50 * n for n in range(100)])\n>>> print(sq.num_output_channels)\n100\n
"},{"location":"node/multichannel/#automatic-upmixing","title":"Automatic upmixing","text":"There are generally multiple inputs connected to a node, which may themselves have differing number of channels. For example, SquareOscillator(frequency=[100, 200, 300, 400, 500], width=0.7)
has a 5-channel input and a 1-channel input. In cases like this, the output of the nodes with fewer channels is upmixed to match the higher-channel inputs.
Upmixing here means simply duplicating the output until it reaches the desired number of channels. In the above case, the width
input will be upmixed to generate 5 channels, all containing 0.7
.
If width
were a stereo input with L and R channels, the output would be tiled, alternating between the channels. Each frame of stereo input would then be upmixed to contain [L, R, L, R, L]
, where L
and R
are the samples corresponding to the L and R channels.
The key rule is that, for nodes that support upmixing, the output signal has as many channels as the input signal with the highest channel count.
This process percolates through the signal chain. For example:
SquareOscillator(frequency=SineLFO([1, 3, 5], min=440, max=880),\n width=SawLFO([0.5, 0.6], min=0.25, max=0.75))\n
- The
min
and max
inputs of the frequency
LFO would be upmixed to 3 channels each - The
min
and max
inputs of the width
LFO would be upmixed to 2 channels each - Then, the output of the
width
node would be upmixed from 2 to 3 channels
"},{"location":"node/multichannel/#nodes-with-fixed-inputoutput-channels","title":"Nodes with fixed input/output channels","text":"Some nodes have immutable numbers of input/output channels. For example:
StereoPanner
has 1 input channel and 2 output channels StereoBalance
has 2 input channels and 2 output channels ChannelMixer
has an arbitrary number of input channels, but a fixed, user-specified number of output channels
Even Nodes that do not have an obvious input (e.g. BufferPlayer
) have input channels, for modulation inputs (for example, modulating the rate of the buffer).
When two nodes are connected together with incompatible channel counts (for example, connecting a StereoBalance
into a StereoMixer
), an InvalidChannelCountException
will be raised.
"},{"location":"node/multichannel/#the-channel-node-classes","title":"The Channel* node classes","text":"There are a number of Node subclasses dedicated to channel handling.
- ChannelArray: Concatenates the channels of multiple nodes, so that calling
ChannelMix
with nodes of N
and M
channels will produce an output of N + M
channels. - ChannelMixer: Reduces or expands the number of channels by evenly spreading the audio across the output channels.
- ChannelSelect: Selects sub-channels of the input, either individually or by group.
"},{"location":"node/multichannel/#querying-channel-subsets-with-the-index-operator","title":"Querying channel subsets with the index operator","text":"Single channels of a multi-channel node can be accessed using the index []
operator. For example:
square = SquareOscillator([440, 441, 442, 443])\noutput = square[0]\n# output now contains a mono output, with a frequency of 440Hz.\n
Slice syntax can be used to query multiple subchannels:
square = SquareOscillator([440, 441, 442, 880])\noutput = square[0:2]\n# now contains a two-channel square wave\n
\u2192 Next: Status and properties
"},{"location":"node/operators/","title":"Nodes","text":""},{"location":"node/operators/#node-operators","title":"Node operators","text":""},{"location":"node/operators/#arithmetic","title":"Arithmetic","text":"The output of multiple nodes can be combined using Python's mathematical operators. For example, to sum two sine waves together to create harmonics, use the +
operator:
output = SineOscillator(440) + SineOscillator(880)\noutput.play()\n
To modulate the amplitude of one node with another, use the *
operator:
sine = SineOscillator(440)\nenvelope = ASREnvelope(0.1, 1, 0.1)\noutput = sine * envelope\n
You can use constant values in place of Node
objects:
sine = SineOscillator(440)\nattenuated = sine * 0.5\n
Operators can be chained together in the normal way:
# Create an envelope that rises from 0.5 to 1.0 and back to 0.5\nenv = (ASREnvelope(0.1, 1, 0.1) * 0.5) + 0.5\n
Behind the scenes, these operators are actually creating composites of Node
subclasses. The last example could alternatively be written as:
Add(Multiply(ASREnvelope(0.1, 1, 0.1), 0.5), 0.5)\n
"},{"location":"node/operators/#comparison","title":"Comparison","text":"Comparison operators can also be used to compare two Node output values, generating a binary (1/0) output. For example:
# Generates an output of 1 when the sinusoid is above 0, and 0 otherwise \nSineOscillator(440) > 0\n
This can then be used as an input to other nodes. The below will generate a half-wave-rectified sine signal (that is, a sine wave with all negative values set to zero).
sine = SineOscillator(440)\nrectified = sine * (sine > 0)\n
"},{"location":"node/operators/#index-of-operators","title":"Index of operators","text":"Below is a full list of operators supported by SignalFlow.
"},{"location":"node/operators/#arithmetic-operators","title":"Arithmetic operators","text":"Operator Node class +
Add -
Subtract *
Multiply /
Divide **
Power %
Modulo"},{"location":"node/operators/#comparison-operators","title":"Comparison operators","text":"Operator Node class ==
Equal !=
NotEqual <
LessThan <=
LessThanOrEqual >
GreaterThan >=
GreaterThanOrEqual \u2192 Next: Multichannel
"},{"location":"node/playback/","title":"Nodes","text":""},{"location":"node/playback/#playing-and-stopping-a-node","title":"Playing and stopping a node","text":""},{"location":"node/playback/#starting-playback","title":"Starting playback","text":"To start a node playing, simply call the play()
method:
graph = AudioGraph()\nnode = SineOscillator(440)\nnode.play()\n
This connects the node to the output
endpoint of the current global AudioGraph
. The next time the graph processes a block of samples, the graph's output
node then calls upon the sine oscillator to generate a block.
It is important to remember that playing a node means \"connecting it to the graph\". For this reason, it is not possible to play the same node more than once, as it is already connected to the graph. To play multiples of a particular Node type, simply create and play multiple instances.
"},{"location":"node/playback/#connecting-a-node-to-another-nodes-input","title":"Connecting a Node to another Node's input","text":"It is often the case that you want to connect a Node to the input of another Node for playback, rather than simply wiring it to the output of a graph -- for example, to pass an oscillator through a processor. In this case, you do not need to call play()
(which means \"connect this node to the graph\"). Instead, it is sufficient to simply connect the Node to the input of another Node that is already playing.
For example:
# create and begin playback of a variable input summer, passed through a filter\nsum = Sum()\nflt = SVFilter(sum, \"low_pass\", 200)\nflt.play()\n
Now, let's create an oscillator. Observe that connecting the oscillator to the filter's input begins playback immediately.
square = SquareOscillator(100)\nsum.add_input(square)\n
"},{"location":"node/playback/#stopping-playback","title":"Stopping playback","text":"To stop a node playing:
node.stop()\n
This disconnects the node from the output device that it is connected to.
\u2192 Next: Inputs
"},{"location":"node/properties/","title":"Nodes","text":""},{"location":"node/properties/#node-properties","title":"Node properties","text":"A Node
has a number of read-only properties which can be used to query its status at a given moment in time.
Property Type Description name str Short alphanumeric string that identifies the type of node (for example, asr-envelope
) num_output_channels int The number of output channels that the node generates. num_input_channels int The number of input channels that the node takes. Note that most nodes have matches_input_channels
set, meaning that their num_input_channels
will be automatically increased according to their inputs. To learn more, see Nodes: Multichannel. matches_input_channels bool Whether the node automatically increases its num_input_channels
based on its inputs. To learn more, see Nodes: Multichannel. has_variable_inputs bool Whether the node supports an arbitrary number of audio-rate inputs output_buffer numpy.ndarray Contains the Node's most recent audio output, in float32
samples. The buffer is indexed by channel
x frame
, so to obtain the 32nd sample in the first channel, query: node.output_buffer[0][31]
. inputs dict A dict containing all of the Node
's audio-rate inputs. Note that buffer inputs are not currently included within this dict. state int The Node's current playback state, which can be one of SIGNALFLOW_NODE_STATE_ACTIVE
and SIGNALFLOW_NODE_STATE_STOPPED
. The STOPPED
state only applies to those nodes which have a finite duration (e.g. ASREnvelope
, or BufferPlayer
with looping disabled) and have reached the end of playback. Nodes continue to have a state of ACTIVE
whether or not they are connected to the graph. patch Patch Indicates the Patch that the node is part of, or None if the Node does not belong to a Patch."},{"location":"node/properties/#monitoring-a-nodes-output","title":"Monitoring a node's output","text":"To monitor the output of a node, call node.poll(num_seconds)
, where num_seconds
is the interval between messages. This will print the last sample generated by the node to stdout
. In the case of multichannel nodes, only the first channel's value is printed.
>>> a = Counter(Impulse(1))\n>>> a.poll(1)\n>>> a.play()\ncounter: 0.00000\ncounter: 1.00000\ncounter: 2.00000\n
To stop polling a node, call node.poll(0)
.
"},{"location":"node/properties/#node-specific-properties","title":"Node-specific properties","text":"Some Node
classes have additional properties, containing information on implementation-specific states. These can be accessed via the get_property
method.
For example, the BufferPlayer
node exposes a position
property, which returns the playhead's current position, in seconds.
>>> buffer = Buffer(\"audio.wav\")\n>>> player = BufferPlayer(buffer)\n>>> player.play()\n...\n>>> player.get_property(\"position\")\n5.984000205993652\n
\u2192 Next: Stochastic nodes
"},{"location":"node/stochastic/","title":"Nodes","text":""},{"location":"node/stochastic/#chance-and-stochastic-nodes","title":"Chance and stochastic nodes","text":"SignalFlow has a number of stochastic nodes, which make use of a pseudo-random number generator (RNG) to produce unpredictable output values.
Each object of these StochasticNode
subclasses stores its own RNG. By default, the RNG is seeded with a random value, so that each run will generate a different set of outputs. However, to create a repeatable pseudo-random output, the seed
of the node's RNG can be set to a known value:
>>> r = RandomUniform(0, 1)\n>>> r.process(1024)\n>>> r.output_buffer[0][:4]\narray([0.48836085, 0.64326525, 0.79819506, 0.8489549 ], dtype=float32)\n>>> r.set_seed(123)\n>>> r.process(1024)\n>>> r.output_buffer[0][:4]\narray([0.7129553 , 0.42847094, 0.6908848 , 0.7191503 ], dtype=float32)\n>>> r.set_seed(123)\n>>> r.process(1024)\n>>> r.output_buffer[0][:4]\narray([0.7129553 , 0.42847094, 0.6908848 , 0.7191503 ], dtype=float32)\n
Note the identical sequences generated after repeatedly setting the seed to a known value.
Warning
Calling node.process()
is generally not good practice, as it does not recursively process all of the node's inputs (unlike when a node is embedded within an AudioGraph, which correctly handles recursion and cyclical loops). Please use at your peril!
\u2192 Next: Node reference library
"},{"location":"patch/","title":"Patch","text":"Warning
This documentation is a work-in-progress and may have sections that are missing or incomplete.
A Patch
represents a connected group of Nodes
, analogous to a synthesizer. Defining patches makes it easy to create higher-level structures, which can then be reused and instantiated with a single line of code, in much the same way as a Node.
Behind the scenes, the structure of a Patch
is encapsulated by a PatchSpec
, a template which can be instantiated or serialised to a JSON file for later use.
- A Patch structure is defined either by declaring a Patch subclass or with a JSON specification file
- Play and stop a Patch by connecting it to the AudioGraph or the input of another Patch or Node
- Similar to nodes, a Patch can be modulated by audio-rate inputs, triggered by trigger inputs, and access sample data via buffer inputs
- The outputs of Patches can be altered or combined by normal Python operators
- The status of a Patch can be queried via its properties
- Patches can be exported and imported to JSON
- The auto-free mechanism allows Patches to automatically stop and free their memory after playback is complete
\u2192 Next: Defining a Patch
"},{"location":"patch/auto-free/","title":"Patch","text":""},{"location":"patch/auto-free/#auto-free-and-memory-management","title":"Auto-free and memory management","text":"Auto-free.
"},{"location":"patch/defining/","title":"Patch","text":""},{"location":"patch/defining/#defining-a-patch","title":"Defining a Patch","text":"A Patch is made up of a connected network of Nodes, together with a set of properties that determine how the Patch can be controlled.
There are two general ways to define the structure of a Patch:
- Create a new class that subclasses
Patch
. In general, this is the recommended approach for defining new Patches. - Create a JSON file that can be loaded as a
PatchSpec
, which describes the structure of a patch
"},{"location":"patch/defining/#creating-a-patch-subclass","title":"Creating a Patch subclass","text":"The quickest and most intuitive way to define a Patch
is by subclassing the Patch
class itself. Let's look at an example.
class Bleep (Patch):\n def __init__(self, frequency=880, duration=0.1):\n super().__init__()\n frequency = self.add_input(\"frequency\", frequency)\n duration = self.add_input(\"duration\", duration)\n sine = SineOscillator(frequency)\n env = ASREnvelope(0.001, duration, 0.001)\n output = sine * env\n self.set_output(output)\n self.set_auto_free(True)\n
In the above example:
- At the very start of the
__init__
function, super().__init__()
must be called to initialise the Patch and its storage. This is vital! Without it, your program will crash. - Two audio-rate input parameters are defined. The
add_input()
method is used to define them as inputs of the Patch
, which can then be subsequently modulated. Note that the add_input()
method returns a reference to the frequency node, which then acts as a pointer to the input node. self.set_output()
is used to define the Patch's output. A Patch can only have one single output. - Finally,
self.set_auto_free()
is used to automatically stop and free the Patch after playback of the envelope is completed. More about auto-free...
You can now instantiate a Bleep
object in just the same way as you would instantiate and play a Node:
b = Bleep(frequency=440, duration=0.2)\nb.play()\n
If you query graph.status
after playback has finished, you should see that the Patch
is automatically freed and the number of nodes returns to 0.
"},{"location":"patch/defining/#creating-a-patchspec-from-json","title":"Creating a PatchSpec from JSON","text":"The structure of a Patch
is described by a PatchSpec
, which can in turn be imported/exported in the JSON text-based data interchange format.
For information on loading or saving PatchSpecs as JSON, see Exporting and importing patches.
\u2192 Next: Playing and stopping a Patch
"},{"location":"patch/exporting/","title":"Patch","text":""},{"location":"patch/exporting/#exporting-and-importing-patches","title":"Exporting and importing patches","text":"A Patch can be exported or imported.
\u2192 Next: Auto-free and memory management
"},{"location":"patch/inputs/","title":"Patch","text":""},{"location":"patch/inputs/#patch-inputs","title":"Patch inputs","text":"Just like a Node, a Patch supports three different classes of input:
- Audio-rate inputs: Takes the output of another Node or Patch as an input, for continuous modulation of synthesis parameters
- Trigger inputs: Used to trigger discrete control events \u2014 for example, restarting buffer playback
- Buffer inputs: Used to pass the contents of an audio buffer to a patch \u2014 for example, as a source of audio samples, or an envelope shape
"},{"location":"patch/inputs/#audio-rate-inputs","title":"Audio-rate inputs","text":"A Patch supports any number of user-defined named inputs, which can be used to modulate the nodes within the patch.
Each input must be defined by calling add_input()
when the Patch is first defined, with an optional default value.
Info
Note that Patches do not yet support variable inputs.
When a Patch is playing, the value of its inputs can be set using patch.set_input()
:
class Bloop (Patch):\n def __init__(self, frequency=880, duration=0.1):\n super().__init__()\n frequency = self.add_input(\"frequency\", frequency)\n sine = SineOscillator(frequency)\n self.set_output(sine)\n self.set_auto_free(True)\n\nbloop = Bloop()\nbloop.play()\n...\nbloop.set_input(\"frequency\", 100)\n
Info
Note that Patches do not yet support setting inputs with Python properties (e.g. patch.prop_name = 123
), as is possible with node inputs.
"},{"location":"patch/inputs/#triggers","title":"Triggers","text":"When defining a Patch
, it is possible to define which Node should receive trigger()
events sent to the Patch. This is done with patch.set_trigger_node()
:
class Hat (Patch):\n def __init__(self, duration=0.1):\n super().__init__()\n duration = self.add_input(\"duration\", duration)\n noise = WhiteNoise()\n env = ASREnvelope(0.0001, 0.0, duration, curve=2)\n output = noise * env\n self.set_trigger_node(env)\n self.set_output(output)\n\nh = Hat()\nh.play()\n...\nh.trigger() # triggers a hit, resetting the ASREnvelope to its start point\n
This can be used to create a Patch
that stays connected to the AudioGraph and can be retriggered to play a hit.
Info
Note that Patches only presently support trigger events directed to a single node within the patch, and cannot route triggers to multiple different nodes.
"},{"location":"patch/inputs/#buffer-inputs","title":"Buffer inputs","text":"Buffer inputs can be declared at define time by calling self.add_buffer_input()
. Similar to add_input
, the return value is a placeholder Buffer
that can be used wherever you would normally pass a Buffer
:
class WobblyPlayer (Patch):\n def __init__(self, buffer):\n super().__init__()\n buffer = self.add_buffer_input(\"buffer\", buffer)\n rate = SineLFO(0.2, 0.5, 1.5)\n player = BufferPlayer(buffer, rate=rate, loop=True)\n self.set_output(player)\n\nbuffer = Buffer(\"examples/audio/stereo-count.wav\")\nplayer = WobblyPlayer(buffer)\nplayer.play()\n
The buffer can then be replaced at runtime by calling set_input()
:
player.set_input(\"buffer\", another_buffer)\n
\u2192 Next: Operators
"},{"location":"patch/operators/","title":"Patch","text":""},{"location":"patch/operators/#operators","title":"Operators","text":"The output of a Patch can be amplified, attenuated, combined, modulated and compared using Python operators, in much the same way as Node:
patch = Patch(patch_spec)\noutput = patch * 0.5\n
For a full list of the operators that can be applied to a Patch
, see Node operators.
\u2192 Next: Patch properties
"},{"location":"patch/playback/","title":"Patch","text":""},{"location":"patch/playback/#playing-a-patch","title":"Playing a Patch","text":"Once a Patch
has been defined or imported, it can be instantiated in two different ways depending on how it was defined:
- From a Patch subclass
- From a PatchSpec
"},{"location":"patch/playback/#from-a-patch-subclass","title":"From a Patch subclass","text":"The simplest way to instantiate a Patch is by defining it as a Patch subclass, and then instantiating it in the same way as a Node.
class Hat (Patch):\n def __init__(self, duration=0.1):\n super().__init__()\n duration = self.add_input(\"duration\", duration)\n noise = WhiteNoise()\n env = ASREnvelope(0.0001, 0.0, duration, curve=2)\n output = noise * env\n self.set_output(output)\n self.set_auto_free(True)\n\nhat = Hat()\nhat.play()\n
Once a Patch has finished, its state changes to SIGNALFLOW_PATCH_STATE_STOPPED
.
Just as with nodes, it is important to remember that playing a patch means \"connecting it to the graph\". For this reason, it is not possible to play the same patch more than once, as it is already connected to the graph.
To play multiples of a particular Patch
type, simply create and play multiple instances.
"},{"location":"patch/playback/#from-a-patchspec","title":"From a PatchSpec","text":"Once a PatchSpec
has been created or imported, it can be played by instantiating a Patch
with the PatchSpec
as an argument:
patch = Patch(patch_spec)\npatch.play()\n
"},{"location":"patch/playback/#connecting-a-patch-to-another-patchs-input","title":"Connecting a Patch to another Patch's input","text":"A Patch
can be connected to the input of another Patch
(or Node), in exactly the same way described in Connecting a Node to another Node's input.
Once you have got to grips with this paradigm, it becomes simple to build up sophisticated processing graphs by abstracting complex functionality within individual Patch
objects, and connecting them to one another.
"},{"location":"patch/playback/#stopping-a-patch","title":"Stopping a Patch","text":"As in Node playback, stopping a Patch disconnects it from the AudioGraph. Patches with auto-free are automatically stopped when their lifetimes ends. Patches with an unlimited lifespan must be stopped manually, with:
patch.stop()\n
This disconnects the Patch from its output.
\u2192 Next: Patch inputs
"},{"location":"patch/properties/","title":"Patch","text":""},{"location":"patch/properties/#patch-properties","title":"Patch properties","text":"Property Type Description nodes list A list of all of the Node objects that make up this Patch inputs dict A dict of key-value pairs corresponding to all of the (audio rate) inputs within the Patch state int The Patch's current playback state, which can be SIGNALFLOW_PATCH_STATE_ACTIVE
or SIGNALFLOW_PATCH_STATE_STOPPED
. graph AudioGraph A reference to the AudioGraph that the Patch is part of \u2192 Next: Exporting and importing patches
"},{"location":"planning/EXAMPLES/","title":"Examples","text":"[ ] Add signalflow-audio repo
[x] Hello world [x] Granular [ ] Additive synthesis [ ] FM synthesis [ ] Multichannel expansion (supersaw) [ ] Stochastic [ ] Filter [ ] Audio input [ ] Waveshaper / Clip / Fold [ ] Wavetable [x] 2D wavetable [ ] Buffer: Play [ ] Buffer: Record [ ] FFT: Tonality [ ] FFT: Convolution reverb [ ] Patch: Simple
[ ] Control: Mouse control
"},{"location":"planning/NAMING/","title":"NAMING","text":""},{"location":"planning/NAMING/#nodes","title":"NODES","text":"Generators - Oscillators - Wavetable - Waveforms (all wrappers around Wavetable with band-limiting) - SineOscillator - SquareOscillator - TriangleOscillator - SawOscillator - LFO (all wrappers around Wavetable) - SineLFO - SquareLFO - TriangleLFO - SawLFO - Buffer - BufferPlayer - BufferRecorder - Stochastic - Processors - Panners - ChannelMixer - LinearPanner - AzimuthPanner - ObjectPanner - Delay - AllpassDelay - Delay - Effects - EQ - Gate - Resampler - Waveshaper
Stochastic - Random signal generators - WhiteNoise - PinkNoise - BrownNoise - PerlinNoise - Random number generators (with clocked inputs) - RandomUniform - RandomLinear - RandomBrownian - RandomExponentialDist - RandomGaussian - RandomBeta - Random event generators - RandomImpulse
-- PATCHES - Patch - PatchDef
"},{"location":"planning/PLAN/","title":"PLAN","text":"doc writing guide - https://numpy.org/numpy-tutorials/content/tutorial-style-guide.html
- Overview
- Graphs, Nodes, Buffers, Patches
- Getting Started
- Nodes
- Inputs
- Channel upmixing
- Triggers
- Buffers
- Monitoring node status
- Chance and stochastic nodes
- Node class reference
- AudioGraph
- Global configuration
- Graph status
- Recording the audio output
- Buffers
- Why called before? Because can store (e.g.) control data, not just audio
- Buffer types
- Interpolation
- Creating buffers
- From a sound file
- From a sample array
- From a function
- Recording to buffers
- Audio data
- Control data
- Saving buffers
- Reading buffer data
- Patches
- Tutorials
- Topics
- Interactive sound design
- Sequencing and composition
- Live coding
- Controls and GUI
- MIDI control
- Offline processing
- Panning and spatial audio
- Spectral processing with FFT nodes
- Sonification
- Algorithmic composition
- Sequencing (using isobar)
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"SignalFlow: Explore sound synthesis and DSP with Python","text":"SignalFlow is a sound synthesis framework whose goal is to make it quick and intuitive to explore complex sonic ideas. It has a simple Python API, allowing for rapid prototyping in Jupyter notebooks or on the command-line. It comes with over 100 signal processing classes for creative exploration, from filters and delays to FFT-based spectral processing and Euclidean rhythm generators.
Its core is implemented in efficient C++11, with cross-platform hardware acceleration.
SignalFlow has robust support for macOS and Linux (including Raspberry Pi), and has work-in-progress support for Windows. The overall project is currently in alpha status, and interfaces may change without warning.
"},{"location":"#example","title":"Example","text":"Let's take a look at a minimal SignalFlow example. Here, we create and immediately start the AudioGraph
, construct a stereo sine oscillator with a short envelope, connect the oscillator to the graph's output, and run the graph indefinitely.
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope\noutput.play()\ngraph.wait()\n
This demo shows a few syntactical benefits that SignalFlow provides to make it easy to work with audio:
- The 2-item array of frequency values passed to
SineOscillator
is expanded to create a stereo, 2-channel output. If you passed a 10-item array, the output would have 10 channels. (Read more: Multichannel nodes) - Mathematical operators like
*
can be used to multiply, add, subtract or divide the output of nodes, and creates a new output Node that corresponds to the output of the operation. This example uses an envelope to modulate the amplitude of an oscillator. (Read more: Node operators) - Even through the envelope is mono and the oscillator is stereo, SignalFlow does the right thing and upmixes the envelope's values to create a stereo output, so that the same envelope shape is applied to the L and R channels of the oscillator, before creating a stereo output. This is called \"automatic upmixing\", and is handy when working with multichannel graphs. (Read more: Automatic upmixing)
In subsequent examples, we will skip the import
line and assume you have already imported everything from the signalflow
namespace.
Info
If you want to enforce separation of namespaces, you might want to do something like the below.
import signalflow as sf\n\ngraph = sf.AudioGraph()\nsine = sf.SineOscillator(440)\n...\n
"},{"location":"#overview","title":"Overview","text":"At its core, SignalFlow has a handful of key concepts.
- At the top level is the AudioGraph, which connects to the system's audio input/output hardware.
- The graph comprises of a network of Nodes, each of which performs a single function (for example, generating a cyclical waveform, or filtering an input node). Nodes are connected by input and output relationships: the output of one node may be used to control the frequency of another. As the output of the first node increases, the frequency of the second node increases correspondingly. This modulation is applied on a sample-by-sample basis: all modulation in SignalFlow happens at audio rate.
- Nodes may have multiple inputs, which determine which synthesis properties can be modulated at runtime.
- A node can also have Buffer properties, which contain audio waveform data that can be read and written to, for playback or recording of samples.
- Nodes can be grouped in a Patch, which is a user-defined configuration of nodes. A patch may have one or more named inputs that are defined by the user when creating the patch. Patches can be thought of like voices of a synthesizer. A patch can also be set to automatically remove itself from the graph when a specified node's playback is complete, which is important for automatic memory management.
"},{"location":"#next-steps","title":"Next steps","text":" - Installing SignalFlow
- Example code
"},{"location":"examples/","title":"Examples","text":"For code examples using SignalFlow, see GitHub.
To download the examples
folder locally:
import signalflow_examples\n\nsignalflow_examples.download_examples()\n
"},{"location":"license/","title":"License","text":"SignalFlow is under the MIT license.
This means that you are welcome to use it for any purpose, including commercial usage, but must include the copyright notice above in any copies or derivative works.
Please do let me know what you use it for!
"},{"location":"buffer/","title":"Buffers","text":"A Buffer
is an area of memory that stores single-channel or multi-channel data, which may represent an audio waveform or any other type of signal.
- A Buffer can be created from a sound file, an array of samples, a specified dimension, or the result of a function
- A Buffer can be saved to a sound file
- A Buffer can be passed to a Node or Patch as an input
- Buffer sample access can be performed by get/set/fill methods, or directly as a numpy array
- Buffers can be modified, combined and queried with standard arithmetic operators
- Buffers can be queried for a number of properties, including interpolation modes and total memory usage
- TODO: Different Buffer subclasses exist for specific operations, including
Buffer2D
, WaveshaperBuffer
and EnvelopeBuffer
- TODO: Playing a buffer, including sample rate conversion and interpolation
- TODO: Recording and rendering audio into a Buffer
"},{"location":"buffer/access/","title":"Accessing in memory","text":"The floating-point samples within a SignalFlow Buffer
can be read and written directly from Python.
"},{"location":"buffer/access/#using-get-and-set-methods","title":"Using get and set methods","text":"The get()
and set()
methods can be used to access individual samples, indexed by channel and frame offset.
# Create a 2-channel buffer\nbuf = Buffer(2, 256)\n\n# Set the sample in channel 1 at index 20 to 0.5\nbuf.set(1, 20, 0.5)\n\n# Confirm that the sample is set correctly\nassert buf.get(1, 20) == 0.5\n
"},{"location":"buffer/access/#as-a-numpy-array","title":"As a numpy array","text":"The .data
property of a Buffer
points to a numpy array of shape (num_channels, num_frames)
, which can be used to read or write the buffer's data in real time.
import time\n\n# Create and play a one-second silent buffer\nbuf = Buffer(2, graph.sample_rate)\nplayer = BufferPlayer(buf, loop=True)\nplayer.play()\n\n# Gradually add crackles to the buffer, which will be heard in real-time\nwhile True:\n buf.data[0][np.random.randint(0, graph.sample_rate)] = 1.0\n buf.data[1][np.random.randint(0, graph.sample_rate)] = 1.0\n time.sleep(1)\n
"},{"location":"buffer/access/#filling-a-buffer-with-the-result-of-a-function","title":"Filling a buffer with the result of a function","text":"Just like when creating a buffer, an existing buffer can be filled with the output of a Python function.
\u2192 Next: Arithmetic operators
"},{"location":"buffer/creating/","title":"Creating a Buffer","text":"A Buffer can be created from:
- a sound file
- an array of samples
- a specified dimension
- the result of a function
"},{"location":"buffer/creating/#loading-a-buffer-from-a-sound-file","title":"Loading a buffer from a sound file","text":"To load an audio buffer from a sound file, pass the file path to Buffer's constructor.
# Load and play a buffer\nbuf = Buffer(\"filename.wav\")\nplayer = BufferPlayer(buf)\nplayer.play()\n
The type of the audio file is automatically inferred from the type and contents. Supported formats include wav
, aif
, mp3
, ogg
, flac
, and many other audio formats.
Interally, file I/O is handled by libsndfile
. For a full list of supported files, see the libsndfile documentation.
"},{"location":"buffer/creating/#creating-a-buffer-from-an-array-of-samples","title":"Creating a buffer from an array of samples","text":"To create and initialise a buffer from an existing array of samples, pass the array to Buffer's constructor. Both native Python arrays and numpy
arrays are supported.
Note that audio samples should always range between -1.0
and 1.0
to avoid distortion.
# Initialise a buffer from a native 1D array containing a sawtooth wave\nsamples = [(n % 100) / 100 - 0.5 for n in range(44100)]\nbuf = Buffer(samples)\nplayer = BufferPlayer(buf)\nplayer.play()\n
If the array is 1D, a mono buffer will be created. If the array is 2D, a multichannel buffer will be created.
# Initialise a buffer from a numpy 2D array containing a stereo sine wave\nimport numpy as np\n\nt = np.linspace(0, 1, 44100)\nstereo = np.array([np.sin(220 * t * np.pi * 2),\n np.sin(225 * t * np.pi * 2)])\nbuf = Buffer(stereo * 0.1)\nplayer = BufferPlayer(buf)\nplayer.play()\n
"},{"location":"buffer/creating/#creating-an-empty-buffer","title":"Creating an empty buffer","text":"An empty buffer can be initialised by specifying its dimensions. All samples will be initialised to zero.
# Create an empty buffer with 2 channels containing 44100 samples each.\nbuf = Buffer(2, 44100)\n
"},{"location":"buffer/creating/#initialising-a-buffer-with-the-result-of-a-function","title":"Initialising a buffer with the result of a function","text":"A buffer can also be populated with the result of a Python function, which takes a single argument containing the index of the frame to be filled.
# Create a buffer containing a 440Hz ping\nimport numpy as np\nbuf = Buffer(1, graph.sample_rate,\n lambda frame: np.sin(frame * 440 * np.pi * 2 / graph.sample_rate) * (1 - frame / graph.sample_rate))\nplayer = BufferPlayer(buf)\nplayer.play()\n
\u2192 Next: Saving and exporting a buffer
"},{"location":"buffer/exporting/","title":"Saving and exporting a buffer","text":""},{"location":"buffer/exporting/#saving-to-a-sound-file","title":"Saving to a sound file","text":"To export a buffer's audio contents to a sound file, use the save()
method:
import numpy as np\nbuf = Buffer(np.sin(np.linspace(0, 1, graph.sample_rate) * 440 * np.pi * 2))\nbuf.save(\"buffer.wav\")\n
The output format will be automatically detected from the filename extension. Supported formats are presently wav
, aif
and flac
.
\u2192 Next: Passing a buffer as an input to a node or patch
"},{"location":"buffer/input/","title":"Passing a buffer as an input to a node or patch","text":"See:
- Node: Buffer inputs
- Patch: Buffer inputs
\u2192 Next: Accessing a buffer's data in memory
"},{"location":"buffer/operators/","title":"Arithmetic operators","text":"Buffers, like nodes, can be manipulated using Python's standard arithmetic operators.
For example, to attenuate a buffer, it can be multiplied by a constant value. A new Buffer
object is returned, with the same dimensions as the original, scaled by the coefficient.
input_buffer = Buffer(\"input.wav\")\nscaled_buffer = input_buffer * 0.5\n# `scaled_buffer` now contains an attenuated version of `input_buffer`\n
Below is a full list of operators supported by SignalFlow Buffer
objects.
Operator Node class +
Add -
Subtract *
Multiply /
Divide \u2192 Next: Buffer properties
"},{"location":"buffer/properties/","title":"Buffer properties","text":"A Buffer
has a number of read-only properties which can be used to query its status at a given moment in time.
Property Type Description num_frames int The number of frames (samples) in the buffer. channels int The number of channels in the buffer. sample_rate int The sample rate of the buffer. duration float The duration of the buffer, in seconds. filename str If the buffer has been loaded from/saved to a file, the absolute path to the file. interpolation_mode str The interpolation mode of the buffer. [LINK]"},{"location":"graph/","title":"The AudioGraph","text":"AudioGraph
is the global audio processing system that schedules and performs audio processing. It is comprised of an interconnected network of Node and Patch objects, which audio flows through.
Each time a new block of audio is requested by the system audio I/O layer, the AudioGraph
object is responsible for traversing the tree of nodes and generating new samples by calling each Node
's process
method.
Why 'Graph'?
You may be more familiar with \"graph\" being used to mean a data visualisation. In signal processing and discrete mathematics, the term \"graph\" is also used to denote a system of nodes related by connections. Read more: Graph Theory Basics (Lumen Learning).
\u2192 Next: Creating the graph
"},{"location":"graph/config/","title":"The AudioGraph","text":""},{"location":"graph/config/#graph-configuration","title":"Graph configuration","text":"There are a number of graph configuration parameters that can be used to change the global behaviour of the audio system. This can be done programmatically, via a config file, or via environmental variables.
Parameter Description output_backend_name The name of the audio output backend to use, which can be one of: jack
, alsa
, pulseaudio
, coreaudio
, wasapi
, dummy
. Defaults to the first of these found on the system. Typically only required for Linux. output_device_name The name of the audio output device to use. This must precisely match the device's name in your system. If not found, DeviceNotFoundException
is thrown when instantiating the graph. output_buffer_size The size of the hardware output audio buffer, in samples. A larger buffer reduces the chance of buffer overflows and glitches, but at the cost of higher latency. Note that this config option merely specifies the preferred output buffer size, which may not be available in the system hardware. To check the actual buffer size used by the AudioGraph, query graph.output_buffer_size
after instantiation. input_device_name The name of the input device to use. input_buffer_size The size of the hardware input audio buffer. sample_rate The audio sample rate to use. cpu_usage_limit Imposes a hard limit on the CPU usage permitted by SignalFlow. If the estimated (single-core) CPU usage exceeds this value, no more nodes or patches can be created until it returns to below the limit. Floating-point value between 0..1, where 0.5 means 50% CPU."},{"location":"graph/config/#configuring-the-graph-programmatically","title":"Configuring the graph programmatically","text":"To specify an alternative config, create and populate an AudioGraphConfig
object before the graph is started:
config = AudioGraphConfig()\nconfig.output_device_name = \"MacBook Pro Speakers\"\nconfig.sample_rate = 44100\nconfig.output_buffer_size = 2048\n\ngraph = AudioGraph(config)\n
"},{"location":"graph/config/#configuring-the-graph-via-signalflowconfig","title":"Configuring the graph via ~/.signalflow/config","text":"To specify a configuration that is used by all future SignalFlow sessions, create a file ~/.signalflow/config
, containing one or more of the \"Graph configuration\" fields listed above.
For example:
[audio]\nsample_rate = 48000\noutput_buffer_size = 256\ninput_buffer_size = 256\noutput_device_name = \"MacBook Pro Speakers\"\ninput_device_name = \"MacBook Pro Microphone\"\n
All fields are optional.
A quick and easy way to edit your config, or create a new config file, is by using the signalflow
command-line utility:
signalflow configure\n
This will use your default $EDITOR
to open the configuration, or pico
if no editor is specified.
"},{"location":"graph/config/#configuring-the-graph-via-environmental-variables","title":"Configuring the graph via environmental variables","text":"SignalFlow config can also be set by setting an environmental variable in your shell. Variable names are identical to the upper-case version of the config string, prefixed with SIGNALFLOW_
. For example:
export SIGNALFLOW_OUTPUT_DEVICE_NAME=\"MacBook Pro Speakers\"\nexport SIGNALFLOW_OUTPUT_BUFFER_SIZE=1024\n
"},{"location":"graph/config/#printing-the-current-config","title":"Printing the current config","text":"To print the current configuration to stdout:
graph.config.print()\n
\u2192 Next: Graph status and properties
"},{"location":"graph/creating/","title":"The AudioGraph","text":""},{"location":"graph/creating/#creating-the-graph","title":"Creating the graph","text":"Creating the graph is simple: graph = AudioGraph()
By default, a new AudioGraph
immediately connects to the system's default audio hardware device (via the integrated libsoundio
library), using the system's default sample rate and buffer size.
Info
Note that the AudioGraph is a singleton object: only one AudioGraph can be created, which is shared globally.
To prevent the graph from starting instantly (for example, if you want to use the graph in offline mode), pass start=False
to the constructor.
To configure graph playback or recording parameters, see AudioGraph: Configuration.
\u2192 Next: Graph configuration
"},{"location":"graph/properties/","title":"The AudioGraph","text":""},{"location":"graph/properties/#status-and-properties","title":"Status and properties","text":"A number of methods are provided to query the graph's current status and properties.
"},{"location":"graph/properties/#status","title":"Status","text":"Querying graph.status
returns a one-line description of the number of nodes and patches in the graph, and the estimated CPU and RAM usage:
>>> graph.status\nAudioGraph: 235 active nodes, 6 patches, 13.95% CPU usage, 34.91MB memory usage\n
To automatically poll and print the graph's status periodically, call graph.poll(interval)
, where interval
is in seconds:
>>> graph.poll(1)\nAudioGraph: 118 active nodes, 3 patches, 7.09% CPU usage, 34.91MB memory usage\nAudioGraph: 118 active nodes, 3 patches, 7.16% CPU usage, 34.91MB memory usage\nAudioGraph: 40 active nodes, 1 patch, 2.60% CPU usage, 34.91MB memory usage\n
To stop polling, call graph.poll(0)
.
"},{"location":"graph/properties/#structure","title":"Structure","text":"Querying graph.structure
returns a multi-line string describing every Node in the graph, their parameter values, and their connectivity structure.
>>> graph.structure\n * audioout-soundio\n input0:\n * linear-panner\n pan: 0.000000\n input:\n * multiply\n input1: 0.251189\n input0:\n * sine\n frequency: 440.000000\n
"},{"location":"graph/properties/#other-graph-properties","title":"Other graph properties","text":" graph.node_count
(int): Returns the current number of Nodes in the graph (including within patches) graph.patch_count
(int): Returns the current number of Patches in the graph cpu_usage
(float): Returns the current CPU usage, between 0.0 (0%) and 1.0 (100%). CPU usage can be lowered by increasing the output buffer size. memory_usage
(int): Returns the current RAM usage, in bytes. This is typically mostly used by waveform data in Buffers. num_output_channels
(int): Returns the graph's current output channel count, which is typically identical to the number of channels supported by the audio output device. output_buffer_size
(int): Returns the current hardware output buffer size, in bytes.
\u2192 Next: Recording graph output
"},{"location":"graph/recording/","title":"The AudioGraph","text":""},{"location":"graph/recording/#recording-the-audio-output-of-the-graph","title":"Recording the audio output of the graph","text":"Convenience methods are provided to make it easy to record the global audio output when rendering audio in real-time:
graph.start_recording(\"filename.wav\")\n...\ngraph.stop_recording()\n
To record output in formats other than the default stereo, start_recording
takes a num_channels
argument that can be used to specify an alternative channel count.
Note
At present, only .wav is supported as an output format for global audio recordings.
"},{"location":"graph/recording/#offline-non-real-time-rendering","title":"Offline (non-real-time) rendering","text":"It is also possible to perform non-real-time rendering of a synthesis graph, by synthesizing audio output to a Buffer
which can then be saved to disk:
# Create an AudioGraph with a dummy output device\ngraph = AudioGraph(output_device=AudioOut_Dummy(2))\n\n# Create a buffer that will be used to store the audio output\nbuffer = Buffer(2, graph.sample_rate * 4)\n\n# Create a synthesis graph to render\nfreq = SawLFO(1, 200, 400)\nsine = SineOscillator([freq, freq+10])\ngraph.play(sine)\n\n# Render to the buffer. Non-real-time, so happens instantaneously.\n# Note that the graph renders as many samples as needed to fill the buffer.\ngraph.render_to_buffer(buffer)\n\n# Write the buffer contents to a file\nbuffer.save(\"output.wav\")\n\n# Finally, tear down the buffer\ngraph.destroy()\n
\u2192 Next: Clearing and stopping the graph
"},{"location":"graph/stopping/","title":"The AudioGraph","text":""},{"location":"graph/stopping/#clearing-and-stopping-the-graph","title":"Clearing and stopping the graph","text":"To clear all nodes and patches from the graph but leave it running for further audio synthesis:
>>> graph.clear()\n
To stop the graph and pause audio I/O:
>>> graph.stop()\n
To permanently destroy the graph:
>>> graph.destroy()\n
"},{"location":"howto/","title":"Howto","text":"Warning
This documentation is a work-in-progress and may have sections that are missing or incomplete.
Tutorials on common tasks with SignalFlow.
"},{"location":"howto/midi/","title":"Howto: MIDI control","text":""},{"location":"howto/plotting/","title":"Howto: Plotting and visualisation","text":"The output of a SignalFlow AudioGraph can be plotted using the popular matplotlib plotting library.
To install the library: pip install matplotlib
import matplotlib.pyplot as plt\nimport numpy as np\nfrom signalflow import *\n\nconfig = AudioGraphConfig()\nconfig.output_buffer_size = 4096\ngraph = AudioGraph(output_device=AudioOut_Dummy(buffer_size=2048),\n config=config)\n\nosc = SawOscillator(500)\nosc.play()\nbuf = graph.render_to_new_buffer(4410)\n\n#--------------------------------------------------------------------------------\n# Plot graphs\n#--------------------------------------------------------------------------------\nfig, axs = plt.subplots(nrows=2, figsize=(12, 5), dpi=200)\naxs[0].plot(buf.data[0])\naxs[1].magnitude_spectrum(buf.data[0], Fs=graph.sample_rate)\n\nplt.show()\n
"},{"location":"howto/plotting/#output","title":"Output","text":""},{"location":"installation/","title":"Getting started","text":""},{"location":"installation/#requirements","title":"Requirements","text":"SignalFlow supports macOS, Linux (including Raspberry Pi), and has alpha support for Windows.
"},{"location":"installation/#installation","title":"Installation","text":""},{"location":"installation/#macos","title":"macOS","text":"If you're new to Python or getting started from scratch:
macOS: Easy install with Visual Studio Code
If you are an existing Python user and confident with the command line:
macOS: Install from the command line
"},{"location":"installation/#linux","title":"Linux","text":"Linux: Install from the command line
"},{"location":"installation/#examples","title":"Examples","text":"Several example scripts are included within the repo, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
"},{"location":"installation/command-line-generic/","title":"Command line generic","text":""},{"location":"installation/command-line-generic/#1-set-up-a-virtual-environment","title":"1. Set up a virtual environment","text":"Creating a new virtual environment for SignalFlow minimises the chances of conflict with other local Python installs.
python3 -m venv signalflow-env\nsource signalflow-env/bin/activate\n
"},{"location":"installation/command-line-generic/#2-install-signalflow","title":"2. Install SignalFlow","text":"Installing SignalFlow with pip
:
pip3 install signalflow\n
If the installation succeeds, you should see Successfully installed signalflow
.
"},{"location":"installation/command-line-generic/#3-line-test","title":"3. Line test","text":"The installation of SignalFlow includes a command-line tool, signalflow
, that can be used to test and configure the framework. Check that the installation has succeeded by playing a test tone through your default system audio output:
This may take a few seconds to run for the first time. To exit the test, press Ctrl-C (^C
).
signalflow test\n
"},{"location":"installation/command-line-generic/#4-hello-world","title":"4. Hello, world","text":"In your text editor, create a new .py
file containing the below code:
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope * 0.1\noutput.play()\ngraph.wait()\n
When you run the script, you should hear a short stereo \"ping\".
"},{"location":"installation/command-line-generic/#5-optional-interactive-notebooks-in-jupyter","title":"5. (Optional) Interactive notebooks in Jupyter","text":"A nice way to experiment with SignalFlow is by using Jupyter interactive notebooks.
Install Jupyter and register this virtual environment as a Jupyter kernel:
pip3 install jupyter\npython3 -m ipykernel install --name signalflow-env\n
Open a Jupyter notebook:
jupyter notebook\n
"},{"location":"installation/next-steps/","title":"Next steps","text":""},{"location":"installation/next-steps/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"installation/linux/","title":"Installation on Linux","text":"Linux: Install from the command line
"},{"location":"installation/linux/buttons/","title":"Buttons","text":"Linux: Install from the command line
"},{"location":"installation/linux/command-line/","title":"SignalFlow: Command-line installation for Linux","text":"SignalFlow currently supports Linux x86_64 and Raspberry Pi.
These instructions assume you have a working version of Python 3.8+.
"},{"location":"installation/linux/command-line/#1-set-up-a-virtual-environment","title":"1. Set up a virtual environment","text":"Creating a new virtual environment for SignalFlow minimises the chances of conflict with other local Python installs.
python3 -m venv signalflow-env\nsource signalflow-env/bin/activate\n
"},{"location":"installation/linux/command-line/#2-install-signalflow","title":"2. Install SignalFlow","text":"Installing SignalFlow with pip
:
pip3 install signalflow\n
If the installation succeeds, you should see Successfully installed signalflow
.
"},{"location":"installation/linux/command-line/#3-line-test","title":"3. Line test","text":"The installation of SignalFlow includes a command-line tool, signalflow
, that can be used to test and configure the framework. Check that the installation has succeeded by playing a test tone through your default system audio output:
This may take a few seconds to run for the first time. To exit the test, press Ctrl-C (^C
).
signalflow test\n
"},{"location":"installation/linux/command-line/#4-hello-world","title":"4. Hello, world","text":"In your text editor, create a new .py
file containing the below code:
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope * 0.1\noutput.play()\ngraph.wait()\n
When you run the script, you should hear a short stereo \"ping\".
"},{"location":"installation/linux/command-line/#5-optional-interactive-notebooks-in-jupyter","title":"5. (Optional) Interactive notebooks in Jupyter","text":"A nice way to experiment with SignalFlow is by using Jupyter interactive notebooks.
Install Jupyter and register this virtual environment as a Jupyter kernel:
pip3 install jupyter\npython3 -m ipykernel install --name signalflow-env\n
Open a Jupyter notebook:
jupyter notebook\n
"},{"location":"installation/linux/command-line/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"installation/macos/","title":"Installation on macOS","text":"If you're new to Python or getting started from scratch:
macOS: Easy install with Visual Studio Code
If you are an existing Python user and confident with the command line:
macOS: Install from the command line
"},{"location":"installation/macos/buttons/","title":"Buttons","text":"If you're new to Python or getting started from scratch:
macOS: Easy install with Visual Studio Code
If you are an existing Python user and confident with the command line:
macOS: Install from the command line
"},{"location":"installation/macos/command-line/","title":"SignalFlow: Command-line installation for macOS","text":"These instructions assume you have a working version of Python 3.8+, installed either via Homebrew or from Python.org.
"},{"location":"installation/macos/command-line/#1-set-up-a-virtual-environment","title":"1. Set up a virtual environment","text":"Creating a new virtual environment for SignalFlow minimises the chances of conflict with other local Python installs.
python3 -m venv signalflow-env\nsource signalflow-env/bin/activate\n
"},{"location":"installation/macos/command-line/#2-install-signalflow","title":"2. Install SignalFlow","text":"Installing SignalFlow with pip
:
pip3 install signalflow\n
If the installation succeeds, you should see Successfully installed signalflow
.
"},{"location":"installation/macos/command-line/#3-line-test","title":"3. Line test","text":"The installation of SignalFlow includes a command-line tool, signalflow
, that can be used to test and configure the framework. Check that the installation has succeeded by playing a test tone through your default system audio output:
This may take a few seconds to run for the first time. To exit the test, press Ctrl-C (^C
).
signalflow test\n
"},{"location":"installation/macos/command-line/#4-hello-world","title":"4. Hello, world","text":"In your text editor, create a new .py
file containing the below code:
from signalflow import *\n\ngraph = AudioGraph()\nsine = SineOscillator([440, 880])\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = sine * envelope * 0.1\noutput.play()\ngraph.wait()\n
When you run the script, you should hear a short stereo \"ping\".
"},{"location":"installation/macos/command-line/#5-optional-interactive-notebooks-in-jupyter","title":"5. (Optional) Interactive notebooks in Jupyter","text":"A nice way to experiment with SignalFlow is by using Jupyter interactive notebooks.
Install Jupyter and register this virtual environment as a Jupyter kernel:
pip3 install jupyter\npython3 -m ipykernel install --name signalflow-env\n
Open a Jupyter notebook:
jupyter notebook\n
"},{"location":"installation/macos/command-line/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"installation/macos/easy/","title":"SignalFlow: Easy install for macOS","text":"The simplest way to start exploring SignalFlow is with the free Visual Studio Code editor. Visual Studio Code can edit interactive \"Jupyter\" notebooks, which allow you to run and modify blocks of Python code in real-time, which is a great way to experiment live with audio synthesis.
You'll only need to do this installation process once. Once setup, experimenting with SignalFlow is as simple as opening Visual Studio Code.
"},{"location":"installation/macos/easy/#1-install-python","title":"1. Install Python","text":"Download and install the latest version of Python (currently 3.12).
Download Python
"},{"location":"installation/macos/easy/#2-download-and-install-visual-studio-code","title":"2. Download and install Visual Studio Code","text":"Download and install the latest version of Visual Studio Code.
Download Visual Studio Code
Once installed, open Applications
and run Visual Studio Code
.
"},{"location":"installation/macos/easy/#3-install-the-python-and-jupyter-extensions","title":"3. Install the Python and Jupyter extensions","text":"Visual Studio Code requires extensions to be installed to handle Python and Jupyter files.
In Visual Studio Code, select the Extensions
icon from in the far-left column (or press \u21e7\u2318X
), and install the Python
and Jupyter
extensions by searching for their names and clicking \"Install\" on each.
Once installation has finished, close the Extensions
tab.
"},{"location":"installation/macos/easy/#4-create-a-new-workspace","title":"4. Create a new workspace","text":"In Visual Studio code, create a new folder to contain your new SignalFlow project:
- Select
File \u2192 Open Folder...
- Select
New Folder
, and pick a name for your new project folder
Where to put your workspace
You can store your project workspace anywhere on your drive. The workspace can hold multiple notebooks, audio files, etc.
Trusted workspaces
If Visual Studio asks \"Do you trust the authors of the files in this folder?\", select \"Yes, I trust the authors\". This is a security mechanism to protect you against untrusted third-party code.
"},{"location":"installation/macos/easy/#5-create-a-notebook","title":"5. Create a notebook","text":"Select File \u2192 New File...
(^\u2325\u2318N
), and select Jupyter Notebook
. You should see the screen layout change to display an empty black text block (in Jupyter parlance, a \"cell\").
"},{"location":"installation/macos/easy/#6-create-a-python-virtual-environment-to-use","title":"6. Create a Python virtual environment to use","text":"Click the button marked Select Kernel
in the top right.
- Select
Python Environments...
- Select
Create Python Environment
- Select
Venv
- Finally, select the version of Python you just installed (
3.12.x
).
Multiple versions of Python?
If you already have one or more versions of Python installed, any version from Python 3.8 upwards is fine.
Visual Studio Code will launch into some activity, in which it is installing necessary libraries and creating a Python \"virtual environment\", which is an isolated area of the filesystem containing all the packages needed for this working space. Working in different virtual environments for different projects is good practice to minimise the likelihood of conflicts and disruptions.
When the setup is complete, the button in the top right should change to say .venv (Python 3.12.x)
.
Info
New notebooks created within this workspace will share the same Python virtual environment.
"},{"location":"installation/macos/easy/#7-install-signalflow","title":"7. Install SignalFlow","text":"In the first block, copy and paste the below:
%pip install signalflow\n
To run the cell, press ^\u21b5
(control-enter). After a minute, you should see some output saying Successfully installed signalflow
.
Running cells with '.venv' requires the ipykernel package.
If you are given a prompt that the ipykernel
package is required, press \"Install\" to install the package.
You're now all set to start writing code!
"},{"location":"installation/macos/easy/#8-start-writing-code","title":"8. Start writing code","text":"In a Jupyter interactive notebook, you can write and run multi-line blocks of Python code. Press enter
to edit the cell, delete its contents, and paste the below.
print(\"Hello\")\nprint(\"world!\")\n
Press ^\u21b5
(control-enter) to run the cell. You should see \"Hello world!\" appear below the cell.
Keyboard shortcuts
- Navigate between cells with the arrow keys
- Press
enter
to begin editing a cell, and escape
to end editing and move to select mode - In select mode, use
b
to add a cell after the current cell, and a
to add a cell before it - To evaluate a cell and move on to the next cell, use
\u21e7\u21b5
(shift-enter)
"},{"location":"installation/macos/easy/#9-signalflow-import-the-library-and-start-audio-processing","title":"9. SignalFlow: Import the library and start audio processing","text":"Clear the first cell, and replace it with:
from signalflow import *\n
Run the cell with ^\u21b5
. This command imports all of the SignalFlow commands and classes, and only needs to be run once per session.
Create a new cell by pressing b
, and in the new cell, run:
graph = AudioGraph()\n
This will create and start a new global audio processing graph, using the system's default audio output. You should see the name of the audio device printed to the notebook.
This also needs to be run once per session. In fact, only one global AudioGraph
object can be created.
"},{"location":"installation/macos/easy/#10-signalflow-make-some-sound","title":"10. SignalFlow: Make some sound","text":"We're finally ready to make some noise!
In a new cell, copy and paste the below:
sine = SineOscillator(440)\npanner = StereoPanner(sine, 0.0)\noutput = panner * 0.1\noutput.play()\n
This will create a simple sine wave oscillator, pan it over a stereo pair, attenuate it, and play it from the system's audio output. Hopefully you should now hear a tone playing from your speaker or headphones.
One of the benefits of coding interactively is that you can modify the parameters of a synthesis network while it is running. In a new cell, try modifying the frequency
property of the oscillator:
sine.frequency = 880\n
You should hear it increase in pitch. Try changing the value to something different and re-running the cell.
The pan
property of StereoPanner
controls its position in the stereo field from left to right, and can range from -1
to 1
:
panner.pan = -1\n
Finally, to stop the playback:
output.stop()\n
"},{"location":"installation/macos/easy/#next-steps","title":"Next steps","text":" - Examples: Several example scripts are available for SignalFlow, covering simple control and modulation, FM synthesis, sample granulation, MIDI control, chaotic functions, etc.
- Configuration: To configure your audio hardware, see AudioGraph configuration.
- Tutorials: Coming soon
"},{"location":"library/","title":"Node reference library","text":""},{"location":"library/#analysis","title":"Analysis","text":" - CrossCorrelate: Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample.
- NearestNeighbour: Nearest Neighbour.
- OnsetDetector: Simple time-domain onset detector. Outputs an impulse when an onset is detected in the input. Maintains short-time and long-time averages. An onset is registered when the short-time average is threshold x the long-time average. min_interval is the minimum interval between onsets, in seconds.
- VampAnalysis: Feature extraction using the Vamp plugin toolkit.
"},{"location":"library/#buffer","title":"Buffer","text":" - BeatCutter: Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities.
- BufferLooper: Read and write from a buffer concurrently, with controllable overdub.
- BufferPlayer: Plays the contents of the given buffer.
start_time
/end_time
are in seconds. When a clock
signal is received, rewinds to the start_time
. Set clock
to 0
to prevent the buffer from being triggered immediately. - BufferRecorder: Records the input to a buffer. feedback controls overdub.
- FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
- FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
- SegmentPlayer: Trigger segments of a buffer at the given onset positions.
"},{"location":"library/#buffer-granulation","title":"Buffer: Granulation","text":" - SegmentedGranulator: Segmented Granulator.
- Granulator: Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. If
wrap
is true, grain playback can wrap around the end/start of the buffer.
"},{"location":"library/#control","title":"Control","text":" - MouseX: Outputs the normalised cursor X position, from 0 to 1. Currently only supported on macOS.
- MouseY: Outputs the normalised cursor Y position, from 0 to 1. Currently only supported on macOS.
- MouseDown: Outputs 1 if the left mouse button is down, 0 otherwise. Currently only supported on macOS.
"},{"location":"library/#envelope","title":"Envelope","text":" - ADSREnvelope: Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero.
- ASREnvelope: Attack-sustain-release envelope.
- DetectSilence: Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete.
- Envelope: Generic envelope constructor, given an array of levels, times and curves.
- Line: Line segment with the given start/end values, and duration (in seconds). If loop is true, repeats indefinitely. Retriggers on a clock signal.
- RectangularEnvelope: Rectangular envelope with the given sustain duration.
"},{"location":"library/#fft","title":"FFT","text":" - FFTContinuousPhaseVocoder: Continuous phase vocoder. Requires an FFT* input.
- FFTConvolve: Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
- FFTContrast: FFT Contrast. Requires an FFT* input.
- FFTMagnitudePhaseArray: Fixed mag/phase array.
- FFTRandomPhase: Randomise phase values.
- FFTScaleMagnitudes: Randomise phase values.
- FFTTransform: Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input.
- FFT: Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output.
- FFTFindPeaks: Find peaks in the FFT magnitude spectrum. Requires an FFT* input.
- IFFT: Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output.
- FFTLPF: FFT-based brick wall low pass filter. Requires an FFT* input.
- FFTNoiseGate: FFT-based noise gate. Requires an FFT* input.
- FFTPhaseVocoder: Phase vocoder. Requires an FFT* input.
- FFTTonality: Tonality filter. Requires an FFT* input.
- FFTZeroPhase: Remove phase information from a frequency-domain input. Requires an FFT* input.
"},{"location":"library/#operators","title":"Operators","text":" - Add: Add each sample of a to each sample of b. Can also be written as a + b
- AmplitudeToDecibels: Map a linear amplitude value to decibels.
- DecibelsToAmplitude: DecibelsToAmplitude
- ChannelArray: Takes an array of inputs and spreads them across multiple channels of output.
- ChannelCrossfade: Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output.
- ChannelMixer: Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels.
- ChannelSelect: Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step.
- Equal: Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b
- NotEqual: Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b
- GreaterThan: Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b
- GreaterThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b
- LessThan: Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b
- LessThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b
- Modulo: Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b
- Abs: Outputs the absolute value of a, per sample. Can also be written as abs(a)
- If: Outputs value_if_true for each non-zero value of a, value_if_false for all other values.
- Divide: Divide each sample of a by each sample of b. Can also be written as a / b
- FrequencyToMidiNote: Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output.
- MidiNoteToFrequency: Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input.
- Multiply: Multiply each sample of a by each sample of b. Can also be written as a * b
- Pow: Outputs a to the power of b, per sample. Can also be written as a ** b
- RoundToScale: Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named)
- Round: Round the input to the nearest integer value.
- ScaleLinExp: Scales the input from a linear range (between a and b) to an exponential range (between c and d).
- ScaleLinLin: Scales the input from a linear range (between a and b) to a linear range (between c and d).
- Subtract: Subtract each sample of b from each sample of a. Can also be written as a - b
- Sum: Sums the output of all of the input nodes, by sample.
- TimeShift: TimeShift
- Sin: Outputs sin(a), per sample.
- Cos: Outputs cos(a), per sample.
- Tan: Outputs tan(a), per sample.
- Tanh: Outputs tanh(a), per sample. Can be used as a soft clipper.
"},{"location":"library/#oscillators","title":"Oscillators","text":" - Impulse: Produces a value of 1 at the given
frequency
, with output of 0 at all other times. If frequency is 0, produces a single impulse. - SawLFO: Produces a sawtooth LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SawOscillator: Produces a (non-band-limited) sawtooth wave, with the given
frequency
and phase
offset. When a reset
or trigger is received, resets the phase to zero. - SineLFO: Produces a sinusoidal LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SineOscillator: Produces a sine wave at the given
frequency
. - SquareLFO: Produces a pulse wave LFO with the given
frequency
and pulse width
, ranging from min
to max
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - SquareOscillator: Produces a pulse wave with the given
frequency
and pulse width
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - TriangleLFO: Produces a triangle LFO with the given
frequency
and phase
offset, ranging from min
to max
. - TriangleOscillator: Produces a triangle wave with the given
frequency
. - Wavetable: Plays the wavetable stored in buffer at the given
frequency
and phase
offset. sync
can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing. - Wavetable2D: Wavetable2D
"},{"location":"library/#processors","title":"Processors","text":" - Clip: Clip the input to
min
/max
. - Fold: Fold the input beyond
min
/max
, reflecting the excess back. - Smooth: Smooth the input with a given smoothing coefficient. When
smooth
= 0, applies no smoothing. - WetDry: Takes
wet
and dry
inputs, and outputs a mix determined by wetness
. - Wrap: Wrap the input beyond
min
/max
.
"},{"location":"library/#processors-delays","title":"Processors: Delays","text":" - AllpassDelay: All-pass delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - CombDelay: Comb delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - OneTapDelay: Single-tap delay line.
delay_time
must be less than or equal to max_delay_time
. - Stutter: Stutters the input whenever a trigger is received on
clock
. Generates stutter_count
repeats, with duration of stutter_time
.
"},{"location":"library/#processors-distortion","title":"Processors: Distortion","text":" - Resample: Resampler and bit crusher.
sample_rate
is in Hz, bit_rate
is an integer between 0 and 16. - SampleAndHold: Samples and holds the input each time a trigger is received on
clock
. - Squiz: Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler.
- WaveShaper: Applies wave-shaping as described in the WaveShaperBuffer
buffer
.
"},{"location":"library/#processors-dynamics","title":"Processors: Dynamics","text":" - Compressor: Dynamic range compression, with optional
sidechain
input. When the input amplitude is above threshold
, compresses the amplitude with the given ratio
, following the given attack_time
and release_time
in seconds. - Gate: Outputs the input value when it is above the given
threshold
, otherwise zero. - Maximiser: Gain maximiser.
- RMS: Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size.
"},{"location":"library/#processors-filters","title":"Processors: Filters","text":" - BiquadFilter: Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter.
- DCFilter: Remove low-frequency and DC content from a signal.
- EQ: Three-band EQ.
- MoogVCF: Moog ladder low-pass filter.
- SVFilter: State variable filter.
filter_type
can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. resonance
should be between [0..1]
.
"},{"location":"library/#processors-panning","title":"Processors: Panning","text":" - AzimuthPanner: Pan input around an equally-spaced ring of
num_channels
speakers. pan
is the pan position from -1..+1, where 0 = centre front. width
is the source's width, where 1.0 spans exactly between an adjacent pair of channels. - ChannelPanner: Pan the input between a linear series of channels, where
pan
0 = channel 0, 1 = channel 1, etc. No wrapping is applied. - SpatialPanner: Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported.
- StereoBalance: Takes a stereo input and rebalances it, where
balance
of 0
is unchanged, -1
is hard left, and 1
is hard right. - StereoPanner: Pans a mono input to a stereo output.
pan
should be between -1 (hard left) to +1 (hard right), with 0 = centre. - StereoWidth: Reduces the width of a stereo signal. When
width
= 1, input is unchanged. When width
= 0, outputs a pair of identical channels both containing L+R.
"},{"location":"library/#sequencing","title":"Sequencing","text":" - ClockDivider: When given a
clock
input (e.g., an Impulse), divides the clock by the given factor
. factor must be an integer greater than or equal to 1. - Counter: Count upwards from
min
to max
, driven by clock
. - Euclidean: Euclidean rhythm as described by Toussaint, with
sequence_length
(n) and num_events
(k), driven by clock
. - FlipFlop: Flips from 0/1 on each
clock
. - ImpulseSequence: Each time a
clock
or trigger is received, outputs the next value in sequence
. At all other times, outputs zero. - Index: Outputs the value in
list
corresponding to index
. - Latch: Initially outputs 0. When a trigger is received at
set
, outputs 1. When a trigger is subsequently received at reset
, outputs 0, until the next set
. - Sequence: Outputs the elements in
sequence
, incrementing position on each clock
.
"},{"location":"library/#stochastic","title":"Stochastic","text":" - Logistic: Logistic noise.
- PinkNoise: Pink noise, with specified low/high cutoffs.
- RandomBrownian: Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick.
- RandomChoice: Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick.
- RandomCoin: Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick.
- RandomExponentialDist: Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick.
- RandomExponential: Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick.
- RandomGaussian: Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick.
- RandomImpulseSequence: Generates a random sequence of 0/1 bits with the given length, and the given probability each each bit = 1. The position of the sequence is incremented on each clock signal. explore and generate are trigger inputs which cause the sequence to mutate and re-generate respectively.
- RandomImpulse: Generate random impulses at the given frequency, with either uniform or poisson distribution.
- RandomUniform: Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick.
- WhiteNoise: Generates whitenoise between min/max. If frequency is zero, generates at audio rate. For frequencies lower than audio rate, interpolate applies linear interpolation between values, and random_interval specifies whether new random values should be equally-spaced or randomly-spaced.
"},{"location":"library/analysis/","title":"Analysis","text":"Reference library > Analysis
"},{"location":"library/analysis/#analysis","title":"Analysis","text":" - CrossCorrelate: Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample.
- NearestNeighbour: Nearest Neighbour.
- OnsetDetector: Simple time-domain onset detector. Outputs an impulse when an onset is detected in the input. Maintains short-time and long-time averages. An onset is registered when the short-time average is threshold x the long-time average. min_interval is the minimum interval between onsets, in seconds.
- VampAnalysis: Feature extraction using the Vamp plugin toolkit.
"},{"location":"library/analysis/crosscorrelate/","title":"CrossCorrelate node documentation","text":"Reference library > Analysis > CrossCorrelate
"},{"location":"library/analysis/crosscorrelate/#crosscorrelate","title":"CrossCorrelate","text":"CrossCorrelate(input=None, buffer=None, hop_size=0)\n
Outputs the cross-correlation of the input signal with the given buffer. If hop_size is zero, calculates the cross-correlation every sample.
"},{"location":"library/analysis/nearestneighbour/","title":"NearestNeighbour node documentation","text":"Reference library > Analysis > NearestNeighbour
"},{"location":"library/analysis/nearestneighbour/#nearestneighbour","title":"NearestNeighbour","text":"NearestNeighbour(buffer=None, target=0.0)\n
Nearest Neighbour.
"},{"location":"library/analysis/onsetdetector/","title":"OnsetDetector node documentation","text":"Reference library > Analysis > OnsetDetector
"},{"location":"library/analysis/onsetdetector/#onsetdetector","title":"OnsetDetector","text":"OnsetDetector(input=0.0, threshold=2.0, min_interval=0.1)\n
Simple time-domain onset detector. Outputs an impulse when an onset is detected in the input. Maintains short-time and long-time averages. An onset is registered when the short-time average is threshold x the long-time average. min_interval is the minimum interval between onsets, in seconds.
"},{"location":"library/analysis/vampanalysis/","title":"VampAnalysis node documentation","text":"Reference library > Analysis > VampAnalysis
"},{"location":"library/analysis/vampanalysis/#vampanalysis","title":"VampAnalysis","text":"VampAnalysis(input=0.0, plugin_id=\"vamp-example-plugins:spectralcentroid:linearcentroid\")\n
Feature extraction using the Vamp plugin toolkit.
"},{"location":"library/buffer/","title":"Buffer","text":"Reference library > Buffer
"},{"location":"library/buffer/#buffer","title":"Buffer","text":" - BeatCutter: Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities.
- BufferLooper: Read and write from a buffer concurrently, with controllable overdub.
- BufferPlayer: Plays the contents of the given buffer.
start_time
/end_time
are in seconds. When a clock
signal is received, rewinds to the start_time
. Set clock
to 0
to prevent the buffer from being triggered immediately. - BufferRecorder: Records the input to a buffer. feedback controls overdub.
- FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
- FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
- SegmentPlayer: Trigger segments of a buffer at the given onset positions.
"},{"location":"library/buffer/beatcutter/","title":"BeatCutter node documentation","text":"Reference library > Buffer > BeatCutter
"},{"location":"library/buffer/beatcutter/#beatcutter","title":"BeatCutter","text":"BeatCutter(buffer=None, segment_count=8, stutter_probability=0.0, stutter_count=1, jump_probability=0.0, duty_cycle=1.0, rate=1.0, segment_rate=1.0)\n
Cuts a buffer into segment_count segments, and stutters/jumps with the given probabilities.
"},{"location":"library/buffer/bufferlooper/","title":"BufferLooper node documentation","text":"Reference library > Buffer > BufferLooper
"},{"location":"library/buffer/bufferlooper/#bufferlooper","title":"BufferLooper","text":"BufferLooper(buffer=None, input=0.0, feedback=0.0, loop_playback=false, loop_record=false)\n
Read and write from a buffer concurrently, with controllable overdub.
"},{"location":"library/buffer/bufferplayer/","title":"BufferPlayer node documentation","text":"Reference library > Buffer > BufferPlayer
"},{"location":"library/buffer/bufferplayer/#bufferplayer","title":"BufferPlayer","text":"BufferPlayer(buffer=None, rate=1.0, loop=0, start_time=None, end_time=None, clock=None)\n
Plays the contents of the given buffer. start_time
/end_time
are in seconds. When a clock
signal is received, rewinds to the start_time
. Set clock
to 0
to prevent the buffer from being triggered immediately.
"},{"location":"library/buffer/bufferrecorder/","title":"BufferRecorder node documentation","text":"Reference library > Buffer > BufferRecorder
"},{"location":"library/buffer/bufferrecorder/#bufferrecorder","title":"BufferRecorder","text":"BufferRecorder(buffer=None, input=0.0, feedback=0.0, loop=false)\n
Records the input to a buffer. feedback controls overdub.
"},{"location":"library/buffer/feedbackbufferreader/","title":"FeedbackBufferReader node documentation","text":"Reference library > Buffer > FeedbackBufferReader
"},{"location":"library/buffer/feedbackbufferreader/#feedbackbufferreader","title":"FeedbackBufferReader","text":"FeedbackBufferReader(buffer=None)\n
Counterpart to FeedbackBufferWriter.
"},{"location":"library/buffer/feedbackbufferwriter/","title":"FeedbackBufferWriter node documentation","text":"Reference library > Buffer > FeedbackBufferWriter
"},{"location":"library/buffer/feedbackbufferwriter/#feedbackbufferwriter","title":"FeedbackBufferWriter","text":"FeedbackBufferWriter(buffer=None, input=0.0, delay_time=0.1)\n
Counterpart to FeedbackBufferReader.
"},{"location":"library/buffer/grainsegments/","title":"GrainSegments node documentation","text":"Reference library > Buffer > GrainSegments
"},{"location":"library/buffer/grainsegments/#grainsegments","title":"GrainSegments","text":"GrainSegments(buffer=None, clock=0, target=0, offsets={}, values={}, durations={})\n
GrainSegments
"},{"location":"library/buffer/granulation/","title":"Index","text":"Reference library > Buffer: Granulation
"},{"location":"library/buffer/granulation/#buffer-granulation","title":"Buffer: Granulation","text":" - SegmentedGranulator: Segmented Granulator.
- Granulator: Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. If
wrap
is true, grain playback can wrap around the end/start of the buffer.
"},{"location":"library/buffer/granulation/granulator/","title":"Granulator node documentation","text":"Reference library > Buffer: Granulation > Granulator
"},{"location":"library/buffer/granulation/granulator/#granulator","title":"Granulator","text":"Granulator(buffer=None, clock=0, pos=0, duration=0.1, pan=0.0, rate=1.0, max_grains=2048, wrap=false)\n
Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo. If wrap
is true, grain playback can wrap around the end/start of the buffer.
"},{"location":"library/buffer/granulation/segmentedgranulator/","title":"SegmentedGranulator node documentation","text":"Reference library > Buffer: Granulation > SegmentedGranulator
"},{"location":"library/buffer/granulation/segmentedgranulator/#segmentedgranulator","title":"SegmentedGranulator","text":"SegmentedGranulator(buffer=None, onset_times={}, durations={}, index=0.0, rate=1.0, clock=0, max_grains=2048)\n
Segmented Granulator.
"},{"location":"library/buffer/granulator/","title":"Granulator node documentation","text":"Reference library > Buffer > Granulator
"},{"location":"library/buffer/granulator/#granulator","title":"Granulator","text":"Granulator(buffer=None, clock=0, pos=0, duration=0.1, pan=0.0, rate=1.0, max_grains=2048)\n
Granulator. Generates a grain from the given buffer each time a clock signal is received, with the given duration/rate/pan parameters. The input buffer can be mono or stereo.
"},{"location":"library/buffer/segmentplayer/","title":"SegmentPlayer node documentation","text":"Reference library > Buffer > SegmentPlayer
"},{"location":"library/buffer/segmentplayer/#segmentplayer","title":"SegmentPlayer","text":"SegmentPlayer(buffer=None, onsets={}, index=None, rate=1.0, clock=None)\n
Trigger segments of a buffer at the given onset positions.
"},{"location":"library/control/","title":"Control","text":"Reference library > Control
"},{"location":"library/control/#control","title":"Control","text":" - MouseX: Outputs the normalised cursor X position, from 0 to 1. Currently only supported on macOS.
- MouseY: Outputs the normalised cursor Y position, from 0 to 1. Currently only supported on macOS.
- MouseDown: Outputs 1 if the left mouse button is down, 0 otherwise. Currently only supported on macOS.
"},{"location":"library/control/mousedown/","title":"MouseDown node documentation","text":"Reference library > Control > MouseDown
"},{"location":"library/control/mousedown/#mousedown","title":"MouseDown","text":"MouseDown(button_index=0)\n
Outputs 1 if the left mouse button is down, 0 otherwise. Currently only supported on macOS.
"},{"location":"library/control/mousedown/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# When the left mouse button is clicked, as detected by MouseDown(), an LFO is \n# applied to the oscillator's frequency.\n#-------------------------------------------------------------------------------\nlfo = SineLFO(5, 100, 600)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
#-------------------------------------------------------------------------------\n# A simple wobbling synthesiser controlled using the mouse. When the mouse is \n# clicked, as detected by MouseDown(), an LFO is activated and affects the \n# oscillator's frequency. MouseX position changes the rate of the LFO. MouseY \n# position changes the upper frequency limit, affecting pitch.\n#-------------------------------------------------------------------------------\nrate = MouseX() * 10\nupper_limit = MouseY() * 1500\nlfo = SineLFO(rate, 100, upper_limit)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
"},{"location":"library/control/mousex/","title":"MouseX node documentation","text":"Reference library > Control > MouseX
"},{"location":"library/control/mousex/#mousex","title":"MouseX","text":"MouseX()\n
Outputs the normalised cursor X position, from 0 to 1. Currently only supported on macOS.
"},{"location":"library/control/mousex/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using the MouseX position to change the rate of an LFO, which is modulating an\n# oscillator's frequency.\n#-------------------------------------------------------------------------------\nlfo_rate = MouseX() * 10\nfrequency = SineLFO(lfo_rate, 100, 600)\nosc = TriangleOscillator(frequency)\nosc.play()\n
#-------------------------------------------------------------------------------\n# A simple wobbling synthesiser controlled using the mouse. When the mouse is \n# clicked, as detected by MouseDown(), an LFO is activated and affects the \n# oscillator's frequency. MouseX position changes the rate of the LFO. MouseY \n# position changes the upper frequency limit, affecting pitch.\n#-------------------------------------------------------------------------------\nrate = MouseX() * 10\nupper_limit = MouseY() * 1500\nlfo = SineLFO(rate, 100, upper_limit)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
"},{"location":"library/control/mousey/","title":"MouseY node documentation","text":"Reference library > Control > MouseY
"},{"location":"library/control/mousey/#mousey","title":"MouseY","text":"MouseY()\n
Outputs the normalised cursor Y position, from 0 to 1. Currently only supported on macOS.
"},{"location":"library/control/mousey/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using the MouseY position to change the frequency of an oscillator.\n#-------------------------------------------------------------------------------\nfrequency = MouseY() * 1000\nosc = TriangleOscillator(frequency)\nosc.play()\n
#-------------------------------------------------------------------------------\n# A simple wobbling synthesiser controlled using the mouse. When the mouse is \n# clicked, as detected by MouseDown(), an LFO is activated and affects the \n# oscillator's frequency. MouseX position changes the rate of the LFO. MouseY \n# position changes the upper frequency limit, affecting pitch.\n#-------------------------------------------------------------------------------\nrate = MouseX() * 10\nupper_limit = MouseY() * 1500\nlfo = SineLFO(rate, 100, upper_limit)\nfrequency = If(MouseDown(), lfo, 100)\nosc = TriangleOscillator(frequency)\nosc.play()\n
"},{"location":"library/envelope/","title":"Envelope","text":"Reference library > Envelope
"},{"location":"library/envelope/#envelope","title":"Envelope","text":" - ADSREnvelope: Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero.
- ASREnvelope: Attack-sustain-release envelope.
- DetectSilence: Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete.
- Envelope: Generic envelope constructor, given an array of levels, times and curves.
- Line: Line segment with the given start/end values, and duration (in seconds). If loop is true, repeats indefinitely. Retriggers on a clock signal.
- RectangularEnvelope: Rectangular envelope with the given sustain duration.
"},{"location":"library/envelope/adsrenvelope/","title":"ADSREnvelope node documentation","text":"Reference library > Envelope > ADSREnvelope
"},{"location":"library/envelope/adsrenvelope/#adsrenvelope","title":"ADSREnvelope","text":"ADSREnvelope(attack=0.1, decay=0.1, sustain=0.5, release=0.1, gate=0)\n
Attack-decay-sustain-release envelope. Sustain portion is held until gate is zero.
"},{"location":"library/envelope/asrenvelope/","title":"ASREnvelope node documentation","text":"Reference library > Envelope > ASREnvelope
"},{"location":"library/envelope/asrenvelope/#asrenvelope","title":"ASREnvelope","text":"ASREnvelope(attack=0.1, sustain=0.5, release=0.1, curve=1.0, clock=None)\n
Attack-sustain-release envelope.
"},{"location":"library/envelope/asrenvelope/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using an ASR Envelope to shape a square wave oscillator\n#-------------------------------------------------------------------------------\nosc = SquareOscillator(500)\nenvelope = ASREnvelope(0.1, 0.0, 0.5)\noutput = osc * envelope\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using ASREnvelope to shape the sound of an oscillator over time.\n# The Line node generates a continuously-changing value which we use as the \n# release time.\n#-------------------------------------------------------------------------------\nclock = Impulse(8.0)\nCMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8\nFMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8\narpeggios = CMaj7 + FMaj9\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nrelease = Line(0.1, 0.5, 6, True)\nenvelope = ASREnvelope(attack=0.0, \n sustain=0.0, \n release=release, \n curve=1.0, \n clock=clock)\nvoice = oscillator * envelope\n\npan = SineLFO(0.1667, -1.0, 1.0)\noutput = StereoPanner(voice, pan)\noutput.play()\n
"},{"location":"library/envelope/detectsilence/","title":"DetectSilence node documentation","text":"Reference library > Envelope > DetectSilence
"},{"location":"library/envelope/detectsilence/#detectsilence","title":"DetectSilence","text":"DetectSilence(input=None, threshold=0.00001)\n
Detects blocks of silence below the threshold value. Used as an auto-free node to terminate a Patch after processing is complete.
"},{"location":"library/envelope/envelope/","title":"Envelope node documentation","text":"Reference library > Envelope > Envelope
"},{"location":"library/envelope/envelope/#envelope","title":"Envelope","text":"Envelope(levels=std::vector<NodeRef> ( ), times=std::vector<NodeRef> ( ), curves=std::vector<NodeRef> ( ), clock=None, loop=false)\n
Generic envelope constructor, given an array of levels, times and curves.
"},{"location":"library/envelope/line/","title":"Line node documentation","text":"Reference library > Envelope > Line
"},{"location":"library/envelope/line/#line","title":"Line","text":"Line(start=0.0, end=1.0, time=1.0, loop=0, clock=None)\n
Line segment with the given start/end values, and duration (in seconds). If loop is true, repeats indefinitely. Retriggers on a clock signal.
"},{"location":"library/envelope/line/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using a line to control the gain of an oscillator, emulating a sidechain \n# ducking effect.\n#-------------------------------------------------------------------------------\nclock = Impulse(frequency=1.0)\nline = Line(0.0, 0.5, 0.5, False, clock)\nosc = SawOscillator(200)\noutput = StereoPanner(osc * line)\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using Line to repeatedly alter the release value of an envelope applied to the\n# main synth voice, in time with the music.\n#-------------------------------------------------------------------------------\nclock = Impulse(8.0)\nCMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8\nFMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8\narpeggios = CMaj7 + FMaj9\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nrelease = Line(0.1, 0.5, 6, True)\nenvelope = ASREnvelope(0.0, 0.0, release, 1.0, clock)\nvoice = oscillator * envelope\n\npan = SineLFO(0.1667, -1.0, 1.0)\noutput = StereoPanner(voice, pan)\noutput.play()\n
"},{"location":"library/envelope/rectangularenvelope/","title":"RectangularEnvelope node documentation","text":"Reference library > Envelope > RectangularEnvelope
"},{"location":"library/envelope/rectangularenvelope/#rectangularenvelope","title":"RectangularEnvelope","text":"RectangularEnvelope(sustain_duration=1.0, clock=None)\n
Rectangular envelope with the given sustain duration.
"},{"location":"library/fft/","title":"FFT","text":"Reference library > FFT
"},{"location":"library/fft/#fft","title":"FFT","text":" - FFTContinuousPhaseVocoder: Continuous phase vocoder. Requires an FFT* input.
- FFTConvolve: Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
- FFTContrast: FFT Contrast. Requires an FFT* input.
- FFTMagnitudePhaseArray: Fixed mag/phase array.
- FFTRandomPhase: Randomise phase values.
- FFTScaleMagnitudes: Randomise phase values.
- FFTTransform: Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input.
- FFT: Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output.
- FFTFindPeaks: Find peaks in the FFT magnitude spectrum. Requires an FFT* input.
- IFFT: Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output.
- FFTLPF: FFT-based brick wall low pass filter. Requires an FFT* input.
- FFTNoiseGate: FFT-based noise gate. Requires an FFT* input.
- FFTPhaseVocoder: Phase vocoder. Requires an FFT* input.
- FFTTonality: Tonality filter. Requires an FFT* input.
- FFTZeroPhase: Remove phase information from a frequency-domain input. Requires an FFT* input.
"},{"location":"library/fft/fft/","title":"FFT node documentation","text":"Reference library > FFT > FFT
"},{"location":"library/fft/fft/#fft","title":"FFT","text":"FFT(input=0.0, fft_size=SIGNALFLOW_DEFAULT_FFT_SIZE, hop_size=SIGNALFLOW_DEFAULT_FFT_HOP_SIZE, window_size=0, do_window=true)\n
Fast Fourier Transform. Takes a time-domain input, and generates a frequency-domain (FFT) output.
"},{"location":"library/fft/fftcontinuousphasevocoder/","title":"FFTContinuousPhaseVocoder node documentation","text":"Reference library > FFT > FFTContinuousPhaseVocoder
"},{"location":"library/fft/fftcontinuousphasevocoder/#fftcontinuousphasevocoder","title":"FFTContinuousPhaseVocoder","text":"FFTContinuousPhaseVocoder(input=None, rate=1.0)\n
Continuous phase vocoder. Requires an FFT* input.
"},{"location":"library/fft/fftcontrast/","title":"FFTContrast node documentation","text":"Reference library > FFT > FFTContrast
"},{"location":"library/fft/fftcontrast/#fftcontrast","title":"FFTContrast","text":"FFTContrast(input=0, contrast=1)\n
FFT Contrast. Requires an FFT* input.
"},{"location":"library/fft/fftconvolve/","title":"FFTConvolve node documentation","text":"Reference library > FFT > FFTConvolve
"},{"location":"library/fft/fftconvolve/#fftconvolve","title":"FFTConvolve","text":"FFTConvolve(input=None, buffer=None)\n
Frequency-domain convolution, using overlap-add. Useful for convolution reverb, with the input buffer containing an impulse response. Requires an FFT* input.
"},{"location":"library/fft/fftfindpeaks/","title":"FFTFindPeaks node documentation","text":"Reference library > FFT > FFTFindPeaks
"},{"location":"library/fft/fftfindpeaks/#fftfindpeaks","title":"FFTFindPeaks","text":"FFTFindPeaks(input=0, prominence=1, threshold=0.000001, count=SIGNALFLOW_MAX_CHANNELS, interpolate=true)\n
Find peaks in the FFT magnitude spectrum. Requires an FFT* input.
"},{"location":"library/fft/fftflipspectrum/","title":"FFTFlipSpectrum node documentation","text":"Reference library > FFT > FFTFlipSpectrum
"},{"location":"library/fft/fftflipspectrum/#fftflipspectrum","title":"FFTFlipSpectrum","text":"FFTFlipSpectrum(input=0, flip=0, rotate=0)\n
Flips the FFT magnitude spectrum in the X axis. Requires an FFT* input.
"},{"location":"library/fft/fftlpf/","title":"FFTLPF node documentation","text":"Reference library > FFT > FFTLPF
"},{"location":"library/fft/fftlpf/#fftlpf","title":"FFTLPF","text":"FFTLPF(input=0, frequency=2000)\n
FFT-based brick wall low pass filter. Requires an FFT* input.
"},{"location":"library/fft/fftmagnitudephasearray/","title":"FFTMagnitudePhaseArray node documentation","text":"Reference library > FFT > FFTMagnitudePhaseArray
"},{"location":"library/fft/fftmagnitudephasearray/#fftmagnitudephasearray","title":"FFTMagnitudePhaseArray","text":"FFTMagnitudePhaseArray(input=0, magnitudes={}, phases={})\n
Fixed mag/phase array.
"},{"location":"library/fft/fftnoisegate/","title":"FFTNoiseGate node documentation","text":"Reference library > FFT > FFTNoiseGate
"},{"location":"library/fft/fftnoisegate/#fftnoisegate","title":"FFTNoiseGate","text":"FFTNoiseGate(input=0, threshold=0.5, invert=0.0)\n
FFT-based noise gate. Requires an FFT* input.
"},{"location":"library/fft/fftphasevocoder/","title":"FFTPhaseVocoder node documentation","text":"Reference library > FFT > FFTPhaseVocoder
"},{"location":"library/fft/fftphasevocoder/#fftphasevocoder","title":"FFTPhaseVocoder","text":"FFTPhaseVocoder(input=None)\n
Phase vocoder. Requires an FFT* input.
"},{"location":"library/fft/fftrandomphase/","title":"FFTRandomPhase node documentation","text":"Reference library > FFT > FFTRandomPhase
"},{"location":"library/fft/fftrandomphase/#fftrandomphase","title":"FFTRandomPhase","text":"FFTRandomPhase(input=0, level=1.0)\n
Randomise phase values.
"},{"location":"library/fft/fftscalemagnitudes/","title":"FFTScaleMagnitudes node documentation","text":"Reference library > FFT > FFTScaleMagnitudes
"},{"location":"library/fft/fftscalemagnitudes/#fftscalemagnitudes","title":"FFTScaleMagnitudes","text":"FFTScaleMagnitudes(input=0, scale={})\n
Randomise phase values.
"},{"location":"library/fft/ffttonality/","title":"FFTTonality node documentation","text":"Reference library > FFT > FFTTonality
"},{"location":"library/fft/ffttonality/#ffttonality","title":"FFTTonality","text":"FFTTonality(input=0, level=0.5, smoothing=0.9)\n
Tonality filter. Requires an FFT* input.
"},{"location":"library/fft/ffttransform/","title":"FFTTransform node documentation","text":"Reference library > FFT > FFTTransform
"},{"location":"library/fft/ffttransform/#ffttransform","title":"FFTTransform","text":"FFTTransform(input=0, flip=0, rotate=0)\n
Transforms the FFT magnitude spectrum in the X axis. Requires an FFT* input.
"},{"location":"library/fft/fftzerophase/","title":"FFTZeroPhase node documentation","text":"Reference library > FFT > FFTZeroPhase
"},{"location":"library/fft/fftzerophase/#fftzerophase","title":"FFTZeroPhase","text":"FFTZeroPhase(input=0)\n
Remove phase information from a frequency-domain input. Requires an FFT* input.
"},{"location":"library/fft/ifft/","title":"IFFT node documentation","text":"Reference library > FFT > IFFT
"},{"location":"library/fft/ifft/#ifft","title":"IFFT","text":"IFFT(input=None, do_window=false)\n
Inverse Fast Fourier Transform. Requires an FFT* input, generates a time-domain output.
"},{"location":"library/operators/","title":"Operators","text":"Reference library > Operators
"},{"location":"library/operators/#operators","title":"Operators","text":" - Add: Add each sample of a to each sample of b. Can also be written as a + b
- AmplitudeToDecibels: Map a linear amplitude value to decibels.
- DecibelsToAmplitude: DecibelsToAmplitude
- ChannelArray: Takes an array of inputs and spreads them across multiple channels of output.
- ChannelCrossfade: Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output.
- ChannelMixer: Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels.
- ChannelSelect: Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step.
- Equal: Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b
- NotEqual: Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b
- GreaterThan: Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b
- GreaterThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b
- LessThan: Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b
- LessThanOrEqual: Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b
- Modulo: Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b
- Abs: Outputs the absolute value of a, per sample. Can also be written as abs(a)
- If: Outputs value_if_true for each non-zero value of a, value_if_false for all other values.
- Divide: Divide each sample of a by each sample of b. Can also be written as a / b
- FrequencyToMidiNote: Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output.
- MidiNoteToFrequency: Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input.
- Multiply: Multiply each sample of a by each sample of b. Can also be written as a * b
- Pow: Outputs a to the power of b, per sample. Can also be written as a ** b
- RoundToScale: Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named)
- Round: Round the input to the nearest integer value.
- ScaleLinExp: Scales the input from a linear range (between a and b) to an exponential range (between c and d).
- ScaleLinLin: Scales the input from a linear range (between a and b) to a linear range (between c and d).
- Subtract: Subtract each sample of b from each sample of a. Can also be written as a - b
- Sum: Sums the output of all of the input nodes, by sample.
- TimeShift: TimeShift
- Sin: Outputs sin(a), per sample.
- Cos: Outputs cos(a), per sample.
- Tan: Outputs tan(a), per sample.
- Tanh: Outputs tanh(a), per sample. Can be used as a soft clipper.
"},{"location":"library/operators/abs/","title":"Abs node documentation","text":"Reference library > Operators > Abs
"},{"location":"library/operators/abs/#abs","title":"Abs","text":"Abs(a=0)\n
Outputs the absolute value of a, per sample. Can also be written as abs(a)
"},{"location":"library/operators/add/","title":"Add node documentation","text":"Reference library > Operators > Add
"},{"location":"library/operators/add/#add","title":"Add","text":"Add(a=0, b=0)\n
Add each sample of a to each sample of b. Can also be written as a + b
"},{"location":"library/operators/amplitudetodecibels/","title":"AmplitudeToDecibels node documentation","text":"Reference library > Operators > AmplitudeToDecibels
"},{"location":"library/operators/amplitudetodecibels/#amplitudetodecibels","title":"AmplitudeToDecibels","text":"AmplitudeToDecibels(a=0)\n
Map a linear amplitude value to decibels.
"},{"location":"library/operators/channelarray/","title":"ChannelArray node documentation","text":"Reference library > Operators > ChannelArray
"},{"location":"library/operators/channelarray/#channelarray","title":"ChannelArray","text":"ChannelArray()\n
Takes an array of inputs and spreads them across multiple channels of output.
"},{"location":"library/operators/channelarray/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using ChannelArray to pan a low tone to the left and a high tone to the right.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\npanned = ChannelArray([low, high]) * 0.3\npanned.play()\n
"},{"location":"library/operators/channelcrossfade/","title":"ChannelCrossfade node documentation","text":"Reference library > Operators > ChannelCrossfade
"},{"location":"library/operators/channelcrossfade/#channelcrossfade","title":"ChannelCrossfade","text":"ChannelCrossfade(input=None, index=None, num_output_channels=1)\n
Given a multichannel input, crossfades between channels based on the given position within the virtual array, producing a single-channel output.
"},{"location":"library/operators/channelmixer/","title":"ChannelMixer node documentation","text":"Reference library > Operators > ChannelMixer
"},{"location":"library/operators/channelmixer/#channelmixer","title":"ChannelMixer","text":"ChannelMixer(num_channels=1, input=0, amplitude_compensation=true)\n
Downmix a multichannel input to a lower-channel output. If num_channels is greater than one, spreads the input channels across the field. If amplitude_compensation is enabled, scale down the amplitude based on the ratio of input to output channels.
"},{"location":"library/operators/channelselect/","title":"ChannelSelect node documentation","text":"Reference library > Operators > ChannelSelect
"},{"location":"library/operators/channelselect/#channelselect","title":"ChannelSelect","text":"ChannelSelect(input=None, offset=0, maximum=0, step=1)\n
Select a subset of channels from a multichannel input, starting at offset, up to a maximum of maximum, with the given step.
"},{"location":"library/operators/cos/","title":"Cos node documentation","text":"Reference library > Operators > Cos
"},{"location":"library/operators/cos/#cos","title":"Cos","text":"Cos(a=0)\n
Outputs cos(a), per sample.
"},{"location":"library/operators/decibelstoamplitude/","title":"DecibelsToAmplitude node documentation","text":"Reference library > Operators > DecibelsToAmplitude
"},{"location":"library/operators/decibelstoamplitude/#decibelstoamplitude","title":"DecibelsToAmplitude","text":"DecibelsToAmplitude(a=0)\n
DecibelsToAmplitude
"},{"location":"library/operators/divide/","title":"Divide node documentation","text":"Reference library > Operators > Divide
"},{"location":"library/operators/divide/#divide","title":"Divide","text":"Divide(a=1, b=1)\n
Divide each sample of a by each sample of b. Can also be written as a / b
"},{"location":"library/operators/equal/","title":"Equal node documentation","text":"Reference library > Operators > Equal
"},{"location":"library/operators/equal/#equal","title":"Equal","text":"Equal(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when equal, 0 otherwise. Can also be written as a == b
"},{"location":"library/operators/frequencytomidinote/","title":"FrequencyToMidiNote node documentation","text":"Reference library > Operators > FrequencyToMidiNote
"},{"location":"library/operators/frequencytomidinote/#frequencytomidinote","title":"FrequencyToMidiNote","text":"FrequencyToMidiNote(a=0)\n
Map a frequency to a MIDI note (where 440Hz = A4 = 69), with floating-point output.
"},{"location":"library/operators/greaterthan/","title":"GreaterThan node documentation","text":"Reference library > Operators > GreaterThan
"},{"location":"library/operators/greaterthan/#greaterthan","title":"GreaterThan","text":"GreaterThan(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a > b, 0 otherwise. Can also be written as a > b
"},{"location":"library/operators/greaterthanorequal/","title":"GreaterThanOrEqual node documentation","text":"Reference library > Operators > GreaterThanOrEqual
"},{"location":"library/operators/greaterthanorequal/#greaterthanorequal","title":"GreaterThanOrEqual","text":"GreaterThanOrEqual(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a >= b, 0 otherwise. Can also be written as a >= b
"},{"location":"library/operators/if/","title":"If node documentation","text":"Reference library > Operators > If
"},{"location":"library/operators/if/#if","title":"If","text":"If(a=0, value_if_true=0, value_if_false=0)\n
Outputs value_if_true for each non-zero value of a, value_if_false for all other values.
"},{"location":"library/operators/lessthan/","title":"LessThan node documentation","text":"Reference library > Operators > LessThan
"},{"location":"library/operators/lessthan/#lessthan","title":"LessThan","text":"LessThan(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a < b, 0 otherwise. Can also be written as a < b
"},{"location":"library/operators/lessthanorequal/","title":"LessThanOrEqual node documentation","text":"Reference library > Operators > LessThanOrEqual
"},{"location":"library/operators/lessthanorequal/#lessthanorequal","title":"LessThanOrEqual","text":"LessThanOrEqual(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 1 when a <= b, 0 otherwise. Can also be written as a <= b
"},{"location":"library/operators/midinotetofrequency/","title":"MidiNoteToFrequency node documentation","text":"Reference library > Operators > MidiNoteToFrequency
"},{"location":"library/operators/midinotetofrequency/#midinotetofrequency","title":"MidiNoteToFrequency","text":"MidiNoteToFrequency(a=0)\n
Map a MIDI note to a frequency (where 440Hz = A4 = 69), supporting floating-point input.
"},{"location":"library/operators/modulo/","title":"Modulo node documentation","text":"Reference library > Operators > Modulo
"},{"location":"library/operators/modulo/#modulo","title":"Modulo","text":"Modulo(a=0, b=0)\n
Outputs the value of a modulo b, per sample. Supports fractional values. Can also be written as a % b
"},{"location":"library/operators/multiply/","title":"Multiply node documentation","text":"Reference library > Operators > Multiply
"},{"location":"library/operators/multiply/#multiply","title":"Multiply","text":"Multiply(a=1.0, b=1.0)\n
Multiply each sample of a by each sample of b. Can also be written as a * b
"},{"location":"library/operators/notequal/","title":"NotEqual node documentation","text":"Reference library > Operators > NotEqual
"},{"location":"library/operators/notequal/#notequal","title":"NotEqual","text":"NotEqual(a=0, b=0)\n
Compares the output of a to the output of b. Outputs 0 when equal, 1 otherwise. Can also be written as a != b
"},{"location":"library/operators/pow/","title":"Pow node documentation","text":"Reference library > Operators > Pow
"},{"location":"library/operators/pow/#pow","title":"Pow","text":"Pow(a=0, b=0)\n
Outputs a to the power of b, per sample. Can also be written as a ** b
"},{"location":"library/operators/round/","title":"Round node documentation","text":"Reference library > Operators > Round
"},{"location":"library/operators/round/#round","title":"Round","text":"Round(a=0)\n
Round the input to the nearest integer value.
"},{"location":"library/operators/roundtoscale/","title":"RoundToScale node documentation","text":"Reference library > Operators > RoundToScale
"},{"location":"library/operators/roundtoscale/#roundtoscale","title":"RoundToScale","text":"RoundToScale(a=0)\n
Given a frequency input, generates a frequency output that is rounded to the nearest MIDI note. (TODO: Not very well named)
"},{"location":"library/operators/scalelinexp/","title":"ScaleLinExp node documentation","text":"Reference library > Operators > ScaleLinExp
"},{"location":"library/operators/scalelinexp/#scalelinexp","title":"ScaleLinExp","text":"ScaleLinExp(input=0, a=0, b=1, c=1, d=10)\n
Scales the input from a linear range (between a and b) to an exponential range (between c and d).
"},{"location":"library/operators/scalelinlin/","title":"ScaleLinLin node documentation","text":"Reference library > Operators > ScaleLinLin
"},{"location":"library/operators/scalelinlin/#scalelinlin","title":"ScaleLinLin","text":"ScaleLinLin(input=0, a=0, b=1, c=1, d=10)\n
Scales the input from a linear range (between a and b) to a linear range (between c and d).
"},{"location":"library/operators/sin/","title":"Sin node documentation","text":"Reference library > Operators > Sin
"},{"location":"library/operators/sin/#sin","title":"Sin","text":"Sin(a=0)\n
Outputs sin(a), per sample.
"},{"location":"library/operators/subtract/","title":"Subtract node documentation","text":"Reference library > Operators > Subtract
"},{"location":"library/operators/subtract/#subtract","title":"Subtract","text":"Subtract(a=0, b=0)\n
Subtract each sample of b from each sample of a. Can also be written as a - b
"},{"location":"library/operators/sum/","title":"Sum node documentation","text":"Reference library > Operators > Sum
"},{"location":"library/operators/sum/#sum","title":"Sum","text":"Sum()\n
Sums the output of all of the input nodes, by sample.
"},{"location":"library/operators/tan/","title":"Tan node documentation","text":"Reference library > Operators > Tan
"},{"location":"library/operators/tan/#tan","title":"Tan","text":"Tan(a=0)\n
Outputs tan(a), per sample.
"},{"location":"library/operators/tanh/","title":"Tanh node documentation","text":"Reference library > Operators > Tanh
"},{"location":"library/operators/tanh/#tanh","title":"Tanh","text":"Tanh(a=0)\n
Outputs tanh(a), per sample. Can be used as a soft clipper.
"},{"location":"library/operators/timeshift/","title":"TimeShift node documentation","text":"Reference library > Operators > TimeShift
"},{"location":"library/operators/timeshift/#timeshift","title":"TimeShift","text":"TimeShift(a=0)\n
TimeShift
"},{"location":"library/oscillators/","title":"Oscillators","text":"Reference library > Oscillators
"},{"location":"library/oscillators/#oscillators","title":"Oscillators","text":" - Impulse: Produces a value of 1 at the given
frequency
, with output of 0 at all other times. If frequency is 0, produces a single impulse. - SawLFO: Produces a sawtooth LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SawOscillator: Produces a (non-band-limited) sawtooth wave, with the given
frequency
and phase
offset. When a reset
or trigger is received, resets the phase to zero. - SineLFO: Produces a sinusoidal LFO at the given
frequency
and phase
offset, with output ranging from min
to max
. - SineOscillator: Produces a sine wave at the given
frequency
. - SquareLFO: Produces a pulse wave LFO with the given
frequency
and pulse width
, ranging from min
to max
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - SquareOscillator: Produces a pulse wave with the given
frequency
and pulse width
, where width
of 0.5
is a square wave and other values produce a rectangular wave. - TriangleLFO: Produces a triangle LFO with the given
frequency
and phase
offset, ranging from min
to max
. - TriangleOscillator: Produces a triangle wave with the given
frequency
. - Wavetable: Plays the wavetable stored in buffer at the given
frequency
and phase
offset. sync
can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing. - Wavetable2D: Wavetable2D
"},{"location":"library/oscillators/constant/","title":"Constant node documentation","text":"Reference library > Oscillators > Constant
"},{"location":"library/oscillators/constant/#constant","title":"Constant","text":"Constant(value=0)\n
Produces a constant value.
"},{"location":"library/oscillators/impulse/","title":"Impulse node documentation","text":"Reference library > Oscillators > Impulse
"},{"location":"library/oscillators/impulse/#impulse","title":"Impulse","text":"Impulse(frequency=1.0)\n
Produces a value of 1 at the given frequency
, with output of 0 at all other times. If frequency is 0, produces a single impulse.
"},{"location":"library/oscillators/impulse/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using an Impulse node as a clock to trigger an envelope once per second.\n#-------------------------------------------------------------------------------\nclock = Impulse(1.0)\nosc = TriangleOscillator(250)\nenvelope = ASREnvelope(0.01, 0.0, 0.5, 1.0, clock)\noutput = StereoPanner(osc * envelope)\noutput.play()\n
"},{"location":"library/oscillators/sawlfo/","title":"SawLFO node documentation","text":"Reference library > Oscillators > SawLFO
"},{"location":"library/oscillators/sawlfo/#sawlfo","title":"SawLFO","text":"SawLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0)\n
Produces a sawtooth LFO at the given frequency
and phase
offset, with output ranging from min
to max
.
"},{"location":"library/oscillators/sawlfo/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Siren effect, using a sawtooth LFO to modulate a sinewave's frequency\n#-------------------------------------------------------------------------------\nlfo = SawLFO(1, 200, 1000)\nsine = SineOscillator(lfo)\noutput = StereoPanner(sine) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/sawoscillator/","title":"SawOscillator node documentation","text":"Reference library > Oscillators > SawOscillator
"},{"location":"library/oscillators/sawoscillator/#sawoscillator","title":"SawOscillator","text":"SawOscillator(frequency=440, phase_offset=None, reset=None)\n
Produces a (non-band-limited) sawtooth wave, with the given frequency
and phase
offset. When a reset
or trigger is received, resets the phase to zero.
"},{"location":"library/oscillators/sawoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple saw wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\nsaw = SawOscillator(440)\nenvelope = ASREnvelope(0.05, 0.1, 0.5)\noutput = StereoPanner(saw * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/sinelfo/","title":"SineLFO node documentation","text":"Reference library > Oscillators > SineLFO
"},{"location":"library/oscillators/sinelfo/#sinelfo","title":"SineLFO","text":"SineLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0)\n
Produces a sinusoidal LFO at the given frequency
and phase
offset, with output ranging from min
to max
.
"},{"location":"library/oscillators/sinelfo/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Siren effect, using a sinewave LFO to modulate a sawtooth's frequency\n#-------------------------------------------------------------------------------\nlfo = SineLFO(1, 200, 1000)\nsaw = SawOscillator(lfo)\noutput = StereoPanner(saw) * 0.3\noutput.play()\n
"},{"location":"library/oscillators/sineoscillator/","title":"SineOscillator node documentation","text":"Reference library > Oscillators > SineOscillator
"},{"location":"library/oscillators/sineoscillator/#sineoscillator","title":"SineOscillator","text":"SineOscillator(frequency=440, phase_offset=None, reset=None)\n
Produces a sine wave at the given frequency
.
"},{"location":"library/oscillators/sineoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple sine wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\nsine = SineOscillator(440)\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = StereoPanner(sine * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/squarelfo/","title":"SquareLFO node documentation","text":"Reference library > Oscillators > SquareLFO
"},{"location":"library/oscillators/squarelfo/#squarelfo","title":"SquareLFO","text":"SquareLFO(frequency=1.0, min=0.0, max=1.0, width=0.5, phase=0.0)\n
Produces a pulse wave LFO with the given frequency
and pulse width
, ranging from min
to max
, where width
of 0.5
is a square wave and other values produce a rectangular wave.
"},{"location":"library/oscillators/squarelfo/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Alarm effect, using a pulse wave LFO to modulate a sinewave's frequency\n#-------------------------------------------------------------------------------\nlfo = SquareLFO(1, 200, 400)\nsine = SineOscillator(lfo)\noutput = StereoPanner(sine) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/squareoscillator/","title":"SquareOscillator node documentation","text":"Reference library > Oscillators > SquareOscillator
"},{"location":"library/oscillators/squareoscillator/#squareoscillator","title":"SquareOscillator","text":"SquareOscillator(frequency=440, width=0.5)\n
Produces a pulse wave with the given frequency
and pulse width
, where width
of 0.5
is a square wave and other values produce a rectangular wave.
"},{"location":"library/oscillators/squareoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple square wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\nsquare = SquareOscillator(440)\nenvelope = ASREnvelope(0, 0.1, 0.5)\noutput = StereoPanner(square * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/trianglelfo/","title":"TriangleLFO node documentation","text":"Reference library > Oscillators > TriangleLFO
"},{"location":"library/oscillators/trianglelfo/#trianglelfo","title":"TriangleLFO","text":"TriangleLFO(frequency=1.0, min=0.0, max=1.0, phase=0.0)\n
Produces a triangle LFO with the given frequency
and phase
offset, ranging from min
to max
.
"},{"location":"library/oscillators/trianglelfo/#examples","title":"Examples","text":"#-----------------------------------------------------------------------------------\n# Pacman ghost sound, using a triangle wave LFO to modulate a sine wave's frequency\n#-----------------------------------------------------------------------------------\nlfo = TriangleLFO(3, 200, 900)\nsine = SineOscillator(lfo)\noutput = StereoPanner(sine) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/triangleoscillator/","title":"TriangleOscillator node documentation","text":"Reference library > Oscillators > TriangleOscillator
"},{"location":"library/oscillators/triangleoscillator/#triangleoscillator","title":"TriangleOscillator","text":"TriangleOscillator(frequency=440)\n
Produces a triangle wave with the given frequency
.
"},{"location":"library/oscillators/triangleoscillator/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Simple triangle wave oscillator shaped by an envelope\n#-------------------------------------------------------------------------------\ntri = TriangleOscillator(440)\nenvelope = ASREnvelope(0.1, 0.1, 0.5)\noutput = StereoPanner(tri * envelope) * 0.5\noutput.play()\n
"},{"location":"library/oscillators/wavetable/","title":"Wavetable node documentation","text":"Reference library > Oscillators > Wavetable
"},{"location":"library/oscillators/wavetable/#wavetable","title":"Wavetable","text":"Wavetable(buffer=None, frequency=440, phase_offset=0, sync=0, phase_map=None)\n
Plays the wavetable stored in buffer at the given frequency
and phase
offset. sync
can be used to provide a hard sync input, which resets the wavetable's phase at each zero-crossing.
"},{"location":"library/oscillators/wavetable2d/","title":"Wavetable2D node documentation","text":"Reference library > Oscillators > Wavetable2D
"},{"location":"library/oscillators/wavetable2d/#wavetable2d","title":"Wavetable2D","text":"Wavetable2D(buffer=None, frequency=440, crossfade=0.0, phase_offset=0.0, sync=0)\n
Wavetable2D
"},{"location":"library/processors/","title":"Processors","text":"Reference library > Processors
"},{"location":"library/processors/#processors","title":"Processors","text":" - Clip: Clip the input to
min
/max
. - Fold: Fold the input beyond
min
/max
, reflecting the excess back. - Smooth: Smooth the input with a given smoothing coefficient. When
smooth
= 0, applies no smoothing. - WetDry: Takes
wet
and dry
inputs, and outputs a mix determined by wetness
. - Wrap: Wrap the input beyond
min
/max
.
"},{"location":"library/processors/clip/","title":"Clip node documentation","text":"Reference library > Processors > Clip
"},{"location":"library/processors/clip/#clip","title":"Clip","text":"Clip(input=None, min=-1.0, max=1.0)\n
Clip the input to min
/max
.
"},{"location":"library/processors/delays/","title":"Processors: Delays","text":"Reference library > Processors: Delays
"},{"location":"library/processors/delays/#processors-delays","title":"Processors: Delays","text":" - AllpassDelay: All-pass delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - CombDelay: Comb delay, with
feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
. - OneTapDelay: Single-tap delay line.
delay_time
must be less than or equal to max_delay_time
. - Stutter: Stutters the input whenever a trigger is received on
clock
. Generates stutter_count
repeats, with duration of stutter_time
.
"},{"location":"library/processors/delays/allpassdelay/","title":"AllpassDelay node documentation","text":"Reference library > Processors: Delays > AllpassDelay
"},{"location":"library/processors/delays/allpassdelay/#allpassdelay","title":"AllpassDelay","text":"AllpassDelay(input=0.0, delay_time=0.1, feedback=0.5, max_delay_time=0.5)\n
All-pass delay, with feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
.
"},{"location":"library/processors/delays/allpassdelay/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using AllpassDelay to add a delay effect to a simple melodic sequence.\n# The original oscillator can be heard in the left channel.\n# The delay effect can be heard in the right channel.\n#-------------------------------------------------------------------------------\nclock = Impulse(1.0)\nsequence = Sequence([ 60, 62, 64, 65, 67, 69, 71, 72 ], clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nenvelope = ASREnvelope(0, 0.2, 0.3, 1.0, clock)\nvoice = oscillator * envelope\ndelayed = AllpassDelay(input=voice, \n delay_time=0.4, \n feedback=0.8)\n\noutput = ChannelArray([ voice, delayed ]) * 0.75\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using AllpassDelay to add a dreamy atmosphere to synth arpeggios\n#-------------------------------------------------------------------------------\nclock = Impulse(3.5)\nAm7 = [ 67, 64, 60, 57 ] * 4\nD7 = [ 62, 66, 69, 72] * 4\narpeggios = Am7 + D7\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SquareOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope\nfiltered = SVFilter(voice, \"low_pass\", 4000, 0.3)\ndelayed = AllpassDelay(input=filtered, \n delay_time=0.15, \n feedback=0.8)\n\npan = TriangleLFO(0.1, -1.0, 1.0)\noutput = StereoPanner(delayed, pan) * 0.5\noutput.play()\n
"},{"location":"library/processors/delays/combdelay/","title":"CombDelay node documentation","text":"Reference library > Processors: Delays > CombDelay
"},{"location":"library/processors/delays/combdelay/#combdelay","title":"CombDelay","text":"CombDelay(input=0.0, delay_time=0.1, feedback=0.5, max_delay_time=0.5)\n
Comb delay, with feedback
between 0 and 1. delay_time
must be less than or equal to max_delay_time
.
"},{"location":"library/processors/delays/combdelay/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using CombDelay to change the character of a saw wave oscillator.\n#-------------------------------------------------------------------------------\nclock = Impulse(4)\narpeggio = [60, 62, 64, 66, 68, 70,\n 72, 70, 68, 66, 64, 62]\nsequence = Sequence(arpeggio, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SawOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope\ncomb = CombDelay(input=voice, \n delay_time=0.09, \n feedback=0.6, \n max_delay_time=0.9)\n\noutput = StereoPanner(comb) * 0.5\noutput.play()\n
"},{"location":"library/processors/delays/onetapdelay/","title":"OneTapDelay node documentation","text":"Reference library > Processors: Delays > OneTapDelay
"},{"location":"library/processors/delays/onetapdelay/#onetapdelay","title":"OneTapDelay","text":"OneTapDelay(input=0.0, delay_time=0.1, max_delay_time=0.5)\n
Single-tap delay line. delay_time
must be less than or equal to max_delay_time
.
"},{"location":"library/processors/delays/onetapdelay/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using OneTapDelay to create a delay effect with no feedback.\n# The original sound is heard in the left channel, and the delayed sound in the\n# right channel.\n#-------------------------------------------------------------------------------\nclock = Impulse(1)\noscillator = TriangleOscillator(440)\nenvelope = ASREnvelope(0.001, 0, 0.3, 1.0, clock)\nvoice = oscillator * envelope\ndelayed = OneTapDelay(voice, 0.25) * 0.5\noutput = ChannelArray([voice, delayed]) * 0.5\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using OneTapDelay to bring controlled rhythmic interest to a melodic sequence\n#-------------------------------------------------------------------------------\nclock = Impulse(3.5)\nDm = [ 62, 65, 69 ] * 2\nBdim = [ 59, 62, 65 ] * 2\nGm = [55, 58, 62 ] * 2\nBb = [77, 74, 70 ]\nA = [ 76, 73, 69 ]\n\narpeggios = Dm + Bdim + Gm + Bb + A\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SquareOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope\nfiltered = SVFilter(voice, \"low_pass\", 4000, 0.3)\ndelayed = filtered + OneTapDelay(filtered, 0.4) * 0.5\n\noutput = StereoPanner(delayed) * 0.3\noutput.play()\n
"},{"location":"library/processors/delays/stutter/","title":"Stutter node documentation","text":"Reference library > Processors: Delays > Stutter
"},{"location":"library/processors/delays/stutter/#stutter","title":"Stutter","text":"Stutter(input=0.0, stutter_time=0.1, stutter_count=1, clock=None, max_stutter_time=1.0)\n
Stutters the input whenever a trigger is received on clock
. Generates stutter_count
repeats, with duration of stutter_time
.
"},{"location":"library/processors/distortion/","title":"Processors: Distortion","text":"Reference library > Processors: Distortion
"},{"location":"library/processors/distortion/#processors-distortion","title":"Processors: Distortion","text":" - Resample: Resampler and bit crusher.
sample_rate
is in Hz, bit_rate
is an integer between 0 and 16. - SampleAndHold: Samples and holds the input each time a trigger is received on
clock
. - Squiz: Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler.
- WaveShaper: Applies wave-shaping as described in the WaveShaperBuffer
buffer
.
"},{"location":"library/processors/distortion/resample/","title":"Resample node documentation","text":"Reference library > Processors: Distortion > Resample
"},{"location":"library/processors/distortion/resample/#resample","title":"Resample","text":"Resample(input=0, sample_rate=44100, bit_rate=16)\n
Resampler and bit crusher. sample_rate
is in Hz, bit_rate
is an integer between 0 and 16.
"},{"location":"library/processors/distortion/resample/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using Resample to distort a sine wave.\n#-------------------------------------------------------------------------------\nsine = SineOscillator(440)\ncrushed = Resample(sine, 11025, 4)\noutput = StereoPanner(crushed) * 0.3\noutput.play()\n
"},{"location":"library/processors/distortion/sampleandhold/","title":"SampleAndHold node documentation","text":"Reference library > Processors: Distortion > SampleAndHold
"},{"location":"library/processors/distortion/sampleandhold/#sampleandhold","title":"SampleAndHold","text":"SampleAndHold(input=None, clock=None)\n
Samples and holds the input each time a trigger is received on clock
.
"},{"location":"library/processors/distortion/squiz/","title":"Squiz node documentation","text":"Reference library > Processors: Distortion > Squiz
"},{"location":"library/processors/distortion/squiz/#squiz","title":"Squiz","text":"Squiz(input=0.0, rate=2.0, chunk_size=1)\n
Implementation of Dan Stowell's Squiz algorithm, a kind of downsampler.
"},{"location":"library/processors/distortion/waveshaper/","title":"WaveShaper node documentation","text":"Reference library > Processors: Distortion > WaveShaper
"},{"location":"library/processors/distortion/waveshaper/#waveshaper","title":"WaveShaper","text":"WaveShaper(input=0.0, buffer=None)\n
Applies wave-shaping as described in the WaveShaperBuffer buffer
.
"},{"location":"library/processors/distortion/waveshaper/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Create a waveshaper buffer that silences any samples with amplitude < 0.5\n#-------------------------------------------------------------------------------\nbuf = WaveShaperBuffer(lambda n: 0 if abs(n) < 0.5 else n)\nsine = SineOscillator(120)\nwaveshaper = WaveShaper(sine, buf)\nattenuated = waveshaper * 0.1\nattenuated.play()\n
#-------------------------------------------------------------------------------\n# Create a range of different waveshaper buffers, and iterate through them.\n#-------------------------------------------------------------------------------\nimport time\nimport math\nimport random\n\nsin_buf = WaveShaperBuffer(lambda n: math.sin(n * math.pi / 2))\ncos_buf = WaveShaperBuffer(lambda n: math.cos(n * math.pi / 2))\ntan_buf = WaveShaperBuffer(lambda n: math.tan(n * math.pi / 2))\ntanh_buf = WaveShaperBuffer(lambda n: math.tanh(n * 20))\nsinx_buf = WaveShaperBuffer(lambda n: math.sin(256 * n * math.pi / 2))\ninvert_buf = WaveShaperBuffer(lambda n: 1 - n if n > 0 else -1 - n)\nnoise_buf = WaveShaperBuffer(lambda n: random.uniform(0, n))\nbufs = [sin_buf, cos_buf, tan_buf, tanh_buf, sinx_buf, invert_buf, noise_buf]\n\nsine = SineOscillator(120)\nwaveshaper = WaveShaper(sine, sin_buf)\nattenuated = waveshaper * 0.1\nattenuated.play()\n\nfor buf in bufs:\n waveshaper.set_buffer(\"buffer\", buf)\n time.sleep(1.0)\n\nattenuated.stop()\n
"},{"location":"library/processors/dynamics/","title":"Processors: Dynamics","text":"Reference library > Processors: Dynamics
"},{"location":"library/processors/dynamics/#processors-dynamics","title":"Processors: Dynamics","text":" - Compressor: Dynamic range compression, with optional
sidechain
input. When the input amplitude is above threshold
, compresses the amplitude with the given ratio
, following the given attack_time
and release_time
in seconds. - Gate: Outputs the input value when it is above the given
threshold
, otherwise zero. - Maximiser: Gain maximiser.
- RMS: Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size.
"},{"location":"library/processors/dynamics/compressor/","title":"Compressor node documentation","text":"Reference library > Processors: Dynamics > Compressor
"},{"location":"library/processors/dynamics/compressor/#compressor","title":"Compressor","text":"Compressor(input=0.0, threshold=0.1, ratio=2, attack_time=0.01, release_time=0.1, sidechain=None)\n
Dynamic range compression, with optional sidechain
input. When the input amplitude is above threshold
, compresses the amplitude with the given ratio
, following the given attack_time
and release_time
in seconds.
"},{"location":"library/processors/dynamics/gate/","title":"Gate node documentation","text":"Reference library > Processors: Dynamics > Gate
"},{"location":"library/processors/dynamics/gate/#gate","title":"Gate","text":"Gate(input=0.0, threshold=0.1)\n
Outputs the input value when it is above the given threshold
, otherwise zero.
"},{"location":"library/processors/dynamics/maximiser/","title":"Maximiser node documentation","text":"Reference library > Processors: Dynamics > Maximiser
"},{"location":"library/processors/dynamics/maximiser/#maximiser","title":"Maximiser","text":"Maximiser(input=0.0, ceiling=0.5, attack_time=1.0, release_time=1.0)\n
Gain maximiser.
"},{"location":"library/processors/dynamics/rms/","title":"RMS node documentation","text":"Reference library > Processors: Dynamics > RMS
"},{"location":"library/processors/dynamics/rms/#rms","title":"RMS","text":"RMS(input=0.0)\n
Outputs the root-mean-squared value of the input, in buffers equal to the graph's current buffer size.
"},{"location":"library/processors/filters/","title":"Processors: Filters","text":"Reference library > Processors: Filters
"},{"location":"library/processors/filters/#processors-filters","title":"Processors: Filters","text":" - BiquadFilter: Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter.
- DCFilter: Remove low-frequency and DC content from a signal.
- EQ: Three-band EQ.
- MoogVCF: Moog ladder low-pass filter.
- SVFilter: State variable filter.
filter_type
can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. resonance
should be between [0..1]
.
"},{"location":"library/processors/filters/biquadfilter/","title":"BiquadFilter node documentation","text":"Reference library > Processors: Filters > BiquadFilter
"},{"location":"library/processors/filters/biquadfilter/#biquadfilter","title":"BiquadFilter","text":"BiquadFilter(input=0.0, filter_type=SIGNALFLOW_FILTER_TYPE_LOW_PASS, cutoff=440, resonance=0.0, peak_gain=0.0)\n
Biquad filter. filter_type can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. Not recommended for real-time modulation; for this, use SVFilter.
"},{"location":"library/processors/filters/dcfilter/","title":"DCFilter node documentation","text":"Reference library > Processors: Filters > DCFilter
"},{"location":"library/processors/filters/dcfilter/#dcfilter","title":"DCFilter","text":"DCFilter(input=0.0)\n
Remove low-frequency and DC content from a signal.
"},{"location":"library/processors/filters/eq/","title":"EQ node documentation","text":"Reference library > Processors: Filters > EQ
"},{"location":"library/processors/filters/eq/#eq","title":"EQ","text":"EQ(input=0.0, low_gain=1.0, mid_gain=1.0, high_gain=1.0, low_freq=500, high_freq=5000)\n
Three-band EQ.
"},{"location":"library/processors/filters/eq/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using EQ to shape white noise. The low band (below 500Hz) is reduced. The mid\n# band is boosted. The high band (above 2000Hz) is reduced drastically.\n#-------------------------------------------------------------------------------\nnoise = WhiteNoise()\neq = EQ(input=noise, \n low_gain=0.0, \n mid_gain=1.5, \n high_gain=0.2, \n low_freq=1000, \n high_freq=2000)\noutput = StereoPanner(eq) * 0.5\noutput.play()\n
"},{"location":"library/processors/filters/moogvcf/","title":"MoogVCF node documentation","text":"Reference library > Processors: Filters > MoogVCF
"},{"location":"library/processors/filters/moogvcf/#moogvcf","title":"MoogVCF","text":"MoogVCF(input=0.0, cutoff=200.0, resonance=0.0)\n
Moog ladder low-pass filter.
"},{"location":"library/processors/filters/svfilter/","title":"SVFilter node documentation","text":"Reference library > Processors: Filters > SVFilter
"},{"location":"library/processors/filters/svfilter/#svfilter","title":"SVFilter","text":"SVFilter(input=0.0, filter_type=SIGNALFLOW_FILTER_TYPE_LOW_PASS, cutoff=440, resonance=0.0)\n
State variable filter. filter_type
can be 'low_pass', 'band_pass', 'high_pass', 'notch', 'peak', 'low_shelf', 'high_shelf'. resonance
should be between [0..1]
.
"},{"location":"library/processors/filters/svfilter/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using SVFilter as a low-pass filter on white noise.\n#-------------------------------------------------------------------------------\nnoise = WhiteNoise()\nfiltered = SVFilter(input=noise,\n filter_type=\"low_pass\", \n cutoff=1000, \n resonance=0.6)\noutput = StereoPanner(filtered)\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using SVFilter as a low-pass filter to reduce the harshness of a square wave\n# oscillator.\n#-------------------------------------------------------------------------------\nclock = Impulse(3.5)\nAm7 = [ 67, 64, 60, 57 ] * 4\nD7 = [ 62, 66, 69, 72] * 4\narpeggios = Am7 + D7\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = SquareOscillator(frequency)\nenvelope = ASREnvelope(0.1, 0, 0.2, 1.0, clock)\nvoice = oscillator * envelope \nfiltered = SVFilter(input=voice,\n filter_type= \"low_pass\", \n cutoff=4000, \n resonance=0.3)\ndelayed = AllpassDelay(filtered, 0.15, 0.8, 0.5)\n\npan = TriangleLFO(0.1, -1.0, 1.0)\noutput = StereoPanner(delayed, pan) * 0.3\noutput.play()\n
"},{"location":"library/processors/fold/","title":"Fold node documentation","text":"Reference library > Processors > Fold
"},{"location":"library/processors/fold/#fold","title":"Fold","text":"Fold(input=None, min=-1.0, max=1.0)\n
Fold the input beyond min
/max
, reflecting the excess back.
"},{"location":"library/processors/panning/","title":"Processors: Panning","text":"Reference library > Processors: Panning
"},{"location":"library/processors/panning/#processors-panning","title":"Processors: Panning","text":" - AzimuthPanner: Pan input around an equally-spaced ring of
num_channels
speakers. pan
is the pan position from -1..+1, where 0 = centre front. width
is the source's width, where 1.0 spans exactly between an adjacent pair of channels. - ChannelPanner: Pan the input between a linear series of channels, where
pan
0 = channel 0, 1 = channel 1, etc. No wrapping is applied. - SpatialPanner: Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported.
- StereoBalance: Takes a stereo input and rebalances it, where
balance
of 0
is unchanged, -1
is hard left, and 1
is hard right. - StereoPanner: Pans a mono input to a stereo output.
pan
should be between -1 (hard left) to +1 (hard right), with 0 = centre. - StereoWidth: Reduces the width of a stereo signal. When
width
= 1, input is unchanged. When width
= 0, outputs a pair of identical channels both containing L+R.
"},{"location":"library/processors/panning/azimuthpanner/","title":"AzimuthPanner node documentation","text":"Reference library > Processors: Panning > AzimuthPanner
"},{"location":"library/processors/panning/azimuthpanner/#azimuthpanner","title":"AzimuthPanner","text":"AzimuthPanner(num_channels=2, input=0, pan=0.0, width=1.0)\n
Pan input around an equally-spaced ring of num_channels
speakers. pan
is the pan position from -1..+1, where 0 = centre front. width
is the source's width, where 1.0 spans exactly between an adjacent pair of channels.
"},{"location":"library/processors/panning/channelpanner/","title":"ChannelPanner node documentation","text":"Reference library > Processors: Panning > ChannelPanner
"},{"location":"library/processors/panning/channelpanner/#channelpanner","title":"ChannelPanner","text":"ChannelPanner(num_channels=2, input=0, pan=0.0, width=1.0)\n
Pan the input between a linear series of channels, where pan
0 = channel 0, 1 = channel 1, etc. No wrapping is applied.
"},{"location":"library/processors/panning/spatialpanner/","title":"SpatialPanner node documentation","text":"Reference library > Processors: Panning > SpatialPanner
"},{"location":"library/processors/panning/spatialpanner/#spatialpanner","title":"SpatialPanner","text":"SpatialPanner(env=None, input=0.0, x=0.0, y=0.0, z=0.0, radius=1.0, use_delays=1.0, algorithm=\"dbap\")\n
Implements a spatial panning algorithm, applied to a given SpatialEnvironment. Currently, only DBAP is supported.
"},{"location":"library/processors/panning/stereobalance/","title":"StereoBalance node documentation","text":"Reference library > Processors: Panning > StereoBalance
"},{"location":"library/processors/panning/stereobalance/#stereobalance","title":"StereoBalance","text":"StereoBalance(input=0, balance=0)\n
Takes a stereo input and rebalances it, where balance
of 0
is unchanged, -1
is hard left, and 1
is hard right.
"},{"location":"library/processors/panning/stereobalance/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Demonstrating the effects of StereoBalance. First a low tone is assigned to \n# the left channel and a high tone is assigned to the right channel.\n# Setting StereoBalance's balance value to 0.0 will mean both tones are heard \n# equally. A value of -1.0 will result in only the left channel being heard. \n# A value of 1.0 will result in only the right channel being heard.\n# In this example, an LFO is modulating the balance value between -1.0 and 1.0.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\npanned = ChannelArray([low, high])\nbalanced = StereoBalance(panned, TriangleLFO(0.2, -1, 1)) * 0.5\nbalanced.play()\n
"},{"location":"library/processors/panning/stereopanner/","title":"StereoPanner node documentation","text":"Reference library > Processors: Panning > StereoPanner
"},{"location":"library/processors/panning/stereopanner/#stereopanner","title":"StereoPanner","text":"StereoPanner(input=0, pan=0.0)\n
Pans a mono input to a stereo output. pan
should be between -1 (hard left) to +1 (hard right), with 0 = centre.
"},{"location":"library/processors/panning/stereopanner/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using StereoPanner to pan a low pitch to the left and a high pitch to the\n# right.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\n\nleft = StereoPanner(low, -0.8)\nright = StereoPanner(high, 0.8)\n\noutput = (left + right) * 0.5\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using StereoPanner to repeatedly pan an arpeggiating oscillator between the \n# left and right channels.\n#-------------------------------------------------------------------------------\nclock = Impulse(8.0)\nCMaj7 = [ 60, 64, 67, 71, 74, 76 ] * 8\nFMaj9 = [ 65, 69, 72, 76, 77, 81 ] * 8\narpeggios = CMaj7 + FMaj9\nsequence = Sequence(arpeggios, clock)\nfrequency = MidiNoteToFrequency(sequence)\n\noscillator = TriangleOscillator(frequency)\nrelease = Line(0.1, 0.5, 12, True)\nenvelope = ASREnvelope(0.0, 0.0, release, 1.0, clock)\nvoice = oscillator * envelope\n\npan = SineLFO(0.1667, -1.0, 1.0)\noutput = StereoPanner(voice, pan)\noutput.play()\n
"},{"location":"library/processors/panning/stereowidth/","title":"StereoWidth node documentation","text":"Reference library > Processors: Panning > StereoWidth
"},{"location":"library/processors/panning/stereowidth/#stereowidth","title":"StereoWidth","text":"StereoWidth(input=0, width=1)\n
Reduces the width of a stereo signal. When width
= 1, input is unchanged. When width
= 0, outputs a pair of identical channels both containing L+R.
"},{"location":"library/processors/panning/stereowidth/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using StereoWidth to continuously alter the width of a stereo signal.\n#-------------------------------------------------------------------------------\nlow = TriangleOscillator(220)\nhigh = TriangleOscillator(660)\npanned = ChannelArray([low, high])\nwidth = StereoWidth(panned, TriangleLFO(0.5, 0, 1)) * 0.3\nwidth.play()\n
"},{"location":"library/processors/smooth/","title":"Smooth node documentation","text":"Reference library > Processors > Smooth
"},{"location":"library/processors/smooth/#smooth","title":"Smooth","text":"Smooth(input=None, smooth=0.99)\n
Smooth the input with a given smoothing coefficient. When smooth
= 0, applies no smoothing.
"},{"location":"library/processors/wetdry/","title":"WetDry node documentation","text":"Reference library > Processors > WetDry
"},{"location":"library/processors/wetdry/#wetdry","title":"WetDry","text":"WetDry(dry_input=None, wet_input=None, wetness=0.0)\n
Takes wet
and dry
inputs, and outputs a mix determined by wetness
.
"},{"location":"library/processors/wrap/","title":"Wrap node documentation","text":"Reference library > Processors > Wrap
"},{"location":"library/processors/wrap/#wrap","title":"Wrap","text":"Wrap(input=None, min=-1.0, max=1.0)\n
Wrap the input beyond min
/max
.
"},{"location":"library/sequencing/","title":"Sequencing","text":"Reference library > Sequencing
"},{"location":"library/sequencing/#sequencing","title":"Sequencing","text":" - ClockDivider: When given a
clock
input (e.g., an Impulse), divides the clock by the given factor
. factor must be an integer greater than or equal to 1. - Counter: Count upwards from
min
to max
, driven by clock
. - Euclidean: Euclidean rhythm as described by Toussaint, with
sequence_length
(n) and num_events
(k), driven by clock
. - FlipFlop: Flips from 0/1 on each
clock
. - ImpulseSequence: Each time a
clock
or trigger is received, outputs the next value in sequence
. At all other times, outputs zero. - Index: Outputs the value in
list
corresponding to index
. - Latch: Initially outputs 0. When a trigger is received at
set
, outputs 1. When a trigger is subsequently received at reset
, outputs 0, until the next set
. - Sequence: Outputs the elements in
sequence
, incrementing position on each clock
.
"},{"location":"library/sequencing/clockdivider/","title":"ClockDivider node documentation","text":"Reference library > Sequencing > ClockDivider
"},{"location":"library/sequencing/clockdivider/#clockdivider","title":"ClockDivider","text":"ClockDivider(clock=0, factor=1)\n
When given a clock
input (e.g., an Impulse), divides the clock by the given factor
. factor must be an integer greater than or equal to 1.
"},{"location":"library/sequencing/clockdivider/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using a ClockDivider to create rhythms related to the main clock. Here the \n# oscillator panned left is heard on every tick of the clock. The oscillator \n# panned right is heard every 3 ticks of the clock.\n#-------------------------------------------------------------------------------\nclock = Impulse(2.0)\ndivided_clock = ClockDivider(clock, 3)\n\noscillator_a = TriangleOscillator(220)\noscillator_b = TriangleOscillator(440)\n\nenvelope_a = ASREnvelope(0.01, 0.0, 0.25, 1.0, clock)\nenvelope_b = ASREnvelope(0.01, 0.0, 0.5, 1.0, divided_clock)\n\nvoice_a = oscillator_a * envelope_a * 0.5\nvoice_b = oscillator_b * envelope_b * 0.5\n\nleft = StereoPanner(voice_a, -0.75)\nright = StereoPanner(voice_b, 0.75)\n\nleft.play()\nright.play()\n
"},{"location":"library/sequencing/counter/","title":"Counter node documentation","text":"Reference library > Sequencing > Counter
"},{"location":"library/sequencing/counter/#counter","title":"Counter","text":"Counter(clock=0, min=0, max=2147483647)\n
Count upwards from min
to max
, driven by clock
.
"},{"location":"library/sequencing/euclidean/","title":"Euclidean node documentation","text":"Reference library > Sequencing > Euclidean
"},{"location":"library/sequencing/euclidean/#euclidean","title":"Euclidean","text":"Euclidean(clock=0, sequence_length=0, num_events=0)\n
Euclidean rhythm as described by Toussaint, with sequence_length
(n) and num_events
(k), driven by clock
.
"},{"location":"library/sequencing/flipflop/","title":"FlipFlop node documentation","text":"Reference library > Sequencing > FlipFlop
"},{"location":"library/sequencing/flipflop/#flipflop","title":"FlipFlop","text":"FlipFlop(clock=0)\n
Flips from 0/1 on each clock
.
"},{"location":"library/sequencing/impulsesequence/","title":"ImpulseSequence node documentation","text":"Reference library > Sequencing > ImpulseSequence
"},{"location":"library/sequencing/impulsesequence/#impulsesequence","title":"ImpulseSequence","text":"ImpulseSequence(sequence=std::vector<int> ( ), clock=None)\n
Each time a clock
or trigger is received, outputs the next value in sequence
. At all other times, outputs zero.
"},{"location":"library/sequencing/index/","title":"Index node documentation","text":"Reference library > Sequencing > Index
"},{"location":"library/sequencing/index/#index","title":"Index","text":"Index(list={}, index=0)\n
Outputs the value in list
corresponding to index
.
"},{"location":"library/sequencing/latch/","title":"Latch node documentation","text":"Reference library > Sequencing > Latch
"},{"location":"library/sequencing/latch/#latch","title":"Latch","text":"Latch(set=0, reset=0)\n
Initially outputs 0. When a trigger is received at set
, outputs 1. When a trigger is subsequently received at reset
, outputs 0, until the next set
.
"},{"location":"library/sequencing/sequence/","title":"Sequence node documentation","text":"Reference library > Sequencing > Sequence
"},{"location":"library/sequencing/sequence/#sequence","title":"Sequence","text":"Sequence(sequence=std::vector<float> ( ), clock=None)\n
Outputs the elements in sequence
, incrementing position on each clock
.
"},{"location":"library/sequencing/sequence/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Creating a sequence using the MIDI note values of a C Major scale, starting on\n# middle C.\n#-------------------------------------------------------------------------------\nclock = Impulse(2.0)\nsequence = Sequence([ 60, 62, 64, 65, 67, 69, 71, 72 ], clock)\nfrequency = MidiNoteToFrequency(sequence)\noscillator = TriangleOscillator(frequency)\noscillator.play()\n
"},{"location":"library/stochastic/","title":"Stochastic","text":"Reference library > Stochastic
"},{"location":"library/stochastic/#stochastic","title":"Stochastic","text":" - Logistic: Logistic noise.
- PinkNoise: Pink noise, with specified low/high cutoffs.
- RandomBrownian: Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick.
- RandomChoice: Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick.
- RandomCoin: Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick.
- RandomExponentialDist: Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick.
- RandomExponential: Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick.
- RandomGaussian: Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick.
- RandomImpulseSequence: Generates a random sequence of 0/1 bits with the given length, and the given probability each each bit = 1. The position of the sequence is incremented on each clock signal. explore and generate are trigger inputs which cause the sequence to mutate and re-generate respectively.
- RandomImpulse: Generate random impulses at the given frequency, with either uniform or poisson distribution.
- RandomUniform: Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick.
- WhiteNoise: Generates whitenoise between min/max. If frequency is zero, generates at audio rate. For frequencies lower than audio rate, interpolate applies linear interpolation between values, and random_interval specifies whether new random values should be equally-spaced or randomly-spaced.
"},{"location":"library/stochastic/logistic/","title":"Logistic node documentation","text":"Reference library > Stochastic > Logistic
"},{"location":"library/stochastic/logistic/#logistic","title":"Logistic","text":"Logistic(chaos=3.7, frequency=0.0)\n
Logistic noise.
"},{"location":"library/stochastic/pinknoise/","title":"PinkNoise node documentation","text":"Reference library > Stochastic > PinkNoise
"},{"location":"library/stochastic/pinknoise/#pinknoise","title":"PinkNoise","text":"PinkNoise(low_cutoff=20.0, high_cutoff=20000.0, reset=None)\n
Pink noise, with specified low/high cutoffs.
"},{"location":"library/stochastic/randombrownian/","title":"RandomBrownian node documentation","text":"Reference library > Stochastic > RandomBrownian
"},{"location":"library/stochastic/randombrownian/#randombrownian","title":"RandomBrownian","text":"RandomBrownian(min=-1.0, max=1.0, delta=0.01, clock=None, reset=None)\n
Outputs Brownian noise between min/max, with a mean change of delta between samples. If a clock is passed, only generates a new value on a clock tick.
"},{"location":"library/stochastic/randomchoice/","title":"RandomChoice node documentation","text":"Reference library > Stochastic > RandomChoice
"},{"location":"library/stochastic/randomchoice/#randomchoice","title":"RandomChoice","text":"RandomChoice(values=std::vector<float> ( ), clock=None, reset=None)\n
Pick a random value from the given array. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomcoin/","title":"RandomCoin node documentation","text":"Reference library > Stochastic > RandomCoin
"},{"location":"library/stochastic/randomcoin/#randomcoin","title":"RandomCoin","text":"RandomCoin(probability=0.5, clock=None, reset=None)\n
Flip a coin with the given probability. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomexponential/","title":"RandomExponential node documentation","text":"Reference library > Stochastic > RandomExponential
"},{"location":"library/stochastic/randomexponential/#randomexponential","title":"RandomExponential","text":"RandomExponential(min=0.001, max=1.0, clock=None, reset=None)\n
Generate an random exponential value between min/max. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomexponentialdist/","title":"RandomExponentialDist node documentation","text":"Reference library > Stochastic > RandomExponentialDist
"},{"location":"library/stochastic/randomexponentialdist/#randomexponentialdist","title":"RandomExponentialDist","text":"RandomExponentialDist(scale=0.0, clock=None, reset=None)\n
Generate an random value following the exponential distribution. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomgaussian/","title":"RandomGaussian node documentation","text":"Reference library > Stochastic > RandomGaussian
"},{"location":"library/stochastic/randomgaussian/#randomgaussian","title":"RandomGaussian","text":"RandomGaussian(mean=0.0, sigma=0.0, clock=None, reset=None)\n
Generate an random Gaussian value, with given mean and sigma. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/randomimpulse/","title":"RandomImpulse node documentation","text":"Reference library > Stochastic > RandomImpulse
"},{"location":"library/stochastic/randomimpulse/#randomimpulse","title":"RandomImpulse","text":"RandomImpulse(frequency=1.0, distribution=SIGNALFLOW_EVENT_DISTRIBUTION_UNIFORM, reset=None)\n
Generate random impulses at the given frequency, with either uniform or poisson distribution.
"},{"location":"library/stochastic/randomimpulsesequence/","title":"RandomImpulseSequence node documentation","text":"Reference library > Stochastic > RandomImpulseSequence
"},{"location":"library/stochastic/randomimpulsesequence/#randomimpulsesequence","title":"RandomImpulseSequence","text":"RandomImpulseSequence(probability=0.5, length=8, clock=None, explore=None, generate=None, reset=None)\n
Generates a random sequence of 0/1 bits with the given length, and the given probability each each bit = 1. The position of the sequence is incremented on each clock signal. explore and generate are trigger inputs which cause the sequence to mutate and re-generate respectively.
"},{"location":"library/stochastic/randomuniform/","title":"RandomUniform node documentation","text":"Reference library > Stochastic > RandomUniform
"},{"location":"library/stochastic/randomuniform/#randomuniform","title":"RandomUniform","text":"RandomUniform(min=0.0, max=1.0, clock=None, reset=None)\n
Generates a uniformly random value between min/max. If a clock is passed, only picks a new value on a clock tick.
"},{"location":"library/stochastic/whitenoise/","title":"WhiteNoise node documentation","text":"Reference library > Stochastic > WhiteNoise
"},{"location":"library/stochastic/whitenoise/#whitenoise","title":"WhiteNoise","text":"WhiteNoise(frequency=0.0, min=-1.0, max=1.0, interpolate=true, random_interval=true, reset=None)\n
Generates whitenoise between min/max. If frequency is zero, generates at audio rate. For frequencies lower than audio rate, interpolate applies linear interpolation between values, and random_interval specifies whether new random values should be equally-spaced or randomly-spaced.
"},{"location":"library/stochastic/whitenoise/#examples","title":"Examples","text":"#-------------------------------------------------------------------------------\n# Using white noise to control the pitch of an oscillator.\n# A new pitch is determined once every second. Interpolation is turned off so \n# that the oscillator jumps to the new pitch instead of smoothly moving to it.\n# Random interval is turned off so that pitch changes occur at a regular rate.\n#-------------------------------------------------------------------------------\nfrequency = WhiteNoise( frequency=1,\n min=100, \n max=1000, \n interpolate=False, \n random_interval=False)\noscillator = SineOscillator(frequency)\noutput = StereoPanner(oscillator) * 0.5\noutput.play()\n
#-------------------------------------------------------------------------------\n# Using white noise to simulate the sound of wind.\n# White noise is generated at audio rate and passed into a band-pass filter.\n# The cutoff of the filter is controlled by another white noise generator, which\n# generates a new value between 100 and 300 at randomly-spaced intervals every \n# second, and smoothly interpolates between these values.\n#-------------------------------------------------------------------------------\nnoise = WhiteNoise()\ncutoff = WhiteNoise(1, 100, 300, True, True)\nfiltered = SVFilter(input=noise,\n filter_type= \"band_pass\", \n cutoff=cutoff,\n resonance=0.8)\noutput = StereoPanner(filtered) * 0.5\noutput.play()\n
"},{"location":"node/","title":"Nodes","text":"A Node
object is an audio processing unit that performs one single function. For example, a Node's role may be to synthesize a waveform, read from a buffer, or take two input Nodes and sum their values.
- Nodes are played and stopped by connecting them to the AudioGraph
- A node has one or more audio-rate inputs, which can be modulated by other nodes \u2014 for example, a filter node has inputs for
cutoff
and resonance
- Some nodes can be triggered with trigger inputs \u2014 for example, to restart playback, or set the position of an envelope
- Some nodes can be used to play back the contents of buffer inputs, or can use buffer data as a source of modulation \u2014 for example, the
Granulator
node plays grains of audio from one buffer, and takes another buffer to shape the envelope of each grain - The output of multiple nodes can be combined and modulated with use of the standard Python operators (
+
, -
, *
, %
, etc) - The output of a node can be mono (single-channel) or multichannel
- A Node's status and output can be examined by querying its properties
- Some Nodes generate unpredictable stochastic output, which can be controlled via its internal random number generator
- Details of how to create a new Node type are detailed in Developing a new Node class
For an overview of every type of Node available in SignalFlow, see the Node Reference Library
\u2192 Next: Node playback
"},{"location":"node/developing/","title":"Nodes","text":""},{"location":"node/developing/#developing-new-node-classes","title":"Developing new Node classes","text":"See CONTRIBUTING.md
"},{"location":"node/inputs/","title":"Nodes","text":""},{"location":"node/inputs/#node-inputs","title":"Node inputs","text":"A node has three different classes of input:
- Audio-rate inputs: Takes the output of another node as an input, for continuous modulation of synthesis parameters
- Trigger inputs: Used to trigger discrete control events \u2014 for example, restarting buffer playback
- Buffer inputs: Used to pass the contents of an audio buffer to a node \u2014 for example, as a source of audio samples, or an envelope shape
"},{"location":"node/inputs/#audio-rate-inputs","title":"Audio-rate inputs","text":"Virtually every node has one or more audio-rate inputs. Put simply, an audio-rate input is the output of another node. Let's look at a short example:
lfo = SineLFO()\nsignal = SquareOscillator(frequency=200, width=lfo)\n
In this case, we are passing the output of a SineLFO
as the pulse width of a SquareOscillator
. This is an audio-rate input.
Although it's not obvious, the frequency
parameter is also an audio-rate input. Any constant value (such as the 200
here) is behind the scenes implemented as a Constant
node, which continuously outputs the value at an audio rate.
All audio-rate inputs can be modified just like a normal Python property. For example:
signal.frequency = TriangleOscillator(0.5, 100, 1000)\n
"},{"location":"node/inputs/#variable-input-nodes","title":"Variable input nodes","text":"Some nodes have a variable number of inputs, which can change over the Node's lifetime. For example, Sum()
takes an arbitrary number of input Nodes, and generates an output which is the sum of all of its inputs.
For variable-input nodes such as this, audio-rate inputs are added with add_input()
, and can be removed with remove_input()
.
a = Constant(1)\nb = Constant(2)\nc = Constant(3)\nsum = Sum()\nsum.add_input(a)\nsum.add_input(b)\nsum.add_input(c)\n# sum will now generate an output of 6.0\n
It is possible to check whether a Node object takes variable inputs by querying node.has_variable_inputs
.
"},{"location":"node/inputs/#triggers","title":"Triggers","text":"When working with sequencing and timing, it is often useful be able to trigger discrete events within a node. This is where trigger inputs come in handy.
There are two different ways to handle trigger inputs:
- by calling the
trigger()
method on a Node
- by passing a Node to an input that corresponds to an audio-rate trigger
"},{"location":"node/inputs/#calling-trigger","title":"Calling trigger()","text":"To generate trigger events at arbitrary times, call node.trigger()
. For example:
freq_env = Line(10000, 100, 0.5)\nsine = SineOscillator(freq_env)\nsine.play()\nwhile True:\n freq_env.trigger()\n graph.wait(1)\n
This is useful because it can be done outside the audio thread. For example, trigger()
could be called each time a MIDI note event is received.
The trigger()
method takes an optional name
parameter, which is used by Node
classes containing more than one type of trigger. This example uses the set_position
trigger of BufferPlayer
to seek to a new location in the sample every second.
buffer = Buffer(\"../audio/stereo-count.wav\")\nplayer = BufferPlayer(buffer, loop=True)\nplayer.play()\nwhile True:\n player.trigger(\"set_position\", random_uniform(0, buffer.duration))\n graph.wait(1)\n
Note
Because the trigger
method happens outside the audio thread, it will take effect at the start of the next audio block. This means that, if you are running at 44.1kHz with an audio buffer size of 1024 samples, this could introduce a latency of up to 1024/44100 = 0.023s
. For time-critical events like drum triggers, this can be minimised by reducing the hardware output buffer size.
This constraint also means that only one event can be triggered per audio block. To trigger events at a faster rate than the hardware buffer size allows, see Audio-rate triggers below.
"},{"location":"node/inputs/#audio-rate-triggers","title":"Audio-rate triggers","text":"It is often desirable to trigger events using the audio-rate output of another Node object as a source of trigger events, to give sample-level precision in timing. Most nodes that support trigger
inputs can also be triggered by a corresponding audio-rate input.
Triggers happen at zero-crossings \u2014 that is, when the output of the node passes above zero (i.e., from <= 0
to >0
). For example, to create a clock with an oscillating tempo to re-trigger buffer playback:
clock = Impulse(SineLFO(0.2, 1, 10))\nbuffer = Buffer(\"examples/audio/stereo-count.wav\")\nplayer = BufferPlayer(buffer, loop=True, clock=clock)\nplayer.play()\n
This can be used to your advantage with the boolean operator nodes.
on_the_right = MouseX() > 0.5\nenvelope = ASREnvelope(0, 0, 0.5, clock=on_the_right)\nsquare = SquareOscillator(100)\noutput = envelope * square * 0.1\noutput.play()\n
TODO: Should the name of the trigger() event always be identical to the trigger input name? So clock
for envelopes, buffer player, etc...?
"},{"location":"node/inputs/#buffer-inputs","title":"Buffer inputs","text":"The third type of input supported by nodes is the buffer. Nodes often take buffer inputs as sources of audio samples. They are also useful as sources of envelope shape data (for example, to shape the grains of a Granulator), or general control data (for example, recording motion patterns from a MouseX
input).
buffer = Buffer(\"audio/stereo-count.wav\")\nplayer = BufferPlayer(buffer, loop=True)\n
A buffer input cannot be set using the same property shorthand as audio-rate inputs; instead, the set_buffer
method should be used.
new_buffer = Buffer(\"audio/example.wav\")\nplayer.set_buffer(\"buffer\", new_buffer)\n
TODO: Should this be set_input
for consistency with Patch?
"},{"location":"node/inputs/#enumerating-a-nodes-inputs","title":"Enumerating a node's inputs","text":"To list the potential and actual inputs of a node, the .inputs
property returns a dict
of key-value pairs:
>>> player.inputs\n{\n 'clock': <signalflow.Impulse at 0x107778eb0>,\n 'end_time': None,\n 'loop': <signalflow.Constant at 0x12a4cd4b0>,\n 'rate': <signalflow.Constant at 0x12a4cd330>,\n 'start_time': None\n}\n
Any constant-valued inputs are wrapped inside a special Constant
node class. The value contained by a Constant
can be accessed with its .value
property.
"},{"location":"node/inputs/#playerinputsratevalue-10","title":">>> player.inputs[\"rate\"].value\n1.0\n
","text":"\u2192 Next: Operators
"},{"location":"node/multichannel/","title":"Nodes","text":""},{"location":"node/multichannel/#multichannel-nodes","title":"Multichannel nodes","text":"When passing a value to audio-rate input of a Node, the signal is by default monophonic (single-channel). For example, SquareOscillator(440)
generates a 1-channel output.
It is possible to generate multi-channel output by passing an array of values in the place of a constant. For example, SquareOscillator([440, 880])
generates stereo output with a different frequency in the L and R channels.
There is no limit to the number of channels that can be generated by a node. For example, SquareOscillator(list(100 + 50 * n for n in range(100)))
will create a node with 100-channel output, each with its own frequency.
>>> sq = SquareOscillator([100 + 50 * n for n in range(100)])\n>>> print(sq.num_output_channels)\n100\n
"},{"location":"node/multichannel/#automatic-upmixing","title":"Automatic upmixing","text":"There are generally multiple inputs connected to a node, which may themselves have differing number of channels. For example, SquareOscillator(frequency=[100, 200, 300, 400, 500], width=0.7)
has a 5-channel input and a 1-channel input. In cases like this, the output of the nodes with fewer channels is upmixed to match the higher-channel inputs.
Upmixing here means simply duplicating the output until it reaches the desired number of channels. In the above case, the width
input will be upmixed to generate 5 channels, all containing 0.7
.
If width
were a stereo input with L and R channels, the output would be tiled, alternating between the channels. Each frame of stereo input would then be upmixed to contain [L, R, L, R, L]
, where L
and R
are the samples corresponding to the L and R channels.
The key rule is that, for nodes that support upmixing, the output signal has as many channels as the input signal with the highest channel count.
This process percolates through the signal chain. For example:
SquareOscillator(frequency=SineLFO([1, 3, 5], min=440, max=880),\n width=SawLFO([0.5, 0.6], min=0.25, max=0.75))\n
- The
min
and max
inputs of the frequency
LFO would be upmixed to 3 channels each - The
min
and max
inputs of the width
LFO would be upmixed to 2 channels each - Then, the output of the
width
node would be upmixed from 2 to 3 channels
"},{"location":"node/multichannel/#nodes-with-fixed-inputoutput-channels","title":"Nodes with fixed input/output channels","text":"Some nodes have immutable numbers of input/output channels. For example:
StereoPanner
has 1 input channel and 2 output channels StereoBalance
has 2 input channels and 2 output channels ChannelMixer
has an arbitrary number of input channels, but a fixed, user-specified number of output channels
Even Nodes that do not have an obvious input (e.g. BufferPlayer
) have input channels, for modulation inputs (for example, modulating the rate of the buffer).
When two nodes are connected together with incompatible channel counts (for example, connecting a StereoBalance
into a StereoMixer
), an InvalidChannelCountException
will be raised.
"},{"location":"node/multichannel/#the-channel-node-classes","title":"The Channel* node classes","text":"There are a number of Node subclasses dedicated to channel handling.
- ChannelArray: Concatenates the channels of multiple nodes, so that calling
ChannelMix
with nodes of N
and M
channels will produce an output of N + M
channels. - ChannelMixer: Reduces or expands the number of channels by evenly spreading the audio across the output channels.
- ChannelSelect: Selects sub-channels of the input, either individually or by group.
"},{"location":"node/multichannel/#querying-channel-subsets-with-the-index-operator","title":"Querying channel subsets with the index operator","text":"Single channels of a multi-channel node can be accessed using the index []
operator. For example:
square = SquareOscillator([440, 441, 442, 443])\noutput = square[0]\n# output now contains a mono output, with a frequency of 440Hz.\n
Slice syntax can be used to query multiple subchannels:
square = SquareOscillator([440, 441, 442, 880])\noutput = square[0:2]\n# now contains a two-channel square wave\n
\u2192 Next: Status and properties
"},{"location":"node/operators/","title":"Nodes","text":""},{"location":"node/operators/#node-operators","title":"Node operators","text":""},{"location":"node/operators/#arithmetic","title":"Arithmetic","text":"The output of multiple nodes can be combined using Python's mathematical operators. For example, to sum two sine waves together to create harmonics, use the +
operator:
output = SineOscillator(440) + SineOscillator(880)\noutput.play()\n
To modulate the amplitude of one node with another, use the *
operator:
sine = SineOscillator(440)\nenvelope = ASREnvelope(0.1, 1, 0.1)\noutput = sine * envelope\n
You can use constant values in place of Node
objects:
sine = SineOscillator(440)\nattenuated = sine * 0.5\n
Operators can be chained together in the normal way:
# Create an envelope that rises from 0.5 to 1.0 and back to 0.5\nenv = (ASREnvelope(0.1, 1, 0.1) * 0.5) + 0.5\n
Behind the scenes, these operators are actually creating composites of Node
subclasses. The last example could alternatively be written as:
Add(Multiply(ASREnvelope(0.1, 1, 0.1), 0.5), 0.5)\n
"},{"location":"node/operators/#comparison","title":"Comparison","text":"Comparison operators can also be used to compare two Node output values, generating a binary (1/0) output. For example:
# Generates an output of 1 when the sinusoid is above 0, and 0 otherwise \nSineOscillator(440) > 0\n
This can then be used as an input to other nodes. The below will generate a half-wave-rectified sine signal (that is, a sine wave with all negative values set to zero).
sine = SineOscillator(440)\nrectified = sine * (sine > 0)\n
"},{"location":"node/operators/#index-of-operators","title":"Index of operators","text":"Below is a full list of operators supported by SignalFlow.
"},{"location":"node/operators/#arithmetic-operators","title":"Arithmetic operators","text":"Operator Node class +
Add -
Subtract *
Multiply /
Divide **
Power %
Modulo"},{"location":"node/operators/#comparison-operators","title":"Comparison operators","text":"Operator Node class ==
Equal !=
NotEqual <
LessThan <=
LessThanOrEqual >
GreaterThan >=
GreaterThanOrEqual \u2192 Next: Multichannel
"},{"location":"node/playback/","title":"Nodes","text":""},{"location":"node/playback/#playing-and-stopping-a-node","title":"Playing and stopping a node","text":""},{"location":"node/playback/#starting-playback","title":"Starting playback","text":"To start a node playing, simply call the play()
method:
graph = AudioGraph()\nnode = SineOscillator(440)\nnode.play()\n
This connects the node to the output
endpoint of the current global AudioGraph
. The next time the graph processes a block of samples, the graph's output
node then calls upon the sine oscillator to generate a block.
It is important to remember that playing a node means \"connecting it to the graph\". For this reason, it is not possible to play the same node more than once, as it is already connected to the graph. To play multiples of a particular Node type, simply create and play multiple instances.
"},{"location":"node/playback/#connecting-a-node-to-another-nodes-input","title":"Connecting a Node to another Node's input","text":"It is often the case that you want to connect a Node to the input of another Node for playback, rather than simply wiring it to the output of a graph -- for example, to pass an oscillator through a processor. In this case, you do not need to call play()
(which means \"connect this node to the graph\"). Instead, it is sufficient to simply connect the Node to the input of another Node that is already playing.
For example:
# create and begin playback of a variable input summer, passed through a filter\nsum = Sum()\nflt = SVFilter(sum, \"low_pass\", 200)\nflt.play()\n
Now, let's create an oscillator. Observe that connecting the oscillator to the filter's input begins playback immediately.
square = SquareOscillator(100)\nsum.add_input(square)\n
"},{"location":"node/playback/#stopping-playback","title":"Stopping playback","text":"To stop a node playing:
node.stop()\n
This disconnects the node from the output device that it is connected to.
\u2192 Next: Inputs
"},{"location":"node/properties/","title":"Nodes","text":""},{"location":"node/properties/#node-properties","title":"Node properties","text":"A Node
has a number of read-only properties which can be used to query its status at a given moment in time.
Property Type Description name str Short alphanumeric string that identifies the type of node (for example, asr-envelope
) num_output_channels int The number of output channels that the node generates. num_input_channels int The number of input channels that the node takes. Note that most nodes have matches_input_channels
set, meaning that their num_input_channels
will be automatically increased according to their inputs. To learn more, see Nodes: Multichannel. matches_input_channels bool Whether the node automatically increases its num_input_channels
based on its inputs. To learn more, see Nodes: Multichannel. has_variable_inputs bool Whether the node supports an arbitrary number of audio-rate inputs output_buffer numpy.ndarray Contains the Node's most recent audio output, in float32
samples. The buffer is indexed by channel
x frame
, so to obtain the 32nd sample in the first channel, query: node.output_buffer[0][31]
. inputs dict A dict containing all of the Node
's audio-rate inputs. Note that buffer inputs are not currently included within this dict. state int The Node's current playback state, which can be one of SIGNALFLOW_NODE_STATE_ACTIVE
and SIGNALFLOW_NODE_STATE_STOPPED
. The STOPPED
state only applies to those nodes which have a finite duration (e.g. ASREnvelope
, or BufferPlayer
with looping disabled) and have reached the end of playback. Nodes continue to have a state of ACTIVE
whether or not they are connected to the graph. patch Patch Indicates the Patch that the node is part of, or None if the Node does not belong to a Patch."},{"location":"node/properties/#monitoring-a-nodes-output","title":"Monitoring a node's output","text":"To monitor the output of a node, call node.poll(num_seconds)
, where num_seconds
is the interval between messages. This will print the last sample generated by the node to stdout
. In the case of multichannel nodes, only the first channel's value is printed.
>>> a = Counter(Impulse(1))\n>>> a.poll(1)\n>>> a.play()\ncounter: 0.00000\ncounter: 1.00000\ncounter: 2.00000\n
To stop polling a node, call node.poll(0)
.
"},{"location":"node/properties/#node-specific-properties","title":"Node-specific properties","text":"Some Node
classes have additional properties, containing information on implementation-specific states. These can be accessed via the get_property
method.
For example, the BufferPlayer
node exposes a position
property, which returns the playhead's current position, in seconds.
>>> buffer = Buffer(\"audio.wav\")\n>>> player = BufferPlayer(buffer)\n>>> player.play()\n...\n>>> player.get_property(\"position\")\n5.984000205993652\n
\u2192 Next: Stochastic nodes
"},{"location":"node/stochastic/","title":"Nodes","text":""},{"location":"node/stochastic/#chance-and-stochastic-nodes","title":"Chance and stochastic nodes","text":"SignalFlow has a number of stochastic nodes, which make use of a pseudo-random number generator (RNG) to produce unpredictable output values.
Each object of these StochasticNode
subclasses stores its own RNG. By default, the RNG is seeded with a random value, so that each run will generate a different set of outputs. However, to create a repeatable pseudo-random output, the seed
of the node's RNG can be set to a known value:
>>> r = RandomUniform(0, 1)\n>>> r.process(1024)\n>>> r.output_buffer[0][:4]\narray([0.48836085, 0.64326525, 0.79819506, 0.8489549 ], dtype=float32)\n>>> r.set_seed(123)\n>>> r.process(1024)\n>>> r.output_buffer[0][:4]\narray([0.7129553 , 0.42847094, 0.6908848 , 0.7191503 ], dtype=float32)\n>>> r.set_seed(123)\n>>> r.process(1024)\n>>> r.output_buffer[0][:4]\narray([0.7129553 , 0.42847094, 0.6908848 , 0.7191503 ], dtype=float32)\n
Note the identical sequences generated after repeatedly setting the seed to a known value.
Warning
Calling node.process()
is generally not good practice, as it does not recursively process all of the node's inputs (unlike when a node is embedded within an AudioGraph, which correctly handles recursion and cyclical loops). Please use at your peril!
\u2192 Next: Node reference library
"},{"location":"patch/","title":"Patch","text":"Warning
This documentation is a work-in-progress and may have sections that are missing or incomplete.
A Patch
represents a connected group of Nodes
, analogous to a synthesizer. Defining patches makes it easy to create higher-level structures, which can then be reused and instantiated with a single line of code, in much the same way as a Node.
Behind the scenes, the structure of a Patch
is encapsulated by a PatchSpec
, a template which can be instantiated or serialised to a JSON file for later use.
- A Patch structure is defined either by declaring a Patch subclass or with a JSON specification file
- Play and stop a Patch by connecting it to the AudioGraph or the input of another Patch or Node
- Similar to nodes, a Patch can be modulated by audio-rate inputs, triggered by trigger inputs, and access sample data via buffer inputs
- The outputs of Patches can be altered or combined by normal Python operators
- The status of a Patch can be queried via its properties
- Patches can be exported and imported to JSON
- The auto-free mechanism allows Patches to automatically stop and free their memory after playback is complete
\u2192 Next: Defining a Patch
"},{"location":"patch/auto-free/","title":"Patch","text":""},{"location":"patch/auto-free/#auto-free-and-memory-management","title":"Auto-free and memory management","text":"Auto-free.
"},{"location":"patch/defining/","title":"Patch","text":""},{"location":"patch/defining/#defining-a-patch","title":"Defining a Patch","text":"A Patch is made up of a connected network of Nodes, together with a set of properties that determine how the Patch can be controlled.
There are two general ways to define the structure of a Patch:
- Create a new class that subclasses
Patch
. In general, this is the recommended approach for defining new Patches. - Create a JSON file that can be loaded as a
PatchSpec
, which describes the structure of a patch
"},{"location":"patch/defining/#creating-a-patch-subclass","title":"Creating a Patch subclass","text":"The quickest and most intuitive way to define a Patch
is by subclassing the Patch
class itself. Let's look at an example.
class Bleep (Patch):\n def __init__(self, frequency=880, duration=0.1):\n super().__init__()\n frequency = self.add_input(\"frequency\", frequency)\n duration = self.add_input(\"duration\", duration)\n sine = SineOscillator(frequency)\n env = ASREnvelope(0.001, duration, 0.001)\n output = sine * env\n self.set_output(output)\n self.set_auto_free(True)\n
In the above example:
- At the very start of the
__init__
function, super().__init__()
must be called to initialise the Patch and its storage. This is vital! Without it, your program will crash. - Two audio-rate input parameters are defined. The
add_input()
method is used to define them as inputs of the Patch
, which can then be subsequently modulated. Note that the add_input()
method returns a reference to the frequency node, which then acts as a pointer to the input node. self.set_output()
is used to define the Patch's output. A Patch can only have one single output. - Finally,
self.set_auto_free()
is used to automatically stop and free the Patch after playback of the envelope is completed. More about auto-free...
You can now instantiate a Bleep
object in just the same way as you would instantiate and play a Node:
b = Bleep(frequency=440, duration=0.2)\nb.play()\n
If you query graph.status
after playback has finished, you should see that the Patch
is automatically freed and the number of nodes returns to 0.
"},{"location":"patch/defining/#creating-a-patchspec-from-json","title":"Creating a PatchSpec from JSON","text":"The structure of a Patch
is described by a PatchSpec
, which can in turn be imported/exported in the JSON text-based data interchange format.
For information on loading or saving PatchSpecs as JSON, see Exporting and importing patches.
\u2192 Next: Playing and stopping a Patch
"},{"location":"patch/exporting/","title":"Patch","text":""},{"location":"patch/exporting/#exporting-and-importing-patches","title":"Exporting and importing patches","text":"A Patch can be exported or imported.
\u2192 Next: Auto-free and memory management
"},{"location":"patch/inputs/","title":"Patch","text":""},{"location":"patch/inputs/#patch-inputs","title":"Patch inputs","text":"Just like a Node, a Patch supports three different classes of input:
- Audio-rate inputs: Takes the output of another Node or Patch as an input, for continuous modulation of synthesis parameters
- Trigger inputs: Used to trigger discrete control events \u2014 for example, restarting buffer playback
- Buffer inputs: Used to pass the contents of an audio buffer to a patch \u2014 for example, as a source of audio samples, or an envelope shape
"},{"location":"patch/inputs/#audio-rate-inputs","title":"Audio-rate inputs","text":"A Patch supports any number of user-defined named inputs, which can be used to modulate the nodes within the patch.
Each input must be defined by calling add_input()
when the Patch is first defined, with an optional default value.
Info
Note that Patches do not yet support variable inputs.
When a Patch is playing, the value of its inputs can be set using patch.set_input()
:
class Bloop (Patch):\n def __init__(self, frequency=880, duration=0.1):\n super().__init__()\n frequency = self.add_input(\"frequency\", frequency)\n sine = SineOscillator(frequency)\n self.set_output(sine)\n self.set_auto_free(True)\n\nbloop = Bloop()\nbloop.play()\n...\nbloop.set_input(\"frequency\", 100)\n
Info
Note that Patches do not yet support setting inputs with Python properties (e.g. patch.prop_name = 123
), as is possible with node inputs.
"},{"location":"patch/inputs/#triggers","title":"Triggers","text":"When defining a Patch
, it is possible to define which Node should receive trigger()
events sent to the Patch. This is done with patch.set_trigger_node()
:
class Hat (Patch):\n def __init__(self, duration=0.1):\n super().__init__()\n duration = self.add_input(\"duration\", duration)\n noise = WhiteNoise()\n env = ASREnvelope(0.0001, 0.0, duration, curve=2)\n output = noise * env\n self.set_trigger_node(env)\n self.set_output(output)\n\nh = Hat()\nh.play()\n...\nh.trigger() # triggers a hit, resetting the ASREnvelope to its start point\n
This can be used to create a Patch
that stays connected to the AudioGraph and can be retriggered to play a hit.
Info
Note that Patches only presently support trigger events directed to a single node within the patch, and cannot route triggers to multiple different nodes.
"},{"location":"patch/inputs/#buffer-inputs","title":"Buffer inputs","text":"Buffer inputs can be declared at define time by calling self.add_buffer_input()
. Similar to add_input
, the return value is a placeholder Buffer
that can be used wherever you would normally pass a Buffer
:
class WobblyPlayer (Patch):\n def __init__(self, buffer):\n super().__init__()\n buffer = self.add_buffer_input(\"buffer\", buffer)\n rate = SineLFO(0.2, 0.5, 1.5)\n player = BufferPlayer(buffer, rate=rate, loop=True)\n self.set_output(player)\n\nbuffer = Buffer(\"examples/audio/stereo-count.wav\")\nplayer = WobblyPlayer(buffer)\nplayer.play()\n
The buffer can then be replaced at runtime by calling set_input()
:
player.set_input(\"buffer\", another_buffer)\n
\u2192 Next: Operators
"},{"location":"patch/operators/","title":"Patch","text":""},{"location":"patch/operators/#operators","title":"Operators","text":"The output of a Patch can be amplified, attenuated, combined, modulated and compared using Python operators, in much the same way as Node:
patch = Patch(patch_spec)\noutput = patch * 0.5\n
For a full list of the operators that can be applied to a Patch
, see Node operators.
\u2192 Next: Patch properties
"},{"location":"patch/playback/","title":"Patch","text":""},{"location":"patch/playback/#playing-a-patch","title":"Playing a Patch","text":"Once a Patch
has been defined or imported, it can be instantiated in two different ways depending on how it was defined:
- From a Patch subclass
- From a PatchSpec
"},{"location":"patch/playback/#from-a-patch-subclass","title":"From a Patch subclass","text":"The simplest way to instantiate a Patch is by defining it as a Patch subclass, and then instantiating it in the same way as a Node.
class Hat (Patch):\n def __init__(self, duration=0.1):\n super().__init__()\n duration = self.add_input(\"duration\", duration)\n noise = WhiteNoise()\n env = ASREnvelope(0.0001, 0.0, duration, curve=2)\n output = noise * env\n self.set_output(output)\n self.set_auto_free(True)\n\nhat = Hat()\nhat.play()\n
Once a Patch has finished, its state changes to SIGNALFLOW_PATCH_STATE_STOPPED
.
Just as with nodes, it is important to remember that playing a patch means \"connecting it to the graph\". For this reason, it is not possible to play the same patch more than once, as it is already connected to the graph.
To play multiples of a particular Patch
type, simply create and play multiple instances.
"},{"location":"patch/playback/#from-a-patchspec","title":"From a PatchSpec","text":"Once a PatchSpec
has been created or imported, it can be played by instantiating a Patch
with the PatchSpec
as an argument:
patch = Patch(patch_spec)\npatch.play()\n
"},{"location":"patch/playback/#connecting-a-patch-to-another-patchs-input","title":"Connecting a Patch to another Patch's input","text":"A Patch
can be connected to the input of another Patch
(or Node), in exactly the same way described in Connecting a Node to another Node's input.
Once you have got to grips with this paradigm, it becomes simple to build up sophisticated processing graphs by abstracting complex functionality within individual Patch
objects, and connecting them to one another.
"},{"location":"patch/playback/#stopping-a-patch","title":"Stopping a Patch","text":"As in Node playback, stopping a Patch disconnects it from the AudioGraph. Patches with auto-free are automatically stopped when their lifetimes ends. Patches with an unlimited lifespan must be stopped manually, with:
patch.stop()\n
This disconnects the Patch from its output.
\u2192 Next: Patch inputs
"},{"location":"patch/properties/","title":"Patch","text":""},{"location":"patch/properties/#patch-properties","title":"Patch properties","text":"Property Type Description nodes list A list of all of the Node objects that make up this Patch inputs dict A dict of key-value pairs corresponding to all of the (audio rate) inputs within the Patch state int The Patch's current playback state, which can be SIGNALFLOW_PATCH_STATE_ACTIVE
or SIGNALFLOW_PATCH_STATE_STOPPED
. graph AudioGraph A reference to the AudioGraph that the Patch is part of \u2192 Next: Exporting and importing patches
"},{"location":"planning/EXAMPLES/","title":"Examples","text":"[ ] Add signalflow-audio repo
[x] Hello world [x] Granular [ ] Additive synthesis [ ] FM synthesis [ ] Multichannel expansion (supersaw) [ ] Stochastic [ ] Filter [ ] Audio input [ ] Waveshaper / Clip / Fold [ ] Wavetable [x] 2D wavetable [ ] Buffer: Play [ ] Buffer: Record [ ] FFT: Tonality [ ] FFT: Convolution reverb [ ] Patch: Simple
[ ] Control: Mouse control
"},{"location":"planning/NAMING/","title":"NAMING","text":""},{"location":"planning/NAMING/#nodes","title":"NODES","text":"Generators - Oscillators - Wavetable - Waveforms (all wrappers around Wavetable with band-limiting) - SineOscillator - SquareOscillator - TriangleOscillator - SawOscillator - LFO (all wrappers around Wavetable) - SineLFO - SquareLFO - TriangleLFO - SawLFO - Buffer - BufferPlayer - BufferRecorder - Stochastic - Processors - Panners - ChannelMixer - LinearPanner - AzimuthPanner - ObjectPanner - Delay - AllpassDelay - Delay - Effects - EQ - Gate - Resampler - Waveshaper
Stochastic - Random signal generators - WhiteNoise - PinkNoise - BrownNoise - PerlinNoise - Random number generators (with clocked inputs) - RandomUniform - RandomLinear - RandomBrownian - RandomExponentialDist - RandomGaussian - RandomBeta - Random event generators - RandomImpulse
-- PATCHES - Patch - PatchDef
"},{"location":"planning/PLAN/","title":"PLAN","text":"doc writing guide - https://numpy.org/numpy-tutorials/content/tutorial-style-guide.html
- Overview
- Graphs, Nodes, Buffers, Patches
- Getting Started
- Nodes
- Inputs
- Channel upmixing
- Triggers
- Buffers
- Monitoring node status
- Chance and stochastic nodes
- Node class reference
- AudioGraph
- Global configuration
- Graph status
- Recording the audio output
- Buffers
- Why called before? Because can store (e.g.) control data, not just audio
- Buffer types
- Interpolation
- Creating buffers
- From a sound file
- From a sample array
- From a function
- Recording to buffers
- Audio data
- Control data
- Saving buffers
- Reading buffer data
- Patches
- Tutorials
- Topics
- Interactive sound design
- Sequencing and composition
- Live coding
- Controls and GUI
- MIDI control
- Offline processing
- Panning and spatial audio
- Spectral processing with FFT nodes
- Sonification
- Algorithmic composition
- Sequencing (using isobar)
"}]}
\ No newline at end of file
diff --git a/sitemap.xml b/sitemap.xml
index eeeec887..c6a8fa8e 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -2,982 +2,987 @@
https://signalflow.dev/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/examples/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/license/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/buffer/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/buffer/access/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/buffer/creating/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/buffer/exporting/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/buffer/input/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/buffer/operators/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/buffer/properties/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/graph/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/graph/config/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/graph/creating/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/graph/properties/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/graph/recording/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/graph/stopping/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/howto/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/howto/midi/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/howto/plotting/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/command-line-generic/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/next-steps/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/linux/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/linux/buttons/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/linux/command-line/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/macos/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/macos/buttons/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/macos/command-line/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/installation/macos/easy/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/analysis/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/analysis/crosscorrelate/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/analysis/nearestneighbour/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/analysis/onsetdetector/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/analysis/vampanalysis/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/beatcutter/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/bufferlooper/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/bufferplayer/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/bufferrecorder/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/feedbackbufferreader/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/feedbackbufferwriter/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/grainsegments/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/granulation/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/granulation/granulator/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/granulation/segmentedgranulator/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/granulator/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/buffer/segmentplayer/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/control/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/control/mousedown/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/control/mousex/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/control/mousey/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/envelope/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/envelope/adsrenvelope/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/envelope/asrenvelope/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/envelope/detectsilence/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/envelope/envelope/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/envelope/line/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/envelope/rectangularenvelope/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fft/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftcontinuousphasevocoder/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftcontrast/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftconvolve/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftfindpeaks/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftflipspectrum/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftlpf/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftmagnitudephasearray/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftnoisegate/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftphasevocoder/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftrandomphase/
- 2024-02-25
+ 2024-06-20
+ daily
+
+
+ https://signalflow.dev/library/fft/fftscalemagnitudes/
+ 2024-06-20
daily
https://signalflow.dev/library/fft/ffttonality/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/ffttransform/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/fftzerophase/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/fft/ifft/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/abs/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/add/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/amplitudetodecibels/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/channelarray/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/channelcrossfade/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/channelmixer/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/channelselect/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/cos/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/decibelstoamplitude/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/divide/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/equal/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/frequencytomidinote/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/greaterthan/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/greaterthanorequal/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/if/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/lessthan/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/lessthanorequal/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/midinotetofrequency/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/modulo/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/multiply/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/notequal/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/pow/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/round/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/roundtoscale/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/scalelinexp/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/scalelinlin/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/sin/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/subtract/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/sum/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/tan/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/tanh/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/operators/timeshift/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/constant/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/impulse/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/sawlfo/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/sawoscillator/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/sinelfo/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/sineoscillator/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/squarelfo/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/squareoscillator/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/trianglelfo/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/triangleoscillator/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/wavetable/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/oscillators/wavetable2d/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/clip/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/delays/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/delays/allpassdelay/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/delays/combdelay/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/delays/onetapdelay/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/delays/stutter/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/distortion/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/distortion/resample/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/distortion/sampleandhold/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/distortion/squiz/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/distortion/waveshaper/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/dynamics/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/dynamics/compressor/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/dynamics/gate/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/dynamics/maximiser/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/dynamics/rms/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/filters/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/filters/biquadfilter/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/filters/dcfilter/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/filters/eq/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/filters/moogvcf/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/filters/svfilter/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/fold/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/panning/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/panning/azimuthpanner/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/panning/channelpanner/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/panning/spatialpanner/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/panning/stereobalance/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/panning/stereopanner/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/panning/stereowidth/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/smooth/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/wetdry/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/processors/wrap/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/clockdivider/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/counter/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/euclidean/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/flipflop/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/impulsesequence/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/index/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/latch/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/sequencing/sequence/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/logistic/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/pinknoise/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randombrownian/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomchoice/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomcoin/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomexponential/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomexponentialdist/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomgaussian/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomimpulse/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomimpulsesequence/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/randomuniform/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/library/stochastic/whitenoise/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/developing/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/inputs/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/multichannel/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/operators/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/playback/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/properties/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/node/stochastic/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/auto-free/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/defining/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/exporting/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/inputs/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/operators/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/playback/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/patch/properties/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/planning/EXAMPLES/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/planning/NAMING/
- 2024-02-25
+ 2024-06-20
daily
https://signalflow.dev/planning/PLAN/
- 2024-02-25
+ 2024-06-20
daily
\ No newline at end of file
diff --git a/sitemap.xml.gz b/sitemap.xml.gz
index c527ad14..72ce46e8 100644
Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ