DSPatch  v.3.00
C++ Cross-Platform, Object-Oriented, Flow-Based Programming Library

** NOTE ** : A graphical tool for creating and routing DSPatch circuits can be found here.


DSPatch, pronounced "dispatch", is a powerful C++ flow-based programming library that allows you to create and route (or "patch") high performance data processing circuits. DSPatch is not limited to any particular type of circuit or signal, its generic object-oriented API allows you to create almost any system imaginable, from simple logic circuits to high performance audio process chains and electronics simulation. DSPatch's simple framework makes development quick and easy, allowing you to hit the ground running on every project.

DSPatch is designed around the concept of a "circuit" containing "components", interconnected via "wires" that transfer "signals" to and from input and output "buses". For more detail on how DSPatch works, check out the DSPatch Design Specification.

The two most important classes to consider are DspComponent and DspCircuit. In order to route data to and from DspComponents they can either be added to an DspCircuit, where they can be wired together (recommended), or they can be wired directly via public DspComponent methods.

The DSPatch engine takes care of data transfer between interconnected components, when data is ready for a component to process, a callback: "Process_()" is executed in that component. For a component to form part of the DSPatch framework, designers simply have to derive their component from the DspComponent base class, configure the component's IO buses, and implement the virtual Process_() callback method.


Getting Started

Step 1: Download DSPatch

The DSPatch library can be downloaded from the SourceForge project page. Download the project archive and extract the contents anywhere you like.

Step 2: Read the Tutorials

The "Tutorials" section below covers 2 vital aspects to developing with DSPatch:

  1. Creating a DspComponent - This tutorial is a start to finish demonstration of how to create a DSPatch component.
  2. Building a DspCircuit - In this tutorial you will learn how to use the DSPatch framework to interconnect and process DspComponent networks using the DspCircuit interface.

Step 3: Check out the example project

In the "example" folder (in the DSPatch root directory) you will find a DSPatch demo project, written to assist developers in understanding the DSPatch API as well as to demonstrate how it could be used to build audio process chains. This project uses the open-source library RtAudio in order to stream sound to your computer's audio device -Linux users will need to install "libasound2-dev" (ALSA) before attempting to build.

Step 4: Make your own DspComponents

A fast way to create your own DspComponent could be to copy an existing component to another destination, rename it, and edit the contents to satisfy your component's required behavior. In the "example" folder (from Step 3) you will find 2 source files: "DspAdder.h" and "DspAdder.cpp". These files make up a very simple DspComponent that receives 2 floating-point buffers into it's 2 inputs, adds each buffer element of the 1st buffer to the corresponding element of the 2nd buffer, then passes the resultant buffer to the output. Alternatively, you could just copy / reference the source code from the "Creating a DspComponent" tutorial (found under the "tutorial" folder in the root directory).

Step 5: Roll your own DSPatch projects

As DSPatch is not reliant on any non-standard 3rd party sources, getting a DSPatch project to compile and run is relatively painless. All you need to do from your project is include "DSPatch.h" from the "include" folder (in the DSPatch root directory), and link to the DSPatch library (either by including all DSPatch source or by linking to a compiled library file). To speed things up you may want to copy, rename, and edit the example project from step 3 to get up and running faster.

Step 6: Refer to the documentation

Between the example project, the DspAdder component template, and the documentation found here, you should have enough resources to get started with DSPatch straight away. If you have any questions or wish to report a bug, feel free to email me at marcu.nosp@m.s@ad.nosp@m.aptau.nosp@m.dio..nosp@m.com.


1. Creating a DspComponent

In order to create a new DspComponent, we must derive our component class from the DspComponent base class, configure component IO, and implement the inherited virtual "Process_()" method.

Lets take a look at how we would go about creating a boolean logic "AND" component. This component will accept 2 boolean input values and output the result of: input 1 && input 2.

We begin by deriving our new "DspAnd" component from DspComponent:

// 1. Derive component class from DspComponent
// ===========================================
class DspAnd : public DspComponent

The next step is to configure our component's input and output buses. This is achieved by calling the base protected methods AddInput_() and AddOutput_() respectively from our component's constructor. Each method must be called once per input / output required. In our component's case, we require 2 inputs and 1 output, therefore our constructor code will look like this:

// 2. Configure component IO buses
// ===============================
// add 2 inputs
// add 1 output

The string values passed into the AddInput_() and AddOutput_() method calls are signal names / IDs. As component IO can be referenced by either string ID or index, IO signal names are optional. If we do not require a signal to have a string ID associated with it, we can simply leave the parenthesis empty.

Lastly, our component must implement the DspComponent virtual Process_() method. This is where our component does it's work. The Process_() method provides us with 2 arguments: the input bus and the output bus. It is our duty as the component designer to pull the inputs we require out of the input bus, process them accordingly, and populate the output bus with the results. Our component's process method will look something like this:

// 3. Implement virtual Process_() method
// ======================================
virtual void Process_(DspSignalBus& inputs, DspSignalBus& outputs)
// create local stack variables to hold input values
bool bool1 = false;
bool bool2 = false;
// get values from inputs bus (GetValue() returns true if successful)
if(inputs.GetValue(0, bool1) && //OR inputs.GetValue("input1", bool1);
inputs.GetValue(1, bool2)) //OR inputs.GetValue("input2", bool2);
// set output as the result of bool1 AND bool2
outputs.SetValue(0, bool1 && bool2); //OR outputs.SetValue("output", bool1 && bool2);

And that's it! Our component is now ready to form part of the DSPatch framework. Next we'll look at how we can add our component to a DspCircuit and route it to and from other DspComponents.

2. Building a DspCircuit

In order for us to get any real use out of our DspComponents, we need them to interact with each other. This is where the DspCircuit class comes in. A DspCircuit is a workspace for adding and routing DspComponents. In this section we will have a look at how to create a simple DSPatch application that generates random boolean pairs, performs a logic AND on each pair, then prints the result to screen.

First we must include the DSPatch header and any other headers that contain DspComponents we wish to use in our application:

#include <DSPatch.h>
#include <components.h>

Next, we must instantiate our DspCircuit object and all DspComponent objects needed for our circuit. Lets say we had 2 other components included with "DspAnd" (from the first tutorial): "DspRandBool" (generates a random boolean value then outputs the result) and "DspPrintBool" (receives a boolean value and outputs it to the console):

void main()
// 1. Create a DspCircuit where we can route our components
// ========================================================
DspCircuit circuit;
// 2. Create instances of the components needed for our circuit
// ============================================================
DspRandBool randBoolGen1;
DspRandBool randBoolGen2;
DspAnd logicAnd;
DspPrintBool boolPrinter;

Now that we have a circuit and some components, lets add all of our components to the circuit:

// 3. Add component instances to circuit
// =====================================
circuit.AddComponent(randBoolGen1, "Bool Generator 1");
circuit.AddComponent(randBoolGen2, "Bool Generator 2");
circuit.AddComponent(logicAnd, "Logic AND");
circuit.AddComponent(boolPrinter, "Bool Printer");

The string values passed into the AddComponent() method calls are component names / IDs. Although we still have the option of referencing a component via it's pointer in a circuit, component string IDs can allow circuit objects to be entirely self-contained. This could give us the ability to pass circuits around by reference, allowing the receiver access to all circuit components via their string IDs, without having to manage both component and circuit references everywhere.

We are now ready to begin wiring the circuit:

// 4. Wire up the components inside the circuit
// ============================================
circuit.ConnectOutToIn(randBoolGen1, 0, logicAnd, 0);
//OR circuit.ConnectOutToIn("Bool Generator 1", 0, "Logic AND", 0);
//OR circuit.ConnectOutToIn("Bool Generator 1", 0, "Logic AND", "input1");
circuit.ConnectOutToIn(randBoolGen2, 0, logicAnd, 1);
//OR circuit.ConnectOutToIn("Bool Generator 2", 0, "Logic AND", 1);
//OR circuit.ConnectOutToIn("Bool Generator 2", 0, "Logic AND", "input2");
circuit.ConnectOutToIn(logicAnd, 0, boolPrinter, 0);
//OR circuit.ConnectOutToIn("Logic AND", 0, "Bool Printer", 0);
//OR circuit.ConnectOutToIn("Logic AND", "output", "Bool Printer", 0);

The code above results in the following wiring configuration:

["Bool Generator 1"] 0 ---> 0 | |
|"Logic AND"| 0 ---> 0 ["Bool Printer"]
["Bool Generator 2"] 0 ---> 1 |___________|

N.B. Each component input can only accept one wire at a time. When another wire is connected to an input that already has a connected wire, that wire is replaced with the new one. One output, on the other hand, can be distributed to multiple inputs.

Lastly, in order for our circuit to do any work it must be ticked over. This is performed by repeatedly calling the circuit's Tick() and Reset() methods. These methods can be called manually in a loop from the main application thread, or alternatively, by calling StartAutoTick(), a seperate thread will spawn, automatically calling Tick() and Reset() continuously. A circuit's thread count can be adjusted at runtime, allowing us to increase / decrease the number of threads use by the circuit as required during execution:

// 5. Tick the circuit
// ===================
// Circuit tick method 1: Manual
for(int i = 0; i < 10; i++)
// Circuit tick method 2: Automatic
std::cout << "Press any key to begin circuit auto-tick.";
// Increase circuit thread count for higher performance
// Press any key to quit

Lastly, the DSPatch::Finalize() method must be called on application exit in order for DSPatch to perform its own internal memory cleanup.

// 6. Clean up
// ===========

(All the source code from these tutorials can be found under the "tutorial" folder in the DSPatch root directory).


v.3.00 (07 April 2015)

v.2.70 (21 December 2014)

v.2.62 (18 August 2014)

v.2.61 (16 June 2014)

v.2.60 (19 January 2014)

v.2.51 (13 September 2013)

v.2.50 (14 July 2013)

v.2.43 (30 June 2013)

v.2.42 (24 June 2013)

v.2.41 (07 February 2013)

v.2.40 (04 February 2013)

v.2.33 (01 February 2013)

v.2.32 (24 January 2013)

v.2.31 (19 December 2012)

v.2.30 (15 December 2012)

v.2.2 (08 December 2012)

v.2.1 (06 November 2012)

v.2.0 (02 November 2012)

v.1.2 (20 October 2012)

v.1.1 (17 October 2012)

v.1.0 (14 October 2012)