diff --git a/howto/plotting/index.html b/howto/plotting/index.html index 3045de9c..fabc51fd 100644 --- a/howto/plotting/index.html +++ b/howto/plotting/index.html @@ -1520,11 +1520,11 @@

Output

Last update: - 2023-12-03 + 2023-12-03
Created: - 2023-12-03 + 2023-12-03
diff --git a/library/oscillators/sinelfo/index.html b/library/oscillators/sinelfo/index.html index 093a15a9..b2f7efa4 100644 --- a/library/oscillators/sinelfo/index.html +++ b/library/oscillators/sinelfo/index.html @@ -1492,14 +1492,10 @@

SineLFO

Produces a sinusoidal LFO at the given frequency and phase offset, with output ranging from min to max.

Examples

-
from signalflow import *
-graph = AudioGraph()
-
-# Siren effect, using a sinewave LFO to modulate a sawtooth's frequency
+
# Siren effect, using a sinewave LFO to modulate a sawtooth's frequency
 lfo = SineLFO(1, 200, 1000)
 saw = SawOscillator(lfo)
 saw.play()
-graph.wait()
 

@@ -1507,7 +1503,7 @@

Examples

Last update: - 2023-12-03 + 2023-12-03
Created: diff --git a/planning/NAMING/index.html b/planning/NAMING/index.html index 4cfa6ca2..da8e9479 100644 --- a/planning/NAMING/index.html +++ b/planning/NAMING/index.html @@ -1544,11 +1544,11 @@

NODES

Last update: - 2023-12-03 + 2023-12-03
Created: - 2023-12-03 + 2023-12-03
diff --git a/search/search_index.json b/search/search_index.json index 0c2afded..6873abb3 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 various code examples using SignalFlow, see examples in GitHub:

https://github.com/ideoforms/signalflow/tree/master/examples

"},{"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":"Buffer","text":"

Warning

This documentation is a work-in-progress and may have sections that are missing or incomplete.

A Buffer is an allocated area of memory that can be used to store 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, or with an empty contents
  • A Buffer can be passed to a Node or Patch as an input
  • A Buffer can be exported to a sound file
  • A Buffer's data can be directly accessed in memory as a numpy array, or by get/set methods
  • The contents of a buffer can be combined with arithmetic operators
  • Properties
  • Buffer interpolation modes
  • 2D buffers
  • Buffer applications: Sample recording and playback, control recording and playback, envelopes, waveshapers
  • The total Buffer memory usage can be queried
"},{"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.
  • 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 receives, rewinds to the start_time.
  • BufferRecorder: Records the input to a buffer. feedback controls overdub.
  • FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
  • FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
  • GrainSegments: GrainSegments
  • 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.
  • SegmentPlayer: Trigger segments of a buffer at the given onset positions.
"},{"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. 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.
  • 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.
  • 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":"
  • Constant: Produces a constant value.
  • 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, 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 pulsewidth of width, ranging from min to max, where width of 0.5 is a square wave.
  • SquareOscillator: Produces a pulse wave with the given frequency and pulse width, where width of 0.5 is a square wave and other width 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 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.
  • 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/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 receives, rewinds to the start_time.
  • BufferRecorder: Records the input to a buffer. feedback controls overdub.
  • FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
  • FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
  • GrainSegments: GrainSegments
  • 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.
  • 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 receives, 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/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={})\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/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/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/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. 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/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. If loop is true, repeats indefinitely. Retriggers on a clock signal.

"},{"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.
  • 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/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/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/fftnoisegate/","title":"FFTNoiseGate node documentation","text":"

Reference library > FFT > FFTNoiseGate

"},{"location":"library/fft/fftnoisegate/#fftnoisegate","title":"FFTNoiseGate","text":"
FFTNoiseGate(input=0, threshold=0.5)\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/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/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.
  • 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/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/oscillators/","title":"Oscillators","text":"

Reference library > Oscillators

"},{"location":"library/oscillators/#oscillators","title":"Oscillators","text":"
  • Constant: Produces a constant value.
  • 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, 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 pulsewidth of width, ranging from min to max, where width of 0.5 is a square wave.
  • SquareOscillator: Produces a pulse wave with the given frequency and pulse width, where width of 0.5 is a square wave and other width 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/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, with output ranging from min to max.

"},{"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=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/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":"
from signalflow import *\ngraph = AudioGraph()\n\n# Siren effect, using a sinewave LFO to modulate a sawtooth's frequency\nlfo = SineLFO(1, 200, 1000)\nsaw = SawOscillator(lfo)\nsaw.play()\ngraph.wait()\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)\n

Produces a sine wave at the given frequency.

"},{"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 pulsewidth of width, ranging from min to max, where width of 0.5 is a square wave.

"},{"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 width values produce a rectangular wave.

"},{"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/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/wavetable/","title":"Wavetable node documentation","text":"

Reference library > Oscillators > Wavetable

"},{"location":"library/oscillators/wavetable/#wavetable","title":"Wavetable","text":"
Wavetable(buffer=None, frequency=440, phase=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=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/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/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/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 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/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 buffer.

"},{"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/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/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/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/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/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/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/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":"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

\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/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

"}]} \ 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 various code examples using SignalFlow, see examples in GitHub:

https://github.com/ideoforms/signalflow/tree/master/examples

"},{"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":"Buffer","text":"

Warning

This documentation is a work-in-progress and may have sections that are missing or incomplete.

A Buffer is an allocated area of memory that can be used to store 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, or with an empty contents
  • A Buffer can be passed to a Node or Patch as an input
  • A Buffer can be exported to a sound file
  • A Buffer's data can be directly accessed in memory as a numpy array, or by get/set methods
  • The contents of a buffer can be combined with arithmetic operators
  • Properties
  • Buffer interpolation modes
  • 2D buffers
  • Buffer applications: Sample recording and playback, control recording and playback, envelopes, waveshapers
  • The total Buffer memory usage can be queried
"},{"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.
  • 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 receives, rewinds to the start_time.
  • BufferRecorder: Records the input to a buffer. feedback controls overdub.
  • FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
  • FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
  • GrainSegments: GrainSegments
  • 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.
  • SegmentPlayer: Trigger segments of a buffer at the given onset positions.
"},{"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. 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.
  • 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.
  • 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":"
  • Constant: Produces a constant value.
  • 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, 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 pulsewidth of width, ranging from min to max, where width of 0.5 is a square wave.
  • SquareOscillator: Produces a pulse wave with the given frequency and pulse width, where width of 0.5 is a square wave and other width 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 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.
  • 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/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 receives, rewinds to the start_time.
  • BufferRecorder: Records the input to a buffer. feedback controls overdub.
  • FeedbackBufferReader: Counterpart to FeedbackBufferWriter.
  • FeedbackBufferWriter: Counterpart to FeedbackBufferReader.
  • GrainSegments: GrainSegments
  • 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.
  • 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 receives, 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/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={})\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/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/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/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. 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/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. If loop is true, repeats indefinitely. Retriggers on a clock signal.

"},{"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.
  • 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/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/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/fftnoisegate/","title":"FFTNoiseGate node documentation","text":"

Reference library > FFT > FFTNoiseGate

"},{"location":"library/fft/fftnoisegate/#fftnoisegate","title":"FFTNoiseGate","text":"
FFTNoiseGate(input=0, threshold=0.5)\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/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/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.
  • 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/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/oscillators/","title":"Oscillators","text":"

Reference library > Oscillators

"},{"location":"library/oscillators/#oscillators","title":"Oscillators","text":"
  • Constant: Produces a constant value.
  • 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, 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 pulsewidth of width, ranging from min to max, where width of 0.5 is a square wave.
  • SquareOscillator: Produces a pulse wave with the given frequency and pulse width, where width of 0.5 is a square wave and other width 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/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, with output ranging from min to max.

"},{"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=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/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":"
# Siren effect, using a sinewave LFO to modulate a sawtooth's frequency\nlfo = SineLFO(1, 200, 1000)\nsaw = SawOscillator(lfo)\nsaw.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)\n

Produces a sine wave at the given frequency.

"},{"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 pulsewidth of width, ranging from min to max, where width of 0.5 is a square wave.

"},{"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 width values produce a rectangular wave.

"},{"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/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/wavetable/","title":"Wavetable node documentation","text":"

Reference library > Oscillators > Wavetable

"},{"location":"library/oscillators/wavetable/#wavetable","title":"Wavetable","text":"
Wavetable(buffer=None, frequency=440, phase=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=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/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/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/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 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/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 buffer.

"},{"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/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/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/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/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/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/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/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":"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

\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/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

"}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index fd9a1c0e..7ba6eebf 100644 Binary files a/sitemap.xml.gz and b/sitemap.xml.gz differ