changeset 468:85cf9c0da052 prerelease

merge
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 20 Jun 2016 17:08:02 +0100
parents 03a2cd5f151b (current diff) 67c45feec3c3 (diff)
children 898d57ac58a5 5a936f8e9447
files examples/08-PureData/basic_libpd/_main.pd examples/08-PureData/basic_libpd/m_pd.h examples/08-PureData/basic_libpd/main.cpp examples/08-PureData/basic_libpd/render.cpp examples/08-PureData/basic_libpd/s_stuff.h examples/08-PureData/basic_libpd/z_libpd.h examples/7segment/render.cpp examples/airharp/Junction.cpp examples/airharp/Junction.h examples/airharp/MassSpringDamper.cpp examples/airharp/MassSpringDamper.h examples/airharp/Plectrum.cpp examples/airharp/Plectrum.h examples/airharp/String.cpp examples/airharp/String.h examples/airharp/Waveguide.cpp examples/airharp/Waveguide.h examples/airharp/render.cpp examples/analogDigitalDemo/main.cpp examples/analogDigitalDemo/render.cpp examples/audio_in_FFT/main.cpp examples/audio_in_FFT/render.cpp examples/basic/main.cpp examples/basic/render.cpp examples/basic_FFT_phase_vocoder/SampleData.h examples/basic_FFT_phase_vocoder/main.cpp examples/basic_FFT_phase_vocoder/render.cpp examples/basic_FFT_phase_vocoder/sample.wav examples/basic_analog_input/main.cpp examples/basic_analog_input/render.cpp examples/basic_analog_output/main.cpp examples/basic_analog_output/render.cpp examples/basic_blink/render.cpp examples/basic_button/render.cpp examples/basic_midi/render.cpp examples/basic_network/main.cpp examples/basic_passthru/main.cpp examples/basic_passthru/render.cpp examples/basic_pulseIn/render.cpp examples/basic_writeFile/main.cpp examples/basic_writeFile/render.cpp examples/bucket_brigade_chorus/render.cpp examples/cape_test/main.cpp examples/cape_test/render.cpp examples/core/link_core.sh examples/core/render.cpp examples/d-box/ADSR.cpp examples/d-box/ADSR.h examples/d-box/AnalogInput.cpp examples/d-box/AnalogInput.h examples/d-box/Biquad.cpp examples/d-box/Biquad.h examples/d-box/DBoxSynth.h examples/d-box/DboxSensors.cpp examples/d-box/DboxSensors.h examples/d-box/FIRfilter.h examples/d-box/FeedbackOscillator.cpp examples/d-box/FeedbackOscillator.h examples/d-box/OscillatorBank.cpp examples/d-box/OscillatorBank.h examples/d-box/PinkNoise.cpp examples/d-box/PinkNoise.h examples/d-box/StatusLED.cpp examples/d-box/StatusLED.h examples/d-box/audio_routines.S examples/d-box/config.h examples/d-box/how_to_build_dbox.txt examples/d-box/logger.cpp examples/d-box/logger.h examples/d-box/main.cpp examples/d-box/prio.cpp examples/d-box/prio.h examples/d-box/render.cpp examples/d-box/sensors.cpp examples/d-box/sensors.h examples/d-box/spear_parser.cpp examples/d-box/spear_parser.h examples/filter_FIR/FIRfilter.h examples/filter_FIR/SampleData.h examples/filter_FIR/longsample.wav examples/filter_FIR/main.cpp examples/filter_FIR/render.cpp examples/filter_IIR/SampleData.h examples/filter_IIR/longsample.wav examples/filter_IIR/main.cpp examples/filter_IIR/render.cpp examples/gpioAnalogLoopbackTest/render.cpp examples/level_meter/render.cpp examples/loggingSensors/main.cpp examples/loggingSensors/render.cpp examples/measure_noisefloor/main.cpp examples/measure_noisefloor/render.cpp examples/minimal/render.cpp examples/mpr121/I2C_MPR121.cpp examples/mpr121/I2C_MPR121.h examples/mpr121/render.cpp examples/osc/render.cpp examples/oscillator_bank/audio_routines.S examples/oscillator_bank/main.cpp examples/oscillator_bank/render.cpp examples/pd/basicAnalogIn/_main.pd examples/pd/basicAnalogOut/_main.pd examples/pd/circularBuffer/_main.pd examples/pd/digital/bela_digital-help.pd examples/pd/digital/digital_example.pd examples/pd/envelopeTrigger/_main.pd examples/pd/hello-midi/_main.pd examples/pd/hello-midi/countTo.pd examples/pd/hello-midi/maxArray.pd examples/pd/hello-midi/mono.pd examples/pd/hello-world/_main.pd examples/pd/karplusStrong/_main.pd examples/pd/karplusStrong/count.pd examples/pd/rubberDuckie/_main.pd examples/pd/samphold/_main.pd examples/pd/simple-fm/_main.pd examples/pd/tableScrubbing/_main.pd examples/pd/tableScrubbing/rt.wav examples/samples/SampleData.h examples/samples/main.cpp examples/samples/render.cpp examples/samples/sample.wav examples/scope_analogue/render.cpp examples/scope_basic/render.cpp examples/stepper/render.cpp examples/tank_wars/game.cpp examples/tank_wars/game.h examples/tank_wars/main.cpp examples/tank_wars/render.cpp examples/tank_wars/vector_graphics.cpp examples/tank_wars/vector_graphics.h
diffstat 260 files changed, 17468 insertions(+), 15827 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/01-Basics/minimal/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,120 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <Bela.h>
+
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+bool setup(BelaContext *context, void *userData)
+{
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+void render(BelaContext *context, void *userData)
+{
+
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+
+\example 01-minimal
+
+The bare bones
+----------------------
+
+The structure of a render.cpp file
+----------------------------------
+A render.cpp file has three functions: `setup()`, `render()` and `cleanup()`.
+
+`setup()` is an initialisation function which runs before audio rendering begins. 
+It is called once when the project starts. Use it to prepare any memory or 
+resources that will be needed in `render()`.
+
+`render()` is a function that is regularly called, over and over continuously, at 
+the highest priority by the audio engine. It is used to process audio and 
+sensor data. This function is called regularly by the system every time there 
+is a new block of audio and/or sensor data to process.
+
+`cleanup()` is a function that is called when the program stops, to finish up any 
+processes that might still be running.
+
+Here we will briefly explain each function and the structure of the render.cpp 
+
+Before any of the functions
+---------------------------
+At the top of the file, include any libraries you might need.
+
+Additionally, declare any global variables. In these tutorial sketches, all 
+global variables are preceded by a `g` so we always know which variables are 
+global - `gSampleData`, for example. It's not mandatory but is a really good way 
+of keeping track of what's global and what's not.
+
+Sometimes it's necessary to access a variable from another file, such as 
+main.cpp. In this case, precede this variable with the keyword `extern`.
+
+Function arguments
+------------------
+`setup()`, `render()` and `cleanup()` each take the same arguments. These are:
+
+`0ext *context`
+`void *userData`
+
+These arguments are pointers to data structures. The main one that's used is 
+`context`, which is a pointer to a data structure containing lots of information 
+you need.
+
+Take a look at what's in the data structure [here]
+(https://code.soundsoftware.ac.uk/projects/beaglert/embedded/structBeagleRTContext.html).
+
+You can access any of these bits of information about current audio and sensor 
+settings and pointers to data buffers that are contained in the data structure 
+like this: `context->name_of_item`.
+
+For example, `context->audioChannels` returns the number of audio channels. 
+`context->audioSampleRate` returns the audio sample rate. 
+`context->audioIn[n]` would give you the current input sample (assuming that 
+your input is mono - if it's not you will have to account for multiple channels).
+
+Note that `audioIn`, `audioOut`, `analogIn`, `analogOut` are all arrays (buffers).
+
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/01-Basics/passthrough/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,107 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --help [-h]:             Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "h", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/01-Basics/passthrough/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,119 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <Bela.h>
+#include <rtdk.h>
+
+bool setup(BelaContext *context, void *userData)
+{
+	// Nothing to do here...
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	// Simplest possible case: pass inputs through to outputs
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		for(unsigned int ch = 0; ch < context->audioChannels; ch++){
+			// Two equivalent ways to write this code
+
+			// The long way, using the buffers directly:
+			// context->audioOut[n * context->audioChannels + ch] =
+			// 		context->audioIn[n * context->audioChannels + ch];
+
+			// Or using the macros:
+			audioWrite(context, n, ch, audioRead(context, n, ch));
+		}
+	}
+
+	// Same with analog channelss
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
+		for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
+			// Two equivalent ways to write this code
+
+			// The long way, using the buffers directly:
+			// context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch];
+
+			// Or using the macros:
+			analogWrite(context, n, ch, analogRead(context, n, ch));
+		}
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 01-passthrough
+
+Audio and analog passthrough: input to output
+-----------------------------------------
+
+This sketch demonstrates how to read from and write to the audio and analog input and output buffers.
+
+In `render()` you'll see a nested for loop structure. You'll see this in all Bela projects. 
+The first for loop cycles through `audioFrames`, the second through 
+`audioChannels` (in this case left 0 and right 1).
+
+You can access any information about current audio and sensor settings you can do the following: 
+`context->name_of_item`. For example `context->audioChannels` returns current number of channels,
+`context->audioFrames` returns the current number of audio frames, 
+`context->audioSampleRate` returns the audio sample rate.
+
+You can look at all the information you can access in ::BeagleRTContext.
+
+Reading and writing from the audio buffers
+------------------------------------------
+
+The simplest way to read samples from the audio input buffer is with
+`audioRead()` which we pass three arguments: context, current audio 
+frame and current channel. In this example we have 
+`audioRead(context, n, ch)` where both `n` and `ch` are provided by 
+the nested for loop structure.
+
+We can write samples to the audio output buffer in a similar way using 
+`audioWrite()`. This has a fourth argument which is the value of the output.
+For example `audioWrite(context, n, ch, value_to_output)`.
+
+Reading and writing from the analog buffers
+-------------------------------------------
+
+The same is true for `analogRead()` and `analogWrite()`.
+
+Note that for the analog channels we write to and read from the buffers in a separate set 
+of nested for loops. This is because the they are sampled at half audio rate by default. 
+The first of these for loops cycles through `analogFrames`, the second through
+`analogChannels`.
+
+By setting `audioWriteFrame(context, n, ch, audioReadFrame(context, n, ch))` and
+`analogWrite(context, n, ch, analogReadFrame(context, n, ch))` we have a simple 
+passthrough of audio input to output and analog input to output.
+
+
+It is also possible to address the buffers directly, for example: 
+`context->audioOut[n * context->audioChannels + ch]`.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/01-Basics/scope/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,102 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+    Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+    Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <Bela.h>
+#include <Scope.h>
+#include <cmath>
+
+// set the frequency of the oscillators
+float gFrequency = 110.0;
+float gPhase;
+float gInverseSampleRate;
+
+// instantiate the scope
+Scope scope;
+
+bool setup(BelaContext *context, void *userData)
+{
+    // tell the scope how many channels and the sample rate
+    scope.setup(3, context->audioSampleRate);
+
+    gPhase = 0;
+    gInverseSampleRate = 1.0f/context->audioSampleRate;
+    
+	return true;
+}
+
+float lastOut = 0.0;
+float lastOut2 = 0.0;
+void render(BelaContext *context, void *userData)
+{
+    // iterate over the audio frames and create three oscillators, seperated in phase by PI/2
+    for (unsigned int n=0; n<context->audioFrames; n++){
+        float out = 0.8f * sinf(gPhase);
+        float out2 = 0.8f * sinf(gPhase - M_PI/2);
+		float out3 = 0.8f * sinf(gPhase + M_PI/2);
+		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
+		if(gPhase > 2.0 * M_PI)
+			gPhase -= 2.0 * M_PI;
+			
+		// log the three oscillators to the scope
+        scope.log(out, out2, out3);
+        
+        // optional - tell the scope to trigger when oscillator 1 becomes less than oscillator 2
+        // note this has no effect unless trigger mode is set to custom in the scope UI
+        if (lastOut >= lastOut2 && out < out2){
+            scope.trigger();
+        }
+        
+        lastOut = out;
+        lastOut2 = out2;
+    }
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 01-scope
+
+Oscilloscope in-browser
+-----------------------
+
+This example demonstrates the scope feature of the IDE.
+
+The scope is instantiated at the top of the file via `Scope scope;`
+
+In `setup()` we define how many channels the scope should have and the sample 
+rate that it should run at via `scope.setup(3, context->audioSampleRate)`.
+
+In `render()` we choose what the scope log via `scope.log(out, out2, out3)`. 
+In this example the scope is logging three sine waves with different phases. To see
+the output click on the <b>Open Scope</b> button.
+
+An additional option is to set the trigger of the oscilloscope from within `render()`.
+In this example we are triggering the scope when oscillator 1 becomes less than 
+oscillator 2 via `scope.trigger()`. Note that this functionality only takes effect
+when the triggering mode is set to custom in the scope UI.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/01-Basics/sinetone/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,114 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <unistd.h>
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 440.0;	// Frequency of oscillator
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/01-Basics/sinetone/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,86 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <Bela.h>
+#include <cmath>
+
+float gFrequency = 440.0;
+float gPhase;
+float gInverseSampleRate;
+
+bool setup(BelaContext *context, void *userData)
+{
+	// Retrieve a parameter passed in from the initAudio() call
+	if(userData != 0)
+		gFrequency = *(float *)userData;
+
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+	gPhase = 0.0;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		float out = 0.8f * sinf(gPhase);
+		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
+		if(gPhase > 2.0 * M_PI)
+			gPhase -= 2.0 * M_PI;
+
+		for(unsigned int channel = 0; channel < context->audioChannels; channel++) {
+			// Two equivalent ways to write this code
+
+			// The long way, using the buffers directly:
+			// context->audioOut[n * context->audioChannels + channel] = out;
+
+			// Or using the macros:
+			audioWrite(context, n, channel, out);
+		}
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 01-sinetone
+
+Producing your first bleep!
+---------------------------
+
+This sketch is the hello world of embedded interactive audio. Better known as bleep, it 
+produces a sine tone.
+
+The frequency of the sine tone is determined by a global variable, `gFrequency` 
+(line 12). The sine tone is produced by incrementing the phase of a sin function 
+on every audio frame.
+
+In render() you'll see a nested for loop structure. You'll see this in all Bela projects. 
+The first for loop cycles through 'audioFrames', the second through 'audioChannels' (in this case left 0 and right 1). 
+It is good to familiarise yourself with this structure as it's fundamental to producing sound with the system.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/02-Digital/digital-input/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,82 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <cmath>
+#include <rtdk.h>
+#include <stdlib.h>
+
+
+bool setup(BelaContext *context, void *userData)
+{
+	pinMode(context, 0, P8_08, INPUT);
+	pinMode(context, 0, P8_07, OUTPUT);
+	return true;
+}
+
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n=0; n<context->digitalFrames; n++){
+		int status=digitalRead(context, 0, P8_08); //read the value of the button
+		digitalWriteOnce(context, n, P8_07, status); //write the status to the LED
+		float out = 0.1 * status * rand() / (float)RAND_MAX * 2 - 1; //generate some noise, gated by the button
+		for(unsigned int j = 0; j < context->audioChannels; j++){
+			audioWrite(context, n, j, out); //write the audio output
+		}
+	}
+}
+
+
+void cleanup(BelaContext *context, void *userData)
+{
+	// Nothing to do here
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 02-digital-input
+
+Switching an LED on and off
+---------------------------
+
+This example brings together digital input and digital output. The program will read 
+a button and turn the LED on and off according to the state of the button.
+
+- connect an LED in series with a 470ohm resistor between P8_07 and ground.
+- connect a 1k resistor to P9_03 (+3.3V),
+- connect the other end of the resistor to both a button and P8_08
+- connect the other end of the button to ground.
+
+You will notice that the LED will normally stay on and will turn off as long as 
+the button is pressed. This is due to the fact that the LED is set to the same 
+value read at input P8_08. When the button is not pressed, P8_08 is `HIGH` and so 
+P8_07 is set to `HIGH` as well, so that the LED conducts and emits light. When 
+the button is pressed, P8_08 goes `LOW` and P8_07 is set to `LOW`, turning off the LED.
+
+As an exercise try and change the code so that the LED only turns on when 
+the button is pressed.
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/02-Digital/digital-output/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,89 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <cmath>
+#include <rtdk.h>
+
+bool setup(BelaContext *context, void *userData)
+{
+    pinMode(context, 0, P8_07, OUTPUT);
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+  static int count=0; //counts elapsed samples
+  float interval=0.5; //how often to toggle the LED (in seconds)
+  static int status=GPIO_LOW;
+	for(unsigned int n=0; n<context->digitalFrames; n++){
+    if(count==context->digitalSampleRate*interval){ //if enough samples have elapsed
+      count=0; //reset the counter
+    // status=digitalRead(context, 0, P8_07);
+      if(status==GPIO_LOW) { //toggle the status
+          digitalWrite(context, n, P8_07, status); //write the status to the LED
+          status=GPIO_HIGH;
+      }
+      else {
+          digitalWrite(context, n, P8_07, status); //write the status to the LED
+          status=GPIO_LOW;
+      }
+    }
+    count++;
+  }
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+	// Nothing to do here
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 02-digital-output
+
+Blinking an LED
+---------------
+
+This sketch shows the simplest case of digital out. 
+
+- Connect an LED in series with a 470ohm resistor between P8_07 and ground. 
+
+The led is blinked on and off by setting the digital pin `HIGH` and `LOW` every interval seconds which is set in 
+`render()`.
+
+In `setup()` the pin mode must be set to output mode via `pinMode()`. For example: 
+`pinMode(context, 0, P8_07, OUTPUT)`. 
+In `render()` the output of the digital pins is set by `digitalWrite()`. For example: 
+`digitalWrite(context, n, P8_07, status)` where `status` can be equal to 
+either `HIGH` or `LOW`. When set `HIGH` the pin will give 3.3V, when set to 
+`LOW` 0V.
+
+To keep track of elapsed time we have a sample counter count. When the count reaches 
+a certain limit it switches state to either `HIGH` or `LOW` depending on its current 
+value. In this case the limit is `context->digitalSampleRate*interval` which 
+allows us to write the desired interval in seconds, stored in `interval`.
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/02-Digital/level-meter/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,138 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <cmath>
+
+#define NUMBER_OF_SEGMENTS	10
+
+// Two levels of audio: one follows current value, the other holds
+// peaks for longer
+float gAudioLocalLevel = 0, gAudioPeakLevel = 0;
+
+// Decay rates for detecting levels
+float gLocalDecayRate = 0.99, gPeakDecayRate = 0.999;
+
+// Thresholds for LEDs: set in setup()
+float gThresholds[NUMBER_OF_SEGMENTS + 1];
+int gSamplesToLight[NUMBER_OF_SEGMENTS];
+
+// High-pass filter on the input
+float gLastX[2] = {0};
+float gLastY[2] = {0};
+
+// These coefficients make a high-pass filter at 5Hz for 44.1kHz sample rate
+double gB0 = 0.99949640;
+double gB1 = -1.99899280;
+double gB2 = gB0;
+double gA1 = -1.99899254;
+double gA2 = 0.99899305;
+
+bool setup(BelaContext *context, void *userData)
+{	
+	// This project makes the assumption that the audio and digital
+	// sample rates are the same. But check it to be sure!
+	if(context->audioFrames != context->digitalFrames) {
+		rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
+		return false;
+	}
+	
+	// Initialise threshold levels in -3dB steps. One extra for efficiency in render()
+	// Level = 10^(dB/20)
+	for(int i = 0; i < NUMBER_OF_SEGMENTS + 1; i++) {
+		gThresholds[i] = powf(10.0f, (-1.0 * (NUMBER_OF_SEGMENTS - i)) * .05);
+	}
+	
+	for(int i = 0; i < NUMBER_OF_SEGMENTS; i++) {
+		gSamplesToLight[i] = 0;
+		pinMode(context, 0, i, OUTPUT);
+	}
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		// Get average of audio input channels
+		float sample = 0;
+		for(unsigned int ch = 0; ch < context->audioChannels; ch++) {
+			context->audioOut[n * context->audioChannels + ch] = 
+				context->audioIn[n * context->audioChannels + ch];
+			sample += context->audioIn[n * context->audioChannels + ch];
+		}
+		
+		// Do DC-blocking on the sum
+		float out = gB0 * sample + gB1 * gLastX[0] + gB2 * gLastX[1]
+						- gA1 * gLastY[0] - gA2 * gLastY[1];
+
+		gLastX[1] = gLastX[0];
+		gLastX[0] = sample;
+		gLastY[1] = gLastY[0];
+		gLastY[0] = out;
+		
+		out = fabsf(out / (float)context->audioChannels);
+		
+		// Do peak detection: fast-responding local level
+		if(out > gAudioLocalLevel)
+			gAudioLocalLevel = out;
+		else
+			gAudioLocalLevel *= gLocalDecayRate;
+		
+		// Do peak detection: slow-responding peak level
+		if(out > gAudioPeakLevel)
+			gAudioPeakLevel = out;
+		else {
+			// Make peak decay slowly by only multiplying
+			// every few samples
+			if(((context->audioFramesElapsed + n) & 31) == 0)
+				gAudioPeakLevel *= gPeakDecayRate;
+		}	
+		// LED bargraph on digital outputs 0-9
+		for(int led = 0; led < NUMBER_OF_SEGMENTS; led++) {
+			// All LEDs up to the local level light up. The LED
+			// for the peak level also remains lit.
+			int state = LOW;
+				
+			if(gAudioLocalLevel > gThresholds[led]) {
+				state = HIGH;
+				gSamplesToLight[led] = 1000;
+			}
+			/*else if(gAudioPeakLevel > gThresholds[led] && gAudioPeakLevel <= gThresholds[led + 1]) {
+				state = HIGH;
+				gSamplesToLight[led] = 1000;
+			}*/
+			else if(--gSamplesToLight[led] > 0)
+				state = HIGH;
+			
+			// Write LED
+			digitalWriteOnce(context, n, led, state);
+		}
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/03-Analog/analog-input/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,133 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+int gSensorInputFrequency = 0;
+int gSensorInputAmplitude = 1;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] input:  Choose the analog input controlling frequency (0-7; default 0)\n";
+	cerr << "   --amplitude [-a] input:  Choose the analog input controlling amplitude (0-7; default 1)\n";
+	cerr << "   --help [-h]:             Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{"amplitude", 1, NULL, 'a'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:a:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				gSensorInputFrequency = atoi(optarg);
+				if(gSensorInputFrequency < 0 || gSensorInputFrequency > 7) {
+					usage(basename(argv[0]));
+					exit(0);
+				}
+				break;
+		case 'a':
+				gSensorInputAmplitude = atoi(optarg);
+				if(gSensorInputAmplitude < 0 || gSensorInputAmplitude > 7) {
+					usage(basename(argv[0]));
+					exit(0);
+				}
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	if(settings.verbose) {
+		cout << "--> Frequency on input " << gSensorInputFrequency << endl;
+		cout << "--> Amplitude on input " << gSensorInputAmplitude << endl;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/03-Analog/analog-input/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,114 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <rtdk.h>
+#include <cmath>
+
+float gPhase;
+float gInverseSampleRate;
+int gAudioFramesPerAnalogFrame;
+
+// These settings are carried over from main.cpp
+// Setting global variables is an alternative approach
+// to passing a structure to userData in setup()
+
+extern int gSensorInputFrequency;
+extern int gSensorInputAmplitude;
+
+bool setup(BelaContext *context, void *userData)
+{
+	if(context->analogFrames == 0 || context->analogFrames > context->audioFrames) {
+		rt_printf("Error: this example needs analog enabled, with 4 or 8 channels\n");
+		return false;
+	}
+
+	gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+	gPhase = 0.0;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	float frequency = 440.0;
+	float amplitude = 0.8;
+
+	// There are twice as many audio frames as matrix frames since audio sample rate
+	// is twice as high
+
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		if(!(n % gAudioFramesPerAnalogFrame)) {
+			// Even audio samples: update frequency and amplitude from the matrix
+			frequency = map(analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputFrequency), 0, 1, 100, 1000);
+			amplitude = analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputAmplitude);
+		}
+
+		float out = amplitude * sinf(gPhase);
+
+		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
+			context->audioOut[n * context->audioChannels + channel] = out;
+
+		gPhase += 2.0 * M_PI * frequency * gInverseSampleRate;
+		if(gPhase > 2.0 * M_PI)
+			gPhase -= 2.0 * M_PI;
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 03-analog-input
+
+Connecting potentiometers
+-------------------------
+
+This sketch produces a sine tone, the frequency and amplitude of which are 
+affected by data received on the analog pins. Before looping through each audio 
+frame, we declare a value for the frequency and amplitude of our sine tone 
+(line 55); we adjust these values by taking in data from analog sensors 
+(for example potentiometers) with `analogRead()`.
+
+- connect a 10K pot to 3.3V and GND on its 1st and 3rd pins.
+- connect the 2nd middle pin of the pot to analogIn 0.
+- connect another 10K pot in the same way but with the middle pin connected to analogIn 1.
+
+The important thing to notice is that audio is sampled twice as often as analog 
+data. The audio sampling rate is 44.1kHz (44100 frames per second) and the 
+analog sampling rate is 22.05kHz (22050 frames per second). On line 62 you might 
+notice that we are processing the analog data and updating frequency and 
+amplitude only on every second audio sample, since the analog sampling rate is 
+half that of the audio.
+
+Note that the pin numbers are stored in the variables `gAnalogInputFrequency` and 
+`gAnalogInputAmplitude`. These are declared in the main.cpp file; if you look in 
+that file you will see that they have the values of 0 and 1. Bear in mind that 
+these are analog input pins which is a specific header!
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/03-Analog/analog-output/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,121 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the LED fade (default: 1.0)\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 1.0;	// Frequency of LED fades
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// In this example, audio isn't used so might as well leave speaker muted
+	settings.beginMuted = 1;
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				if(frequency < 0)
+					frequency = 0;
+				if(frequency > 11025.0)
+					frequency = 11025.0;
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/03-Analog/analog-output/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,109 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <rtdk.h>
+#include <cmath>
+
+// Set range for analog outputs designed for driving LEDs
+const float kMinimumAmplitude = (1.5 / 5.0);
+const float kAmplitudeRange = 1.0 - kMinimumAmplitude;
+
+float gFrequency;
+float gPhase;
+float gInverseSampleRate;
+
+bool setup(BelaContext *context, void *userData)
+{
+	// Retrieve a parameter passed in from the initAudio() call
+	gFrequency = *(float *)userData;
+
+	if(context->analogFrames == 0) {
+		rt_printf("Error: this example needs the matrix enabled\n");
+		return false;
+	}
+
+	gInverseSampleRate = 1.0 / context->analogSampleRate;
+	gPhase = 0.0;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
+		// Set LED to different phase for each matrix channel
+		float relativePhase = 0.0;
+		for(unsigned int channel = 0; channel < context->analogChannels; channel++) {
+			float out = kMinimumAmplitude + kAmplitudeRange * 0.5f * (1.0f + sinf(gPhase + relativePhase));
+
+			analogWrite(context, n, channel, out);
+
+			// Advance by pi/4 (1/8 of a full rotation) for each channel
+			relativePhase += M_PI * 0.25;
+		}
+
+		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
+		if(gPhase > 2.0 * M_PI)
+			gPhase -= 2.0 * M_PI;
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 03-analog-output
+
+Fading LEDs
+-----------
+
+This sketch uses a sine wave to drive the brightness of a series of LEDs 
+connected to the eight analog out pins. Again you can see the nested `for` loop 
+structure but this time for the analog output channels rather than the audio.
+
+- connect an LED in series with a 470ohm resistor between each of the analogOut pins and ground.
+
+Within the first for loop in render we cycle through each frame in the analog 
+output matrix. At each frame we then cycle through the analog output channels 
+with another for loop and set the output voltage according to the phase of a 
+sine tone that acts as an LFO. The analog output pins can provide a voltage of 
+~4.092V.
+
+The output on each pin is set with `analogWrite()` within the for loop that 
+cycles through the analog output channels. This needs to be provided with 
+arguments as follows `analogWrite(context, n, channel, out)`. Channel is 
+where the you give the address of the analog output pin (in this case we cycle 
+through each pin address in the for loop), out is the variable that holds the 
+desired output (in this case set by the sine wave).
+
+Notice that the phase of the brightness cycle for each led is different. This 
+is achieved by updating a variable that stores a relative phase value. This 
+variable is advanced by pi/4 (1/8 of a full rotation) for each channel giving 
+each of the eight LEDs a different phase.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/03-Analog/scope-analog/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,102 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <cmath>
+#include <Scope.h>
+
+Scope scope;
+
+float gInverseSampleRate;
+float gPhase;
+
+bool setup(BelaContext *context, void *userData)
+{
+
+    // setup the scope with 3 channels at the audio sample rate
+	scope.setup(3, context->audioSampleRate);
+	
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+	gPhase = 0.0;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+	    
+	    // read analogIn channels 0 and 1
+	    float in1 = analogRead(context, n, 0);
+	    float in2 = analogRead(context, n, 1);
+	    
+	    // map in1 to amplitude and in2 to frequency
+	    float amplitude = in1 * 0.8f;
+	    float frequency = map(in2, 0, 1, 100, 1000);
+	    
+	    // generate a sine wave with the amplitude and frequency 
+	    float out = amplitude * sinf(gPhase);
+	    gPhase += 2.0 * M_PI * frequency * gInverseSampleRate;
+		if(gPhase > 2.0 * M_PI)
+			gPhase -= 2.0 * M_PI;
+	    
+	    // log the sine wave and sensor values on the scope
+	    scope.log(out, in1, in2);
+	    
+	    // pass the sine wave to the audio outputs
+	    for(unsigned int channel = 0; channel < context->audioChannels; channel++)
+			context->audioOut[n * context->audioChannels + channel] = out;
+
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 03-scope-analog
+
+Connecting potentiometers
+-------------------------
+
+This example reads from analogue inputs 0 and 1 via `analogReadFrame()` and 
+generates a sine wave with amplitude and frequency determined by their values. 
+It's best to connect a 10K potentiometer to each of these analog inputs. Far 
+left and far right pins of the pot go to 3.3V and GND, the middle should be 
+connected to the analog in pins.
+
+The sine wave is then plotted on the oscilloscope. Click the Open Scope button to 
+view the results. As you turn the potentiometers you will see the amplitude and 
+frequency of the sine wave change.
+
+This project also shows as example of `map()` which allows you to re-scale a number 
+from one range to another. Note that `map()` does not constrain your variable 
+within the upper and lower limits. If you want to do this use the `constrain()`
+function.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/FFT-audio-in/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,116 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --fftsize [-s] size:     Set the fSize of the FFT, in samples\n";
+	cerr << "   --help [-h]:             Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	int fftSize = 64;		    // Size of the FFT, in samples
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"fftsize", 1, NULL, 's'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+//	settings.useAnalog = 0;	// No matrix usage by default
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hs:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 's':
+				fftSize = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &fftSize) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/FFT-audio-in/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,111 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <rtdk.h>
+#include <ne10/NE10.h>					// neon library
+#include <cmath>
+
+int gFFTSize;
+
+int gReadPointer = 0;
+int gWritePointer = 0;
+
+// FFT vars
+static ne10_fft_cpx_float32_t* timeDomainIn;
+static ne10_fft_cpx_float32_t* timeDomainOut;
+static ne10_fft_cpx_float32_t* frequencyDomain;
+static ne10_fft_cfg_float32_t cfg;
+
+bool setup(BelaContext *context, void *userData)
+{
+	// Retrieve a parameter passed in from the initAudio() call
+	gFFTSize = *(int *)userData;
+
+	timeDomainIn = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+	timeDomainOut = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+	frequencyDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+	cfg = ne10_fft_alloc_c2c_float32_neon (gFFTSize);
+
+	memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		timeDomainIn[gReadPointer].r = (ne10_float32_t) ((context->audioIn[n*context->audioChannels] +
+															context->audioIn[n*context->audioChannels+1]) * 0.5);
+		timeDomainIn[gReadPointer].i = 0;
+
+		if(++gReadPointer >= gFFTSize)
+		{
+			//FFT
+			ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg, 0);
+
+			//Do frequency domain stuff
+
+			//IFFT
+			ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg, 1);
+
+			gReadPointer = 0;
+			gWritePointer = 0;
+		}
+
+		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
+			context->audioOut[n * context->audioChannels + channel] = (float) timeDomainOut[gWritePointer].r;
+		gWritePointer++;
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+	NE10_FREE(timeDomainIn);
+	NE10_FREE(timeDomainOut);
+	NE10_FREE(frequencyDomain);
+	NE10_FREE(cfg);
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 04-FFT-audio-in
+
+Fast Fourier Transform
+----------------------
+
+This sketch performs an FFT (Fast Fourier Transform) on incoming audio. It uses 
+the NE10 library, included at the top of the file.
+
+Read the documentation on the NE10 library [here](http://projectne10.github.io/Ne10/doc/annotated.html).
+
+The variables `timeDomainIn`, `timeDomainOut` and `frequencyDomain` are 
+variables of the struct `ne10_fft_cpx_float32_t` [http://projectne10.github.io/Ne10/doc/structne10__fft__cpx__float32__t.html](http://projectne10.github.io/Ne10/doc/structne10__fft__cpx__float32__t.html). 
+These are declared at the top of the file, and memory is allocated 
+for them in `setup()`.
+
+In `render()` a `for` loop performs the FFT which is performed on each sample, 
+and the resulting output is placed on each channel.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/FFT-phase-vocoder/SampleData.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,19 @@
+/*
+ * SampleData.h
+ *
+ *  Created on: Nov 5, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef SAMPLEDATA_H_
+#define SAMPLEDATA_H_
+
+// User defined structure to pass between main and rendere complex data retrieved from file
+struct SampleData {
+	float *samples;	// Samples in file
+	int sampleLen;	// Total nume of samples
+};
+
+
+
+#endif /* SAMPLEDATA_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/FFT-phase-vocoder/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,212 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sndfile.h>				// to load audio files
+#include "SampleData.h"
+#include <Bela.h>
+
+using namespace std;
+
+// Global variables used by getCurrentTime()
+unsigned long long gFirstSeconds, gFirstMicroseconds;
+
+// Load samples from file
+int initFile(string file, SampleData *smp)//float *& smp)
+{
+  	SNDFILE *sndfile ;
+	SF_INFO sfinfo ;
+
+	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
+		cout << "Couldn't open file " << file << endl;
+		return 1;
+	}
+
+	int numChan = sfinfo.channels;
+	if(numChan != 1)
+	{
+		cout << "Error: " << file << " is not a mono file" << endl;
+		return 1;
+	}
+
+	smp->sampleLen = sfinfo.frames * numChan;
+	smp->samples = new float[smp->sampleLen];
+	if(smp == NULL){
+		cout << "Could not allocate buffer" << endl;
+		return 1;
+	}
+
+	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
+	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
+
+	// Pad with zeros in case we couldn't read whole file
+	for(int k = readcount; k <smp->sampleLen; k++)
+		smp->samples[k] = 0;
+
+	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
+		double	scale ;
+		int 	m ;
+
+		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
+		if (scale < 1e-10)
+			scale = 1.0 ;
+		else
+			scale = 32700.0 / scale ;
+		cout << "File samples scale = " << scale << endl;
+
+		for (m = 0; m < smp->sampleLen; m++)
+			smp->samples[m] *= scale;
+	}
+
+	sf_close(sndfile);
+
+	return 0;
+}
+
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+/* Function which returns the time since start of the program
+ * in (fractional) seconds.
+ */
+double getCurrentTime(void) {
+	unsigned long long result;
+	struct timeval tv;
+
+	gettimeofday(&tv, NULL);
+	result = (tv.tv_sec - gFirstSeconds) * 1000000ULL + (tv.tv_usec - gFirstMicroseconds);
+	return (double)result / 1000000.0;
+}
+extern SampleData gSampleData;
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	struct timeval tv;
+	string fileName;			// Name of the sample to load
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"file", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	gSampleData.samples = 0;
+	gSampleData.sampleLen = -1;
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	settings.periodSize = 32; // Larger period size by default, for testing
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				fileName = string((char *)optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	if(fileName.empty()){
+		fileName = "sample.wav";
+	}
+
+
+	// Load file
+	if(initFile(fileName, &gSampleData) != 0)
+	{
+		cout << "Error: unable to load samples " << endl;
+		return -1;
+	}
+
+	if(settings.verbose)
+		cout << "File contains " << gSampleData.sampleLen << " samples" << endl;
+
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &gSampleData) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Initialise time
+	gettimeofday(&tv, NULL);
+	gFirstSeconds = tv.tv_sec;
+	gFirstMicroseconds = tv.tv_usec;
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/FFT-phase-vocoder/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,309 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <rtdk.h>
+#include <ne10/NE10.h>					// NEON FFT library
+#include <cmath>
+#include "SampleData.h"
+#include <Midi.h>
+
+#define BUFFER_SIZE 16384
+
+// TODO: your buffer and counter go here!
+float gInputBuffer[BUFFER_SIZE];
+int gInputBufferPointer = 0;
+float gOutputBuffer[BUFFER_SIZE];
+int gOutputBufferWritePointer = 0;
+int gOutputBufferReadPointer = 0;
+int gSampleCount = 0;
+
+float *gWindowBuffer;
+
+// -----------------------------------------------
+// These variables used internally in the example:
+int gFFTSize = 2048;
+int gHopSize = 512;
+int gPeriod = 512;
+float gFFTScaleFactor = 0;
+
+// FFT vars
+ne10_fft_cpx_float32_t* timeDomainIn;
+ne10_fft_cpx_float32_t* timeDomainOut;
+ne10_fft_cpx_float32_t* frequencyDomain;
+ne10_fft_cfg_float32_t cfg;
+
+// Sample info
+SampleData gSampleData;	// User defined structure to get complex data from main
+int gReadPtr = 0;		// Position of last read sample from file
+
+// Auxiliary task for calculating FFT
+AuxiliaryTask gFFTTask;
+int gFFTInputBufferPointer = 0;
+int gFFTOutputBufferPointer = 0;
+
+void process_fft_background();
+
+
+int gEffect = 0; // change this here or with midi CC
+enum{
+	kBypass,
+	kRobot,
+	kWhisper,
+};
+
+float gDryWet = 1; // mix between the unprocessed and processed sound
+float gPlaybackLive = 0.5f; // mix between the file playback and the live audio input
+float gGain = 1; // overall gain
+float *gInputAudio = NULL;
+Midi midi;
+
+
+void midiCallback(MidiChannelMessage message, void* arg){
+	if(message.getType() == kmmNoteOn){
+		if(message.getDataByte(1) > 0){
+			int note = message.getDataByte(0);
+			float frequency = powf(2, (note-69)/12.f)*440;
+			gPeriod = (int)(44100 / frequency + 0.5);
+			printf("\nnote: %d, frequency: %f, hop: %d\n", note, frequency, gPeriod);
+		}
+	}
+
+	bool shouldPrint = false;
+	if(message.getType() == kmmControlChange){
+		float data = message.getDataByte(1) / 127.0f;
+		switch (message.getDataByte(0)){
+		case 2 :
+			gEffect = (int)(data * 2 + 0.5); // CC2 selects an effect between 0,1,2
+			break;
+		case 3 :
+			gPlaybackLive = data;
+			break;
+		case 4 :
+			gDryWet = data;
+			break;
+		case 5:
+			gGain = data*10;
+			break;
+		default:
+			shouldPrint = true;
+		}
+	}
+	if(shouldPrint){
+		message.prettyPrint();
+	}
+}
+
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+bool setup(BelaContext* context, void* userData)
+{
+	midi.readFrom(0);
+	midi.setParserCallback(midiCallback);
+	// Retrieve a parameter passed in from the initAudio() call
+	gSampleData = *(SampleData *)userData;
+
+	gFFTScaleFactor = 1.0f / (float)gFFTSize;
+	gOutputBufferWritePointer += gHopSize;
+
+	timeDomainIn = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+	timeDomainOut = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+	frequencyDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+	cfg = ne10_fft_alloc_c2c_float32_neon (gFFTSize);
+
+	memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
+	memset(gOutputBuffer, 0, BUFFER_SIZE * sizeof(float));
+
+	// Allocate buffer to mirror and modify the input
+	gInputAudio = (float *)malloc(context->audioFrames * context->audioChannels * sizeof(float));
+	if(gInputAudio == 0)
+		return false;
+
+	// Allocate the window buffer based on the FFT size
+	gWindowBuffer = (float *)malloc(gFFTSize * sizeof(float));
+	if(gWindowBuffer == 0)
+		return false;
+
+	// Calculate a Hann window
+	for(int n = 0; n < gFFTSize; n++) {
+		gWindowBuffer[n] = 0.5f * (1.0f - cosf(2.0 * M_PI * n / (float)(gFFTSize - 1)));
+	}
+
+	// Initialise auxiliary tasks
+	if((gFFTTask = Bela_createAuxiliaryTask(&process_fft_background, 90, "fft-calculation")) == 0)
+		return false;
+	rt_printf("You are listening to an FFT phase-vocoder with overlap-and-add.\n"
+	"Use Midi Control Change to control:\n"
+	"CC 2: effect type (bypass/robotization/whisperization)\n"
+	"CC 3: mix between recorded sample and live audio input\n"
+	"CC 4: mix between the unprocessed and processed sound\n"
+	"CC 5: gain\n"
+	);
+	return true;
+}
+
+// This function handles the FFT processing in this example once the buffer has
+// been assembled.
+void process_fft(float *inBuffer, int inWritePointer, float *outBuffer, int outWritePointer)
+{
+	// Copy buffer into FFT input
+	int pointer = (inWritePointer - gFFTSize + BUFFER_SIZE) % BUFFER_SIZE;
+	for(int n = 0; n < gFFTSize; n++) {
+		timeDomainIn[n].r = (ne10_float32_t) inBuffer[pointer] * gWindowBuffer[n];
+		timeDomainIn[n].i = 0;
+
+		pointer++;
+		if(pointer >= BUFFER_SIZE)
+			pointer = 0;
+	}
+
+	// Run the FFT
+	ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg, 0);
+
+	switch (gEffect){
+	  case kRobot :
+	  // Robotise the output
+	    for(int n = 0; n < gFFTSize; n++) {
+	      float amplitude = sqrtf(frequencyDomain[n].r * frequencyDomain[n].r + frequencyDomain[n].i * frequencyDomain[n].i);
+	      frequencyDomain[n].r = amplitude;
+	      frequencyDomain[n].i = 0;
+	    }
+	    break;
+	  case kWhisper :
+	    for(int n = 0; n < gFFTSize; n++) {
+	      float amplitude = sqrtf(frequencyDomain[n].r * frequencyDomain[n].r + frequencyDomain[n].i * frequencyDomain[n].i);
+	      float phase = rand()/(float)RAND_MAX * 2 * M_PI;
+	      frequencyDomain[n].r = cosf(phase) * amplitude;
+	      frequencyDomain[n].i = sinf(phase) * amplitude;
+	    }
+	    break;
+	  case kBypass:
+	    //bypass
+	    break;
+	  }
+
+	// Run the inverse FFT
+	ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg, 1);
+	// Overlap-and-add timeDomainOut into the output buffer
+	pointer = outWritePointer;
+	for(int n = 0; n < gFFTSize; n++) {
+		outBuffer[pointer] += (timeDomainOut[n].r) * gFFTScaleFactor;
+		if(isnan(outBuffer[pointer]))
+			rt_printf("outBuffer OLA\n");
+		pointer++;
+		if(pointer >= BUFFER_SIZE)
+			pointer = 0;
+	}
+}
+
+// Function to process the FFT in a thread at lower priority
+void process_fft_background() {
+	process_fft(gInputBuffer, gFFTInputBufferPointer, gOutputBuffer, gFFTOutputBufferPointer);
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+void render(BelaContext* context, void* userData)
+{
+	float* audioOut = context->audioOut;
+	int numAudioFrames = context->audioFrames;
+	int numAudioChannels = context->audioChannels;
+	// ------ this code internal to the demo; leave as is ----------------
+
+	// Prep the "input" to be the sound file played in a loop
+	for(int n = 0; n < numAudioFrames; n++) {
+		if(gReadPtr < gSampleData.sampleLen)
+			gInputAudio[2*n] = gInputAudio[2*n+1] = gSampleData.samples[gReadPtr]*(1-gPlaybackLive) +
+			gPlaybackLive*0.5f*(audioRead(context,n,0)+audioRead(context,n,1));
+		else
+			gInputAudio[2*n] = gInputAudio[2*n+1] = 0;
+		if(++gReadPtr >= gSampleData.sampleLen)
+			gReadPtr = 0;
+	}
+	// -------------------------------------------------------------------
+
+	for(int n = 0; n < numAudioFrames; n++) {
+		gInputBuffer[gInputBufferPointer] = ((gInputAudio[n*numAudioChannels] + gInputAudio[n*numAudioChannels+1]) * 0.5);
+
+		// Copy output buffer to output
+		for(int channel = 0; channel < numAudioChannels; channel++){
+			audioOut[n * numAudioChannels + channel] = gOutputBuffer[gOutputBufferReadPointer] * gGain * gDryWet + (1 - gDryWet) * gInputAudio[n * numAudioChannels + channel];
+		}
+
+		// Clear the output sample in the buffer so it is ready for the next overlap-add
+		gOutputBuffer[gOutputBufferReadPointer] = 0;
+		gOutputBufferReadPointer++;
+		if(gOutputBufferReadPointer >= BUFFER_SIZE)
+			gOutputBufferReadPointer = 0;
+		gOutputBufferWritePointer++;
+		if(gOutputBufferWritePointer >= BUFFER_SIZE)
+			gOutputBufferWritePointer = 0;
+
+		gInputBufferPointer++;
+		if(gInputBufferPointer >= BUFFER_SIZE)
+			gInputBufferPointer = 0;
+
+		gSampleCount++;
+		if(gSampleCount >= gHopSize) {
+			//process_fft(gInputBuffer, gInputBufferPointer, gOutputBuffer, gOutputBufferPointer);
+			gFFTInputBufferPointer = gInputBufferPointer;
+			gFFTOutputBufferPointer = gOutputBufferWritePointer;
+			Bela_scheduleAuxiliaryTask(gFFTTask);
+
+			gSampleCount = 0;
+		}
+	}
+	gHopSize = gPeriod;
+}
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BelaContext* context, void* userData)
+{
+	NE10_FREE(timeDomainIn);
+	NE10_FREE(timeDomainOut);
+	NE10_FREE(frequencyDomain);
+	NE10_FREE(cfg);
+	free(gInputAudio);
+	free(gWindowBuffer);
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 04_audio_FFT_phase_vocoder
+
+Phase Vocoder
+----------------------
+
+This sketch shows an implementation of a phase vocoder and builds on the previous FFT example.
+Again it uses the NE10 library, included at the top of the file.
+
+Read the documentation on the NE10 library [here](http://projectne10.github.io/Ne10/doc/annotated.html).
+*/
Binary file examples/04-Audio/FFT-phase-vocoder/sample.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/bucket-brigade-chorus/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,144 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h> 
+#include <Scope.h>
+#include <cmath>
+
+float gPhase1, gPhase2;
+float gFrequency1, gFrequency2;
+float gInverseSampleRate;
+
+// initialise_render() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+#include <I2c_Codec.h>
+#include <PRU.h>
+extern I2c_Codec *gAudioCodec;
+extern PRU *gPRU;
+float D=5264;
+#define delayLength 256
+float delay[delayLength];
+int writePointer=0;
+int readPointer=writePointer+1;
+AuxiliaryTask updatePll;
+
+void updatePllFunction(){
+//	gPRU->setGPIOTestPin();
+	static int count = 0;
+	while(!gShouldStop){
+		gAudioCodec->setPllD(D);
+		count++;
+		if((count&4095)==0)
+			printf("sampling rate: %f\n",gAudioCodec->getAudioSamplingRate());
+		usleep(100);
+	}
+//	gPRU->clearGPIOTestPin();
+}
+
+bool setup(BelaContext *context, void *userData)
+{
+	gInverseSampleRate = 1.0/context->audioSampleRate;
+	
+	gPhase1 = 0.0;
+	gPhase2 = 0.0;
+	
+	gFrequency1 = 200.0;
+	gFrequency2 = 201.0;
+	updatePll=Bela_createAuxiliaryTask(&updatePllFunction, 91, "update PLL");
+	for(int n=0; n<delayLength; n++){
+		delay[n]=0;
+	}
+	return true; 
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+//	printf("here\n");
+	static bool init = false;
+	if(init == false){
+		Bela_scheduleAuxiliaryTask(updatePll);
+//		gAudioCodec->setPllP(2);
+//		gAudioCodec->setPllR();
+//		gAudioCodec->setAudioSamplingRate(43600);
+//		printf("samplingRate: %f, k: %f\n", gAudioCodec->getAudioSamplingRate(), gAudioCodec->getPllK());
+		init = true;
+	}
+	static int count=0;
+	static float lfoPhase=0;
+	static float feedback=0;
+	int updateRate=1;
+	if((count&(updateRate-1))==0){
+		float amplitude = 8000;
+		float rate = 2;
+		lfoPhase+=rate*2*M_PI*updateRate*context->analogFrames/context->audioSampleRate;
+		D=amplitude+amplitude*sinf(lfoPhase);
+		if((count&255)==0){
+//			rt_printf("frequency: %f\n", gAudioCodec->getAudioSamplingRate());
+//			rt_printf("D: %.0f\n", D);
+//			rt_printf("rate: %f\n", rate);
+//			rt_printf("amplitude: %.3f\n", amplitude);
+//			rt_printf("feedback: %.3f\n\n", feedback);
+		}
+	}
+	count++;
+
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		feedback = 0.4;
+		float input = audioRead(context, n, 0) + audioRead(context, n, 1);
+	    delay[writePointer++] = input + delay[readPointer]*feedback;
+	    float output = (input + 0.9*delay[readPointer++] ) * 0.5;
+		audioWrite(context, n, 0, output);
+		audioWrite(context, n, 1, output);
+		if(writePointer>=delayLength)
+			writePointer-=delayLength;
+		if(readPointer>=delayLength)
+			readPointer-=delayLength;
+
+		gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate;
+	    gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
+		if(gPhase1 > 2.0 * M_PI)
+			gPhase1 -= 2.0 * M_PI;
+		if(gPhase2 > 2.0 * M_PI)
+			gPhase2 -= 2.0 * M_PI;
+	}
+}
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BelaContext *context, void *userData)
+{
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/filter-FIR/FIRfilter.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,51 @@
+/*
+ * FIRfilter.h
+ *
+ *  Created on: Aug 5, 2014
+ *      Author: Victor Zappi and Andrew McPherson
+ */
+
+#ifndef FIRFILTER_H_
+#define FIRFILTER_H_
+
+
+#include <ne10/NE10.h>
+
+#define FILTER_TAP_NUM 31
+
+// Coefficients for FIR High Pass Filter at 3 KHz
+ne10_float32_t filterTaps[FILTER_TAP_NUM] = {
+		-0.000055,
+		0.000318,
+		0.001401,
+		0.003333,
+		0.005827,
+		0.007995,
+		0.008335,
+		0.004991,
+		-0.003764,
+		-0.018906,
+		-0.040112,
+		-0.065486,
+		-0.091722,
+		-0.114710,
+		-0.130454,
+		0.863946,
+		-0.130454,
+		-0.114710,
+		-0.091722,
+		-0.065486,
+		-0.040112,
+		-0.018906,
+		-0.003764,
+		0.004991,
+		0.008335,
+		0.007995,
+		0.005827,
+		0.003333,
+		0.001401,
+		0.000318,
+		-0.000055
+};
+
+#endif /* FIRFILTER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/filter-FIR/SampleData.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,19 @@
+/*
+ * SampleData.h
+ *
+ *  Created on: Nov 5, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef SAMPLEDATA_H_
+#define SAMPLEDATA_H_
+
+// User defined structure to pass between main and rendere complex data retrieved from file
+struct SampleData {
+	float *samples;	// Samples in file
+	int sampleLen;	// Total nume of samples
+};
+
+
+
+#endif /* SAMPLEDATA_H_ */
Binary file examples/04-Audio/filter-FIR/longsample.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/filter-FIR/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,196 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <string>
+#include <getopt.h>
+#include <sndfile.h>				// to load audio files
+
+#include <Bela.h>
+#include "SampleData.h"
+
+using namespace std;
+
+// Load samples from file
+int initFile(string file, SampleData *smp)//float *& smp)
+{
+	SNDFILE *sndfile ;
+	SF_INFO sfinfo ;
+
+	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
+		cout << "Couldn't open file " << file << endl;
+		return 1;
+	}
+
+	int numChan = sfinfo.channels;
+	if(numChan != 1)
+	{
+		cout << "Error: " << file << " is not a mono file" << endl;
+		return 1;
+	}
+
+	smp->sampleLen = sfinfo.frames * numChan;
+	smp->samples = new float[smp->sampleLen];
+	if(smp == NULL){
+		cout << "Could not allocate buffer" << endl;
+		return 1;
+	}
+
+	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
+	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
+
+	// Pad with zeros in case we couldn't read whole file
+	for(int k = readcount; k <smp->sampleLen; k++)
+		smp->samples[k] = 0;
+
+	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
+		double	scale ;
+		int 	m ;
+
+		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
+		if (scale < 1e-10)
+			scale = 1.0 ;
+		else
+			scale = 32700.0 / scale ;
+		cout << "File samples scale = " << scale << endl;
+
+		for (m = 0; m < smp->sampleLen; m++)
+			smp->samples[m] *= scale;
+	}
+
+	sf_close(sndfile);
+
+	return 0;
+}
+
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	//rt_task_delete ((RT_TASK *) &gTriggerSamplesTask);
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --file [-f] filename:    Name of the file to load (default is \"longsample.wav\")\n";
+	cerr << "   --help [-h]:             Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	string fileName;			// Name of the sample to load
+
+	SampleData sampleData;		// User define structure to pass data retrieved from file to render function
+	sampleData.samples = 0;
+	sampleData.sampleLen = -1;
+
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"file", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				fileName = string((char *)optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	if(fileName.empty()){
+		fileName = "filter/longsample.wav";
+	}
+
+	if(settings.verbose) {
+		cout << "Loading file " << fileName << endl;
+	}
+
+	// Load file
+	if(initFile(fileName, &sampleData) != 0)
+	{
+		cout << "Error: unable to load samples " << endl;
+		return -1;
+	}
+
+	if(settings.verbose)
+		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
+
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &sampleData) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/filter-FIR/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,172 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#define ENABLE_NE10_FIR_FLOAT_NEON	// Define needed for Ne10 library
+
+#include <Bela.h>
+#include <cmath>
+#include <ne10/NE10.h>					// neon library
+#include "SampleData.h"
+#include "FIRfilter.h"
+
+SampleData gSampleData;	// User defined structure to get complex data from main
+int gReadPtr;			// Position of last read sample from file
+
+// filter vars
+ne10_fir_instance_f32_t gFIRfilter;
+ne10_float32_t *gFIRfilterIn;
+ne10_float32_t *gFIRfilterOut;
+ne10_uint32_t blockSize;
+ne10_float32_t *gFIRfilterState;
+
+void initialise_filter(BelaContext *context);
+
+// Task for handling the update of the frequencies using the matrix
+AuxiliaryTask gTriggerSamplesTask;
+
+bool initialise_trigger();
+void trigger_samples();
+
+bool setup(BelaContext *context, void *userData)
+{
+
+	// Retrieve a parameter passed in from the initAudio() call
+	gSampleData = *(SampleData *)userData;
+
+	gReadPtr = -1;
+
+	initialise_filter(context);
+
+	// Initialise auxiliary tasks
+	if(!initialise_trigger())
+		return false;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		float in = 0;
+
+		// If triggered...
+		if(gReadPtr != -1)
+			in += gSampleData.samples[gReadPtr++];	// ...read each sample...
+
+		if(gReadPtr >= gSampleData.sampleLen)
+			gReadPtr = -1;
+
+		gFIRfilterIn[n] = in;
+	}
+
+	ne10_fir_float_neon(&gFIRfilter, gFIRfilterIn, gFIRfilterOut, blockSize);
+
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
+				context->audioOut[n * context->audioChannels + channel] = gFIRfilterOut[n];	// ...and put it in both left and right channel
+	}
+
+
+	// Request that the lower-priority task run at next opportunity
+	Bela_scheduleAuxiliaryTask(gTriggerSamplesTask);
+}
+
+// Initialise NE10 data structures to define FIR filter
+
+void initialise_filter(BelaContext *context)
+{
+	blockSize = context->audioFrames;
+	gFIRfilterState	= (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
+	gFIRfilterIn = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
+	gFIRfilterOut = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
+	ne10_fir_init_float(&gFIRfilter, FILTER_TAP_NUM, filterTaps, gFIRfilterState, blockSize);
+}
+
+
+// Initialise the auxiliary task
+// and print info
+
+bool initialise_trigger()
+{
+	if((gTriggerSamplesTask = Bela_createAuxiliaryTask(&trigger_samples, 50, "bela-trigger-samples")) == 0)
+		return false;
+
+	rt_printf("Press 'a' to trigger sample, 's' to stop\n");
+	rt_printf("Press 'q' to quit\n");
+
+	return true;
+}
+
+// This is a lower-priority call to periodically read keyboard input
+// and trigger samples. By placing it at a lower priority,
+// it has minimal effect on the audio performance but it will take longer to
+// complete if the system is under heavy audio load.
+
+void trigger_samples()
+{
+	// This is not a real-time task!
+	// Cos getchar is a system call, not handled by Xenomai.
+	// This task will be automatically down graded.
+
+	char keyStroke = '.';
+
+	keyStroke =	getchar();
+	while(getchar()!='\n'); // to read the first stroke
+
+	switch (keyStroke)
+	{
+		case 'a':
+			gReadPtr = 0;
+			break;
+		case 's':
+			gReadPtr = -1;
+			break;
+		case 'q':
+			gShouldStop = true;
+			break;
+		default:
+			break;
+	}
+}
+
+
+void cleanup(BelaContext *context, void *userData)
+{
+	delete[] gSampleData.samples;
+
+	NE10_FREE(gFIRfilterState);
+	NE10_FREE(gFIRfilterIn);
+	NE10_FREE(gFIRfilterOut);
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 04-filter-FIR
+
+Finite Impulse Response Filter
+------------------------------
+
+This is an example of a finite impulse response filter implementation.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/filter-IIR/SampleData.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,19 @@
+/*
+ * SampleData.h
+ *
+ *  Created on: Nov 5, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef SAMPLEDATA_H_
+#define SAMPLEDATA_H_
+
+// User defined structure to pass between main and rendere complex data retrieved from file
+struct SampleData {
+	float *samples;	// Samples in file
+	int sampleLen;	// Total nume of samples
+};
+
+
+
+#endif /* SAMPLEDATA_H_ */
Binary file examples/04-Audio/filter-IIR/longsample.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/filter-IIR/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,202 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <string>
+#include <getopt.h>
+#include <sndfile.h>				// to load audio files
+
+#include <Bela.h>
+#include "SampleData.h"
+
+using namespace std;
+
+float gCutFreq = 100;
+
+// Load samples from file
+int initFile(string file, SampleData *smp)//float *& smp)
+{
+	SNDFILE *sndfile ;
+	SF_INFO sfinfo ;
+
+	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
+		cout << "Couldn't open file " << file << endl;
+		return 1;
+	}
+
+	int numChan = sfinfo.channels;
+	if(numChan != 1)
+	{
+		cout << "Error: " << file << " is not a mono file" << endl;
+		return 1;
+	}
+
+	smp->sampleLen = sfinfo.frames * numChan;
+	smp->samples = new float[smp->sampleLen];
+	if(smp == NULL){
+		cout << "Could not allocate buffer" << endl;
+		return 1;
+	}
+
+	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
+	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
+
+	// Pad with zeros in case we couldn't read whole file
+	for(int k = readcount; k <smp->sampleLen; k++)
+		smp->samples[k] = 0;
+
+	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
+		double	scale ;
+		int 	m ;
+
+		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
+		if (scale < 1e-10)
+			scale = 1.0 ;
+		else
+			scale = 32700.0 / scale ;
+		cout << "File samples scale = " << scale << endl;
+
+		for (m = 0; m < smp->sampleLen; m++)
+			smp->samples[m] *= scale;
+	}
+
+	sf_close(sndfile);
+
+	return 0;
+}
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	//rt_task_delete ((RT_TASK *) &gTriggerSamplesTask);
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --file [-f] filename:    Name of the file to load (default is \"longsample.wav\")\n";
+	cerr << "   --cutfreq [-c] freq:     Set the cut off frequency of the filter in Hz\n";
+	cerr << "   --help [-h]:             Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	string fileName;			// Name of the sample to load
+
+	SampleData sampleData;		// User define structure to pass data retrieved from file to render function
+	sampleData.samples = 0;
+	sampleData.sampleLen = -1;
+
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"cutfreq", 1, NULL, 'c'},
+		{"file", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:c:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				fileName = string((char *)optarg);
+				break;
+		case 'c':
+				gCutFreq = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	if(fileName.empty()){
+		fileName = "filter/longsample.wav";
+	}
+
+	if(settings.verbose) {
+		cout << "Loading file " << fileName << endl;
+	}
+
+	// Load file
+	if(initFile(fileName, &sampleData) != 0)
+	{
+		cout << "Error: unable to load samples " << endl;
+		return -1;
+	}
+
+	if(settings.verbose)
+		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
+
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &sampleData) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/filter-IIR/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,230 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>	// to schedule lower prio parallel process
+#include <rtdk.h>
+#include <cmath>
+#include <stdio.h>
+#include "SampleData.h"
+
+SampleData gSampleData;	// User defined structure to get complex data from main
+int gReadPtr;			// Position of last read sample from file
+
+// filter vars
+float gLastX[2];
+float gLastY[2];
+double lb0, lb1, lb2, la1, la2 = 0.0;
+
+// communication vars between the 2 auxiliary tasks
+int gChangeCoeff = 0;
+int gFreqDelta = 0;
+
+void initialise_filter(float freq);
+
+void calculate_coeff(float cutFreq);
+
+bool initialise_aux_tasks();
+
+// Task for handling the update of the frequencies using the matrix
+AuxiliaryTask gChangeCoeffTask;
+
+void check_coeff();
+
+// Task for handling the update of the frequencies using the matrix
+AuxiliaryTask gInputTask;
+
+void read_input();
+
+
+extern float gCutFreq;
+
+
+bool setup(BelaContext *context, void *userData)
+{
+
+	// Retrieve a parameter passed in from the initAudio() call
+	gSampleData = *(SampleData *)userData;
+
+	gReadPtr = -1;
+
+	initialise_filter(200);
+
+	// Initialise auxiliary tasks
+	if(!initialise_aux_tasks())
+		return false;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		float sample = 0;
+		float out = 0;
+
+		// If triggered...
+		if(gReadPtr != -1)
+			sample += gSampleData.samples[gReadPtr++];	// ...read each sample...
+
+		if(gReadPtr >= gSampleData.sampleLen)
+			gReadPtr = -1;
+
+		out = lb0*sample+lb1*gLastX[0]+lb2*gLastX[1]-la1*gLastY[0]-la2*gLastY[1];
+
+		gLastX[1] = gLastX[0];
+		gLastX[0] = out;
+		gLastY[1] = gLastY[0];
+		gLastY[0] = out;
+
+		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
+			context->audioOut[n * context->audioChannels + channel] = out;	// ...and put it in both left and right channel
+
+	}
+
+	// Request that the lower-priority tasks run at next opportunity
+	Bela_scheduleAuxiliaryTask(gChangeCoeffTask);
+	Bela_scheduleAuxiliaryTask(gInputTask);
+}
+
+// First calculation of coefficients
+
+void initialise_filter(float freq)
+{
+	calculate_coeff(freq);
+}
+
+
+// Calculate the filter coefficients
+// second order low pass butterworth filter
+
+void calculate_coeff(float cutFreq)
+{
+	// Initialise any previous state (clearing buffers etc.)
+	// to prepare for calls to render()
+	float sampleRate = 44100;
+	double f = 2*M_PI*cutFreq/sampleRate;
+	double denom = 4+2*sqrt(2)*f+f*f;
+	lb0 = f*f/denom;
+	lb1 = 2*lb0;
+	lb2 = lb0;
+	la1 = (2*f*f-8)/denom;
+	la2 = (f*f+4-2*sqrt(2)*f)/denom;
+	gLastX[0] = gLastX [1] = 0;
+	gLastY[0] = gLastY[1] = 0;
+
+}
+
+
+// Initialise the auxiliary tasks
+// and print info
+
+bool initialise_aux_tasks()
+{
+	if((gChangeCoeffTask = Bela_createAuxiliaryTask(&check_coeff, 90, "bela-check-coeff")) == 0)
+		return false;
+
+	if((gInputTask = Bela_createAuxiliaryTask(&read_input, 50, "bela-read-input")) == 0)
+		return false;
+
+	rt_printf("Press 'a' to trigger sample, 's' to stop\n");
+	rt_printf("Press 'z' to low down cut-off freq of 100 Hz, 'x' to raise it up\n");
+	rt_printf("Press 'q' to quit\n");
+
+	return true;
+}
+
+// Check if cut-off freq has been changed
+// and new coefficients are needed
+
+void check_coeff()
+{
+	if(gChangeCoeff == 1)
+	{
+		gCutFreq += gFreqDelta;
+		gCutFreq = gCutFreq < 0 ? 0 : gCutFreq;
+		gCutFreq = gCutFreq > 22050 ? 22050 : gCutFreq;
+
+		rt_printf("Cut-off frequency: %f\n", gCutFreq);
+
+		calculate_coeff(gCutFreq);
+		gChangeCoeff = 0;
+	}
+}
+
+// This is a lower-priority call to periodically read keyboard input
+// and trigger samples. By placing it at a lower priority,
+// it has minimal effect on the audio performance but it will take longer to
+// complete if the system is under heavy audio load.
+
+void read_input()
+{
+	// This is not a real-time task!
+	// Cos getchar is a system call, not handled by Xenomai.
+	// This task will be automatically down graded.
+
+	char keyStroke = '.';
+
+	keyStroke =	getchar();
+	while(getchar()!='\n'); // to read the first stroke
+
+	switch (keyStroke)
+	{
+		case 'a':
+			gReadPtr = 0;
+			break;
+		case 's':
+			gReadPtr = -1;
+			break;
+		case 'z':
+			gChangeCoeff = 1;
+			gFreqDelta = -100;
+			break;
+		case 'x':
+			gChangeCoeff = 1;
+			gFreqDelta = 100;
+			break;
+		case 'q':
+			gShouldStop = true;
+			break;
+		default:
+			break;
+	}
+}
+
+
+void cleanup(BelaContext *context, void *userData)
+{
+	delete[] gSampleData.samples;
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 04-filter-IIR
+
+Infinite Impulse Response Filter
+------------------------------
+
+This is an example of a infinite impulse response filter implementation.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/measure-noisefloor/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,120 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+extern int gBufferSize;
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --buffer-size [-b] size  Set the analysis buffer size\n";
+	cerr << "   --help [-h]:             Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"buffer-size", 1, NULL, 'b'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// By default use a longer period size because latency is not an issue
+	settings.periodSize = 32;
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hb:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'b':
+				gBufferSize = atoi(optarg);
+				break;
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+	
+	if(gBufferSize < settings.periodSize)
+		gBufferSize = settings.periodSize;
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/measure-noisefloor/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,178 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <cmath>
+
+int gBufferSize = 8192;
+
+// Double buffers to hold samples for noise analysis
+float *gReadBuffers[10], *gWriteBuffers[10];
+float *gBuffers0[10], *gBuffers1[10];
+
+int gWriteBufferPointers[10], gReadBufferPointers[10];
+
+// Task to analyse and print results which would otherwise be too slow for render()
+AuxiliaryTask gAnalysisTask;
+
+void analyseResults();
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+bool setup(BelaContext *context, void *userData)
+{	
+	// Clear the filter data structures
+	for(int i = 0; i < 10; i++) {
+		gReadBufferPointers[i] = gWriteBufferPointers[i] = 0;
+		gBuffers0[i] = new float[gBufferSize];
+		gBuffers1[i] = new float[gBufferSize];		
+		gWriteBuffers[i] = gBuffers0[i];
+		gReadBuffers[i] = gBuffers1[i];
+		if(gBuffers0[i] == 0 || gBuffers1[i] == 0) {
+			rt_printf("Error allocating buffer %d\n", i);
+			return false;
+		}
+	}
+	
+	gAnalysisTask = Bela_createAuxiliaryTask(analyseResults, 50, "bela-analyse-results");
+
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	bool bufferIsFull = false;	// Whether at least one buffer has filled
+	
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		// Store audio inputs in buffer
+		for(unsigned int ch = 0; ch < context->audioChannels; ch++) {
+			if(gWriteBufferPointers[ch] < gBufferSize) {
+				gWriteBuffers[ch][gWriteBufferPointers[ch]] = 
+					context->audioIn[n * context->audioChannels + ch];
+				gWriteBufferPointers[ch]++;
+				if(gWriteBufferPointers[ch] >= gBufferSize)
+					bufferIsFull = true;
+			}
+		}
+	}
+	
+	if(context->analogChannels != 0) {
+		for(unsigned int n = 0; n < context->analogFrames; n++) {
+			// Store analog inputs in buffer, starting at channel 2
+			for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
+				if(gWriteBufferPointers[ch + 2] < gBufferSize) {
+					gWriteBuffers[ch + 2][gWriteBufferPointers[ch + 2]] = 
+						context->analogIn[n * context->analogChannels + ch];
+					gWriteBufferPointers[ch + 2]++;
+					if(gWriteBufferPointers[ch + 2] >= gBufferSize)
+						bufferIsFull = true;
+				}
+				
+				// Set all analog outputs to halfway point so they can be more
+				// easily measured for noise
+				context->analogOut[n * context->analogChannels + ch] = 0.5;
+			}
+		}	
+	}
+	
+
+	if(bufferIsFull) {
+		// Swap buffers and reset write pointers
+		for(int ch = 0; ch < 10; ch++) {
+			gReadBufferPointers[ch] = gWriteBufferPointers[ch];
+			gWriteBufferPointers[ch] = 0;
+			
+			if(gReadBuffers[ch] == gBuffers0[ch]) {
+				gReadBuffers[ch] = gBuffers1[ch];
+				gWriteBuffers[ch] = gBuffers0[ch];
+			}
+			else {
+				gReadBuffers[ch] = gBuffers0[ch];
+				gWriteBuffers[ch] = gBuffers1[ch];				
+			}
+		}
+		
+		Bela_scheduleAuxiliaryTask(gAnalysisTask);
+	}
+}
+
+void analyseResults()
+{
+	rt_printf("\e[1;1H\e[2J");	// Command to clear the screen
+
+	// Print the analysis results. channels 0-1 are audio, channels 2-9 are analog
+	for(int ch = 0; ch < 10; ch++) {
+		// Skip unused channels
+		if(gReadBufferPointers[ch] == 0)
+			continue;
+		
+		float mean = 0;
+		for(int n = 0; n < gReadBufferPointers[ch]; n++) {
+			mean += gReadBuffers[ch][n];
+		}
+		mean /= (float)gReadBufferPointers[ch];
+		
+		float rms = 0;
+		for(int n = 0; n < gReadBufferPointers[ch]; n++) {
+			rms += (gReadBuffers[ch][n] - mean) * (gReadBuffers[ch][n] - mean);
+		}				
+		rms = sqrtf(rms / (float)gReadBufferPointers[ch]);
+		
+		if(ch == 0)
+			rt_printf("Audio In L:  ");
+		else if(ch == 1)
+			rt_printf("Audio In R:  ");
+		else
+			rt_printf("Analog In %d: ", ch - 2);
+		
+		rt_printf("Noise %6.1fdB    DC offset %6.4f (%6.1fdB)    window size: %d\n", 
+					20.0f * log10f(rms),
+					mean, 
+					20.0f * log10f(fabsf(mean)),
+					gReadBufferPointers[ch]);
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	for(int i = 0; i < 10; i++) {
+		delete gBuffers0[i];
+		delete gBuffers1[i];
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/oscillator-bank/audio_routines.S	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,161 @@
+@
+@ audio_routines.S
+@
+@ NEON-based functions for time-critical audio processing
+@
+@ Andrew McPherson 2014
+@ Queen Mary University of London
+@
+
+	.syntax unified
+	.arch armv7-a
+	.fpu neon
+
+@ 	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
+@							  int activePartialNum, int lookupTableSize,
+@							  float *phases, float *frequencies, float *amplitudes,
+@							  float *freqDerivatives, float *ampDerivatives,
+@							  float *lookupTable);
+
+@ Registers:
+@    r0: numAudioFrames        How many frames to render
+@    r1: audioOut              Buffer for audio output samples [stereo]
+@    r2: activePartialNum      How many active partials to render
+@    r3: lookupTableSize       Size of lookup table
+@    ---- other arguments start on the stack and are moved: -----
+@    r4: phases                Phase of each oscillator (pointer)
+@    r5: frequencies           Normalised frequency of each oscillator (pointer)
+@    r6: amplitudes            Normalised amplitude of each oscillator (pointer)
+@    r7: freqDerivatives       Derivative of frequency for each oscillator (pointer)
+@    r8: ampDerivatives        Derivative of amplitude for each oscillator (pointer)
+@    r9: lookupTable           Lookup table containing one oscillation
+@
+@ Alignment requirements:
+@    audioOut: 8-byte boundary
+@    phases: 16-byte boundary
+@    frequencies: 16-byte boundary
+@    amplitudes: 16-byte boundary
+@    freqDerivatives: 16-byte bounary
+@    ampDerivatives: 16-byte boundary
+@    lookupTable: 4-byte boundary (TODO: check this)
+
+	.align	2
+	.global	oscillator_bank_neon
+	.thumb
+	.thumb_func
+	.type	oscillator_bank_neon, %function
+oscillator_bank_neon:
+
+
+dSample		.dn		D6.F32
+qPhases		.qn		Q8.F32
+dPhases_0	.dn		D16.F32
+dPhases_1	.dn		D17.F32
+qFreqs		.qn		Q9.F32
+dFreqs_0	.dn		D18.F32
+dFreqs_1	.dn		D19.F32
+qAmps		.qn		Q10.F32
+dAmps_0		.dn		D20.F32
+dAmps_1		.dn		D21.F32
+qFreqDs		.qn		Q11.F32
+dFreqDs_0	.dn		D22.F32
+dFreqDs_1	.dn		D23.F32
+qAmpDs		.qn		Q12.F32
+dAmpDs_0	.dn		D24.F32
+dAmpDs_1	.dn		D25.F32
+
+qBaseInts	.qn		Q13.U32		@ Base indexes: unsigned ints x4
+dBaseInts_0	.dn		D26.U32
+dBaseInts_1	.dn		D27.U32
+qFractions  .qn     Q14.F32		@ Fraction indexes: floats x4
+qTableBase	.qn		Q15.U32		@ Base of lookup table
+
+	cmp r0, #0					@ Check for trivial case 1: zero frames
+	it eq
+	bxeq lr						@ Return if that's the case (otherwise might have odd behaviour)
+	cmp r2, #4					@ Check for trivial case 2: zero oscillators
+	it lt
+	bxlt lr						@ Return if that's the case
+
+	push {r4-r11}				@ Now arguments start 32 bytes above SP
+    add r11, sp, #32			@ Pointer to 32 bytes into the stack
+    ldm r11, {r4-r9}			@ Load 6 arguments into registers
+
+	vdup qTableBase, r9			@ Move lookup table base index into 4 ints
+
+	@ Outer loop: iterate over the number of oscillators, choosing 4 at a
+	@ time to work with.
+oscbank_oscillator_loop:
+	vld1 {dPhases_0, dPhases_1}, [r4]		@ no increment; will store at end of sample loop
+	vld1 {dFreqs_0, dFreqs_1}, [r5]
+	vld1 {dAmps_0, dAmps_1}, [r6]
+	vld1 {dFreqDs_0, dFreqDs_1}, [r7]!		@ increment; won't update at end of sample loop
+	vld1 {dAmpDs_0, dAmpDs_1}, [r8]!
+
+	push {r0-r1,r4-r8}
+	@ --- inner loop: iterate over the number of samples ---
+oscbank_sample_loop:
+	vcvt qBaseInts, qPhases		     		@ Take floor(phases)
+	vmov q2.f32, #1.0						@ Load 1.0 into every slot of q2
+	vshl q0.U32, qBaseInts, #2				@ Shift the indexes left 2 (*4 for float addressing)
+	vcvt qFractions, qBaseInts				@ int back to float
+	vadd q0.U32, q0.U32, qTableBase			@ Find memory addresses
+
+	vmov r4, r5, d0							@ Move two indexes to ARM registers
+	vmov r6, r7, d1							@ Move two more indexes to ARM registers
+	vsub qFractions, qPhases, qFractions	@ fraction = phase - floor(phase)
+
+	vldr.64	d0, [r4]						@ Load two consecutive floats at each location
+	vldr.64 d1, [r5]						@ These hold the previous and following samples in the table
+	vldr.64	d2, [r6]						@ TODO: check whether these work at 4-byte alignment
+	vldr.64 d3, [r7]
+
+	@ Format at this point:
+	@ Osc0(before) Osc0(after) Osc1(before) Osc1(after) Osc2(before) Osc2(after) Osc3(before) Osc3(after)
+	@ We want:
+	@ Osc0(before) Osc1(before) Osc2(before) Osc3(before) Osc0(after) Osc1(after) Osc2(after) Osc3(after)
+
+	vuzp.32 q0, q1							@ Now q0 contains before, q1 contains after
+	vsub q2.f32, q2.f32, qFractions			@ q2 = 1.0 - fraction
+	vmul q1.f32, q1.f32, qFractions			@ q1 = fraction * after
+	vmul q0.f32, q0.f32, q2.f32				@ q0 = (1.0 - fraction) * before
+
+	vadd qPhases, qPhases, qFreqs			@ Update phases
+	vadd qFreqs, qFreqs, qFreqDs			@ Update frequencies
+
+	vadd q0.f32, q0.f32, q1.f32				@ Add two interpolated components to get the final sample
+	vdup q2.u32, r3							@ Put lookup table size into each element of q2
+	vcvt qBaseInts, qPhases					@ Take floor of new phases
+	vmul q0.f32, q0.f32, qAmps				@ Multiply samples by current amplitude
+
+	vld1 dSample, [r1]						@ Load the current stereo samples
+	vpadd d2.f32, d0.f32, d1.f32			@ Pairwise accumulate q0 (output sample) into d2
+
+	vand q2, q2, qBaseInts					@ Logical AND of new phase int leaves 1 bit set only if phase >= table size
+	vpadd d3.f32, d2.f32, d2.f32			@ Pairwise accumulate d2 into d0 --> d0[0] and d0[1] both hold total of 4 oscillators
+	vadd qAmps, qAmps, qAmpDs				@ Update amplitudes
+	vcvt q0.f32, q2.u32						@ Convert int back to float after AND operation
+
+	vadd  dSample, dSample, d3.f32			@ Add oscillator outputs to each channel
+
+	subs r0, r0, #1							@ numFrames--
+	vsub qPhases, qPhases, q0.f32			@ Keep phases in table range
+	vst1 dSample, [r1]!						@ Store back in buffer and increment by 8
+
+	it gt
+	bgt oscbank_sample_loop					@ Loop if numFrames > 0
+
+	@ --- end inner loop ---
+	pop {r0-r1,r4-r8}						@ Restore registers: restores audioOut and numFrames, among others
+
+	vst1 {dPhases_0, dPhases_1}, [r4]!		@ Store phases back to array
+	vst1 {dFreqs_0, dFreqs_1}, [r5]!		@ Store frequencies back to array
+	vst1 {dAmps_0, dAmps_1}, [r6]!			@ Store amplitudes back to array
+											@ No need to update r7, r8
+
+	subs r2, r2, #4							@ numPartials -= 4
+	it  gt
+	bgt oscbank_oscillator_loop	@ Loop if numPartials > 0
+
+    pop {r4-r11}
+	bx lr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/oscillator-bank/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,132 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+int gNumOscillators = 32;
+int gWavetableLength = 1024;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --num-oscillators [-n] oscs: Set the number of oscillators to use (default: 32)\n";
+	cerr << "   --wavetable [-w] length:     Set the wavetable length in samples (default: 1024)\n";
+	cerr << "   --help [-h]:                 Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"num-oscillators", 1, NULL, 'n'},
+		{"wavetable", 1, NULL, 'w'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hn:w:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'n':
+				gNumOscillators = atoi(optarg);
+				if(gNumOscillators <= 0) {
+					usage(basename(argv[0]));
+					exit(0);
+				}
+				break;
+		case 'w':
+				gWavetableLength = atoi(optarg);
+				if(gWavetableLength < 4)
+					gWavetableLength = 4;
+				if(gWavetableLength > 16384)
+					gWavetableLength = 16384;
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	if(settings.verbose) {
+		cout << "--> Using " << gNumOscillators << " oscillators and wavetable of " << gWavetableLength << " samples\n";
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/oscillator-bank/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,248 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <rtdk.h>
+#include <cstdlib>
+#include <cmath>
+#include <cstring>
+#include <time.h>
+
+const float kMinimumFrequency = 20.0f;
+const float kMaximumFrequency = 8000.0f;
+
+float *gWavetable;		// Buffer holding the precalculated sine lookup table
+float *gPhases;			// Buffer holding the phase of each oscillator
+float *gFrequencies;	// Buffer holding the frequencies of each oscillator
+float *gAmplitudes;		// Buffer holding the amplitudes of each oscillator
+float *gDFrequencies;	// Buffer holding the derivatives of frequency
+float *gDAmplitudes;	// Buffer holding the derivatives of amplitude
+
+float gAudioSampleRate;
+int gSampleCount;		// Sample counter for indicating when to update frequencies
+float gNewMinFrequency;
+float gNewMaxFrequency;
+
+// Task for handling the update of the frequencies using the matrix
+AuxiliaryTask gFrequencyUpdateTask;
+
+// These settings are carried over from main.cpp
+// Setting global variables is an alternative approach
+// to passing a structure to userData in setup()
+
+extern int gNumOscillators;
+extern int gWavetableLength;
+
+void recalculate_frequencies();
+
+extern "C" {
+	// Function prototype for ARM assembly implementation of oscillator bank
+	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
+							  int activePartialNum, int lookupTableSize,
+							  float *phases, float *frequencies, float *amplitudes,
+							  float *freqDerivatives, float *ampDerivatives,
+							  float *lookupTable);
+}
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+bool setup(BelaContext *context, void *userData)
+{
+	srandom(time(NULL));
+
+	if(context->audioChannels != 2) {
+		rt_printf("Error: this example needs stereo audio enabled\n");
+		return false;
+	}
+
+	// Initialise the sine wavetable
+	if(posix_memalign((void **)&gWavetable, 8, (gWavetableLength + 1) * sizeof(float))) {
+		rt_printf("Error allocating wavetable\n");
+		return false;
+	}
+	for(int n = 0; n < gWavetableLength + 1; n++)
+		gWavetable[n] = sinf(2.0 * M_PI * (float)n / (float)gWavetableLength);
+
+	// Allocate the other buffers
+	if(posix_memalign((void **)&gPhases, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating phase buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gFrequencies, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating frequency buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gAmplitudes, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating amplitude buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gDFrequencies, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating frequency derivative buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gDAmplitudes, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating amplitude derivative buffer\n");
+		return false;
+	}
+
+	// Initialise buffer contents
+
+	float freq = kMinimumFrequency;
+	float increment = (kMaximumFrequency - kMinimumFrequency) / (float)gNumOscillators;
+
+	for(int n = 0; n < gNumOscillators; n++) {
+		gPhases[n] = 0.0;
+
+		if(context->analogFrames == 0) {
+			// Random frequencies when used without matrix
+			gFrequencies[n] = kMinimumFrequency + (kMaximumFrequency - kMinimumFrequency) * ((float)random() / (float)RAND_MAX);
+		}
+		else {
+			// Constant spread of frequencies when used with matrix
+			gFrequencies[n] = freq;
+			freq += increment;
+		}
+
+		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
+		gFrequencies[n] *= (float)gWavetableLength / context->audioSampleRate;
+		gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators;
+		gDFrequencies[n] = gDAmplitudes[n] = 0.0;
+	}
+
+	increment = 0;
+	freq = 440.0;
+
+	for(int n = 0; n < gNumOscillators; n++) {
+		// Update the frequencies to a regular spread, plus a small amount of randomness
+		// to avoid weird phase effects
+		float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
+		float newFreq = freq * randScale;
+
+		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
+		gFrequencies[n] = newFreq * (float)gWavetableLength / context->audioSampleRate;
+
+		freq += increment;
+	}
+
+	// Initialise auxiliary tasks
+	if((gFrequencyUpdateTask = Bela_createAuxiliaryTask(&recalculate_frequencies, 85, "bela-update-frequencies")) == 0)
+		return false;
+
+	//for(int n = 0; n < gNumOscillators; n++)
+	//	rt_printf("%f\n", gFrequencies[n]);
+
+	gAudioSampleRate = context->audioSampleRate;
+	gSampleCount = 0;
+
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	// Initialise buffer to 0
+	memset(context->audioOut, 0, 2 * context->audioFrames * sizeof(float));
+
+	// Render audio frames
+	oscillator_bank_neon(context->audioFrames, context->audioOut,
+			gNumOscillators, gWavetableLength,
+			gPhases, gFrequencies, gAmplitudes,
+			gDFrequencies, gDAmplitudes,
+			gWavetable);
+
+	if(context->analogFrames != 0 && (gSampleCount += context->audioFrames) >= 128) {
+		gSampleCount = 0;
+		gNewMinFrequency = map(context->analogIn[0], 0, 1.0, 1000.0f, 8000.0f);
+		gNewMaxFrequency = map(context->analogIn[1], 0, 1.0, 1000.0f, 8000.0f);
+
+		// Make sure max >= min
+		if(gNewMaxFrequency < gNewMinFrequency) {
+			float temp = gNewMaxFrequency;
+			gNewMaxFrequency = gNewMinFrequency;
+			gNewMinFrequency = temp;
+		}
+
+		// Request that the lower-priority task run at next opportunity
+		//Bela_scheduleAuxiliaryTask(gFrequencyUpdateTask);
+	}
+}
+
+// This is a lower-priority call to update the frequencies which will happen
+// periodically when the matrix is enabled. By placing it at a lower priority,
+// it has minimal effect on the audio performance but it will take longer to
+// complete if the system is under heavy audio load.
+
+void recalculate_frequencies()
+{
+	float freq = gNewMinFrequency;
+	float increment = (gNewMaxFrequency - gNewMinFrequency) / (float)gNumOscillators;
+
+	for(int n = 0; n < gNumOscillators; n++) {
+		// Update the frequencies to a regular spread, plus a small amount of randomness
+		// to avoid weird phase effects
+		float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
+		float newFreq = freq * randScale;
+
+		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
+		gFrequencies[n] = newFreq * (float)gWavetableLength / gAudioSampleRate;
+
+		freq += increment;
+	}
+}
+
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	free(gWavetable);
+	free(gPhases);
+	free(gFrequencies);
+	free(gAmplitudes);
+	free(gDFrequencies);
+	free(gDAmplitudes);
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 04-oscillator-bank
+
+Oscillator Bank
+----------------------
+
+These files demonstrate an oscillator bank implemented in assembly code 
+that is used as part of the d-box project.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/samples/SampleData.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,19 @@
+/*
+ * SampleData.h
+ *
+ *  Created on: Nov 5, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef SAMPLEDATA_H_
+#define SAMPLEDATA_H_
+
+// User defined structure to pass between main and rendere complex data retrieved from file
+struct SampleData {
+	float *samples;	// Samples in file
+	int sampleLen;	// Total nume of samples
+};
+
+
+
+#endif /* SAMPLEDATA_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/samples/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,195 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <string>
+#include <getopt.h>
+#include <sndfile.h>				// to load audio files
+
+#include <Bela.h>
+#include "SampleData.h"
+
+using namespace std;
+
+// Load samples from file
+int initFile(string file, SampleData *smp)//float *& smp)
+{
+	SNDFILE *sndfile ;
+	SF_INFO sfinfo ;
+
+	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
+		cout << "Couldn't open file " << file << endl;
+		return 1;
+	}
+
+	int numChan = sfinfo.channels;
+	if(numChan != 1)
+	{
+		cout << "Error: " << file << " is not a mono file" << endl;
+		return 1;
+	}
+
+	smp->sampleLen = sfinfo.frames * numChan;
+	smp->samples = new float[smp->sampleLen];
+	if(smp == NULL){
+		cout << "Could not allocate buffer" << endl;
+		return 1;
+	}
+
+	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
+	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
+
+	// Pad with zeros in case we couldn't read whole file
+	for(int k = readcount; k <smp->sampleLen; k++)
+		smp->samples[k] = 0;
+
+	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
+		double	scale ;
+		int 	m ;
+
+		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
+		if (scale < 1e-10)
+			scale = 1.0 ;
+		else
+			scale = 32700.0 / scale ;
+		cout << "File samples scale = " << scale << endl;
+
+		for (m = 0; m < smp->sampleLen; m++)
+			smp->samples[m] *= scale;
+	}
+
+	sf_close(sndfile);
+
+	return 0;
+}
+
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	//rt_task_delete ((RT_TASK *) &gTriggerSamplesTask);
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --file [-f] filename:    Name of the file to load (default is \"sample.wav\")\n";
+	cerr << "   --help [-h]:             Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	string fileName;			// Name of the sample to load
+
+	SampleData sampleData;		// User define structure to pass data retrieved from file to render function
+	sampleData.samples = 0;
+	sampleData.sampleLen = -1;
+
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"file", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				fileName = string((char *)optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	if(fileName.empty()){
+		fileName = "samples/sample.wav";
+	}
+
+	if(settings.verbose) {
+		cout << "Loading file " << fileName << endl;
+	}
+
+	// Load file
+	if(initFile(fileName, &sampleData) != 0)
+	{
+		cout << "Error: unable to load samples " << endl;
+		return -1;
+	}
+
+	if(settings.verbose)
+		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
+
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &sampleData) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/04-Audio/samples/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,147 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <cmath>
+#include "SampleData.h"
+
+SampleData gSampleData;	// User defined structure to get complex data from main
+int gReadPtr;			// Position of last read sample from file
+
+// Task for handling the update of the frequencies using the matrix
+AuxiliaryTask gTriggerSamplesTask;
+
+bool initialise_trigger();
+void trigger_samples();
+
+bool setup(BelaContext *context, void *userData)
+{
+
+	// Retrieve a parameter passed in from the initAudio() call
+	gSampleData = *(SampleData *)userData;
+
+	gReadPtr = -1;
+
+	// Initialise auxiliary tasks
+	if(!initialise_trigger())
+		return false;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		float out = 0;
+
+		// If triggered...
+		if(gReadPtr != -1)
+			out += gSampleData.samples[gReadPtr++];	// ...read each sample...
+
+		if(gReadPtr >= gSampleData.sampleLen)
+			gReadPtr = -1;
+
+		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
+			context->audioOut[n * context->audioChannels + channel] = out;	// ...and put it in both left and right channel
+	}
+
+	// Request that the lower-priority task run at next opportunity
+	Bela_scheduleAuxiliaryTask(gTriggerSamplesTask);
+}
+
+// Initialise the auxiliary task
+// and print info
+
+bool initialise_trigger()
+{
+	if((gTriggerSamplesTask = Bela_createAuxiliaryTask(&trigger_samples, 50, "bela-trigger-samples")) == 0)
+		return false;
+
+	rt_printf("Press 'a' to trigger sample, 's' to stop\n");
+	rt_printf("Press 'q' to quit\n");
+
+	return true;
+}
+
+// This is a lower-priority call to periodically read keyboard input
+// and trigger samples. By placing it at a lower priority,
+// it has minimal effect on the audio performance but it will take longer to
+// complete if the system is under heavy audio load.
+
+void trigger_samples()
+{
+	// This is not a real-time task!
+	// Cos getchar is a system call, not handled by Xenomai.
+	// This task will be automatically down graded.
+
+	char keyStroke = '.';
+
+	keyStroke =	getchar();
+	while(getchar()!='\n'); // to read the first stroke
+
+	switch (keyStroke)
+	{
+		case 'a':
+			gReadPtr = 0;
+			break;
+		case 's':
+			gReadPtr = -1;
+			break;
+		case 'q':
+			gShouldStop = true;
+			break;
+		default:
+			break;
+	}
+}
+
+
+void cleanup(BelaContext *context, void *userData)
+{
+	delete[] gSampleData.samples;
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 04-samples
+
+Playback WAV files
+------------------
+
+This sketch shows how to playback audio samples from a buffer.
+
+An audio file is loaded into a buffer `SampleData` as `gSampleData`. This is 
+accessed with a read pointer that is incremented at audio rate within the render 
+function: `out += gSampleData.samples[gReadPtr++]`.
+
+Note that the read pointer is stopped from incrementing past the length of the 
+`gSampleData`. This is achieved by comparing the read pointer value against the 
+sample length which we can access as follows: `gSampleData.sampleLen`.
+
+The sample is triggered by keyboard input: (a) starts sample playback, (s) 
+stops sample playback. The triggering is treated as a lower priority task than 
+the audio. You can see this at the bottom of the render function: 
+`Bela_scheduleAuxiliaryTask(gTriggerSamplesTask)`;
+*/
Binary file examples/04-Audio/samples/sample.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/05-Communication/OSC/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,111 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <OSCServer.h>
+#include <OSCClient.h>
+
+OSCServer oscServer;
+OSCClient oscClient;
+
+// this example is designed to be run alongside resources/osc/osc.js
+
+// parse messages recieved by OSC Server
+// msg is Message class of oscpkt: http://gruntthepeon.free.fr/oscpkt/
+void parseMessage(oscpkt::Message msg){
+    
+    rt_printf("recieved message to: %s\n", msg.addressPattern().c_str());
+    
+    int intArg;
+    float floatArg;
+    if (msg.match("/osc-test").popInt32(intArg).popFloat(floatArg).isOkNoMoreArgs()){
+        rt_printf("recieved int %i and float %f\n", intArg, floatArg);
+    }
+    
+}
+
+bool setup(BelaContext *context, void *userData)
+{
+    // setup the OSC server to recieve on port 7562
+    oscServer.setup(7562);
+    // setup the OSC client to send on port 7563
+    oscClient.setup(7563);
+    
+    // the following code sends an OSC message to address /osc-setup
+    // then waits 1 second for a reply on /osc-setup-reply
+    bool handshakeRecieved = false;
+    oscClient.sendMessageNow(oscClient.newMessage.to("/osc-setup").end());
+    oscServer.recieveMessageNow(1000);
+    while (oscServer.messageWaiting()){
+        if (oscServer.popMessage().match("/osc-setup-reply")){
+            handshakeRecieved = true;
+        }
+    }
+    
+    if (handshakeRecieved){
+        rt_printf("handshake recieved!\n");
+    } else {
+        rt_printf("timeout!\n");
+    }
+    
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+    // recieve OSC messages, parse them, and send back an acknowledgment
+    while (oscServer.messageWaiting()){
+        parseMessage(oscServer.popMessage());
+        oscClient.queueMessage(oscClient.newMessage.to("/osc-acknowledge").add(5).add(4.2f).add(std::string("OSC message recieved")).end());
+    }
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 05-OSC
+
+Open Sound Control
+------------------
+
+This example shows an implementation of OSC (Open Sound Control) which was 
+developed at UC Berkeley Center for New Music and Audio Technology (CNMAT).
+
+It is designed to be run alongside resources/osc/osc.js
+
+The OSC server port on which to receive is set in `setup()` 
+via `oscServer.setup()`. Likewise the OSC client port on which to 
+send is set in `oscClient.setup()`.
+
+In `setup()` an OSC message to address `/osc-setup`, it then waits 
+1 second for a reply on `/osc-setup-reply`.
+
+in `render()` the code receives OSC messages, parses them, and sends 
+back an acknowledgment.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/05-Communication/basic-midi/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,182 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <Midi.h>
+#include <stdlib.h>
+#include <rtdk.h>
+#include <cmath>
+
+float gFreq;
+float gPhaseIncrement = 0;
+bool gIsNoteOn = 0;
+int gVelocity = 0;
+float gSamplingPeriod = 0;
+
+void midiMessageCallback(MidiChannelMessage message, void* arg){
+	if(arg != NULL){
+		rt_printf("Message from midi port %d: ", *(int*)arg);
+	}
+	message.prettyPrint();
+	if(message.getType() == kmmNoteOn){
+		gFreq = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
+		gVelocity = message.getDataByte(1);
+		gPhaseIncrement = 2 * M_PI * gFreq * gSamplingPeriod;
+		gIsNoteOn = gVelocity > 0;
+		rt_printf("v0:%f, ph: %6.5f, gVelocity: %d\n", gFreq, gPhaseIncrement, gVelocity);
+	}
+}
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+Midi midi;
+int gMidiPort0 = 0;
+bool setup(BelaContext *context, void *userData)
+{
+	midi.readFrom(gMidiPort0);
+	midi.writeTo(gMidiPort0);
+	midi.enableParser(true);
+	midi.setParserCallback(midiMessageCallback, &gMidiPort0);
+	if(context->analogFrames == 0) {
+		rt_printf("Error: this example needs the analog I/O to be enabled\n");
+		return false;
+	}
+	gSamplingPeriod = 1/context->audioSampleRate;
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+
+enum {kVelocity, kNoteOn, kNoteNumber};
+void render(BelaContext *context, void *userData)
+{
+// one way of getting the midi data is to parse them yourself
+//	(you should set midi.enableParser(false) above):
+/*
+	static midi_byte_t noteOnStatus = 0x90; //on channel 1
+	static int noteNumber = 0;
+	static int waitingFor = kNoteOn;
+	static int playingNote = -1;
+	int message;
+	while ((message = midi.getInput()) >= 0){
+		rt_printf("%d\n", message);
+		switch(waitingFor){
+		case kNoteOn:
+			if(message == noteOnStatus){
+				waitingFor = kNoteNumber;
+			}
+			break;
+		case kNoteNumber:
+			if((message & (1<<8)) == 0){
+				noteNumber = message;
+				waitingFor = kVelocity;
+			}
+			break;
+		case kVelocity:
+			if((message & (1<<8)) == 0){
+				int _velocity = message;
+				waitingFor = kNoteOn;
+				// "monophonic" behaviour, with priority to the latest note on
+				// i.e.: a note off from a previous note does not stop the current note
+				// still you might end up having a key down and no note being played if you pressed and released another
+				// key in the meantime
+				if(_velocity == 0 && noteNumber == playingNote){
+					noteOn = false;
+					playingNote = -1;
+					velocity = _velocity;
+				} else if (_velocity > 0) {
+					noteOn = true;
+					velocity = _velocity;
+					playingNote = noteNumber;
+					f0 = powf(2, (playingNote-69)/12.0f) * 440;
+					phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
+				}
+				rt_printf("NoteOn: %d, NoteNumber: %d, velocity: %d\n", noteOn, noteNumber, velocity);
+			}
+			break;
+		}
+	}
+*/
+	/*
+	int num;
+	//alternatively, you can use the built-in parser (only processes channel messages at the moment).
+	while((num = midi.getParser()->numAvailableMessages()) > 0){
+		static MidiChannelMessage message;
+		message = midi.getParser()->getNextChannelMessage();
+		message.prettyPrint();
+		if(message.getType() == kmmNoteOn){
+			f0 = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
+			velocity = message.getDataByte(1);
+			phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
+			noteOn = velocity > 0;
+			rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, gVelocity);
+		}
+	}
+	 */
+	// the following block toggles the LED on an Owl pedal
+	// and asks the pedal to return the status of the LED
+	// using MIDI control changes
+	for(unsigned int n = 0; n < context->analogFrames; n++){
+		static int count = 0;
+		static bool state = 0;
+		analogWriteOnce(context, n, 1, state);
+		if(count % 40000 == 0){
+			state = !state;
+			midi_byte_t bytes[6] = {176, 30, (char)(state*127), 176, 67, 30}; // toggle the OWL led and ask for the led status
+			midi.writeOutput(bytes, 6);
+		}
+		count++;
+	}
+	for(unsigned int n = 0; n < context->audioFrames; n++){
+		if(gIsNoteOn == 1){
+			static float phase = 0;
+			phase += gPhaseIncrement;
+			if(phase > 2 * M_PI)
+				phase -= 2 * M_PI;
+			float value = sinf(phase) * gVelocity/128.0f;
+			audioWrite(context, n, 0, value);
+			audioWrite(context, n, 1, value);
+		} else {
+			audioWrite(context, n, 0, 0);
+			audioWrite(context, n, 1, 0);
+		}
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/05-Communication/basic-network/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,114 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+	Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+	Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 440.0;		// Frequency of oscillator
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/05-Communication/basic-network/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,101 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+//#include <rtdk.h>
+#include <cmath>
+#include <NetworkSend.h>
+#include <ReceiveAudioThread.h>
+#include <Utilities.h>
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+NetworkSend networkSend;
+ReceiveAudioThread receive;
+float gFrequency;
+float gInverseSampleRate;
+float gPhase;
+bool setup(BelaContext *context, void *userData)
+{
+	// Retrieve a parameter passed in from the initAudio() call
+	gFrequency = *(float *)userData;
+
+	networkSend.setup(context->audioSampleRate, context->audioFrames, 0, 9999, "192.168.7.1");
+	receive.init(10000, context->audioFrames, 0);
+	receive.startThread();
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+	gPhase = 0;
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		float out = 0.7f * sinf(gPhase);
+		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
+		if(gPhase > 2.0 * M_PI)
+			gPhase -= 2.0 * M_PI;
+
+		networkSend.log(out);
+		float in;
+		int ret = receive.getSamplesSrc(&in, 1, 1);
+		for(unsigned int channel = 0; channel < context->audioChannels; channel++){
+			audioWrite(context, n, channel, in);
+		}
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 05-basic-network
+
+Networking 
+----------
+
+This sketch allows you to send audio and sensor data over UDP to a 
+DAW on the host. The host needs to run Udpioplugin which you can find 
+[here](https://code.soundsoftware.ac.uk/projects/udpioplugin). 
+
+Note that this sketch and the accompanying plugin are still in testing.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/06-Sensors/basic-pulseIn/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,73 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <PulseIn.h>
+#include <stdlib.h>
+#include <rtdk.h>
+#include <cmath>
+
+PulseIn pulseIn;
+int gPulseInPin = 0;
+int gDigitalOutPin = 1;
+int gPulseLength = 1234;
+int gSamplesBetweenPulses = 10000;
+
+bool setup(BelaContext *context, void *userData)
+{
+	pinMode(context, 0, gDigitalOutPin, OUTPUT);
+	pulseIn.init(context, gPulseInPin, 1); //third parameter is direction
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+	static bool pulseOut = 0;
+	static int count = 0;
+	for(unsigned int n = 0; n < context->digitalFrames; n++){
+		// detect if a pulse just ended
+		int duration = pulseIn.hasPulsed(context, n);
+		if(duration > 0){
+			rt_printf("duration = %d\n", duration);
+		}
+
+		// generate a rectangular waveform as a test signal.
+		// Connect gDigitalOutPin to gPulseInPin
+		// to verify that the detected pulse length is gPulseLength
+		if(count == gPulseLength ){
+			pulseOut = false;
+		}
+		if(count == (gPulseLength + gSamplesBetweenPulses)){
+			pulseOut = true;
+			count = 0;
+		}
+		digitalWrite(context, n, gDigitalOutPin, pulseOut);
+		count++;
+	}
+}
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/06-Sensors/mpr121/I2C_MPR121.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,176 @@
+/*
+ * I2C_MPR121.cpp
+ *
+ *  Created on: Oct 14, 2013
+ *      Author: Victor Zappi
+ */
+
+
+#include "I2C_MPR121.h"
+
+I2C_MPR121::I2C_MPR121() {
+
+}
+
+boolean I2C_MPR121::begin(uint8_t bus, uint8_t i2caddr) {
+  _i2c_address = i2caddr;
+	
+  if(initI2C_RW(bus, i2caddr, 0) > 0)
+	  return false;
+
+  // soft reset
+  writeRegister(MPR121_SOFTRESET, 0x63);
+  usleep(1000);
+  //delay(1);
+  for (uint8_t i=0; i<0x7F; i++) {
+  //  Serial.print("$"); Serial.print(i, HEX); 
+  //  Serial.print(": 0x"); Serial.println(readRegister8(i));
+  }
+  
+
+  writeRegister(MPR121_ECR, 0x0);
+
+  uint8_t c = readRegister8(MPR121_CONFIG2);
+  
+  if (c != 0x24) {
+	  rt_printf("MPR121 read 0x%x instead of 0x24\n", c);
+	  return false;
+  }
+
+  setThresholds(12, 6);
+  writeRegister(MPR121_MHDR, 0x01);
+  writeRegister(MPR121_NHDR, 0x01);
+  writeRegister(MPR121_NCLR, 0x0E);
+  writeRegister(MPR121_FDLR, 0x00);
+
+  writeRegister(MPR121_MHDF, 0x01);
+  writeRegister(MPR121_NHDF, 0x05);
+  writeRegister(MPR121_NCLF, 0x01);
+  writeRegister(MPR121_FDLF, 0x00);
+
+  writeRegister(MPR121_NHDT, 0x00);
+  writeRegister(MPR121_NCLT, 0x00);
+  writeRegister(MPR121_FDLT, 0x00);
+
+  writeRegister(MPR121_DEBOUNCE, 0);
+  writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
+  writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
+
+//  writeRegister(MPR121_AUTOCONFIG0, 0x8F);
+
+//  writeRegister(MPR121_UPLIMIT, 150);
+//  writeRegister(MPR121_TARGETLIMIT, 100); // should be ~400 (100 shifted)
+//  writeRegister(MPR121_LOWLIMIT, 50);
+  // enable all electrodes
+  writeRegister(MPR121_ECR, 0x8F);  // start with first 5 bits of baseline tracking
+
+  return true;
+}
+
+void I2C_MPR121::setThresholds(uint8_t touch, uint8_t release) {
+  for (uint8_t i=0; i<12; i++) {
+    writeRegister(MPR121_TOUCHTH_0 + 2*i, touch);
+    writeRegister(MPR121_RELEASETH_0 + 2*i, release);
+  }
+}
+
+uint16_t  I2C_MPR121::filteredData(uint8_t t) {
+  if (t > 12) return 0;
+  return readRegister16(MPR121_FILTDATA_0L + t*2);
+}
+
+uint16_t  I2C_MPR121::baselineData(uint8_t t) {
+  if (t > 12) return 0;
+  uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
+  return (bl << 2);
+}
+
+uint16_t  I2C_MPR121::touched(void) {
+  uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
+  return t & 0x0FFF;
+}
+
+/*********************************************************************/
+
+
+uint8_t I2C_MPR121::readRegister8(uint8_t reg) {
+    unsigned char inbuf, outbuf;
+    struct i2c_rdwr_ioctl_data packets;
+    struct i2c_msg messages[2];
+
+    /*
+     * In order to read a register, we first do a "dummy write" by writing
+     * 0 bytes to the register we want to read from.  This is similar to
+     * the packet in set_i2c_register, except it's 1 byte rather than 2.
+     */
+    outbuf = reg;
+    messages[0].addr  = 0x5A;
+    messages[0].flags = 0;
+    messages[0].len   = sizeof(outbuf);
+    messages[0].buf   = &outbuf;
+
+    /* The data will get returned in this structure */
+    messages[1].addr  = 0x5A;
+    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
+    messages[1].len   = sizeof(inbuf);
+    messages[1].buf   = &inbuf;
+
+    /* Send the request to the kernel and get the result back */
+    packets.msgs      = messages;
+    packets.nmsgs     = 2;
+    if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
+        rt_printf("Unable to send data");
+        return 0;
+    }
+
+    return inbuf;
+}
+
+uint16_t I2C_MPR121::readRegister16(uint8_t reg) {
+    unsigned char inbuf[2], outbuf;
+    struct i2c_rdwr_ioctl_data packets;
+    struct i2c_msg messages[2];
+
+    /*
+     * In order to read a register, we first do a "dummy write" by writing
+     * 0 bytes to the register we want to read from.  This is similar to
+     * the packet in set_i2c_register, except it's 1 byte rather than 2.
+     */
+    outbuf = reg;
+    messages[0].addr  = _i2c_address;
+    messages[0].flags = 0;
+    messages[0].len   = sizeof(outbuf);
+    messages[0].buf   = &outbuf;
+
+    /* The data will get returned in this structure */
+    messages[1].addr  = _i2c_address;
+    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
+    messages[1].len   = sizeof(inbuf);
+    messages[1].buf   = inbuf;
+
+    /* Send the request to the kernel and get the result back */
+    packets.msgs      = messages;
+    packets.nmsgs     = 2;
+    if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
+        rt_printf("Unable to send data");
+        return 0;
+    }
+
+    return (uint16_t)inbuf[0] | (((uint16_t)inbuf[1]) << 8);
+}
+
+/**************************************************************************/
+/*!
+    @brief  Writes 8-bits to the specified destination register
+*/
+/**************************************************************************/
+void I2C_MPR121::writeRegister(uint8_t reg, uint8_t value) {
+	uint8_t buf[2] = { reg, value };
+
+	if(write(i2C_file, buf, 2) != 2)
+	{
+		cout << "Failed to write register " << (int)reg << " on MPR121\n";
+		return;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/06-Sensors/mpr121/I2C_MPR121.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,82 @@
+/*
+ * MPR121 Bela demo
+ * 
+ * Andrew McPherson
+ * Based on Adafruit library by Limor Fried/Ladyada
+ */
+
+#ifndef I2CTK_H_
+#define I2CTK_H_
+
+#include <I2c.h>
+#include "Utilities.h"
+
+typedef bool boolean;
+
+#define MPR121_I2CADDR_DEFAULT 0x5A
+
+#define MPR121_TOUCHSTATUS_L 0x00
+#define MPR121_TOUCHSTATUS_H 0x01
+#define MPR121_FILTDATA_0L  0x04
+#define MPR121_FILTDATA_0H  0x05
+#define MPR121_BASELINE_0   0x1E
+#define MPR121_MHDR         0x2B
+#define MPR121_NHDR         0x2C
+#define MPR121_NCLR         0x2D
+#define MPR121_FDLR         0x2E
+#define MPR121_MHDF         0x2F
+#define MPR121_NHDF         0x30
+#define MPR121_NCLF         0x31
+#define MPR121_FDLF         0x32
+#define MPR121_NHDT         0x33
+#define MPR121_NCLT         0x34
+#define MPR121_FDLT         0x35
+
+#define MPR121_TOUCHTH_0    0x41
+#define MPR121_RELEASETH_0    0x42
+#define MPR121_DEBOUNCE 0x5B
+#define MPR121_CONFIG1 0x5C
+#define MPR121_CONFIG2 0x5D
+#define MPR121_CHARGECURR_0 0x5F
+#define MPR121_CHARGETIME_1 0x6C
+#define MPR121_ECR 0x5E
+#define MPR121_AUTOCONFIG0 0x7B
+#define MPR121_AUTOCONFIG1 0x7C
+#define MPR121_UPLIMIT   0x7D
+#define MPR121_LOWLIMIT  0x7E
+#define MPR121_TARGETLIMIT  0x7F
+
+#define MPR121_GPIODIR  0x76
+#define MPR121_GPIOEN  0x77
+#define MPR121_GPIOSET  0x78
+#define MPR121_GPIOCLR  0x79
+#define MPR121_GPIOTOGGLE  0x7A
+
+#define MPR121_SOFTRESET 0x80
+
+class I2C_MPR121 : public I2c
+{
+public:
+	// Hardware I2C
+	I2C_MPR121();
+
+	boolean begin(uint8_t bus = 1, uint8_t i2caddr = MPR121_I2CADDR_DEFAULT);
+
+	uint16_t filteredData(uint8_t t);
+	uint16_t  baselineData(uint8_t t);
+
+	uint8_t readRegister8(uint8_t reg);
+	uint16_t readRegister16(uint8_t reg);
+	void writeRegister(uint8_t reg, uint8_t value);
+	uint16_t touched(void);
+ 
+ 	void setThresholds(uint8_t touch, uint8_t release);
+	
+	int readI2C() { return 0; } // Unused
+	
+private:
+	int _i2c_address;
+};
+
+
+#endif /* I2CTK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/06-Sensors/mpr121/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,171 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+#include <cmath>
+#include <rtdk.h>
+#include "I2C_MPR121.h"
+
+// How many pins there are
+#define NUM_TOUCH_PINS 12
+
+// Define this to print data to terminal
+#undef DEBUG_MPR121
+
+// Change this to change how often the MPR121 is read (in Hz)
+int readInterval = 50;
+
+// Change this threshold to set the minimum amount of touch
+int threshold = 40;
+
+// This array holds the continuous sensor values
+int sensorValue[NUM_TOUCH_PINS];
+
+// ---- test code stuff -- can be deleted for your example ----
+
+// 12 notes of a C major scale...
+float gFrequencies[NUM_TOUCH_PINS] = {261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25, 698.25, 783.99};
+
+// This is internal stuff for the demo
+float gNormFrequencies[NUM_TOUCH_PINS];
+float gPhases[NUM_TOUCH_PINS] = {0};
+
+// ---- internal stuff -- do not change -----
+
+I2C_MPR121 mpr121;			// Object to handle MPR121 sensing
+AuxiliaryTask i2cTask;		// Auxiliary task to read I2C
+
+int readCount = 0;			// How long until we read again...
+int readIntervalSamples = 0; // How many samples between reads
+
+void readMPR121();
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+bool setup(BelaContext *context, void *userData)
+{
+	if(!mpr121.begin(1, 0x5A)) {
+		rt_printf("Error initialising MPR121\n");
+		return false;
+	}
+	
+	i2cTask = Bela_createAuxiliaryTask(readMPR121, 50, "bela-mpr121");
+	readIntervalSamples = context->audioSampleRate / readInterval;
+	
+	for(int i = 0; i < NUM_TOUCH_PINS; i++) {
+		gNormFrequencies[i] = 2.0 * M_PI * gFrequencies[i] / context->audioSampleRate;
+	}
+	
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numAnalogFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	for(int n = 0; n < context->audioFrames; n++) {
+		// Keep this code: it schedules the touch sensor readings
+		if(++readCount >= readIntervalSamples) {
+			readCount = 0;
+			Bela_scheduleAuxiliaryTask(i2cTask);
+		}
+		
+		float sample = 0.0;
+		
+		// This code can be replaced with your favourite audio code
+		for(int i = 0; i < NUM_TOUCH_PINS; i++) {
+			float amplitude = sensorValue[i] / 400.0;
+			
+			// Prevent clipping
+			if(amplitude > 0.5)
+				amplitude = 0.5;
+			
+			sample += amplitude * sinf(gPhases[i]);
+			gPhases[i] += gNormFrequencies[i];
+			if(gPhases[i] > 2.0 * M_PI)
+				gPhases[i] -= 2.0 * M_PI;
+		}
+		
+		for(int ch = 0; ch < context->audioChannels; ch++)
+			context->audioOut[context->audioChannels * n + ch] = sample;
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	// Nothing to do here
+}
+
+
+// Auxiliary task to read the I2C board
+void readMPR121()
+{
+	for(int i = 0; i < NUM_TOUCH_PINS; i++) {
+		sensorValue[i] = -(mpr121.filteredData(i) - mpr121.baselineData(i));
+		sensorValue[i] -= threshold;
+		if(sensorValue[i] < 0)
+			sensorValue[i] = 0;
+#ifdef DEBUG_MPR121
+		rt_printf("%d ", sensorValue[i]);
+#endif
+	}
+#ifdef DEBUG_MPR121
+	rt_printf("\n");
+#endif
+	
+	// You can use this to read binary on/off touch state more easily
+	//rt_printf("Touched: %x\n", mpr121.touched());
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 06-capacitive-touch
+
+Capacitive touch sensing with MPR121
+---------------------------
+
+This sketch allows you to hook up an MPR121 capactive touch sensing device
+to Bela, for example the SparkFun Capacitive Touch Sensor Breakout - MPR121.
+The breakout board gives you 12 electrode connections.
+
+To get this working with Bela you need to connect the breakout board to the I2C
+terminal on the Bela board. See the Pin guide for details of which pin is which.
+
+The sensor data will then be available for you to use in the array 
+`sensorValue[NUM_TOUCH_PINS]`.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/basic-writeFile/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <unistd.h>
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 440.0;	// Frequency of oscillator
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/basic-writeFile/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,100 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h> 
+#include <cmath>
+#include <WriteFile.h>
+
+float gPhase1, gPhase2;
+float gFrequency1, gFrequency2;
+float gInverseSampleRate;
+
+WriteFile file1;
+WriteFile file2;
+
+bool setup(BelaContext *context, void *userData)
+{
+	gInverseSampleRate = 1.0/context->audioSampleRate;
+	file1.init("out1.m"); //set the file name to write to
+	file1.setHeader("myvar=[\n"); //set a line to be printed at the beginning of the file
+	file1.setFooter("];\n"); //set a line to be printed at the end of the file
+	file1.setEcho(true); // enable echo to the console (as well as to the file)
+	file1.setFormat("%.5f %.10f %f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers)
+	file2.init("out2.m");
+	file2.setHeader("input=[\n");
+	file2.setFooter("];\n");
+	file2.setEcho(false);
+	file2.setFormat("%f\n");
+	gPhase1 = 0.0;
+	gPhase2 = 0.0;
+
+	gFrequency1 = 200.0;
+	gFrequency2 = 201.0;
+	return true; 
+}
+
+void render(BelaContext *context, void *userData)
+{
+	static int count = 0;
+	if((count&16383) == 0){
+    	file2.log(context->audioIn, context->audioFrames); //write the input buffer every so often
+	}
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+	    float chn1 = sinf(gPhase1);
+	    float chn2 = sinf(gPhase2);
+	    gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate;
+	    gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
+		if(gPhase1 > 2.0 * M_PI)
+			gPhase1 -= 2.0 * M_PI;
+		if(gPhase2 > 2.0 * M_PI)
+			gPhase2 -= 2.0 * M_PI;
+		if( (count&511) == 0){
+			file1.log(chn1);
+			file1.log(chn2);
+			file1.log(count);
+		}
+		count++;
+	}
+}
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BelaContext *context, void *userData)
+{
+    
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 07-write-file
+
+Writing data to a file
+---------------------------
+
+This sketch demonstrates how to log values from within a project for later processing or analysis.
+
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/loggingSensors/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <unistd.h>
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 440.0;	// Frequency of oscillator
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/07-DataLogging/loggingSensors/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,73 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h> 
+#include <cmath>
+#include <WriteFile.h>
+
+WriteFile file1;
+WriteFile file2;
+
+bool setup(BelaContext *context, void *userData)
+{
+	file1.init("out.bin"); //set the file name to write to
+	file1.setEchoInterval(1000);
+	file1.setFileType(kBinary);
+	file1.setFormat("%.4f %.4f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers). When in binary mode, this is used only for echoing to console
+	file2.init("out.m"); //set the file name to write to
+	file2.setHeader("myvar=[\n"); //set one or more lines to be printed at the beginning of the file
+	file2.setFooter("];\n"); //set one or more lines to be printed at the end of the file
+	file2.setFormat("%.4f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers)
+	file2.setFileType(kText);
+	file2.setEchoInterval(10000); // only print to the console 1 line every other 10000
+	return true; 
+}
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
+			file1.log(&(context->analogIn[n*context->analogFrames]), 2); // log an array of values
+			file2.log(context->analogIn[n*context->analogFrames]); // log a single value
+	}
+}
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BelaContext *context, void *userData)
+{
+    
+}
+
+/* ------------ Project Explantation ------------ */
+
+/**
+\example 07-logging-sensors
+
+Logging Sensor Data
+---------------------------
+
+This sketch demonstrates how to log sensor data for later processing or analysis.
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/basicAnalogIn/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,30 @@
+#N canvas 203 356 637 339 10;
+#X obj 63 170 osc~ 440;
+#X obj 63 223 dac~;
+#X obj 63 191 *~;
+#X text 440 95 ADC 3: Analog In 0;
+#X text 34 41 Basic analog in (or 'theremin');
+#X text 34 51 ===============================;
+#X text 121 105 << Use first two analog in's;
+#X text 440 49 ADC routing:;
+#X text 440 57 ------------;
+#X text 440 105 ADC 4: Analog In 1;
+#X text 440 115 ADC 5: Analog In 2;
+#X text 440 125 ADC 6: Analog In 3;
+#X text 440 135 ADC 7: Analog In 4;
+#X text 440 145 ADC 8: Analog In 5;
+#X text 440 155 ADC 9: Analog In 6;
+#X text 440 165 ADC 10: Analog In 7;
+#X text 440 75 ADC 1: Audio In L;
+#X text 440 85 ADC 2: Audio In R;
+#X obj 63 149 *~ 880;
+#X obj 63 106 adc~ 3 4;
+#X text 355 277 ---------------------------------;
+#X text 355 267 @krighxz / BELA / heavy / 12/2015;
+#X text 379 286 beaglert.cc / enzienaudio.com;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
+#X connect 2 0 1 1;
+#X connect 18 0 0 0;
+#X connect 19 0 18 0;
+#X connect 19 1 2 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/basicAnalogOut/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,30 @@
+#N canvas 275 504 679 362 10;
+#X text 148 124 << Use first two analog in's;
+#X text 431 57 ------------;
+#X text 44 51 Basic analog out;
+#X text 44 61 ================;
+#X text 431 95 DAC 3: Analog Out 0;
+#X text 431 105 DAC 4: Analog Out 1;
+#X text 431 115 DAC 5: Analog Out 2;
+#X text 431 125 DAC 6: Analog Out 3;
+#X text 431 145 DAC 8: Analog Out 5;
+#X text 431 135 DAC 7: Analog Out 4;
+#X text 431 155 DAC 9: Analog Out 6;
+#X text 431 165 DAC 10: Analog Out 7;
+#X text 431 85 DAC 2: Audio Out R;
+#X text 431 75 DAC 1: Audio Out L;
+#X obj 92 201 *~;
+#X obj 92 159 *~ 10;
+#X obj 92 180 osc~ 1;
+#X obj 35 242 dac~ 1 2 3;
+#X text 143 241 << Output to first analog out;
+#X text 431 49 DAC routing:;
+#X text 432 289 ---------------------------------;
+#X text 432 279 @krighxz / BELA / heavy / 12/2015;
+#X text 456 298 beaglert.cc / enzienaudio.com;
+#X obj 92 125 adc~ 3 4;
+#X connect 14 0 17 2;
+#X connect 15 0 16 0;
+#X connect 16 0 14 0;
+#X connect 23 0 15 0;
+#X connect 23 1 14 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/circularBuffer/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,79 @@
+#N canvas 436 490 738 494 10;
+#X obj 135 167 loadbang;
+#X msg 135 212 1;
+#X obj 183 234 / 44.1;
+#X obj 135 253 metro;
+#X obj 135 286 f;
+#X obj 160 286 + 64;
+#X obj 160 308 % 65536, f 8;
+#X msg 160 329 start \$1;
+#X obj 160 351 tabwrite~ circbuf;
+#X obj 363 303 - 32768;
+#X obj 363 325 + 65536;
+#X obj 363 347 % 65536;
+#X obj 342 371 +~ 0;
+#X msg 381 236 0;
+#X obj 342 258 phasor~;
+#X obj 342 392 tabread4~ circbuf;
+#X obj 341 415 dac~;
+#N canvas 422 781 312 126 buf 0;
+#N canvas 0 22 450 278 (subpatch) 0;
+#X array circbuf 65536 float 2;
+#X coords 0 1 65535 -1 256 64 1 0 0;
+#X restore 23 28 graph;
+#X restore 129 441 pd buf;
+#X obj 32 101 osc~ 440;
+#X obj 342 213 samplerate~;
+#X obj 134 189 t b b b b;
+#X text 30 82 audio input;
+#X text 219 310 write pointer;
+#X text 412 349 read pointer;
+#X obj 342 282 *~ 16;
+#X obj 342 236 / 16;
+#X obj 183 214 f 16;
+#X obj 363 189 r \$0-blocksize;
+#X obj 204 186 r \$0-blocksize;
+#X obj 394 259 r \$0-blocksize;
+#X obj 390 123 s \$0-blocksize;
+#X text 34 13 VIRTUAL CIRCULAR BUFFER;
+#X text 34 23 =======================;
+#X obj 390 55 loadbang;
+#X msg 390 77 16;
+#X text 517 454 ---------------------------------;
+#X text 517 444 @krighxz / BELA / heavy / 12/2015;
+#X text 541 463 beaglert.cc / enzienaudio.com;
+#X text 426 78 << replace with target blocksize;
+#X text 446 90 BELA default: 16;
+#X text 446 102 PD default: 64;
+#X connect 0 0 20 0;
+#X connect 1 0 3 0;
+#X connect 2 0 3 1;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 5 0 9 0;
+#X connect 6 0 7 0;
+#X connect 6 0 4 1;
+#X connect 7 0 8 0;
+#X connect 9 0 10 0;
+#X connect 10 0 11 0;
+#X connect 11 0 12 1;
+#X connect 12 0 15 0;
+#X connect 13 0 14 1;
+#X connect 14 0 24 0;
+#X connect 15 0 16 0;
+#X connect 15 0 16 1;
+#X connect 18 0 8 0;
+#X connect 19 0 25 0;
+#X connect 20 0 1 0;
+#X connect 20 1 26 0;
+#X connect 20 2 13 0;
+#X connect 20 3 19 0;
+#X connect 24 0 12 0;
+#X connect 25 0 14 0;
+#X connect 26 0 2 0;
+#X connect 27 0 25 1;
+#X connect 28 0 26 1;
+#X connect 29 0 24 1;
+#X connect 33 0 34 0;
+#X connect 34 0 30 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/digital/bela_digital-help.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,97 @@
+#N canvas 121 46 877 628 10;
+#X obj 64 94 r bela_digitalIn11;
+#X obj 219 94 r bela_digitalIn12;
+#X obj 386 107 adc~ 13 14;
+#X text 49 64 Digital in \, message rate;
+#X text 214 69 Digital in \, message rate;
+#X text 394 85 Digital ins \, signal rate;
+#X obj 32 283 s bela_digitalOut15;
+#X text 13 309 Digital out \, message rate;
+#X obj 396 593 s bela_setDigital;
+#X obj 396 533 loadbang;
+#X msg 431 401 in 11;
+#X text 524 390 First argument is the pin direction Second argument
+is the pin number Third argument is the rate \, can be "~" or "sig"
+for signal-rate or "message" for message-rate. Defaults to message-rate.
+;
+#X msg 431 458 in 13 ~;
+#X msg 432 429 in 12 message;
+#X msg 517 506 disable 17;
+#X obj 386 139 snapshot~;
+#X obj 500 134 snapshot~;
+#X obj 529 56 loadbang;
+#X obj 384 181 print digitalIn13;
+#X obj 500 183 print digitalIn14;
+#X obj 497 105 metro 200;
+#X text 525 474 To stop using a pin (e.g.: to save CPU) \, send a disable
+message containing the pin number;
+#X obj 224 280 dac~ 16;
+#X obj 22 232 metro 500;
+#X obj 32 257 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 224 253 phasor~ 300;
+#X text 160 234 Nice \, anti-aliased square wave;
+#X obj 22 207 loadbang;
+#X text 15 181 Blink that LED!;
+#X obj 411 306 dac~ 17;
+#X obj 405 248 osc~ 300;
+#X obj 470 248 phasor~ 169;
+#X obj 457 278 -~ 0.5;
+#X text 403 210 Sum signals together for unpredictable effects;
+#X obj 612 303 dac~ 18;
+#X text 198 305 Digital out \, signal rate;
+#X text 378 325 Digital out \, signal rate;
+#X text 588 325 Digital out \, signal rate;
+#X obj 608 222 adc~;
+#X obj 612 249 *~ 0.5;
+#X obj 612 276 +~ 0.5;
+#X text 585 203 The ultimate bit-crusher;
+#X msg 426 555 in 11 \, in 12 \, in 13 ~ \, in 14 ~ \, out 15 \, out
+16 ~ \, out 17 ~ \, out 18 ~;
+#X text 23 377 Each digital channel can be configured as either an
+input or an output. Send messages to bela_setDigital to configure the
+digitalPins (needed before using them). Pins settings can be modified
+at will during execution. Message-rate input pins receive messages
+only when the input changes. Message-rate output pins will write to
+the output the most recent value you send them. Signal-rate inputs
+and outputs are handled as regular audio channels. Outputs are thresholded
+to 0.5 before being written to the actual output. Note that each pin
+that is managed adds to the CPU usage \, so only activate the pins
+you actually need.;
+#X text 34 19 Digital channels are numbered 11 to 26 \, which corresponds
+to Bela's 0 to 15 digital channels. They can be set to respond at message
+rate or at signal rate;
+#X obj 415 271 osc~ 1;
+#X obj 385 157 change;
+#X obj 500 158 change;
+#X obj 64 116 print digitalIn11;
+#X obj 219 117 print digitalIn12;
+#X connect 0 0 48 0;
+#X connect 1 0 49 0;
+#X connect 2 0 15 0;
+#X connect 2 1 16 0;
+#X connect 9 0 42 0;
+#X connect 10 0 8 0;
+#X connect 12 0 8 0;
+#X connect 13 0 8 0;
+#X connect 14 0 8 0;
+#X connect 15 0 46 0;
+#X connect 16 0 47 0;
+#X connect 17 0 20 0;
+#X connect 20 0 16 0;
+#X connect 20 0 15 0;
+#X connect 23 0 24 0;
+#X connect 24 0 6 0;
+#X connect 25 0 22 0;
+#X connect 27 0 23 0;
+#X connect 30 0 29 0;
+#X connect 31 0 32 0;
+#X connect 32 0 29 0;
+#X connect 38 0 39 0;
+#X connect 38 1 39 0;
+#X connect 39 0 40 0;
+#X connect 40 0 34 0;
+#X connect 42 0 8 0;
+#X connect 45 0 29 0;
+#X connect 46 0 18 0;
+#X connect 47 0 19 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/digital/digital_example.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,89 @@
+#N canvas 279 78 857 690 10;
+#X obj 18 477 osc~ 200;
+#X obj 57 522 *~;
+#X obj 112 405 line~ 1;
+#X msg 116 372 1 \, 0 200;
+#X obj 205 472 line~ 1;
+#X msg 209 439 1 \, 0 200;
+#X obj 210 405 select 1;
+#X obj 140 531 *~;
+#X obj 484 601 s bela_setDigital;
+#X obj 484 532 loadbang;
+#X msg 65 445 0;
+#X obj 116 332 r bela_digitalIn12;
+#X obj 422 217 r bela_digitalIn14;
+#X obj 422 243 s bela_digitalOut13;
+#X obj 285 218 r bela_digitalIn12;
+#X obj 285 243 s bela_digitalOut11;
+#X obj 374 339 timer;
+#X msg 404 304 bang;
+#X msg 368 304 bang;
+#X obj 555 184 metro 1000;
+#X obj 575 304 s bela_digitalOut15;
+#X obj 374 366 print sourceto12;
+#X obj 488 351 timer;
+#X msg 518 316 bang;
+#X msg 482 316 bang;
+#X obj 487 380 print sourceto14;
+#X obj 663 15 r bela_digitalIn16;
+#X msg 553 265 1;
+#X obj 577 214 delay 500;
+#X obj 480 275 select 1;
+#X obj 346 268 select 1;
+#X msg 584 281 0;
+#X obj 634 251 select 1 0;
+#X obj 80 622 dac~ 3 4;
+#X obj 65 566 expr~ $v1*0.5 + 0.5;
+#X obj 138 588 expr~ $v1*0.5 + 0.5;
+#X obj 65 202 dac~ 11;
+#X obj 114 83 osc~ 300;
+#X obj 176 179 dac~ 1 3;
+#X obj 34 136 adc~ 17;
+#X obj 423 504 delay 3000;
+#X msg 388 552 disable 12;
+#X msg 484 552 out 11 ~ \, out 13 \, in 14 \, out 15 \, in 16 \, in
+17 ~;
+#X connect 0 0 1 0;
+#X connect 0 0 7 0;
+#X connect 1 0 34 0;
+#X connect 2 0 1 1;
+#X connect 3 0 2 0;
+#X connect 4 0 7 1;
+#X connect 5 0 4 0;
+#X connect 6 0 5 0;
+#X connect 6 0 10 0;
+#X connect 7 0 35 0;
+#X connect 9 0 42 0;
+#X connect 9 0 40 0;
+#X connect 10 0 0 1;
+#X connect 11 0 3 0;
+#X connect 12 0 13 0;
+#X connect 12 0 29 0;
+#X connect 14 0 15 0;
+#X connect 14 0 30 0;
+#X connect 16 0 21 0;
+#X connect 17 0 16 1;
+#X connect 18 0 16 0;
+#X connect 19 0 27 0;
+#X connect 19 0 28 0;
+#X connect 22 0 25 0;
+#X connect 23 0 22 1;
+#X connect 24 0 22 0;
+#X connect 26 0 32 0;
+#X connect 27 0 20 0;
+#X connect 27 0 24 0;
+#X connect 27 0 18 0;
+#X connect 28 0 31 0;
+#X connect 29 0 23 0;
+#X connect 30 0 17 0;
+#X connect 31 0 20 0;
+#X connect 32 0 27 0;
+#X connect 32 1 31 0;
+#X connect 34 0 33 0;
+#X connect 35 0 33 1;
+#X connect 37 0 38 0;
+#X connect 37 0 38 1;
+#X connect 39 0 36 0;
+#X connect 40 0 41 0;
+#X connect 41 0 8 0;
+#X connect 42 0 8 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/envelopeTrigger/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,196 @@
+#N canvas 646 209 359 287 10;
+#X obj 28 207 dac~;
+#N canvas 324 380 556 621 env 0;
+#N canvas 886 1001 131 207 >~ 0;
+#X obj 19 -37 -~;
+#X obj 19 -58 min~;
+#X obj 19 26 *~ 1e+37;
+#X obj 19 5 +~ 1e-37;
+#X obj 19 -16 clip~ -1e-37 0;
+#X obj 19 -83 inlet~;
+#X obj 62 -83 inlet~;
+#X obj 19 48 outlet~;
+#X connect 0 0 4 0;
+#X connect 1 0 0 0;
+#X connect 2 0 7 0;
+#X connect 3 0 2 0;
+#X connect 4 0 3 0;
+#X connect 5 0 1 0;
+#X connect 6 0 0 1;
+#X connect 6 0 1 1;
+#X restore 199 106 pd >~;
+#X obj 23 173 /~ 44100;
+#X obj 68 153 samplerate~;
+#X obj 68 133 loadbang;
+#X obj 199 128 biquad~ 0 0 -1 1 0;
+#X obj 23 209 rpole~;
+#X obj 23 153 sig~ 1;
+#X obj 226 171 sig~ 0.5;
+#N canvas 0 22 110 231 <~ 0;
+#X obj 11 -41 -~;
+#X obj 11 29 +~ 1e-37;
+#X obj 11 8 clip~ -1e-37 0;
+#X obj 11 -86 inlet~;
+#X obj 55 -85 inlet~;
+#X obj 11 -62 max~;
+#X obj 11 -17 *~ -1;
+#X obj 11 81 outlet~;
+#X obj 11 50 *~ 1e+37;
+#X connect 0 0 6 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 1;
+#X connect 4 0 5 1;
+#X connect 5 0 0 0;
+#X connect 6 0 2 0;
+#X connect 8 0 7 0;
+#X restore 199 192 pd <~;
+#X text 237 193 (x != x);
+#X obj 23 467 *~;
+#X obj 199 150 *~ -1;
+#X obj 23 331 *~ 512;
+#X obj 23 229 clip~ 0 1;
+#X obj 23 352 tabread4~ env1;
+#X obj 23 310 *~;
+#X obj 199 64 abs~;
+#X obj 199 43 hip~ 1;
+#X obj 199 22 inlet~ excitationSignal;
+#X obj 218 269 sig~ 1;
+#X obj 218 292 /~;
+#X obj 226 86 inlet~ threshold;
+#X obj 262 229 inlet~ envDuration;
+#X obj 38 445 osc~ 220;
+#X obj 38 425 +~ 50;
+#X obj 38 385 *~;
+#X obj 38 405 *~ 1000;
+#X obj 262 269 clip~ 1e-05 100000;
+#X obj 23 487 outlet~;
+#N canvas 0 22 450 278 (subpatch) 0;
+#X array env1 512 float 3;
+#A 0 0 0.0625 0.0883883 0.108253 0.125 0.139754 0.153093 0.165359 0.176777
+0.1875 0.197642 0.207289 0.216506 0.225347 0.233854 0.242061 0.25 0.257694
+0.265165 0.272431 0.279509 0.286411 0.293151 0.299739 0.306186 0.3125
+0.318689 0.32476 0.330719 0.336573 0.342327 0.347985 0.353553 0.359035
+0.364434 0.369755 0.375 0.380173 0.385276 0.390312 0.395285 0.400195
+0.405046 0.40984 0.414578 0.419263 0.423896 0.428478 0.433013 0.4375
+0.441942 0.446339 0.450694 0.455007 0.459279 0.463512 0.467707 0.471865
+0.475986 0.480072 0.484123 0.488141 0.492125 0.496078 0.5 0.503891
+0.507752 0.511585 0.515388 0.519164 0.522913 0.526634 0.53033 0.534
+0.537645 0.541266 0.544862 0.548435 0.551985 0.555512 0.559017 0.5625
+0.565962 0.569402 0.572822 0.576222 0.579601 0.582961 0.586302 0.589624
+0.592927 0.596212 0.599479 0.602728 0.60596 0.609175 0.612372 0.615554
+0.618718 0.621867 0.625 0.628117 0.631219 0.634306 0.637377 0.640434
+0.643477 0.646505 0.649519 0.652519 0.655506 0.658478 0.661438 0.664384
+0.667317 0.670238 0.673146 0.676041 0.678924 0.681795 0.684653 0.6875
+0.690335 0.693159 0.695971 0.698771 0.701561 0.704339 0.707107 0.709864
+0.71261 0.715345 0.71807 0.720785 0.72349 0.726184 0.728869 0.731544
+0.734209 0.736864 0.73951 0.742146 0.744773 0.747391 0.75 0.7526 0.75519
+0.757772 0.760345 0.76291 0.765466 0.768013 0.770552 0.773082 0.775605
+0.778119 0.780625 0.783123 0.785613 0.788095 0.790569 0.793036 0.795495
+0.797947 0.800391 0.802827 0.805256 0.807678 0.810093 0.8125 0.8149
+0.817294 0.81968 0.822059 0.824432 0.826797 0.829156 0.831508 0.833854
+0.836193 0.838525 0.840851 0.843171 0.845484 0.847791 0.850092 0.852386
+0.854675 0.856957 0.859233 0.861503 0.863767 0.866025 0.868278 0.870524
+0.872765 0.875 0.877229 0.879453 0.881671 0.883883 0.88609 0.888292
+0.890488 0.892679 0.894864 0.897044 0.899218 0.901388 0.903552 0.905711
+0.907865 0.910014 0.912157 0.914296 0.91643 0.918559 0.920682 0.922801
+0.924916 0.927025 0.929129 0.931229 0.933324 0.935414 0.9375 0.939581
+0.941657 0.943729 0.945797 0.947859 0.949918 0.951972 0.954021 0.956066
+0.958107 0.960143 0.962175 0.964203 0.966227 0.968246 0.970261 0.972272
+0.974279 0.976281 0.97828 0.980274 0.982265 0.984251 0.986233 0.988212
+0.990186 0.992157 0.994123 0.996086 0.998045 1 0.992172 0.984375 0.976609
+0.968874 0.961169 0.953495 0.945852 0.938239 0.930657 0.923106 0.915586
+0.908097 0.900638 0.89321 0.885813 0.878447 0.871111 0.863806 0.856532
+0.849289 0.842076 0.834894 0.827743 0.820623 0.813533 0.806474 0.799446
+0.792449 0.785483 0.778547 0.771642 0.764767 0.757924 0.751111 0.744329
+0.737578 0.730857 0.724168 0.717509 0.71088 0.704283 0.697716 0.69118
+0.684675 0.678201 0.671757 0.665344 0.658962 0.652611 0.64629 0.64
+0.633741 0.627513 0.621315 0.615148 0.609012 0.602907 0.596832 0.590788
+0.584775 0.578793 0.572841 0.56692 0.56103 0.555171 0.549343 0.543545
+0.537778 0.532041 0.526336 0.520661 0.515017 0.509404 0.503822 0.49827
+0.492749 0.487259 0.481799 0.476371 0.470973 0.465605 0.460269 0.454963
+0.449689 0.444444 0.439231 0.434048 0.428897 0.423775 0.418685 0.413625
+0.408597 0.403599 0.398631 0.393695 0.388789 0.383914 0.37907 0.374256
+0.369473 0.364721 0.36 0.355309 0.35065 0.346021 0.341423 0.336855
+0.332318 0.327812 0.323337 0.318893 0.314479 0.310096 0.305744 0.301423
+0.297132 0.292872 0.288643 0.284444 0.280277 0.27614 0.272034 0.267958
+0.263914 0.2599 0.255917 0.251965 0.248043 0.244152 0.240292 0.236463
+0.232664 0.228897 0.22516 0.221453 0.217778 0.214133 0.210519 0.206936
+0.203383 0.199862 0.196371 0.19291 0.189481 0.186082 0.182714 0.179377
+0.176071 0.172795 0.16955 0.166336 0.163153 0.16 0.156878 0.153787
+0.150727 0.147697 0.144698 0.14173 0.138793 0.135886 0.13301 0.130165
+0.127351 0.124567 0.121815 0.119093 0.116401 0.113741 0.111111 0.108512
+0.105944 0.103406 0.1009 0.0984237 0.0959785 0.093564 0.0911803 0.0888274
+0.0865052 0.0842138 0.0819531 0.0797232 0.077524 0.0753556 0.073218
+0.0711111 0.069035 0.0669896 0.064975 0.0629911 0.0610381 0.0591157
+0.0572241 0.0553633 0.0535332 0.0517339 0.0499654 0.0482276 0.0465206
+0.0448443 0.0431988 0.041584 0.04 0.0384467 0.0369243 0.0354325 0.0339715
+0.0325413 0.0311419 0.0297732 0.0284352 0.027128 0.0258516 0.0246059
+0.023391 0.0222068 0.0210534 0.0199308 0.0188389 0.0177778 0.0167474
+0.0157478 0.0147789 0.0138408 0.0129335 0.0120569 0.0112111 0.010396
+0.00961169 0.00885813 0.00813533 0.00744329 0.00678201 0.00615148 0.00555171
+0.0049827 0.00444444 0.00393695 0.00346021 0.00301423 0.002599 0.00221453
+0.00186082 0.00153787 0.00124567 0.000984237 0.000753556 0.000553633
+0.000384467 0.000246059 0.000138408 6.15148e-05 1.53787e-05 0;
+#X coords 0 1 512 0 512 64 1 0 0;
+#X restore 24 536 graph;
+#X text 244 55 centre signal around zero and take abs value;
+#X text 243 107 if greater than threshold output 1;
+#X text 313 129 differentiator;
+#X text 238 150 (generates impulse on positive trigger (0->1);
+#X text 67 210 signal-rate counter;
+#X text 296 193 -> resets counter by briefly setting;
+#X text 314 204 rpole~ coeff to 0;
+#X text 96 416 kickdrum 101 :P;
+#X text 400 514 pre-generated envelope;
+#X obj 262 249 *~;
+#X text 127 352 << use envelope value for volume and frequency;
+#X connect 0 0 4 0;
+#X connect 1 0 5 0;
+#X connect 2 0 1 1;
+#X connect 3 0 2 0;
+#X connect 4 0 11 0;
+#X connect 5 0 13 0;
+#X connect 6 0 1 0;
+#X connect 7 0 8 1;
+#X connect 8 0 5 1;
+#X connect 10 0 28 0;
+#X connect 11 0 8 0;
+#X connect 12 0 14 0;
+#X connect 13 0 15 0;
+#X connect 14 0 10 0;
+#X connect 14 0 25 0;
+#X connect 14 0 25 1;
+#X connect 15 0 12 0;
+#X connect 16 0 0 0;
+#X connect 17 0 16 0;
+#X connect 18 0 17 0;
+#X connect 19 0 20 0;
+#X connect 20 0 15 1;
+#X connect 21 0 0 1;
+#X connect 22 0 39 0;
+#X connect 22 0 39 1;
+#X connect 23 0 10 1;
+#X connect 24 0 23 0;
+#X connect 25 0 26 0;
+#X connect 26 0 24 0;
+#X connect 27 0 20 1;
+#X connect 39 0 27 0;
+#X restore 28 174 pd env;
+#X obj 79 110 adc~ 9;
+#X obj 129 130 adc~ 10;
+#X text 72 90 piezo input for excitation;
+#X text 123 110 fader 1 sets threshold;
+#X text 183 130 fader 2 sets duration;
+#X text 29 17 SAMPLE-ACCURATE ENVELOPE TRIGGER;
+#X text 29 27 ================================;
+#X obj 28 90 adc~ 8;
+#X text 141 236 ---------------------------------;
+#X text 141 226 @krighxz / BELA / heavy / 12/2015;
+#X text 165 245 beaglert.cc / enzienaudio.com;
+#X connect 1 0 0 0;
+#X connect 1 0 0 1;
+#X connect 2 0 1 1;
+#X connect 3 0 1 2;
+#X connect 9 0 1 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/hello-midi/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,81 @@
+#N canvas 85 58 1280 685 10;
+#X obj 19 396 dac~ 1 2;
+#X text 39 1 Hello world!;
+#X text 37 11 ============;
+#X obj 31 353 *~ 0.1;
+#X text 202 448 ---------------------------------;
+#X text 202 438 @krighxz / BELA / heavy / 12/2015;
+#X text 226 457 beaglert.cc / enzienaudio.com;
+#X obj 39 132 mtof;
+#X floatatom 79 59 5 0 0 0 - - -, f 5;
+#X floatatom 122 59 5 0 0 0 - - -, f 5;
+#X floatatom 41 63 5 0 0 0 - - -, f 5;
+#X obj 26 170 phasor~ 440;
+#X text 100 363 (the harsh sound of success);
+#X obj 260 83 * 20;
+#X obj 261 112 + 200;
+#X obj 132 85 loadbang;
+#X msg 131 111 1000;
+#X obj 125 166 sig~;
+#X text 673 121 [pgmin];
+#X obj 218 178 * 10;
+#X obj 30 250 hip~;
+#X obj 26 275 hip~;
+#X obj 20 302 hip~;
+#X obj 19 323 hip~;
+#X obj 87 192 lop~ 4;
+#X obj 152 256 line;
+#X obj 200 200 + 50;
+#X msg 170 227 \$1 200;
+#X msg 93 114 0;
+#X msg 185 112 0;
+#X obj 29 224 vcf~ 4;
+#X obj 70 333 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 42 92 mono;
+#X obj 40 28 bela_notein 0;
+#X obj 260 60 bela_ctlin 5 0;
+#X obj 220 151 bela_ctlin 6 0;
+#X text 537 58 [ctlin];
+#X text 332 27 [notein];
+#X text 140 29 <== the bela equivalent of ==>;
+#X text 349 59 <== the bela equivalent of ==>;
+#X text 483 121 <== the bela equivalent of ==>;
+#X obj 405 175 print pgmin;
+#X obj 408 121 bela_pgmin 0;
+#X connect 3 0 0 1;
+#X connect 3 0 0 0;
+#X connect 7 0 11 0;
+#X connect 8 0 32 1;
+#X connect 10 0 32 0;
+#X connect 11 0 30 0;
+#X connect 13 0 14 0;
+#X connect 14 0 17 0;
+#X connect 15 0 16 0;
+#X connect 15 0 29 0;
+#X connect 15 0 28 0;
+#X connect 16 0 17 0;
+#X connect 17 0 24 0;
+#X connect 19 0 26 0;
+#X connect 20 0 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 3 0;
+#X connect 24 0 30 1;
+#X connect 25 0 20 1;
+#X connect 25 0 21 1;
+#X connect 25 0 22 1;
+#X connect 25 0 23 1;
+#X connect 26 0 27 0;
+#X connect 27 0 25 0;
+#X connect 29 0 19 0;
+#X connect 30 0 20 0;
+#X connect 31 0 3 1;
+#X connect 32 0 7 0;
+#X connect 32 1 31 0;
+#X connect 33 0 10 0;
+#X connect 33 1 8 0;
+#X connect 33 2 9 0;
+#X connect 34 0 13 0;
+#X connect 35 0 19 0;
+#X connect 42 0 41 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/hello-midi/countTo.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,33 @@
+#N canvas 584 255 450 300 10;
+#X obj 65 196 outlet;
+#X obj 98 8 inlet;
+#X text 189 49 counts from 0 to the given number -1;
+#X text 214 95 inlet:N;
+#X text 212 112 outlet: 0 \, 1 \, 2 \, ... \, N-1;
+#X obj 143 61 f;
+#X obj 100 138 spigot;
+#X obj 129 89 <;
+#X obj 129 113 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 95 28 t b f b;
+#X obj 92 74 + 1;
+#X obj 43 73 f;
+#X obj 63 104 t b f f f;
+#X msg 92 53 0;
+#X obj 16 144 delay 0;
+#X connect 1 0 9 0;
+#X connect 5 0 7 1;
+#X connect 6 0 11 0;
+#X connect 7 0 8 0;
+#X connect 8 0 6 1;
+#X connect 9 0 11 0;
+#X connect 9 1 5 0;
+#X connect 9 1 13 0;
+#X connect 10 0 11 1;
+#X connect 11 0 12 0;
+#X connect 12 0 14 0;
+#X connect 12 1 0 0;
+#X connect 12 2 7 0;
+#X connect 12 3 10 0;
+#X connect 13 0 11 1;
+#X connect 14 0 6 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/hello-midi/maxArray.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,67 @@
+#N canvas 464 23 1002 583 10;
+#X obj 224 202 max;
+#X obj 265 200 f;
+#X obj 223 229 change;
+#X obj 223 251 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 223 271 f;
+#X obj 259 323 f;
+#X obj 187 315 f;
+#X obj 268 282 t b b;
+#X obj 183 364 outlet;
+#X obj 269 379 outlet;
+#X obj 179 17 inlet;
+#X obj 225 177 tabread \$1;
+#X obj 230 88 t f f b;
+#X text 376 37 Finds a maximum value in an array;
+#X text 531 112 \$2 arrayLength;
+#X obj 292 10 inlet;
+#X text 425 146 inlets:;
+#X text 473 144 1 bang to find the maximum;
+#X text 475 157 2 arrayLength;
+#X text 407 90 creation arguments: \$1 arrayName;
+#X obj 246 38 \$2;
+#X obj 202 40 bang;
+#X obj 230 65 f;
+#X obj 224 6 loadbang;
+#X text 444 216 outlets: 1 maximum value;
+#X text 498 231 2 index of the maximum value;
+#X msg 276 141 -1e+15;
+#X obj 222 142 t f f f;
+#X floatatom 158 266 5 0 0 0 - - -, f 5;
+#X obj 332 302 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 288 253 select 127;
+#X floatatom 301 324 5 0 0 0 - - -, f 5;
+#X text 362 256 heavy does not support the second inlet of select so
+I have to hard code 127 in here;
+#X obj 223 110 countTo;
+#X connect 0 0 1 0;
+#X connect 0 0 2 0;
+#X connect 0 0 6 1;
+#X connect 0 0 28 0;
+#X connect 1 0 0 1;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 1;
+#X connect 4 0 31 0;
+#X connect 5 0 9 0;
+#X connect 6 0 8 0;
+#X connect 7 0 6 0;
+#X connect 7 1 5 0;
+#X connect 10 0 21 0;
+#X connect 11 0 0 0;
+#X connect 12 0 33 0;
+#X connect 12 2 26 0;
+#X connect 15 0 22 1;
+#X connect 20 0 22 1;
+#X connect 21 0 22 0;
+#X connect 22 0 12 0;
+#X connect 23 0 20 0;
+#X connect 26 0 0 1;
+#X connect 27 0 30 0;
+#X connect 27 1 11 0;
+#X connect 27 2 4 1;
+#X connect 30 0 7 0;
+#X connect 30 0 29 0;
+#X connect 33 0 27 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/hello-midi/mono.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,106 @@
+#N canvas 69 182 1020 452 10;
+#N canvas 0 23 450 278 (subpatch) 0;
+#X array \$0-activeNotes 127 float 2;
+#X coords 0 100 127 -1 200 140 1 0 0;
+#X restore 537 25 graph;
+#N canvas 89 91 450 300 resetArray 1;
+#X obj 121 145 tabwrite \$0-activeNotes;
+#X msg 123 115 -0.5;
+#X obj 154 90 t b f;
+#X msg 129 45 128;
+#X obj 103 14 inlet;
+#X text 212 71 countto;
+#X obj 153 69 countTo;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
+#X connect 2 1 0 1;
+#X connect 3 0 6 0;
+#X connect 4 0 3 0;
+#X connect 6 0 2 0;
+#X restore 83 49 pd resetArray;
+#X obj 83 3 loadbang;
+#X obj 88 25 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 39 188 maxArray \$0-activeNotes 128;
+#X obj 183 219 f;
+#X obj 39 237 >= 0;
+#X floatatom 148 313 5 0 0 0 - - -, f 5;
+#X obj 70 262 select 1;
+#X obj 366 87 f;
+#X obj 426 60 f;
+#X text 334 39 note;
+#X text 424 16 velocity;
+#X obj 423 87 > 0;
+#X obj 344 281 tabwrite \$0-activeNotes;
+#X obj 330 207 f;
+#X floatatom 303 178 5 0 0 0 - - -, f 5;
+#X obj 265 163 f;
+#X obj 304 150 + 1;
+#X msg 277 130 -1;
+#X msg 371 207 -0.5;
+#X obj 400 116 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 367 137 spigot;
+#X obj 447 134 spigot;
+#X obj 460 86 == 0;
+#X obj 470 109 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 434 163 t b f;
+#X obj 337 60 inlet;
+#X obj 426 32 inlet;
+#X obj 148 350 outlet;
+#X obj 275 89 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 41 163 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 363 172 t b f;
+#X obj 334 240 t b f;
+#X text 578 211 pass in velocity/note pairs (velocity first) and obtain
+as an output the most recent note still active;
+#X text 581 268 outlet 2 gate;
+#X obj 330 366 outlet;
+#X text 583 251 outlet 1 most recent note active (-1 otherwise);
+#X text 155 329 most recent note active;
+#X msg 338 338 0;
+#X msg 378 339 1;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 3 0 19 0;
+#X connect 4 0 6 0;
+#X connect 4 1 5 1;
+#X connect 5 0 7 0;
+#X connect 5 0 40 0;
+#X connect 6 0 8 0;
+#X connect 7 0 29 0;
+#X connect 8 0 5 0;
+#X connect 8 1 39 0;
+#X connect 9 0 22 0;
+#X connect 9 0 23 0;
+#X connect 10 0 13 0;
+#X connect 10 0 24 0;
+#X connect 13 0 21 0;
+#X connect 15 0 33 0;
+#X connect 16 0 15 1;
+#X connect 17 0 18 0;
+#X connect 18 0 16 0;
+#X connect 18 0 17 1;
+#X connect 19 0 17 1;
+#X connect 20 0 33 0;
+#X connect 21 0 22 1;
+#X connect 22 0 32 0;
+#X connect 23 0 26 0;
+#X connect 24 0 25 0;
+#X connect 25 0 23 1;
+#X connect 26 0 20 0;
+#X connect 26 1 14 1;
+#X connect 27 0 9 0;
+#X connect 28 0 10 0;
+#X connect 28 0 30 0;
+#X connect 30 0 17 0;
+#X connect 31 0 4 0;
+#X connect 32 0 15 0;
+#X connect 32 1 14 1;
+#X connect 33 0 31 0;
+#X connect 33 1 14 0;
+#X connect 39 0 36 0;
+#X connect 40 0 36 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/hello-world/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,13 @@
+#N canvas 275 573 461 212 10;
+#X obj 39 143 dac~ 1 2;
+#X text 35 32 Hello world!;
+#X text 35 42 ============;
+#X text 95 79 (the sweet sound of success);
+#X obj 39 102 *~ 0.1;
+#X obj 39 81 osc~ 440;
+#X text 238 160 ---------------------------------;
+#X text 238 150 @krighxz / BELA / heavy / 12/2015;
+#X text 262 169 beaglert.cc / enzienaudio.com;
+#X connect 4 0 0 1;
+#X connect 4 0 0 0;
+#X connect 5 0 4 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/karplusStrong/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,240 @@
+#N canvas 440 516 715 490 10;
+#X obj 38 370 dac~ 1 2;
+#X text 470 442 ---------------------------------;
+#X text 470 432 @krighxz / BELA / heavy / 12/2015;
+#X text 494 451 beaglert.cc / enzienaudio.com;
+#X text 33 22 Karplus Strong;
+#X text 33 32 ==============;
+#X obj 38 323 vd~ \$0-wg1;
+#X obj 118 345 lop~ 1000;
+#X obj 118 367 *~ 0.99;
+#X obj 118 389 s~ \$0-fb1;
+#X obj 38 94 adc~ 3;
+#X obj 38 116 hip~ 100;
+#X obj 98 176 r~ \$0-fb1;
+#X obj 38 198 delwrite~ \$0-wg1 100;
+#X obj 38 268 *~;
+#X obj 38 290 *~ 10;
+#X text 99 116 <<< centre (i.e. DC block) signal with high-pass filter
+;
+#X text 100 94 <<< use accelerometer \, piezo or FSR on first analog
+in;
+#X text 105 245 <<< use potentiometer or fader on second analog in
+;
+#X text 100 75 EXCITATION INPUT:;
+#X text 100 225 DELAY PERIOD:;
+#X text 182 365 <<< and decay here [0-0.9999];
+#X text 182 345 <<< set damping here [~100-20000];
+#N canvas 335 566 461 274 gate 0;
+#N canvas 0 22 450 278 (subpatch) 0;
+#X array \$0-xfer 1024 float 3;
+#A 0 0 -0.808242 -0.804734 -0.801234 -0.797741 -0.794256 -0.790778
+-0.787309 -0.783846 -0.780392 -0.776945 -0.773506 -0.770074 -0.76665
+-0.763233 -0.759824 -0.756423 -0.75303 -0.749644 -0.746266 -0.742895
+-0.739532 -0.736176 -0.732829 -0.729488 -0.726156 -0.722831 -0.719514
+-0.716204 -0.712902 -0.709608 -0.706321 -0.703042 -0.69977 -0.696507
+-0.69325 -0.690002 -0.686761 -0.683527 -0.680302 -0.677084 -0.673873
+-0.67067 -0.667475 -0.664288 -0.661108 -0.657935 -0.654771 -0.651614
+-0.648464 -0.645323 -0.642188 -0.639062 -0.635943 -0.632832 -0.629728
+-0.626632 -0.623544 -0.620463 -0.61739 -0.614324 -0.611266 -0.608216
+-0.605174 -0.602139 -0.599111 -0.596092 -0.59308 -0.590075 -0.587078
+-0.584089 -0.581107 -0.578134 -0.575167 -0.572209 -0.569257 -0.566314
+-0.563378 -0.56045 -0.55753 -0.554617 -0.551711 -0.548814 -0.545924
+-0.543041 -0.540167 -0.537299 -0.53444 -0.531588 -0.528744 -0.525907
+-0.523078 -0.520257 -0.517443 -0.514637 -0.511839 -0.509048 -0.506265
+-0.503489 -0.500721 -0.497961 -0.495208 -0.492463 -0.489726 -0.486996
+-0.484274 -0.481559 -0.478852 -0.476153 -0.473461 -0.470777 -0.468101
+-0.465432 -0.462771 -0.460117 -0.457472 -0.454833 -0.452203 -0.44958
+-0.446964 -0.444357 -0.441757 -0.439164 -0.436579 -0.434002 -0.431432
+-0.42887 -0.426316 -0.42377 -0.42123 -0.418699 -0.416175 -0.413659
+-0.41115 -0.40865 -0.406156 -0.403671 -0.401193 -0.398722 -0.396259
+-0.393804 -0.391357 -0.388917 -0.386485 -0.38406 -0.381643 -0.379234
+-0.376832 -0.374438 -0.372051 -0.369673 -0.367301 -0.364938 -0.362582
+-0.360233 -0.357893 -0.35556 -0.353234 -0.350916 -0.348606 -0.346304
+-0.344009 -0.341721 -0.339442 -0.33717 -0.334905 -0.332649 -0.330399
+-0.328158 -0.325924 -0.323698 -0.321479 -0.319268 -0.317065 -0.314869
+-0.312681 -0.3105 -0.308328 -0.306162 -0.304005 -0.301855 -0.299713
+-0.297578 -0.295451 -0.293331 -0.291219 -0.289115 -0.287019 -0.28493
+-0.282848 -0.280775 -0.278709 -0.27665 -0.2746 -0.272556 -0.270521
+-0.268493 -0.266473 -0.26446 -0.262455 -0.260458 -0.258468 -0.256486
+-0.254511 -0.252545 -0.250585 -0.248634 -0.24669 -0.244753 -0.242825
+-0.240904 -0.23899 -0.237084 -0.235186 -0.233296 -0.231413 -0.229537
+-0.22767 -0.22581 -0.223957 -0.222112 -0.220275 -0.218446 -0.216624
+-0.21481 -0.213003 -0.211204 -0.209413 -0.207629 -0.205853 -0.204084
+-0.202323 -0.20057 -0.198824 -0.197086 -0.195356 -0.193633 -0.191918
+-0.190211 -0.188511 -0.186819 -0.185134 -0.183457 -0.181788 -0.180126
+-0.178472 -0.176826 -0.175187 -0.173556 -0.171932 -0.170316 -0.168708
+-0.167108 -0.165515 -0.163929 -0.162351 -0.160781 -0.159219 -0.157664
+-0.156117 -0.154577 -0.153045 -0.151521 -0.150004 -0.148495 -0.146993
+-0.1455 -0.144013 -0.142535 -0.141064 -0.139601 -0.138145 -0.136697
+-0.135256 -0.133824 -0.132398 -0.130981 -0.129571 -0.128169 -0.126774
+-0.125387 -0.124008 -0.122636 -0.121272 -0.119915 -0.118566 -0.117225
+-0.115891 -0.114565 -0.113247 -0.111936 -0.110633 -0.109338 -0.10805
+-0.10677 -0.105497 -0.104232 -0.102975 -0.101725 -0.100483 -0.0992487
+-0.0980219 -0.0968027 -0.0955911 -0.0943872 -0.0931909 -0.0920023 -0.0908212
+-0.0896478 -0.0884821 -0.0873239 -0.0861734 -0.0850305 -0.0838953 -0.0827676
+-0.0816476 -0.0805353 -0.0794305 -0.0783334 -0.077244 -0.0761621 -0.0750879
+-0.0740213 -0.0729623 -0.071911 -0.0708673 -0.0698312 -0.0688028 -0.067782
+-0.0667688 -0.0657632 -0.0647653 -0.063775 -0.0627924 -0.0618173 -0.0608499
+-0.0598901 -0.058938 -0.0579935 -0.0570566 -0.0561273 -0.0552057 -0.0542917
+-0.0533853 -0.0524866 -0.0515955 -0.050712 -0.0498361 -0.0489679 -0.0481073
+-0.0472543 -0.046409 -0.0455713 -0.0447412 -0.0439188 -0.0431039 -0.0422968
+-0.0414972 -0.0407053 -0.039921 -0.0391443 -0.0383752 -0.0376138 -0.03686
+-0.0361139 -0.0353754 -0.0346445 -0.0339212 -0.0332056 -0.0324976 -0.0317972
+-0.0311044 -0.0304193 -0.0297418 -0.029072 -0.0284097 -0.0277551 -0.0271082
+-0.0264688 -0.0258371 -0.025213 -0.0245966 -0.0239877 -0.0233865 -0.022793
+-0.022207 -0.0216287 -0.021058 -0.020495 -0.0199396 -0.0193918 -0.0188516
+-0.0183191 -0.0177942 -0.0172769 -0.0167673 -0.0162653 -0.0157709 -0.0152841
+-0.014805 -0.0143335 -0.0138696 -0.0134134 -0.0129648 -0.0125238 -0.0120905
+-0.0116647 -0.0112466 -0.0108362 -0.0104333 -0.0100381 -0.00965057
+-0.00927063 -0.00889832 -0.00853363 -0.00817657 -0.00782715 -0.00748535
+-0.00715118 -0.00682465 -0.00650574 -0.00619446 -0.00589081 -0.00559479
+-0.0053064 -0.00502563 -0.0047525 -0.004487 -0.00422913 -0.00397888
+-0.00373627 -0.00350128 -0.00327393 -0.0030542 -0.0028421 -0.00263763
+-0.0024408 -0.00225159 -0.00207001 -0.00189606 -0.00172974 -0.00157104
+-0.00141998 -0.00127655 -0.00114075 -0.00101257 -0.000892029 -0.000779114
+-0.000673828 -0.000576172 -0.000486145 -0.000403747 -0.000328979 -0.000261841
+-0.000202332 -0.000150452 -0.000106201 -6.95801e-05 -4.05884e-05 -1.92261e-05
+-5.49316e-06 0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0
+-0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0
+-0 -0 -0 -0 -0 -0 -0 -0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5.49316e-06
+1.92261e-05 4.05884e-05 6.95801e-05 0.000106201 0.000150452 0.000202332
+0.000261841 0.000328979 0.000403747 0.000486145 0.000576172 0.000673828
+0.000779114 0.000892029 0.00101257 0.00114075 0.00127655 0.00141998
+0.00157104 0.00172974 0.00189606 0.00207001 0.00225159 0.0024408 0.00263763
+0.0028421 0.0030542 0.00327393 0.00350128 0.00373627 0.00397888 0.00422913
+0.004487 0.0047525 0.00502563 0.0053064 0.00559479 0.00589081 0.00619446
+0.00650574 0.00682465 0.00715118 0.00748535 0.00782715 0.00817657 0.00853363
+0.00889832 0.00927063 0.00965057 0.0100381 0.0104333 0.0108362 0.0112466
+0.0116647 0.0120905 0.0125238 0.0129648 0.0134134 0.0138696 0.0143335
+0.014805 0.0152841 0.0157709 0.0162653 0.0167673 0.0172769 0.0177942
+0.0183191 0.0188516 0.0193918 0.0199396 0.020495 0.021058 0.0216287
+0.022207 0.022793 0.0233865 0.0239877 0.0245966 0.025213 0.0258371
+0.0264688 0.0271082 0.0277551 0.0284097 0.029072 0.0297418 0.0304193
+0.0311044 0.0317972 0.0324976 0.0332056 0.0339212 0.0346445 0.0353754
+0.0361139 0.03686 0.0376138 0.0383752 0.0391443 0.039921 0.0407053
+0.0414972 0.0422968 0.0431039 0.0439188 0.0447412 0.0455713 0.046409
+0.0472543 0.0481073 0.0489679 0.0498361 0.050712 0.0515955 0.0524866
+0.0533853 0.0542917 0.0552057 0.0561273 0.0570566 0.0579935 0.058938
+0.0598901 0.0608499 0.0618173 0.0627924 0.063775 0.0647653 0.0657632
+0.0667688 0.067782 0.0688028 0.0698312 0.0708673 0.071911 0.0729623
+0.0740213 0.0750879 0.0761621 0.077244 0.0783334 0.0794305 0.0805353
+0.0816476 0.0827676 0.0838953 0.0850305 0.0861734 0.0873239 0.0884821
+0.0896478 0.0908212 0.0920023 0.0931909 0.0943872 0.0955911 0.0968027
+0.0980219 0.0992487 0.100483 0.101725 0.102975 0.104232 0.105497 0.10677
+0.10805 0.109338 0.110633 0.111936 0.113247 0.114565 0.115891 0.117225
+0.118566 0.119915 0.121272 0.122636 0.124008 0.125387 0.126774 0.128169
+0.129571 0.130981 0.132398 0.133824 0.135256 0.136697 0.138145 0.139601
+0.141064 0.142535 0.144013 0.1455 0.146993 0.148495 0.150004 0.151521
+0.153045 0.154577 0.156117 0.157664 0.159219 0.160781 0.162351 0.163929
+0.165515 0.167108 0.168708 0.170316 0.171932 0.173556 0.175187 0.176826
+0.178472 0.180126 0.181788 0.183457 0.185134 0.186819 0.188511 0.190211
+0.191918 0.193633 0.195356 0.197086 0.198824 0.20057 0.202323 0.204084
+0.205853 0.207629 0.209413 0.211204 0.213003 0.21481 0.216624 0.218446
+0.220275 0.222112 0.223957 0.22581 0.22767 0.229537 0.231413 0.233296
+0.235186 0.237084 0.23899 0.240904 0.242825 0.244753 0.24669 0.248634
+0.250585 0.252545 0.254511 0.256486 0.258468 0.260458 0.262455 0.26446
+0.266473 0.268493 0.270521 0.272556 0.2746 0.27665 0.278709 0.280775
+0.282848 0.28493 0.287019 0.289115 0.291219 0.293331 0.295451 0.297578
+0.299713 0.301855 0.304005 0.306162 0.308328 0.3105 0.312681 0.314869
+0.317065 0.319268 0.321479 0.323698 0.325924 0.328158 0.330399 0.332649
+0.334905 0.33717 0.339442 0.341721 0.344009 0.346304 0.348606 0.350916
+0.353234 0.35556 0.357893 0.360233 0.362582 0.364938 0.367301 0.369673
+0.372051 0.374438 0.376832 0.379234 0.381643 0.38406 0.386485 0.388917
+0.391357 0.393804 0.396259 0.398722 0.401193 0.403671 0.406156 0.40865
+0.41115 0.413659 0.416175 0.418699 0.42123 0.42377 0.426316 0.42887
+0.431432 0.434002 0.436579 0.439164 0.441757 0.444357 0.446964 0.44958
+0.452203 0.454833 0.457472 0.460117 0.462771 0.465432 0.468101 0.470777
+0.473461 0.476153 0.478852 0.481559 0.484274 0.486996 0.489726 0.492463
+0.495208 0.497961 0.500721 0.503489 0.506265 0.509048 0.511839 0.514637
+0.517443 0.520257 0.523078 0.525907 0.528744 0.531588 0.53444 0.537299
+0.540167 0.543041 0.545924 0.548814 0.551711 0.554617 0.55753 0.56045
+0.563378 0.566314 0.569257 0.572209 0.575167 0.578134 0.581107 0.584089
+0.587078 0.590075 0.59308 0.596092 0.599111 0.602139 0.605174 0.608216
+0.611266 0.614324 0.61739 0.620463 0.623544 0.626632 0.629728 0.632832
+0.635943 0.639062 0.642188 0.645323 0.648464 0.651614 0.654771 0.657935
+0.661108 0.664288 0.667475 0.67067 0.673873 0.677084 0.680302 0.683527
+0.686761 0.690002 0.69325 0.696507 0.69977 0.703042 0.706321 0.709608
+0.712902 0.716204 0.719514 0.722831;
+#A 1000 0.726156 0.729488 0.732829 0.736176 0.739532 0.742895 0.746266
+0.749644 0.75303 0.756423 0.759824 0.763233 0.76665 0.770074 0.773506
+0.776945 0.780392 0.783846 0.787309 0.790778 0.794256 0.797741 0.801234
+0.804734;
+#X coords 0 1 1023 -1 200 200 1 0 0;
+#X restore 230 34 graph;
+#X obj 25 27 inlet~;
+#X obj 25 49 clip~ -1 1;
+#X obj 25 71 *~ 512;
+#X obj 25 93 +~ 512;
+#X obj 25 115 tabread4~ \$0-xfer;
+#X obj 25 137 outlet~;
+#N canvas 0 22 334 332 generate-xfer 0;
+#X obj 8 290 tabwrite \$0-xfer;
+#X obj 8 109 / 1024;
+#X obj 8 129 * 2;
+#X obj 8 149 - 1;
+#X obj 8 169 moses 0;
+#X obj 8 191 + 0.1;
+#X obj 8 213 clip -1 0;
+#X obj 68 191 - 0.1;
+#X obj 68 213 clip 0 1;
+#X obj 101 16 inlet threshold;
+#X obj 101 78 count 1024;
+#X obj 128 58 s \$0-thresh;
+#X obj 95 169 r \$0-thresh;
+#X obj 101 38 t b f;
+#X obj 68 236 *;
+#X obj 8 236 *;
+#X obj 8 258 * -1;
+#X text 140 203 <<< deadzone;
+#X text 140 253 <<< smooth by taking exponent;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 4 1 7 0;
+#X connect 5 0 6 0;
+#X connect 6 0 15 0;
+#X connect 6 0 15 1;
+#X connect 7 0 8 0;
+#X connect 8 0 14 0;
+#X connect 8 0 14 1;
+#X connect 9 0 13 0;
+#X connect 10 0 0 1;
+#X connect 10 0 1 0;
+#X connect 12 0 5 1;
+#X connect 12 0 7 1;
+#X connect 13 0 10 0;
+#X connect 13 1 11 0;
+#X connect 14 0 0 0;
+#X connect 15 0 16 0;
+#X connect 16 0 0 0;
+#X restore 26 217 pd generate-xfer;
+#X text 58 196 <<< threshold;
+#X obj 26 173 loadbang;
+#X msg 26 195 0.1;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 6 0;
+#X connect 9 0 10 0;
+#X connect 10 0 7 0;
+#X restore 38 137 pd gate;
+#X obj 38 246 adc~ 10;
+#X text 98 137 <<< thresholding to remove any consistent noise in the
+excitation signal;
+#X connect 6 0 7 0;
+#X connect 6 0 0 0;
+#X connect 6 0 0 1;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 10 0 11 0;
+#X connect 11 0 23 0;
+#X connect 12 0 13 0;
+#X connect 14 0 15 0;
+#X connect 15 0 6 0;
+#X connect 23 0 13 0;
+#X connect 24 0 14 0;
+#X connect 24 0 14 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/karplusStrong/count.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,30 @@
+#N canvas 592 177 306 227 10;
+#X obj 32 111 f;
+#X obj 57 111 + 1;
+#X obj 57 151 sel 0;
+#X obj 57 171 del 1e-36;
+#X obj 57 131 > 1023;
+#X msg 32 90 0;
+#X obj 19 171 - 1;
+#X obj 19 193 outlet;
+#X obj 90 87 \$1;
+#X obj 90 109 - 1;
+#X obj 90 66 loadbang;
+#X obj 32 48 inlet;
+#X obj 32 69 t b;
+#X text 33 14 temporary replacement for [until] object;
+#X text 67 195 outputs index (0->[N-1]);
+#X connect 0 0 1 0;
+#X connect 1 0 0 1;
+#X connect 1 0 4 0;
+#X connect 1 0 6 0;
+#X connect 2 0 3 0;
+#X connect 3 0 0 0;
+#X connect 4 0 2 0;
+#X connect 5 0 0 0;
+#X connect 6 0 7 0;
+#X connect 8 0 9 0;
+#X connect 9 0 4 1;
+#X connect 10 0 8 0;
+#X connect 11 0 12 0;
+#X connect 12 0 5 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,186 @@
+#N canvas 8 23 1272 752 10;
+#X text 39 1 Hello world!;
+#X text 1003 636 ---------------------------------;
+#X text 1003 626 @krighxz / BELA / heavy / 12/2015;
+#X text 1027 645 beaglert.cc / enzienaudio.com;
+#X text 306 61 [pgmin];
+#X text 416 31 [ctlin];
+#X text 825 28 [notein];
+#X text 228 32 <== the bela equivalent of ==>;
+#X text 116 61 <== the bela equivalent of ==>;
+#X obj 740 28 bela_notein 0;
+#X obj 740 57 pack 0 0;
+#X obj 740 106 pack 0 0 0;
+#X obj 596 976 dac~ 1 2;
+#X obj 646 178 s voice-note-1;
+#X obj 736 178 s voice-note-2;
+#X obj 826 178 s voice-note-3;
+#X obj 916 178 s voice-note-4;
+#X obj 594 252 catch~ output;
+#X obj 541 57 voice 1;
+#X obj 1150 21 loadbang;
+#X obj 1150 43 metro 10;
+#X obj 1150 65 s metro;
+#X obj 944 336 * 1000;
+#X obj 1036 392 s Q;
+#X obj 944 381 s attack;
+#X obj 1036 336 * 8000;
+#X obj 1036 365 + 200;
+#X obj 1116 379 s~ wobble;
+#X obj 944 358 + 5;
+#X obj 1116 336 *~ 25;
+#X obj 629 334 r Q;
+#X obj 594 309 *~ 1;
+#X obj 981 565 clip~ 0 0.999;
+#X obj 836 610 *~;
+#X obj 740 128 route 1 2 3 4, f 36;
+#X obj 836 509 +~ 100;
+#X obj 836 485 *~ 1900;
+#X obj 624 651 delwrite~ ddd 2000;
+#X obj 740 84 poly 4 1;
+#X obj 664 729 *~ 0.5;
+#X obj 598 730 *~ 0.5;
+#X obj 597 757 hip~ 5;
+#X obj 624 558 hip~ 5;
+#X obj 624 580 hv_tanh;
+#X obj 836 667 hip~ 5;
+#X obj 836 689 hv_tanh;
+#X obj 836 566 delread~ ddd 500;
+#N canvas 0 22 178 130 snapshot 0;
+#X obj 24 20 inlet~;
+#X obj 24 62 snapshot~;
+#X obj 24 84 outlet;
+#X obj 86 29 r metro;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 3 0 1 0;
+#X restore 846 538 pd snapshot;
+#X obj 78 173 bela_ctlin 1 0;
+#X obj 159 203 s c1;
+#X obj 41 61 bela_pgmin 0;
+#X obj 78 233 bela_ctlin 2 0;
+#X obj 159 263 s c2;
+#X obj 78 293 bela_ctlin 3 0;
+#X obj 159 323 s c3;
+#X obj 78 353 bela_ctlin 4 0;
+#X obj 159 383 s c4;
+#X obj 498 731 r c1;
+#X obj 498 753 / 127;
+#X obj 943 311 / 127;
+#X obj 943 289 r c2;
+#X obj 1033 311 / 127;
+#X obj 1033 289 r c3;
+#X obj 1115 291 / 127;
+#X obj 1115 269 r c4;
+#X obj 1115 313 sig~;
+#X obj 78 413 bela_ctlin 5 0;
+#X obj 159 443 s c5;
+#X obj 78 473 bela_ctlin 6 0;
+#X obj 159 503 s c6;
+#X obj 828 407 / 127;
+#X obj 828 429 sig~;
+#X obj 828 385 r c5;
+#X obj 981 519 / 127;
+#X obj 981 541 sig~;
+#X obj 981 497 r c6;
+#X obj 593 389 *~ 0.5;
+#X obj 777 562 vd~ ddd;
+#X obj 597 784 hv_tanh;
+#X obj 597 818 *~;
+#X obj 593 360 lop~ 1000;
+#X obj 828 458 lop~ 10;
+#X obj 78 533 bela_ctlin 7 0;
+#X obj 159 563 s c7;
+#X obj 78 593 bela_ctlin 8 0;
+#X obj 159 623 s c8;
+#X obj 664 769 loadbang;
+#X msg 665 792 0.75;
+#X obj 1116 456 * 8000;
+#X obj 1116 485 + 200;
+#X obj 1113 431 / 127;
+#X obj 1113 409 r c7;
+#X obj 1116 512 s QP;
+#X obj 653 850 lop~ 8000;
+#X obj 1065 725 r c8;
+#X obj 689 824 r QP;
+#X obj 1065 750 / 127;
+#X obj 1065 772 s octVol;
+#X obj 541 77 voice 2;
+#X obj 541 97 voice 3;
+#X obj 541 117 voice 4;
+#X connect 9 0 10 0;
+#X connect 9 1 10 1;
+#X connect 10 0 38 0;
+#X connect 11 0 34 0;
+#X connect 17 0 31 0;
+#X connect 19 0 20 0;
+#X connect 20 0 21 0;
+#X connect 22 0 28 0;
+#X connect 25 0 26 0;
+#X connect 26 0 23 0;
+#X connect 28 0 24 0;
+#X connect 29 0 27 0;
+#X connect 30 0 80 1;
+#X connect 31 0 80 0;
+#X connect 32 0 33 1;
+#X connect 33 0 39 0;
+#X connect 33 0 44 0;
+#X connect 34 0 13 0;
+#X connect 34 1 14 0;
+#X connect 34 2 15 0;
+#X connect 34 3 16 0;
+#X connect 35 0 47 0;
+#X connect 35 0 77 0;
+#X connect 36 0 35 0;
+#X connect 38 0 11 0;
+#X connect 38 1 11 1;
+#X connect 38 2 11 2;
+#X connect 39 0 41 0;
+#X connect 40 0 41 0;
+#X connect 41 0 78 0;
+#X connect 42 0 43 0;
+#X connect 43 0 37 0;
+#X connect 44 0 45 0;
+#X connect 45 0 37 0;
+#X connect 47 0 46 0;
+#X connect 48 0 49 0;
+#X connect 51 0 52 0;
+#X connect 53 0 54 0;
+#X connect 55 0 56 0;
+#X connect 57 0 58 0;
+#X connect 58 0 79 1;
+#X connect 59 0 22 0;
+#X connect 60 0 59 0;
+#X connect 61 0 25 0;
+#X connect 62 0 61 0;
+#X connect 63 0 65 0;
+#X connect 64 0 63 0;
+#X connect 65 0 29 0;
+#X connect 66 0 67 0;
+#X connect 68 0 69 0;
+#X connect 70 0 71 0;
+#X connect 71 0 81 0;
+#X connect 72 0 70 0;
+#X connect 73 0 74 0;
+#X connect 74 0 32 0;
+#X connect 75 0 73 0;
+#X connect 76 0 40 0;
+#X connect 76 0 42 0;
+#X connect 77 0 33 0;
+#X connect 78 0 79 0;
+#X connect 79 0 93 0;
+#X connect 80 0 76 0;
+#X connect 81 0 36 0;
+#X connect 82 0 83 0;
+#X connect 84 0 85 0;
+#X connect 86 0 87 0;
+#X connect 87 0 79 1;
+#X connect 88 0 89 0;
+#X connect 89 0 92 0;
+#X connect 90 0 88 0;
+#X connect 91 0 90 0;
+#X connect 93 0 12 0;
+#X connect 93 0 12 1;
+#X connect 94 0 96 0;
+#X connect 95 0 93 1;
+#X connect 96 0 97 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/backmain.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,79 @@
+#N canvas 85 58 1280 685 10;
+#X obj 19 396 dac~ 1 2;
+#X text 39 1 Hello world!;
+#X text 37 11 ============;
+#X obj 31 353 *~ 0.1;
+#X text 202 448 ---------------------------------;
+#X text 202 438 @krighxz / BELA / heavy / 12/2015;
+#X text 226 457 beaglert.cc / enzienaudio.com;
+#X obj 39 132 mtof;
+#X floatatom 79 59 5 0 0 0 - - -, f 5;
+#X floatatom 122 59 5 0 0 0 - - -, f 5;
+#X floatatom 41 63 5 0 0 0 - - -, f 5;
+#X obj 26 170 phasor~ 440;
+#X text 100 363 (the harsh sound of success);
+#X obj 260 83 * 20;
+#X obj 261 112 + 200;
+#X obj 132 85 loadbang;
+#X msg 131 111 1000;
+#X obj 125 166 sig~;
+#X text 673 121 [pgmin];
+#X obj 218 178 * 10;
+#X obj 30 250 hip~;
+#X obj 26 275 hip~;
+#X obj 20 302 hip~;
+#X obj 19 323 hip~;
+#X obj 87 192 lop~ 4;
+#X obj 152 256 line;
+#X obj 200 200 + 50;
+#X msg 170 227 \$1 200;
+#X msg 93 114 0;
+#X msg 185 112 0;
+#X obj 29 224 vcf~ 4;
+#X obj 70 333 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 42 92 mono;
+#X obj 40 28 bela_notein 0;
+#X obj 260 60 bela_ctlin 5 0;
+#X obj 220 151 bela_ctlin 6 0;
+#X obj 408 121 bela_pgmin 3;
+#X text 537 58 [ctlin];
+#X text 332 27 [notein];
+#X text 140 29 <== the bela equivalent of ==>;
+#X text 349 59 <== the bela equivalent of ==>;
+#X text 483 121 <== the bela equivalent of ==>;
+#X connect 3 0 0 1;
+#X connect 3 0 0 0;
+#X connect 7 0 11 0;
+#X connect 8 0 32 1;
+#X connect 10 0 32 0;
+#X connect 11 0 30 0;
+#X connect 13 0 14 0;
+#X connect 14 0 17 0;
+#X connect 15 0 16 0;
+#X connect 15 0 29 0;
+#X connect 15 0 28 0;
+#X connect 16 0 17 0;
+#X connect 17 0 24 0;
+#X connect 19 0 26 0;
+#X connect 20 0 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 0;
+#X connect 23 0 3 0;
+#X connect 24 0 30 1;
+#X connect 25 0 20 1;
+#X connect 25 0 21 1;
+#X connect 25 0 22 1;
+#X connect 25 0 23 1;
+#X connect 26 0 27 0;
+#X connect 27 0 25 0;
+#X connect 29 0 19 0;
+#X connect 30 0 20 0;
+#X connect 31 0 3 1;
+#X connect 32 0 7 0;
+#X connect 32 1 31 0;
+#X connect 33 0 10 0;
+#X connect 33 1 8 0;
+#X connect 33 2 9 0;
+#X connect 34 0 13 0;
+#X connect 35 0 19 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/bela_ctlin.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,76 @@
+#N canvas 554 204 703 475 10;
+#X obj 53 431 outlet;
+#X obj 108 429 outlet;
+#X obj 99 127 r ctlin;
+#X obj 92 151 unpack f f f;
+#X obj 154 429 outlet;
+#X obj 86 322 spigot;
+#X text 51 450 value;
+#X text 105 450 number;
+#X obj 211 138 loadbang;
+#X obj 177 193 \$1;
+#X obj 126 214 == \$1;
+#X obj 119 299 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 84 349 unpack f f f;
+#X obj 143 247 ||;
+#X obj 177 217 == 0;
+#X text 70 11 Emulates ctlin \, except number of outlets is fixed.
+;
+#X obj 228 247 ||;
+#X obj 262 217 == 0;
+#X obj 212 214 == \$2;
+#X obj 262 193 \$2;
+#X obj 177 277 &&;
+#X obj 211 163 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X text 173 299 If (inputController==\$1 || \$1==0) && (inputChannel==\$2
+|| \$2==0);
+#X text 197 52 Known issue: trying to select inputController 0 will
+result i accepting all controllers (because a pd external cannot tell
+the difference between \$1 been explicitely set to 0 and the patch
+not having any argument);
+#X text 162 450 channel;
+#X obj 56 192 pack f f f;
+#X obj 80 408 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X floatatom 81 382 5 0 0 0 - - -, f 5;
+#X obj 121 412 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X floatatom 122 386 5 0 0 0 - - -, f 5;
+#X obj 172 406 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X floatatom 173 380 5 0 0 0 - - -, f 5;
+#X obj 122 92 s ctlin;
+#X obj 64 29 r bela_ctlin;
+#X connect 2 0 3 0;
+#X connect 3 0 25 0;
+#X connect 3 1 10 0;
+#X connect 3 1 25 1;
+#X connect 3 2 18 0;
+#X connect 3 2 25 2;
+#X connect 5 0 12 0;
+#X connect 8 0 21 0;
+#X connect 9 0 14 0;
+#X connect 10 0 13 0;
+#X connect 11 0 5 1;
+#X connect 12 0 0 0;
+#X connect 12 0 27 0;
+#X connect 12 1 1 0;
+#X connect 12 1 29 0;
+#X connect 12 2 4 0;
+#X connect 12 2 31 0;
+#X connect 13 0 20 0;
+#X connect 14 0 13 1;
+#X connect 16 0 20 1;
+#X connect 17 0 16 1;
+#X connect 18 0 16 0;
+#X connect 19 0 17 0;
+#X connect 20 0 11 0;
+#X connect 21 0 9 0;
+#X connect 21 0 19 0;
+#X connect 25 0 5 0;
+#X connect 27 0 26 0;
+#X connect 29 0 28 0;
+#X connect 31 0 30 0;
+#X connect 33 0 32 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/bela_notein.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,59 @@
+#N canvas 399 23 629 685 10;
+#X obj 94 481 outlet;
+#X obj 165 475 outlet;
+#X obj 141 184 unpack f f f;
+#X obj 221 472 outlet;
+#X obj 143 365 spigot;
+#X obj 268 181 loadbang;
+#X obj 234 236 \$1;
+#X obj 183 257 == \$1;
+#X obj 176 342 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 143 392 unpack f f f;
+#X obj 200 290 ||;
+#X obj 234 260 == 0;
+#X obj 268 206 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X text 160 65 Emulates notein \, except number of outlets is fixed.
+;
+#X text 92 499 notenumber;
+#X text 161 489 velocity;
+#X text 220 486 channel;
+#X text 229 311 If (inputChannel==\$1 || \$1==0);
+#X obj 115 232 pack f f f;
+#X obj 82 428 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X floatatom 84 410 5 0 0 0 - - -, f 5;
+#X obj 145 448 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X floatatom 147 430 5 0 0 0 - - -, f 5;
+#X obj 198 451 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X floatatom 200 433 5 0 0 0 - - -, f 5;
+#X obj 131 112 s notein;
+#X obj 140 149 r notein;
+#X obj 135 84 r bela_notein;
+#X connect 2 0 18 0;
+#X connect 2 1 18 1;
+#X connect 2 2 7 0;
+#X connect 2 2 18 2;
+#X connect 4 0 9 0;
+#X connect 5 0 12 0;
+#X connect 6 0 11 0;
+#X connect 7 0 10 0;
+#X connect 8 0 4 1;
+#X connect 9 0 0 0;
+#X connect 9 0 20 0;
+#X connect 9 1 1 0;
+#X connect 9 1 22 0;
+#X connect 9 2 3 0;
+#X connect 9 2 24 0;
+#X connect 10 0 8 0;
+#X connect 11 0 10 1;
+#X connect 12 0 6 0;
+#X connect 18 0 4 0;
+#X connect 20 0 19 0;
+#X connect 22 0 21 0;
+#X connect 24 0 23 0;
+#X connect 26 0 2 0;
+#X connect 27 0 25 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/bela_pgmin.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,53 @@
+#N canvas 623 197 587 546 10;
+#X obj 73 413 outlet;
+#X obj 174 411 outlet;
+#X obj 106 304 spigot;
+#X obj 197 126 loadbang;
+#X obj 197 175 \$1;
+#X obj 146 196 == \$1;
+#X obj 139 281 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 163 229 ||;
+#X obj 197 199 == 0;
+#X obj 197 151 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 89 111 unpack f f;
+#X obj 106 332 unpack f f;
+#X text 52 436 program number;
+#X text 182 432 channel;
+#X text 193 281 If (channel==\$1 || \$1==0);
+#X text 167 45 emulates pgmin except it always has 2 outlets and requires
+the input parameters to be explicitely set. Set them to 0 to avoid
+filtering;
+#X text 262 132 It'd be nicer with [t l l] but have to compensate for
+the fact that it is not supported by heavy;
+#X obj 77 183 pack f f;
+#X floatatom 72 355 5 0 0 0 - - -, f 5;
+#X obj 63 379 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X floatatom 150 361 5 0 0 0 - - -, f 5;
+#X obj 141 385 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 91 63 s pgmin;
+#X obj 93 87 r pgmin;
+#X obj 89 42 r bela_pgmin;
+#X connect 2 0 11 0;
+#X connect 3 0 9 0;
+#X connect 4 0 8 0;
+#X connect 5 0 7 0;
+#X connect 6 0 2 1;
+#X connect 7 0 6 0;
+#X connect 8 0 7 1;
+#X connect 9 0 4 0;
+#X connect 10 0 17 0;
+#X connect 10 1 5 0;
+#X connect 10 1 17 1;
+#X connect 11 0 0 0;
+#X connect 11 0 18 0;
+#X connect 11 1 1 0;
+#X connect 11 1 20 0;
+#X connect 17 0 2 0;
+#X connect 18 0 19 0;
+#X connect 20 0 21 0;
+#X connect 23 0 10 0;
+#X connect 24 0 22 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/countTo.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,33 @@
+#N canvas 584 255 450 300 10;
+#X obj 65 196 outlet;
+#X obj 98 8 inlet;
+#X text 189 49 counts from 0 to the given number -1;
+#X text 214 95 inlet:N;
+#X text 212 112 outlet: 0 \, 1 \, 2 \, ... \, N-1;
+#X obj 143 61 f;
+#X obj 100 138 spigot;
+#X obj 129 89 <;
+#X obj 129 113 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 95 28 t b f b;
+#X obj 92 74 + 1;
+#X obj 43 73 f;
+#X obj 63 104 t b f f f;
+#X msg 92 53 0;
+#X obj 16 144 delay 0;
+#X connect 1 0 9 0;
+#X connect 5 0 7 1;
+#X connect 6 0 11 0;
+#X connect 7 0 8 0;
+#X connect 8 0 6 1;
+#X connect 9 0 11 0;
+#X connect 9 1 5 0;
+#X connect 9 1 13 0;
+#X connect 10 0 11 1;
+#X connect 11 0 12 0;
+#X connect 12 0 14 0;
+#X connect 12 1 0 0;
+#X connect 12 2 7 0;
+#X connect 12 3 10 0;
+#X connect 13 0 11 1;
+#X connect 14 0 6 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/hv_tanh.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,27 @@
+#N canvas 254 82 445 331 10;
+#X obj 39 37 inlet~;
+#X obj 39 67 clip~ -3 3;
+#X obj 54 107 *~;
+#X obj 39 277 outlet~;
+#X obj 109 107 sig~ 27;
+#X obj 54 147 +~;
+#X obj 54 217 /~;
+#X obj 39 247 *~;
+#X obj 94 147 *~ 9;
+#X obj 94 187 +~;
+#X text 142 177 // http://www.musicdsp.org/showone.php?id=238;
+#X text 140 198 // y = x * (27 + x^2) / (27 + 9*x^2);
+#X text 144 152 // pade-approximation of tanh function;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 0 2 1;
+#X connect 1 0 7 0;
+#X connect 2 0 5 0;
+#X connect 2 0 8 0;
+#X connect 4 0 5 1;
+#X connect 4 0 9 1;
+#X connect 5 0 6 0;
+#X connect 6 0 7 1;
+#X connect 7 0 3 0;
+#X connect 8 0 9 0;
+#X connect 9 0 6 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/maxArray.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,67 @@
+#N canvas 464 23 1002 583 10;
+#X obj 224 202 max;
+#X obj 265 200 f;
+#X obj 223 229 change;
+#X obj 223 251 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 223 271 f;
+#X obj 259 323 f;
+#X obj 187 315 f;
+#X obj 268 282 t b b;
+#X obj 183 364 outlet;
+#X obj 269 379 outlet;
+#X obj 179 17 inlet;
+#X obj 225 177 tabread \$1;
+#X obj 230 88 t f f b;
+#X text 376 37 Finds a maximum value in an array;
+#X text 531 112 \$2 arrayLength;
+#X obj 292 10 inlet;
+#X text 425 146 inlets:;
+#X text 473 144 1 bang to find the maximum;
+#X text 475 157 2 arrayLength;
+#X text 407 90 creation arguments: \$1 arrayName;
+#X obj 246 38 \$2;
+#X obj 202 40 bang;
+#X obj 230 65 f;
+#X obj 224 6 loadbang;
+#X text 444 216 outlets: 1 maximum value;
+#X text 498 231 2 index of the maximum value;
+#X msg 276 141 -1e+15;
+#X obj 222 142 t f f f;
+#X floatatom 158 266 5 0 0 0 - - -, f 5;
+#X obj 332 302 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 288 253 select 127;
+#X floatatom 301 324 5 0 0 0 - - -, f 5;
+#X text 362 256 heavy does not support the second inlet of select so
+I have to hard code 127 in here;
+#X obj 223 110 countTo;
+#X connect 0 0 1 0;
+#X connect 0 0 2 0;
+#X connect 0 0 6 1;
+#X connect 0 0 28 0;
+#X connect 1 0 0 1;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 1;
+#X connect 4 0 31 0;
+#X connect 5 0 9 0;
+#X connect 6 0 8 0;
+#X connect 7 0 6 0;
+#X connect 7 1 5 0;
+#X connect 10 0 21 0;
+#X connect 11 0 0 0;
+#X connect 12 0 33 0;
+#X connect 12 2 26 0;
+#X connect 15 0 22 1;
+#X connect 20 0 22 1;
+#X connect 21 0 22 0;
+#X connect 22 0 12 0;
+#X connect 23 0 20 0;
+#X connect 26 0 0 1;
+#X connect 27 0 30 0;
+#X connect 27 1 11 0;
+#X connect 27 2 4 1;
+#X connect 30 0 7 0;
+#X connect 30 0 29 0;
+#X connect 33 0 27 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/mono.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,106 @@
+#N canvas 69 182 1020 452 10;
+#N canvas 0 23 450 278 (subpatch) 0;
+#X array \$0-activeNotes 127 float 2;
+#X coords 0 100 127 -1 200 140 1 0 0;
+#X restore 537 25 graph;
+#N canvas 89 91 450 300 resetArray 1;
+#X obj 121 145 tabwrite \$0-activeNotes;
+#X msg 123 115 -0.5;
+#X obj 154 90 t b f;
+#X msg 129 45 128;
+#X obj 103 14 inlet;
+#X text 212 71 countto;
+#X obj 153 69 countTo;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
+#X connect 2 1 0 1;
+#X connect 3 0 6 0;
+#X connect 4 0 3 0;
+#X connect 6 0 2 0;
+#X restore 83 49 pd resetArray;
+#X obj 83 3 loadbang;
+#X obj 88 25 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 39 188 maxArray \$0-activeNotes 128;
+#X obj 183 219 f;
+#X obj 39 237 >= 0;
+#X floatatom 148 313 5 0 0 0 - - -, f 5;
+#X obj 70 262 select 1;
+#X obj 366 87 f;
+#X obj 426 60 f;
+#X text 334 39 note;
+#X text 424 16 velocity;
+#X obj 423 87 > 0;
+#X obj 344 281 tabwrite \$0-activeNotes;
+#X obj 330 207 f;
+#X floatatom 303 178 5 0 0 0 - - -, f 5;
+#X obj 265 163 f;
+#X obj 304 150 + 1;
+#X msg 277 130 -1;
+#X msg 371 207 -0.5;
+#X obj 400 116 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 367 137 spigot;
+#X obj 447 134 spigot;
+#X obj 460 86 == 0;
+#X obj 470 109 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 434 163 t b f;
+#X obj 337 60 inlet;
+#X obj 426 32 inlet;
+#X obj 148 350 outlet;
+#X obj 275 89 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 41 163 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 363 172 t b f;
+#X obj 334 240 t b f;
+#X text 578 211 pass in velocity/note pairs (velocity first) and obtain
+as an output the most recent note still active;
+#X text 581 268 outlet 2 gate;
+#X obj 330 366 outlet;
+#X text 583 251 outlet 1 most recent note active (-1 otherwise);
+#X text 155 329 most recent note active;
+#X msg 338 338 0;
+#X msg 378 339 1;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X connect 3 0 19 0;
+#X connect 4 0 6 0;
+#X connect 4 1 5 1;
+#X connect 5 0 7 0;
+#X connect 5 0 40 0;
+#X connect 6 0 8 0;
+#X connect 7 0 29 0;
+#X connect 8 0 5 0;
+#X connect 8 1 39 0;
+#X connect 9 0 22 0;
+#X connect 9 0 23 0;
+#X connect 10 0 13 0;
+#X connect 10 0 24 0;
+#X connect 13 0 21 0;
+#X connect 15 0 33 0;
+#X connect 16 0 15 1;
+#X connect 17 0 18 0;
+#X connect 18 0 16 0;
+#X connect 18 0 17 1;
+#X connect 19 0 17 1;
+#X connect 20 0 33 0;
+#X connect 21 0 22 1;
+#X connect 22 0 32 0;
+#X connect 23 0 26 0;
+#X connect 24 0 25 0;
+#X connect 25 0 23 1;
+#X connect 26 0 20 0;
+#X connect 26 1 14 1;
+#X connect 27 0 9 0;
+#X connect 28 0 10 0;
+#X connect 28 0 30 0;
+#X connect 30 0 17 0;
+#X connect 31 0 4 0;
+#X connect 32 0 15 0;
+#X connect 32 1 14 1;
+#X connect 33 0 31 0;
+#X connect 33 1 14 0;
+#X connect 39 0 36 0;
+#X connect 40 0 36 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/midi-poly-synth/voice.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,55 @@
+#N canvas 145 23 388 553 10;
+#X obj 45 25 r voice-note-\$1;
+#X obj 45 47 unpack 0 0;
+#X obj 45 103 mtof;
+#X obj 111 446 *~;
+#X obj 152 367 / 127;
+#X obj 111 500 throw~ output;
+#X obj 152 419 line~;
+#X obj 152 393 pack 0 0;
+#X obj 59 176 phasor~;
+#X obj 129 176 phasor~;
+#X obj 86 304 +~;
+#X obj 197 367 r attack;
+#X obj 137 115 sig~;
+#X obj 137 137 +~;
+#X obj 171 113 r~ wobble;
+#X obj 59 198 *~ 2;
+#X obj 59 220 -~ 1;
+#X obj 129 198 *~ 2;
+#X obj 129 220 -~ 1;
+#X obj 310 280 r octVol;
+#X obj 268 397 osc~;
+#X obj 268 419 *~;
+#X obj 111 371 +~;
+#X obj 123 475 *~ 0.5;
+#X obj 268 364 mtof;
+#X obj 267 323 - 12;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 0 25 0;
+#X connect 1 1 4 0;
+#X connect 2 0 8 0;
+#X connect 2 0 12 0;
+#X connect 3 0 23 0;
+#X connect 4 0 7 0;
+#X connect 6 0 3 1;
+#X connect 7 0 6 0;
+#X connect 8 0 15 0;
+#X connect 9 0 17 0;
+#X connect 10 0 22 0;
+#X connect 11 0 7 1;
+#X connect 12 0 13 0;
+#X connect 13 0 9 0;
+#X connect 14 0 13 1;
+#X connect 15 0 16 0;
+#X connect 16 0 10 1;
+#X connect 17 0 18 0;
+#X connect 18 0 10 0;
+#X connect 19 0 21 1;
+#X connect 20 0 21 0;
+#X connect 21 0 22 1;
+#X connect 22 0 3 0;
+#X connect 23 0 5 0;
+#X connect 24 0 20 0;
+#X connect 25 0 24 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/rubberDuckie/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,247 @@
+#N canvas 275 573 442 207 10;
+#X obj 39 149 dac~ 1 2;
+#X text 218 143 ---------------------------------;
+#X text 218 133 @krighxz / BELA / heavy / 12/2015;
+#X text 242 152 beaglert.cc / enzienaudio.com;
+#X text 35 32 Rubber Duckie;
+#X text 35 42 =============;
+#N canvas 325 86 823 605 duckie 0;
+#X obj 186 510 *~;
+#X obj 306 517 *~;
+#X obj 372 468 noise~;
+#X obj 372 492 bp~ 3000 10;
+#X obj 366 162 abs~;
+#X obj 509 158 sig~ 0;
+#X obj 467 371 +~;
+#X obj 411 210 -~ 0.55;
+#X obj 411 231 /~ 0.2;
+#X obj 411 252 clip~ 0 1;
+#X obj 411 282 *~;
+#X obj 411 308 *~ 1000;
+#X obj 366 334 +~;
+#X obj 366 308 +~ 800;
+#X obj 186 536 *~ 0.2;
+#X obj 366 282 *~ 800;
+#N canvas 568 775 135 226 <~ 0;
+#X obj 20 -43 -~;
+#X obj 20 27 +~ 1e-37;
+#X obj 20 6 clip~ -1e-37 0;
+#X obj 20 -88 inlet~;
+#X obj 64 -87 inlet~;
+#X obj 20 -64 max~;
+#X obj 20 -19 *~ -1;
+#X obj 20 79 outlet~;
+#X obj 20 48 *~ 1e+37;
+#X connect 0 0 6 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 1;
+#X connect 4 0 5 1;
+#X connect 5 0 0 0;
+#X connect 6 0 2 0;
+#X connect 8 0 7 0;
+#X restore 186 367 pd <~ 0;
+#N canvas 568 775 135 226 <~ 0;
+#X obj 20 -43 -~;
+#X obj 20 27 +~ 1e-37;
+#X obj 20 6 clip~ -1e-37 0;
+#X obj 20 -88 inlet~;
+#X obj 64 -87 inlet~;
+#X obj 20 -64 max~;
+#X obj 20 -19 *~ -1;
+#X obj 20 79 outlet~;
+#X obj 20 48 *~ 1e+37;
+#X connect 0 0 6 0;
+#X connect 1 0 8 0;
+#X connect 2 0 1 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 1;
+#X connect 4 0 5 1;
+#X connect 5 0 0 0;
+#X connect 6 0 2 0;
+#X connect 8 0 7 0;
+#X restore 482 181 pd <~;
+#X obj 186 428 *~;
+#X obj 225 345 sig~ 1;
+#X obj 186 394 lop~ 10;
+#X text 524 393 << band-limited pulse;
+#X text 10 367 reed stops when overblown >>;
+#X obj 186 460 *~;
+#X obj 186 480 *~;
+#X text 25 470 exp amplitude response >>;
+#X text 537 238 << detune frequency on change of direction;
+#X obj 482 236 *~ -300;
+#X obj 306 485 *~;
+#X obj 306 449 *~ 0.1;
+#X text 448 493 << noise simulates non-oscillating airflow when overblown
+;
+#X obj 186 561 outlet~;
+#N canvas 58 1286 407 525 pulse 0;
+#X obj 83 340 *~;
+#X obj 83 366 *~;
+#X obj 31 366 sig~ 1;
+#X obj 52 419 /~;
+#X obj 67 393 +~;
+#X text 116 366 X^2;
+#X text 97 396 1+X^2;
+#X text 84 421 1/(1+X^2);
+#X obj 83 317 osc~;
+#X obj 167 320 clip~ 0 999999;
+#X obj 52 483 outlet~;
+#X text 271 218 << tweak all this;
+#X text 25 14 based on F04.waveshaping.pulse.pd;
+#X obj 83 84 /~ 2;
+#X obj 167 148 -~;
+#X obj 167 170 /~ 127;
+#X obj 52 452 hip~ 5;
+#X obj 167 202 *~;
+#X obj 167 232 *~;
+#X obj 167 262 *~;
+#X obj 167 294 *~ 1000;
+#X obj 118 125 sig~ 139;
+#X obj 83 58 inlet~;
+#N canvas 331 1377 215 174 _ftom 0;
+#X obj -482 -776 tabread4~ _ftom;
+#X obj -482 -818 /~ 10000;
+#X obj -482 -797 *~ 256;
+#N canvas 0 23 450 278 (subpatch) 0;
+#X array _ftom 256 float 3;
+#A 0 0 27.0762 39.0762 46.0958 51.0762 54.9394 58.0958 60.7645 63.0762
+65.1153 66.9394 68.5894 70.0958 71.4815 72.7645 73.9589 75.0762 76.1258
+77.1153 78.0514 78.9394 79.784 80.5894 81.359 82.0958 82.8025 83.4815
+84.1349 84.7645 85.372 85.9589 86.5266 87.0762 87.609 88.1258 88.6276
+89.1153 89.5897 90.0514 90.5011 90.9394 91.3669 91.784 92.1914 92.5894
+92.9785 93.359 93.7313 94.0958 94.4528 94.8025 95.1453 95.4815 95.8113
+96.1349 96.4525 96.7645 97.0709 97.372 97.6679 97.9589 98.2451 98.5266
+98.8036 99.0762 99.3446 99.609 99.8693 100.126 100.379 100.628 100.873
+101.115 101.354 101.59 101.822 102.051 102.278 102.501 102.722 102.939
+103.154 103.367 103.577 103.784 103.989 104.191 104.392 104.589 104.785
+104.978 105.17 105.359 105.546 105.731 105.914 106.096 106.275 106.453
+106.629 106.803 106.975 107.145 107.314 107.482 107.647 107.811 107.974
+108.135 108.294 108.453 108.609 108.764 108.918 109.071 109.222 109.372
+109.521 109.668 109.814 109.959 110.103 110.245 110.386 110.527 110.666
+110.804 110.94 111.076 111.211 111.345 111.477 111.609 111.74 111.869
+111.998 112.126 112.253 112.379 112.504 112.628 112.751 112.873 112.995
+113.115 113.235 113.354 113.472 113.59 113.706 113.822 113.937 114.051
+114.165 114.278 114.39 114.501 114.612 114.722 114.831 114.939 115.047
+115.154 115.261 115.367 115.472 115.577 115.681 115.784 115.887 115.989
+116.09 116.191 116.292 116.392 116.491 116.589 116.688 116.785 116.882
+116.978 117.074 117.17 117.265 117.359 117.453 117.546 117.639 117.731
+117.823 117.915 118.005 118.096 118.186 118.275 118.364 118.453 118.541
+118.629 118.716 118.803 118.889 118.975 119.06 119.145 119.23 119.314
+119.398 119.482 119.565 119.647 119.729 119.811 119.893 119.974 120.055
+120.135 120.215 120.294 120.374 120.453 120.531 120.609 120.687 120.764
+120.842 120.918 120.995 121.071 121.147 121.222 121.297 121.372 121.446
+121.521 121.594 121.668 121.741 121.814 121.887 121.959 122.031 122.103
+122.174 122.245 122.316 122.386 122.457 122.527 122.596 122.666 122.735
+122.804 122.872 122.94 123.008;
+#X coords 0 127 256 -12 50 50 1 0 0;
+#X restore -546 -793 graph;
+#X obj -482 -838 clip~ 0 10000;
+#X obj -482 -858 inlet~;
+#X obj -482 -755 outlet~;
+#X text -567 -722 shoddy temp replacement for ftom~;
+#X connect 0 0 6 0;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 4 0 1 0;
+#X connect 5 0 4 0;
+#X restore 182 125 pd _ftom;
+#X connect 0 0 1 0;
+#X connect 0 0 1 1;
+#X connect 1 0 4 1;
+#X connect 2 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 16 0;
+#X connect 4 0 3 1;
+#X connect 8 0 0 0;
+#X connect 9 0 0 1;
+#X connect 13 0 8 0;
+#X connect 13 0 23 0;
+#X connect 14 0 15 0;
+#X connect 15 0 17 0;
+#X connect 15 0 17 1;
+#X connect 16 0 10 0;
+#X connect 17 0 18 0;
+#X connect 17 0 18 1;
+#X connect 18 0 19 0;
+#X connect 18 0 19 1;
+#X connect 19 0 20 0;
+#X connect 20 0 9 0;
+#X connect 21 0 14 0;
+#X connect 22 0 13 0;
+#X connect 23 0 14 1;
+#X restore 467 394 pd pulse;
+#X obj 366 105 inlet~;
+#X text 295 104 airflow >>;
+#X text 218 118 ('squeeze pressure');
+#X text 13 20 Sound model of a rubber duckie toy;
+#X text 14 51 Hint: use the differential of a continuous signal as
+input for a realistic response;
+#X text 13 29 ==================================;
+#X obj 366 133 lop~ 0.5;
+#X text 423 132 << airflow resistance;
+#X connect 0 0 14 0;
+#X connect 1 0 14 0;
+#X connect 2 0 3 0;
+#X connect 3 0 1 1;
+#X connect 4 0 7 0;
+#X connect 4 0 15 0;
+#X connect 4 0 29 0;
+#X connect 4 0 18 1;
+#X connect 4 0 16 0;
+#X connect 5 0 17 1;
+#X connect 6 0 32 0;
+#X connect 7 0 8 0;
+#X connect 8 0 9 0;
+#X connect 9 0 10 0;
+#X connect 9 0 10 1;
+#X connect 10 0 11 0;
+#X connect 11 0 12 1;
+#X connect 12 0 6 0;
+#X connect 13 0 12 0;
+#X connect 14 0 31 0;
+#X connect 15 0 13 0;
+#X connect 16 0 20 0;
+#X connect 17 0 27 0;
+#X connect 18 0 23 0;
+#X connect 18 0 23 1;
+#X connect 19 0 16 1;
+#X connect 20 0 18 0;
+#X connect 23 0 24 1;
+#X connect 23 0 24 0;
+#X connect 24 0 0 0;
+#X connect 27 0 6 1;
+#X connect 28 0 1 0;
+#X connect 29 0 28 1;
+#X connect 29 0 28 0;
+#X connect 32 0 0 1;
+#X connect 33 0 39 0;
+#X connect 39 0 4 0;
+#X connect 39 0 17 0;
+#X restore 39 127 pd duckie;
+#X obj 39 77 adc~ 10;
+#N canvas 0 22 504 229 differential 0;
+#X obj 27 80 rzero~ 1;
+#X obj 72 57 sig~ 1;
+#X obj 27 152 *~ 44100;
+#X obj 72 131 samplerate~;
+#X obj 72 110 loadbang;
+#X obj 27 25 inlet~;
+#X obj 27 190 outlet~;
+#X text 84 83 y[n] = x[n] - x[n-1];
+#X text 121 57 <<< heavy currently requires signal input to set coefficient
+;
+#X text 91 151 <<< multiply by samplerate to get velocity;
+#X connect 0 0 2 0;
+#X connect 1 0 0 1;
+#X connect 2 0 6 0;
+#X connect 3 0 2 1;
+#X connect 4 0 3 0;
+#X connect 5 0 0 0;
+#X restore 39 101 pd differential;
+#X connect 6 0 0 0;
+#X connect 6 0 0 1;
+#X connect 7 0 8 0;
+#X connect 8 0 6 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/samphold/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,22 @@
+#N canvas 275 504 414 247 10;
+#X obj 55 212 dac~ 1 2;
+#X obj 55 171 *~ 0.1;
+#X obj 55 150 osc~ 440;
+#X obj 55 61 noise~;
+#X obj 55 128 samphold~;
+#X text 51 21 ==================;
+#X text 51 11 Sample and hold FM;
+#X obj 55 85 lop~ 1;
+#X obj 122 107 phasor~ 880;
+#X obj 55 107 *~ 1e+06;
+#X text 193 199 ---------------------------------;
+#X text 193 189 @krighxz / BELA / heavy / 12/2015;
+#X text 217 208 beaglert.cc / enzienaudio.com;
+#X connect 1 0 0 1;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
+#X connect 3 0 7 0;
+#X connect 4 0 2 0;
+#X connect 7 0 9 0;
+#X connect 8 0 4 1;
+#X connect 9 0 4 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/simple-fm/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,42 @@
+#N canvas 275 573 409 282 10;
+#X obj 37 230 dac~ 1 2;
+#X text 175 222 ---------------------------------;
+#X obj 37 102 *~ 1000;
+#X obj 37 199 *~ 0.1;
+#X obj 37 79 adc~ 3;
+#X obj 65 125 adc~ 4;
+#X obj 94 147 adc~ 5;
+#N canvas 81 574 322 252 FMvoice 1;
+#X obj 20 174 +~;
+#X obj 93 116 osc~;
+#X obj 93 157 *~;
+#X obj 93 76 *~;
+#X obj 158 98 *~;
+#X obj 20 225 outlet~;
+#X obj 20 200 osc~;
+#X obj 20 39 inlet~ freq;
+#X obj 108 39 inlet~ harmRatio~;
+#X obj 173 69 inlet~ modIndex~;
+#X connect 0 0 6 0;
+#X connect 1 0 2 0;
+#X connect 2 0 0 1;
+#X connect 3 0 4 0;
+#X connect 3 0 1 0;
+#X connect 4 0 2 1;
+#X connect 6 0 5 0;
+#X connect 7 0 3 0;
+#X connect 7 0 0 0;
+#X connect 8 0 3 1;
+#X connect 9 0 4 1;
+#X restore 37 169 pd FMvoice;
+#X text 33 22 Simple FM;
+#X text 33 32 =========;
+#X text 175 212 @krighxz / BELA / heavy / 12/2015;
+#X text 199 231 beaglert.cc / enzienaudio.com;
+#X connect 2 0 7 0;
+#X connect 3 0 0 1;
+#X connect 3 0 0 0;
+#X connect 4 0 2 0;
+#X connect 5 0 7 1;
+#X connect 6 0 7 2;
+#X connect 7 0 3 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/08-PureData/tableScrubbing/_main.pd	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,35 @@
+#N canvas 503 319 861 473 10;
+#N canvas 0 22 450 278 (subpatch) 0;
+#X array exampleTable 65238 float 2;
+#X coords 0 1 65238 -1 200 140 1 0 0;
+#X restore 21 213 graph;
+#X obj 243 329 adc~ 1 2 3;
+#X obj 300 426 dac~;
+#X text 317 264 <<< delete this object before compiling!;
+#X obj 300 392 tabread4~ exampleTable;
+#X msg 243 218 read -resize rt.wav exampleTable;
+#X obj 300 350 lop~ 1;
+#X obj 300 371 *~ 65238;
+#X obj 243 266 soundfiler;
+#X text 489 229 right-click array -> properties -> toggle "save contents"
+;
+#X text 463 216 <<< after loading a file:;
+#X text 17 23 Load sample into table and scrub using analog input;
+#X text 17 33 ===================================================;
+#X text 362 351 <<< avoid zipper noise;
+#X text 362 371 <<< length of sample;
+#X text 317 328 <<< analog input 0 (range 0-1);
+#X text 631 419 ---------------------------------;
+#X text 631 409 @krighxz / BELA / heavy / 12/2015;
+#X text 655 428 beaglert.cc / enzienaudio.com;
+#X text 30 61 N.B. the patch cannot be bigger than 512kb in size \;
+only use this for *very small soundfiles*;
+#X text 29 99 You can modify the render.cpp file to load samples into
+tables using the Heavy API: https://enzienaudio.com/docs/c.html#api-hv-table
+;
+#X connect 1 2 6 0;
+#X connect 4 0 2 0;
+#X connect 4 0 2 1;
+#X connect 5 0 8 0;
+#X connect 6 0 7 0;
+#X connect 7 0 4 0;
Binary file examples/08-PureData/tableScrubbing/rt.wav has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/Junction.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,95 @@
+/*
+ *
+ * Excitation Junction for two waveguides
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+#include "Junction.h"
+#include "../include/Utilities.h"
+
+Junction::Junction()	{
+
+	setFrequency(440);
+	_dt = 1.0/44100.0;
+
+	// initialize variables
+	for(int i=0;i<WG_BUFFER_SIZE;i++)	{
+		_buffer_l[i] = 0;
+		_buffer_r[i] = 0;
+	}
+	_excitation = 0;
+	_lastPlectrumDisplacement = 0;
+	_readPtr = 0;
+
+}
+
+void Junction::update(float excitation, float left, float right)	{
+
+	// 1. advance delay buffer read pointer
+
+	if(++_readPtr>=WG_BUFFER_SIZE)
+		_readPtr=0;
+
+	// 2. add excitation sample into buffer
+
+	_buffer_l[(_readPtr+_delay_l+WG_BUFFER_SIZE)%WG_BUFFER_SIZE] = excitation;
+	_buffer_r[(_readPtr+_delay_r+WG_BUFFER_SIZE)%WG_BUFFER_SIZE] = excitation;
+
+	// 3. feed right input to left output and vice versa
+
+	_buffer_l[_readPtr] += right;
+	_buffer_r[_readPtr] += left;
+
+	// 4. store excitation value for later use
+	_excitation = excitation;
+
+}
+
+float Junction::getOutput(int direction)	{
+
+	if(direction = 0)
+		return _buffer_l[_readPtr];
+	else
+		return _buffer_r[_readPtr];
+
+}
+
+float Junction::getExcitationDisplacement()	{
+
+	// string displacement and excitation force
+	// use delayed value to account for excitation position
+	float in = _buffer_l[(_readPtr+_delay_l+WG_BUFFER_SIZE)%WG_BUFFER_SIZE] + _excitation;
+
+	// integrate total force
+	float out = 0.00001 * in + 0.99999 * _lastPlectrumDisplacement;
+
+	// store variable for next iteration
+	_lastPlectrumDisplacement = out;
+
+	// multiply by delta time
+	return out * _dt;
+
+}
+
+void Junction::setPluckPosition(float pluckPos){
+
+	pluckPos = constrain(pluckPos,0,1);
+	_delay_l = pluckPos * _periodInSamples;
+	_delay_r = (1-pluckPos) * _periodInSamples;
+
+}
+
+void Junction::setPeriod(float period)	{
+
+	_periodInMilliseconds = period;
+
+}
+
+void Junction::setFrequency(float frequency)	{
+
+	_periodInMilliseconds = 1000.0/frequency;
+	_periodInSamples = (int)(_periodInMilliseconds * 44.1);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/Junction.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,54 @@
+/*
+ *
+ * Excitation Junction for two waveguides
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+#ifndef JUNCTION_H_
+#define JUNCTION_H_
+
+#include <cmath>
+
+#ifndef WG_BUFFER_SIZE
+#define WG_BUFFER_SIZE 4096
+#endif
+
+#ifndef		M_PI
+#define		M_PI		3.14159265358979323846264338
+#endif
+
+class Junction
+{
+
+public:
+
+	Junction();
+	void setup();
+	void update(float excitation, float left, float right);
+	float getOutput(int direction);
+	float getExcitationDisplacement();
+	void setFrequency(float frequency);
+	void setPeriod(float periodInMs);
+	void setPluckPosition(float pluckPos);
+
+private:
+
+	double _dt;
+	float _periodInMilliseconds;
+	int _periodInSamples;
+
+	int _delay_l;
+	int _delay_r;
+
+	float _buffer_l[WG_BUFFER_SIZE];
+	float _buffer_r[WG_BUFFER_SIZE];
+	int _readPtr;
+
+	float _excitation;
+	float _lastPlectrumDisplacement;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/MassSpringDamper.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,59 @@
+/*
+ *
+ * Simple 1-Dimensional Mass Spring Damper
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+#include "MassSpringDamper.h"
+
+MassSpringDamper::MassSpringDamper(float mass, float spring, float damp)	{
+
+	_dt = 1.0/44100.0;
+	_mass = mass;
+	_spring = spring;
+	_damp = damp;
+	_position = 0;
+	_velocity = 0;
+
+}
+
+void MassSpringDamper::setup()	{
+
+}
+
+double MassSpringDamper::update(float inForce)	{
+
+	// 1. calculate spring/damper forces using current position and velocity
+
+	double out = (_position * (double)_spring * -1) + (_velocity * (double)_damp * -1);
+
+	// 2. apply external force
+
+	out += inForce;
+
+	// 3. derive acceleration (a = f/m)
+
+	out /= (double)_mass;
+
+	// 4. derive velocity (v = a*dt)
+
+	out *= _dt;
+
+	// 5. apply previous velocity
+
+	out += _velocity;
+
+	// 6. save current velocity state for next iteration
+
+	_velocity = out;
+
+	// 7. derive new position (x[n] = x[n-1] + v[n]) and save for next iteration
+
+	out += _position;
+	_position = out;
+
+	return out;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/MassSpringDamper.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,32 @@
+/*
+ *
+ * Simple 1-Dimensional Mass Spring Damper
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+#ifndef MASSSPRINGDAMPER_H_
+#define MASSSPRINGDAMPER_H_
+
+class MassSpringDamper
+{
+
+public:
+
+	MassSpringDamper(float mass, float spring, float damp);
+	void setup();
+	double update(float inForce);
+
+private:
+
+	double _dt;
+	float _mass;
+	float _spring;
+	float _damp;
+	double _position;
+	double _velocity;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/Plectrum.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,61 @@
+/*
+ *
+ * Plectrum model for touching and plucking strings
+ *
+ * Christian Heinrichs 04/2015
+ *
+ * [inspired by E. Berdahl's pluck~ abstraction for the FireFader]
+ *
+ */
+
+#include "Plectrum.h"
+
+#include "../include/Utilities.h"
+#include <cmath>
+#include <stdio.h>
+#include <cstdlib>
+
+Plectrum::Plectrum()	{
+
+	_contact = 0;
+	_lastDistance = 0;
+
+}
+
+void Plectrum::setup(float spring, float damp, float hyst)	{
+
+	_spring = spring;
+	_damp = damp;
+	_hyst = hyst;
+
+}
+
+float Plectrum::update(float position, float stringPosition)	{
+
+	float distance = position - stringPosition;
+
+	// Calculate spring/damp forces based on distance to string
+
+	float springOut = distance * _spring;
+
+	float dampOut = (distance - _lastDistance) * 44100;
+
+	float out = springOut+dampOut;
+
+	// If distance crosses zero, enable contact
+
+	if((distance>0 && _lastDistance<=0)||(distance<0 && _lastDistance>=0))
+		_contact = 1;
+
+	// If distance exceeds hysteresis threshold, jump to zero (i.e. 'pluck')
+
+	if(fabs(distance)>_hyst)
+		_contact = 0;
+
+	// FIXME: contact doesn't switch back to zero if distance goes back in original direction
+
+	_lastDistance = distance;
+
+	return out * _contact;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/Plectrum.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,35 @@
+/*
+ *
+ * Plectrum model for touching and plucking strings
+ *
+ * [inspired by E. Berdahl's pluck~ abstraction for the FireFader]
+ *
+ */
+
+#ifndef PLECTRUM_H_
+#define PLECTRUM_H_
+
+class Plectrum
+{
+
+public:
+
+	Plectrum();
+	void setup(float spring, float damp, float hyst);
+	float update(float position, float stringPosition);
+
+private:
+
+	double _dt;
+	float _spring;
+	float _damp;
+	double _position;
+	double _velocity;
+	float _hyst;
+	float _lastDistance;
+	int _contact;
+
+};
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/String.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,91 @@
+/*
+ *
+ * 1-D string consisting of two waveguides and junction
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+#include "String.h"
+#include "Junction.h"
+#include "Waveguide.h"
+
+#include "../include/Utilities.h"
+#include <rtdk.h>
+#include <cmath>
+#include <stdio.h>
+#include <cstdlib>
+
+String::String(){
+
+	wg_l = Waveguide();
+	wg_r = Waveguide();
+	junction = Junction();
+
+	junction.setPluckPosition(0.5);
+
+	_previous_l = 0;
+	_previous_r = 0;
+
+}
+
+float String::update(float in)	{
+
+	// 1. send excitation signal and previous waveguide outputs into junction
+
+	junction.update(in,_previous_l,_previous_r);
+
+	// 2. save new waveguide outputs for next iteration
+
+	_previous_l = wg_l.update(junction.getOutput(0));
+	_previous_r = wg_r.update(junction.getOutput(1));
+
+	// 3. use right waveguide as output
+
+	//rt_printf("BANANA %f ",_readPtr);
+	//rt_printf("%f\n",_previous_r);
+
+	return _previous_r;
+}
+
+float String::getPlectrumDisplacement()	{
+
+	return junction.getExcitationDisplacement();
+
+}
+
+void String::setPluckPosition(float pluckPos){
+
+	junction.setPluckPosition(pluckPos);
+
+}
+
+void String::setGlobalPosition(float pos)	{
+
+	_globalPosition = pos;
+
+}
+
+float String::getGlobalPosition()	{
+
+	return _globalPosition;
+
+}
+
+void String::setMidinote(float midinote)	{
+
+	float frequency = 440.0f*(float)powf(2,(midinote-57)/12.0f);
+
+	junction.setFrequency(frequency);
+	wg_l.setFrequency(frequency);
+	wg_r.setFrequency(frequency);
+
+}
+
+void String::setFrequency(float frequency)	{
+
+	junction.setFrequency(frequency);
+	wg_l.setFrequency(frequency);
+	wg_r.setFrequency(frequency);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/String.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ *
+ * 1-D string consisting of two waveguides and junction
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+#ifndef STRING_H_
+#define STRING_H_
+
+#include <cmath>
+#include "Junction.h"
+#include "Waveguide.h"
+
+class String
+{
+
+public:
+
+	String();
+	float update(float in);
+
+	float getPlectrumDisplacement();
+	void setMidinote(float midinote);
+	void setFrequency(float frequency);
+	void setPeriod(float periodInMs);
+	void setPluckPosition(float pluckPos);
+	void setGlobalPosition(float pos);
+	float getGlobalPosition();
+
+private:
+
+	float _previous_l;
+	float _previous_r;
+
+	float _globalPosition;
+
+	Waveguide wg_l;
+	Waveguide wg_r;
+	Junction junction;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/Waveguide.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,128 @@
+/*
+ *
+ * Simple 1-Dimensional Waveguide
+ *
+ */
+
+#include "Waveguide.h"
+#include "../include/Utilities.h"
+#include <rtdk.h>
+#include <cmath>
+#include <stdio.h>
+#include <cstdlib>
+
+#define DECAY 0.995//0.999
+#define DAMPING 0.01//0.05
+
+// TODO: make damping and decay parametrisable
+
+Waveguide::Waveguide()	{
+
+	// initialize variables
+	a1_lp = 0;
+	a2_lp = 0;
+	b0_lp = 0;
+	b1_lp = 0;
+	b2_lp = 0;
+	_dt = 1.0/44100.0;
+	setFrequency(440);
+	updateFilterCoeffs(8000);
+	_filterReadPtr=0;
+	for(int i=0;i<FILTER_BUFFER_SIZE;i++)	{
+		_filterBuffer_x[i] = 0;
+		_filterBuffer_y[i] = 0;
+	}
+	for(int i=0;i<WG_BUFFER_SIZE;i++)	{
+		_buffer[i] = 0;
+	}
+	_lastX = 0;
+	_lastY = 0;
+	_readPtr = 0;
+
+}
+
+void Waveguide::setup()	{
+
+}
+
+float Waveguide::update(float in)	{
+
+	// 1. advance delay buffer read pointer
+
+	if(++_readPtr>=WG_BUFFER_SIZE)
+		_readPtr=0;
+
+	// 2. write input into buffer
+
+	_buffer[_readPtr] = in;
+
+	// 3. read delayed sample from buffer
+
+	float out = _buffer[(_readPtr-_periodInSamples+WG_BUFFER_SIZE)%WG_BUFFER_SIZE];
+
+	// 4. apply damping (low-pass) filter to output
+
+	if(++_filterReadPtr>=FILTER_BUFFER_SIZE)
+			_filterReadPtr=0;
+
+	out = b0_lp*out +
+					b1_lp*_filterBuffer_x[(_filterReadPtr-1+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] +
+					b2_lp*_filterBuffer_x[(_filterReadPtr-2+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] -
+					a1_lp*_filterBuffer_y[(_filterReadPtr-1+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] -
+					a2_lp*_filterBuffer_y[(_filterReadPtr-2+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE];
+
+	// 5. Simple high-pass filter to block DC-offset
+	// y[n] = x[n] - x[n-1] + a * y[n-1]
+	float gain = 0.9999;
+	float temp = out;
+	out = out - _lastX + gain * _lastY;
+	_lastY = out;
+	_lastX = temp;
+
+	// 6. Apply intensity damping
+	out *= DECAY;
+
+	_filterBuffer_x[_filterReadPtr] = in;
+	_filterBuffer_y[_filterReadPtr] = out;
+
+	return out;
+
+}
+
+void Waveguide::setFrequency(float frequency)	{
+
+	// NB: currently no interpolation, so may not be ideal for dynamically changing waveguide frequency
+	_periodInMilliseconds = 1000.0/frequency;
+	_periodInSamples = (int)(_periodInMilliseconds * 44.1);
+
+}
+
+void Waveguide::updateFilterCoeffs(float frequency)	{
+
+	// FIXME: Butterworth filter doesn't work very well,
+	//		  using simple FIR in the meantime
+
+	a1_lp = 0;
+	a2_lp = 0;
+	b0_lp = 1.0 - DAMPING;
+	b1_lp = DAMPING;
+	b2_lp = 0;
+
+	/*
+	// 'w' for sake of resembling lower-case 'omega'
+	float w = 2.0 * M_PI * frequency;
+	float t = _dt;
+	// The Q for a 2nd-order Butterworth is sqrt(2)/2
+	float q = 0.707;//sqrt(2.0)/2.0;
+
+	// low-pass filter coefficients
+	float a0_lp = w*w*t*t + 2*(w/q)*t + 4.0;
+	float k = 1.0/a0_lp;
+	a1_lp = (2.0*w*w*t*t - 8.0) * k;
+	a2_lp = (4.0 - (w/q)*2.0*t + w*w*t*t) * k;
+	b0_lp = (w*w*t*t) * k;
+	b1_lp = (2.0*w*w*t*t) * k;
+	b2_lp = (w*w*t*t) * k;
+	*/
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/Waveguide.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,57 @@
+/*
+ *
+ * Simple 1-Dimensional Waveguide
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+#ifndef WAVEGUIDE_H_
+#define WAVEGUIDE_H_
+
+#include <cmath>
+
+#ifndef WG_BUFFER_SIZE
+#define WG_BUFFER_SIZE 4096
+#endif
+
+#ifndef FILTER_BUFFER_SIZE
+#define FILTER_BUFFER_SIZE 4
+#endif
+
+#ifndef		M_PI
+#define		M_PI		3.14159265358979323846264338
+#endif
+
+class Waveguide
+{
+
+public:
+
+	Waveguide();
+	void setup();
+	float update(float in);
+	void updateFilterCoeffs(float frequency);
+	void setFrequency(float frequency);
+
+private:
+
+	double _dt;
+	float _periodInMilliseconds;
+	int _periodInSamples;
+
+	float _buffer[WG_BUFFER_SIZE];
+	int _readPtr;
+
+	float _filterBuffer_x[FILTER_BUFFER_SIZE];
+	float _filterBuffer_y[FILTER_BUFFER_SIZE];
+	float _hipBuffer_x[FILTER_BUFFER_SIZE];
+	float _hipBuffer_y[FILTER_BUFFER_SIZE];
+	int _filterReadPtr;
+
+	float b0_lp,b1_lp,b2_lp,a1_lp, a2_lp;
+	float _lastY,_lastX;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/airharp/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,211 @@
+/*
+ * AIR-HARP
+ * Physically modelled strings using waveguide junctions and mass-spring-dampers
+ *
+ * render.cpp
+ *
+ * Christian Heinrichs 04/2015
+ *
+ */
+
+
+#include "MassSpringDamper.h"
+#include "String.h"
+#include "Plectrum.h"
+
+#include <Bela.h>
+#include <cmath>
+#include <stdio.h>
+#include <cstdlib>
+#include <rtdk.h>
+
+#define ACCEL_BUF_SIZE 8
+#define NUMBER_OF_STRINGS 9
+
+// PENTATONIC SCALE
+float gMidinotes[NUMBER_OF_STRINGS] = {40,45,50,55,57,60,62,64,67};
+
+float gInverseSampleRate;
+
+float out_gain = 5.0;
+
+int accelPin_x = 0;
+int accelPin_y = 1;
+int accelPin_z = 2;
+
+MassSpringDamper msd = MassSpringDamper(1,0.1,10);// (10,0.001,10);
+String strings[NUMBER_OF_STRINGS];
+Plectrum plectrums[NUMBER_OF_STRINGS];
+
+float gPlectrumDisplacement = 0;
+
+float gAccel_x[ACCEL_BUF_SIZE] = {0};
+int gAccelReadPtr = 0;
+
+// DC BLOCK BUTTERWORTH
+
+// Coefficients for 100hz cut-off
+float a0_l = 0.9899759179893742;
+float a1_l = -1.9799518359787485;
+float a2_l = 0.9899759179893742;
+float a3_l = -1.979851353142371;
+float a4_l = 0.9800523188151258;
+
+float a0_r = a0_l;
+float a1_r = a1_l;
+float a2_r = a2_l;
+float a3_r = a3_l;
+float a4_r = a4_l;
+
+float x1_l = 0;
+float x2_l = 0;
+float y1_l = 0;
+float y2_l = 0;
+
+float x1_r = 0;
+float x2_r = 0;
+float y1_r = 0;
+float y2_r = 0;
+
+
+bool setup(BelaContext *context, void *userData)
+{
+
+	gInverseSampleRate = 1.0 / context->audioSampleRate;
+
+	// initialise strings & plectrums
+	for(int i=0;i<NUMBER_OF_STRINGS;i++)	{
+
+		plectrums[i] = Plectrum();
+		plectrums[i].setup(250,0.25,0.05);
+
+		strings[i] = String();
+		strings[i].setMidinote(gMidinotes[i]);
+
+		float spacing = 2.0 / (NUMBER_OF_STRINGS+1);
+
+		strings[i].setGlobalPosition( -1 + spacing*(i+1) );
+
+		rt_printf("STRING %d // midinote: %f position: %f\n",i,gMidinotes[i],( -1 + spacing*(i+1) ));
+
+	}
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+
+	float lastAccel = 0;
+
+	for(int n = 0; n < context->audioFrames; n++) {
+
+		/*
+		 *
+		 * ACCELEROMETER DATA
+		 *
+		 */
+
+		// Read accelerometer data from analog input
+		float accel_x = 0;
+		if(n%2)	{
+			accel_x = (float)context->analogIn[(n/2)*8+accelPin_x] * 2 - 1;	// 15800 - 28300 - 41500
+			lastAccel = accel_x;
+		} else {
+			// grab previous value if !n%2
+			accel_x = lastAccel;
+		}
+
+		// Dead-zone avoids noise when box is lying horizontally on a surface
+
+		float accelDeadZone = 0.1;
+
+		if(accel_x <= accelDeadZone && accel_x >= -accelDeadZone)
+			accel_x = 0;
+
+		// Perform smoothing (moving average) on acceleration value
+		if(++gAccelReadPtr >= ACCEL_BUF_SIZE)
+			gAccelReadPtr = 0;
+		gAccel_x[gAccelReadPtr] = accel_x;
+		float gravity = 0;
+		for(int i=0;i<ACCEL_BUF_SIZE;i++)	{
+			gravity = gAccel_x[(gAccelReadPtr-i+ACCEL_BUF_SIZE)%ACCEL_BUF_SIZE];
+		}
+		gravity /= ACCEL_BUF_SIZE;
+
+		/*
+		 *
+		 * PHYSICS SIMULATION
+		 *
+		 */
+
+		// The horizontal force (which can be gravity if box is tipped on its side)
+		// is used as the input to a Mass-Spring-Damper model
+		// Plectrum displacement (i.e. when interacting with string) is included
+		float massPosition = (float)msd.update(gravity - gPlectrumDisplacement);
+
+		float out_l = 0;
+		float out_r = 0;
+		// Use this parameter to quickly adjust output gain
+		float gain = 0.0015;	// 0.0015 is a good value or 12 strings
+		gPlectrumDisplacement = 0;
+
+		for(int s=0;s<NUMBER_OF_STRINGS;s++)	{
+
+			float stringPosition = strings[s].getGlobalPosition();
+
+			float plectrumForce = plectrums[s].update(massPosition, stringPosition);
+			gPlectrumDisplacement += strings[s].getPlectrumDisplacement();
+
+			// calculate panning based on string position (-1->left / 1->right)
+			float panRight = map(stringPosition,1,-1,0.1,1);
+			float panLeft = map(stringPosition,-1,1,0.1,1);
+			panRight *= panRight;
+			panLeft *= panLeft;
+
+			float out = strings[s].update(plectrumForce)*gain;
+
+			out_l += out*panLeft;
+			out_r += out*panRight;
+
+		}
+
+		// APPLY DC-BLOCK FILTER TO OUTPUTS
+
+		// LEFT CHANNEL
+		float temp_in = out_l;
+		/* compute result */
+    	out_l = a0_l * out_l + a1_l * x1_l + a2_l * x2_l - a3_l * y1_l - a4_l * y2_l;
+    	/* shift x1 to x2, sample to x1 */
+    	x2_l = x1_l;
+    	x1_l = temp_in;
+    	/* shift y1 to y2, result to y1 */
+    	y2_l = y1_l;
+   	 	y1_l = out_l;
+
+   	 	// RIGHT CHANNEL
+		temp_in = out_r;
+		/* compute result */
+    	out_r = a0_r * out_r + a1_r * x1_r + a2_r * x2_r - a3_r * y1_r - a4_r * y2_r;
+    	/* shift x1 to x2, sample to x1 */
+    	x2_r = x1_r;
+    	x1_r = temp_in;
+    	/* shift y1 to y2, result to y1 */
+    	y2_r = y1_r;
+   	 	y1_r = out_r;
+
+		context->audioOut[n * context->audioChannels + 1] = out_l * out_gain;
+		context->audioOut[n * context->audioChannels + 0] = out_r * out_gain;
+
+	}
+
+}
+
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/ADSR.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,76 @@
+//
+//  ADSR.cpp
+//
+//  Created by Nigel Redmon on 12/18/12.
+//  EarLevel Engineering: earlevel.com
+//  Copyright 2012 Nigel Redmon
+//
+//  For a complete explanation of the ADSR envelope generator and code,
+//  read the series of articles by the author, starting here:
+//  http://www.earlevel.com/main/2013/06/01/envelope-generators/
+//
+//  License:
+//
+//  This source code is provided as is, without warranty.
+//  You may copy and distribute verbatim copies of this document.
+//  You may modify and use this source code to create binary code for your own purposes, free or commercial.
+//
+
+#include "ADSR.h"
+#include <math.h>
+
+
+ADSR::ADSR(void) {
+    reset();
+    setAttackRate(0);
+    setDecayRate(0);
+    setReleaseRate(0);
+    setSustainLevel(1.0);
+    setTargetRatioA(0.3);
+    setTargetRatioDR(0.0001);
+}
+
+ADSR::~ADSR(void) {
+}
+
+void ADSR::setAttackRate(float rate) {
+    attackRate = rate;
+    attackCoef = calcCoef(rate, targetRatioA);
+    attackBase = (1.0 + targetRatioA) * (1.0 - attackCoef);
+}
+
+void ADSR::setDecayRate(float rate) {
+    decayRate = rate;
+    decayCoef = calcCoef(rate, targetRatioDR);
+    decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
+}
+
+void ADSR::setReleaseRate(float rate) {
+    releaseRate = rate;
+    releaseCoef = calcCoef(rate, targetRatioDR);
+    releaseBase = -targetRatioDR * (1.0 - releaseCoef);
+}
+
+float ADSR::calcCoef(float rate, float targetRatio) {
+    return exp(-log((1.0 + targetRatio) / targetRatio) / rate);
+}
+
+void ADSR::setSustainLevel(float level) {
+    sustainLevel = level;
+    decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
+}
+
+void ADSR::setTargetRatioA(float targetRatio) {
+    if (targetRatio < 0.000000001)
+        targetRatio = 0.000000001;  // -180 dB
+    targetRatioA = targetRatio;
+    attackBase = (1.0 + targetRatioA) * (1.0 - attackCoef);
+}
+
+void ADSR::setTargetRatioDR(float targetRatio) {
+    if (targetRatio < 0.000000001)
+        targetRatio = 0.000000001;  // -180 dB
+    targetRatioDR = targetRatio;
+    decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
+    releaseBase = -targetRatioDR * (1.0 - releaseCoef);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/ADSR.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,137 @@
+//
+//  ADRS.h
+//
+//  Created by Nigel Redmon on 12/18/12.
+//  EarLevel Engineering: earlevel.com
+//  Copyright 2012 Nigel Redmon
+//
+//  For a complete explanation of the ADSR envelope generator and code,
+//  read the series of articles by the author, starting here:
+//  http://www.earlevel.com/main/2013/06/01/envelope-generators/
+//
+//  License:
+//
+//  This source code is provided as is, without warranty.
+//  You may copy and distribute verbatim copies of this document.
+//  You may modify and use this source code to create binary code for your own purposes, free or commercial.
+//
+
+#ifndef ADRS_h
+#define ADRS_h
+
+#include <stdio.h>
+#include <string>
+
+using namespace std;
+
+enum envState {
+	env_idle = 0,
+	env_attack,
+	env_decay,
+	env_sustain,
+	env_release
+};
+
+class ADSR {
+public:
+	ADSR(void);
+	~ADSR(void);
+	float process(void);
+	float process(int sampleCount);
+    float getOutput(void);
+    int getState(void);
+	void gate(int on);
+    void setAttackRate(float rate);
+    void setDecayRate(float rate);
+    void setReleaseRate(float rate);
+	void setSustainLevel(float level);
+    void setTargetRatioA(float targetRatio);
+    void setTargetRatioDR(float targetRatio);
+    void reset(void);
+
+protected:
+	int state;
+	float output;
+	float attackRate;
+	float decayRate;
+	float releaseRate;
+	float attackCoef;
+	float decayCoef;
+	float releaseCoef;
+	float sustainLevel;
+    float targetRatioA;
+    float targetRatioDR;
+    float attackBase;
+    float decayBase;
+    float releaseBase;
+	string name;
+    float calcCoef(float rate, float targetRatio);
+};
+
+inline float ADSR::process() {
+	switch (state) {
+        case env_idle:
+            break;
+        case env_attack:
+            output = attackBase + output * attackCoef;
+            if (output >= 1.0) {
+                output = 1.0;
+                state = env_decay;
+            }
+            break;
+        case env_decay:
+            output = decayBase + output * decayCoef;
+            if (output <= sustainLevel) {
+                output = sustainLevel;
+                state = env_sustain;
+            }
+            break;
+        case env_sustain:
+            break;
+        case env_release:
+            output = releaseBase + output * releaseCoef;
+            if (output <= 0.0) {
+                output = 0.0;
+                state = env_idle;
+            }
+            break;
+	}
+	return output;
+}
+
+inline float ADSR::process(int sampleCount)
+{
+	float retVal = 0;
+
+	if(state != env_idle)
+	{
+		for(int i=0; i<sampleCount; i++)
+			retVal = process();
+	}
+
+	return retVal;
+}
+
+inline void ADSR::gate(int gate) {
+
+	if (gate)
+		state = env_attack;
+	else if (state != env_idle)
+        state = env_release;
+}
+
+inline int ADSR::getState() {
+    return state;
+}
+
+inline void ADSR::reset() {
+    state = env_idle;
+    output = 0.0;
+}
+
+inline float ADSR::getOutput() {
+	return output;
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/AnalogInput.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,163 @@
+/*
+ * AnalogInput.cpp
+ *
+ *  Created on: Oct 17, 2013
+ *      Author: Victor Zappi
+ */
+
+
+#include "AnalogInput.h"
+
+using namespace std;
+
+
+AnalogInput::AnalogInput()
+{
+	ActivateAnalogHnd  = NULL;
+	activateAnalogPath = "";
+	analogIsSet        = false;
+
+	AnalogInHnd    = NULL;
+	analogInPath   = "";
+	helperNumFound = false;
+
+	// support var for init
+	// these are fixed for BBB
+	startPath = "/sys/devices/bone_capemgr.*/slots";
+	readPath = "";
+
+	buffer = (char*) malloc (sizeof(char)*lSize); // reading buffer
+
+	verbose = false;
+}
+
+
+AnalogInput::~AnalogInput()
+{
+	free(buffer);
+}
+
+int AnalogInput::initAnalogInputs()
+{
+	 if(analogIsSet)
+	 {
+		 if(verbose)
+			 cout << "Fine, but Analog Input already active..."<< endl;
+		 return 0;
+	 }
+
+	// title
+	 if(verbose)
+	 	cout << "Init Analog Input"<< endl;
+
+
+	  // first: activate analog pins on cape manager
+	  // cape-bone-iio > /sys/devices/bone_capemgr.*/slots
+
+	  // we have to look for the semi-random number the BBB has initialized the bone_capemgr with [value of *]
+	  // to reach /slots and set cape-bone-iio.
+	  // to do so, we use glob lib, which translates wildcards [*] into all the values found in paths
+
+
+	  glob( startPath.c_str(), 0, NULL, &globbuf);
+
+	  if(globbuf.gl_pathc >0)
+	  {
+	    if (globbuf.gl_pathc == 1 )
+	    {
+	      activateAnalogPath = globbuf.gl_pathv[0];
+
+	      // check if file is existing
+	      if((ActivateAnalogHnd = fopen(activateAnalogPath.c_str(), "r+")) != NULL)
+	      {
+	        // we found that current capemgr num
+
+			fwrite("cape-bone-iio", sizeof(char), 13, ActivateAnalogHnd); // activate pins
+
+	        analogIsSet = true;
+
+			if(verbose)
+				cout << "Analog Pins activated via cape-bone-iio at path " << activateAnalogPath << endl;
+
+			fclose(ActivateAnalogHnd); // close file
+	      }
+	    }
+	    //else
+	      //printf("toomany", );
+	  }
+
+	  globfree(&globbuf); // self freeing
+
+
+	  if(!analogIsSet)
+	  {
+	    cout << "cannot find bone_capemgr" << endl;
+	    cout << "------Init failed------" << endl;
+	    return 1;
+	  }
+
+
+	  // build read path
+	  startPath = "/sys/devices/ocp.2/helper.*";
+
+	  glob( startPath.c_str(), 0, NULL, &globbuf);
+
+	  if(globbuf.gl_pathc >0)
+	  {
+		if (globbuf.gl_pathc == 1 )
+		{
+		  analogInPath = globbuf.gl_pathv[0] + (string)"/AIN";
+		}
+	    else
+	      cout << "Too many analog inputs with this name! [I am puzzled...]" << endl;
+	  }
+	  else
+	    cout << "Cannot find analog input dir...puzzled" << endl;
+
+
+	  return 0;
+}
+
+
+int AnalogInput::read(int index)
+{
+	  // convert int index into string
+	  stringstream ss;
+	  ss << index;
+
+	  readPath = analogInPath + ss.str(); // create pin0 file path
+
+
+	  // check if file is existing
+	  if((AnalogInHnd = fopen(readPath.c_str(), "rb")) != NULL)
+	  {
+		// we found that current helper num
+
+		// prepare read buffer to reading
+		fseek (AnalogInHnd , 0 , SEEK_END);
+		lSize = ftell (AnalogInHnd);
+		rewind (AnalogInHnd);
+
+		result = fread (buffer, 1, lSize, AnalogInHnd);
+
+		fclose(AnalogInHnd); // close file
+
+		helperNumFound = true;
+
+		//cout << "Analog Pins can be read at path " << analogInPath << endl;
+		//cout << "Test reading of Pin0 gives: " << buffer << endl;
+	  }
+
+	  if(!helperNumFound)
+	  {
+	    cout << "cannot find helper" << endl;
+	    cout << "------Analog Read failed------" << endl;
+	    return -1;
+	  }
+
+	  return atoi(buffer);
+
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/AnalogInput.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,55 @@
+/*
+ * AnalogInput.h
+ *
+ *  Created on: Oct 17, 2013
+ *      Author: Victor Zappi
+ */
+
+#ifndef ANALOGINPUT_H_
+#define ANALOGINPUT_H_
+
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <glob.h>
+
+using namespace std;
+
+class AnalogInput
+{
+private:
+	FILE *ActivateAnalogHnd;
+	string activateAnalogPath;
+	bool analogIsSet;
+
+	FILE *AnalogInHnd;
+	string analogInPath;
+	bool helperNumFound;
+
+	// suport var for init
+	string startPath;
+	string readPath;
+
+	glob_t  globbuf;
+
+	// support vars for pin reading
+	long lSize;
+	char * buffer;
+	size_t result;
+
+	bool verbose;
+
+public:
+	AnalogInput();
+	~AnalogInput();
+
+	int initAnalogInputs();
+	int read(int index);
+
+};
+
+
+
+
+#endif /* ANALOGINPUT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/Biquad.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,169 @@
+//
+//  Biquad.cpp
+//
+//  Created by Nigel Redmon on 11/24/12
+//  EarLevel Engineering: earlevel.com
+//  Copyright 2012 Nigel Redmon
+//
+//  For a complete explanation of the Biquad code:
+//  http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
+//
+//  License:
+//
+//  This source code is provided as is, without warranty.
+//  You may copy and distribute verbatim copies of this document.
+//  You may modify and use this source code to create binary code
+//  for your own purposes, free or commercial.
+//
+
+#include <math.h>
+#include "Biquad.h"
+#include <iostream>
+
+Biquad::Biquad() {
+    type = bq_type_lowpass;
+    a0 = 1.0;
+    a1 = a2 = b1 = b2 = 0.0;
+    Fc = 0.50;
+    Q = 0.707;
+    peakGain = 0.0;
+    z1 = z2 = 0.0;
+}
+
+Biquad::Biquad(int type, double Fc, double Q, double peakGainDB) {
+    setBiquad(type, Fc, Q, peakGainDB);
+    z1 = z2 = 0.0;
+}
+
+Biquad::~Biquad() {
+}
+
+void Biquad::setType(int type) {
+    this->type = type;
+    calcBiquad();
+}
+
+void Biquad::setQ(double Q) {
+    this->Q = Q;
+    calcBiquad();
+}
+
+void Biquad::setFc(double Fc) {
+    this->Fc = Fc;
+    calcBiquad();
+}
+
+void Biquad::setPeakGain(double peakGainDB) {
+    this->peakGain = peakGainDB;
+    calcBiquad();
+}
+    
+void Biquad::setBiquad(int type, double Fc, double Q, double peakGainDB) {
+    this->type = type;
+    this->Q = Q;
+    this->Fc = Fc;
+    startFc = Fc;
+    startQ = Q;
+    startPeakGain = peakGainDB;
+    setPeakGain(peakGainDB);
+}
+
+void Biquad::calcBiquad(void) {
+    double norm;
+    double V = pow(10, fabs(peakGain) / 20.0);
+    double K = tan(M_PI * Fc);
+    switch (this->type) {
+        case bq_type_lowpass:
+            norm = 1 / (1 + K / Q + K * K);
+            a0 = K * K * norm;
+            a1 = 2 * a0;
+            a2 = a0;
+            b1 = 2 * (K * K - 1) * norm;
+            b2 = (1 - K / Q + K * K) * norm;
+            break;
+            
+        case bq_type_highpass:
+            norm = 1 / (1 + K / Q + K * K);
+            a0 = 1 * norm;
+            a1 = -2 * a0;
+            a2 = a0;
+            b1 = 2 * (K * K - 1) * norm;
+            b2 = (1 - K / Q + K * K) * norm;
+            break;
+            
+        case bq_type_bandpass:
+            norm = 1 / (1 + K / Q + K * K);
+            a0 = K / Q * norm;
+            a1 = 0;
+            a2 = -a0;
+            b1 = 2 * (K * K - 1) * norm;
+            b2 = (1 - K / Q + K * K) * norm;
+            break;
+            
+        case bq_type_notch:
+            norm = 1 / (1 + K / Q + K * K);
+            a0 = (1 + K * K) * norm;
+            a1 = 2 * (K * K - 1) * norm;
+            a2 = a0;
+            b1 = a1;
+            b2 = (1 - K / Q + K * K) * norm;
+            break;
+            
+        case bq_type_peak:
+            if (peakGain >= 0) {    // boost
+                norm = 1 / (1 + 1/Q * K + K * K);
+                a0 = (1 + V/Q * K + K * K) * norm;
+                a1 = 2 * (K * K - 1) * norm;
+                a2 = (1 - V/Q * K + K * K) * norm;
+                b1 = a1;
+                b2 = (1 - 1/Q * K + K * K) * norm;
+            }
+            else {    // cut
+                norm = 1 / (1 + V/Q * K + K * K);
+                a0 = (1 + 1/Q * K + K * K) * norm;
+                a1 = 2 * (K * K - 1) * norm;
+                a2 = (1 - 1/Q * K + K * K) * norm;
+                b1 = a1;
+                b2 = (1 - V/Q * K + K * K) * norm;
+            }
+            break;
+        case bq_type_lowshelf:
+            if (peakGain >= 0) {    // boost
+                norm = 1 / (1 + sqrt(2) * K + K * K);
+                a0 = (1 + sqrt(2*V) * K + V * K * K) * norm;
+                a1 = 2 * (V * K * K - 1) * norm;
+                a2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
+                b1 = 2 * (K * K - 1) * norm;
+                b2 = (1 - sqrt(2) * K + K * K) * norm;
+            }
+            else {    // cut
+                norm = 1 / (1 + sqrt(2*V) * K + V * K * K);
+                a0 = (1 + sqrt(2) * K + K * K) * norm;
+                a1 = 2 * (K * K - 1) * norm;
+                a2 = (1 - sqrt(2) * K + K * K) * norm;
+                b1 = 2 * (V * K * K - 1) * norm;
+                b2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
+            }
+            break;
+        case bq_type_highshelf:
+            if (peakGain >= 0) {    // boost
+                norm = 1 / (1 + sqrt(2) * K + K * K);
+                a0 = (V + sqrt(2*V) * K + K * K) * norm;
+                a1 = 2 * (K * K - V) * norm;
+                a2 = (V - sqrt(2*V) * K + K * K) * norm;
+                b1 = 2 * (K * K - 1) * norm;
+                b2 = (1 - sqrt(2) * K + K * K) * norm;
+            }
+            else {    // cut
+                norm = 1 / (V + sqrt(2*V) * K + K * K);
+                a0 = (1 + sqrt(2) * K + K * K) * norm;
+                a1 = 2 * (K * K - 1) * norm;
+                a2 = (1 - sqrt(2) * K + K * K) * norm;
+                b1 = 2 * (K * K - V) * norm;
+                b2 = (V - sqrt(2*V) * K + K * K) * norm;
+            }
+            break;
+    }
+    
+    return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/Biquad.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,99 @@
+//
+//  Biquad.h
+//
+//  Created by Nigel Redmon on 11/24/12
+//  EarLevel Engineering: earlevel.com
+//  Copyright 2012 Nigel Redmon
+//
+//  For a complete explanation of the Biquad code:
+//  http://www.earlevel.com/main/2012/11/25/biquad-c-source-code/
+//
+//  License:
+//
+//  This source code is provided as is, without warranty.
+//  You may copy and distribute verbatim copies of this document.
+//  You may modify and use this source code to create binary code
+//  for your own purposes, free or commercial.
+//
+
+#ifndef Biquad_h
+#define Biquad_h
+
+enum {
+    bq_type_lowpass = 0,
+    bq_type_highpass,
+    bq_type_bandpass,
+    bq_type_notch,
+    bq_type_peak,
+    bq_type_lowshelf,
+    bq_type_highshelf
+};
+
+class Biquad {
+public:
+    Biquad();
+    Biquad(int type, double Fc, double Q, double peakGainDB);
+    ~Biquad();
+    void setType(int type);
+    void setQ(double Q);
+    void setFc(double Fc);
+    void setPeakGain(double peakGainDB);
+    void setBiquad(int type, double Fc, double Q, double peakGain);
+    float process(float in);
+    
+    double getQ();
+    double getFc();
+    double getPeakGain();
+
+    double getStartingQ();
+	double getStartingFc();
+	double getStartingPeakGain();
+
+protected:
+    void calcBiquad(void);
+
+    int type;
+    double a0, a1, a2, b1, b2;
+    double Fc, Q, peakGain;
+    double startFc, startQ, startPeakGain;
+    double z1, z2;
+};
+
+inline double Biquad::getQ()
+{
+	return Q;
+}
+
+inline double Biquad::getFc()
+{
+	return Fc;
+}
+
+inline double Biquad::getPeakGain()
+{
+	return peakGain;
+}
+
+inline double Biquad::getStartingQ()
+{
+	return startQ;
+}
+
+inline double Biquad::getStartingFc()
+{
+	return startFc;
+}
+
+inline double Biquad::getStartingPeakGain()
+{
+	return startPeakGain;
+}
+
+inline float Biquad::process(float in) {
+    double out = in * a0 + z1;
+    z1 = in * a1 + z2 - b1 * out;
+    z2 = in * a2 - b2 * out;
+    return out;
+}
+
+#endif // Biquad_h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/DBoxSynth.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,35 @@
+/*
+ * SimpleSynth.h
+ *
+ *  Created on: Oct 22, 2013
+ *      Author: Victor Zappi
+ */
+
+#ifndef DBOXSYNTH_H_
+#define DBOXSYNTH_H_
+
+#include <iostream>
+#include <string>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "Synth.h"
+
+
+class DBoxSynth : public Synth
+{
+public:
+	DBoxSynth(unsigned int rate, unsigned long buffer_size);
+	double getSample();
+	double *getBlock(int block_size);
+
+
+private:
+	Sampler *smp;
+
+};
+
+
+
+
+#endif /* DBOXSYNTH_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/DboxSensors.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,157 @@
+/*
+ * DboxSensors.cpp
+ *
+ *  Created on: May 19, 2014
+ *      Author: Victor Zappi
+ */
+
+
+#include "DboxSensors.h"
+#include "config.h"
+
+using namespace std;
+
+
+
+int DboxSensors::initSensors(int tk0_bus, int tk0_address, int tk1_bus, int tk1_address, int tk_file, int fsr_pin, int fsrmax, int sensorTypeToUse, int gpio_0, int gpio_1)
+{
+	sensorType = sensorTypeToUse;
+	// init first touch key on i2c bus
+	if(tk0_address >= 0) {
+		if(TK0.initI2C_RW(tk0_bus, tk0_address, tk_file)>0)
+			return 1;
+		if(TK0.initTouchKey(sensorType)>0)
+			return 2;
+	}
+
+	// init second touch key on i2c bus
+	if(tk1_address >= 0) {
+		if(TK1.initI2C_RW(tk1_bus, tk1_address, tk_file)>0)
+			return 1;
+		if(TK1.initTouchKey(sensorType)>0)
+			return 2;
+	}
+
+	// init fsr on analog input pin
+	fsr_pinNum	= fsr_pin;
+	fsr_max	  	= fsrmax;
+
+	if(FSR.initAnalogInputs()>0)
+		return 3;
+
+	gpio[0] = gpio_0;
+	if(gpio[0]!=-1)
+	{
+		fdDi[0] = gpio_export(gpio[0]);
+		if(fdDi[0] == -1)
+			return 4;
+	}
+	digitalIn[0] = 1;
+
+	return 0;
+}
+
+
+int DboxSensors::readSensors()
+{
+	// write data into first touch key
+	if(TK0.ready()) {
+		if(TK0.readI2C()>0)
+			return 1;
+
+		// retrieve data from first touch key
+		tk0_touchCnt = TK0.getTouchCount();
+	}
+	else
+		tk0_touchCnt = 0;
+
+	// write data into second touch key
+	if(TK1.ready()) {
+		if(TK1.readI2C()>0)
+			return 1;
+		// retrieve data from second touch key
+		tk1_touchCnt = TK1.getTouchCount();
+	}
+	else
+		tk1_touchCnt = 0;
+
+
+	int max = 3;
+	if(sensorType != kSensorTypeTouchKey)
+		max = 5;
+	// if touches detected on main touch key
+	if(tk0_touchCnt == 0 && tk1_touchCnt == 0)
+		resetSensorsData();
+	else
+	{
+		for(int i=0; i<max; i++)
+		{
+			tk0_touchPosX[i] = TK0.getSliderPosition()[i];
+			tk0_touchSize[i] = TK0.getSlidersize()[i];
+
+			tk1_touchPosX[i] = TK1.getSliderPosition()[i];
+			tk1_touchSize[i] = TK1.getSlidersize()[i];
+		}
+		tk0_touchPosY 	 = TK0.getSliderPositionH();
+		tk1_touchPosY 	 = TK1.getSliderPositionH();
+		fsr_read		 = (double)FSR.read(fsr_pinNum);
+	}
+
+	if(gpio[0]!=-1)
+	{
+		if(gpio_read(fdDi[0], &digitalIn[0])==-1)
+			return 1;
+	}
+
+	return 0;
+}
+
+
+
+DboxSensors::DboxSensors()
+{
+	resetSensorsData();
+}
+
+
+
+DboxSensors::~DboxSensors()
+{
+	if(gpio[0]!=-1)
+		gpio_dismiss(fdDi[0], gpio[0]);
+}
+
+
+
+//--------------------------------------------------------------------------------------------------------
+// private methods
+//--------------------------------------------------------------------------------------------------------
+
+// idle values
+void DboxSensors::resetSensorsData()
+{
+	int max = 3;
+	if(sensorType != kSensorTypeTouchKey)
+		max = 5;
+
+	for(int i=0; i<max; i++)
+	{
+		tk0_touchPosX[i] = -1;
+		tk0_touchPosY	 = -1;
+		tk0_touchSize[i] = 0;
+
+		tk1_touchPosX[i] = -1;
+		tk1_touchPosY	 = -1;
+		tk1_touchSize[i] = 0;
+
+		fsr_read		 = 0;
+	}
+
+	return;
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/DboxSensors.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,128 @@
+/*
+ * DboxSensors.h
+ *
+ *  Created on: May 19, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef DBOXSENSORS_H_
+#define DBOXSENSORS_H_
+
+#include <stdio.h>
+#include <sys/mount.h>	// mount()
+#include <string.h> 	// strerror()
+#include <fstream> 		// fstream
+#include <iostream>
+#include <unistd.h> 	// usleep()
+#include <glob.h>		// glob()
+#include <sys/time.h>	// elapsed time
+#include <sys/stat.h>	// mkdir()
+#include <algorithm>	// reverse() [string...]
+
+#include "I2c_TouchKey.h"
+#include "AnalogInput.h"
+#include <GPIOcontrol.h>	// TODO wrap this into a class
+
+/*---------------------------------------------------------------------------------------------------------------------------------------------------
+ * This class retrieves data from all the connected sensors,
+ * logs them
+ * and exposes to the main only the values needed to synthesize sound
+ *
+ * The simple instrument has:
+ *
+ *
+ *
+ *---------------------------------------------------------------------------------------------------------------------------------------------------
+ */
+class DboxSensors
+{
+public:
+	int initSensors(int tk0_bus, int tk0_address, int tk1_bus, int tk1_address, int tk_file, int fsr_pin, int fsrmax, int sensorTypeToUse, int gpio0=-1, int gpio1=-1);
+	int readSensors();
+	int getTKTouchCount(int index);
+	float *getTKXPositions(int index);
+	float getTKYPosition(int index);
+	float *getTKTouchSize(int index);
+	double getFSRVAlue();
+	int getDigitalIn(int index);
+
+	DboxSensors();
+	~DboxSensors();
+
+private:
+	int sensorType;
+
+	I2c_TouchKey TK0;
+	int tk0_touchCnt;
+	float tk0_touchPosX[5];
+	float tk0_touchPosY;
+	float tk0_touchSize[5];
+
+	I2c_TouchKey TK1;
+	int tk1_touchCnt;
+	float tk1_touchPosX[5];
+	float tk1_touchPosY;
+	float tk1_touchSize[5];
+
+	AnalogInput FSR;
+	int fsr_pinNum;
+	double fsr_read;
+	int fsr_max;
+
+	unsigned int digitalIn[2];
+	int fdDi[2];
+	int gpio[2];
+
+	void resetSensorsData();
+
+};
+
+
+
+//--------------------------------------------------------------------------------
+// read interface
+inline int DboxSensors::getTKTouchCount(int index)
+{
+	if(index==0)
+		return tk0_touchCnt;
+	else
+		return tk1_touchCnt;
+}
+
+inline float *DboxSensors::getTKXPositions(int index)
+{
+	if(index==0)
+		return tk0_touchPosX;
+	else
+		return tk1_touchPosX;
+}
+
+inline float DboxSensors::getTKYPosition(int index)
+{
+	if(index==0)
+		return tk0_touchPosY;
+	else
+		return tk1_touchPosY;
+}
+
+inline float *DboxSensors::getTKTouchSize(int index)
+{
+	if(index==0)
+		return tk0_touchSize;
+	else
+		return tk1_touchSize;
+}
+
+inline double DboxSensors::getFSRVAlue()
+{
+	return fsr_read;
+}
+
+inline int DboxSensors::getDigitalIn(int index)
+{
+	return digitalIn[index];
+}
+//--------------------------------------------------------------------------------
+
+
+#endif /* DBOXSENSORS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/FIRfilter.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,73 @@
+/*
+ * FIRfilter.h
+ *
+ *  Created on: Aug 5, 2014
+ *      Author: Victor Zappi and Andrew McPherson
+ */
+
+#ifndef FIRFILTER_H_
+#define FIRFILTER_H_
+
+#define ENABLE_NE10_FIR_FLOAT_NEON	// Define needed for Ne10 library
+#include <ne10/NE10.h>
+
+//#define FILTER_TAP_NUM 21
+//ne10_float32_t filterTaps[FILTER_TAP_NUM] = {
+//	0.000350,
+//	0.001133,
+//	0.002407,
+//	0.004203,
+//	0.006468,
+//	0.009057,
+//	0.011748,
+//	0.014265,
+//	0.016323,
+//	0.017671,
+//	0.018141,
+//	0.017671,
+//	0.016323,
+//	0.014265,
+//	0.011748,
+//	0.009057,
+//	0.006468,
+//	0.004203,
+//	0.002407,
+//	0.001133,
+//	0.000350
+//};
+#define FILTER_TAP_NUM 31
+ne10_float32_t filterTaps[FILTER_TAP_NUM] = {
+		0.000018,
+		0.000043,
+		0.000078,
+		0.000125,
+		0.000183,
+		0.000252,
+		0.000330,
+		0.000415,
+		0.000504,
+		0.000592,
+		0.000677,
+		0.000754,
+		0.000818,
+		0.000866,
+		0.000897,
+		0.000907,
+		0.000897,
+		0.000866,
+		0.000818,
+		0.000754,
+		0.000677,
+		0.000592,
+		0.000504,
+		0.000415,
+		0.000330,
+		0.000252,
+		0.000183,
+		0.000125,
+		0.000078,
+		0.000043,
+		0.000018
+};
+
+#endif /* FIRFILTER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/FeedbackOscillator.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,105 @@
+/*
+ * FeedbackOscillator.cpp
+ *
+ * Recursive phase-shift oscillator implemented
+ * on the matrix
+ *
+ * Andrew McPherson 2014
+ */
+
+#include "FeedbackOscillator.h"
+#include <cstdlib>
+#include <cmath>
+
+#define COEFF_B0 	0
+#define COEFF_B1	1
+#define COEFF_A1	2
+
+FeedbackOscillator::FeedbackOscillator()
+: wavetable1(0), wavetable2(0)
+{
+
+}
+
+FeedbackOscillator::~FeedbackOscillator() {
+	if(wavetable1 != 0)
+		free(wavetable1);
+	if(wavetable2 != 0)
+		free(wavetable2);
+
+}
+
+// Initialise the settings for the feedback oscillator
+void FeedbackOscillator::initialise(int maxTableSize, float hpfCutoffFrequency, float matrixSampleRate) {
+	wavetableMaxLength = maxTableSize;
+	if(wavetable1 != 0)
+		free(wavetable1);
+	if(wavetable2 != 0)
+		free(wavetable2);
+
+	wavetable1 = (float *)malloc(maxTableSize * sizeof(float));
+	wavetable2 = (float *)malloc(maxTableSize * sizeof(float));
+
+	float omega = tan(M_PI * hpfCutoffFrequency / matrixSampleRate);
+	float n = 1.0f / (1.0f + omega);
+
+	coeffs[COEFF_A1] = (omega - 1.0f) * n;
+	coeffs[COEFF_B0] = n;
+	coeffs[COEFF_B1] = -n;
+
+	for(int n = 0; n < maxTableSize; n++)
+		wavetable1[n] = wavetable2[n] = 0;
+
+	wavetableRead = wavetable1;
+	wavetableWrite = wavetable2;
+	wavetableWritePointer = 0;
+	sampleCount = lastTriggerCount = 0;
+}
+
+// Process one sample and store the output value
+// Returns true if the wavetable needs rendering
+int FeedbackOscillator::process(float input, float *output) {
+	float outFloat = coeffs[COEFF_B0] * input + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput;
+	int requestRenderLength = 0;
+
+	if(outFloat < -0.5)
+		*output = 0;
+	else if(outFloat > 0.5)
+		*output = 1;
+	else
+		*output = outFloat + 0.5;
+
+	if(canTrigger && outFloat > 0 && lastOutput <= 0) {
+		triggered = true;
+		requestRenderLength = wavetableWritePointer;	// How many samples stored thus far?
+		if(requestRenderLength < 4)
+			requestRenderLength = 0;	// Ignore anything with fewer than 4 points
+
+		lastTriggerCount = sampleCount;
+		canTrigger = false;
+		wavetableWritePointer = 0;
+
+		// Swap buffers
+		float *temp = wavetableWrite;
+		wavetableWrite = wavetableRead;
+		wavetableRead = temp;
+	}
+
+	if(triggered) {
+		wavetableWrite[wavetableWritePointer] = outFloat;
+		if(++wavetableWritePointer >= wavetableMaxLength) {
+			triggered = false;
+			wavetableWritePointer = 0;
+		}
+	}
+
+	if(sampleCount - lastTriggerCount > 40)
+		canTrigger = true;
+
+	sampleCount++;
+
+	lastOutput = outFloat;
+	lastInput = input;
+
+	return requestRenderLength;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/FeedbackOscillator.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,41 @@
+/*
+ * FeedbackOscillator.h
+ *
+ *  Created on: June 8, 2014
+ *      Author: Andrew McPherson
+ */
+
+#ifndef FEEDBACKOSCILLATOR_H
+#define FEEDBACKOSCILLATOR_H
+
+class FeedbackOscillator
+{
+public:
+	FeedbackOscillator();
+	~FeedbackOscillator();
+
+	// Initialise the settings for the feedback oscillator
+	void initialise(int maxTableSize, float hpfCutoffFrequency, float matrixSampleRate);
+
+	// Process one sample and store the output value
+	// Returns the length of table to interpolate; or 0 if nothing to process further
+	int process(float input, float *output);
+
+	float *wavetable() { return wavetableRead; }
+
+private:
+	float coeffs[3];			// Coefficients of first-order high-pass filter
+	float lastInput;			// last input sample for HPF
+	float lastOutput;			// last output sample of HPF
+	bool triggered;				// whether we are currently saving samples
+	bool canTrigger;			// whether we are able to begin saving samples
+	int wavetableMaxLength;		// how long the stored wavetable can be
+	int sampleCount;			// how many samples have elapsed
+	int lastTriggerCount;		// sample count when we last triggered
+
+	float *wavetable1, *wavetable2;			// Two wavetables where we record samples
+	float *wavetableRead, *wavetableWrite;	// Pointers to the above wavetables
+	int wavetableWritePointer;				// Where we are currently writing
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/OscillatorBank.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,1016 @@
+/*
+ * OscillatorBank.cpp
+ *
+ *  Created on: May 23, 2014
+ *      Author: Victor Zappi and Andrew McPherson
+ */
+
+
+/*
+ * There is a problem with name consistency between this class and the Parser class in spear_parser files.
+ * There, a "frame" is each of the time values where partials are sampled, while a "hop" is the actual jump between frames [calculated in samples]
+ * Here, "hop" is used with the meaning of "frame", while "frame" became the local frame of a partial
+ *
+ * example
+ *
+ * frames:	0		1		2
+ * p0				p0_0 	p0_1
+ * p1		p1_0	p1_1 	p1_2
+ * p2		p2_0	p2_1
+ *
+ * 	In this case:
+ * 		 in Parser there are 2 hops, 3 total frames and the 3 partials have respectively 2, 3 and 2 local frames
+ *
+ * 		 here there are 3 total hops [the concept of jumps is discarded, cos not in use] and the 3 partials have respectively 2, 3 and 2 frames
+ *
+ * 	This must be fixed
+*/
+
+// TODO: fix hop-frame name consistency
+
+
+#include <stdlib.h>
+
+#include "OscillatorBank.h"
+
+OscillatorBank::OscillatorBank() {
+	loaded = false;
+}
+
+OscillatorBank::OscillatorBank(string filename, int hopsize, int samplerate) {
+	loaded = false;
+	loadFile(filename.c_str(), hopsize, samplerate);
+}
+
+OscillatorBank::OscillatorBank(char *filename, int hopsize, int samplerate) {
+	loaded = false;
+	loadFile(filename, hopsize, samplerate);
+}
+
+OscillatorBank::~OscillatorBank() {
+	free(oscillatorPhases);
+	free(oscillatorNextNormFreq);
+	free(oscillatorNextAmp);
+	free(oscillatorNormFrequencies);
+	free(oscillatorAmplitudes);
+	free(oscillatorNormFreqDerivatives);
+	free(oscillatorAmplitudeDerivatives);
+	free(phaseCopies);
+	free(nextNormFreqCopies);
+	free(nextAmpCopies);
+
+	delete[] oscStatNormFrequenciesMean;
+	delete[] oscStatNumHops;
+	delete[] lookupTable;
+	delete[] indicesMapping;
+	delete[] freqFixedDeltas;
+	delete[] ampFixedDeltas;
+	delete[] nyquistCut;
+}
+
+bool OscillatorBank::initBank(int oversamp) {
+	if (!loaded)
+		return false;
+
+	//---prepare look-up table
+	lookupTableSize = 1024;
+	lookupTable		= new float[lookupTableSize + 1];
+	for (int n = 0; n < (lookupTableSize + 1); n++)
+		lookupTable[n] = sin(2.0 * M_PI * (float) n / (float) lookupTableSize);
+	frequencyScaler = (float) lookupTableSize / rate;
+	nyqNorm			= rate / 2 * frequencyScaler;
+
+	if (oversamp < 1)
+		oversamp = 1;
+
+	//---prepare oscillators
+	partials = &(parser.partials); // pointer to paser's partials
+	partialsHopSize = parser.getHopSize();
+	lastHop = partials->getHopNum(); // last bank hop is equal to last partial frame, which is equal to partial hop num
+	overSampling = oversamp;
+	hopSize = partialsHopSize / overSampling; // if oversampling, osc bank hop num > partials hop num
+	hopSizeReminder = partialsHopSize % overSampling;
+	oscBankHopSize = hopSize;
+	numOfPartials = partials->getPartialNum();
+	numOfOscillators = partials->getMaxActivePartialNum(); // get the maximum number of active partials at the same time
+
+	// set to next multiple of 4 [NEON]
+	numOfOscillators = (numOfOscillators + 3) & ~0x3; // to be sure we can add up to 3 fake oscillators
+
+	int err;
+	//---allocate buffers
+	// alligned buffers [NEON]
+	err = posix_memalign((void**) &oscillatorPhases, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &oscillatorNextNormFreq, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &oscillatorNextAmp, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &oscillatorNormFrequencies, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &oscillatorAmplitudes, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &oscillatorNormFreqDerivatives, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &oscillatorAmplitudeDerivatives, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &phaseCopies, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &nextNormFreqCopies, 16,
+			numOfOscillators * sizeof(float));
+	err += posix_memalign((void**) &nextAmpCopies, 16,
+			numOfOscillators * sizeof(float));
+
+	// regular ones
+	oscStatNormFrequenciesMean	= new float[numOfPartials];
+	oscStatNumHops				= new float[numOfPartials];
+	indicesMapping				= new int[numOfPartials];
+	freqFixedDeltas				= new float[numOfPartials];
+	ampFixedDeltas				= new float[numOfPartials];
+	nyquistCut 					= new bool[numOfPartials];
+
+	if (err > 0) {
+		dbox_printf("Failed memory allocations %@#!\n");
+		return false;
+	}
+
+	// copy stats [they do not change]
+	for (int n = 0; n < numOfPartials; n++) {
+		oscStatNormFrequenciesMean[n] = partials->partialFreqMean[n]
+				* frequencyScaler;
+		oscStatNumHops[n] = partials->partialNumFrames[n]; // in Parser and Partials "frames" are what we call here "hops" [see comment at top of file]
+	}
+
+	// deafult values
+	actPartNum		= 0;
+	loopStartHop	= 0;
+	loopEndHop		= (parser.partials.getHopNum() - 2) * overSampling;
+	ampTh			= 0.0001;
+	hopNumTh		= 0;
+	pitchMultiplier = 1;
+	freqMovement	= 1;
+	filterNum		= 0;
+	note			= false;
+	speed			= 1;
+	nextSpeed		= -1;
+	maxSpeed 		= 10;
+	minSpeed 		= 0.1;
+	jumpHop 		= -1;
+
+	// filter
+	filterMaxF		= 22000;
+	filterAmpMinF	= 10 * frequencyScaler;
+	filterAmpMaxF	= 5000 * frequencyScaler;
+	filterAmpMul	= 10.0;
+
+	// adsr
+	minAttackTime	= .0001;
+	deltaAttackTime = 2.;
+	minReleaseTime	= 1;
+	deltaReleaseTime = 2.5;
+
+	adsr.setAttackRate(minAttackTime * rate);
+	adsr.setDecayRate(.0001 * rate);
+	adsr.setSustainLevel(1);
+	adsr.setReleaseRate(minReleaseTime * rate);
+
+	state = bank_stopped;
+	return true;
+}
+
+void OscillatorBank::resetOscillators() {
+	currentHop			= -1;
+	loopDir				= 1;
+	loopDirShift 		= 0;
+	fill(nyquistCut, nyquistCut + numOfPartials, false);
+	prevAdsrVal			= 0;
+	prevAmpTh			= ampTh;
+	prevHopNumTh		= hopNumTh;
+	prevPitchMultiplier = pitchMultiplier;
+	prevFreqMovement 	= freqMovement;
+	prevFilterNum = filterNum;
+	memcpy(prevFilterFreqs, filterFreqs, filterNum * sizeof(float));
+	memcpy(prevFilterQ, filterQ, filterNum * sizeof(float));
+
+	int activePNum		= partials->activePartialNum[0];
+	unsigned int *activeP = partials->activePartials[0];
+	for (int i = 0; i < activePNum; i++) {
+		freqFixedDeltas[activeP[i]] = partials->partialFreqDelta[activeP[i]][0]
+				/ overSampling;
+		ampFixedDeltas[activeP[i]]	= partials->partialAmpDelta[activeP[i]][0]
+				/ overSampling;
+	}
+	// attack!
+	adsr.gate(1);
+	note = true;
+
+	nextHop();
+
+	state = bank_playing;
+}
+
+void OscillatorBank::nextHop() {
+	hopSize = oscBankHopSize;
+
+	// copy phases, next freqs and next amps from previous frame
+	memcpy(phaseCopies, oscillatorPhases, actPartNum * sizeof(float));
+	memcpy(nextNormFreqCopies, oscillatorNextNormFreq,
+			actPartNum * sizeof(float));
+	memcpy(nextAmpCopies, oscillatorNextAmp, actPartNum * sizeof(float));
+
+	// next frame is forward or backwards, cos we could be in the loop
+	currentHop += loopDir;
+
+	checkDirection();
+
+//	if((currentHop/overSampling)%100 == 0)
+//		dbox_printf("currentHop %d, direction: %d\n", currentHop/overSampling, loopDir);
+
+	// if needs jump, end here this method, cos jumpToHop() will do tee rest
+	if (checkJump() == 0)
+		return;
+	// otherwise, if jump is not needed or fails, continue regular stuff
+
+	if (nextEnvState() != 0)
+		return; // release has ended!
+
+	checkSpeed();
+
+	// now let's decide how to calculate next hop
+	if (!checkOversampling())
+		nextOscBankHop();
+	else
+		nextPartialHop();
+}
+
+void OscillatorBank::nextOscBankHop() {
+	int parIndex, localHop;
+	float parDamp = 1;
+	int currentPartialHop = (currentHop / overSampling) + loopDirShift;
+
+	// if going backwards in the loop, get previous frame active partials...
+	actPartNum = partials->activePartialNum[currentPartialHop - loopDirShift];
+	actPart = partials->activePartials[currentPartialHop - loopDirShift];
+	//cout << "actPartNum: " << actPartNum << endl;
+
+	envState = adsr.getState(); // to determine what state we will be in next hop [attack, decay, sustain, release]
+
+	int parCnt = 0;
+	int currentHopReminder = currentHop % overSampling;
+	// steps to reach next bank hop from previous partial hop
+	int steps = currentHopReminder + 1;
+	if (loopDir < 0)
+		steps = overSampling - currentHopReminder + 1;
+
+	for (int i = 0; i < actPartNum; i++) {
+		// find partial and frame
+		parIndex = actPart[i];
+		//localHop	= partials->localPartialFrames[currentPartialHop][parIndex];
+		localHop = currentPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
+
+		//float delta = partials->partialFrequencies[parIndex][localHop+loopDir] - partials->partialFrequencies[parIndex][localHop];
+
+		// if this partial was over nyquist on previous hop...
+		if (nyquistCut[parIndex]) {
+			// ...restart from safe values
+			oscillatorPhases[parCnt] = 0;
+			//TODO add freqmove dependency
+			oscillatorNextNormFreq[parCnt] =
+					(partials->partialFrequencies[parIndex][localHop]
+							+ freqFixedDeltas[parIndex] * (steps - 1))
+							* frequencyScaler * prevPitchMultiplier;
+			oscillatorNextAmp[parCnt] = 0;
+		} else if (loopDir == 1) // otherwise recover phase, target freq and target amp from previous frame
+				{
+			if ((localHop != 0) || (currentHopReminder != 0)) {
+				oscillatorPhases[parCnt] =
+						phaseCopies[indicesMapping[parIndex]];
+				oscillatorNextNormFreq[parCnt] =
+						nextNormFreqCopies[indicesMapping[parIndex]];
+				oscillatorNextAmp[parCnt] =
+						nextAmpCopies[indicesMapping[parIndex]];
+			} else // first oscillator hop [both for bank and partial], so no previous data are available
+			{
+				oscillatorPhases[parCnt] = 0;
+				//TODO add freqmove dependency
+				oscillatorNextNormFreq[parCnt] =
+						partials->partialFrequencies[parIndex][localHop]
+								* frequencyScaler * prevPitchMultiplier;
+				parDamp = calculateParDamping(parIndex, prevHopNumTh,
+						prevAdsrVal, oscillatorNextNormFreq[parCnt],
+						prevFilterNum, prevFilterFreqs, prevFilterQ);
+				oscillatorNextAmp[parCnt] =
+						partials->partialAmplitudes[parIndex][localHop]
+								* parDamp;
+				if(oscillatorNextAmp[parCnt] > 1)
+						oscillatorNextAmp[parCnt] = 1;
+				freqFixedDeltas[parIndex] =
+						partials->partialFreqDelta[parIndex][localHop + loopDir]
+								* loopDir / overSampling;
+				ampFixedDeltas[parIndex] =
+						partials->partialAmpDelta[parIndex][localHop + loopDir]
+								* loopDir / overSampling;
+			}
+		} else {
+			oscillatorPhases[parCnt] = phaseCopies[indicesMapping[parIndex]];
+			oscillatorNextNormFreq[parCnt] =
+					nextNormFreqCopies[indicesMapping[parIndex]];
+			oscillatorNextAmp[parCnt] = nextAmpCopies[indicesMapping[parIndex]];
+		}
+
+		// remove aliasing, skipping partial over nyquist freq
+		if (oscillatorNextNormFreq[parCnt] > nyqNorm) {
+			nyquistCut[parIndex] = true;
+			continue;
+		}
+		nyquistCut[parIndex] = false;
+
+		// first set up freq, cos filter affects amplitude damping according to freq content
+		oscillatorNormFrequencies[parCnt] = oscillatorNextNormFreq[parCnt]; // to fix any possible drifts
+		// save next values, current for next round
+		oscillatorNextNormFreq[parCnt] = (freqMovement
+				* (partials->partialFrequencies[parIndex][localHop]
+						+ freqFixedDeltas[parIndex] * steps) * frequencyScaler
+				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
+				* pitchMultiplier;
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
+				- oscillatorNormFrequencies[parCnt]) / hopCounter;
+		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
+		oscillatorNormFreqDerivatives[parCnt] = freqMovement
+				* oscillatorNormFreqDerivatives[parCnt]
+				+ (1 - freqMovement)
+						* ((oscStatNormFrequenciesMean[parIndex]
+								* pitchMultiplier)
+								- oscillatorNormFrequencies[parCnt])
+						/ hopCounter;
+
+		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
+				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
+
+		// now amplitudes
+		oscillatorAmplitudes[parCnt] = oscillatorNextAmp[parCnt]; // to fix any possible drifts
+		// save next values, current for next round
+		//delta = partials->partialAmplitudes[parIndex][localHop+loopDir] - partials->partialAmplitudes[parIndex][localHop];
+		oscillatorNextAmp[parCnt] =
+				(partials->partialAmplitudes[parIndex][localHop]
+						+ ampFixedDeltas[parIndex] * steps) * parDamp;
+		if(oscillatorNextAmp[parCnt] > 1)
+				oscillatorNextAmp[parCnt] = 1;
+		if ((loopDir == -1) && (localHop = 1) && (currentHopReminder == 1))
+			oscillatorNextAmp[parCnt] = 0;
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
+				- oscillatorAmplitudes[parCnt]) / hopCounter;
+
+		// finally update current mapping between oscillators and partials
+		indicesMapping[parIndex] = parCnt;
+		parCnt++;
+	}
+	actPartNum = parCnt;
+	// [NEON] if not multiple of 4...
+	if (actPartNum % 4 != 0)
+		addFakeOsc();
+}
+
+void OscillatorBank::nextPartialHop() {
+	unsigned int parIndex, localHop;
+	float parDamp = 1;
+	int currentPartialHop = currentHop / overSampling;
+
+	// if going backwards in the loop, get previous frame active partials...
+	actPartNum = partials->activePartialNum[currentPartialHop - loopDirShift];
+	actPart    = partials->activePartials[currentPartialHop - loopDirShift];
+
+	envState = adsr.getState(); // to determine what state we will be in next hop [attack, decay, sustain, release]
+
+	int parCnt = 0;
+	int steps = overSampling - 1; // steps to reach next hop [partial or bank] from previous partial hop
+
+	for (int i = 0; i < actPartNum; i++) {
+		// find partial and frame
+		parIndex = actPart[i];
+		//localHop	= partials->localPartialFrames[currentPartialHop][parIndex];
+		localHop = currentPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
+
+		// if this partial was over nyquist on previous hop...
+		if (nyquistCut[parIndex]) {
+			// ...restart from safe values
+			oscillatorPhases[parCnt] = 0;
+			//TODO add freqmove dependency
+			oscillatorNextNormFreq[parCnt] =
+					(partials->partialFrequencies[parIndex][localHop]
+							+ freqFixedDeltas[parIndex] * steps
+									* (1 - loopDirShift)) * frequencyScaler
+							* prevPitchMultiplier;
+			oscillatorNextAmp[parCnt] = 0;
+		} else if (loopDir == 1) // otherwise recover phase, target freq and target amp from previous frame
+		{
+			if ((localHop != 0) || (overSampling > 1)) {
+				oscillatorPhases[parCnt] =
+						phaseCopies[indicesMapping[parIndex]];
+				oscillatorNextNormFreq[parCnt] =
+						nextNormFreqCopies[indicesMapping[parIndex]];
+				oscillatorNextAmp[parCnt] =
+						nextAmpCopies[indicesMapping[parIndex]];
+			} else // first oscillator hop [both for bank and partial], so no previous data are available
+			{
+				oscillatorPhases[parCnt] = 0;
+				//TODO add freqmove dependency
+				oscillatorNextNormFreq[parCnt] =
+						partials->partialFrequencies[parIndex][localHop]
+								* frequencyScaler * prevPitchMultiplier;
+				parDamp = calculateParDamping(parIndex, prevHopNumTh,
+						prevAdsrVal, oscillatorNextNormFreq[parCnt],
+						prevFilterNum, prevFilterFreqs, prevFilterQ);
+				oscillatorNextAmp[parCnt] =
+						partials->partialAmplitudes[parIndex][localHop]
+								* parDamp;
+				if(oscillatorNextAmp[parCnt] > 1)
+						oscillatorNextAmp[parCnt] = 1;
+				freqFixedDeltas[parIndex] =
+						partials->partialFreqDelta[parIndex][localHop + loopDir]
+								* loopDir / overSampling;
+				ampFixedDeltas[parIndex] =
+						partials->partialAmpDelta[parIndex][localHop + loopDir]
+								* loopDir / overSampling;
+			}
+		} else {
+			if (localHop != partials->partialNumFrames[parIndex] - 1) {
+				oscillatorPhases[parCnt] =
+						phaseCopies[indicesMapping[parIndex]];
+				oscillatorNextNormFreq[parCnt] =
+						nextNormFreqCopies[indicesMapping[parIndex]];
+				oscillatorNextAmp[parCnt] =
+						nextAmpCopies[indicesMapping[parIndex]];
+			} else // first oscillator hop [going backwards - both for bank and partial] , so no previous data are available
+			{
+				oscillatorPhases[parCnt] = 0;
+				//TODO add freqmove dependency
+				oscillatorNextNormFreq[parCnt] =
+						partials->partialFrequencies[parIndex][localHop]
+								* frequencyScaler * prevPitchMultiplier;
+				parDamp = calculateParDamping(parIndex, prevHopNumTh,
+						prevAdsrVal, oscillatorNextNormFreq[parCnt],
+						prevFilterNum, prevFilterFreqs, prevFilterQ);
+				oscillatorNextAmp[parCnt] =
+						partials->partialAmplitudes[parIndex][localHop]
+								* parDamp;
+				if(oscillatorNextAmp[parCnt] > 1)
+						oscillatorNextAmp[parCnt] = 1;
+				freqFixedDeltas[parIndex] =
+						partials->partialFreqDelta[parIndex][localHop + loopDir]
+								* loopDir / overSampling;
+				ampFixedDeltas[parIndex] =
+						partials->partialAmpDelta[parIndex][localHop + loopDir]
+								* loopDir / overSampling;
+			}
+		}
+		// remove aliasing, skipping partial over nyquist freq
+		if (oscillatorNextNormFreq[parCnt] > nyqNorm) {
+			//cout << nyqNorm << endl;
+			nyquistCut[parIndex] = true;
+			continue;
+		}
+		nyquistCut[parIndex] = false;
+
+		// first set up freq, cos filter affects amplitude damping according to freq content
+		oscillatorNormFrequencies[parCnt] = oscillatorNextNormFreq[parCnt]; // to fix any possible drifts
+		// save next values, current for next round
+		oscillatorNextNormFreq[parCnt] = (freqMovement
+				* (partials->partialFrequencies[parIndex][localHop + loopDir]
+						- freqFixedDeltas[parIndex] * steps * loopDirShift)
+				* frequencyScaler
+				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
+				* pitchMultiplier;
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
+				- oscillatorNormFrequencies[parCnt]) / hopCounter;
+		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
+		oscillatorNormFreqDerivatives[parCnt] = freqMovement
+				* oscillatorNormFreqDerivatives[parCnt]
+				+ (1 - freqMovement)
+						* ((oscStatNormFrequenciesMean[parIndex]
+								* pitchMultiplier)
+								- oscillatorNormFrequencies[parCnt])
+						/ hopCounter;
+
+		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
+				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
+
+		// now amplitudes
+		oscillatorAmplitudes[parCnt] = oscillatorNextAmp[parCnt]; // to fix any possible drifts
+		// save next values, current for next round
+		//delta = partials->partialAmplitudes[parIndex][localHop+loopDir] - partials->partialAmplitudes[parIndex][localHop];
+		oscillatorNextAmp[parCnt] =
+				(partials->partialAmplitudes[parIndex][localHop + loopDir]
+						- (ampFixedDeltas[parIndex]) * steps * loopDirShift)
+						* parDamp;
+		if(oscillatorNextAmp[parCnt] > 1)
+			oscillatorNextAmp[parCnt] = 1;
+
+		// to avoid bursts when transients are played backwards
+		if ((loopDir == -1) && (localHop - 1 == 0) && (overSampling == 1)) {
+			oscillatorNextAmp[parCnt] = 0;
+		}
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
+				- oscillatorAmplitudes[parCnt]) / hopCounter;
+
+		// if next is not going to loop boundaries, get next deltas [same direction]
+		if ((((currentPartialHop + loopDir) * overSampling != loopEndHop)
+				|| (loopDir == -1))
+				&& (((currentPartialHop + loopDir) * overSampling + loopDir
+						!= loopStartHop) || (loopDir == 1))) {
+			freqFixedDeltas[parIndex] =
+					partials->partialFreqDelta[parIndex][localHop + loopDir]
+							* loopDir / overSampling;
+			ampFixedDeltas[parIndex] =
+					partials->partialAmpDelta[parIndex][localHop + loopDir]
+							* loopDir / overSampling;
+		} else // .. otherwise, keep deltas but change sign [co swe change direction]
+		{
+			freqFixedDeltas[parIndex] = -freqFixedDeltas[parIndex];
+			ampFixedDeltas[parIndex] = -ampFixedDeltas[parIndex];
+		}
+
+		// finally update current mapping between oscillators and partials
+		indicesMapping[parIndex] = parCnt;
+		parCnt++;
+	}
+	actPartNum = parCnt;
+	// [NEON] if not multiple of 4...
+	if (actPartNum % 4 != 0)
+		addFakeOsc();
+
+	updatePrevControls();
+}
+
+void OscillatorBank::addFakeOsc() {
+	// ...calculate difference
+	int newPartNum = (actPartNum + 3) & ~0x3;
+	// ...add fake oscillators until total num is multiple of 4
+	for (int i = actPartNum; i < newPartNum; i++) {
+		oscillatorAmplitudes[i] = 0;
+		oscillatorNormFrequencies[i] = 0;
+		oscillatorAmplitudeDerivatives[i] = 0;
+		oscillatorNormFreqDerivatives[i] = 0;
+		oscillatorPhases[i] = 0;
+	}
+	// ...and update num of active partials
+	actPartNum = newPartNum;
+}
+
+void OscillatorBank::play(float vel) {
+	// set attack and release params according to velocity
+	//adsr.setAttackRate((minAttackTime + ((1 - vel) * deltaAttackTime)) * rate);
+	adsr.setAttackRate(minAttackTime * rate);
+	//adsr.setReleaseRate((minReleaseTime + (1 - vel) * deltaReleaseTime) * rate);
+	adsr.setReleaseRate(minReleaseTime * rate);
+
+	// set timbre
+	hopNumTh = log((1 - vel) + 1) / log(2) * 20000;
+
+	state = bank_toreset;
+}
+
+//---------------------------------------------------------------------------------------------------------------------------
+// private methods
+//---------------------------------------------------------------------------------------------------------------------------
+
+bool OscillatorBank::loader(char *filename, int hopsize, int samplerate) {
+	rate = samplerate;
+	loaded = parser.parseFile(filename, hopsize, samplerate);
+	return loaded;
+}
+
+int OscillatorBank::jumpToHop() {
+	int jumpGap = abs(jumpHop - currentHop / overSampling); // gaps in partial reference
+
+	// can't jump to self dude
+	if (jumpGap == 0)
+		return 1;
+
+	// direction is in general maintained with jump
+	if (jumpHop == 0)
+		setDirection(1);
+	else if (jumpHop == lastHop)
+		setDirection(-1);
+
+	dbox_printf("\tJump from %d to %d\n", currentHop / overSampling, jumpHop);
+	dbox_printf("\tdirection %d\n", loopDir);
+
+	currentHop = jumpHop * overSampling;
+
+	if (nextEnvState() != 0)
+		return 0; // release has ended!
+
+	checkSpeed();
+
+	int parIndex, localHop, targetHop;
+	float parDamp = 1;
+	int currentPartialHop = currentHop / overSampling;
+	int targetPartialHop = jumpHop;
+
+	actPartNum = partials->activePartialNum[currentPartialHop];
+	actPart = partials->activePartials[currentPartialHop];
+	int targetActParNum = partials->activePartialNum[targetPartialHop];
+	unsigned int *targetActPar = partials->activePartials[targetPartialHop];
+
+	envState = adsr.getState(); // to determine what state we will be in next hop [attack, decay, sustain, release]
+
+	int parCnt = 0;
+	int currentHopReminder = currentHop % overSampling;
+
+	// steps to walk where i am [bank of partial hop] from previous partial hop
+	int steps = currentHopReminder * (overSampling != 1); // no oversampling 0, oversampling and going ff currentHopReminder
+
+	for (int i = 0; i < actPartNum; i++) {
+		// find partial and frame
+		parIndex = actPart[i];
+		//localHop	= partials->localPartialFrames[currentPartialHop][parIndex];
+		localHop = currentPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
+
+		// if this partial was over nyquist on previous hop...
+		if (nyquistCut[parIndex]) {
+			// ...restart from safe values
+			oscillatorPhases[parCnt] = 0;
+			//TODO add freqmove dependency
+			oscillatorNextNormFreq[parCnt] =
+					(partials->partialFrequencies[parIndex][localHop]
+							+ freqFixedDeltas[parIndex] * steps * loopDir)
+							* frequencyScaler * prevPitchMultiplier;
+			oscillatorNextAmp[parCnt] = 0;
+		} else if (loopDir == 1) {// otherwise recover phase, target freq and target amp from previous frame
+			if ((localHop != 0)
+					|| ((overSampling > 1) && (currentHopReminder != 0))) {
+				oscillatorPhases[parCnt] =
+						phaseCopies[indicesMapping[parIndex]];
+				oscillatorNextNormFreq[parCnt] =
+						nextNormFreqCopies[indicesMapping[parIndex]];
+				oscillatorNextAmp[parCnt] =
+						nextAmpCopies[indicesMapping[parIndex]];
+			} else { // first oscillator hop [both for bank and partial], so no previous data are available
+				oscillatorPhases[parCnt] = 0;
+				//TODO add freqmove dependency
+				oscillatorNextNormFreq[parCnt] =
+						partials->partialFrequencies[parIndex][localHop]
+								* frequencyScaler * prevPitchMultiplier;
+				parDamp = calculateParDamping(parIndex, prevHopNumTh,
+						prevAdsrVal, oscillatorNextNormFreq[parCnt],
+						prevFilterNum, prevFilterFreqs, prevFilterQ);
+				oscillatorNextAmp[parCnt] =
+						partials->partialAmplitudes[parIndex][localHop]
+								* parDamp;
+				if(oscillatorNextAmp[parCnt] > 1)
+						oscillatorNextAmp[parCnt] = 1;
+			}
+		} else {
+			if (( (unsigned)localHop != partials->partialNumFrames[parIndex] - 1)
+					|| ((overSampling > 1) && (currentHopReminder != 0))) {
+				oscillatorPhases[parCnt] =
+						phaseCopies[indicesMapping[parIndex]];
+				oscillatorNextNormFreq[parCnt] =
+						nextNormFreqCopies[indicesMapping[parIndex]];
+				oscillatorNextAmp[parCnt] =
+						nextAmpCopies[indicesMapping[parIndex]];
+			} else // first oscillator hop [going backwards - both for bank and partial] , so no previous data are available, so retrieve where i am
+			{
+				oscillatorPhases[parCnt] = 0;
+				//TODO add freqmove dependency
+				oscillatorNextNormFreq[parCnt] =
+						partials->partialFrequencies[parIndex][localHop]
+								* frequencyScaler * prevPitchMultiplier;
+				parDamp = calculateParDamping(parIndex, prevHopNumTh,
+						prevAdsrVal, oscillatorNextNormFreq[parCnt],
+						prevFilterNum, prevFilterFreqs, prevFilterQ);
+				oscillatorNextAmp[parCnt] =
+						partials->partialAmplitudes[parIndex][localHop]
+								* parDamp;
+				if(oscillatorNextAmp[parCnt] > 1)
+						oscillatorNextAmp[parCnt] = 1;
+			}
+		}
+		// remove aliasing, skipping partial over nyquist freq
+		if (oscillatorNextNormFreq[parCnt] > nyqNorm) {
+			//cout << nyqNorm << endl;
+			nyquistCut[parIndex] = true;
+			continue;
+		}
+		nyquistCut[parIndex] = false;
+
+		// check what happens of this partial at target hop
+		float targetFreqVal, targetAmpVal;
+		//targetHop = partials->localPartialFrames[targetPartialHop][parIndex];
+		targetHop = targetPartialHop - partials->partialStartFrame[parIndex];
+
+		if (targetHop == -1)
+			targetFreqVal = targetAmpVal = 0;
+		else {
+			targetFreqVal = partials->partialFrequencies[parIndex][targetHop]
+					* frequencyScaler; // pitch shift will be multiplied later!!!
+			targetAmpVal = partials->partialFrequencies[parIndex][targetHop]; // parDamp will be multiplied later!!!
+		}
+
+		// first set up freq, cos filter affects amplitude damping according to freq content
+		oscillatorNormFrequencies[parCnt] = oscillatorNextNormFreq[parCnt]; // to fix any possible drifts
+		// save next values, current for next round
+		oscillatorNextNormFreq[parCnt] = (freqMovement * targetFreqVal
+				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
+				* pitchMultiplier;
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
+				- oscillatorNormFrequencies[parCnt]) / hopCounter;
+		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
+		oscillatorNormFreqDerivatives[parCnt] = freqMovement
+				* oscillatorNormFreqDerivatives[parCnt]
+				+ (1 - freqMovement)
+						* ((oscStatNormFrequenciesMean[parIndex]
+								* pitchMultiplier)
+								- oscillatorNormFrequencies[parCnt])
+						/ hopCounter;
+
+		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
+				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
+
+		// now amplitudes
+		oscillatorAmplitudes[parCnt] = oscillatorNextAmp[parCnt]; // to fix any possible drifts
+		// save next values, current for next round
+		oscillatorNextAmp[parCnt] = targetAmpVal * parDamp;
+		if(oscillatorNextAmp[parCnt] > 1)
+				oscillatorNextAmp[parCnt] = 1;
+		// to avoid bursts when transients are played backwards
+		if ((loopDir == -1) && (targetHop == 0)
+				&& ((overSampling == 1) || (currentHopReminder == 0))) {
+			oscillatorNextAmp[parCnt] = 0;
+		}
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
+				- oscillatorAmplitudes[parCnt]) / hopCounter;
+
+		//if partial does not die at target, calculate deltas according to direction
+		if (targetHop != -1) {
+			freqFixedDeltas[parIndex] =
+					partials->partialFreqDelta[parIndex][targetHop] * loopDir
+							/ overSampling;
+			ampFixedDeltas[parIndex] =
+					partials->partialAmpDelta[parIndex][targetHop] * loopDir
+							/ overSampling;
+		}
+
+		// finally update current mapping between oscillators and partials
+		indicesMapping[parIndex] = parCnt;
+		parCnt++;
+	}
+	actPartNum = parCnt;
+
+	// now add the ones that start at target hop!
+	for (int i = 0; i < targetActParNum; i++) {
+		// find partial and frame
+		parIndex = targetActPar[i];
+		//targetHop	= partials->localPartialFrames[targetPartialHop][parIndex];
+		targetHop = targetPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
+
+		// check if this partials was already active before the jump
+		//localHop = partials->localPartialFrames[currentPartialHop][parIndex];
+		localHop = currentPartialHop - partials->partialStartFrame[parIndex];
+
+		// if yes, skip it
+		if (localHop != -1)
+			continue;
+
+		// otherwise add it to active bunch and calcucalte values
+
+		// first set up freq, cos filter affects amplitude damping according to freq content
+		oscillatorNormFrequencies[parCnt] = 0;
+		// save next values, current for next round
+		oscillatorNextNormFreq[parCnt] = (freqMovement
+				* partials->partialFrequencies[parIndex][targetHop]
+				* frequencyScaler
+				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
+				* pitchMultiplier;
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
+				- oscillatorNormFrequencies[parCnt]) / hopCounter;
+		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
+		oscillatorNormFreqDerivatives[parCnt] = freqMovement
+				* oscillatorNormFreqDerivatives[parCnt]
+				+ (1 - freqMovement)
+						* ((oscStatNormFrequenciesMean[parIndex]
+								* pitchMultiplier)
+								- oscillatorNormFrequencies[parCnt])
+						/ hopCounter;
+
+		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
+				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
+
+		// now amplitudes
+		oscillatorAmplitudes[parCnt] = 0;
+		// save next values, current for next round
+		oscillatorNextAmp[parCnt] =
+				partials->partialFrequencies[parIndex][targetHop] * parDamp;
+		if(oscillatorNextAmp[parCnt] > 1)
+				oscillatorNextAmp[parCnt] = 1;
+		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
+		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
+				- oscillatorAmplitudes[parCnt]) / hopCounter;
+
+		//calculate deltas according to direction
+		freqFixedDeltas[parIndex] =
+				partials->partialFreqDelta[parIndex][targetHop] * loopDir
+						/ overSampling;
+		ampFixedDeltas[parIndex] =
+				partials->partialAmpDelta[parIndex][targetHop] * loopDir
+						/ overSampling;
+
+		// finally update current mapping between oscillators and partials
+		indicesMapping[parIndex] = parCnt;
+		parCnt++;
+
+	}
+	// [NEON] if not multiple of 4...
+	if (actPartNum % 4 != 0)
+		addFakeOsc();
+
+	updatePrevControls();
+
+	jumpHop = -1;
+
+	return 0;
+}
+
+int OscillatorBank::nextEnvState() {
+	/*
+	 envState = Attack.getState();	// to determine what state we are in [attack, decay, sustain, release]
+
+	 // osc bank is playing the tail and the tail ends...
+	 if( (state == bank_playing)&&(envState == env_idle) )
+	 {
+	 state = bank_stopped;	// ...stop bank
+	 return 1;					// and return immediately
+	 }
+	 else if( (envState == env_attack) || (envState == env_decay) )
+	 {
+	 // run envelopes until next frame
+	 dampWeight	= Attack.process(hopSize);
+	 }
+	 else if(envState == env_release)
+	 {
+	 // run envelopes until next frame
+	 dampWeight 	= Attack.process(hopSize);
+	 releaseDamp = Release.process(hopSize);
+	 }*/
+
+	envState = adsr.getState();
+	// osc bank is playing the tail and the tail ends...
+	if ((state == bank_playing) && (envState == env_idle)) {
+		state = bank_stopped; // ...stop bank
+		adsrVal = 0;
+		return 1; // and return immediately
+	} else
+		adsrVal = adsr.process(hopSize);
+
+	return 0;
+}
+
+void OscillatorBank::checkDirection() {
+	// end of the loop or end of file
+	if (((currentHop >= loopEndHop) && (loopDir == 1))
+			|| ((currentHop >= lastHop) && (loopDir == 1))) {
+		// move backwards
+		setDirection(-1);
+		//dbox_printf("backward from %d\n", loopEndHop);
+	} else if (((currentHop <= loopStartHop) && (loopDir == -1))
+			|| ((currentHop <= 0) && (loopDir == -1))) // start of the loop or start of file
+			{
+		// move forward
+		setDirection(1);
+		//dbox_printf("forward from %d\n", loopStartHop);
+	}
+}
+
+void OscillatorBank::checkSpeed() {
+	// speed control [alike on highways, LOL]
+	if (nextSpeed > 0) {
+		nextSpeed = (nextSpeed < maxSpeed) ? nextSpeed : maxSpeed;
+		nextSpeed = (nextSpeed > minSpeed) ? nextSpeed : minSpeed;
+		speed = nextSpeed;
+		nextSpeed = -1;
+	}
+	hopCounter = hopSize / speed;
+}
+
+int OscillatorBank::checkJump() {
+	//check if has to jump somewhere
+	if (jumpHop > -1) {
+		// needs to jump!
+		if (jumpToHop() == 0)
+			return 0;
+	}
+	return 1; // no jump
+}
+
+bool OscillatorBank::checkOversampling() {
+	//TODO fix this, but need andrew to fix oversampling multiple of period size
+	// if partialsHopSize is not a multiple of oversampling, change hop size to periodically match next partial hop
+	if (hopSizeReminder > 0) {
+		// if next osc bank hop overtakes next partial hop...
+		if ((currentHop + loopDir) * hopSize > partialsHopSize) {
+			hopSize = hopSizeReminder; // ...shrink osc bank hop size to match partial hop
+			return true; // and set next hop as matching with next partial hop
+		}
+	} else if (((currentHop + (1 - loopDirShift)) % overSampling) == 0) // if next osc bank hop matches next partial hop
+		return true; // ...mark next hop as partial hop
+
+	return false; // ,otherwise mark next hop as osc bank hop
+}
+
+void OscillatorBank::updatePrevControls() {
+	prevAdsrVal = adsrVal;
+	prevAmpTh = ampTh;
+	prevHopNumTh = hopNumTh;
+	prevPitchMultiplier = pitchMultiplier;
+	prevFreqMovement = freqMovement;
+	prevFilterNum = filterNum;
+	memcpy(prevFilterFreqs, filterFreqs, filterNum * sizeof(float));
+	memcpy(prevFilterQ, filterQ, filterNum * sizeof(float));
+}
+
+float OscillatorBank::calculateParDamping(int parIndex, int hopNTh,
+		float adsrVl, float nextFreq, int filNum, float *filFreq, float *filQ) {
+	float parDamp = 1;
+
+	// timbre
+	parDamp = ((float) (oscStatNumHops[parIndex] + 1)) / (hopNTh + 1);
+	parDamp = (parDamp > 1) ? 1 : parDamp;
+	parDamp = adsrVl * parDamp;
+
+	//filters
+
+	float filterWeights[MAX_TOUCHES];
+	float filterDamp[MAX_TOUCHES];
+	float filDist;
+	float filterWeightsAcc;
+	float filDmp;
+	float filAmp;
+
+// 		band reject notch filter
+//		float dist, dmp;
+//		for(int k=0; k<filterNum; k++)
+//		{
+//			dist = fabs(oscillatorNextNormFreq[parCnt]-filterFreqs[k]);
+//			if(dist<=filterQ[k])
+//			{
+//				dmp 	= dist/filterQ[k];
+//				parDamp *= dmp*dmp*dmp;
+//			}
+//		}
+
+
+	// each filter is a band pass notch filter
+
+	// if at least one is active
+	if (filNum > 0) {
+		// reset values
+		filDist = 0;
+		filterWeightsAcc = 0;
+		filDmp = 0;
+		filAmp = 0;
+		// for each filter
+		for (int k = 0; k < filNum; k++) {
+			// here are a couple of kludges to boost sound output of hi freq filters
+
+			// damping effect of filter increases with distance, but decreases with filter frequency [kludge]
+			float mul = ((filterMaxF-nextFreq)/filterMaxF) * 0.9 + 0.1 ;
+			//filDist = fabs(nextFreq - filFreq[k])*( ((exp(a*4)-1)/EXP_DENOM) * 0.9 + 0.1 );
+			filDist = fabs(nextFreq - filFreq[k])*mul;
+
+			// these to merge all filters contributions according to distance
+			filterWeights[k] = filterMaxF - filDist;
+			filterWeightsAcc += filterWeights[k];
+			// freqs very close to filter center are slightly amplified
+			// the size of this amp area and the effect of amplification increase with frequency [kludge]
+			if (filDist
+					< filterAmpMinF
+							+ (filterAmpMaxF*(1-mul) - filterAmpMinF) * (1 - filQ[k]) )
+				filAmp = filQ[k] * filterAmpMul*(1-mul);
+			else
+				filAmp = 0;
+			// actual damping
+			filDmp = 1 / (filDist * filQ[k]);
+			filDmp = (filDmp > 1) ? 1 : filDmp;
+			// sum damp+amplification
+			filterDamp[k] = filDmp + filAmp;
+		}
+		// do weighted mean to merge all filters contributions
+		filDmp = 0;
+		for (int k = 0; k < filNum; k++)
+			filDmp += filterDamp[k] * filterWeights[k];
+		filDmp /= filterWeightsAcc;
+		// apply
+		parDamp *= filDmp;
+	}
+
+
+	return parDamp;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/OscillatorBank.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,240 @@
+/*
+ * OscillatorBank.h
+ *
+ *  Created on: May 23, 2014
+ *      Author: Victor Zappi and Andrew McPherson
+ */
+
+#ifndef OSCILLATORBANK_H_
+#define OSCILLATORBANK_H_
+
+
+#include <string>
+
+#include "spear_parser.h"
+#include "ADSR.h"
+#include "config.h"
+
+using namespace std;
+
+enum OscBankstates {bank_stopped, bank_playing, bank_toreset};
+
+class OscillatorBank
+{
+public:
+	OscillatorBank();
+	OscillatorBank(string filename, int hopsize=-1, int samplerate=44100);
+	OscillatorBank(char *filename, int hopsize=-1, int samplerate=44100);
+	~OscillatorBank();
+	float *oscillatorPhases;
+	float *oscillatorNormFrequencies;
+	float *oscillatorNormFreqDerivatives;
+	float *oscillatorAmplitudes;
+	float *oscillatorAmplitudeDerivatives;
+	float *oscStatNormFrequenciesMean;
+	float *oscStatNumHops;
+	OscBankstates state;
+	bool note;
+	int actPartNum;
+	unsigned int *actPart;
+	int hopCounter;
+	int lookupTableSize;
+	float *lookupTable;
+	float ampTh;
+	int hopNumTh;
+	float pitchMultiplier;
+	float freqMovement;
+	int filterNum;
+	float filterFreqs[5];
+	float filterQ[5];
+	float filterMaxF;
+	float filterAmpMinF;
+	float filterAmpMaxF;
+	float filterAmpMul;
+
+	bool loadFile(string filename, int hopsize=-1, int samplerate=44100);
+	bool loadFile(char *filename, int hopsize=-1, int samplerate=44100);
+	bool initBank(int oversamp=1);
+	void resetOscillators();
+	int getHopSize() { return hopSize; }
+	void nextHop();
+	void setLoopHops(int start, int end);
+	void play(float vel);
+	void stop();
+	void afterTouch(float vel);
+	int getEnvelopeState();
+	float getFrequencyScaler();
+	void setSpeed(float sp);
+	float getSpeed();
+	float getMaxSpeed();
+	float getMinSpeed();
+	void setJumpHop(int hop);
+	int getLastHop();
+	int getCurrentHop() { return currentHop; }
+
+private:
+
+	bool loaded;
+	int numOfPartials;
+	int numOfOscillators;
+	int partialsHopSize;
+	int overSampling;
+	int hopSize;
+	int hopSizeReminder;
+	int oscBankHopSize;
+	float frequencyScaler;
+	float nyqNorm;
+	int lastHop;
+	int currentHop;
+	int	loopDir;
+	int loopDirShift;
+	int loopStartHop;
+	int loopEndHop;
+	int *indicesMapping;
+	float *phaseCopies;
+	float *oscillatorNextNormFreq;
+	float *oscillatorNextAmp;
+	float *nextNormFreqCopies;
+	float *nextAmpCopies;
+	float *freqFixedDeltas;
+	float *ampFixedDeltas;
+	bool *nyquistCut;
+	Spear_parser parser;
+	Partials *partials;
+	ADSR adsr;
+	float minAttackTime;
+	float deltaAttackTime;
+	float minReleaseTime;
+	float deltaReleaseTime;
+	int envState;
+	int rate;
+	float speed;
+	float nextSpeed;
+	float maxSpeed;
+	float minSpeed;
+	int jumpHop;
+	float adsrVal;
+	float prevAdsrVal;
+	float prevAmpTh;
+	int prevHopNumTh;
+	float prevPitchMultiplier;
+	float prevFreqMovement;
+	int prevFilterNum;
+	float prevFilterFreqs[5];
+	float prevFilterQ[5];
+
+	bool loader(char *filename, int hopsize=-1, int samplerate=44100);
+	void addFakeOsc();
+	void nextOscBankHop();
+	void nextPartialHop();
+	int jumpToHop();
+	void setDirection(int dir);
+	int nextEnvState();
+	void checkDirection();
+	void checkSpeed();
+	int checkJump();
+	bool checkOversampling();
+	void updatePrevControls();
+	float calculateParDamping(int parIndex, int hopNTh, float adsrVl, float nextFreq,
+							  int filNum, float *filFreq, float *filQ);
+};
+
+inline bool OscillatorBank::loadFile(string filename, int hopsize, int samplerate)
+{
+	return loader((char *)filename.c_str(), hopsize, samplerate);
+}
+
+inline bool OscillatorBank::loadFile(char *filename, int hopsize, int samplerate)
+{
+	return loader(filename, hopsize, samplerate);
+}
+
+inline void OscillatorBank::setLoopHops(int start, int end)
+{
+	if(start > end)
+		end = start;
+
+	if(start<0)
+		start = 0;
+	else if(start>lastHop)
+		start = 0;
+	if(end < 1)
+		end = 1;
+	end = (end<=lastHop) ? end : lastHop;
+
+	// set it, take into consideration hop oversampling
+	loopStartHop = start*overSampling;
+	loopEndHop	 = end*overSampling;
+}
+
+inline void OscillatorBank::stop()
+{
+	note = false;
+	adsr.gate(0);
+}
+
+inline float OscillatorBank::getFrequencyScaler()
+{
+	return frequencyScaler;
+}
+
+inline void OscillatorBank::afterTouch(float vel)
+{
+	hopNumTh = log((1-vel)+1)/log(2)*20000;
+	if(adsr.getState()==env_attack)
+		adsr.setAttackRate( (minAttackTime + ( (1-vel)*deltaAttackTime )) * rate );
+	adsr.setReleaseRate( (minReleaseTime+(1-vel)*deltaReleaseTime)* rate );
+}
+
+inline int OscillatorBank::getEnvelopeState()
+{
+	return envState;
+}
+
+inline void OscillatorBank::setSpeed(float sp)
+{
+	nextSpeed = sp;
+}
+
+inline float OscillatorBank::getSpeed()
+{
+	return speed;
+}
+
+inline float OscillatorBank::getMaxSpeed()
+{
+	return maxSpeed;
+}
+
+inline float OscillatorBank::getMinSpeed()
+{
+	return minSpeed;
+}
+
+inline void OscillatorBank::setJumpHop(int hop)
+{
+	if(hop<0)
+		return;
+	hop = (hop<=lastHop) ? hop : lastHop;
+	jumpHop = hop;
+}
+
+inline void OscillatorBank::setDirection(int dir)
+{
+	if(dir>=0)
+	{
+		loopDir			= 1;
+		loopDirShift	= 0;
+	}
+	else
+	{
+		loopDir			= -1;
+		loopDirShift	= 1;
+	}
+}
+
+inline int OscillatorBank::getLastHop()
+{
+	return lastHop;
+}
+#endif /* OSCILLATORBANK_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/PinkNoise.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,16 @@
+/*
+ * PinkNoise.cpp
+ *
+ *  Created on: Oct 15, 2013
+ *      Author: Victor Zappi
+ */
+
+#include "PinkNoise.h"
+
+// miserable definition to init static const array members...otherwise gets error when PinkNoise.h is included into another header file
+const float PinkNoise::A[] = { 0.02109238, 0.07113478, 0.68873558 }; // rescaled by (1+P)/(1-P)
+const float PinkNoise::P[] = { 0.3190,  0.7756,  0.9613  };
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/PinkNoise.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,49 @@
+#ifndef _PinkNoise_H
+#define _PinkNoise_H
+
+// Technique by Larry "RidgeRat" Trammell 3/2006
+// http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
+// implementation and optimization by David Lowenfels
+
+#include <cstdlib>
+#include <ctime>
+#include <stdlib.h>
+
+#define PINK_NOISE_NUM_STAGES 3
+
+class PinkNoise {
+public:
+  PinkNoise() {
+  srand ( time(NULL) ); // initialize random generator
+    clear();
+  }
+
+  void clear() {
+    for( size_t i=0; i< PINK_NOISE_NUM_STAGES; i++ )
+      state[ i ] = 0.0;
+    }
+
+  float tick() {
+    static const float RMI2 = 2.0 / float(RAND_MAX); // + 1.0; // change for range [0,1)
+    static const float offset = A[0] + A[1] + A[2];
+
+  // unrolled loop
+    float temp = float( rand() );
+    state[0] = P[0] * (state[0] - temp) + temp;
+    temp = float( rand() );
+    state[1] = P[1] * (state[1] - temp) + temp;
+    temp = float( rand() );
+    state[2] = P[2] * (state[2] - temp) + temp;
+    return ( A[0]*state[0] + A[1]*state[1] + A[2]*state[2] )*RMI2 - offset;
+  }
+
+protected:
+  float state[ PINK_NOISE_NUM_STAGES ];
+  static const float A[ PINK_NOISE_NUM_STAGES ];
+  static const float P[ PINK_NOISE_NUM_STAGES ];
+};
+
+//const float PinkNoise::A[] = { 0.02109238, 0.07113478, 0.68873558 }; // rescaled by (1+P)/(1-P)
+//const float PinkNoise::P[] = { 0.3190,  0.7756,  0.9613  };
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/StatusLED.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,90 @@
+/*
+ * StatusLED.cpp
+ *
+ * Routines for manipulating the status LED
+ *
+ * (c) 2014 Andrew McPherson and Victor Zappi
+ * QMUL, Centre for Digital Music
+ */
+
+#include <iostream>
+#include "StatusLED.h"
+#include <GPIOcontrol.h>
+
+extern int gShouldStop;
+extern int gVerbose;
+
+using namespace std;
+
+StatusLED::StatusLED() {
+	gpio_number = -1;
+	milliseconds_on = 0;
+	milliseconds_off = 100;
+	blink_thread = -1;
+}
+
+StatusLED::~StatusLED() {
+	if(gpio_number >= 0) {
+		this_should_stop = true;
+		pthread_join(blink_thread, NULL);
+		gpio_unexport(gpio_number);
+	}
+}
+
+bool StatusLED::init(int gpio_pin) {
+	gpio_number = gpio_pin;
+	this_should_stop = false;
+
+	if(gpio_export(gpio_number)) {
+		if(gVerbose)
+			cout << "Warning: couldn't export status LED pin\n";
+	}
+	if(gpio_set_dir(gpio_number, OUTPUT_PIN)) {
+		if(gVerbose)
+			cout << "Couldn't set direction on status LED pin\n";
+		return false;
+	}
+	if(gpio_set_value(gpio_number, LOW)) {
+		if(gVerbose)
+			cout << "Couldn't set value on status LED pin\n";
+		return false;
+	}
+
+
+	if ( pthread_create(&blink_thread, NULL, static_blink_loop, this) )
+	{
+		cout << "Error:unable to create status LED thread" << endl;
+		return false;
+	}
+
+	return true;
+}
+
+void StatusLED::on() {
+	milliseconds_on = 100;
+	milliseconds_off = 0;
+}
+
+void StatusLED::off() {
+	milliseconds_on = 0;
+	milliseconds_off = 100;
+}
+
+void StatusLED::blink(int ms_on, int ms_off) {
+	milliseconds_on = ms_on;
+	milliseconds_off = ms_off;
+}
+
+void* StatusLED::blink_loop(void *) {
+	while(!gShouldStop && !this_should_stop) {
+		if(milliseconds_on != 0)
+			gpio_set_value(gpio_number, HIGH);
+		usleep(1000 * milliseconds_on);
+		if(gShouldStop)
+			break;
+		if(milliseconds_off != 0)
+			gpio_set_value(gpio_number, LOW);
+		usleep(1000 * milliseconds_off);
+	}
+	pthread_exit(NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/StatusLED.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,39 @@
+/*
+ * StatusLED.h
+ *
+ *
+ */
+
+#ifndef STATUSLED_H_
+#define STATUSLED_H_
+
+#include <pthread.h>
+#include <unistd.h>
+
+class StatusLED
+{
+public:
+	StatusLED();
+	~StatusLED();
+
+	bool init(int gpio_pin);
+
+	void on();
+	void off();
+	void blink(int ms_on, int ms_off);
+
+	static void *static_blink_loop(void *data) {
+		((StatusLED*)data)->blink_loop(NULL);
+		return 0;
+	}
+
+	void* blink_loop(void *);
+
+private:
+	int gpio_number;
+	int milliseconds_on, milliseconds_off;
+	bool this_should_stop;
+	pthread_t blink_thread;
+};
+
+#endif // STATUSLED_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/audio_routines.S	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,185 @@
+@
+@ audio_routines.S
+@
+@ NEON-based functions for time-critical audio processing
+@
+@ Andrew McPherson 2014
+@ Queen Mary University of London
+@
+
+	.syntax unified
+	.arch armv7-a
+	.fpu neon
+
+@ 	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
+@							  int activePartialNum, int lookupTableSize,
+@							  float *phases, float *frequencies, float *amplitudes,
+@							  float *freqDerivatives, float *ampDerivatives,
+@							  float *lookupTable);
+
+@ Registers:
+@    r0: numAudioFrames        How many frames to render
+@    r1: audioOut              Buffer for audio output samples [stereo]
+@    r2: activePartialNum      How many active partials to render
+@    r3: lookupTableSize       Size of lookup table
+@    ---- other arguments start on the stack and are moved: -----
+@    r4: phases                Phase of each oscillator (pointer)
+@    r5: frequencies           Normalised frequency of each oscillator (pointer)
+@    r6: amplitudes            Normalised amplitude of each oscillator (pointer)
+@    r7: freqDerivatives       Derivative of frequency for each oscillator (pointer)
+@    r8: ampDerivatives        Derivative of amplitude for each oscillator (pointer)
+@    r9: lookupTable           Lookup table containing one oscillation
+@
+@ Alignment requirements:
+@    audioOut: 8-byte boundary
+@    phases: 16-byte boundary
+@    frequencies: 16-byte boundary
+@    amplitudes: 16-byte boundary
+@    freqDerivatives: 16-byte bounary
+@    ampDerivatives: 16-byte boundary
+@    lookupTable: 4-byte boundary (TODO: check this)
+
+	.align	2
+	.global	oscillator_bank_neon
+	.thumb
+	.thumb_func
+	.type	oscillator_bank_neon, %function
+oscillator_bank_neon:
+
+
+dSample		.dn		D6.F32
+qPhases		.qn		Q8.F32
+dPhases_0	.dn		D16.F32
+dPhases_1	.dn		D17.F32
+qFreqs		.qn		Q9.F32
+dFreqs_0	.dn		D18.F32
+dFreqs_1	.dn		D19.F32
+qAmps		.qn		Q10.F32
+dAmps_0		.dn		D20.F32
+dAmps_1		.dn		D21.F32
+qFreqDs		.qn		Q11.F32
+dFreqDs_0	.dn		D22.F32
+dFreqDs_1	.dn		D23.F32
+qAmpDs		.qn		Q12.F32
+dAmpDs_0	.dn		D24.F32
+dAmpDs_1	.dn		D25.F32
+
+qBaseInts	.qn		Q13.U32		@ Base indexes: unsigned ints x4
+dBaseInts_0	.dn		D26.U32
+dBaseInts_1	.dn		D27.U32
+qFractions  .qn     Q14.F32		@ Fraction indexes: floats x4
+qTableBase	.qn		Q15.U32		@ Base of lookup table
+
+	cmp r0, #0					@ Check for trivial case 1: zero frames
+	it eq
+	bxeq lr						@ Return if that's the case (otherwise might have odd behaviour)
+	cmp r2, #4					@ Check for trivial case 2: zero oscillators
+	it lt
+	bxlt lr						@ Return if that's the case
+
+	push {r4-r11}				@ Now arguments start 32 bytes above SP
+    add r11, sp, #32			@ Pointer to 32 bytes into the stack
+    ldm r11, {r4-r9}			@ Load 6 arguments into registers
+
+	vdup qTableBase, r9			@ Move lookup table base index into 4 ints
+
+	@ Outer loop: iterate over the number of oscillators, choosing 4 at a
+	@ time to work with.
+oscbank_oscillator_loop:
+	vld1 {dPhases_0, dPhases_1}, [r4]		@ no increment; will store at end of sample loop
+	vld1 {dFreqs_0, dFreqs_1}, [r5]
+	vld1 {dAmps_0, dAmps_1}, [r6]
+	vld1 {dFreqDs_0, dFreqDs_1}, [r7]!		@ increment; won't update at end of sample loop
+	vld1 {dAmpDs_0, dAmpDs_1}, [r8]!
+
+	push {r0-r1,r4-r8}
+	@ --- inner loop: iterate over the number of samples ---
+oscbank_sample_loop:
+	vcvt qBaseInts, qPhases		     		@ Take floor(phases)
+	vmov q2.f32, #1.0						@ Load 1.0 into every slot of q2
+	vshl q0.U32, qBaseInts, #2				@ Shift the indexes left 2 (*4 for float addressing)
+	vcvt qFractions, qBaseInts				@ int back to float
+	vadd q0.U32, q0.U32, qTableBase			@ Find memory addresses
+
+	vmov r4, r5, d0							@ Move two indexes to ARM registers
+	vmov r6, r7, d1							@ Move two more indexes to ARM registers
+	vsub qFractions, qPhases, qFractions	@ fraction = phase - floor(phase)
+
+	vldr.64	d0, [r4]						@ Load two consecutive floats at each location
+	vldr.64 d1, [r5]						@ These hold the previous and following samples in the table
+	vldr.64	d2, [r6]						@ TODO: check whether these work at 4-byte alignment
+	vldr.64 d3, [r7]
+
+	@ Format at this point:
+	@ Osc0(before) Osc0(after) Osc1(before) Osc1(after) Osc2(before) Osc2(after) Osc3(before) Osc3(after)
+	@ We want:
+	@ Osc0(before) Osc1(before) Osc2(before) Osc3(before) Osc0(after) Osc1(after) Osc2(after) Osc3(after)
+
+	vuzp.32 q0, q1							@ Now q0 contains before, q1 contains after
+	vsub q2.f32, q2.f32, qFractions			@ q2 = 1.0 - fraction
+	vmul q1.f32, q1.f32, qFractions			@ q1 = fraction * after
+	vmul q0.f32, q0.f32, q2.f32				@ q0 = (1.0 - fraction) * before
+
+	vadd qPhases, qPhases, qFreqs			@ Update phases
+	vadd qFreqs, qFreqs, qFreqDs			@ Update frequencies
+
+	vadd q0.f32, q0.f32, q1.f32				@ Add two interpolated components to get the final sample
+	vdup q2.u32, r3							@ Put lookup table size into each element of q2
+	vcvt qBaseInts, qPhases					@ Take floor of new phases
+	vmul q0.f32, q0.f32, qAmps				@ Multiply samples by current amplitude
+
+	vld1 dSample, [r1]						@ Load the current stereo samples
+	vpadd d2.f32, d0.f32, d1.f32			@ Pairwise accumulate q0 (output sample) into d2
+
+	vand q2, q2, qBaseInts					@ Logical AND of new phase int leaves 1 bit set only if phase >= table size
+	vpadd d3.f32, d2.f32, d2.f32			@ Pairwise accumulate d2 into d0 --> d0[0] and d0[1] both hold total of 4 oscillators
+	vadd qAmps, qAmps, qAmpDs				@ Update amplitudes
+	vcvt q0.f32, q2.u32						@ Convert int back to float after AND operation
+
+	vadd  dSample, dSample, d3.f32			@ Add oscillator outputs to each channel
+
+	subs r0, r0, #1							@ numFrames--
+	vsub qPhases, qPhases, q0.f32			@ Keep phases in table range
+	vst1 dSample, [r1]!						@ Store back in buffer and increment by 8
+
+	it gt
+	bgt oscbank_sample_loop					@ Loop if numFrames > 0
+
+	@ --- end inner loop ---
+	pop {r0-r1,r4-r8}						@ Restore registers: restores audioOut and numFrames, among others
+
+	vst1 {dPhases_0, dPhases_1}, [r4]!		@ Store phases back to array
+	vst1 {dFreqs_0, dFreqs_1}, [r5]!		@ Store frequencies back to array
+	vst1 {dAmps_0, dAmps_1}, [r6]!			@ Store amplitudes back to array
+											@ No need to update r7, r8
+
+	subs r2, r2, #4							@ numPartials -= 4
+	it  gt
+	bgt oscbank_oscillator_loop	@ Loop if numPartials > 0
+
+    pop {r4-r11}
+	bx lr
+
+
+@   void wavetable_interpolate_neon(int numSamplesIn, int numSamplesOut,
+@                              float *tableIn, float *tableOut);
+
+@ Registers:
+@    r0: numSamplesIn          Size of the input table
+@    r1: numSamplesOut         Size of the output table
+@    r2: tableIn               Pointer to input table
+@    r3: tableOut              Pointer to output table
+
+@ Alignment requirements:
+@    tableIn: 8-byte boundary
+@    tableOut: 8-byte boundary
+
+	.align	2
+	.global	wavetable_interpolate_neon
+	.thumb
+	.thumb_func
+	.type	wavetable_interpolate_neon, %function
+wavetable_interpolate_neon:
+    @ TODO
+
+    bx lr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/config.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,43 @@
+/*
+ * config.h
+ *
+ * Global settings for D-Box project
+ *
+ * Andrew McPherson and Victor Zappi 2014
+ */
+
+
+#ifndef DBOX_CONFIG_H_
+#define DBOX_CONFIG_H_
+
+
+/* Number of maximum touches used by the TouchKey sensors */
+#define MAX_TOUCHES 5
+
+// for sensor 1 filter
+#define EXP_DENOM 53.5981500331			// exp(4)-1
+
+/* Define this to use Xenomai real-time extensions */
+#define DBOX_USE_XENOMAI
+//#define OLD_OSCBANK
+
+#ifdef DBOX_USE_XENOMAI
+// Xenomai-specific includes
+#include <sys/mman.h>
+
+#include <native/task.h>
+#include <native/timer.h>
+#include <rtdk.h>
+#endif
+
+#ifdef DBOX_USE_XENOMAI
+
+#define dbox_printf rt_printf
+
+#else
+
+#define dbox_printf printf
+
+#endif
+
+#endif /* DBOX_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/how_to_build_dbox.txt	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,35 @@
+The D-Box code can be built on the board using the scripts included with
+Bela. To build the code, do the following from the scripts/ directory:
+
+./setup_board.sh    # Only if Bela is not already copied to the board
+./build_project.sh -n ../projects/d-box  # -n means don't run yet
+
+You will now need to copy the .dbx sound files to the box. These need to
+be in a directory: /root/d-box/sounds
+
+Log into the board via ssh to create the d-box directory, or run:
+
+ssh root@192.168.7.2 "mkdir /root/d-box"
+
+Now copy the .dbx files from a source of your choice to the board. Assuming
+they are in a directory called "sounds":
+
+scp -r sounds root@192.168.7.2:/root/d-box/
+
+Now you can run the D-Box program to make sure it plays. You will need the
+sensors and matrix connected to the box (i.e. a complete hardware D-Box).
+From the scripts/ directory:
+
+./run_project.sh -f -c "-q 24 -r 25 -t 2 -s -p 2 -l 0 -u 0 -i 1 -n f -g 3 -v"
+
+If this plays properly, the D-Box can then be set to run automatically on boot:
+
+./set_startup.sh -l -c "-q 24 -r 25 -t 2 -s -p 2 -l 0 -u 0 -i 1 -n f -g 3 -v"
+
+If at any time you want to stop the D-Box program running, you can run:
+
+./stop_running.sh
+
+To turn off further autoboot, run:
+
+./set_startup.sh -n
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/logger.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,188 @@
+/*
+ * logger.cpp
+ *
+ *  Created on: Aug 6, 2014
+ *      Author: VIctor Zappi and Andrew McPherson
+ */
+
+#include "logger.h"
+
+// main extern vars
+extern int gShouldStop;
+extern int gVerbose;
+
+// file nanme extern vars
+extern char gId;
+extern char gGroup;
+
+
+// logged extern vars
+extern int s0TouchNum;
+extern float s0Touches_[MAX_TOUCHES];
+extern float s0Size_[MAX_TOUCHES];
+extern int s0LastIndex;
+
+extern int s1TouchNum;
+extern float s1Touches_[MAX_TOUCHES];
+extern float s1Size_[MAX_TOUCHES];
+extern int s1LastIndex;
+
+extern int fsr;
+
+
+
+string logPath			= "/boot/uboot/instrumentLog";
+string logFileIncipit	= "/datalog";
+string logFileName		= "";
+ofstream logFile;
+timeval logTimeVal;
+unsigned long long logTimeOrig;
+int logCnt				= 0;	// counts how many lines so far
+int logCntSwap			= 50;	// how many log lines before closing and re-opening the file
+
+
+// create the log file, using incremental name convention
+int initLogLoop()
+{
+	if(gVerbose==1)
+		cout << "---------------->Init Log Thread" << endl;
+
+
+	// transform chars into strings via stringstream objs
+	stringstream id_ss, group_ss, freedom_ss;
+	id_ss 		<< gId;
+	group_ss 	<< gGroup;
+
+	int logNum	= -1;
+	int logMax	= -1;
+	int pathLen	= logPath.length() + logFileIncipit.length() + 4;	// + 4 is: "_", id, group, "_"
+	glob_t globbuf;
+
+	// check how many log files are already there, and choose name according to this
+	glob( (logPath + logFileIncipit + "*").c_str(), 0, NULL, &globbuf);
+
+	// cycle through all and find the highest index
+	for(unsigned int i=0; i<globbuf.gl_pathc; i++)
+	{
+		// playing with 0-9 char digits, forming a number from 0 to 9999
+		logNum  = (globbuf.gl_pathv[i][pathLen]-48)   * 1000;	// 42 to 45 are the indices of the chars forming the file index
+		logNum += (globbuf.gl_pathv[i][pathLen+1]-48) * 100;
+		logNum += (globbuf.gl_pathv[i][pathLen+2]-48) * 10;
+		logNum +=  globbuf.gl_pathv[i][pathLen+3]-48;
+		if(logNum > logMax)
+			logMax = logNum;
+	}
+	logNum = logMax + 1;	// new index
+
+	globfree(&globbuf);
+
+	ostringstream numString;
+	numString << setw (4) << setfill ('0') << logNum;	// set integer with 4 figures
+
+	// here are the new names: PATH + DIR + INCIPIT + _ + id + group + freedom + _ + NUM (4figures) + _A.txt
+	logFileName	= logPath + logFileIncipit;
+	logFileName	+= "_" + id_ss.str() + group_ss.str() + freedom_ss.str();
+	logFileName	+= "_" + numString.str();	 //static_cast<ostringstream*>( &(ostringstream() << logNum) )->str();
+	logFileName	+= ".txt";
+
+
+	// create new files
+	FILE *fp_a		= fopen(logFileName.c_str(), "wb");
+	if(!fp_a)
+	{
+		dbox_printf("Cannot create files...\n");
+		return 2;
+	}
+	fclose(fp_a);
+
+	// ready to append
+	logFile.open(logFileName.c_str(), ios::out | ios::app);
+
+	dbox_printf("Logging on file %s\n", logFileName.c_str());
+
+	return 0;
+}
+
+
+void writeData(unsigned long long time)
+{
+
+	float fsr_ = ((float)(1799-fsr)/1799.0);
+	logFile << time 				<< "\t"		// timestamp
+			<< s0TouchNum			<< "\t";	// sensor 0 touch count
+	for(int i=0; i<MAX_TOUCHES; i++)
+		logFile << s0Touches_[i] 	<< "\t";	// sensor 0 touch pos x
+	for(int i=0; i<MAX_TOUCHES; i++)
+		logFile << s0Size_[i] 		<< "\t";	// sensor 0 touch size
+	logFile << s0LastIndex 			<< "\t"		// sensor 0 last index
+			<< fsr_					<< "\t"		// sensor 0 FSR pressure
+			<< s1TouchNum			<< "\t";	// sensor 1 touch count
+	for(int i=0; i<MAX_TOUCHES; i++)
+		logFile << s1Touches_[i] 	<< "\t";	// sensor 1 touch pos x
+	for(int i=0; i<MAX_TOUCHES; i++)
+		logFile	<< s1Size_[i] 		<< "\t";	// sensor 1 touch size
+	logFile << s1LastIndex 			<< "\t"		// sensor 1 last index
+	//... AND SO ON
+			<< "\n";
+
+	//dbox_printf("%d\n", s0LastIndex);
+	//dbox_printf("s0TouchNum: %d\t s0Touches[0]: %f\t s0Size[0]: %f\t s0LastIndex: %d\n", s0TouchNum, s0Touches_[0], s0Size_[0], s0LastIndex);
+
+}
+
+void logData(unsigned long long time)
+{
+	// if it's time to change write-file
+	if(logCnt >= logCntSwap)
+	{
+		logFile.close();	// close file, dump stream
+		logCnt = 0;		// ready for another whole round
+
+		// open again, ready to append
+		logFile.open(logFileName.c_str(), ios::out | ios::app);
+	}
+
+	writeData(time);
+
+	logCnt++;
+}
+
+
+
+
+void *logLoop(void *)
+{
+	set_realtime_priority(10);
+
+	if(gVerbose==1)
+		dbox_printf("_________________Log Thread!\n");
+
+	// get time reference
+	gettimeofday(&logTimeVal, NULL);
+	logData(0);
+
+	logTimeOrig = logTimeVal.tv_usec;
+	logTimeOrig *= 0.001;					// from usec to msec
+	logTimeOrig += logTimeVal.tv_sec*1000;	// from sec to msec
+
+	usleep(5000);
+
+	while(!gShouldStop)
+	{
+		gettimeofday(&logTimeVal, NULL);
+		unsigned long long currentTime = logTimeVal.tv_usec;
+		currentTime *= 0.001;					// from usec to msec
+		currentTime += logTimeVal.tv_sec*1000;	// from sec to msec
+
+		logData(currentTime-logTimeOrig);
+
+		usleep(5000);
+	}
+
+	if(logFile!=NULL)
+		logFile.close();
+
+	dbox_printf("log thread ended\n");
+
+	return (void *)0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/logger.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,31 @@
+/*
+ * logger.h
+ *
+ *  Created on: Aug 6, 2014
+ *      Author: Victor Zappi and Andrew McPherson
+ */
+
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+#include <string.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fstream>		// file handle
+#include <iostream>		// stringstream
+#include <sstream>		// stringstream
+#include <glob.h>		// alternative to dirent.h to handle files in dirs
+#include <iomanip>		// setfill
+#include <sys/time.h>	// elapsed time
+
+#include "config.h"
+#include "prio.h"
+
+using namespace std;
+
+int initLogLoop();
+void *logLoop(void *);
+
+
+#endif /* LOGGER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,491 @@
+/*
+ *  RTAudio.cpp
+ *
+ *  Central control code for hard real-time audio on BeagleBone Black
+ *  using PRU and Xenomai Linux extensions. This code began as part
+ *  of the Hackable Instruments project (EPSRC) at Queen Mary University
+ *  of London, 2013-14.
+ *
+ *  (c) 2014 Victor Zappi and Andrew McPherson
+ *  Queen Mary University of London
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <math.h>
+#include <iostream>
+#include <signal.h>		// interrupt handler
+#include <assert.h>
+#include <vector>
+#include <dirent.h>		// to handle files in dirs
+#include <mntent.h>		// to check if device is mounted
+#include <sys/mount.h>	// mount()
+#include <sys/time.h>	// elapsed time
+#include <ne10/NE10.h>	// neon library
+
+// thread priority
+#include <pthread.h>
+#include <sched.h>
+
+// get_opt_long
+#include <getopt.h>
+
+#include <Bela.h>
+#include "config.h"
+#include "sensors.h"
+#include "OscillatorBank.h"
+#include "StatusLED.h"
+#include "logger.h"
+
+using namespace std;
+
+//----------------------------------------
+// main variables
+//----------------------------------------
+vector<OscillatorBank*> gOscBanks;
+int gCurrentOscBank = 0;
+int gNextOscBank = 0;
+int oscBnkOversampling 				 = 1;	// oscillator bank frame oversampling
+
+const int kStatusLEDPin 	 = 30;	// P9-11 controls status LED
+StatusLED gStatusLED;
+
+pthread_t keyboardThread;
+pthread_t logThread;
+
+// general settings
+int gVerbose		= 0;        			// verbose flag
+bool forceKeyboard 	= true;					// activate/deactivate keyboard control
+bool forceSensors	= false;				// activate/deactivate sensor control
+bool forceLog		= true;					// activate/deactivate log on boot partition
+bool useSD   		= true;    				// activate/deactivate file loading from SD [as opposed to emmc]
+bool useAudioTest   = false;    			// activate/deactivate sensors and test audio only
+
+// audio settings
+unsigned int gPeriodSize = 8;				// period size for audio
+char* gPartialFilename = 0;					// name of the partials file to load
+bool gAudioIn = false;						// stereo audio in status
+
+int touchSensor0Address = 0x0C;				// I2C addresses of touch sensors
+int touchSensor1Address = 0x0B;
+int sensorType = 0;
+
+char sdPath[256]			= "/dev/mmcblk0p2";			// system path of the SD, partition 2
+char mountPath[256]			= "/root/d-box/usersounds";	// mount point of SD partition 2 [where user files are]
+char gUserDirName[256] 		= "usersounds";				// Directory in which user analysis files can be found [dir of mountPath]
+char gDefaultDirName[256] 	= "/root/d-box/sounds";		// Directory in which built in analysis files can be found
+char *gDirName;
+bool gIsLoading 			= false;
+int fileCnt 				= 0;
+std::vector <std::string> files;
+
+char gId	= 'f';	// from 0 to 14, hexadecimal [0-d]! f means not set
+char gGroup	= '2';	// 0 is no info, 1 info.   2 is not set
+
+// audio in filter
+extern ne10_float32_t *filterState[2];
+extern ne10_float32_t *filterIn[2];
+extern ne10_float32_t *filterOut[2];
+
+struct arg_data
+{
+   int  argc;
+   char **argv;
+};
+
+arg_data args;
+
+
+int readFiles()
+{
+	if(useSD)
+		gDirName = gUserDirName;
+	else
+		gDirName = gDefaultDirName;
+	DIR *dir;
+	struct dirent *ent;
+
+	// From http://stackoverflow.com/questions/612097/how-can-i-get-a-list-of-files-in-a-directory-using-c-or-c
+	if ((dir = opendir (gDirName)) != NULL) {
+		/* print all the files and directories within directory */
+		while ((ent = readdir (dir)) != NULL) {
+			// Ignore dotfiles and . and .. paths
+			if(!strncmp(ent->d_name, ".", 1))
+				continue;
+
+			//dbox_printf("%s\n", ent->d_name);
+
+			// take only .dbx and .txt files
+			string name = string(ent->d_name);
+			int len		= name.length();
+
+			bool dboxFile = false;
+
+			if( (name[len-4]=='.') && (name[len-3]=='d') && (name[len-2]=='b') && (name[len-1]=='x') )
+				dboxFile = true;
+			if( (name[len-4]=='.') && (name[len-3]=='t') && (name[len-2]=='x') && (name[len-1]=='t') )
+				dboxFile = true;
+
+			if(dboxFile)
+			{
+				fileCnt++;
+				//dbox_printf("%s\n", ent->d_name);
+				files.push_back( std::string( ent->d_name ) );
+			}
+		}
+		closedir (dir);
+	} else {
+		/* could not open directory */
+		printf("Could not open directory %s\n", gDirName);
+		return 1;
+	}
+
+	// order by name
+	std::sort( files.begin(), files.end() );
+
+	if(fileCnt==0)
+	{
+		printf("No .dbx or .txt files in %s!\n", gDirName);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* Load sounds from the directory */
+void loadAudioFiles(bool loadFirstFile)
+{
+	char fullFileName[256];
+
+	if(loadFirstFile) {
+		strcpy(fullFileName, gDirName);
+		strcat(fullFileName, "/");
+		strncat(fullFileName, files[0].c_str(), 255 - strlen(gDirName));
+		dbox_printf("Loading first file %s...\n", fullFileName);
+		OscillatorBank *bank = new OscillatorBank(fullFileName);
+		if(bank->initBank(oscBnkOversampling)) {
+			bank->setLoopHops(100, bank->getLastHop());
+			gOscBanks.push_back(bank);
+		}
+	}
+
+	else {
+		for(int i=1; i<fileCnt; i++){
+			strcpy(fullFileName, gDirName);
+			strcat(fullFileName, "/");
+			strncat(fullFileName, files[i].c_str(), 255 - strlen(gDirName));
+			dbox_printf("Loading file %s...\n", fullFileName);
+			OscillatorBank *bank = new OscillatorBank(fullFileName);
+			if(bank->initBank(oscBnkOversampling)) {
+				bank->setLoopHops(100, bank->getLastHop());
+				gOscBanks.push_back(bank);
+			}
+		}
+	}
+}
+
+// adapted from http://program-nix.blogspot.co.uk/2008/08/c-language-check-filesystem-is-mounted.html
+int checkIfMounted (char * dev_path)
+{
+	FILE * mtab				= NULL;
+	struct mntent * part	= NULL;
+	int is_mounted			= 0;
+
+	if ( ( mtab = setmntent ("/etc/mtab", "r") ) != NULL)
+	{
+		while ( ( part = getmntent ( mtab) ) != NULL)
+		{
+			if ( ( part->mnt_fsname != NULL ) && ( strcmp ( part->mnt_fsname, dev_path ) ) == 0 )
+			   is_mounted = 1;
+		}
+	endmntent(mtab);
+	}
+	return is_mounted;
+}
+
+int mountSDuserPartition()
+{
+	if(checkIfMounted(sdPath))
+	{
+		printf("device %s already mounted, fair enough, let's move on\n", sdPath);
+		return 0;
+	}
+	// if mount rootfs from SD [rootfs eMMC not used] or from eMMC via properly formatted SD [SD rootfs used as storage volume]
+	// we always use rootfs on SD as storage volume ----> "/dev/mmcblk0p2"
+	int ret = mount(sdPath, "/root/d-box/usersounds", "vfat",  0, NULL);
+	if (ret!=0)
+	{
+			printf("Error in mount...%s\n", strerror(ret));
+			return 1;
+	}
+	return 0;
+}
+
+int initSoundFiles()
+{
+	if(gVerbose==1)
+		cout << "---------------->Init Audio Thread" << endl;
+
+	if(useSD)
+	{
+		// mount the SD partition where user sounds are located
+		// [this is p2, p1 is already mounted and we will log data there]
+		if(mountSDuserPartition()!=0)
+			return -1;
+	}
+
+	gIsLoading = true;
+
+	// read files from SD and order them alphabetically
+	if(readFiles()!=0)
+		return 1;
+
+	// load first file into oscBank
+	loadAudioFiles(true);
+
+	return 0;
+}
+
+//---------------------------------------------------------------------------------------------------------
+
+// Handle Ctrl-C
+void interrupt_handler(int var)
+{
+	// kill keyboard thread mercilessly
+	if(forceKeyboard)
+		pthread_cancel(keyboardThread);
+
+	gShouldStop = true;
+}
+
+
+void parseArguments(arg_data args, BelaInitSettings *settings)
+{
+	// Default filename;
+	gPartialFilename = strdup("D-Box_sound_250_60_40_h88_2.txt");
+
+	const int kOptionAudioTest = 1000;
+
+	// TODO: complete this
+	struct option long_option[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"audioin", 1, NULL, 'i'},
+		{"file", 1, NULL, 'f'},
+		{"keyboard", 1, NULL, 'k'},
+		{"audio-test", 0, NULL, kOptionAudioTest},
+		{"sensor-type", 1, NULL, 't'},
+		{"sensor0", 1, NULL, 'q'},
+		{"sensor1", 1, NULL, 'r'},
+		{"log", 1, NULL, 'l'},
+		{"usesd", 1, NULL, 'u'},
+		{"oversamp", 1, NULL, 'o'},
+		{"boxnumber", 1, NULL, 'n'},
+		{"group", 1, NULL, 'g'},
+		{NULL, 0, NULL, 0},
+	};
+	int morehelp = 0;
+	int tmp = -1;
+
+	Bela_defaultSettings(settings);
+
+	while (1)
+	{
+		int c;
+		if ((c = Bela_getopt_long(args.argc, args.argv, "hf:ki:sq:r:t:l:u:o:n:g:", long_option, settings)) < 0)
+				break;
+		switch (c)
+		{
+		case 'h':
+				morehelp++;
+				break;
+		case 'f':
+				free(gPartialFilename);
+				gPartialFilename = strdup(optarg);
+				break;
+		case 'k':
+				forceKeyboard = true;
+				break;
+		case 'i':
+				gAudioIn = (atoi(optarg)==0) ? false : true;
+				break;
+		case 's':
+				forceSensors = true;
+				break;
+		case kOptionAudioTest:
+				useAudioTest = true;
+				break;
+		case 't':
+				sensorType = atoi(optarg);
+				break;
+		case 'q':
+				touchSensor0Address = atoi(optarg);
+				break;
+		case 'r':
+				touchSensor1Address = atoi(optarg);
+				break;
+		case 'l':
+				tmp = atoi(optarg);
+				if(tmp==0)
+					forceLog = false;
+				else if(tmp>0)
+					forceLog = true;
+				break;
+		case 'u':
+				tmp = atoi(optarg);
+				if(tmp==0)
+					useSD = false;
+				else if(tmp>0)
+					useSD = true;
+				break;
+		case 'o':
+				oscBnkOversampling = atoi(optarg);
+				break;
+		case 'n':
+				gId = *optarg;
+				cout << "-set box number to: " << gId << endl;
+				break;
+		case 'g':
+				gGroup = *optarg;
+				cout << "-set group to: " << gId << endl;
+				break;
+		default:
+				break;
+		}
+	}
+
+	gPeriodSize = settings->periodSize;
+	gVerbose = settings->verbose;
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	RT_TASK rtSensorThread;
+	const char rtSensorThreadName[] = "dbox-sensor";
+	int oscBankHopSize;
+
+	// Parse command-line arguments
+	args.argc = argc;
+	args.argv = argv;
+	parseArguments(args, &settings);
+
+	Bela_setVerboseLevel(gVerbose);
+	if(gVerbose == 1 && useAudioTest)
+		cout << "main() : running in audio test mode" << endl;
+
+	// Load sound files from directory
+	if(initSoundFiles() != 0)
+		return -1;
+
+	oscBankHopSize = gOscBanks[gCurrentOscBank]->getHopSize()/gOscBanks[gCurrentOscBank]->getMinSpeed();
+
+	// Initialise the audio device
+	if(Bela_initAudio(&settings, &oscBankHopSize) != 0)
+		return -1;
+
+	// Initialise the status LED
+	if(!gStatusLED.init(kStatusLEDPin)) {
+		if(gVerbose)
+			cout << "Couldn't initialise status LED pin\n";
+	}
+
+	// Free file name string which is no longer needed
+	if(gPartialFilename != 0)
+		free(gPartialFilename);
+
+	if(!useAudioTest) {
+		if(initSensorLoop(touchSensor0Address, touchSensor1Address, sensorType) != 0)
+			return -1;
+	}
+
+	if(gVerbose == 1)
+		cout << "main() : creating audio thread" << endl;
+
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// LED on...
+	gStatusLED.on();
+
+	if(forceSensors && !useAudioTest) {
+		if(gVerbose==1)
+			cout << "main() : creating control thread" << endl;
+
+		if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, BELA_AUDIO_PRIORITY - 5, T_JOINABLE | T_FPU)) {
+			  cout << "Error:unable to create Xenomai control thread" << endl;
+			  return -1;
+		}
+		if(rt_task_start(&rtSensorThread, &sensorLoop, 0)) {
+			  cout << "Error:unable to start Xenomai control thread" << endl;
+			  return -1;
+		}
+	}
+
+	if(forceKeyboard) {
+		if(gVerbose==1)
+			cout << "main() : creating keyboard thread" << endl;
+
+		if ( pthread_create(&keyboardThread, NULL, keyboardLoop, NULL) ) {
+		  cout << "Error:unable to create keyboard thread" << endl;
+		  return -1;
+		}
+	}
+
+	if(forceLog) {
+		if(gVerbose==1)
+			cout << "main() : creating log thread" << endl;
+
+		if(initLogLoop()!=0) {
+			cout << "Error:unable to create log thread" << endl;
+			return -1;
+		}
+
+		if ( pthread_create(&logThread, NULL, logLoop, NULL) ) {
+		  cout << "Error:unable to create keyboard thread" << endl;
+		  return -1;
+		}
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// load all other files into oscBanks
+	loadAudioFiles(false);
+	cout << "Finished loading analysis files\n";
+	gIsLoading = false;
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	Bela_stopAudio();
+
+	if(!useAudioTest)
+		rt_task_join(&rtSensorThread);
+
+	Bela_cleanupAudio();
+
+	pthread_join( keyboardThread, NULL);
+	pthread_join( logThread, NULL);
+
+	for(unsigned int i = 0; i < gOscBanks.size(); i++)
+		delete gOscBanks[i];
+
+	NE10_FREE(filterState[0]);
+	NE10_FREE(filterState[1]);
+	NE10_FREE(filterIn[0]);
+	NE10_FREE(filterIn[1]);
+	NE10_FREE(filterOut[0]);
+	NE10_FREE(filterOut[1]);
+
+	printf("Program ended\nBye bye\n");
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/prio.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,48 @@
+/*
+ * prio.cpp
+ *
+ *  Created on: May 14, 2014
+ *      Author: Victor Zappi
+ */
+
+#include "prio.h"
+using namespace std;
+//-----------------------------------------------------------------------------------------------------------
+// set wanted real-time priority to this thread
+//-----------------------------------------------------------------------------------------------------------
+void set_realtime_priority(int order)
+{
+    int ret;
+
+    // We'll operate on the currently running thread.
+    pthread_t this_thread = pthread_self();
+    // struct sched_param is used to store the scheduling priority
+	struct sched_param params;
+	// We'll set the priority to the maximum.
+	params.sched_priority = sched_get_priority_max(SCHED_FIFO) - order;
+
+	// Attempt to set thread real-time priority to the SCHED_FIFO policy
+	ret = pthread_setschedparam(this_thread, SCHED_FIFO, &params);
+	if (ret != 0) {
+		// Print the error
+		cout << "Unsuccessful in setting thread realtime prio" << endl;
+		return;
+	}
+
+	// Now verify the change in thread priority
+    int policy = 0;
+    ret = pthread_getschedparam(this_thread, &policy, &params);
+    if (ret != 0) {
+        cout << "Couldn't retrieve real-time scheduling parameters" << endl;
+        return;
+    }
+
+    // Check the correct policy was applied
+    if(policy != SCHED_FIFO) {
+        cout << "Scheduling is NOT SCHED_FIFO!" << endl;
+    }
+}
+
+//-----------------------------------------------------------------------------------------------------------
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/prio.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,22 @@
+/*
+ * prio.h
+ *
+ *  Created on: May 14, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef PRIO_H_
+#define PRIO_H_
+
+
+#include <pthread.h>
+#include <sched.h>
+#include <iostream>
+
+//-----------------------------------------------------------------------------------------------------------
+// set maximum real-time priority to this thread
+//-----------------------------------------------------------------------------------------------------------
+void set_realtime_priority(int order);
+//-----------------------------------------------------------------------------------------------------------
+
+#endif /* PRIO_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,870 @@
+/*
+ * render.cpp
+ *
+ *  Created on: May 28, 2014
+ *      Author: Victor Zappi
+ */
+
+#include <Bela.h>
+#include <PRU.h>
+
+#include "StatusLED.h"
+#include "config.h"
+#include "OscillatorBank.h"
+#include "FeedbackOscillator.h"
+#include "ADSR.h"
+#include "FIRfilter.h"
+#include <assert.h>
+#include <cmath>
+#include <vector>
+
+#undef DBOX_CAPE_TEST
+
+// Mappings from pin numbers on PCB to actual DAC channels
+// This gives the DAC and ADC connectors the same effective pinout
+// Update June 2016: this is no longer needed in the latest Bela
+// release, but is kept here for convenience: it used to be 
+// 6 4 2 0 1 3 5 7 for the DAC pins
+#define DAC_PIN0	0
+#define DAC_PIN1	1
+#define DAC_PIN2	2
+#define DAC_PIN3	3
+#define DAC_PIN4	4
+#define DAC_PIN5	5
+#define DAC_PIN6	6
+#define DAC_PIN7	7
+
+#define ADC_PIN0	0
+#define ADC_PIN1	1
+#define ADC_PIN2	2
+#define ADC_PIN3	3
+#define ADC_PIN4	4
+#define ADC_PIN5	5
+#define ADC_PIN6	6
+#define ADC_PIN7	7
+
+#define N_OCT		4.0	// maximum number of octaves on sensor 1
+
+extern vector<OscillatorBank*> gOscBanks;
+extern int gCurrentOscBank;
+extern int gNextOscBank;
+extern PRU *gPRU;
+extern StatusLED gStatusLED;
+extern bool gIsLoading;
+extern bool gAudioIn;
+
+float *gOscillatorBuffer1, *gOscillatorBuffer2;
+float *gOscillatorBufferRead, *gOscillatorBufferWrite;
+int gOscillatorBufferReadPointer		= 0;
+int gOscillatorBufferReadCurrentSize	= 0;
+int gOscillatorBufferWriteCurrentSize	= 0;
+bool gOscillatorNeedsRender				= false;
+
+int gMatrixSampleCount = 0;		// How many samples have elapsed on the matrix
+
+// Wavetable which changes in response to an oscillator
+float *gDynamicWavetable;
+int gDynamicWavetableLength;
+bool gDynamicWavetableNeedsRender = false;
+
+// These variables handle the hysteresis oscillator used for setting the playback speed
+bool gSpeedHysteresisOscillatorRising	= false;
+int gSpeedHysteresisLastTrigger			= 0;
+
+// These variables handle the feedback oscillator used for controlling the wavetable
+FeedbackOscillator gFeedbackOscillator;
+float *gFeedbackOscillatorTable;
+int gFeedbackOscillatorTableLength;
+
+// This comes from sensor.cpp where it records the most recent touch location on
+// sensor 0.
+extern float gSensor0LatestTouchPos;
+extern int gSensor0LatestTouchNum;
+float gPitchLatestInput = 0;
+
+extern float gSensor1LatestTouchPos[];
+//extern float gSensor1LatestTouchSizes[];
+extern int gSensor1LatestTouchCount;
+extern int gSensor1LatestTouchIndex;
+int gSensor1LastTouchIndex		= -1;
+int gSensor1InputDelayCounter	= -1;
+int gSensor1InputIndex			= 0;
+float gSensor1MatrixTouchPos[5]	= {0};
+
+// FSR value from matrix input
+extern int gLastFSRValue;
+
+// Loop points from matrix input 4
+const int gLoopPointsInputBufferSize	= 256;
+float gLoopPointsInputBuffer[gLoopPointsInputBufferSize];
+int gLoopPointsInputBufferPointer		= 0;
+float gLoopPointMin = 0, gLoopPointMax	= 0;
+
+// multiplier to activate or mute audio in
+int audioInStatus = 0;
+
+// xenomai timer
+SRTIME prevChangeNs = 0;
+
+// pitch vars
+float octaveSplitter;
+float semitones[((int)N_OCT*12)+1];
+float deltaTouch	= 0;
+float deltaWeightP	= 0.5 / 65536.0;
+float deltaWeightI	= 0.0005 / 65536.0;
+
+// filter vars
+ne10_fir_instance_f32_t filter[2];
+ne10_float32_t *filterIn[2];
+ne10_float32_t *filterOut[2];
+ne10_uint32_t blockSize;
+ne10_float32_t *filterState[2];
+ne10_float32_t prevFiltered[2];
+int filterGain = 80;
+ADSR PeakBurst[2];
+float peak[2];
+float peakThresh = 0.2;
+
+// Tasks for lower-priority calculation
+AuxiliaryTask gMediumPriorityRender, gLowPriorityRender;
+
+
+extern "C" {
+	// Function prototype for ARM assembly implementation of oscillator bank
+	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
+							  int activePartialNum, int lookupTableSize,
+							  float *phases, float *frequencies, float *amplitudes,
+							  float *freqDerivatives, float *ampDerivatives,
+							  float *lookupTable);
+
+	void wavetable_interpolate_neon(int numSamplesIn, int numSamplesOut,
+	                              float *tableIn, float *tableOut);
+}
+
+void wavetable_interpolate(int numSamplesIn, int numSamplesOut,
+                              float *tableIn, float *tableOut,
+                              float *sineTable, float sineMix);
+
+inline float hysteresis_oscillator(float input, float risingThreshold,
+									float fallingThreshold, bool *rising);
+
+void render_medium_prio();
+void render_low_prio();
+
+#ifdef DBOX_CAPE_TEST
+void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
+			uint16_t *matrixIn, uint16_t *matrixOut);
+#endif
+
+bool setup(BelaContext *context, void *userData) {
+	int oscBankHopSize = *(int *)userData;
+
+	if(context->analogChannels != 8) {
+		printf("Error: D-Box needs matrix enabled with 8 channels.\n");
+		return false;
+	}
+
+	// Allocate two buffers for rendering oscillator bank samples
+	// One will be used for writing in the background while the other is used for reading
+	// on the audio thread. 8-byte alignment needed for the NEON code.
+	if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * context->audioChannels * sizeof(float))) {
+		printf("Error allocating render buffers\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * context->audioChannels * sizeof(float))) {
+		printf("Error allocating render buffers\n");
+		return false;
+	}
+	gOscillatorBufferWrite	= gOscillatorBuffer1;
+	gOscillatorBufferRead	= gOscillatorBuffer2;
+
+	memset(gOscillatorBuffer1, 0, oscBankHopSize * context->audioChannels * sizeof(float));
+	memset(gOscillatorBuffer2, 0, oscBankHopSize * context->audioChannels * sizeof(float));
+
+	// Initialise the dynamic wavetable used by the oscillator bank
+	// It should match the size of the static one already allocated in the OscillatorBank object
+	// Don't forget a guard point at the end of the table
+	gDynamicWavetableLength = gOscBanks[gCurrentOscBank]->lookupTableSize;
+	if(posix_memalign((void **)&gDynamicWavetable, 8, (gDynamicWavetableLength + 1) * sizeof(float))) {
+		printf("Error allocating wavetable\n");
+		return false;
+	}
+
+	gFeedbackOscillator.initialise(8192, 10.0, context->analogSampleRate);
+
+	for(int n = 0; n < gDynamicWavetableLength + 1; n++)
+		gDynamicWavetable[n] = 0;
+
+	// pitch
+	float midPos		= 0.5;
+	octaveSplitter		= 1.0 / N_OCT;
+	int numOfSemi		= 12*N_OCT;
+	int middleSemitone	= 12*N_OCT/2;
+	int lastSemitone	= middleSemitone+numOfSemi/2;
+	float inc 			= 1.0 / (N_OCT*12.0);
+	int i 				= -1;
+	for(int semi=middleSemitone; semi<=lastSemitone; semi++)
+		semitones[semi] = ( midPos + (++i)*inc) + 0.5;
+	i 					= 0;
+	for(int semi=middleSemitone-1; semi>=0; semi--)
+		semitones[semi] = ( midPos - (++i)*inc) + 0.5;
+
+	if(gAudioIn)
+		audioInStatus = 1;
+
+	// filter
+	blockSize		= context->audioFrames;
+	filterState[0]	= (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
+	filterState[1]	= (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
+	filterIn[0]		= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
+	filterIn[1]		= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
+	filterOut[0]	= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
+	filterOut[1]	= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
+	ne10_fir_init_float(&filter[0], FILTER_TAP_NUM, filterTaps, filterState[0], blockSize);
+	ne10_fir_init_float(&filter[1], FILTER_TAP_NUM, filterTaps, filterState[1], blockSize);
+
+	// peak outputs
+	PeakBurst[0].setAttackRate(.00001 * context->analogSampleRate);
+	PeakBurst[1].setAttackRate(.00001 * context->analogSampleRate);
+	PeakBurst[0].setDecayRate(.5 * context->analogSampleRate);
+	PeakBurst[1].setDecayRate(.5 * context->analogSampleRate);
+	PeakBurst[0].setSustainLevel(0.0);
+	PeakBurst[1].setSustainLevel(0.0);
+
+	// Initialise auxiliary tasks
+	if((gMediumPriorityRender = Bela_createAuxiliaryTask(&render_medium_prio, BELA_AUDIO_PRIORITY - 10, "dbox-calculation-medium")) == 0)
+		return false;
+	if((gLowPriorityRender = Bela_createAuxiliaryTask(&render_low_prio, BELA_AUDIO_PRIORITY - 15, "dbox-calculation-low")) == 0)
+		return false;
+
+	return true;
+}
+
+void render(BelaContext *context, void *userData)
+{
+#ifdef DBOX_CAPE_TEST
+	render_capetest(numMatrixFrames, numAudioFrames, audioIn, audioOut, matrixIn, matrixOut);
+#else
+	if(gOscBanks[gCurrentOscBank]->state==bank_toreset)
+		gOscBanks[gCurrentOscBank]->resetOscillators();
+
+	if(gOscBanks[gCurrentOscBank]->state==bank_playing)
+	{
+		assert(context->audioChannels == 2);
+
+#ifdef OLD_OSCBANK
+		memset(audioOut, 0, numAudioFrames *  * sizeof(float));
+
+		/* Render the oscillator bank. The oscillator bank function is written in NEON assembly
+		 * and it strips out all extra checks, so find out in advance whether we can render a whole
+		 * block or whether the frame will increment in the middle of this buffer.
+		 */
+
+		int framesRemaining = numAudioFrames;
+		float *audioOutWithOffset = audioOut;
+
+		while(framesRemaining > 0) {
+			if(gOscBanks[gCurrentOscBank]->hopCounter >= framesRemaining) {
+				/* More frames left in this hop than we need this time. Render and finish */
+				oscillator_bank_neon(framesRemaining, audioOutWithOffset,
+									 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize,
+									 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies,
+									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
+									 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
+									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
+									 gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/);
+				gOscBanks[gCurrentOscBank]->hopCounter -= framesRemaining;
+				if(gOscBanks[gCurrentOscBank]->hopCounter <= 0)
+					gOscBanks[gCurrentOscBank]->nextHop();
+				framesRemaining = 0;
+			}
+			else {
+				/* More frames to render than are left in this hop. Render and decrement the
+				 * number of remaining frames; then advance to the next oscillator frame.
+				 */
+				oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, audioOutWithOffset,
+									 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize,
+									 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies,
+									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
+									 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
+									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
+									 gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/);
+				framesRemaining -= gOscBanks[gCurrentOscBank]->hopCounter;
+				audioOutWithOffset +=  * gOscBanks[gCurrentOscBank]->hopCounter;
+				gOscBanks[gCurrentOscBank]->sampleCount += gOscBanks[gCurrentOscBank]->hopCounter;
+				gOscBanks[gCurrentOscBank]->nextHop();
+			}
+		}
+#else
+		for(unsigned int n = 0; n < context->audioFrames; n++) {
+			context->audioOut[2*n] 	  = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n]*audioInStatus;
+			context->audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n+1]*audioInStatus;
+
+			filterIn[0][n] = fabs(context->audioIn[2*n]);	// rectify for peak detection in 1
+			filterIn[1][n] = fabs(context->audioIn[2*n+1]);	// rectify for peak detection in 2
+
+			/* FIXME why doesn't this work? */
+			/*
+			if(gOscillatorBufferReadPointer == gOscillatorBufferCurrentSize/2) {
+				gOscillatorNeedsRender = true;
+				scheduleAuxiliaryTask(gLowPriorityRender);
+			} */
+
+			if(gOscillatorBufferReadPointer >= gOscillatorBufferReadCurrentSize) {
+				// Finished reading from the buffer: swap to the next buffer
+				if(gOscillatorBufferRead == gOscillatorBuffer1) {
+					gOscillatorBufferRead = gOscillatorBuffer2;
+					gOscillatorBufferWrite = gOscillatorBuffer1;
+				}
+				else {
+					gOscillatorBufferRead = gOscillatorBuffer1;
+					gOscillatorBufferWrite = gOscillatorBuffer2;
+				}
+
+				// New buffer size is whatever finished writing last hop
+				gOscillatorBufferReadCurrentSize = gOscillatorBufferWriteCurrentSize;
+				gOscillatorBufferReadPointer = 0;
+
+				gOscillatorNeedsRender = true;
+				Bela_scheduleAuxiliaryTask(gMediumPriorityRender);
+			}
+		}
+#endif
+	}
+	else
+	{
+		for(unsigned int n = 0; n < context->audioFrames; n++) {
+			context->audioOut[2*n] 	  = context->audioIn[2*n]*audioInStatus;
+			context->audioOut[2*n + 1] = context->audioIn[2*n+1]*audioInStatus;
+
+			filterIn[0][n] = fabs(context->audioIn[2*n]);	// rectify for peak detection in 1
+			filterIn[1][n] = fabs(context->audioIn[2*n+1]);	// rectify for peak detection in 2
+		}
+	}
+
+	// low pass filter audio in 1 and 2 for peak detection
+	ne10_fir_float_neon(&filter[0], filterIn[0], filterOut[0], blockSize);
+	ne10_fir_float_neon(&filter[1], filterIn[1], filterOut[1], blockSize);
+
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
+
+
+		/* Matrix Out 0, In 0
+		 *
+		 * CV loop
+		 * Controls pitch of sound
+		 */
+		float touchPosInt = gSensor0LatestTouchPos;
+		if(touchPosInt < 0) touchPosInt = 0;
+		if(touchPosInt > 1.0) touchPosInt = 1.0;
+		context->analogOut[n*8 + DAC_PIN0] = touchPosInt;
+
+		gPitchLatestInput = context->analogIn[n*8 + ADC_PIN0];
+
+
+		/* Matrix Out 7
+		 *
+		 * Loop feedback with Matrix In 0
+		 * Controls discreet pitch
+		 */
+		float deltaTarget = 0;
+		int semitoneIndex = 0;
+		if(gSensor0LatestTouchNum>0)
+		{
+			// current pitch is gPitchLatestInput, already retrieved
+			semitoneIndex	= ( gPitchLatestInput * 12 * N_OCT  )+0.5;	// closest semitone
+			deltaTarget		= (semitones[semitoneIndex]-gPitchLatestInput);				// delta between pitch and target
+			deltaTouch 		+= deltaTarget*(deltaWeightI);								// update feedback [previous + current]
+		}
+		else
+			deltaTouch = 0;
+
+		float nextOut = touchPosInt  + deltaTarget*deltaWeightP + deltaTouch;			// add feedback to touch -> next out
+		if(nextOut < 0) nextOut = 0;												// clamp
+		if(nextOut > 1.0) nextOut = 1.0;										// clamp
+		context->analogOut[n*8 + DAC_PIN7] = nextOut;										// send next nextOut
+
+
+		/*
+		 * Matrix Out 1, In 1
+		 *
+		 * Hysteresis (comparator) oscillator
+		 * Controls speed of playback
+		 */
+		bool wasRising = gSpeedHysteresisOscillatorRising;
+		context->analogOut[n*8 + DAC_PIN1] = hysteresis_oscillator(context->analogIn[n*8 + ADC_PIN1], 48000.0/65536.0,
+																	16000.0/65536.0, &gSpeedHysteresisOscillatorRising);
+
+		// Find interval of zero crossing
+		if(wasRising && !gSpeedHysteresisOscillatorRising) {
+			int interval = gMatrixSampleCount - gSpeedHysteresisLastTrigger;
+
+			// Interval since last trigger will be the new hop size; calculate to set speed
+			if(interval < 1)
+				interval = 1;
+			//float speed = (float)gOscBanks[gCurrentOscBank]->getHopSize() / (float)interval;
+			float speed = 144.0 / interval;	// Normalise to a fixed expected speed
+			gOscBanks[gCurrentOscBank]->setSpeed(speed);
+
+			gSpeedHysteresisLastTrigger = gMatrixSampleCount;
+		}
+
+		/*
+		 * Matrix Out 2, In 2
+		 *
+		 * Feedback (phase shift) oscillator
+		 * Controls wavetable used for oscillator bank
+		 */
+
+		int tableLength = gFeedbackOscillator.process(context->analogIn[n*8 + ADC_PIN2], &context->analogOut[n*8 + DAC_PIN2]);
+		if(tableLength != 0) {
+			gFeedbackOscillatorTableLength = tableLength;
+			gFeedbackOscillatorTable = gFeedbackOscillator.wavetable();
+			gDynamicWavetableNeedsRender = true;
+			Bela_scheduleAuxiliaryTask(gLowPriorityRender);
+		}
+
+		/*
+		 * Matrix Out 3, In 3
+		 *
+		 * CV loop with delay for time alignment
+		 * Touch positions from sensor 1
+		 * Change every 32 samples (ca. 1.5 ms)
+		 */
+		volatile int touchCount = gSensor1LatestTouchCount;
+		if(touchCount == 0)
+			context->analogOut[n*8 + DAC_PIN3] = 0;
+		else {
+			int touchIndex = (gMatrixSampleCount >> 5) % touchCount;
+			context->analogOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f / 65536.0f;
+			if(touchIndex != gSensor1LastTouchIndex) {
+				// Just changed to a new touch output. Reset the counter.
+				// It will take 2*matrixFrames samples for this output to come back to the
+				// ADC input. But we also want to read near the end of the 32 sample block;
+				// let's say 24 samples into it.
+
+				// FIXME this won't work for p > 2
+				gSensor1InputDelayCounter = 24 + 2*context->analogFrames;
+				gSensor1InputIndex = touchIndex;
+			}
+			gSensor1LastTouchIndex = touchIndex;
+		}
+
+		if(gSensor1InputDelayCounter-- >= 0 && touchCount > 0) {
+			gSensor1MatrixTouchPos[gSensor1InputIndex] = context->analogIn[n*8 + ADC_PIN3];
+		}
+
+		/* Matrix Out 4
+		 *
+		 * Sensor 1 last pos
+		 */
+		touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex];
+		if(touchPosInt < 0) touchPosInt = 0;
+		if(touchPosInt > 1.0) touchPosInt = 1.0;
+		context->analogOut[n*8 + DAC_PIN4] = touchPosInt;
+
+		/* Matrix In 4
+		 *
+		 * Loop points selector
+		 */
+		gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = context->analogIn[n*8 + ADC_PIN4];
+		if(gLoopPointsInputBufferPointer >= gLoopPointsInputBufferSize) {
+			// Find min and max values
+			float loopMax = 0, loopMin = 1.0;
+			for(int i = 0; i < gLoopPointsInputBufferSize; i++) {
+				if(gLoopPointsInputBuffer[i] < loopMin)
+					loopMin = gLoopPointsInputBuffer[i];
+				if(gLoopPointsInputBuffer[i] > loopMax/* && gLoopPointsInputBuffer[i] != 65535*/)
+					loopMax = gLoopPointsInputBuffer[i];
+			}
+
+			if(loopMin >= loopMax)
+				loopMax = loopMin;
+
+			gLoopPointMax = loopMax;
+			gLoopPointMin = loopMin;
+			gLoopPointsInputBufferPointer = 0;
+		}
+
+		/* Matrix Out 5
+		 *
+		 * Audio In 1 peak detection and peak burst output
+		 */
+
+		filterOut[0][n*2+1]	*= filterGain;
+		float burstOut		= PeakBurst[0].getOutput();
+		if( burstOut < 0.1)
+		{
+			if( (prevFiltered[0]>=peakThresh) && (prevFiltered[0]>=filterOut[0][n*2+1]) )
+			{
+				peak[0] = prevFiltered[0];
+				PeakBurst[0].gate(1);
+			}
+		}
+
+		PeakBurst[0].process(1);
+
+		float convAudio = burstOut*peak[0];
+		context->analogOut[n*8 + DAC_PIN5] = convAudio;
+		prevFiltered[0] = filterOut[0][n*2+1];
+		if(prevFiltered[0]>1)
+			prevFiltered[0] = 1;
+
+		/* Matrix In 5
+		 *
+		 * Dissonance, via changing frequency motion of partials
+		 */
+		float amount = (float)context->analogIn[n*8 + ADC_PIN5];
+		gOscBanks[gCurrentOscBank]->freqMovement = 1.0 - amount;
+
+
+
+
+		/* Matrix Out 6
+		 *
+		 * Audio In 2 peak detection and peak burst output
+		 */
+
+		filterOut[1][n*2+1]	*= filterGain;
+		burstOut			= PeakBurst[1].getOutput();
+		if( burstOut < 0.1)
+		{
+			if( (prevFiltered[1]>=peakThresh) && (prevFiltered[1]>=filterOut[1][n*2+1]) )
+			{
+				peak[1] = prevFiltered[1];
+				PeakBurst[1].gate(1);
+			}
+		}
+
+		PeakBurst[1].process(1);
+
+		convAudio = burstOut*peak[1];
+		context->analogOut[n*8 + DAC_PIN6] = convAudio;
+		prevFiltered[1] = filterOut[1][n*2+1];
+		if(prevFiltered[1]>1)
+			prevFiltered[1] = 1;
+
+		/* Matrix In 6
+		 *
+		 * Sound selector
+		 */
+		if(!gIsLoading) {
+			// Use hysteresis to avoid jumping back and forth between sounds
+			if(gOscBanks.size() > 1) {
+				float input = context->analogIn[n*8 + ADC_PIN6];
+				const float hystValue = 16000.0 / 65536.0;
+
+				float upHysteresisValue = ((gCurrentOscBank + 1) + hystValue) / gOscBanks.size();
+				float downHysteresisValue = (gCurrentOscBank - hystValue) / gOscBanks.size();
+
+				if(input > upHysteresisValue || input < downHysteresisValue) {
+					gNextOscBank = input * gOscBanks.size();
+					if(gNextOscBank < 0)
+						gNextOscBank = 0;
+					if((unsigned)gNextOscBank >= gOscBanks.size())
+						gNextOscBank = gOscBanks.size() - 1;
+				}
+			}
+		}
+
+		/*
+		 * Matrix In 7
+		 *
+		 * FSR from primary touch sensor
+		 * Value ranges from 0-1799
+		 */
+		gLastFSRValue = context->analogIn[n*8 + ADC_PIN7] * 1799.0;
+		//gLastFSRValue = 1799 - context->analogIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0);
+		//dbox_printf("%i\n",gLastFSRValue);
+
+		gMatrixSampleCount++;
+	}
+
+#endif /* DBOX_CAPE_TEST */
+}
+
+// Medium-priority render function used for audio hop calculations
+void render_medium_prio()
+{
+
+	if(gOscillatorNeedsRender) {
+		gOscillatorNeedsRender = false;
+
+		/* Render one frame into the write buffer */
+		memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * 2 * sizeof(float)); /* assumes 2 audio channels */
+
+		oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, gOscillatorBufferWrite,
+							 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize,
+							 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies,
+							 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
+							 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
+							 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
+							 /*gOscBanks[gCurrentOscBank]->lookupTable*/gDynamicWavetable);
+
+		gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * 2;
+
+		/* Update the pitch right before the hop
+		 * Total CV range +/- N_OCT octaves
+		 */
+		float pitch = (float)gPitchLatestInput / octaveSplitter - N_OCT/2;
+		//gOscBanks[gCurrentOscBank]->pitchMultiplier = powf(2.0f, pitch);
+		gOscBanks[gCurrentOscBank]->pitchMultiplier = pow(2.0f, pitch);
+
+#ifdef FIXME_LATER // This doesn't work very well yet
+		gOscBanks[gCurrentOscBank]->filterNum = gSensor1LatestTouchCount;
+		float freqScaler = gOscBanks[gCurrentOscBank]->getFrequencyScaler();
+		for(int i=0; i < gOscBanks[gCurrentOscBank]->filterNum; i++)
+		{
+			// touch pos is linear but freqs are log
+			gOscBanks[gCurrentOscBank]->filterFreqs[i] = ((expf(gSensor1MatrixTouchPos[i]*4)-1)/(expf(4)-1))*gOscBanks[gCurrentOscBank]->filterMaxF*freqScaler;
+			gOscBanks[gCurrentOscBank]->filterQ[i] = gSensor1LatestTouchSizes[i];
+			if(gOscBanks[gCurrentOscBank]->filterFreqs[i]>500*freqScaler)
+				gOscBanks[gCurrentOscBank]->filterPadding[i] = 1+100000*( (gOscBanks[gCurrentOscBank]->filterFreqs[i]-500*freqScaler)/(gOscBanks[gCurrentOscBank]->filterMaxF-500)*freqScaler );
+			else
+				gOscBanks[gCurrentOscBank]->filterPadding[i] = 1;
+		}
+#endif
+
+		RTIME ticks		= rt_timer_read();
+		SRTIME ns		= rt_timer_tsc2ns(ticks);
+		SRTIME delta 	= ns-prevChangeNs;
+
+		// switch to next bank cannot be too frequent, to avoid seg fault! [for example sef fault happens when removing both VDD and GND from breadboard]
+		if(gNextOscBank != gCurrentOscBank && delta>100000000) {
+
+			/*printf("ticks %llu\n", (unsigned long long)ticks);
+			printf("ns %llu\n", (unsigned long long)ns);
+			printf("prevChangeNs %llu\n", (unsigned long long)prevChangeNs);
+			printf("-------------------------->%llud\n", (unsigned long long)(ns-prevChangeNs));*/
+
+			prevChangeNs = ns;
+			dbox_printf("Changing to bank %d...\n", gNextOscBank);
+			if(gOscBanks[gCurrentOscBank]->state==bank_playing){
+				gOscBanks[gCurrentOscBank]->stop();
+			}
+
+			gCurrentOscBank = gNextOscBank;
+			gOscBanks[gCurrentOscBank]->hopNumTh = 0;
+		}
+		else {
+			/* Advance to the next oscillator frame */
+			gOscBanks[gCurrentOscBank]->nextHop();
+		}
+	}
+}
+
+// Lower-priority render function which performs matrix calculations
+// State should be transferred in via global variables
+void render_low_prio()
+{
+	gPRU->setGPIOTestPin();
+	if(gDynamicWavetableNeedsRender) {
+		// Find amplitude of wavetable
+		float meanAmplitude = 0;
+		float sineMix;
+
+		for(int i = 0; i < gFeedbackOscillatorTableLength; i++) {
+			//meanAmplitude += fabsf(gFeedbackOscillatorTable[i]);
+			meanAmplitude += fabs(gFeedbackOscillatorTable[i]);
+		}
+		meanAmplitude /= (float)gFeedbackOscillatorTableLength;
+
+		if(meanAmplitude > 0.35)
+			sineMix = 0;
+		else
+			sineMix = (.35 - meanAmplitude) / .35;
+
+		//dbox_printf("amp %f mix %f\n", meanAmplitude, sineMix);
+
+		// Copy to main wavetable
+		wavetable_interpolate(gFeedbackOscillatorTableLength, gDynamicWavetableLength,
+				gFeedbackOscillatorTable, gDynamicWavetable,
+				gOscBanks[gCurrentOscBank]->lookupTable, sineMix);
+	}
+
+	if(gLoopPointMin >= 60000.0/65536.0 && gLoopPointMax >= 60000.0/65536.0) {
+		// KLUDGE!
+		if(gCurrentOscBank == 0)
+			gOscBanks[gCurrentOscBank]->setLoopHops(50, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.6) - 1);
+		else
+			gOscBanks[gCurrentOscBank]->setLoopHops(5, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.7) - 1);
+	}
+	else {
+		float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop();
+		float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop();
+
+		int intLoopPointMin = normLoopPointMin;
+		if(intLoopPointMin < 1)
+			intLoopPointMin = 1;
+		int intLoopPointMax = normLoopPointMax;
+		if(intLoopPointMax <= intLoopPointMin)
+			intLoopPointMax = intLoopPointMin + 1;
+		if(intLoopPointMax > gOscBanks[gCurrentOscBank]->getLastHop() - 1)
+			intLoopPointMax =  gOscBanks[gCurrentOscBank]->getLastHop() - 1;
+
+		//dbox_printf("Loop points %d-%d / %d-%d\n", gLoopPointMin, gLoopPointMax, intLoopPointMin, intLoopPointMax);
+
+		/* WORKS, jsut need to fix the glitch when jumps!
+		 * *int currentHop = gOscBanks[gCurrentOscBank]->getCurrentHop();
+		if(currentHop < intLoopPointMin -1 )
+			gOscBanks[gCurrentOscBank]->setJumpHop(intLoopPointMin + 1);
+		else if(currentHop > intLoopPointMax + 1)
+			gOscBanks[gCurrentOscBank]->setJumpHop(intLoopPointMax - 1);*/
+		gOscBanks[gCurrentOscBank]->setLoopHops(intLoopPointMin, intLoopPointMax);
+	}
+
+	if(gIsLoading)
+		gStatusLED.blink(25, 75);	// Blink quickly until load finished
+	else
+		gStatusLED.blink(250 / gOscBanks[gCurrentOscBank]->getSpeed(), 250 / gOscBanks[gCurrentOscBank]->getSpeed());
+	gPRU->clearGPIOTestPin();
+
+//	static int counter = 32;
+//	if(--counter == 0) {
+//		for(int i = 0; i < gLoopPointsInputBufferSize; i++) {
+//			dbox_printf("%d ", gLoopPointsInputBuffer[i]);
+//			if(i % 32 == 31)
+//				dbox_printf("\n");
+//		}
+//		dbox_printf("\n\n");
+//		counter = 32;
+//	}
+
+	//dbox_printf("min %d max %d\n", gLoopPointMin, gLoopPointMax);
+}
+
+// Clean up at the end of render
+void cleanup(BelaContext *context, void *userData)
+{
+	free(gOscillatorBuffer1);
+	free(gOscillatorBuffer2);
+	free(gDynamicWavetable);
+}
+
+// Interpolate one wavetable into another. The output size
+// does not include the guard point at the end which will be identical
+// to the first point
+void wavetable_interpolate(int numSamplesIn, int numSamplesOut,
+                           float *tableIn, float *tableOut,
+                           float *sineTable, float sineMix)
+{
+	float fractionalScaler = (float)numSamplesIn / (float)numSamplesOut;
+
+	for(int k = 0; k < numSamplesOut; k++) {
+		float fractionalIndex = (float) k * fractionalScaler;
+		//int sB = (int)floorf(fractionalIndex);
+		int sB = (int)floor(fractionalIndex);
+		int sA = sB + 1;
+		if(sA >= numSamplesIn)
+			sA = 0;
+		float fraction = fractionalIndex - sB;
+		tableOut[k] = fraction * tableIn[sA] + (1.0f - fraction) * tableIn[sB];
+		tableOut[k] = sineMix * sineTable[k] + (1.0 - sineMix) * tableOut[k];
+	}
+
+	tableOut[numSamplesOut] = tableOut[0];
+}
+
+// Create a hysteresis oscillator with a matrix input and output
+inline float hysteresis_oscillator(float input, float risingThreshold, float fallingThreshold, bool *rising)
+{
+	float value;
+
+	if(*rising) {
+		if(input > risingThreshold) {
+			*rising = false;
+			value = 0;
+		}
+		else
+			value = 1.0;
+	}
+	else {
+		if(input < fallingThreshold) {
+			*rising = true;
+			value = 1.0;
+		}
+		else
+			value = 0;
+	}
+
+	return value;
+}
+
+#ifdef DBOX_CAPE_TEST
+// Test the functionality of the D-Box cape by checking each input and output
+// Loopback cable from ADC to DAC needed
+void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
+			uint16_t *matrixIn, uint16_t *matrixOut)
+{
+	static float phase = 0.0;
+	static int sampleCounter = 0;
+	static int invertChannel = 0;
+
+	// Play a sine wave on the audio output
+	for(int n = 0; n < numAudioFrames; n++) {
+		audioOut[2*n] = audioOut[2*n + 1] = 0.5*sinf(phase);
+		phase += 2.0 * M_PI * 440.0 / 44100.0;
+		if(phase >= 2.0 * M_PI)
+			phase -= 2.0 * M_PI;
+	}
+
+	for(int n = 0; n < numMatrixFrames; n++) {
+		// Change outputs every 512 samples
+		if(sampleCounter < 512) {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel)
+					matrixOut[n*8 + k] = 50000;
+				else
+					matrixOut[n*8 + k] = 0;
+			}
+		}
+		else {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel)
+					matrixOut[n*8 + k] = 0;
+				else
+					matrixOut[n*8 + k] = 50000;
+			}
+		}
+
+		// Read after 256 samples: input should be low
+		if(sampleCounter == 256) {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel) {
+					if(matrixIn[n*8 + k] < 50000) {
+						dbox_printf("FAIL channel %d -- output HIGH input %d (inverted)\n", k, matrixIn[n*8 + k]);
+					}
+				}
+				else {
+					if(matrixIn[n*8 + k] > 2048) {
+						dbox_printf("FAIL channel %d -- output LOW input %d\n", k, matrixIn[n*8 + k]);
+					}
+				}
+			}
+		}
+		else if(sampleCounter == 768) {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel) {
+					if(matrixIn[n*8 + k] > 2048) {
+						dbox_printf("FAIL channel %d -- output LOW input %d (inverted)\n", k, matrixIn[n*8 + k]);
+					}
+				}
+				else {
+					if(matrixIn[n*8 + k] < 50000) {
+						dbox_printf("FAIL channel %d -- output HIGH input %d\n", k, matrixIn[n*8 + k]);
+					}
+				}
+			}
+		}
+
+		if(++sampleCounter >= 1024) {
+			sampleCounter = 0;
+			invertChannel++;
+			if(invertChannel >= 8)
+				invertChannel = 0;
+		}
+	}
+}
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/sensors.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,642 @@
+/*
+ * sensors.cpp
+ *
+ *  Created on: May 28, 2014
+ *      Author: Victor Zappi
+ */
+
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <math.h>
+#include <vector>
+#include "prio.h"
+#include "sensors.h"
+#include "OscillatorBank.h"
+#include "DboxSensors.h"
+
+
+//----------------------------------------
+// main extern variables
+//----------------------------------------
+extern vector<OscillatorBank*> gOscBanks;
+extern int gCurrentOscBank;
+extern int gNextOscBank;
+extern int gShouldStop;
+extern int gVerbose;
+
+float gSensor0LatestTouchPos = 0;	// most recent pitch touch location [0-1] on sensor 0, used by render.cpp
+int gSensor0LatestTouchNum	 = 0;	// most recent num of touches on sensor 0, used by render.cpp
+float gSensor1LatestTouchPos[5];	// most recent touche locations on sensor 1, used by render.cpp
+//float gSensor1LatestTouchSizes[5];
+int gSensor1LatestTouchCount;		// most recent number touches on sensor 1, used by render.cpp
+int gSensor1LatestTouchIndex = 0;	// index of last touch in gSensor1LatestTouchPos[5], used by render.cpp
+int gLastFSRValue = 1799;			// most recent fsr value, used by render.cpp
+
+
+DboxSensors Sensors;
+
+
+//----------------------------------------
+// var shared with logger
+//----------------------------------------
+int s0TouchNum	 	= 0;
+float s0Touches_[MAX_TOUCHES];
+float s0Size_[MAX_TOUCHES];
+int s0LastIndex;
+
+int s1TouchNum	 	= 0;
+float s1Touches_[MAX_TOUCHES];
+float s1Size_[MAX_TOUCHES];
+int s1LastIndex;
+
+int fsr				= 1799;
+
+
+
+using namespace std;
+
+int initSensorLoop(int sensorAddress0, int sensorAddress1, int sensorType)
+{
+	int tk0_bus			= 1;
+	int tk0_address		= sensorAddress0;
+	int tk1_bus			= 1;
+	int tk1_address		= sensorAddress1;
+	int tk_file			= 0;
+	int fsr_max			= 1799;
+	int fsr_pinNum		= 4;
+
+	if(gVerbose==1)
+		cout << "---------------->Init Control Thread" << endl;
+
+	if(Sensors.initSensors(tk0_bus, tk0_address, tk1_bus, tk1_address, tk_file, fsr_pinNum, fsr_max, sensorType)>0)
+	{
+		gShouldStop = 1;
+		cout << "control cannot start" << endl;
+		return -1;
+	}
+
+	for(int i=0; i<MAX_TOUCHES; i++)
+	{
+		s0Touches_[i]	= 0.0;
+		s0Size_[i]		= 0.0;
+
+		s1Touches_[i]	= 0.0;
+		s1Size_[i]	= 0.0;
+	}
+
+	return 0;
+}
+
+void sensorLoop(void *)
+{
+	timeval start, end;
+	unsigned long elapsedTime;
+	//float touchSize		= 0;	// once used for timbre
+
+
+
+	float *s0Touches;
+	float *s0Size;
+	int s0PrevTouchNum 	= 0;
+	int s0SortedTouchIndices[MAX_TOUCHES];
+	float s0SortedTouches[MAX_TOUCHES];
+	float s0PrevSortedTouches[MAX_TOUCHES];
+
+	float *s1Touches;
+	float *s1Size;
+	int s1PrevTouchNum 	= 0;
+	int s1SortedTouchIndices[MAX_TOUCHES];
+	float s1SortedTouches[MAX_TOUCHES];
+	float s1PrevSortedTouches[MAX_TOUCHES];
+
+	float freqScaler	= 0;
+	int fsrMin			= 0;//50; // was 200
+	int fsrMax			= 1799;//1300; // was 800
+	float vel			= 0;
+	float prevVel		= 0;
+	float filterMaxF	= 0;
+	if(gVerbose==1)
+		dbox_printf("__________set Control Thread priority\n");
+
+	if(gVerbose==1)
+		dbox_printf("_________________Control Thread!\n");
+
+	// get freq scaler, cos freqs must be scaled according to the wavetable used in the oscillator bank
+	freqScaler 		= gOscBanks[gCurrentOscBank]->getFrequencyScaler();
+	filterMaxF		= gOscBanks[gCurrentOscBank]->filterMaxF;
+
+	// init time vals
+	gettimeofday(&start, NULL);
+
+	// here we go, sensor loop until the end of the application
+	while(!gShouldStop)
+	{
+		gettimeofday(&end, NULL);
+		elapsedTime = ( (end.tv_sec*1000000+end.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
+		if( elapsedTime<4000 )
+			usleep(4000-elapsedTime);
+		else
+			dbox_printf("%d\n", (int)elapsedTime); // this print happens when something's gone bad...
+
+		if(Sensors.readSensors()==0)
+		{
+			s0TouchNum	= Sensors.getTKTouchCount(0);
+			s0Touches	= Sensors.getTKXPositions(0);
+			s0Size 		= Sensors.getTKTouchSize(0);
+
+			s1TouchNum	= Sensors.getTKTouchCount(1);
+			s1Touches	= Sensors.getTKXPositions(1);
+			s1Size 		= Sensors.getTKTouchSize(1);
+
+			for(int i=0; i<MAX_TOUCHES; i++)
+			{
+				s0Touches_[i]	= s0Touches[i];
+				s0Size_[i]		= s0Size[i];
+
+				s1Touches_[i]	= s1Touches[i];
+				s1Size_[i]		= s1Size[i];
+			}
+
+			gSensor0LatestTouchNum	= s0TouchNum;
+			if(s0TouchNum > 0)
+			{
+				//-----------------------------------------------------------------------------------
+				// timbre, speed and  pitch
+				//touchSize	 = 0;	\\ once used for timbre
+
+				// if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison]
+				if(s0PrevTouchNum!=s0TouchNum)
+				{
+					float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches
+					int ids[MAX_TOUCHES*(MAX_TOUCHES-1)];
+					// calculate all distance permutations between previous and current touches
+					for(int i=0; i<s0TouchNum; i++)
+					{
+						for(int p=0; p<s0PrevTouchNum; p++)
+						{
+							int index			= i*s0PrevTouchNum+p;	// permutation id [says between which touches we are calculating distance]
+							distances[index]	= fabs(s0Touches[i]-s0PrevSortedTouches[p]);
+							ids[index]			= index;
+							if(index>0)
+							{
+								// sort, from min to max distance
+								float tmp;
+								while(distances[index]<distances[index-1])
+								{
+									tmp				= ids[index-1];
+									ids[index-1]	= ids[index];
+									ids[index]		= tmp;
+
+									tmp				= distances[index-1];
+									distances[index-1] = distances[index];
+									distances[index] = tmp;
+
+									index--;
+
+									if(index == 0)
+										break;
+								}
+							}
+						}
+					}
+
+					int sorted = 0;
+					bool currAssigned[MAX_TOUCHES] = {false};
+					bool prevAssigned[MAX_TOUCHES] = {false};
+
+					// track touches assigning index according to shortest distance
+					for(int i=0; i<s0TouchNum*s0PrevTouchNum; i++)
+					{
+						int currentIndex	= ids[i]/s0PrevTouchNum;
+						int prevIndex		= ids[i]%s0PrevTouchNum;
+						// avoid double assignment
+						if(!currAssigned[currentIndex] && !prevAssigned[prevIndex])
+						{
+							currAssigned[currentIndex]	= true;
+							prevAssigned[prevIndex]		= true;
+							s0SortedTouchIndices[currentIndex] = prevIndex;
+							sorted++;
+						}
+					}
+					// we still have to assign a free index to new touches
+					if(s0PrevTouchNum<s0TouchNum)
+					{
+						for(int i=0; i<s0TouchNum; i++)
+						{
+							if(!currAssigned[i])
+								s0SortedTouchIndices[i] = sorted++; // assign next free index
+
+							// update tracked value
+							s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
+							s0PrevSortedTouches[i]			         = s0SortedTouches[i];
+							if(s0SortedTouchIndices[i]==s0TouchNum-1)
+								s0LastIndex = i;
+
+							// accumulate sizes for timbre
+							//touchSize += s0Size[i];
+						}
+					}
+					else // some touches have disappeared...
+					{
+						// ...we have to shift all indices...
+						for(int i=s0PrevTouchNum-1; i>=0; i--)
+						{
+							if(!prevAssigned[i])
+							{
+								for(int j=0; j<s0TouchNum; j++)
+								{
+									// ...only if touches that disappeared were before the current one
+									if(s0SortedTouchIndices[j]>i)
+										s0SortedTouchIndices[j]--;
+								}
+							}
+						}
+						// done! now update
+						for(int i=0; i<s0TouchNum; i++)
+						{
+							// update tracked value
+							s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
+							s0PrevSortedTouches[i]			         = s0SortedTouches[i];
+							if(s0SortedTouchIndices[i]==s0TouchNum-1)
+								s0LastIndex = i;
+
+							// accumulate sizes for timbre
+							//touchSize += s0Size[i];
+						}
+					}
+				}
+				else // nothing's changed since last round
+				{
+					for(int i=0; i<s0TouchNum; i++)
+					{
+						// update tracked value
+						s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
+						s0PrevSortedTouches[i]			         = s0SortedTouches[i];
+
+						// accumulate sizes for timbre
+						//touchSize += s0Size[i];
+					}
+				}
+
+				if(s0TouchNum == 0)
+					s0LastIndex = -1;
+
+				// timbre
+				//touchSize = (touchSize > 0.7) ? 1 : touchSize/0.7;
+				//gOscBanks[gCurrentOscBank]->hopNumTh = log((1-touchSize)+1)/log(2)*20000;
+				//gOscBanks[gCurrentOscBank]->hopNumTh = 0;
+
+
+				// pitch, controlled by last touch
+				//prevTouchPos 				= touch[touchIndex];
+				//touchPos	 			 	= (s0SortedTouches[s0TouchNum-1]-0.5)/0.5;	// from [0,1] to [-1,1]
+				gSensor0LatestTouchPos      = s0SortedTouches[s0TouchNum-1];
+				//touchPos					= s0Touches[0];
+				//gOscBanks[gCurrentOscBank]->pitchMultiplier 	= pow(2, touchPos);
+				//-----------------------------------------------------------------------------------
+
+
+
+				//-----------------------------------------------------------------------------------
+				// note on
+				//if(s0PrevTouchNum == 0)
+				//	gOscBanks[gCurrentOscBank]->play();
+				// fsr = Sensors.getFSRVAlue();
+				fsr = gLastFSRValue;
+				//dbox_printf("fsr: %d\n", fsr);
+				if(!gOscBanks[gCurrentOscBank]->note)
+				{
+					vel = fsr;
+					vel /= (float)(fsrMax-fsrMin);
+
+					vel = 1-vel;
+					dbox_printf("Attack vel: %f\n", vel);
+					gOscBanks[gCurrentOscBank]->play(vel);
+					prevVel = vel;
+				}
+				else if(gOscBanks[gCurrentOscBank]->getEnvelopeState() != env_release)
+				{
+					fsr = (fsr > fsrMax) ? fsrMax : fsr;
+					vel = (fsr < fsrMin) ? fsrMin : fsr;
+					vel -= fsrMin;
+					vel /= (float)(fsrMax-fsrMin);
+					vel = 1-vel;
+					if(vel > prevVel)
+					{
+						gOscBanks[gCurrentOscBank]->afterTouch(vel);
+						prevVel = vel;
+					}
+				}
+				//-----------------------------------------------------------------------------------
+			}
+			else
+			{
+				//prevFsr = 1799;
+				//prevTouchPos = -1;
+				//-----------------------------------------------------------------------------------
+				// note off
+				if(s0PrevTouchNum > 0)
+				{
+					if(gOscBanks[gCurrentOscBank]->state==bank_playing)
+						gOscBanks[gCurrentOscBank]->stop();
+				}
+				//-----------------------------------------------------------------------------------
+			}
+
+
+
+			// sensor 2
+			//-----------------------------------------------------------------------------------
+			//filter - calculated even when no touches on first sensor, to filter also release tail
+			gOscBanks[gCurrentOscBank]->filterNum	= s1TouchNum;
+
+			gSensor1LatestTouchCount = gOscBanks[gCurrentOscBank]->filterNum;
+			for(int i = 0; i < gSensor1LatestTouchCount; i++) {
+				gSensor1LatestTouchPos[i] = s1Touches[i];
+				//gSensor1LatestTouchSizes[i] = s1Size[i];
+			}
+
+/*			for(int i=0; i<gOscBanks[gCurrentOscBank]->filterNum; i++)
+			{
+				// touch pos is linear but freqs are log
+				gOscBanks[gCurrentOscBank]->filterFreqs[i] = ((exp(s0Touches[i]*4)-1)/(exp(4)-1))*filterMaxF*freqScaler;
+				//gOscBanks[gCurrentOscBank]->filterQ[i] = size[i]*5*(1+touch[i]*1000)*freqScaler;
+				gOscBanks[gCurrentOscBank]->filterQ[i] = s0Size[i];
+				if(gOscBanks[gCurrentOscBank]->filterFreqs[i]>500*freqScaler)
+					gOscBanks[gCurrentOscBank]->filterPadding[i] = 1+100000*( (gOscBanks[gCurrentOscBank]->filterFreqs[i]-500*freqScaler)/(filterMaxF-500)*freqScaler );
+				else
+					gOscBanks[gCurrentOscBank]->filterPadding[i] = 1;
+			}*/
+
+			// each touch on sensor 2 is a notch filter, whose Q is determined by touch size
+			for(int i=0; i<gOscBanks[gCurrentOscBank]->filterNum; i++)
+			{
+				// map touch pos [which is linear] on freqs exponentially
+				float freq = ((exp(s1Touches[i]*4)-1)/EXP_DENOM)*filterMaxF;
+				gOscBanks[gCurrentOscBank]->filterFreqs[i] = freq*freqScaler;
+				// also size is mapped exponentially on Q
+				float siz = (exp(s1Size[i])-1)/1.71828;
+				gOscBanks[gCurrentOscBank]->filterQ[i] = siz*( (filterMaxF-freq)/filterMaxF * 0.9 + 0.1 );	// size weight on Q decreases with frequency
+			}
+			//-----------------------------------------------------------------------------------
+
+
+
+			//-----------------------------------------------------------------------------------
+			// sort touches on sensor 2
+			if(s1TouchNum > 0)
+			{
+				// if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison]
+				if(s1PrevTouchNum!=s1TouchNum)
+				{
+					float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches
+					int ids[MAX_TOUCHES*(MAX_TOUCHES-1)];
+					// calculate all distance permutations between previous and current touches
+					for(int i=0; i<s1TouchNum; i++)
+					{
+						for(int p=0; p<s1PrevTouchNum; p++)
+						{
+							int index 			= i*s1PrevTouchNum+p;	// permutation id [says between which touches we are calculating distance]
+							distances[index]	= fabs(s1Touches[i]-s1PrevSortedTouches[p]);
+							ids[index]			= index;
+							if(index>0)
+							{
+								// sort, from min to max distance
+								float tmp;
+								while(distances[index]<distances[index-1])
+								{
+									tmp 				= ids[index-1];
+									ids[index-1] 		= ids[index];
+									ids[index] 			= tmp;
+
+									tmp					= distances[index-1];
+									distances[index-1]	= distances[index];
+									distances[index] 	= tmp;
+
+									index--;
+
+									if(index == 0)
+										break;
+								}
+							}
+						}
+					}
+
+					int sorted = 0;
+					bool currAssigned[MAX_TOUCHES] = {false};
+					bool prevAssigned[MAX_TOUCHES] = {false};
+
+					// track touches assigning index according to shortest distance
+					for(int i=0; i<s1TouchNum*s1PrevTouchNum; i++)
+					{
+						int currentIndex	= ids[i]/s1PrevTouchNum;
+						int prevIndex		= ids[i]%s1PrevTouchNum;
+						// avoid double assignment
+						if(!currAssigned[currentIndex] && !prevAssigned[prevIndex])
+						{
+							currAssigned[currentIndex]			= true;
+							prevAssigned[prevIndex]				= true;
+							s1SortedTouchIndices[currentIndex] = prevIndex;
+							sorted++;
+						}
+					}
+					// we still have to assign a free index to new touches
+					if(s1PrevTouchNum<s1TouchNum)
+					{
+						for(int i=0; i<s1TouchNum; i++)
+						{
+							if(!currAssigned[i])
+								s1SortedTouchIndices[i] = sorted++; // assign next free index
+
+							// update tracked value
+							s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
+							s1PrevSortedTouches[i]			       	 = s1SortedTouches[i];
+							if(s1SortedTouchIndices[i]==s1TouchNum-1)
+								s1LastIndex = i;
+						}
+					}
+					else // some touches have disappeared...
+					{
+						// ...we have to shift all indices...
+						for(int i=s1PrevTouchNum-1; i>=0; i--)
+						{
+							if(!prevAssigned[i])
+							{
+								for(int j=0; j<s1TouchNum; j++)
+								{
+									// ...only if touches that disappeared were before the current one
+									if(s1SortedTouchIndices[j]>i)
+										s1SortedTouchIndices[j]--;
+								}
+							}
+						}
+						// done! now update
+						for(int i=0; i<s1TouchNum; i++)
+						{
+							// update tracked value
+							s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
+							s1PrevSortedTouches[i]			       	 = s1SortedTouches[i];
+							if(s1SortedTouchIndices[i]==s1TouchNum-1)
+								s1LastIndex = i;
+						}
+					}
+				}
+				else // nothing's changed since last round
+				{
+					for(int i=0; i<s1TouchNum; i++)
+					{
+						// update tracked value
+						s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
+						s1PrevSortedTouches[i]			       	 = s1SortedTouches[i];
+					}
+				}
+			}
+
+			if(s1TouchNum > 0)
+			{
+				gSensor1LatestTouchIndex = s1LastIndex;
+			}
+			else
+				s1LastIndex = -1;
+
+/*			dbox_printf("-----------------------------\nnum: %d, latest: %d\n", s1TouchNum, gSensor1LatestTouchIndex);
+			for(int i=0; i<s1TouchNum; i++)
+				dbox_printf("\t%f\n", gSensor1LatestTouchPos[i]);
+			dbox_printf("------\n");
+			for(int i=0; i<s1TouchNum; i++)
+				dbox_printf("\t%f\n", s1SortedTouches[i]);*/
+
+
+
+			// update variables for both sensors
+			s0PrevTouchNum	= s0TouchNum;
+			s1PrevTouchNum	= s1TouchNum;
+		}
+		else
+			dbox_printf("Come on instrument!\n");	//break
+
+		gettimeofday(&start, NULL);
+	}
+
+	dbox_printf("sensor thread ended\n");
+}
+
+void *keyboardLoop(void *)
+{
+	if(gVerbose==1)
+		cout << "_________________Keyboard Control Thread!" << endl;
+
+	char keyStroke = '.';
+	cout << "Press q to quit." << endl;
+
+	float speed;
+
+	do
+	{
+		keyStroke =	getchar();
+		while(getchar()!='\n'); // to read the first stroke
+
+		switch (keyStroke)
+		{
+			//----------------------------------------------------------------------------
+			case 'a':
+				gOscBanks[gCurrentOscBank]->hopNumTh = 0;
+				gOscBanks[gCurrentOscBank]->play(1);
+				//cout << "Note on" << endl;
+				break;
+			case 's':
+				if(gOscBanks[gCurrentOscBank]->state==bank_playing)
+				{
+					gOscBanks[gCurrentOscBank]->stop();
+					//cout << "Note off" << endl;
+				}
+				break;
+			//----------------------------------------------------------------------------
+			case '[':
+				gOscBanks[gCurrentOscBank]->freqMovement-=0.05;
+				if(gOscBanks[gCurrentOscBank]->freqMovement<0)
+					gOscBanks[gCurrentOscBank]->freqMovement = 0;
+				//cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl;
+				break;
+			case ']':
+				gOscBanks[gCurrentOscBank]->freqMovement+=0.05;
+				if(gOscBanks[gCurrentOscBank]->freqMovement>1)
+					gOscBanks[gCurrentOscBank]->freqMovement = 1;
+				//cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl;
+				break;
+			//----------------------------------------------------------------------------
+			case '<':
+				speed = gOscBanks[gCurrentOscBank]->getSpeed() - 0.1 ;
+				gOscBanks[gCurrentOscBank]->setSpeed(speed);
+				dbox_printf("Speed: %f\n", speed);
+
+				break;
+			case '>':
+				speed = gOscBanks[gCurrentOscBank]->getSpeed() + 0.1 ;
+				gOscBanks[gCurrentOscBank]->setSpeed(speed);
+				dbox_printf("Speed: %f\n", speed);
+				break;
+			case '0':
+				speed = 0.1;
+				gOscBanks[gCurrentOscBank]->setSpeed(speed);
+				dbox_printf("Speed: %f\n", speed);
+				break;
+			case '1':
+				speed = 0.5;
+				gOscBanks[gCurrentOscBank]->setSpeed(speed);
+				dbox_printf("Speed: %f\n", speed);
+				break;
+			case '2':
+				speed = 1;
+				gOscBanks[gCurrentOscBank]->setSpeed(speed);
+				dbox_printf("Speed: %f\n", speed);
+				break;
+			case '3':
+				speed = 2;
+				gOscBanks[gCurrentOscBank]->setSpeed(speed);
+				dbox_printf("Speed: %f\n", speed);
+				break;
+			case '4':
+				speed = 3;
+				gOscBanks[gCurrentOscBank]->setSpeed(speed);
+				dbox_printf("Speed: %f\n", speed);
+				break;
+			//----------------------------------------------------------------------------
+			case 'z':
+				gOscBanks[gCurrentOscBank]->setJumpHop(0);
+				break;
+			case 'x':
+				gOscBanks[gCurrentOscBank]->setJumpHop(100);
+				break;
+			case 'c':
+				gOscBanks[gCurrentOscBank]->setJumpHop(600);
+				break;
+			case 'v':
+				gOscBanks[gCurrentOscBank]->setJumpHop(1100);
+				break;
+			case 'b':
+				gOscBanks[gCurrentOscBank]->setJumpHop(2000);
+				break;
+			case 'n':
+				gOscBanks[gCurrentOscBank]->setJumpHop(gOscBanks[gCurrentOscBank]->getLastHop());
+				break;
+			//----------------------------------------------------------------------------
+			case 'q':
+				gShouldStop = true;
+				break;
+			case 'o':
+				gNextOscBank = (gCurrentOscBank + 1) % gOscBanks.size();
+				break;
+			default:
+				break;
+			//----------------------------------------------------------------------------
+		}
+		usleep(1000); /* Wait 1ms to avoid checking too quickly */
+	}
+	while (keyStroke!='q');
+
+	cout << "keyboard thread ended" << endl;
+
+	return (void *)0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/sensors.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,19 @@
+/*
+ * sensors.h
+ *
+ *  Created on: May 28, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef SENSORS_H_
+#define SENSORS_H_
+
+#include "config.h"
+
+int initSensorLoop(int sensorAddress0, int sensorAddress1, int sensorType);
+
+void sensorLoop(void *);
+void *keyboardLoop(void *);
+
+
+#endif /* SENSORS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/spear_parser.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,641 @@
+/*
+ * spear_parser.cpp v1.2
+ *
+ *  Created on: May 6, 2014
+ *      Author: Victor Zappi
+ */
+
+#include "spear_parser.h"
+
+using namespace std;
+
+//#define DO_CHECKS
+
+//------------------------------------------------------------------------------------------------
+// partials
+//------------------------------------------------------------------------------------------------
+
+Partials::Partials()
+{
+	partialFrequencies	= NULL;
+//	partialAmplitudes	= NULL;
+//	partialNumFrames	= NULL;
+//	partialStartSample	= NULL;
+//	partialEndSample	= NULL;
+//	partialCurrentFrame	= NULL;
+//	partialFreqDelta	= NULL;
+//	partialAmpDelta	= NULL;
+
+
+	activePartialNum	= NULL;
+//	activePartials		= NULL;
+
+	currentSample = -1;
+}
+
+Partials::~Partials()
+{
+	if(partialFrequencies != NULL)			// check on one is enough
+	{
+		if(partialFrequencies[0] != NULL)	// check on one is enough
+		{
+			for(unsigned int i=0; i<parNum; i++)
+			{
+				delete[] partialFrequencies[i];
+				delete[] partialAmplitudes[i];
+				delete[] partialFreqDelta[i];
+				delete[] partialAmpDelta[i];
+
+			}
+		}
+
+		delete[] partialFrequencies;
+		delete[] partialAmplitudes;
+		delete[] partialNumFrames;
+		delete[] partialFreqDelta;
+		delete[] partialAmpDelta;
+		delete[] partialFreqMean;
+	}
+
+	if(activePartialNum != NULL)
+	{
+		for(unsigned int i=0; i<hopNum+1; i++)
+			delete[] activePartials[i];
+
+		delete[] activePartialNum;
+		delete[] activePartials ;
+	}
+}
+
+void Partials::init(int parN, int hopS, bool isDBX)
+{
+	if(!isDBX)
+	{
+		parNum	= parN;
+		hopSize	= hopS;
+
+		partialFrequencies	= new float *[parNum];
+		partialAmplitudes	= new float *[parNum];
+		partialNumFrames	= new unsigned int[parNum];
+		partialStartFrame	= new unsigned int[parNum];
+		partialStartSample	= new unsigned int[parNum];
+		partialEndSample	= new unsigned int[parNum];
+		partialFreqDelta	= new float *[parNum];
+		partialAmpDelta		= new float *[parNum];
+		partialFreqMean		= new float[parNum];
+
+
+
+		// init in one shot
+		fill(partialFreqMean, partialFreqMean+parNum, 0);			// mean is zero
+
+		partialFrequencies[0] 	= NULL;								// for free check
+	}
+	else
+	{
+		parNum	= parN;
+		hopSize	= hopS;
+
+		partialFrequencies	= new float *[parNum];
+		partialAmplitudes	= new float *[parNum];
+		partialNumFrames	= new unsigned int[parNum];
+		partialStartFrame	= new unsigned int[parNum];
+		partialFreqDelta	= new float *[parNum];
+		partialAmpDelta		= new float *[parNum];
+		partialFreqMean		= new float[parNum];
+
+		partialFrequencies[0] 	= NULL;								// for free check
+	}
+}
+
+
+
+void Partials::update(int parIndex, int frameNum)
+{
+	partialFrequencies[parIndex] = new float[frameNum];
+	partialAmplitudes[parIndex]	 = new float[frameNum];
+	partialFreqDelta[parIndex]	 = new float[frameNum];
+	partialAmpDelta[parIndex]	 = new float[frameNum];
+
+	fill(partialFreqDelta[parIndex], partialFreqDelta[parIndex]+frameNum, 99999.0);	// in the end, only the last one will have 99999
+	fill(partialAmpDelta[parIndex], partialAmpDelta[parIndex]+frameNum, 99999.0);	// in the end, only the last one will have 99999
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//------------------------------------------------------------------------------------------------
+// spear parser
+//------------------------------------------------------------------------------------------------
+Spear_parser::Spear_parser()
+{
+	// some default values
+	hopSize			= -1;
+	fileSampleRate	= -1;
+}
+
+Spear_parser::~Spear_parser()
+{
+}
+
+void Spear_parser::calculateHopSize(char *filename)
+{
+	int index 		= 0;
+	bool prevWas_ 	= false;
+	bool found_h	= false;
+	int n 			= 0;
+
+	hopSize 		= 0;
+
+	do
+	{
+		// check if '_'
+		if(filename[index] == '_')
+			prevWas_ = true;
+		else if( (filename[index] == 'h') && prevWas_) // if it is not, but it is 'h' and previous was '_', found "_h"!
+		{
+			found_h = true;
+			while(filename[index] != '\0')
+			{
+				index++;
+				if( (filename[index] == '.') || (filename[index] == '_'))
+					break;
+				else // i am not checking if char are digits...!
+				{
+					n = filename[index];
+					hopSize =  hopSize*10+(n-48);
+				}
+			}
+		}
+		else	// else, nothing
+			prevWas_ = false;
+		index++;
+	}
+	while( (filename[index] != '\0') && !found_h );
+
+	if( !found_h || (hopSize<1) )
+		hopSize = 551;	// default val
+
+}
+
+
+bool Spear_parser::parser(char *filename, int hopsize, int samplerate)
+{
+	string name = string(filename);
+	int len		= name.length();
+	// invoke correct parser according to the type of file...just checking the extension, crude but functional
+	if( (name[len-4]=='.') && (name[len-3]=='d') && (name[len-2]=='b') && (name[len-1]=='x') )
+		return DBXparser(filename, samplerate);				// .dbox
+	else
+		return TXTparser(filename, hopSize, samplerate);	// .txt, or whatever
+}
+
+
+bool Spear_parser::DBXparser(char *filename, int samplerate)
+{
+	fileSampleRate 	= samplerate;
+
+	// working vars
+	int parNum		= 0;	// total num of partials
+	int hopNum		= 0;	// total num of hops
+
+	//----------------------------------------------------------------------------------------
+	// open a file
+	ifstream fin;
+	fin.open(filename, ios::in | ios::binary);
+	if (!fin.good())
+	{
+		cout << "Parser Error: file not found" << endl;	// exit if file not found
+		return false;
+	}
+
+	gettimeofday(&start, NULL);
+	//----------------------------------------------------------------------------------------
+	// general data
+
+	// look for partial count
+	fin.read((char *) &parNum, sizeof(int));
+	partials.parNum 		= parNum;
+
+	// look for hop count
+	fin.read((char *) &hopNum, sizeof(int));
+	partials.setHopNum(hopNum);
+
+	// look for hop size
+	fin.read((char *) &hopSize, sizeof(int));
+	partials.hopSize 		= hopSize;		// it's handy for both classes to know it
+
+	// init partials data structure
+	partials.init(parNum, hopSize, true);
+
+	// look for max active par num
+	fin.read((char *) &(partials.maxActiveParNum), sizeof(int));
+
+
+
+	// partial data
+
+	// start frame of each partial
+	fin.read((char *) partials.partialStartFrame, sizeof(int)*parNum);
+
+	// num of frames of each partial
+	fin.read((char *) partials.partialNumFrames, sizeof(int)*parNum);
+
+	// frequency mean of each partial
+	fin.read((char *) partials.partialFreqMean, sizeof(int)*parNum);
+
+	for(int par=0; par<parNum; par++)
+	{
+		int frameNum = partials.partialNumFrames[par];
+		partials.update(par, frameNum);
+		fin.read((char *)partials.partialAmplitudes[par], sizeof(float)*frameNum);		// amplitude of each partial in each frame
+		fin.read((char *)partials.partialFrequencies[par], sizeof(float)*frameNum);		// frequency of each partial in each frame
+		fin.read((char *)partials.partialAmpDelta[par], sizeof(float)*frameNum);			// amplitude delta of each partial in each frame
+		fin.read((char *)partials.partialFreqDelta[par], sizeof(float)*frameNum);			// frequency delta of each partial in each frame
+	}
+
+
+
+
+	// frame data
+
+	// number of active partial per each frame
+	fin.read((char *) partials.activePartialNum, sizeof(short)*(hopNum+1));
+	// init array
+	for(int frame=0; frame<hopNum+1; frame++)
+	{
+		partials.activePartials[frame] = new unsigned int[partials.activePartialNum[frame]];
+		fin.read((char *)partials.activePartials[frame], sizeof(int)*partials.activePartialNum[frame]);			// active partials per each frame
+	}
+
+
+
+
+
+	gettimeofday(&stop, NULL);
+	parserT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
+
+
+	printf("\n-----------------------\n");
+	printf("\nFile: %s\n", filename);
+	printf("\n-----------------------\n");
+	printf("Profiler\n");
+	printf("-----------------------\n");
+	printf("File parser:\t\t\t%lu usec\n", parserT);
+	printf("\n\nTotal:\t\t%lu usec\n", parserT);
+	printf("-----------------------\n");
+
+	fin.close();
+
+	return true;
+}
+
+
+
+
+bool Spear_parser::TXTparser(char *filename, int hopsize, int samplerate)
+{
+	hopSize 		= hopsize;
+	fileSampleRate 	= samplerate;
+	if(hopsize<0)
+	{
+		gettimeofday(&start, NULL);
+		calculateHopSize(filename);
+		gettimeofday(&stop, NULL);
+		hopSizeT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
+	}
+	else
+		hopSizeT = 0;
+
+	calculateDeltaTime();
+
+	// working vars
+	char * token;			// where to save single figures from file
+	string s		= "";	// where to save lines from file
+	int parNum		= 0;	// total num of partials
+	int parIndex	= -1;	// index of current partial
+	int frameNum	= 0;	// total num of frames
+	int frameIndex	= -1;	// index of current frame
+	int startSample	= -1;	// sample value for first frame of partials
+	int endSample	= -1;	// sample value for last frame of partials
+	int maxSample	= 0;	// to calculate total number of hops in file
+	int missSampCnt = 0;	// number of mising samples
+	double freq		= 0;	// to calculate frequency delta
+	double prevFreq	= 0;	// to calculate frequency delta
+	double amp		= 0;	// to calculate amplitude delta
+	double prevAmp	= 0;	// to calculate amplitude delta
+
+
+	//----------------------------------------------------------------------------------------
+	// open a file
+	ifstream fin;
+	fin.open(filename);
+	if (!fin.good())
+	{
+		cout << "Parser Error: file not found" << endl;	// exit if file not found
+		return false;
+	}
+
+	gettimeofday(&start, NULL);
+	//----------------------------------------------------------------------------------------
+	// init partials data structure
+	getline(fin, s);
+	getline(fin, s);
+	getline(fin, s);	// third line is the first we are interested into
+
+	// look for partial count
+	token = strtok((char *)s.c_str(), " ");
+	// check if first token is there
+	if(token)
+	{
+		token = strtok(0, " ");
+		// check if second token is there
+		if(token)
+			parNum = atoi(token);
+		#ifdef DO_CHECKS
+		else
+		{
+			cout << "Parser Error: partial count not found, bad file format" << endl;	// exit if value not found
+			return false;
+		}
+		#endif
+	}
+	#ifdef DO_CHECKS
+	else
+	{
+		cout << "Parser Error: partial count not found, bad file format" << endl;		// exit if value not found
+		return false;
+	}
+	#endif
+	// from now on we take for granted that format is correct
+
+	// init partials data structure
+	partials.init(parNum, hopSize);
+
+	//----------------------------------------------------------------------------------------
+	// fill in partials data structure
+	getline(fin, s);		// get rid of intro line "partials-data"
+	getline(fin, s);		// first important line
+
+	while (!fin.eof())
+	{
+		//-------------------------------------
+		// partial specific info
+		token		= strtok((char *)s.c_str(), " ");
+		parIndex	= atoi(token);						// partial index
+
+		token		= strtok(0, " ");					// num of frames, not used, cos we will do linear interpolation for missing frames
+//		frameNum	= atoi(token);
+//		partials.partialNumFrames[parIndex]	= frameNum;
+
+		token		= strtok(0, " ");					// time of first frame, still char *
+		startSample = fromTimeToSamples(atof(token));	// convert time to samples
+		partials.partialStartSample[parIndex]	= startSample;
+
+		token		= strtok(0, " ");					// time of last frame, still char *
+		endSample	= fromTimeToSamples(atof(token)); 	// convert time to samples
+		partials.partialEndSample[parIndex]		= endSample;
+
+		frameNum	= ((endSample-startSample)/hopSize) + 1;	// num of frames, including missing consecutive ones [+1 one cos we count frames, not hops]
+		partials.partialNumFrames[parIndex]		= frameNum;
+
+
+		// check if this is the highest sample value so far
+		if(endSample > maxSample)
+			maxSample = endSample;
+
+		// update data structure
+		partials.update(parIndex, frameNum);
+
+
+		//-------------------------------------
+		// frames
+		getline(fin, s);
+		token		= strtok((char *)s.c_str(), " ");	// frame time
+		frameIndex	= -1;
+
+		// unroll first iteration, so that in the following loop we save the check on the last frame to calculate increments
+		if(token)						// all frames data are on one line, in groups of 3 entries
+		{
+			frameIndex++;
+
+			endSample	= fromTimeToSamples(atof(token));
+
+			token		= strtok(0, " ");	// frame frequency
+			prevFreq	= atof(token);
+			partials.partialFrequencies[parIndex][frameIndex]	= (float)prevFreq;
+			partials.partialFreqMean[parIndex] 					+= prevFreq;		// for frequency mean
+
+			token	 	= strtok(0, " ");	// frame amplitude
+			prevAmp  	= atof(token);
+			partials.partialAmplitudes[parIndex][frameIndex]	= (float)prevAmp;
+
+			token 		= strtok(0, " ");	// next frame frequency, to be checked
+		}
+
+		// here the loop starts
+		while(token)						// all frames data are on one line, in groups of 3 entries
+		{
+			frameIndex++;
+			missSampCnt 	= 0;
+
+			startSample		= fromTimeToSamples(atof(token));
+
+			token			= strtok(0, " ");	// frame frequency
+			freq			= atof(token);
+
+			token			= strtok(0, " ");	// frame amplitude
+			amp				= atof(token);
+			// now we know all about the current frame, but we want to know if some frames are missing between this and the last one
+
+			// while current frame sample is farther than one hopsize...
+			while(startSample > endSample+hopSize)
+			{
+				missSampCnt++;				// ...one sample is missing
+				endSample += hopSize;		// move to next hop
+			}
+
+			// if frames are missing do interpolation and update indices
+			if(missSampCnt>0)
+				startSample = interpolateSamples(parIndex, &frameIndex, missSampCnt, endSample+hopSize, freq, amp, &prevFreq, &prevAmp);
+
+			partials.partialFrequencies[parIndex][frameIndex]	= (float)freq;
+			partials.partialFreqMean[parIndex] 					+= freq;			// for frequency mean
+			partials.setFreqDelta(parIndex, frameIndex-1, (freq-prevFreq)/hopSize);	// freq delta between prev and current frame
+			prevFreq 	= freq;
+
+			partials.partialAmplitudes[parIndex][frameIndex]	= (float)amp;
+			partials.setAmpDelta(parIndex, frameIndex-1, (amp-prevAmp)/hopSize);	// amp delta between prev and current frame
+			prevAmp		= amp;
+
+			endSample	= startSample;
+			token		= strtok(0, " ");	// next frame frequency, to be checked
+		}
+		#ifdef DO_CHECKS
+		if(frameIndex != (frameNum-1))
+		{
+			cout << "Parser Error: frame count mismatch on partial " << parIndex << ", bad file format"  << endl;	// exit if mismatch
+			cout << "frameIndex: " << frameIndex << endl;
+			cout << "frameNum: " << frameNum << endl;
+			return false;
+		}
+		#endif
+
+		partials.partialFreqMean[parIndex] /= partials.partialNumFrames[parIndex];									// frequency mean
+
+		getline(fin, s);					// next partial line, to check
+	}
+	#ifdef DO_CHECKS
+	if(parIndex != (parNum-1))
+	{
+		cout << "Parser Error: partial count mismatch, bad file format"  << endl;									// exit if mismatch
+		return false;
+	}
+	#endif
+
+	partials.setHopNum(maxSample/hopSize);
+
+	gettimeofday(&stop, NULL);
+	parserT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
+
+	gettimeofday(&start, NULL);
+	staticCalculations();
+	gettimeofday(&stop, NULL);
+	staticT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
+
+	fin.close();
+
+
+	printf("\n-----------------------\n");
+	printf("\nFile: %s\n", filename);
+	printf("\n-----------------------\n");
+	printf("Profiler\n");
+	printf("-----------------------\n");
+	printf("Hop size parser:\t\t%lu usec\n", hopSizeT);
+	printf("File parser:\t\t\t%lu usec\n", parserT);
+	printf("Static calculations:\t\t%lu usec\n", staticT);
+	printf("\n\nTotal:\t\t%lu usec\n", hopSizeT+parserT+staticT);
+	printf("-----------------------\n");
+
+	return true;
+}
+
+
+int Spear_parser::interpolateSamples(int parIndex, int *frameIndex, int missCnt, int nextSample, double nextFreq, double nextAmp, double *prevFreq, double *prevAmp)
+{
+	int frame			= *frameIndex;						// current frame index
+	int sample			= nextSample - (hopSize*(missCnt)); // move from next real frame sample to first missing frame sample
+	double freq			= *prevFreq;						// freq of the prev real frame
+	double freqStep		= (nextFreq-*prevFreq)/(missCnt+1);	// fixed freq step between hops, for missing frames [linear interpolation]
+	double deltaFreq	= freqStep/hopSize;					// fixed hop freq step in samples
+	double amp			= *prevAmp;							// same for amp...
+	double ampStep		= (nextAmp-*prevAmp)/(missCnt+1);
+	double deltaAmp		= ampStep/hopSize;
+
+	// for each missing frame
+	for(int i=0; i<missCnt; i++)
+	{
+		// calculate values for current missing frame
+		freq	+= freqStep;
+		amp		+= ampStep;
+		// save values
+		partials.partialFrequencies[parIndex][frame]	= freq;
+		partials.partialAmplitudes[parIndex][frame]		= amp;
+		partials.partialFreqMean[parIndex]				+= freq;	// for frequency mean
+		// set deltas of previous frame [real or missing]
+		partials.setFreqDelta(parIndex, frame-1, deltaFreq);
+		partials.setAmpDelta(parIndex, frame-1, deltaAmp);
+		// move to next frame [missing or real]
+		sample += hopSize;
+		frame++;
+	}
+
+	// update global values
+	*frameIndex	= frame;
+	*prevFreq	= freq;
+	*prevAmp	= amp;
+
+	return sample;	// return the frame sample of the next real frame
+}
+
+
+
+// for each frame, statically calculate:
+// - which partial is active [and the total num of active partials]
+// - at which local frame each partial is
+void Spear_parser::staticCalculations()
+{
+	partials.maxActiveParNum = 0;				// init to find maximum
+
+	unsigned short *indices	= new unsigned short[partials.parNum];	// temp array to store up to the maximum num of active partial indices
+	unsigned int activeCnt	= 0;						// counts the num of active partials in each frame
+
+	unsigned int frameSample = 0;						// current frame in samples
+
+	char *partialStarted = new char [partials.parNum];	// index of the last local frame found per each partial
+	fill(partialStarted, partialStarted+partials.parNum, 0);
+
+	for(unsigned int i=0; i<partials.hopNum+1; i++)		// for each frame [not hops, this explains the +1]
+	{
+		//partials.localPartialFrames[i] = new int[partials.parNum];	// init all local frames to -1
+		//fill(partials.localPartialFrames[i], partials.localPartialFrames[i]+partials.parNum, -1);
+
+		frameSample = i*hopSize;	// current frame, expressed in samples
+		activeCnt	  = 0;			// reset a each frame
+
+		for(unsigned int j=0; j<partials.parNum; j++)	// for each partial
+		{
+			// check if inside active time region [expressed in samples]
+			if( (frameSample>=partials.partialStartSample[j]) && (frameSample<partials.partialEndSample[j]) )	// frame sample not equal to end sample, this filters out last frames and partials with one frame only
+			{
+				// activity
+				indices[activeCnt] = j;	// save active index
+				activeCnt++;			// increase counter
+
+				// partial local frames
+				if(partialStarted[j]==0)	// this partial has just started, so current local frame is first frame
+				{
+					partialStarted[j] 		 		= 1;
+					partials.partialStartFrame[j]	= i;	// here is the number of the first frame
+				}
+			}
+		}
+
+		// activity
+		partials.activePartialNum[i] = activeCnt;							// save number of active partials for this frame
+		partials.activePartials[i]	 = new unsigned int[activeCnt];					// set correct size to save all indices
+
+		// look for maximum number of active partials at the same time
+		if(activeCnt > partials.maxActiveParNum)
+			partials.maxActiveParNum = activeCnt;
+
+		// copy indices
+		for(unsigned int k=0; k<activeCnt; k++)
+			partials.activePartials[i][k] = indices[k];
+	}
+
+	delete[] indices;
+	delete[] partialStarted;
+
+	delete[] partials.partialStartSample;
+	delete[] partials.partialEndSample;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/d-box/spear_parser.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,188 @@
+/*
+ * spear_parser.h v1.2
+ *
+ *  Created on: May 6, 2014
+ *      Author: Victor Zappi
+ */
+
+#ifndef SPEAR_PARSER_H_
+#define SPEAR_PARSER_H_
+
+#include <iostream>
+#include <fstream>
+#include <cstring>
+#include <string>
+#include <stdlib.h>		// atoi, atof
+#include <math.h>
+#include <algorithm>	// std::fill
+
+#include <sys/time.h>
+
+using namespace std;
+
+
+//------------------------------------------------------------------------------------------------
+// partials
+//------------------------------------------------------------------------------------------------
+
+class Spear_parser; // for class friendship
+
+class Partials
+{
+	friend class Spear_parser;
+	friend class Dbox_parser;
+
+public:
+	int **partialSamples;				// sample at which each frame is
+	float **partialFrequencies;			// frequencies at each frame
+	float **partialAmplitudes;			// amplitudes at each frame
+	unsigned int *partialNumFrames;		// Length of each partial in frames
+	unsigned int *partialStartFrame;	// frame at which each partial begins
+	float **partialFreqDelta;			// constant frequency slope for each partial in each frame interval
+	float **partialAmpDelta;			// constant amplitude slope for each partial in each frame interval
+	float *partialFreqMean;				// frequency mean for each partial, over all its frames
+
+	unsigned short *activePartialNum;	// num of each active partial at each frame
+	unsigned int **activePartials;		// indices of all active partials at each frame
+
+
+	int getPartialNum();
+	int getHopNum();
+	int getMaxActivePartialNum();
+
+private:
+	Partials();
+	~Partials();
+
+	unsigned int *partialStartSample;	// sample at which each partial begins
+	unsigned int *partialEndSample;		// sample at which each partial ends [sample gap between 2 consecutive frames can be an integer multiple of hopSize]
+	unsigned int parNum;
+	unsigned int currentSample;
+	unsigned int hopSize;
+	unsigned int hopNum;
+	unsigned int maxActiveParNum;
+
+	void init(int parNum, int hopSize, bool isDBX=false);
+	void update(int parIndex, int frameNum);
+	void setFreqDelta(int parIndex, int frameNum, double delta);
+	void setAmpDelta(int parIndex, int frameNum, double delta);
+	void setHopNum(int hopNum);
+};
+
+inline int Partials::getPartialNum()
+{
+	return parNum;
+}
+
+inline void Partials::setHopNum(int hopN)
+{
+	hopNum = hopN;
+
+	// prepare data structures
+	activePartialNum 	= new unsigned short[hopNum+1];	// +1 cos total num of frames = num of hops+1
+	activePartials	 	= new unsigned int *[hopNum+1];
+}
+
+// useful to increase current sample using a modulo on the total number of samples [easy to be deduced from the total num or hops]
+inline int Partials::getHopNum()
+{
+	return hopNum;
+}
+
+inline void Partials::setFreqDelta(int parIndex, int frameNum, double delta)
+{
+	partialFreqDelta[parIndex][frameNum] = delta;
+}
+
+inline void Partials::setAmpDelta(int parIndex, int frameNum, double delta)
+{
+	partialAmpDelta[parIndex][frameNum] = delta;
+}
+
+inline int Partials::getMaxActivePartialNum()
+{
+	return maxActiveParNum;
+}
+
+
+
+
+
+
+
+//------------------------------------------------------------------------------------------------
+// spear parser
+//------------------------------------------------------------------------------------------------
+
+class Spear_parser
+{
+public:
+	Spear_parser();
+	~Spear_parser();
+
+	Partials partials;
+
+	bool parseFile(string filename, int hopsize=-1, int samplerate = 44100);
+	bool parseFile(char *filename, int hopsize=-1, int samplerate = 44100);
+	int getHopSize();
+	int getFileSampleRate();
+	double getDeltaTime();
+
+private:
+
+	int hopSize;
+	int fileSampleRate;
+	double deltaTime;	// min time gap between consecutive frames
+
+	timeval start, stop;
+	unsigned long hopSizeT, parserT, staticT;
+
+	void calculateDeltaTime();
+	void calculateHopSize(char *filename);
+	bool parser(char *filename, int hopsize=-1, int samplerate=44100);
+	bool DBXparser(char *filename, int samplerate=44100);
+	bool TXTparser(char *filename, int hopsize=-1, int samplerate=44100);
+	int fromTimeToSamples(float time);
+	int interpolateSamples(int parIndex, int *frameIndex, int missCnt, int nextSample,
+							double nextFreq, double nextAmp, double *prevFreq, double *prevAmp);
+	void staticCalculations();
+
+};
+
+inline bool Spear_parser::parseFile(string filename, int hopsize, int samplerate)
+{
+	return parser((char *)filename.c_str(), hopsize, samplerate);
+}
+
+inline bool Spear_parser::parseFile(char *filename, int hopsize, int samplerate)
+{
+	return parser(filename, hopsize, samplerate);
+}
+
+inline void Spear_parser::calculateDeltaTime()
+{
+	deltaTime = (double)hopSize/ (double)fileSampleRate;
+}
+
+// each time value in the file is rounded, and 2 consecutive frames can differ of a time gap = i*deltaTime, where i is a positive integer
+inline int Spear_parser::fromTimeToSamples(float time)
+{
+	return round(time/deltaTime)*hopSize;	// round is necessary since in the file log time values are rounded, so they do not apparently look like integer multiples of deltaTime
+}
+
+inline int Spear_parser::getHopSize()
+{
+	return hopSize;
+}
+
+inline int Spear_parser::getFileSampleRate()
+{
+	return fileSampleRate;
+}
+
+inline double Spear_parser::getDeltaTime()
+{
+	return deltaTime;
+}
+
+#endif /* SPEAR_PARSER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/oscillator_bank/audio_routines.S	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,161 @@
+@
+@ audio_routines.S
+@
+@ NEON-based functions for time-critical audio processing
+@
+@ Andrew McPherson 2014
+@ Queen Mary University of London
+@
+
+	.syntax unified
+	.arch armv7-a
+	.fpu neon
+
+@ 	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
+@							  int activePartialNum, int lookupTableSize,
+@							  float *phases, float *frequencies, float *amplitudes,
+@							  float *freqDerivatives, float *ampDerivatives,
+@							  float *lookupTable);
+
+@ Registers:
+@    r0: numAudioFrames        How many frames to render
+@    r1: audioOut              Buffer for audio output samples [stereo]
+@    r2: activePartialNum      How many active partials to render
+@    r3: lookupTableSize       Size of lookup table
+@    ---- other arguments start on the stack and are moved: -----
+@    r4: phases                Phase of each oscillator (pointer)
+@    r5: frequencies           Normalised frequency of each oscillator (pointer)
+@    r6: amplitudes            Normalised amplitude of each oscillator (pointer)
+@    r7: freqDerivatives       Derivative of frequency for each oscillator (pointer)
+@    r8: ampDerivatives        Derivative of amplitude for each oscillator (pointer)
+@    r9: lookupTable           Lookup table containing one oscillation
+@
+@ Alignment requirements:
+@    audioOut: 8-byte boundary
+@    phases: 16-byte boundary
+@    frequencies: 16-byte boundary
+@    amplitudes: 16-byte boundary
+@    freqDerivatives: 16-byte bounary
+@    ampDerivatives: 16-byte boundary
+@    lookupTable: 4-byte boundary (TODO: check this)
+
+	.align	2
+	.global	oscillator_bank_neon
+	.thumb
+	.thumb_func
+	.type	oscillator_bank_neon, %function
+oscillator_bank_neon:
+
+
+dSample		.dn		D6.F32
+qPhases		.qn		Q8.F32
+dPhases_0	.dn		D16.F32
+dPhases_1	.dn		D17.F32
+qFreqs		.qn		Q9.F32
+dFreqs_0	.dn		D18.F32
+dFreqs_1	.dn		D19.F32
+qAmps		.qn		Q10.F32
+dAmps_0		.dn		D20.F32
+dAmps_1		.dn		D21.F32
+qFreqDs		.qn		Q11.F32
+dFreqDs_0	.dn		D22.F32
+dFreqDs_1	.dn		D23.F32
+qAmpDs		.qn		Q12.F32
+dAmpDs_0	.dn		D24.F32
+dAmpDs_1	.dn		D25.F32
+
+qBaseInts	.qn		Q13.U32		@ Base indexes: unsigned ints x4
+dBaseInts_0	.dn		D26.U32
+dBaseInts_1	.dn		D27.U32
+qFractions  .qn     Q14.F32		@ Fraction indexes: floats x4
+qTableBase	.qn		Q15.U32		@ Base of lookup table
+
+	cmp r0, #0					@ Check for trivial case 1: zero frames
+	it eq
+	bxeq lr						@ Return if that's the case (otherwise might have odd behaviour)
+	cmp r2, #4					@ Check for trivial case 2: zero oscillators
+	it lt
+	bxlt lr						@ Return if that's the case
+
+	push {r4-r11}				@ Now arguments start 32 bytes above SP
+    add r11, sp, #32			@ Pointer to 32 bytes into the stack
+    ldm r11, {r4-r9}			@ Load 6 arguments into registers
+
+	vdup qTableBase, r9			@ Move lookup table base index into 4 ints
+
+	@ Outer loop: iterate over the number of oscillators, choosing 4 at a
+	@ time to work with.
+oscbank_oscillator_loop:
+	vld1 {dPhases_0, dPhases_1}, [r4]		@ no increment; will store at end of sample loop
+	vld1 {dFreqs_0, dFreqs_1}, [r5]
+	vld1 {dAmps_0, dAmps_1}, [r6]
+	vld1 {dFreqDs_0, dFreqDs_1}, [r7]!		@ increment; won't update at end of sample loop
+	vld1 {dAmpDs_0, dAmpDs_1}, [r8]!
+
+	push {r0-r1,r4-r8}
+	@ --- inner loop: iterate over the number of samples ---
+oscbank_sample_loop:
+	vcvt qBaseInts, qPhases		     		@ Take floor(phases)
+	vmov q2.f32, #1.0						@ Load 1.0 into every slot of q2
+	vshl q0.U32, qBaseInts, #2				@ Shift the indexes left 2 (*4 for float addressing)
+	vcvt qFractions, qBaseInts				@ int back to float
+	vadd q0.U32, q0.U32, qTableBase			@ Find memory addresses
+
+	vmov r4, r5, d0							@ Move two indexes to ARM registers
+	vmov r6, r7, d1							@ Move two more indexes to ARM registers
+	vsub qFractions, qPhases, qFractions	@ fraction = phase - floor(phase)
+
+	vldr.64	d0, [r4]						@ Load two consecutive floats at each location
+	vldr.64 d1, [r5]						@ These hold the previous and following samples in the table
+	vldr.64	d2, [r6]						@ TODO: check whether these work at 4-byte alignment
+	vldr.64 d3, [r7]
+
+	@ Format at this point:
+	@ Osc0(before) Osc0(after) Osc1(before) Osc1(after) Osc2(before) Osc2(after) Osc3(before) Osc3(after)
+	@ We want:
+	@ Osc0(before) Osc1(before) Osc2(before) Osc3(before) Osc0(after) Osc1(after) Osc2(after) Osc3(after)
+
+	vuzp.32 q0, q1							@ Now q0 contains before, q1 contains after
+	vsub q2.f32, q2.f32, qFractions			@ q2 = 1.0 - fraction
+	vmul q1.f32, q1.f32, qFractions			@ q1 = fraction * after
+	vmul q0.f32, q0.f32, q2.f32				@ q0 = (1.0 - fraction) * before
+
+	vadd qPhases, qPhases, qFreqs			@ Update phases
+	vadd qFreqs, qFreqs, qFreqDs			@ Update frequencies
+
+	vadd q0.f32, q0.f32, q1.f32				@ Add two interpolated components to get the final sample
+	vdup q2.u32, r3							@ Put lookup table size into each element of q2
+	vcvt qBaseInts, qPhases					@ Take floor of new phases
+	vmul q0.f32, q0.f32, qAmps				@ Multiply samples by current amplitude
+
+	vld1 dSample, [r1]						@ Load the current stereo samples
+	vpadd d2.f32, d0.f32, d1.f32			@ Pairwise accumulate q0 (output sample) into d2
+
+	vand q2, q2, qBaseInts					@ Logical AND of new phase int leaves 1 bit set only if phase >= table size
+	vpadd d3.f32, d2.f32, d2.f32			@ Pairwise accumulate d2 into d0 --> d0[0] and d0[1] both hold total of 4 oscillators
+	vadd qAmps, qAmps, qAmpDs				@ Update amplitudes
+	vcvt q0.f32, q2.u32						@ Convert int back to float after AND operation
+
+	vadd  dSample, dSample, d3.f32			@ Add oscillator outputs to each channel
+
+	subs r0, r0, #1							@ numFrames--
+	vsub qPhases, qPhases, q0.f32			@ Keep phases in table range
+	vst1 dSample, [r1]!						@ Store back in buffer and increment by 8
+
+	it gt
+	bgt oscbank_sample_loop					@ Loop if numFrames > 0
+
+	@ --- end inner loop ---
+	pop {r0-r1,r4-r8}						@ Restore registers: restores audioOut and numFrames, among others
+
+	vst1 {dPhases_0, dPhases_1}, [r4]!		@ Store phases back to array
+	vst1 {dFreqs_0, dFreqs_1}, [r5]!		@ Store frequencies back to array
+	vst1 {dAmps_0, dAmps_1}, [r6]!			@ Store amplitudes back to array
+											@ No need to update r7, r8
+
+	subs r2, r2, #4							@ numPartials -= 4
+	it  gt
+	bgt oscbank_oscillator_loop	@ Loop if numPartials > 0
+
+    pop {r4-r11}
+	bx lr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/oscillator_bank/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,116 @@
+/*
+ * main.cpp
+ *
+ *  Created on: Oct 24, 2014
+ *      Author: parallels
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+int gNumOscillators = 32;
+int gWavetableLength = 1024;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --num-oscillators [-n] oscs: Set the number of oscillators to use (default: 32)\n";
+	cerr << "   --wavetable [-w] length:     Set the wavetable length in samples (default: 1024)\n";
+	cerr << "   --help [-h]:                 Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"num-oscillators", 1, NULL, 'n'},
+		{"wavetable", 1, NULL, 'w'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hn:w:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'n':
+				gNumOscillators = atoi(optarg);
+				if(gNumOscillators <= 0) {
+					usage(basename(argv[0]));
+					exit(0);
+				}
+				break;
+		case 'w':
+				gWavetableLength = atoi(optarg);
+				if(gWavetableLength < 4)
+					gWavetableLength = 4;
+				if(gWavetableLength > 16384)
+					gWavetableLength = 16384;
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	if(settings.verbose) {
+		cout << "--> Using " << gNumOscillators << " oscillators and wavetable of " << gWavetableLength << " samples\n";
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/oscillator_bank/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,238 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\.io
+
+ */
+
+/*
+ * render.cpp
+ *
+ *  Created on: Oct 24, 2014
+ *      Author: parallels
+ */
+
+/**
+\example 4_oscillator_bank
+
+Oscillator Bank
+----------------------
+
+These files demonstrate an oscillator bank implemented in assembly code 
+that is used as part of the d-box project.
+*/
+
+#include <Bela.h>
+#include <rtdk.h>
+#include <cstdlib>
+#include <cmath>
+#include <cstring>
+#include <time.h>
+
+const float kMinimumFrequency = 20.0f;
+const float kMaximumFrequency = 8000.0f;
+
+float *gWavetable;		// Buffer holding the precalculated sine lookup table
+float *gPhases;			// Buffer holding the phase of each oscillator
+float *gFrequencies;	// Buffer holding the frequencies of each oscillator
+float *gAmplitudes;		// Buffer holding the amplitudes of each oscillator
+float *gDFrequencies;	// Buffer holding the derivatives of frequency
+float *gDAmplitudes;	// Buffer holding the derivatives of amplitude
+
+float gAudioSampleRate;
+int gSampleCount;		// Sample counter for indicating when to update frequencies
+float gNewMinFrequency;
+float gNewMaxFrequency;
+
+// Task for handling the update of the frequencies using the matrix
+AuxiliaryTask gFrequencyUpdateTask;
+
+// These settings are carried over from main.cpp
+// Setting global variables is an alternative approach
+// to passing a structure to userData in setup()
+
+extern int gNumOscillators;
+extern int gWavetableLength;
+
+void recalculate_frequencies();
+
+extern "C" {
+	// Function prototype for ARM assembly implementation of oscillator bank
+	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
+							  int activePartialNum, int lookupTableSize,
+							  float *phases, float *frequencies, float *amplitudes,
+							  float *freqDerivatives, float *ampDerivatives,
+							  float *lookupTable);
+}
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+bool setup(BelaContext *context, void *userData)
+{
+	srandom(time(NULL));
+
+	if(context->audioChannels != 2) {
+		rt_printf("Error: this example needs stereo audio enabled\n");
+		return false;
+	}
+
+	// Initialise the sine wavetable
+	if(posix_memalign((void **)&gWavetable, 8, (gWavetableLength + 1) * sizeof(float))) {
+		rt_printf("Error allocating wavetable\n");
+		return false;
+	}
+	for(int n = 0; n < gWavetableLength + 1; n++)
+		gWavetable[n] = sinf(2.0 * M_PI * (float)n / (float)gWavetableLength);
+
+	// Allocate the other buffers
+	if(posix_memalign((void **)&gPhases, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating phase buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gFrequencies, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating frequency buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gAmplitudes, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating amplitude buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gDFrequencies, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating frequency derivative buffer\n");
+		return false;
+	}
+	if(posix_memalign((void **)&gDAmplitudes, 16, gNumOscillators * sizeof(float))) {
+		rt_printf("Error allocating amplitude derivative buffer\n");
+		return false;
+	}
+
+	// Initialise buffer contents
+
+	float freq = kMinimumFrequency;
+	float increment = (kMaximumFrequency - kMinimumFrequency) / (float)gNumOscillators;
+
+	for(int n = 0; n < gNumOscillators; n++) {
+		gPhases[n] = 0.0;
+
+		if(context->analogFrames == 0) {
+			// Random frequencies when used without matrix
+			gFrequencies[n] = kMinimumFrequency + (kMaximumFrequency - kMinimumFrequency) * ((float)random() / (float)RAND_MAX);
+		}
+		else {
+			// Constant spread of frequencies when used with matrix
+			gFrequencies[n] = freq;
+			freq += increment;
+		}
+
+		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
+		gFrequencies[n] *= (float)gWavetableLength / context->audioSampleRate;
+		gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators;
+		gDFrequencies[n] = gDAmplitudes[n] = 0.0;
+	}
+
+	increment = 0;
+	freq = 440.0;
+
+	for(int n = 0; n < gNumOscillators; n++) {
+		// Update the frequencies to a regular spread, plus a small amount of randomness
+		// to avoid weird phase effects
+		float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
+		float newFreq = freq * randScale;
+
+		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
+		gFrequencies[n] = newFreq * (float)gWavetableLength / context->audioSampleRate;
+
+		freq += increment;
+	}
+
+	// Initialise auxiliary tasks
+	if((gFrequencyUpdateTask = Bela_createAuxiliaryTask(&recalculate_frequencies, 85, "bela-update-frequencies")) == 0)
+		return false;
+
+	//for(int n = 0; n < gNumOscillators; n++)
+	//	rt_printf("%f\n", gFrequencies[n]);
+
+	gAudioSampleRate = context->audioSampleRate;
+	gSampleCount = 0;
+
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	// Initialise buffer to 0
+	memset(context->audioOut, 0, 2 * context->audioFrames * sizeof(float));
+
+	// Render audio frames
+	oscillator_bank_neon(context->audioFrames, context->audioOut,
+			gNumOscillators, gWavetableLength,
+			gPhases, gFrequencies, gAmplitudes,
+			gDFrequencies, gDAmplitudes,
+			gWavetable);
+
+	if(context->analogFrames != 0 && (gSampleCount += context->audioFrames) >= 128) {
+		gSampleCount = 0;
+		gNewMinFrequency = map(context->analogIn[0], 0, 1.0, 1000.0f, 8000.0f);
+		gNewMaxFrequency = map(context->analogIn[1], 0, 1.0, 1000.0f, 8000.0f);
+
+		// Make sure max >= min
+		if(gNewMaxFrequency < gNewMinFrequency) {
+			float temp = gNewMaxFrequency;
+			gNewMaxFrequency = gNewMinFrequency;
+			gNewMinFrequency = temp;
+		}
+
+		// Request that the lower-priority task run at next opportunity
+		//Bela_scheduleAuxiliaryTask(gFrequencyUpdateTask);
+	}
+}
+
+// This is a lower-priority call to update the frequencies which will happen
+// periodically when the matrix is enabled. By placing it at a lower priority,
+// it has minimal effect on the audio performance but it will take longer to
+// complete if the system is under heavy audio load.
+
+void recalculate_frequencies()
+{
+	float freq = gNewMinFrequency;
+	float increment = (gNewMaxFrequency - gNewMinFrequency) / (float)gNumOscillators;
+
+	for(int n = 0; n < gNumOscillators; n++) {
+		// Update the frequencies to a regular spread, plus a small amount of randomness
+		// to avoid weird phase effects
+		float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
+		float newFreq = freq * randScale;
+
+		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
+		gFrequencies[n] = newFreq * (float)gWavetableLength / gAudioSampleRate;
+
+		freq += increment;
+	}
+}
+
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	free(gWavetable);
+	free(gPhases);
+	free(gFrequencies);
+	free(gAmplitudes);
+	free(gDFrequencies);
+	free(gDAmplitudes);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/tank_wars/game.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,339 @@
+/*
+ * game.cpp
+ *
+ *  Created on: Nov 10, 2014
+ *      Author: parallels
+ */
+
+#include <cmath>
+#include <cstdlib>
+#include "vector_graphics.h"
+#include <Utilities.h>
+
+// Virtual screen size
+int screenWidth, screenHeight;
+
+// Basic information on the terrain and the tanks
+float *groundLevel;  // Y coordinate of the ground for each X coordinate
+float tank1X, tank1Y, tank2X, tank2Y; // Positions of the two tanks
+float tankRadius = 20;  // Radius of the tanks
+float cannonLength = 40;   // How long the cannon on each tank extends
+float gravity = 0.05;      // Strength of gravity
+
+// Current state of the game
+int playerHasWon = 0; // 1 if player 1 wins, 2 if player 2 wins, 0 if game in progress
+bool player1Turn = true;  // true if it's player 1's turn; false otherwise
+float tank1CannonAngle = M_PI/2;
+float tank2CannonAngle = M_PI/2; // Direction the tank cannons are pointing
+float tank1CannonStrength = 3;
+float tank2CannonStrength = 3; // Strength of intended projectile launch
+
+// Location of the projectile
+bool projectileInMotion = false;
+float projectilePositionX, projectilePositionY;
+float projectileVelocityX, projectileVelocityY;
+
+// Infor needed for sound rendering
+bool collisionJustOccurred = false;
+bool tankHitJustOccurred = false;
+
+// Useful utility function for generating random floating-point values
+float randomFloat(float low, float hi)
+{
+	float r = (float)random() / (float)RAND_MAX;
+	return map(r, 0, 1, low, hi);
+}
+
+// Restart the game, without reallocating memory
+void restartGame()
+{
+	float player1Height = screenHeight * 3/4; // randomFloat(screenHeight/2, screenHeight-5);
+	float player2Height = screenHeight - 5; // randomFloat(screenHeight/2, screenHeight-5);
+	for(int i = 0; i < screenWidth * 0.2; i++) {
+		groundLevel[i] = player1Height;
+	}
+	for(int i = screenWidth * 0.2; i < screenWidth * 0.8; i++) {
+		groundLevel[i] = player1Height + (player2Height - player1Height) * (i - screenWidth*0.2)/(screenWidth*0.6);
+	}
+	for(int i = screenWidth * 0.8; i < screenWidth; i++) {
+		groundLevel[i] = player2Height;
+	}
+
+	// Set the location of the two tanks so they rest on the ground at opposite sides
+	tank1X = screenWidth * 0.1;
+	tank1Y = player1Height;
+	tank2X = screenWidth * 0.9;
+	tank2Y = player2Height;
+
+	playerHasWon = 0;
+	projectileInMotion = false;
+}
+
+// Initialise the game
+void setupGame(int width, int height)
+{
+	// Set the screen size
+	screenWidth = width;
+	screenHeight = height;
+
+	// Initialize the ground level
+	groundLevel = new float[screenWidth];
+
+	restartGame();
+}
+
+// Advance the turn to the next player
+void nextPlayersTurn() {
+	player1Turn = !player1Turn;
+}
+
+
+// Move forward one frame on the game physics
+void nextGameFrame()
+{
+	if(!projectileInMotion)
+		return;
+
+	// Update position of projectile
+	projectilePositionX += projectileVelocityX;
+	projectilePositionY += projectileVelocityY;
+	projectileVelocityY += gravity;
+
+	// Check collision with tanks first: a collision with tank 1 means player 2 wins and vice-versa
+	if((tank1X - projectilePositionX)*(tank1X - projectilePositionX) +
+		(tank1Y - projectilePositionY)*(tank1Y - projectilePositionY)
+		<= tankRadius * tankRadius)
+	{
+		projectileInMotion = false;
+		collisionJustOccurred = false;
+		tankHitJustOccurred = true;
+		playerHasWon = 2;
+	}
+	else if((tank2X - projectilePositionX)*(tank2X - projectilePositionX) +
+		(tank2Y - projectilePositionY)*(tank2Y - projectilePositionY)
+		<= tankRadius * tankRadius)
+	{
+		projectileInMotion = false;
+		collisionJustOccurred = false;
+		tankHitJustOccurred = true;
+		playerHasWon = 1;
+	}
+	else if(projectilePositionX < 0 || projectilePositionX >= screenWidth) {
+		// Check collision whether projectile has exited the screen to the left or right
+		projectileInMotion = false;
+		collisionJustOccurred = true;
+		nextPlayersTurn();
+	}
+	else if(projectilePositionY >= groundLevel[(int)floorf(projectilePositionX)]) {
+		// Check for projectile collision with ground
+		projectileInMotion = false;
+		collisionJustOccurred = true;
+		nextPlayersTurn();
+	}
+}
+
+// Updates for game state
+void setTank1CannonAngle(float angle)
+{
+	tank1CannonAngle = angle;
+}
+
+void setTank2CannonAngle(float angle)
+{
+	tank2CannonAngle = angle;
+}
+
+void setTank1CannonStrength(float strength)
+{
+	tank1CannonStrength = strength;
+}
+
+void setTank2CannonStrength(float strength)
+{
+	tank2CannonStrength = strength;
+}
+
+// FIRE!
+void fireProjectile()
+{
+	// Can't fire while projectile is already moving, or if someone has won
+	if(projectileInMotion)
+		return;
+	if(playerHasWon != 0)
+		return;
+
+    if(player1Turn) {
+		projectilePositionX = tank1X + cannonLength * cosf(tank1CannonAngle);
+		projectilePositionY = tank1Y - cannonLength * sinf(tank1CannonAngle);
+		projectileVelocityX = tank1CannonStrength * cosf(tank1CannonAngle);
+		projectileVelocityY = -tank1CannonStrength * sinf(tank1CannonAngle);
+    }
+    else {
+		projectilePositionX = tank2X + cannonLength * cosf(tank2CannonAngle);
+		projectilePositionY = tank2Y - cannonLength * sinf(tank2CannonAngle);
+		projectileVelocityX = tank2CannonStrength * cosf(tank2CannonAngle);
+		projectileVelocityY = -tank2CannonStrength * sinf(tank2CannonAngle);
+    }
+
+    // GO!
+    projectileInMotion = true;
+}
+
+// Game state queries
+bool gameStatusPlayer1Turn()
+{
+	return player1Turn;
+}
+
+bool gameStatusProjectileInMotion()
+{
+	return projectileInMotion;
+}
+
+int gameStatusWinner()
+{
+	return playerHasWon;
+}
+
+bool gameStatusCollisionOccurred()
+{
+	if(collisionJustOccurred) {
+		collisionJustOccurred = false;
+		return true;
+	}
+	return false;
+}
+
+bool gameStatusTankHitOccurred()
+{
+	if(tankHitJustOccurred) {
+		tankHitJustOccurred = false;
+		return true;
+	}
+	return false;
+}
+
+
+float gameStatusProjectileHeight()
+{
+	return projectilePositionY / (float)screenHeight;
+}
+
+// Clean up any allocated memory for the game
+void cleanupGame()
+{
+	delete groundLevel;
+}
+
+// Drawing routines. Arguments are (interleaved) buffer to render
+// into, the available size, and the target for how many samples
+// to use (actual usage might vary slightly). Regardless of
+// lengthTarget, never use more than bufferSize samples.
+
+int drawGround(float *buffer, int bufferSize, int framesTarget)
+{
+	int length;
+
+	// Calculate total length of ground line, to arrive at a speed calculation
+	float totalLineLength = 0.4f*screenWidth
+							+ sqrtf(0.36f*screenWidth*screenWidth
+									+ (tank2Y-tank1Y)*(tank2Y-tank1Y));
+
+	// Speed is calculated in pixels per frame
+	float speed = totalLineLength / (float)framesTarget;
+
+	// Draw three lines: platforms for tanks and the connecting line.
+	// Eventually, render a more complex ground from the array.
+	length = renderLine(0, tank1Y, screenWidth * 0.2, tank1Y,
+						speed, buffer, bufferSize);
+	length += renderLine(screenWidth * 0.2, tank1Y, screenWidth * 0.8, tank2Y,
+						speed, &buffer[length], bufferSize - length);
+	length += renderLine(screenWidth * 0.8, tank2Y, screenWidth, tank2Y,
+						speed, &buffer[length], bufferSize - length);
+
+	return length;
+}
+
+int drawTanks(float *buffer, int bufferSize, int framesTarget)
+{
+	int length = 0;
+
+	// Calculate total length of tank lines, to arrive at a speed calculation
+	float totalLineLength = 2.0*M_PI*tankRadius + 2.0*(cannonLength - tankRadius);
+
+	// Speed is calculated in pixels per frame
+	float speed = totalLineLength / (float)framesTarget;
+
+	if(playerHasWon != 2) {
+		// Tank 1 body = semicircle + line
+		length += renderArc(tank1X, tank1Y, tankRadius, M_PI, 2.0 * M_PI,
+							speed, buffer, bufferSize);
+		length += renderLine(tank1X + tankRadius, tank1Y,
+							 tank1X - tankRadius, tank1Y,
+							speed, &buffer[length], bufferSize - length);
+		// Tank 1 cannon (line depending on angle)
+		length += renderLine(tank1X + tankRadius * cosf(tank1CannonAngle),
+			 tank1Y - tankRadius * sinf(tank1CannonAngle),
+			 tank1X + cannonLength * cosf(tank1CannonAngle),
+			 tank1Y - cannonLength * sinf(tank1CannonAngle),
+			 speed, &buffer[length], bufferSize - length);
+	}
+
+	if(playerHasWon != 1) {
+		// Same idea for tank 2
+		length += renderArc(tank2X, tank2Y, tankRadius, M_PI, 2.0 * M_PI,
+							speed, &buffer[length], bufferSize - length);
+		length += renderLine(tank2X + tankRadius, tank2Y,
+							 tank2X - tankRadius, tank2Y,
+							 speed, &buffer[length], bufferSize - length);
+		length += renderLine(tank2X + tankRadius * cosf(tank2CannonAngle),
+			 tank2Y - tankRadius * sinf(tank2CannonAngle),
+			 tank2X + cannonLength * cosf(tank2CannonAngle),
+			 tank2Y - cannonLength * sinf(tank2CannonAngle),
+			 speed, &buffer[length], bufferSize - length);
+	}
+
+	return length;
+}
+
+int drawProjectile(float *buffer, int bufferSize, int framesTarget)
+{
+	if(!projectileInMotion)
+		return 0;
+
+	// Draw a point for a specified number of frames (each containing X and Y)
+	// Return the number of items used in the buffer, which will be twice
+	// the number of frames unless the buffer is full
+
+	if(bufferSize/2 < framesTarget) {
+		renderPoint(projectilePositionX, projectilePositionY, buffer, bufferSize/2);
+		return bufferSize;
+	}
+	else {
+		renderPoint(projectilePositionX, projectilePositionY, buffer, framesTarget);
+		return framesTarget*2;
+	}
+}
+
+// Main drawing routine entry point
+int drawGame(float *buffer, int bufferSize)
+{
+	int length;
+
+	// Based on buffer size, come up with speeds for each of the elements
+	// 50% of time to ground; 30% to the tanks and 20% to the projectile
+	// Give a margin of 25% beyond so we don't run out of buffer space
+	// if things take longer to draw than we guess they will
+	const float amountToUse = 0.375; // 0.75/2 because two samples per frame
+	const float groundFraction = 0.5 * amountToUse;
+	const float tankFraction = 0.3 * amountToUse;
+	const float projectileFraction = 0.2 * amountToUse;
+
+	length = drawGround(buffer, bufferSize, bufferSize * groundFraction);
+	length += drawTanks(&buffer[length], bufferSize - length,
+						bufferSize * tankFraction);
+	length += drawProjectile(&buffer[length], bufferSize - length,
+						bufferSize * projectileFraction);
+
+	return length;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/tank_wars/game.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,39 @@
+/*
+ * game.h
+ *
+ *  Created on: Nov 10, 2014
+ *      Author: parallels
+ */
+
+#ifndef GAME_H_
+#define GAME_H_
+
+// Initialisation
+void setupGame(int width, int height);
+void restartGame();
+
+// Update physics
+void nextGameFrame();
+
+// State updaters
+void setTank1CannonAngle(float angle);
+void setTank2CannonAngle(float angle);
+void setTank1CannonStrength(float strength);
+void setTank2CannonStrength(float strength);
+void fireProjectile();
+
+// State queries
+bool gameStatusPlayer1Turn();
+bool gameStatusProjectileInMotion();
+int gameStatusWinner();
+bool gameStatusCollisionOccurred();
+bool gameStatusTankHitOccurred();
+float gameStatusProjectileHeight();
+
+// Render screen; returns length of buffer used
+int drawGame(float *buffer, int bufferSize);
+
+// Cleanup and memory release
+void cleanupGame();
+
+#endif /* GAME_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/tank_wars/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,169 @@
+/*
+ * main.cpp
+ *
+ *  Created on: Oct 24, 2014
+ *      Author: parallels
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <sndfile.h>
+#include <Bela.h>
+
+extern int gScreenFramesPerSecond;
+
+float *gMusicBuffer = 0;
+int gMusicBufferLength = 0;
+float *gSoundBoomBuffer = 0;
+int gSoundBoomBufferLength = 0;
+float *gSoundHitBuffer = 0;
+int gSoundHitBufferLength = 0;
+
+
+using namespace std;
+
+// Load a sound sample from file
+int loadSoundFile(const string& path, float **buffer, int *bufferLength)
+{
+	SNDFILE *sndfile ;
+	SF_INFO sfinfo ;
+
+	if (!(sndfile = sf_open (path.c_str(), SFM_READ, &sfinfo))) {
+		cout << "Couldn't open file " << path << endl;
+		return 1;
+	}
+
+	int numChan = sfinfo.channels;
+	if(numChan != 1)
+	{
+		cout << "Error: " << path << " is not a mono file" << endl;
+		return 1;
+	}
+
+	*bufferLength = sfinfo.frames * numChan;
+	*buffer = new float[*bufferLength];
+	if(*buffer == 0){
+		cout << "Could not allocate buffer" << endl;
+		return 1;
+	}
+
+	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
+	int readcount = sf_read_float(sndfile, *buffer, *bufferLength);
+
+	// Pad with zeros in case we couldn't read whole file
+	for(int k = readcount; k < *bufferLength; k++)
+		(*buffer)[k] = 0;
+
+	sf_close(sndfile);
+	return 0;
+}
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --fps [-f] value:           Set target frames per second\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	string musicFileName = "music.wav";
+	string soundBoomFileName = "boom.wav";
+	string soundHitFileName = "hit.wav";
+	
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"fps", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'f':
+				gScreenFramesPerSecond = atoi(optarg);
+				if(gScreenFramesPerSecond < 1)
+					gScreenFramesPerSecond = 1;
+				if(gScreenFramesPerSecond > 100)
+					gScreenFramesPerSecond = 100;
+				break;
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Load the sound files
+	if(loadSoundFile(musicFileName, &gMusicBuffer, &gMusicBufferLength) != 0) {
+		cout << "Warning: unable to load sound file " << musicFileName << endl;
+	}
+	if(loadSoundFile(soundBoomFileName, &gSoundBoomBuffer, &gSoundBoomBufferLength) != 0) {
+		cout << "Warning: unable to load sound file " << soundBoomFileName << endl;
+	}
+	if(loadSoundFile(soundHitFileName, &gSoundHitBuffer, &gSoundHitBufferLength) != 0) {
+		cout << "Warning: unable to load sound file " << soundHitFileName << endl;
+	}
+	
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// Release sound files
+	if(gMusicBuffer != 0)
+		free(gMusicBuffer);
+	if(gSoundBoomBuffer != 0)
+		free(gSoundBoomBuffer);
+	if(gSoundHitBuffer != 0)
+		free(gSoundHitBuffer);
+	
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/tank_wars/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,337 @@
+/*
+ * render.cpp
+ *
+ *  Created on: Oct 24, 2014
+ *      Author: parallels
+ */
+
+
+#include <Bela.h>
+#include "game.h"
+#include <rtdk.h>
+#include <cmath>
+#include <cstdlib>
+#include <time.h>
+
+int gAudioFramesPerMatrixFrame = 2; // Ratio in audio to matrix sample rate
+
+int gInputTank1Angle = 0;		// Inputs for the cannon angles
+int gInputTank2Angle = 1;
+int gInputLauncher = 2;			// Input for launcher FSR
+
+int gOutputX = 0;				// Outputs for the scope
+int gOutputY = 1;
+int gOutputPlayer1LED = 2;
+int gOutputPlayer2LED = 3;
+
+int gGameFramesPerSecond = 60;	// How often the physics are updated
+int gGameFrameInterval;			// ...and in frames
+int gSamplesUntilNextFrame;		// Counter until next update
+int gSamplesSinceFinish = 0;	// How long since somebody won?
+bool gGameShouldRestart = false;// Whether we need to reinitiliase the game
+
+// Counter for overall number of samples that have elapsed
+unsigned int gSampleCounter = 0;
+
+// 1st-order filter and peak detector for launcher input
+float gLauncherLastSample = 0;
+float gLauncherFilterPole = 0.8;
+float gLauncherPeakValue = 0;
+float gLauncherPeakFilterPole = 0.999;
+float gLauncherNoiseThreshold = 0.01;
+float gLauncherMinimumPeak = 0.1;
+bool gLauncherTriggered = false;
+
+// Screen update rate; affects buffer size. Actual contents of buffer
+// may be smaller than this
+int gScreenWidth = 512;
+int gScreenHeight = 512;
+int gScreenFramesPerSecond = 25;
+
+// Double buffer for rendering screen. Each is an interleaved buffer
+// of XY data.
+float *gScreenBuffer1, *gScreenBuffer2;
+float *gScreenBufferWrite, *gScreenBufferRead;
+int gScreenBufferMaxLength;				// What is the total buffer allocated?
+int gScreenBufferReadLength;			// How long is the read buffer?
+int gScreenBufferWriteLength;			// How long is the write (next) buffer?
+int gScreenBufferReadPointer;			// Where are we in the read buffer now?
+int gScreenBufferNextUpdateLocation;	// When should we render the next buffer?
+bool gScreenNextBufferReady;			// Is the next buffer ready to go?
+
+// Auxiliary (low-priority) task for updating the screen
+AuxiliaryTask gScreenUpdateTask;
+
+// Buffers for music and sound effects
+extern float *gMusicBuffer;
+extern int gMusicBufferLength;
+extern float *gSoundBoomBuffer;
+extern int gSoundBoomBufferLength;
+extern float *gSoundHitBuffer;
+extern int gSoundHitBufferLength;
+
+// Current state for sound and music
+int gMusicBufferPointer = 0;	  // 0 means start of buffer...
+int gSoundBoomBufferPointer = -1; // -1 means don't play...
+int gSoundHitBufferPointer = -1;
+float gSoundProjectileOscillatorPhase = 0;
+float gSoundProjectileOscillatorGain = 0.2;
+float gOscillatorPhaseScaler = 0;
+
+void screen_update();
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+bool setup(BelaContext *context, void *userData)
+{
+	srandom(time(NULL));
+
+	// Verify we are running with matrix enabled
+	if(context->analogFrames == 0 || context->analogChannels < 4) {
+		rt_printf("Error: this example needs the matrix enabled with at least 4 channels\n");
+		return false;
+	}
+
+	// Initialise audio variables
+	gAudioFramesPerMatrixFrame = context->audioFrames / context->analogFrames;
+	gOscillatorPhaseScaler = 2.0 * M_PI / context->audioSampleRate;
+
+	// Initialise the screen buffers
+	gScreenBufferMaxLength = 2 * context->analogSampleRate / gScreenFramesPerSecond;
+	gScreenBuffer1 = new float[gScreenBufferMaxLength];
+	gScreenBuffer2 = new float[gScreenBufferMaxLength];
+	if(gScreenBuffer1 == 0 || gScreenBuffer2 == 0) {
+		rt_printf("Error initialising screen buffers\n");
+		return false;
+	}
+
+	gScreenBufferRead = gScreenBuffer1;
+	gScreenBufferWrite = gScreenBuffer2;
+	gScreenBufferReadLength = gScreenBufferWriteLength = 0;
+	gScreenBufferReadPointer = 0;
+	gScreenBufferNextUpdateLocation = 0;
+	gScreenNextBufferReady = false;
+
+	// Initialise the game
+	setupGame(gScreenWidth, gScreenHeight);
+	gGameFrameInterval = context->analogSampleRate / gGameFramesPerSecond;
+	gSamplesUntilNextFrame = gGameFrameInterval;
+
+	// Initialise auxiliary tasks
+	if((gScreenUpdateTask = Bela_createAuxiliaryTask(&screen_update, 90,
+														 "bela-screen-update")) == 0)
+		return false;
+
+	return true;
+}
+
+// Swap buffers on the screen
+void swap_buffers()
+{
+	if(gScreenBufferRead == gScreenBuffer1) {
+		gScreenBufferRead = gScreenBuffer2;
+		gScreenBufferWrite = gScreenBuffer1;
+	}
+	else {
+		gScreenBufferRead = gScreenBuffer1;
+		gScreenBufferWrite = gScreenBuffer2;
+	}
+
+	gScreenBufferReadLength = gScreenBufferWriteLength;
+	gScreenBufferReadPointer = 0;
+
+	// Schedule next update for 3/4 of the way through the buffer
+	gScreenBufferNextUpdateLocation = gScreenBufferReadLength * 0.75;
+	gScreenNextBufferReady = false;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	int audioIndex = 0;
+
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
+		for(int k = 0; k < gAudioFramesPerMatrixFrame; k++) {
+			// Render music and sound
+			float audioSample = 0;
+
+			// Music plays in a loop
+			if(gMusicBuffer != 0 && gMusicBufferPointer >= 0) {
+				audioSample += gMusicBuffer[gMusicBufferPointer++];
+				if(gMusicBufferPointer >= gMusicBufferLength)
+					gMusicBufferPointer = 0;
+			}
+
+			// Sound effect plays until finished, then stops
+			if(gSoundBoomBuffer != 0 && gSoundBoomBufferPointer >= 0) {
+				audioSample += gSoundBoomBuffer[gSoundBoomBufferPointer++];
+				if(gSoundBoomBufferPointer >= gSoundBoomBufferLength)
+					gSoundBoomBufferPointer = -1;
+			}
+
+			if(gSoundHitBuffer != 0 && gSoundHitBufferPointer >= 0) {
+				audioSample += gSoundHitBuffer[gSoundHitBufferPointer++];
+				if(gSoundHitBufferPointer >= gSoundHitBufferLength)
+					gSoundHitBufferPointer = -1;
+			}
+
+			// Oscillator plays to indicate projectile height
+			if(gameStatusProjectileInMotion()) {
+				audioSample += gSoundProjectileOscillatorGain * sinf(gSoundProjectileOscillatorPhase);
+
+				gSoundProjectileOscillatorPhase += gOscillatorPhaseScaler * constrain(map(gameStatusProjectileHeight(),
+						1.0, 0, 300, 2000), 200, 6000);
+				if(gSoundProjectileOscillatorPhase > 2.0 * M_PI)
+					gSoundProjectileOscillatorPhase -= 2.0 * M_PI;
+			}
+
+			context->audioOut[2*audioIndex] = context->audioOut[2*audioIndex + 1] = audioSample;
+			audioIndex++;
+		}
+
+		// First-order lowpass filter to remove noise on launch FSR
+		float rawSample = analogRead(context, n, gInputLauncher);
+		float launchSample = gLauncherFilterPole * gLauncherLastSample +
+							(1.0f - gLauncherFilterPole) * rawSample;
+		gLauncherLastSample = launchSample;
+
+		// Peak-detect on launch signal
+		if(launchSample >= gLauncherPeakValue) {
+			gLauncherPeakValue = launchSample;
+			gLauncherTriggered = false;
+		}
+		else {
+			if(gLauncherPeakValue - launchSample > gLauncherNoiseThreshold && !gLauncherTriggered) {
+				// Detected a peak; is it big enough overall?
+				if(gLauncherPeakValue >= gLauncherMinimumPeak) {
+					gLauncherTriggered = true;
+					// Peak detected-- fire!!
+					// Set both cannon strengths but only one will
+					// fire depending on whose turn it is
+					float strength = map(gLauncherPeakValue,
+									     gLauncherMinimumPeak, 1.0,
+										 0.5f, 10.0f);
+					setTank1CannonStrength(strength);
+					setTank2CannonStrength(strength);
+					fireProjectile();
+				}
+			}
+
+			gLauncherPeakValue *= gLauncherPeakFilterPole;
+		}
+
+		if(--gSamplesUntilNextFrame <= 0) {
+			// Update game physics and cannon angles
+			gSamplesUntilNextFrame = gGameFrameInterval;
+
+			setTank1CannonAngle(map(analogRead(context, n, gInputTank1Angle),
+									0, 1.0, M_PI, 0));
+			setTank2CannonAngle(map(analogRead(context, n, gInputTank2Angle),
+									0, 1.0, M_PI, 0));
+			nextGameFrame();
+
+			// Check for collision and start sound accordingly
+			if(gameStatusCollisionOccurred()) {
+				gSoundBoomBufferPointer = 0;
+			}
+			
+			if(gameStatusTankHitOccurred()) {
+				gSoundHitBufferPointer = 0;
+			}
+		}
+
+		if(gScreenBufferReadPointer >= gScreenBufferReadLength - 1
+			&& gScreenNextBufferReady) {
+			// Got to the end; swap buffers
+			swap_buffers();
+		}
+
+		// Push current screen buffer to the matrix output
+		if(gScreenBufferReadPointer < gScreenBufferReadLength - 1) {
+			float x = gScreenBufferRead[gScreenBufferReadPointer++];
+			float y = gScreenBufferRead[gScreenBufferReadPointer++];
+
+			// Rescale screen coordinates to matrix ranges; invert the Y
+			// coordinate to go from normal screen coordinates to scope coordinates
+			analogWriteOnce(context, n, gOutputX, constrain(map(x, 0, gScreenWidth, 0, 1.0), 0, 1.0));
+			analogWriteOnce(context, n, gOutputY, constrain(map(y, 0, gScreenHeight, 1.0, 0), 0, 1.0));
+		}
+		else {
+			// Still not ready! Write 0 until something happens
+			analogWriteOnce(context, n, gOutputX, 0);
+			analogWriteOnce(context, n, gOutputY, 0);
+		}
+
+		if(gameStatusWinner() != 0) {
+			// Blink one LED to show who won
+			// Blink both LEDs when projectile is in motion
+			float val = (gSampleCounter % 4000 > 2000) ? 1.0 : 0;
+			analogWriteOnce(context, n, gOutputPlayer1LED, gameStatusWinner() == 1 ? val : 0);
+			analogWriteOnce(context, n, gOutputPlayer2LED, gameStatusWinner() == 2 ? val : 0);
+
+			// After 5 seconds, restart the game
+			gSamplesSinceFinish++;
+			if(gSamplesSinceFinish > 22050*5)
+				gGameShouldRestart = true;
+		}
+		else if(gameStatusProjectileInMotion()) {
+			// Blink both LEDs when projectile is in motion
+			float val = (gSampleCounter % 2000 > 1000) ? 1.0 : 0;
+			analogWriteOnce(context, n, gOutputPlayer1LED, val);
+			analogWriteOnce(context, n, gOutputPlayer2LED, val);
+		}
+		else if(gameStatusPlayer1Turn()) {
+			analogWriteOnce(context, n, gOutputPlayer1LED, 1.0);
+			analogWriteOnce(context, n, gOutputPlayer2LED, 0);
+		}
+		else {
+			analogWriteOnce(context, n, gOutputPlayer2LED, 1.0);
+			analogWriteOnce(context, n, gOutputPlayer1LED, 0);
+		}
+
+		// Check if we have reached the point where we should next update
+		if(gScreenBufferReadPointer >= gScreenBufferNextUpdateLocation &&
+		   !gScreenNextBufferReady) {
+			// Update the screen at lower priority than the audio thread
+			Bela_scheduleAuxiliaryTask(gScreenUpdateTask);
+		}
+
+		gSampleCounter++;
+	}
+}
+
+void screen_update()
+{
+	// If we should restart, reinitialise the game
+	if(gGameShouldRestart) {
+		restartGame();
+		gGameShouldRestart = false;
+		gSamplesSinceFinish = 0;
+	}
+
+	// Render the game based on the current state
+	gScreenBufferWriteLength = drawGame(gScreenBufferWrite, gScreenBufferMaxLength);
+
+	// Flag it as ready to go
+	gScreenNextBufferReady = true;
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	// Clean up the game state
+	cleanupGame();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/tank_wars/vector_graphics.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,72 @@
+/*
+ * vector_graphics.cpp
+ *
+ *  Created on: Nov 10, 2014
+ *      Author: parallels
+ */
+
+#include <cmath>
+
+// Draw a line between two points at a specified rate in
+// pixels per buffer sample. Indicate maximum available space.
+// Returns space used
+int renderLine(float x1, float y1, float x2, float y2, float speed,
+			   float *buffer, int maxLength) {
+	// Figure out length of line and therefore how many samples
+	// are needed to represent it based on the speed (rounded to nearest int)
+	float totalLineLength = sqrtf((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
+	int samplesNeeded = floorf(totalLineLength / speed + 0.5);
+
+	// Now render into the buffer
+	int length = 0;
+	float scaleFactor = 1.0f / samplesNeeded;
+	for(int n = 0; n < samplesNeeded; n++) {
+		if(length >= maxLength - 1)
+			return length;
+		// X coordinate
+		*buffer++ = x1 + (float)n * scaleFactor * (x2 - x1);
+		// Y coordinate
+		*buffer++ = y1 + (float)n * scaleFactor * (y2 - y1);
+		length += 2;
+	}
+
+	return length;
+}
+
+// Draw an arc around a centre point at a specified rate of pixels
+// per buffer sample. Indicate maximum available space.
+// Returns space used
+int renderArc(float x, float y, float radius, float thetaMin, float thetaMax,
+			  float speed, float *buffer, int maxLength) {
+	// Figure out circumference of arc and therefore how many samples
+	// are needed to represent it based on the speed (rounded to nearest int)
+	float circumference = (thetaMax - thetaMin) * radius;
+	int samplesNeeded = floorf(circumference / speed + 0.5);
+
+	// Now render into the buffer
+	int length = 0;
+	float scaleFactor = 1.0f / samplesNeeded;
+	for(int n = 0; n < samplesNeeded; n++) {
+		if(length >= maxLength - 1)
+			return length;
+		// Get current angle
+		float theta = thetaMin + (float)n * scaleFactor * (thetaMax - thetaMin);
+
+		// Convert polar to cartesian coordinates
+		*buffer++ = x + radius * cosf(theta);
+		*buffer++ = y + radius * sinf(theta);
+
+		length += 2;
+	}
+
+	return length;
+}
+
+// Draw a single point for a specified number of frames
+void renderPoint(float x, float y, float *buffer, float length) {
+	while(length > 0) {
+		*buffer++ = x;
+		*buffer++ = y;
+		length--;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/10-Instruments/tank_wars/vector_graphics.h	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,18 @@
+/*
+ * vector_graphics.h
+ *
+ *  Created on: Nov 10, 2014
+ *      Author: parallels
+ */
+
+#ifndef VECTOR_GRAPHICS_H_
+#define VECTOR_GRAPHICS_H_
+
+int renderLine(float x1, float y1, float x2, float y2, float speed,
+			   float *buffer, int maxLength);
+int renderArc(float x, float y, float radius, float thetaMin, float thetaMax,
+			  float speed, float *buffer, int maxLength);
+void renderPoint(float x, float y, float *buffer, float length);
+
+
+#endif /* VECTOR_GRAPHICS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/11-Extras/7segment/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,142 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+
+#define NUM_PINS 12
+
+// Breadboard wiring layout:
+// 11 10 12 9  8  7
+// [ LED DISP ]
+// 1  2  3  6  4  5
+
+// Organised by display segments:
+// e d . X c g b X X X f a
+const int kPins[NUM_PINS] = {P8_07, P8_08, P8_09, P8_10, P8_11, P8_12,
+							 P8_15, P8_16, P8_27, P8_28, P8_29, P8_30};
+
+// Indices into the above array: pins 12, 9, 8, 6
+const int kDigits[4] = {9, 8, 7, 3};
+
+int gCurrentlyDisplayingDigit = 0;
+int gDigitDisplayTime = 0;
+const int kDigitMaxDisplayTime = 44;
+
+int gState = 0;
+int gStateCounter = 0;
+const int kMaxState = 25;
+
+// . g f e d c b a
+//const unsigned char kBELA[4] = {0x7C, 0x79, 0x38, 0x77};
+const unsigned char kBELA[4] = {0x7C, 0x7B, 0x38, 0x5F};
+const unsigned char kPerimeter[6] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20};
+
+int gCharacterToDisplay[4] = {0, 0, 0, 0};
+	
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+bool setup(BelaContext *context, void *userData)
+{	
+	// This project makes the assumption that the audio and digital
+	// sample rates are the same. But check it to be sure!
+	if(context->audioFrames != context->digitalFrames) {
+		rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
+		return false;
+	}
+	
+	for(int i = 0; i < NUM_PINS; i++) {
+		pinMode(context, 0, kPins[i], OUTPUT);
+	}
+
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		// Check for rotation between digits
+		if(--gDigitDisplayTime <= 0) {
+			gCurrentlyDisplayingDigit = (gCurrentlyDisplayingDigit + 1) % 4;
+			gDigitDisplayTime = kDigitMaxDisplayTime;
+		}
+	
+		// Write the currently displaying digit low and the rest high
+		for(int i = 0; i < 4; i++)
+				digitalWriteOnce(context, n, kPins[kDigits[i]], HIGH);
+		digitalWriteOnce(context, n, kPins[kDigits[gCurrentlyDisplayingDigit]], LOW);
+		
+		// Write the digit to the other outputs
+		digitalWriteOnce(context, n, kPins[11],
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x01);	// a
+		digitalWriteOnce(context, n, kPins[6], 
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x02);	// b
+		digitalWriteOnce(context, n, kPins[4], 
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x04);	// c
+		digitalWriteOnce(context, n, kPins[1],
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x08);	// d
+		digitalWriteOnce(context, n, kPins[0],
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x10);	// e
+		digitalWriteOnce(context, n, kPins[10],
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x20);	// f
+		digitalWriteOnce(context, n, kPins[5],
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x40);	// g
+		digitalWriteOnce(context, n, kPins[2],
+			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x80);	// .
+			
+		// Check for changing state
+		if(--gStateCounter <= 0) {
+			gState = (gState + 1) % kMaxState;
+			if(gState != (kMaxState - 1)) {
+				for(int i = 0; i < 4; i++)
+					gCharacterToDisplay[i] = 1 << (gState % 6);
+				gStateCounter = 2000;
+			}
+			else {
+				for(int i = 0; i < 4; i++)
+					gCharacterToDisplay[i] = kBELA[i];
+				gStateCounter = 50000;
+			}
+		}
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/11-Extras/cape-test/main.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,97 @@
+/*
+ * main.cpp
+ *
+ *  Created on: Oct 24, 2014
+ *      Author: parallels
+ */
+#include <unistd.h>
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <Bela.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	Bela_usage();
+
+	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BelaInitSettings settings;	// Standard audio settings
+	float frequency = 440.0;	// Frequency of oscillator
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	Bela_defaultSettings(&settings);
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case 'f':
+				frequency = atof(optarg);
+				break;
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(Bela_initAudio(&settings, &frequency) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(Bela_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	Bela_stopAudio();
+
+	// Clean up any resources allocated for audio
+	Bela_cleanupAudio();
+
+	// All done!
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/11-Extras/cape-test/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,279 @@
+/*
+ * render.cpp
+ *
+ *  Created on: Oct 24, 2014
+ *      Author: parallels
+ */
+
+
+#include <Bela.h>
+#include <cmath>
+
+#define ANALOG_LOW	(2048.0 / 65536.0)
+#define ANALOG_HIGH (50000.0 / 65536.0)
+
+const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7};
+
+enum {
+	kStateTestingAudioLeft = 0,
+	kStateTestingAudioRight,
+	kStateTestingAudioDone
+};
+
+uint64_t gLastErrorFrame = 0;
+uint32_t gEnvelopeSampleCount = 0;
+float gEnvelopeValueL = 0.5, gEnvelopeValueR = 0.5;
+float gEnvelopeDecayRate = 0.9995;
+int gEnvelopeLastChannel = 0;
+
+float gPositivePeakLevels[2] = {0, 0};
+float gNegativePeakLevels[2] = {0, 0};
+float gPeakLevelDecayRate = 0.999;
+const float gPeakLevelLowThreshold = 0.02;
+const float gPeakLevelHighThreshold = 0.2;
+const float gDCOffsetThreshold = 0.1;
+int gAudioTestState = kStateTestingAudioLeft;
+int gAudioTestStateSampleCount = 0;
+int gAudioTestSuccessCounter = 0;
+const int gAudioTestSuccessCounterThreshold = 64;
+const int gAudioTestStateSampleThreshold = 16384;
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+bool setup(BelaContext *context, void *userData)
+{
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	static float phase = 0.0;
+	static int sampleCounter = 0;
+	static int invertChannel = 0;
+	float frequency = 0;
+
+	// Play a sine wave on the audio output
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		
+		// Peak detection on the audio inputs, with offset to catch
+		// DC errors
+		for(int ch = 0; ch < 2; ch++) {
+			if(context->audioIn[2*n + ch] > gPositivePeakLevels[ch])
+				gPositivePeakLevels[ch] = context->audioIn[2*n + ch];
+			gPositivePeakLevels[ch] += 0.1;
+			gPositivePeakLevels[ch] *= gPeakLevelDecayRate;
+			gPositivePeakLevels[ch] -= 0.1;
+			if(context->audioIn[2*n + ch] < gNegativePeakLevels[ch])
+				gNegativePeakLevels[ch] = context->audioIn[2*n + ch];
+			gNegativePeakLevels[ch] -= 0.1;			
+			gNegativePeakLevels[ch] *= gPeakLevelDecayRate;
+			gNegativePeakLevels[ch] += 0.1;
+		}
+		
+		if(gAudioTestState == kStateTestingAudioLeft) {
+			context->audioOut[2*n] = 0.2 * sinf(phase);
+			context->audioOut[2*n + 1] = 0;		
+			
+			frequency = 3000.0;
+			phase += 2.0 * M_PI * frequency / 44100.0;
+			if(phase >= 2.0 * M_PI)
+				phase -= 2.0 * M_PI;
+			
+			gAudioTestStateSampleCount++;
+			if(gAudioTestStateSampleCount >= gAudioTestStateSampleThreshold) {
+				// Check if we have the expected input: signal on the left but not
+				// on the right. Also check that there is not too much DC offset on the
+				// inactive signal
+				if((gPositivePeakLevels[0] - gNegativePeakLevels[0]) >= gPeakLevelHighThreshold 
+					&& (gPositivePeakLevels[1] -  gNegativePeakLevels[1]) <= gPeakLevelLowThreshold &&
+					fabsf(gPositivePeakLevels[1]) < gDCOffsetThreshold &&
+					fabsf(gNegativePeakLevels[1]) < gDCOffsetThreshold) {
+					// Successful test: increment counter
+					gAudioTestSuccessCounter++;
+					if(gAudioTestSuccessCounter >= gAudioTestSuccessCounterThreshold) {
+						gAudioTestState = kStateTestingAudioRight;
+						gAudioTestStateSampleCount = 0;
+						gAudioTestSuccessCounter = 0;
+					}
+
+				}
+				else {
+					if(!((context->audioFramesElapsed + n) % 22050)) {
+						// Debugging print messages
+						if((gPositivePeakLevels[0] - gNegativePeakLevels[0]) < gPeakLevelHighThreshold)
+							rt_printf("Left Audio In FAIL: insufficient signal: %f\n", 
+										gPositivePeakLevels[0] - gNegativePeakLevels[0]);
+						else if(gPositivePeakLevels[1] -  gNegativePeakLevels[1] > gPeakLevelLowThreshold)
+							rt_printf("Right Audio In FAIL: signal present when it should not be: %f\n",
+										gPositivePeakLevels[1] -  gNegativePeakLevels[1]);
+						else if(fabsf(gPositivePeakLevels[1]) >= gDCOffsetThreshold ||
+								fabsf(gNegativePeakLevels[1]) >= gDCOffsetThreshold)
+							rt_printf("Right Audio In FAIL: DC offset: (%f, %f)\n",
+										gPositivePeakLevels[1], gNegativePeakLevels[1]);						
+					}
+					gAudioTestSuccessCounter--;
+					if(gAudioTestSuccessCounter <= 0)
+						gAudioTestSuccessCounter = 0;
+				}
+			}
+		}
+		else if(gAudioTestState == kStateTestingAudioRight) {
+			context->audioOut[2*n] = 0;
+			context->audioOut[2*n + 1] = 0.2 * sinf(phase);
+			
+			frequency = 3000.0;
+			phase += 2.0 * M_PI * frequency / 44100.0;
+			if(phase >= 2.0 * M_PI)
+				phase -= 2.0 * M_PI;
+			
+			gAudioTestStateSampleCount++;
+			if(gAudioTestStateSampleCount >= gAudioTestStateSampleThreshold) {
+				// Check if we have the expected input: signal on the left but not
+				// on the right
+				if((gPositivePeakLevels[1] - gNegativePeakLevels[1]) >= gPeakLevelHighThreshold 
+					&& (gPositivePeakLevels[0] -  gNegativePeakLevels[0]) <= gPeakLevelLowThreshold &&
+					fabsf(gPositivePeakLevels[0]) < gDCOffsetThreshold &&
+					fabsf(gNegativePeakLevels[0]) < gDCOffsetThreshold) {
+					// Successful test: increment counter
+					gAudioTestSuccessCounter++;
+					if(gAudioTestSuccessCounter >= gAudioTestSuccessCounterThreshold) {
+						gAudioTestSuccessCounter = 0;							
+						gAudioTestStateSampleCount = 0;
+						gAudioTestState = kStateTestingAudioDone;
+					}
+				}
+				else {
+					if(!((context->audioFramesElapsed + n) % 22050)) {
+						// Debugging print messages
+						if((gPositivePeakLevels[1] - gNegativePeakLevels[1]) < gPeakLevelHighThreshold)
+							rt_printf("Right Audio In FAIL: insufficient signal: %f\n", 
+										gPositivePeakLevels[1] - gNegativePeakLevels[1]);
+						else if(gPositivePeakLevels[0] -  gNegativePeakLevels[0] > gPeakLevelLowThreshold)
+							rt_printf("Left Audio In FAIL: signal present when it should not be: %f\n",
+										gPositivePeakLevels[0] -  gNegativePeakLevels[0]);
+						else if(fabsf(gPositivePeakLevels[0]) >= gDCOffsetThreshold ||
+								fabsf(gNegativePeakLevels[0]) >= gDCOffsetThreshold)
+							rt_printf("Left Audio In FAIL: DC offset: (%f, %f)\n",
+										gPositivePeakLevels[0], gNegativePeakLevels[0]);						
+					}
+					gAudioTestSuccessCounter--;
+					if(gAudioTestSuccessCounter <= 0)
+						gAudioTestSuccessCounter = 0;
+				}
+			}			
+		}
+		else {
+			// Audio input testing finished. Play tones depending on status of
+			// analog testing
+			context->audioOut[2*n] = gEnvelopeValueL * sinf(phase);
+			context->audioOut[2*n + 1] = gEnvelopeValueR * sinf(phase);
+
+			// If one second has gone by with no error, play one sound, else
+			// play another
+			if(context->audioFramesElapsed + n - gLastErrorFrame > 44100) {
+				gEnvelopeValueL *= gEnvelopeDecayRate;
+				gEnvelopeValueR *= gEnvelopeDecayRate;
+				gEnvelopeSampleCount++;
+				if(gEnvelopeSampleCount > 22050) {
+					if(gEnvelopeLastChannel == 0)
+						gEnvelopeValueR = 0.5;
+					else
+						gEnvelopeValueL = 0.5;
+					gEnvelopeLastChannel = !gEnvelopeLastChannel;
+					gEnvelopeSampleCount = 0;
+				}
+				frequency = 880.0;
+			}
+			else {
+				gEnvelopeValueL = gEnvelopeValueR = 0.5;
+				gEnvelopeLastChannel = 0;
+				frequency = 220.0;
+			}
+
+			phase += 2.0 * M_PI * frequency / 44100.0;
+			if(phase >= 2.0 * M_PI)
+				phase -= 2.0 * M_PI;
+		}
+	}
+
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
+		// Change outputs every 512 samples
+		if(sampleCounter < 512) {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel)
+					context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH;
+				else
+					context->analogOut[n*8 + gDACPinOrder[k]] = 0;
+			}
+		}
+		else {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel)
+					context->analogOut[n*8 + gDACPinOrder[k]] = 0;
+				else
+					context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH;
+			}
+		}
+
+		// Read after 256 samples: input should be low
+		if(sampleCounter == 256) {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel) {
+					if(context->analogIn[n*8 + k] < ANALOG_HIGH) {
+						rt_printf("FAIL [output %d, input %d] -- output HIGH input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
+						gLastErrorFrame = context->audioFramesElapsed + n;
+					}
+				}
+				else {
+					if(context->analogIn[n*8 + k] > ANALOG_LOW) {
+						rt_printf("FAIL [output %d, input %d] -- output LOW --> input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
+						gLastErrorFrame = context->audioFramesElapsed + n;
+					}
+				}
+			}
+		}
+		else if(sampleCounter == 768) {
+			for(int k = 0; k < 8; k++) {
+				if(k == invertChannel) {
+					if(context->analogIn[n*8 + k] > ANALOG_LOW) {
+						rt_printf("FAIL [output %d, input %d] -- output LOW input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
+						gLastErrorFrame = context->audioFramesElapsed + n;
+					}
+				}
+				else {
+					if(context->analogIn[n*8 + k] < ANALOG_HIGH) {
+						rt_printf("FAIL [output %d, input %d] -- output HIGH input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
+						gLastErrorFrame = context->audioFramesElapsed + n;
+					}
+				}
+			}
+		}
+
+		if(++sampleCounter >= 1024) {
+			sampleCounter = 0;
+			invertChannel++;
+			if(invertChannel >= 8)
+				invertChannel = 0;
+		}
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/11-Extras/gpioAnalogLoopbackTest/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,209 @@
+#include <Bela.h>
+#include <cmath>
+#include <rtdk.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stats.hpp>
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+
+// digital inputs can be changed at will (as they are all being processed at the same time)
+// analog channels must be as per below
+int gAnalogOutCh = 1;
+int gDigitalOutCh = 2;
+int gDigitalInACh = 0;
+int gDigitalInDCh = 3;
+int gAnalogOutLoopDelay;
+int gDigitalOutLoopDelay;
+bool setup(BelaContext *context, void *userData)
+{
+	rt_printf("For this test you need the following connections:\n"
+			"analog%d out->digital%d in, analog%d out->analog%d in, "
+			"digital%d out -> digital%d in, digital%d out-> analog%d in\n",
+			gAnalogOutCh, gDigitalInACh, gAnalogOutCh, 0, gDigitalOutCh, gDigitalInDCh, gDigitalOutCh, 0);
+	rt_printf("Running test with %d analog channels and a buffer size of %d\n",
+			context->analogChannels, context->audioFrames);
+
+	for(unsigned int n = 0; n < context->digitalFrames; n++){
+		pinMode(context, n, gDigitalInACh, INPUT);
+		pinMode(context, n, gDigitalInDCh, INPUT);
+		pinMode(context, n, gDigitalOutCh, OUTPUT);
+	}
+	switch (context->analogChannels){
+		case 2:
+			gAnalogOutLoopDelay = context->audioFrames*2 + 3;
+			gDigitalOutLoopDelay = context->audioFrames*2 + 2;
+			break;
+		case 4:
+			gAnalogOutLoopDelay = context->audioFrames*2 + 3;
+			gDigitalOutLoopDelay = context->audioFrames*2 + 2;
+			break;
+		case 8:
+			gAnalogOutLoopDelay = context->audioFrames + 3;
+			gDigitalOutLoopDelay = context->audioFrames + 1;
+			break;
+		default:
+			exit(2);
+	}
+
+    return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numAnalogFrames
+// will be 0.
+
+const int patternLength = 31;
+static int anaErrorCount = 0;
+static int digErrorCount = 0;
+void render(BelaContext *context, void *userData)
+{
+	static bool writePattern[patternLength] = {
+									0,1,0,1,0,0,1,1,
+									0,0,0,1,1,1,0,0,
+									1,1,1,1,0,0,0,0,
+									1,1,1,1,1,0,0};
+//	for(int n = 0; n < patternLength; n++){
+//		writePattern[n]=1;
+//	}
+	static int inPointer = 0;
+	static int outPointer = 0;
+	static int digitalOutPointer = 0;
+	static int digitalInPointer = 0;
+	static int analogOut = 1;
+	/** Checking offset between analog and digital
+	 * how it should be :
+	 * The PRU loop does the following (the loop runs at 88.2kHz):
+	 * - Read/write audio sample (once for the left channel, once for the right channel)
+	 * - Write DAC 0 or 0/2 or 0/2/4/6
+	 * - Read ADC 0 or 0/2 or 0/2/4/6, 2 samples (@176.4) older than NOW
+	 * - /During/ the line above, every two loops we also Read/Write GPIO,
+	 * therefore reading on ADC 0/2/4/6 a value that is being output from GPIO will lead to undefined results
+	 * - Write DAC 1 or 1/3 or 1/3/5/7
+	 * - Read ADC 1 or 1/3 or 1/3/5/7, 2 samples (@176.4) older than NOW
+	 */
+	if(1)
+	for(unsigned int n = 0; n < context->audioFrames; n++){
+		static bool analog0In = false;
+		static bool digitalAIn = false;
+		static int count = 0;
+		bool doReadWrite = context->analogChannels<=4 ? true : ((context->analogChannels == 8) && (n&1)==0);
+		if(doReadWrite){
+			digitalAIn = digitalRead(context, n, gDigitalInACh);
+			switch(context->analogChannels){
+			case 8:
+				analog0In = analogRead(context, n/2, 0) > 0.5;
+				analogWrite(context, n/2, analogOut, writePattern[outPointer]);
+				break;
+			case 4:
+				analog0In = analogRead(context, n, 0) > 0.5;
+				analogWrite(context, n, analogOut, writePattern[outPointer]);
+				break;
+			case 2:
+				analog0In = analogRead(context, n * 2 + 1, 0) > 0.5;
+				analogWrite(context, 2 * n, analogOut, writePattern[outPointer]);
+				analogWrite(context, 2 * n + 1, analogOut, writePattern[outPointer]);
+				break;
+			}
+			gAnalogOutLoopDelay--;
+			outPointer++;
+			if(gAnalogOutLoopDelay <= 0){
+				if(++inPointer == patternLength){
+					inPointer = 0;
+				}
+			}
+		}
+		bool expectedIn = writePattern[inPointer];
+		if(gAnalogOutLoopDelay <= 0 && doReadWrite == true){
+			if(analog0In != expectedIn || digitalAIn != expectedIn){
+				rt_printf("expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n",
+					expectedIn, analog0In, digitalAIn, inPointer, gAnalogOutLoopDelay, count);
+				anaErrorCount++;
+			}
+		}
+		count++;
+		if(analog0In != digitalAIn){ // at any time the analog and digital in should be the same
+			rt_printf("ana %d_%d %d,\n", analog0In, digitalAIn, n);
+		}
+		if(outPointer == patternLength){
+			outPointer = 0;
+		}
+	}
+	if(1)
+	for(unsigned int n = 0; n < context->audioFrames; n++){
+		static int count = 0;
+		static bool analog1In = false;
+		static bool digitalDIn = false;
+/* we need to remember the pastAnalog1In because
+ *  reading GPIO takes place before writing to it, therefore
+ *  when reading a GPIOout, the GPIOin samples will always be one sample late
+ */
+		bool doReadWrite = false;
+		static bool pastAnalog1In = false;
+		digitalWriteOnce(context, n, gDigitalOutCh,  writePattern[digitalOutPointer]);
+		if(context->analogChannels == 8){
+			if((n&1) == 0){ //do it every other sample
+				pastAnalog1In = analogRead(context, n/2, 1) > 0.5;
+				digitalDIn = digitalRead(context, n, gDigitalInDCh);
+				doReadWrite = true;
+			}
+		}
+		if(context->analogChannels == 4){
+			pastAnalog1In = analogRead(context, n, 1) > 0.5;
+			digitalDIn = digitalRead(context, n, gDigitalInDCh);
+			digitalWriteOnce(context, n, gDigitalOutCh,  writePattern[digitalOutPointer]);
+			doReadWrite = true;
+		}
+		if(context->analogChannels == 2){
+			pastAnalog1In = analogRead(context, n * 2, 1) > 0.5;
+			digitalDIn = digitalRead(context, n, gDigitalInDCh);
+			digitalWriteOnce(context, n, gDigitalOutCh,  writePattern[digitalOutPointer]);
+			doReadWrite = true;
+		}
+		bool expectedDigitalIn = writePattern[digitalInPointer];
+		if(doReadWrite == true){
+			gDigitalOutLoopDelay--;
+			if(gDigitalOutLoopDelay <= 0){
+				if(expectedDigitalIn != pastAnalog1In || expectedDigitalIn != digitalDIn){
+					rt_printf("D expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n",
+						expectedDigitalIn, pastAnalog1In, digitalDIn, inPointer, gDigitalOutLoopDelay, count);
+					digErrorCount++;
+				}
+				if(++digitalInPointer == patternLength){
+					digitalInPointer = 0;
+				}
+			}
+			pastAnalog1In = analog1In;
+			if(++digitalOutPointer == patternLength){
+				digitalOutPointer = 0;
+			}
+		}
+		count++;
+	}
+	if(context->audioFramesElapsed > 30000){
+		gShouldStop = true;
+	}
+}
+
+
+void cleanup(BelaContext *context, void *userData)
+{
+	if(anaErrorCount == 0 && digErrorCount == 0){
+		rt_printf("Test was succesful with %d analog channels and a buffer size of %d\n", context->analogChannels, context->audioFrames);
+	} else {
+		rt_printf("------------------------\n%danalog %ddigital errors over %dsamples while running test with ",
+				anaErrorCount, digErrorCount, context->audioFramesElapsed);
+		rt_printf("%d analog channels and a buffer size of %d \n\n\n",
+				context->analogChannels, context->audioFrames);
+		exit(1);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/11-Extras/stepper/render.cpp	Mon Jun 20 17:08:02 2016 +0100
@@ -0,0 +1,166 @@
+/*
+ ____  _____ _        _    
+| __ )| ____| |      / \   
+|  _ \|  _| | |     / _ \  
+| |_) | |___| |___ / ___ \ 
+|____/|_____|_____/_/   \_\
+
+The platform for ultra-low latency audio and sensor processing
+
+http://bela.io
+
+A project of the Augmented Instruments Laboratory within the
+Centre for Digital Music at Queen Mary University of London.
+http://www.eecs.qmul.ac.uk/~andrewm
+
+(c) 2016 Augmented Instruments Laboratory: Andrew McPherson,
+  Astrid Bin, Liam Donovan, Christian Heinrichs, Robert Jack,
+  Giulio Moro, Laurel Pardue, Victor Zappi. All rights reserved.
+
+The Bela software is distributed under the GNU Lesser General Public License
+(LGPL 3.0), available here: https://www.gnu.org/licenses/lgpl-3.0.txt
+*/
+
+
+#include <Bela.h>
+
+const int kStepLengthSlow = 1000;
+const int kStepLengthFast = 500;
+
+int gStepLengthSamples = kStepLengthSlow;
+
+const int gPinA1 = P8_27;
+const int gPinA2 = P8_28;
+const int gPinB1 = P8_29;
+const int gPinB2 = P8_30;
+const int gPinServo = P9_16;
+
+int gStepCounter = 0;
+int gPhase = 0;
+
+int gServoCounter = 0;
+
+
+enum {
+	kStateMoveRight1 = 0,
+	kStateMoveLeft1,
+	kStateMoveRight2,
+	kStateMoveLeft2,
+	kStateMoveRight3,
+	kStateMoveLeft3,
+	kStateSpin,
+	kStateMax
+};
+
+int gState = 0;
+int gStateCounter = 0;
+
+// setup() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+
+bool setup(BelaContext *context, void *userData)
+{	
+	// This project makes the assumption that the audio and digital
+	// sample rates are the same. But check it to be sure!
+	if(context->audioFrames != context->digitalFrames) {
+		rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
+		return false;
+	}
+	
+	pinMode(context, 0, gPinA1, OUTPUT);
+	pinMode(context, 0, gPinA2, OUTPUT);
+	pinMode(context, 0, gPinB1, OUTPUT);
+	pinMode(context, 0, gPinB2, OUTPUT);
+	pinMode(context, 0, gPinServo, OUTPUT);
+		
+	return true;
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BelaContext *context, void *userData)
+{
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		if(gPhase == 0 || gPhase == 1) {
+			digitalWriteOnce(context, n, gPinB1, HIGH);
+			digitalWriteOnce(context, n, gPinB2, LOW);
+		}
+		else {
+			digitalWriteOnce(context, n, gPinB1, LOW);
+			digitalWriteOnce(context, n, gPinB2, HIGH);			
+		}
+		
+		if(gPhase == 1 || gPhase == 2) {
+			digitalWriteOnce(context, n, gPinA1, HIGH);
+			digitalWriteOnce(context, n, gPinA2, LOW);
+		}
+		else {
+			digitalWriteOnce(context, n, gPinA1, LOW);
+			digitalWriteOnce(context, n, gPinA2, HIGH);			
+		}
+		
+		if(--gServoCounter > 0) 
+			digitalWriteOnce(context, n, gPinServo, HIGH);
+		else
+			digitalWriteOnce(context, n, gPinServo, LOW);
+		
+		if(++gStepCounter >= gStepLengthSamples) {
+			gStateCounter++;
+			
+			switch(gState) {
+				case kStateMoveRight1:
+				case kStateMoveRight2:
+				case kStateMoveRight3:
+					gPhase = (gPhase + 1) & 3;
+					break;
+				case kStateMoveLeft1:
+				case kStateMoveLeft2:
+				case kStateMoveLeft3:				
+					gPhase = (gPhase + 3) & 3;	
+					break;
+				case kStateSpin:
+					gPhase = (gPhase + 1) & 3;
+					break;		
+			}
+			
+			if(gState == kStateSpin) {
+				if(gStateCounter >= 48) {
+					gStateCounter = 0;
+					gState = 0;
+					gStepLengthSamples = kStepLengthSlow;
+				}				
+			}
+			else {
+				if(gStateCounter >= 16) {
+					gStateCounter = 0;
+					gState++;
+					if(gState & 1)
+						gServoCounter = 120;
+					else
+						gServoCounter = 80;
+					if(gState == kStateSpin)
+						gStepLengthSamples = kStepLengthFast;
+				}
+			}
+			
+			gStepCounter = 0;
+		}
+	}
+}
+
+// cleanup() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in setup().
+
+void cleanup(BelaContext *context, void *userData)
+{
+	
+}
--- a/examples/7segment/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-
-#include <Bela.h>
-
-#define NUM_PINS 12
-
-// Breadboard wiring layout:
-// 11 10 12 9  8  7
-// [ LED DISP ]
-// 1  2  3  6  4  5
-
-// Organised by display segments:
-// e d . X c g b X X X f a
-const int kPins[NUM_PINS] = {P8_07, P8_08, P8_09, P8_10, P8_11, P8_12,
-							 P8_15, P8_16, P8_27, P8_28, P8_29, P8_30};
-
-// Indices into the above array: pins 12, 9, 8, 6
-const int kDigits[4] = {9, 8, 7, 3};
-
-int gCurrentlyDisplayingDigit = 0;
-int gDigitDisplayTime = 0;
-const int kDigitMaxDisplayTime = 44;
-
-int gState = 0;
-int gStateCounter = 0;
-const int kMaxState = 25;
-
-// . g f e d c b a
-//const unsigned char kBELA[4] = {0x7C, 0x79, 0x38, 0x77};
-const unsigned char kBELA[4] = {0x7C, 0x7B, 0x38, 0x5F};
-const unsigned char kPerimeter[6] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20};
-
-int gCharacterToDisplay[4] = {0, 0, 0, 0};
-	
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{	
-	// This project makes the assumption that the audio and digital
-	// sample rates are the same. But check it to be sure!
-	if(context->audioFrames != context->digitalFrames) {
-		rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
-		return false;
-	}
-	
-	for(int i = 0; i < NUM_PINS; i++) {
-		pinMode(context, 0, kPins[i], OUTPUT);
-	}
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		// Check for rotation between digits
-		if(--gDigitDisplayTime <= 0) {
-			gCurrentlyDisplayingDigit = (gCurrentlyDisplayingDigit + 1) % 4;
-			gDigitDisplayTime = kDigitMaxDisplayTime;
-		}
-	
-		// Write the currently displaying digit low and the rest high
-		for(int i = 0; i < 4; i++)
-				digitalWriteOnce(context, n, kPins[kDigits[i]], HIGH);
-		digitalWriteOnce(context, n, kPins[kDigits[gCurrentlyDisplayingDigit]], LOW);
-		
-		// Write the digit to the other outputs
-		digitalWriteOnce(context, n, kPins[11],
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x01);	// a
-		digitalWriteOnce(context, n, kPins[6], 
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x02);	// b
-		digitalWriteOnce(context, n, kPins[4], 
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x04);	// c
-		digitalWriteOnce(context, n, kPins[1],
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x08);	// d
-		digitalWriteOnce(context, n, kPins[0],
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x10);	// e
-		digitalWriteOnce(context, n, kPins[10],
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x20);	// f
-		digitalWriteOnce(context, n, kPins[5],
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x40);	// g
-		digitalWriteOnce(context, n, kPins[2],
-			gCharacterToDisplay[gCurrentlyDisplayingDigit] & 0x80);	// .
-			
-		// Check for changing state
-		if(--gStateCounter <= 0) {
-			gState = (gState + 1) % kMaxState;
-			if(gState != (kMaxState - 1)) {
-				for(int i = 0; i < 4; i++)
-					gCharacterToDisplay[i] = 1 << (gState % 6);
-				gStateCounter = 2000;
-			}
-			else {
-				for(int i = 0; i < 4; i++)
-					gCharacterToDisplay[i] = kBELA[i];
-				gStateCounter = 50000;
-			}
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	
-}
--- a/examples/airharp/Junction.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- *
- * Excitation Junction for two waveguides
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-#include "Junction.h"
-#include "../include/Utilities.h"
-
-Junction::Junction()	{
-
-	setFrequency(440);
-	_dt = 1.0/44100.0;
-
-	// initialize variables
-	for(int i=0;i<WG_BUFFER_SIZE;i++)	{
-		_buffer_l[i] = 0;
-		_buffer_r[i] = 0;
-	}
-	_excitation = 0;
-	_lastPlectrumDisplacement = 0;
-	_readPtr = 0;
-
-}
-
-void Junction::update(float excitation, float left, float right)	{
-
-	// 1. advance delay buffer read pointer
-
-	if(++_readPtr>=WG_BUFFER_SIZE)
-		_readPtr=0;
-
-	// 2. add excitation sample into buffer
-
-	_buffer_l[(_readPtr+_delay_l+WG_BUFFER_SIZE)%WG_BUFFER_SIZE] = excitation;
-	_buffer_r[(_readPtr+_delay_r+WG_BUFFER_SIZE)%WG_BUFFER_SIZE] = excitation;
-
-	// 3. feed right input to left output and vice versa
-
-	_buffer_l[_readPtr] += right;
-	_buffer_r[_readPtr] += left;
-
-	// 4. store excitation value for later use
-	_excitation = excitation;
-
-}
-
-float Junction::getOutput(int direction)	{
-
-	if(direction = 0)
-		return _buffer_l[_readPtr];
-	else
-		return _buffer_r[_readPtr];
-
-}
-
-float Junction::getExcitationDisplacement()	{
-
-	// string displacement and excitation force
-	// use delayed value to account for excitation position
-	float in = _buffer_l[(_readPtr+_delay_l+WG_BUFFER_SIZE)%WG_BUFFER_SIZE] + _excitation;
-
-	// integrate total force
-	float out = 0.00001 * in + 0.99999 * _lastPlectrumDisplacement;
-
-	// store variable for next iteration
-	_lastPlectrumDisplacement = out;
-
-	// multiply by delta time
-	return out * _dt;
-
-}
-
-void Junction::setPluckPosition(float pluckPos){
-
-	pluckPos = constrain(pluckPos,0,1);
-	_delay_l = pluckPos * _periodInSamples;
-	_delay_r = (1-pluckPos) * _periodInSamples;
-
-}
-
-void Junction::setPeriod(float period)	{
-
-	_periodInMilliseconds = period;
-
-}
-
-void Junction::setFrequency(float frequency)	{
-
-	_periodInMilliseconds = 1000.0/frequency;
-	_periodInSamples = (int)(_periodInMilliseconds * 44.1);
-
-}
--- a/examples/airharp/Junction.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- *
- * Excitation Junction for two waveguides
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-#ifndef JUNCTION_H_
-#define JUNCTION_H_
-
-#include <cmath>
-
-#ifndef WG_BUFFER_SIZE
-#define WG_BUFFER_SIZE 4096
-#endif
-
-#ifndef		M_PI
-#define		M_PI		3.14159265358979323846264338
-#endif
-
-class Junction
-{
-
-public:
-
-	Junction();
-	void setup();
-	void update(float excitation, float left, float right);
-	float getOutput(int direction);
-	float getExcitationDisplacement();
-	void setFrequency(float frequency);
-	void setPeriod(float periodInMs);
-	void setPluckPosition(float pluckPos);
-
-private:
-
-	double _dt;
-	float _periodInMilliseconds;
-	int _periodInSamples;
-
-	int _delay_l;
-	int _delay_r;
-
-	float _buffer_l[WG_BUFFER_SIZE];
-	float _buffer_r[WG_BUFFER_SIZE];
-	int _readPtr;
-
-	float _excitation;
-	float _lastPlectrumDisplacement;
-
-};
-
-#endif
--- a/examples/airharp/MassSpringDamper.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- *
- * Simple 1-Dimensional Mass Spring Damper
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-#include "MassSpringDamper.h"
-
-MassSpringDamper::MassSpringDamper(float mass, float spring, float damp)	{
-
-	_dt = 1.0/44100.0;
-	_mass = mass;
-	_spring = spring;
-	_damp = damp;
-	_position = 0;
-	_velocity = 0;
-
-}
-
-void MassSpringDamper::setup()	{
-
-}
-
-double MassSpringDamper::update(float inForce)	{
-
-	// 1. calculate spring/damper forces using current position and velocity
-
-	double out = (_position * (double)_spring * -1) + (_velocity * (double)_damp * -1);
-
-	// 2. apply external force
-
-	out += inForce;
-
-	// 3. derive acceleration (a = f/m)
-
-	out /= (double)_mass;
-
-	// 4. derive velocity (v = a*dt)
-
-	out *= _dt;
-
-	// 5. apply previous velocity
-
-	out += _velocity;
-
-	// 6. save current velocity state for next iteration
-
-	_velocity = out;
-
-	// 7. derive new position (x[n] = x[n-1] + v[n]) and save for next iteration
-
-	out += _position;
-	_position = out;
-
-	return out;
-
-}
--- a/examples/airharp/MassSpringDamper.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- *
- * Simple 1-Dimensional Mass Spring Damper
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-#ifndef MASSSPRINGDAMPER_H_
-#define MASSSPRINGDAMPER_H_
-
-class MassSpringDamper
-{
-
-public:
-
-	MassSpringDamper(float mass, float spring, float damp);
-	void setup();
-	double update(float inForce);
-
-private:
-
-	double _dt;
-	float _mass;
-	float _spring;
-	float _damp;
-	double _position;
-	double _velocity;
-
-};
-
-#endif
--- a/examples/airharp/Plectrum.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- *
- * Plectrum model for touching and plucking strings
- *
- * Christian Heinrichs 04/2015
- *
- * [inspired by E. Berdahl's pluck~ abstraction for the FireFader]
- *
- */
-
-#include "Plectrum.h"
-
-#include "../include/Utilities.h"
-#include <cmath>
-#include <stdio.h>
-#include <cstdlib>
-
-Plectrum::Plectrum()	{
-
-	_contact = 0;
-	_lastDistance = 0;
-
-}
-
-void Plectrum::setup(float spring, float damp, float hyst)	{
-
-	_spring = spring;
-	_damp = damp;
-	_hyst = hyst;
-
-}
-
-float Plectrum::update(float position, float stringPosition)	{
-
-	float distance = position - stringPosition;
-
-	// Calculate spring/damp forces based on distance to string
-
-	float springOut = distance * _spring;
-
-	float dampOut = (distance - _lastDistance) * 44100;
-
-	float out = springOut+dampOut;
-
-	// If distance crosses zero, enable contact
-
-	if((distance>0 && _lastDistance<=0)||(distance<0 && _lastDistance>=0))
-		_contact = 1;
-
-	// If distance exceeds hysteresis threshold, jump to zero (i.e. 'pluck')
-
-	if(fabs(distance)>_hyst)
-		_contact = 0;
-
-	// FIXME: contact doesn't switch back to zero if distance goes back in original direction
-
-	_lastDistance = distance;
-
-	return out * _contact;
-
-}
--- a/examples/airharp/Plectrum.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- *
- * Plectrum model for touching and plucking strings
- *
- * [inspired by E. Berdahl's pluck~ abstraction for the FireFader]
- *
- */
-
-#ifndef PLECTRUM_H_
-#define PLECTRUM_H_
-
-class Plectrum
-{
-
-public:
-
-	Plectrum();
-	void setup(float spring, float damp, float hyst);
-	float update(float position, float stringPosition);
-
-private:
-
-	double _dt;
-	float _spring;
-	float _damp;
-	double _position;
-	double _velocity;
-	float _hyst;
-	float _lastDistance;
-	int _contact;
-
-};
-
-#endif
-
--- a/examples/airharp/String.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- *
- * 1-D string consisting of two waveguides and junction
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-#include "String.h"
-#include "Junction.h"
-#include "Waveguide.h"
-
-#include "../include/Utilities.h"
-#include <rtdk.h>
-#include <cmath>
-#include <stdio.h>
-#include <cstdlib>
-
-String::String(){
-
-	wg_l = Waveguide();
-	wg_r = Waveguide();
-	junction = Junction();
-
-	junction.setPluckPosition(0.5);
-
-	_previous_l = 0;
-	_previous_r = 0;
-
-}
-
-float String::update(float in)	{
-
-	// 1. send excitation signal and previous waveguide outputs into junction
-
-	junction.update(in,_previous_l,_previous_r);
-
-	// 2. save new waveguide outputs for next iteration
-
-	_previous_l = wg_l.update(junction.getOutput(0));
-	_previous_r = wg_r.update(junction.getOutput(1));
-
-	// 3. use right waveguide as output
-
-	//rt_printf("BANANA %f ",_readPtr);
-	//rt_printf("%f\n",_previous_r);
-
-	return _previous_r;
-}
-
-float String::getPlectrumDisplacement()	{
-
-	return junction.getExcitationDisplacement();
-
-}
-
-void String::setPluckPosition(float pluckPos){
-
-	junction.setPluckPosition(pluckPos);
-
-}
-
-void String::setGlobalPosition(float pos)	{
-
-	_globalPosition = pos;
-
-}
-
-float String::getGlobalPosition()	{
-
-	return _globalPosition;
-
-}
-
-void String::setMidinote(float midinote)	{
-
-	float frequency = 440.0f*(float)powf(2,(midinote-57)/12.0f);
-
-	junction.setFrequency(frequency);
-	wg_l.setFrequency(frequency);
-	wg_r.setFrequency(frequency);
-
-}
-
-void String::setFrequency(float frequency)	{
-
-	junction.setFrequency(frequency);
-	wg_l.setFrequency(frequency);
-	wg_r.setFrequency(frequency);
-
-}
--- a/examples/airharp/String.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- *
- * 1-D string consisting of two waveguides and junction
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-#ifndef STRING_H_
-#define STRING_H_
-
-#include <cmath>
-#include "Junction.h"
-#include "Waveguide.h"
-
-class String
-{
-
-public:
-
-	String();
-	float update(float in);
-
-	float getPlectrumDisplacement();
-	void setMidinote(float midinote);
-	void setFrequency(float frequency);
-	void setPeriod(float periodInMs);
-	void setPluckPosition(float pluckPos);
-	void setGlobalPosition(float pos);
-	float getGlobalPosition();
-
-private:
-
-	float _previous_l;
-	float _previous_r;
-
-	float _globalPosition;
-
-	Waveguide wg_l;
-	Waveguide wg_r;
-	Junction junction;
-
-};
-
-#endif
--- a/examples/airharp/Waveguide.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- *
- * Simple 1-Dimensional Waveguide
- *
- */
-
-#include "Waveguide.h"
-#include "../include/Utilities.h"
-#include <rtdk.h>
-#include <cmath>
-#include <stdio.h>
-#include <cstdlib>
-
-#define DECAY 0.995//0.999
-#define DAMPING 0.01//0.05
-
-// TODO: make damping and decay parametrisable
-
-Waveguide::Waveguide()	{
-
-	// initialize variables
-	a1_lp = 0;
-	a2_lp = 0;
-	b0_lp = 0;
-	b1_lp = 0;
-	b2_lp = 0;
-	_dt = 1.0/44100.0;
-	setFrequency(440);
-	updateFilterCoeffs(8000);
-	_filterReadPtr=0;
-	for(int i=0;i<FILTER_BUFFER_SIZE;i++)	{
-		_filterBuffer_x[i] = 0;
-		_filterBuffer_y[i] = 0;
-	}
-	for(int i=0;i<WG_BUFFER_SIZE;i++)	{
-		_buffer[i] = 0;
-	}
-	_lastX = 0;
-	_lastY = 0;
-	_readPtr = 0;
-
-}
-
-void Waveguide::setup()	{
-
-}
-
-float Waveguide::update(float in)	{
-
-	// 1. advance delay buffer read pointer
-
-	if(++_readPtr>=WG_BUFFER_SIZE)
-		_readPtr=0;
-
-	// 2. write input into buffer
-
-	_buffer[_readPtr] = in;
-
-	// 3. read delayed sample from buffer
-
-	float out = _buffer[(_readPtr-_periodInSamples+WG_BUFFER_SIZE)%WG_BUFFER_SIZE];
-
-	// 4. apply damping (low-pass) filter to output
-
-	if(++_filterReadPtr>=FILTER_BUFFER_SIZE)
-			_filterReadPtr=0;
-
-	out = b0_lp*out +
-					b1_lp*_filterBuffer_x[(_filterReadPtr-1+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] +
-					b2_lp*_filterBuffer_x[(_filterReadPtr-2+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] -
-					a1_lp*_filterBuffer_y[(_filterReadPtr-1+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE] -
-					a2_lp*_filterBuffer_y[(_filterReadPtr-2+FILTER_BUFFER_SIZE)%FILTER_BUFFER_SIZE];
-
-	// 5. Simple high-pass filter to block DC-offset
-	// y[n] = x[n] - x[n-1] + a * y[n-1]
-	float gain = 0.9999;
-	float temp = out;
-	out = out - _lastX + gain * _lastY;
-	_lastY = out;
-	_lastX = temp;
-
-	// 6. Apply intensity damping
-	out *= DECAY;
-
-	_filterBuffer_x[_filterReadPtr] = in;
-	_filterBuffer_y[_filterReadPtr] = out;
-
-	return out;
-
-}
-
-void Waveguide::setFrequency(float frequency)	{
-
-	// NB: currently no interpolation, so may not be ideal for dynamically changing waveguide frequency
-	_periodInMilliseconds = 1000.0/frequency;
-	_periodInSamples = (int)(_periodInMilliseconds * 44.1);
-
-}
-
-void Waveguide::updateFilterCoeffs(float frequency)	{
-
-	// FIXME: Butterworth filter doesn't work very well,
-	//		  using simple FIR in the meantime
-
-	a1_lp = 0;
-	a2_lp = 0;
-	b0_lp = 1.0 - DAMPING;
-	b1_lp = DAMPING;
-	b2_lp = 0;
-
-	/*
-	// 'w' for sake of resembling lower-case 'omega'
-	float w = 2.0 * M_PI * frequency;
-	float t = _dt;
-	// The Q for a 2nd-order Butterworth is sqrt(2)/2
-	float q = 0.707;//sqrt(2.0)/2.0;
-
-	// low-pass filter coefficients
-	float a0_lp = w*w*t*t + 2*(w/q)*t + 4.0;
-	float k = 1.0/a0_lp;
-	a1_lp = (2.0*w*w*t*t - 8.0) * k;
-	a2_lp = (4.0 - (w/q)*2.0*t + w*w*t*t) * k;
-	b0_lp = (w*w*t*t) * k;
-	b1_lp = (2.0*w*w*t*t) * k;
-	b2_lp = (w*w*t*t) * k;
-	*/
-
-}
--- a/examples/airharp/Waveguide.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- *
- * Simple 1-Dimensional Waveguide
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-#ifndef WAVEGUIDE_H_
-#define WAVEGUIDE_H_
-
-#include <cmath>
-
-#ifndef WG_BUFFER_SIZE
-#define WG_BUFFER_SIZE 4096
-#endif
-
-#ifndef FILTER_BUFFER_SIZE
-#define FILTER_BUFFER_SIZE 4
-#endif
-
-#ifndef		M_PI
-#define		M_PI		3.14159265358979323846264338
-#endif
-
-class Waveguide
-{
-
-public:
-
-	Waveguide();
-	void setup();
-	float update(float in);
-	void updateFilterCoeffs(float frequency);
-	void setFrequency(float frequency);
-
-private:
-
-	double _dt;
-	float _periodInMilliseconds;
-	int _periodInSamples;
-
-	float _buffer[WG_BUFFER_SIZE];
-	int _readPtr;
-
-	float _filterBuffer_x[FILTER_BUFFER_SIZE];
-	float _filterBuffer_y[FILTER_BUFFER_SIZE];
-	float _hipBuffer_x[FILTER_BUFFER_SIZE];
-	float _hipBuffer_y[FILTER_BUFFER_SIZE];
-	int _filterReadPtr;
-
-	float b0_lp,b1_lp,b2_lp,a1_lp, a2_lp;
-	float _lastY,_lastX;
-
-};
-
-#endif
--- a/examples/airharp/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,211 +0,0 @@
-/*
- * AIR-HARP
- * Physically modelled strings using waveguide junctions and mass-spring-dampers
- *
- * render.cpp
- *
- * Christian Heinrichs 04/2015
- *
- */
-
-
-#include "MassSpringDamper.h"
-#include "String.h"
-#include "Plectrum.h"
-
-#include <Bela.h>
-#include <cmath>
-#include <stdio.h>
-#include <cstdlib>
-#include <rtdk.h>
-
-#define ACCEL_BUF_SIZE 8
-#define NUMBER_OF_STRINGS 9
-
-// PENTATONIC SCALE
-float gMidinotes[NUMBER_OF_STRINGS] = {40,45,50,55,57,60,62,64,67};
-
-float gInverseSampleRate;
-
-float out_gain = 5.0;
-
-int accelPin_x = 0;
-int accelPin_y = 1;
-int accelPin_z = 2;
-
-MassSpringDamper msd = MassSpringDamper(1,0.1,10);// (10,0.001,10);
-String strings[NUMBER_OF_STRINGS];
-Plectrum plectrums[NUMBER_OF_STRINGS];
-
-float gPlectrumDisplacement = 0;
-
-float gAccel_x[ACCEL_BUF_SIZE] = {0};
-int gAccelReadPtr = 0;
-
-// DC BLOCK BUTTERWORTH
-
-// Coefficients for 100hz cut-off
-float a0_l = 0.9899759179893742;
-float a1_l = -1.9799518359787485;
-float a2_l = 0.9899759179893742;
-float a3_l = -1.979851353142371;
-float a4_l = 0.9800523188151258;
-
-float a0_r = a0_l;
-float a1_r = a1_l;
-float a2_r = a2_l;
-float a3_r = a3_l;
-float a4_r = a4_l;
-
-float x1_l = 0;
-float x2_l = 0;
-float y1_l = 0;
-float y2_l = 0;
-
-float x1_r = 0;
-float x2_r = 0;
-float y1_r = 0;
-float y2_r = 0;
-
-
-bool setup(BelaContext *context, void *userData)
-{
-
-	gInverseSampleRate = 1.0 / context->audioSampleRate;
-
-	// initialise strings & plectrums
-	for(int i=0;i<NUMBER_OF_STRINGS;i++)	{
-
-		plectrums[i] = Plectrum();
-		plectrums[i].setup(250,0.25,0.05);
-
-		strings[i] = String();
-		strings[i].setMidinote(gMidinotes[i]);
-
-		float spacing = 2.0 / (NUMBER_OF_STRINGS+1);
-
-		strings[i].setGlobalPosition( -1 + spacing*(i+1) );
-
-		rt_printf("STRING %d // midinote: %f position: %f\n",i,gMidinotes[i],( -1 + spacing*(i+1) ));
-
-	}
-
-	return true;
-}
-
-void render(BelaContext *context, void *userData)
-{
-
-	float lastAccel = 0;
-
-	for(int n = 0; n < context->audioFrames; n++) {
-
-		/*
-		 *
-		 * ACCELEROMETER DATA
-		 *
-		 */
-
-		// Read accelerometer data from analog input
-		float accel_x = 0;
-		if(n%2)	{
-			accel_x = (float)context->analogIn[(n/2)*8+accelPin_x] * 2 - 1;	// 15800 - 28300 - 41500
-			lastAccel = accel_x;
-		} else {
-			// grab previous value if !n%2
-			accel_x = lastAccel;
-		}
-
-		// Dead-zone avoids noise when box is lying horizontally on a surface
-
-		float accelDeadZone = 0.1;
-
-		if(accel_x <= accelDeadZone && accel_x >= -accelDeadZone)
-			accel_x = 0;
-
-		// Perform smoothing (moving average) on acceleration value
-		if(++gAccelReadPtr >= ACCEL_BUF_SIZE)
-			gAccelReadPtr = 0;
-		gAccel_x[gAccelReadPtr] = accel_x;
-		float gravity = 0;
-		for(int i=0;i<ACCEL_BUF_SIZE;i++)	{
-			gravity = gAccel_x[(gAccelReadPtr-i+ACCEL_BUF_SIZE)%ACCEL_BUF_SIZE];
-		}
-		gravity /= ACCEL_BUF_SIZE;
-
-		/*
-		 *
-		 * PHYSICS SIMULATION
-		 *
-		 */
-
-		// The horizontal force (which can be gravity if box is tipped on its side)
-		// is used as the input to a Mass-Spring-Damper model
-		// Plectrum displacement (i.e. when interacting with string) is included
-		float massPosition = (float)msd.update(gravity - gPlectrumDisplacement);
-
-		float out_l = 0;
-		float out_r = 0;
-		// Use this parameter to quickly adjust output gain
-		float gain = 0.0015;	// 0.0015 is a good value or 12 strings
-		gPlectrumDisplacement = 0;
-
-		for(int s=0;s<NUMBER_OF_STRINGS;s++)	{
-
-			float stringPosition = strings[s].getGlobalPosition();
-
-			float plectrumForce = plectrums[s].update(massPosition, stringPosition);
-			gPlectrumDisplacement += strings[s].getPlectrumDisplacement();
-
-			// calculate panning based on string position (-1->left / 1->right)
-			float panRight = map(stringPosition,1,-1,0.1,1);
-			float panLeft = map(stringPosition,-1,1,0.1,1);
-			panRight *= panRight;
-			panLeft *= panLeft;
-
-			float out = strings[s].update(plectrumForce)*gain;
-
-			out_l += out*panLeft;
-			out_r += out*panRight;
-
-		}
-
-		// APPLY DC-BLOCK FILTER TO OUTPUTS
-
-		// LEFT CHANNEL
-		float temp_in = out_l;
-		/* compute result */
-    	out_l = a0_l * out_l + a1_l * x1_l + a2_l * x2_l - a3_l * y1_l - a4_l * y2_l;
-    	/* shift x1 to x2, sample to x1 */
-    	x2_l = x1_l;
-    	x1_l = temp_in;
-    	/* shift y1 to y2, result to y1 */
-    	y2_l = y1_l;
-   	 	y1_l = out_l;
-
-   	 	// RIGHT CHANNEL
-		temp_in = out_r;
-		/* compute result */
-    	out_r = a0_r * out_r + a1_r * x1_r + a2_r * x2_r - a3_r * y1_r - a4_r * y2_r;
-    	/* shift x1 to x2, sample to x1 */
-    	x2_r = x1_r;
-    	x1_r = temp_in;
-    	/* shift y1 to y2, result to y1 */
-    	y2_r = y1_r;
-   	 	y1_r = out_r;
-
-		context->audioOut[n * context->audioChannels + 1] = out_l * out_gain;
-		context->audioOut[n * context->audioChannels + 0] = out_r * out_gain;
-
-	}
-
-}
-
-
-// cleanup_render() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in initialise_render().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/analogDigitalDemo/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * assignment1_crossover
- * RTDSP 2015
- *
- * First assignment for ECS732 RTDSP, to implement a 2-way audio crossover
- * using the BeagleBone Black.
- *
- * Andrew McPherson and Victor Zappi
- * Queen Mary, University of London
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	float frequency = 1000.0;	// Frequency of crossover
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-        case 'f':
-        		frequency = atof(optarg);
-        		if(frequency < 20.0)
-        			frequency = 20.0;
-        		if(frequency > 5000.0)
-        			frequency = 5000.0;
-        		break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &frequency) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/analogDigitalDemo/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- *
- * Andrew McPherson and Victor Zappi
- * Queen Mary, University of London
- */
-
-/**
-\example 3_analogDigitalDemo
-
-Analog digital workout
-----------------------
-
-This sketch showcases many different ways to write and read digital pins, 
-including generating clocks and creating binary counters.
-
-The code as it is will not work properly, as the direction of the pins is not 
-set. As an exercise, you will need to set the pin mode before writing or reading 
-the digital pins. 
-
-This is for advanced users only.
-*/
-
-#include <Bela.h>
-#include <cmath>
-#include <rtdk.h>
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numAnalogFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-/*
-we assume that gNumAnalogChannels=8, numAnalogFrames==8 and  numDigitalFrames==numAudioFrames
- * */
-{
-  /*
-  * TODO: as an exercise, you will need to set the pin mode before writing or reading the digital pins.
-  */
-	if((context->audioFramesElapsed&31)==0){ //every 32 frames...
-        //ANALOG channels
-		analogWrite(context, 0, 0, analogRead(context, 0,0));
-		// read the input0 at frame0  and write it to output0 frame0. Using analogWrite will fill the rest of the buffer with the same value
-                                            // The value at the last frame will persist through the successive buffers until is set again.
-                                            // This effectively is a pass-through with downsampling by 32 times
-        analogWrite(context, 0, 3, 1.0);  // write 1.0 to channel3 from frame0 to the end of the buffer
-        analogWrite(context, 4, 3, 0.1);  // write 0.1  to channel3 from frame4 to the end of the buffer
-        analogWriteOnce(context, 6, 3, 0.2); //write 0.2 to channel3 only on frame 6
-        //this buffer for channel 3 will look like this:  1 1 1 1 0.1 0.1 0.2 0.1 
-        //the next buffers for channel 3 will be filled up with 0.1 ....
-        //DIGITAL channels
-        digitalWrite(context, 0, P8_07, GPIO_HIGH); //sets all the frames  to HIGH for channel 0
-        digitalWriteOnce(context, 4, P8_07, GPIO_LOW); //only frame 4 will be LOW  for channel 0
-        // in this buffer the frames of channel 0 will look like this: 1 1 1 1 0 1 1 1 ...... 1 
-        // in the next buffer each frame of channel 0 will be initialized to 1 (the last value of this buffer)
-        digitalWrite(context, 0, P8_08, GPIO_HIGH);
-        digitalWrite(context, 2, P8_08, GPIO_LOW);
-        digitalWrite(context, 4, P8_08, GPIO_HIGH);
-        digitalWrite(context, 5, P8_08, GPIO_LOW);
-        pinMode(context, 0, P9_16, GPIO_INPUT); // set channel 10 to input
-        // in this buffer the frames of channel 1 will look like this: 1 1 0 0 1 0 0 0 .... 0
-        // in the next buffer each frame of channel 1 will be initialized to 0 (the last value of this buffer)
-	}
-	for(unsigned int n=0; n<context->audioFrames; n++){
-		for(unsigned int c=0; c<context->audioChannels; c++){
-			context->audioOut[n*context->audioChannels + c]=context->audioIn[n*context->audioChannels + c];
-		}
-        //use digital channels 2-8 to create a 7 bit binary counter
-        context->digital[n]=context->digital[n] & (~0b111111100); // set to zero (GPIO_OUTPUT) the bits in the lower word
-        context->digital[n]=context->digital[n] & ((~0b111111100<<16) | 0xffff ); //initialize to zero the bits in the higher word (output value)
-        context->digital[n]=context->digital[n] | ( ((context->audioFramesElapsed&0b1111111)<<(16+2)) ) ;  // set the bits in the higher word to the desired output value, keeping the lower word unchanged
-        digitalWrite(context, n, P8_29, digitalRead(context, n, P8_30)); // echo the input from from channel 15 to channel 14
-        digitalWrite(context, n, P8_28, digitalRead(context, n, P9_16)); // echo the input from from channel 10 to channel 13
-        pinMode(context, 0, P8_30, 0); //set channel 15 to input
-	}
-
-	for(unsigned int n=0; n<context->analogFrames; n++){
-    	analogWrite(context, n, 1, (context->audioFramesElapsed&8191)/8192.0); // writes a single frame. channel 1 is a ramp that follows gCountFrames
-    	analogWrite(context, n, 2, analogRead(context, n, 2)); // writes a single frame. channel2 is just a passthrough
-//		rt_printf("Analog out frame %d :",n);
-//		for(int c=0; c<gNumAnalogChannels; c++)
-//			rt_printf("%.1f ",analogOut[n*gNumAnalogChannels + c]);
-//		rt_printf("\n");
-	}
-	return;
-
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	// Nothing to do here
-}
--- a/examples/audio_in_FFT/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --fftsize [-s] size:     Set the fSize of the FFT, in samples\n";
-	cerr << "   --help [-h]:             Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	int fftSize = 64;		    // Size of the FFT, in samples
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"fftsize", 1, NULL, 's'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-//	settings.useAnalog = 0;	// No matrix usage by default
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hs:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 's':
-				fftSize = atof(optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &fftSize) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
-
--- a/examples/audio_in_FFT/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: Andrew McPherson, C4DM, QMUL
- */
-
-/**
-\example 4_audio_FFT
-
-Fast Fourier Transform
-----------------------
-
-This sketch performs an FFT (Fast Fourier Transform) on incoming audio. It uses 
-the NE10 library, included at the top of the file (line 11).
-
-Read the documentation on the NE10 library [here](http://projectne10.github.io/Ne10/doc/annotated.html).
-
-The variables `timeDomainIn`, `timeDomainOut` and `frequencyDomain` are 
-variables of the struct `ne10_fft_cpx_float32_t` [http://projectne10.github.io/Ne10/doc/structne10__fft__cpx__float32__t.html](http://projectne10.github.io/Ne10/doc/structne10__fft__cpx__float32__t.html). 
-These are declared at the top of the file (line 21), and memory is allocated 
-for them in `setup()` (line 41).
-
-In `render()` a `for` loop performs the FFT which is performed on each sample, 
-and the resulting output is placed on each channel.
-*/
-
-#include <Bela.h>
-#include <rtdk.h>
-#include <ne10/NE10.h>					// neon library
-#include <cmath>
-
-int gFFTSize;
-
-int gReadPointer = 0;
-int gWritePointer = 0;
-
-// FFT vars
-static ne10_fft_cpx_float32_t* timeDomainIn;
-static ne10_fft_cpx_float32_t* timeDomainOut;
-static ne10_fft_cpx_float32_t* frequencyDomain;
-static ne10_fft_cfg_float32_t cfg;
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	// Retrieve a parameter passed in from the initAudio() call
-	gFFTSize = *(int *)userData;
-
-	timeDomainIn = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-	timeDomainOut = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-	frequencyDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-	cfg = ne10_fft_alloc_c2c_float32_neon (gFFTSize);
-
-	memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		timeDomainIn[gReadPointer].r = (ne10_float32_t) ((context->audioIn[n*context->audioChannels] +
-															context->audioIn[n*context->audioChannels+1]) * 0.5);
-		timeDomainIn[gReadPointer].i = 0;
-
-		if(++gReadPointer >= gFFTSize)
-		{
-			//FFT
-			ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg, 0);
-
-			//Do frequency domain stuff
-
-			//IFFT
-			ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg, 1);
-
-			gReadPointer = 0;
-			gWritePointer = 0;
-		}
-
-		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-			context->audioOut[n * context->audioChannels + channel] = (float) timeDomainOut[gWritePointer].r;
-		gWritePointer++;
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	NE10_FREE(timeDomainIn);
-	NE10_FREE(timeDomainOut);
-	NE10_FREE(frequencyDomain);
-	NE10_FREE(cfg);
-}
--- a/examples/basic/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-#include <unistd.h>
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	float frequency = 440.0;	// Frequency of oscillator
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				frequency = atof(optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &frequency) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/basic/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-/**
-\example 1_basic_helloworld
-
-Producing your first bleep!
----------------------------
-
-This sketch is the hello world of embedded interactive audio. Better known as bleep, it 
-produces a sine tone.
-
-The frequency of the sine tone is determined by a global variable, `gFrequency` 
-(line 12). The sine tone is produced by incrementing the phase of a sin function 
-on every audio frame.
-
-In render() you'll see a nested for loop structure. You'll see this in all Bela projects. 
-The first for loop cycles through 'audioFrames', the second through 'audioChannels' (in this case left 0 and right 1). 
-It is good to familiarise yourself with this structure as it's fundamental to producing sound with the system.
-*/
-
-#include <Bela.h>
-#include <cmath>
-
-float gFrequency = 440.0;
-float gPhase;
-float gInverseSampleRate;
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	// Retrieve a parameter passed in from the initAudio() call
-	if(userData != 0)
-		gFrequency = *(float *)userData;
-
-	gInverseSampleRate = 1.0 / context->audioSampleRate;
-	gPhase = 0.0;
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		float out = 0.8f * sinf(gPhase);
-		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
-		if(gPhase > 2.0 * M_PI)
-			gPhase -= 2.0 * M_PI;
-
-		for(unsigned int channel = 0; channel < context->audioChannels; channel++) {
-			// Two equivalent ways to write this code
-
-			// The long way, using the buffers directly:
-			// context->audioOut[n * context->audioChannels + channel] = out;
-
-			// Or using the macros:
-			audioWrite(context, n, channel, out);
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/basic_FFT_phase_vocoder/SampleData.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/*
- * SampleData.h
- *
- *  Created on: Nov 5, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef SAMPLEDATA_H_
-#define SAMPLEDATA_H_
-
-// User defined structure to pass between main and rendere complex data retrieved from file
-struct SampleData {
-	float *samples;	// Samples in file
-	int sampleLen;	// Total nume of samples
-};
-
-
-
-#endif /* SAMPLEDATA_H_ */
--- a/examples/basic_FFT_phase_vocoder/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <cstdio>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sndfile.h>				// to load audio files
-#include "SampleData.h"
-#include <Bela.h>
-
-using namespace std;
-
-// Global variables used by getCurrentTime()
-unsigned long long gFirstSeconds, gFirstMicroseconds;
-
-// Load samples from file
-int initFile(string file, SampleData *smp)//float *& smp)
-{
-  	SNDFILE *sndfile ;
-	SF_INFO sfinfo ;
-
-	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
-		cout << "Couldn't open file " << file << endl;
-		return 1;
-	}
-
-	int numChan = sfinfo.channels;
-	if(numChan != 1)
-	{
-		cout << "Error: " << file << " is not a mono file" << endl;
-		return 1;
-	}
-
-	smp->sampleLen = sfinfo.frames * numChan;
-	smp->samples = new float[smp->sampleLen];
-	if(smp == NULL){
-		cout << "Could not allocate buffer" << endl;
-		return 1;
-	}
-
-	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
-	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
-
-	// Pad with zeros in case we couldn't read whole file
-	for(int k = readcount; k <smp->sampleLen; k++)
-		smp->samples[k] = 0;
-
-	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
-		double	scale ;
-		int 	m ;
-
-		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
-		if (scale < 1e-10)
-			scale = 1.0 ;
-		else
-			scale = 32700.0 / scale ;
-		cout << "File samples scale = " << scale << endl;
-
-		for (m = 0; m < smp->sampleLen; m++)
-			smp->samples[m] *= scale;
-	}
-
-	sf_close(sndfile);
-
-	return 0;
-}
-
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-/* Function which returns the time since start of the program
- * in (fractional) seconds.
- */
-double getCurrentTime(void) {
-	unsigned long long result;
-	struct timeval tv;
-
-	gettimeofday(&tv, NULL);
-	result = (tv.tv_sec - gFirstSeconds) * 1000000ULL + (tv.tv_usec - gFirstMicroseconds);
-	return (double)result / 1000000.0;
-}
-extern SampleData gSampleData;
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	struct timeval tv;
-	string fileName;			// Name of the sample to load
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"file", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	gSampleData.samples = 0;
-	gSampleData.sampleLen = -1;
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	settings.periodSize = 32; // Larger period size by default, for testing
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				fileName = string((char *)optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	if(fileName.empty()){
-		fileName = "sample.wav";
-	}
-
-
-	// Load file
-	if(initFile(fileName, &gSampleData) != 0)
-	{
-		cout << "Error: unable to load samples " << endl;
-		return -1;
-	}
-
-	if(settings.verbose)
-		cout << "File contains " << gSampleData.sampleLen << " samples" << endl;
-
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &gSampleData) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Initialise time
-	gettimeofday(&tv, NULL);
-	gFirstSeconds = tv.tv_sec;
-	gFirstMicroseconds = tv.tv_usec;
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/basic_FFT_phase_vocoder/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,299 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-/**
-\example 4_audio_FFT_phase_vocoder
-
-Phase Vocoder
-----------------------
-
-This sketch shows an implementation of a phase vocoder and builds on the previous FFT example.
-Again it uses the NE10 library, included at the top of the file (line 11).
-
-Read the documentation on the NE10 library [here](http://projectne10.github.io/Ne10/doc/annotated.html).
-*/
-
-#include <Bela.h>
-#include <rtdk.h>
-#include <ne10/NE10.h>					// NEON FFT library
-#include <cmath>
-#include "SampleData.h"
-#include <Midi.h>
-
-#define BUFFER_SIZE 16384
-
-// TODO: your buffer and counter go here!
-float gInputBuffer[BUFFER_SIZE];
-int gInputBufferPointer = 0;
-float gOutputBuffer[BUFFER_SIZE];
-int gOutputBufferWritePointer = 0;
-int gOutputBufferReadPointer = 0;
-int gSampleCount = 0;
-
-float *gWindowBuffer;
-
-// -----------------------------------------------
-// These variables used internally in the example:
-int gFFTSize = 2048;
-int gHopSize = 512;
-int gPeriod = 512;
-float gFFTScaleFactor = 0;
-
-// FFT vars
-ne10_fft_cpx_float32_t* timeDomainIn;
-ne10_fft_cpx_float32_t* timeDomainOut;
-ne10_fft_cpx_float32_t* frequencyDomain;
-ne10_fft_cfg_float32_t cfg;
-
-// Sample info
-SampleData gSampleData;	// User defined structure to get complex data from main
-int gReadPtr = 0;		// Position of last read sample from file
-
-// Auxiliary task for calculating FFT
-AuxiliaryTask gFFTTask;
-int gFFTInputBufferPointer = 0;
-int gFFTOutputBufferPointer = 0;
-
-void process_fft_background();
-
-
-int gEffect = 0; // change this here or with midi CC
-enum{
-	kBypass,
-	kRobot,
-	kWhisper,
-};
-
-float gDryWet = 1; // mix between the unprocessed and processed sound
-float gPlaybackLive = 0.5f; // mix between the file playback and the live audio input
-float gGain = 1; // overall gain
-float *gInputAudio = NULL;
-Midi midi;
-
-
-void midiCallback(MidiChannelMessage message, void* arg){
-	if(message.getType() == kmmNoteOn){
-		if(message.getDataByte(1) > 0){
-			int note = message.getDataByte(0);
-			float frequency = powf(2, (note-69)/12.f)*440;
-			gPeriod = (int)(44100 / frequency + 0.5);
-			printf("\nnote: %d, frequency: %f, hop: %d\n", note, frequency, gPeriod);
-		}
-	}
-
-	bool shouldPrint = false;
-	if(message.getType() == kmmControlChange){
-		float data = message.getDataByte(1) / 127.0f;
-		switch (message.getDataByte(0)){
-		case 2 :
-			gEffect = (int)(data * 2 + 0.5); // CC2 selects an effect between 0,1,2
-			break;
-		case 3 :
-			gPlaybackLive = data;
-			break;
-		case 4 :
-			gDryWet = data;
-			break;
-		case 5:
-			gGain = data*10;
-			break;
-		default:
-			shouldPrint = true;
-		}
-	}
-	if(shouldPrint){
-		message.prettyPrint();
-	}
-}
-
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-bool setup(BelaContext* context, void* userData)
-{
-	midi.readFrom(0);
-	midi.setParserCallback(midiCallback);
-	// Retrieve a parameter passed in from the initAudio() call
-	gSampleData = *(SampleData *)userData;
-
-	gFFTScaleFactor = 1.0f / (float)gFFTSize;
-	gOutputBufferWritePointer += gHopSize;
-
-	timeDomainIn = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-	timeDomainOut = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-	frequencyDomain = (ne10_fft_cpx_float32_t*) NE10_MALLOC (gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-	cfg = ne10_fft_alloc_c2c_float32_neon (gFFTSize);
-
-	memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
-	memset(gOutputBuffer, 0, BUFFER_SIZE * sizeof(float));
-
-	// Allocate buffer to mirror and modify the input
-	gInputAudio = (float *)malloc(context->audioFrames * context->audioChannels * sizeof(float));
-	if(gInputAudio == 0)
-		return false;
-
-	// Allocate the window buffer based on the FFT size
-	gWindowBuffer = (float *)malloc(gFFTSize * sizeof(float));
-	if(gWindowBuffer == 0)
-		return false;
-
-	// Calculate a Hann window
-	for(int n = 0; n < gFFTSize; n++) {
-		gWindowBuffer[n] = 0.5f * (1.0f - cosf(2.0 * M_PI * n / (float)(gFFTSize - 1)));
-	}
-
-	// Initialise auxiliary tasks
-	if((gFFTTask = Bela_createAuxiliaryTask(&process_fft_background, 90, "fft-calculation")) == 0)
-		return false;
-	rt_printf("You are listening to an FFT phase-vocoder with overlap-and-add.\n"
-	"Use Midi Control Change to control:\n"
-	"CC 2: effect type (bypass/robotization/whisperization)\n"
-	"CC 3: mix between recorded sample and live audio input\n"
-	"CC 4: mix between the unprocessed and processed sound\n"
-	"CC 5: gain\n"
-	);
-	return true;
-}
-
-// This function handles the FFT processing in this example once the buffer has
-// been assembled.
-void process_fft(float *inBuffer, int inWritePointer, float *outBuffer, int outWritePointer)
-{
-	// Copy buffer into FFT input
-	int pointer = (inWritePointer - gFFTSize + BUFFER_SIZE) % BUFFER_SIZE;
-	for(int n = 0; n < gFFTSize; n++) {
-		timeDomainIn[n].r = (ne10_float32_t) inBuffer[pointer] * gWindowBuffer[n];
-		timeDomainIn[n].i = 0;
-
-		pointer++;
-		if(pointer >= BUFFER_SIZE)
-			pointer = 0;
-	}
-
-	// Run the FFT
-	ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg, 0);
-
-	switch (gEffect){
-	  case kRobot :
-	  // Robotise the output
-	    for(int n = 0; n < gFFTSize; n++) {
-	      float amplitude = sqrtf(frequencyDomain[n].r * frequencyDomain[n].r + frequencyDomain[n].i * frequencyDomain[n].i);
-	      frequencyDomain[n].r = amplitude;
-	      frequencyDomain[n].i = 0;
-	    }
-	    break;
-	  case kWhisper :
-	    for(int n = 0; n < gFFTSize; n++) {
-	      float amplitude = sqrtf(frequencyDomain[n].r * frequencyDomain[n].r + frequencyDomain[n].i * frequencyDomain[n].i);
-	      float phase = rand()/(float)RAND_MAX * 2 * M_PI;
-	      frequencyDomain[n].r = cosf(phase) * amplitude;
-	      frequencyDomain[n].i = sinf(phase) * amplitude;
-	    }
-	    break;
-	  case kBypass:
-	    //bypass
-	    break;
-	  }
-
-	// Run the inverse FFT
-	ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg, 1);
-	// Overlap-and-add timeDomainOut into the output buffer
-	pointer = outWritePointer;
-	for(int n = 0; n < gFFTSize; n++) {
-		outBuffer[pointer] += (timeDomainOut[n].r) * gFFTScaleFactor;
-		if(isnan(outBuffer[pointer]))
-			rt_printf("outBuffer OLA\n");
-		pointer++;
-		if(pointer >= BUFFER_SIZE)
-			pointer = 0;
-	}
-}
-
-// Function to process the FFT in a thread at lower priority
-void process_fft_background() {
-	process_fft(gInputBuffer, gFFTInputBufferPointer, gOutputBuffer, gFFTOutputBufferPointer);
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-void render(BelaContext* context, void* userData)
-{
-	float* audioOut = context->audioOut;
-	int numAudioFrames = context->audioFrames;
-	int numAudioChannels = context->audioChannels;
-	// ------ this code internal to the demo; leave as is ----------------
-
-	// Prep the "input" to be the sound file played in a loop
-	for(int n = 0; n < numAudioFrames; n++) {
-		if(gReadPtr < gSampleData.sampleLen)
-			gInputAudio[2*n] = gInputAudio[2*n+1] = gSampleData.samples[gReadPtr]*(1-gPlaybackLive) +
-			gPlaybackLive*0.5f*(audioRead(context,n,0)+audioRead(context,n,1));
-		else
-			gInputAudio[2*n] = gInputAudio[2*n+1] = 0;
-		if(++gReadPtr >= gSampleData.sampleLen)
-			gReadPtr = 0;
-	}
-	// -------------------------------------------------------------------
-
-	for(int n = 0; n < numAudioFrames; n++) {
-		gInputBuffer[gInputBufferPointer] = ((gInputAudio[n*numAudioChannels] + gInputAudio[n*numAudioChannels+1]) * 0.5);
-
-		// Copy output buffer to output
-		for(int channel = 0; channel < numAudioChannels; channel++){
-			audioOut[n * numAudioChannels + channel] = gOutputBuffer[gOutputBufferReadPointer] * gGain * gDryWet + (1 - gDryWet) * gInputAudio[n * numAudioChannels + channel];
-		}
-
-		// Clear the output sample in the buffer so it is ready for the next overlap-add
-		gOutputBuffer[gOutputBufferReadPointer] = 0;
-		gOutputBufferReadPointer++;
-		if(gOutputBufferReadPointer >= BUFFER_SIZE)
-			gOutputBufferReadPointer = 0;
-		gOutputBufferWritePointer++;
-		if(gOutputBufferWritePointer >= BUFFER_SIZE)
-			gOutputBufferWritePointer = 0;
-
-		gInputBufferPointer++;
-		if(gInputBufferPointer >= BUFFER_SIZE)
-			gInputBufferPointer = 0;
-
-		gSampleCount++;
-		if(gSampleCount >= gHopSize) {
-			//process_fft(gInputBuffer, gInputBufferPointer, gOutputBuffer, gOutputBufferPointer);
-			gFFTInputBufferPointer = gInputBufferPointer;
-			gFFTOutputBufferPointer = gOutputBufferWritePointer;
-			Bela_scheduleAuxiliaryTask(gFFTTask);
-
-			gSampleCount = 0;
-		}
-	}
-	gHopSize = gPeriod;
-}
-
-// cleanup_render() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in initialise_render().
-
-void cleanup(BelaContext* context, void* userData)
-{
-	NE10_FREE(timeDomainIn);
-	NE10_FREE(timeDomainOut);
-	NE10_FREE(frequencyDomain);
-	NE10_FREE(cfg);
-	free(gInputAudio);
-	free(gWindowBuffer);
-}
Binary file examples/basic_FFT_phase_vocoder/sample.wav has changed
--- a/examples/basic_analog_input/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-int gSensorInputFrequency = 0;
-int gSensorInputAmplitude = 1;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --frequency [-f] input:  Choose the analog input controlling frequency (0-7; default 0)\n";
-	cerr << "   --amplitude [-a] input:  Choose the analog input controlling amplitude (0-7; default 1)\n";
-	cerr << "   --help [-h]:             Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{"amplitude", 1, NULL, 'a'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:a:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				gSensorInputFrequency = atoi(optarg);
-				if(gSensorInputFrequency < 0 || gSensorInputFrequency > 7) {
-					usage(basename(argv[0]));
-					exit(0);
-				}
-				break;
-		case 'a':
-				gSensorInputAmplitude = atoi(optarg);
-				if(gSensorInputAmplitude < 0 || gSensorInputAmplitude > 7) {
-					usage(basename(argv[0]));
-					exit(0);
-				}
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, 0) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	if(settings.verbose) {
-		cout << "--> Frequency on input " << gSensorInputFrequency << endl;
-		cout << "--> Amplitude on input " << gSensorInputAmplitude << endl;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/basic_analog_input/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-/**
-\example 3_analog_input
-
-Connecting potentiometers
--------------------------
-
-This sketch produces a sine tone, the frequency and amplitude of which are 
-affected by data received on the analog pins. Before looping through each audio 
-frame, we declare a value for the frequency and amplitude of our sine tone 
-(line 55); we adjust these values by taking in data from analog sensors 
-(for example potentiometers) with `analogRead()`.
-
-- connect a 10K pot to 3.3V and GND on its 1st and 3rd pins.
-- connect the 2nd middle pin of the pot to analogIn 0.
-- connect another 10K pot in the same way but with the middle pin connected to analogIn 1.
-
-The important thing to notice is that audio is sampled twice as often as analog 
-data. The audio sampling rate is 44.1kHz (44100 frames per second) and the 
-analog sampling rate is 22.05kHz (22050 frames per second). On line 62 you might 
-notice that we are processing the analog data and updating frequency and 
-amplitude only on every second audio sample, since the analog sampling rate is 
-half that of the audio.
-
-Note that the pin numbers are stored in the variables `gAnalogInputFrequency` and 
-`gAnalogInputAmplitude`. These are declared in the main.cpp file; if you look in 
-that file you will see that they have the values of 0 and 1. Bear in mind that 
-these are analog input pins which is a specific header!
-*/
-
-#include <Bela.h>
-#include <rtdk.h>
-#include <cmath>
-
-float gPhase;
-float gInverseSampleRate;
-int gAudioFramesPerAnalogFrame;
-
-// These settings are carried over from main.cpp
-// Setting global variables is an alternative approach
-// to passing a structure to userData in setup()
-
-extern int gSensorInputFrequency;
-extern int gSensorInputAmplitude;
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	if(context->analogFrames == 0 || context->analogFrames > context->audioFrames) {
-		rt_printf("Error: this example needs analog enabled, with 4 or 8 channels\n");
-		return false;
-	}
-
-	gAudioFramesPerAnalogFrame = context->audioFrames / context->analogFrames;
-	gInverseSampleRate = 1.0 / context->audioSampleRate;
-	gPhase = 0.0;
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	float frequency = 440.0;
-	float amplitude = 0.8;
-
-	// There are twice as many audio frames as matrix frames since audio sample rate
-	// is twice as high
-
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		if(!(n % gAudioFramesPerAnalogFrame)) {
-			// Even audio samples: update frequency and amplitude from the matrix
-			frequency = map(analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputFrequency), 0, 1, 100, 1000);
-			amplitude = analogRead(context, n/gAudioFramesPerAnalogFrame, gSensorInputAmplitude);
-		}
-
-		float out = amplitude * sinf(gPhase);
-
-		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-			context->audioOut[n * context->audioChannels + channel] = out;
-
-		gPhase += 2.0 * M_PI * frequency * gInverseSampleRate;
-		if(gPhase > 2.0 * M_PI)
-			gPhase -= 2.0 * M_PI;
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/basic_analog_output/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --frequency [-f] frequency: Set the frequency of the LED fade (default: 1.0)\n";
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	float frequency = 1.0;	// Frequency of LED fades
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// In this example, audio isn't used so might as well leave speaker muted
-	settings.beginMuted = 1;
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				frequency = atof(optarg);
-				if(frequency < 0)
-					frequency = 0;
-				if(frequency > 11025.0)
-					frequency = 11025.0;
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &frequency) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/basic_analog_output/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- *
- * Andrew McPherson and Victor Zappi
- * Queen Mary, University of London
- */
-
-/**
-\example 3_analog_output
-
-Fading LEDs
------------
-
-This sketch uses a sine wave to drive the brightness of a series of LEDs 
-connected to the eight analog out pins. Again you can see the nested `for` loop 
-structure but this time for the analog output channels rather than the audio.
-
-- connect an LED in series with a 470ohm resistor between each of the analogOut pins and ground.
-
-Within the first for loop in render we cycle through each frame in the analog 
-output matrix. At each frame we then cycle through the analog output channels 
-with another for loop and set the output voltage according to the phase of a 
-sine tone that acts as an LFO. The analog output pins can provide a voltage of 
-~4.092V.
-
-The output on each pin is set with `analogWrite()` within the for loop that 
-cycles through the analog output channels. This needs to be provided with 
-arguments as follows `analogWrite(context, n, channel, out)`. Channel is 
-where the you give the address of the analog output pin (in this case we cycle 
-through each pin address in the for loop), out is the variable that holds the 
-desired output (in this case set by the sine wave).
-
-Notice that the phase of the brightness cycle for each led is different. This 
-is achieved by updating a variable that stores a relative phase value. This 
-variable is advanced by pi/4 (1/8 of a full rotation) for each channel giving 
-each of the eight LEDs a different phase.
-*/
-
-#include <Bela.h>
-#include <rtdk.h>
-#include <cmath>
-
-// Set range for analog outputs designed for driving LEDs
-const float kMinimumAmplitude = (1.5 / 5.0);
-const float kAmplitudeRange = 1.0 - kMinimumAmplitude;
-
-float gFrequency;
-float gPhase;
-float gInverseSampleRate;
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	// Retrieve a parameter passed in from the initAudio() call
-	gFrequency = *(float *)userData;
-
-	if(context->analogFrames == 0) {
-		rt_printf("Error: this example needs the matrix enabled\n");
-		return false;
-	}
-
-	gInverseSampleRate = 1.0 / context->analogSampleRate;
-	gPhase = 0.0;
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->analogFrames; n++) {
-		// Set LED to different phase for each matrix channel
-		float relativePhase = 0.0;
-		for(unsigned int channel = 0; channel < context->analogChannels; channel++) {
-			float out = kMinimumAmplitude + kAmplitudeRange * 0.5f * (1.0f + sinf(gPhase + relativePhase));
-
-			analogWrite(context, n, channel, out);
-
-			// Advance by pi/4 (1/8 of a full rotation) for each channel
-			relativePhase += M_PI * 0.25;
-		}
-
-		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
-		if(gPhase > 2.0 * M_PI)
-			gPhase -= 2.0 * M_PI;
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/basic_blink/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- *
- * Andrew McPherson and Victor Zappi
- * Queen Mary, University of London
- */
-
-/**
-\example 2_digital_blink
-
-Blinking an LED
----------------
-
-This sketch shows the simplest case of digital out. 
-
-- Connect an LED in series with a 470ohm resistor between P8_07 and ground. 
-
-The led is blinked on and off by setting the digital pin `HIGH` and `LOW` every interval seconds which is set in 
-`render()`.
-
-In `setup()` the pin mode must be set to output mode via `pinMode()`. For example: 
-`pinMode(context, 0, P8_07, OUTPUT)`. 
-In `render()` the output of the digital pins is set by `digitalWrite()`. For example: 
-`digitalWrite(context, n, P8_07, status)` where `status` can be equal to 
-either `HIGH` or `LOW`. When set `HIGH` the pin will give 3.3V, when set to 
-`LOW` 0V.
-
-To keep track of elapsed time we have a sample counter count. When the count reaches 
-a certain limit it switches state to either `HIGH` or `LOW` depending on its current 
-value. In this case the limit is `context->digitalSampleRate*interval` which 
-allows us to write the desired interval in seconds, stored in `interval`.
-*/
-
-#include <Bela.h>
-#include <cmath>
-#include <rtdk.h>
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-    pinMode(context, 0, P8_07, OUTPUT);
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numAnalogFrames
-// will be 0.
-
-/* basic_blink
-* Connect an LED in series with a 470ohm resistor between P8_07 and ground.
-* The LED will blink every @interval seconds.
-*/
-
-void render(BelaContext *context, void *userData)
-{
-  static int count=0; //counts elapsed samples
-  float interval=0.5; //how often to toggle the LED (in seconds)
-  static int status=GPIO_LOW;
-	for(unsigned int n=0; n<context->digitalFrames; n++){
-    if(count==context->digitalSampleRate*interval){ //if enough samples have elapsed
-      count=0; //reset the counter
-    // status=digitalRead(context, 0, P8_07);
-      if(status==GPIO_LOW) { //toggle the status
-          digitalWrite(context, n, P8_07, status); //write the status to the LED
-          status=GPIO_HIGH;
-      }
-      else {
-          digitalWrite(context, n, P8_07, status); //write the status to the LED
-          status=GPIO_LOW;
-      }
-    }
-    count++;
-  }
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	// Nothing to do here
-}
--- a/examples/basic_button/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- *
- * Andrew McPherson and Victor Zappi
- * Queen Mary, University of London
- */
-
-/**
-\example 2_digital_button
-
-Switching an LED on and off
----------------------------
-
-This example brings together digital input and digital output. The program will read 
-a button and turn the LED on and off according to the state of the button.
-
-- connect an LED in series with a 470ohm resistor between P8_07 and ground.
-- connect a 1k resistor to P9_03 (+3.3V),
-- connect the other end of the resistor to both a button and P8_08
-- connect the other end of the button to ground.
-
-You will notice that the LED will normally stay on and will turn off as long as 
-the button is pressed. This is due to the fact that the LED is set to the same 
-value read at input P8_08. When the button is not pressed, P8_08 is `HIGH` and so 
-P8_07 is set to `HIGH` as well, so that the LED conducts and emits light. When 
-the button is pressed, P8_08 goes `LOW` and P8_07 is set to `LOW`, turning off the LED.
-
-As an exercise try and change the code so that the LED only turns on when 
-the button is pressed.
-*/
-
-#include <Bela.h>
-#include <cmath>
-#include <rtdk.h>
-#include <stdlib.h>
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	pinMode(context, 0, P8_08, INPUT);
-	pinMode(context, 0, P8_07, OUTPUT);
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numAnalogFrames
-// will be 0.
-
-/* basic_button
-* - connect an LED in series with a 470ohm resistor between P8_07 and ground.
-* - connect a 1k resistor to P9_03 (+3.3V), 
-* - connect the other end of the resistor to both a button and P8_08
-* - connect the other end of the button to ground.
-* The program will read the button and make the LED blink when the button is pressed.
-*/
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n=0; n<context->digitalFrames; n++){
-		int status=digitalRead(context, 0, P8_08); //read the value of the button
-		digitalWriteOnce(context, n, P8_07, status); //write the status to the LED
-		float out = 0.1 * status * rand() / (float)RAND_MAX * 2 - 1; //generate some noise, gated by the button
-		for(unsigned int j = 0; j < context->audioChannels; j++){
-			audioWrite(context, n, j, out); //write the audio output
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	// Nothing to do here
-}
-
--- a/examples/basic_midi/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,165 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <Bela.h>
-#include <Midi.h>
-#include <stdlib.h>
-#include <rtdk.h>
-#include <cmath>
-
-float gFreq;
-float gPhaseIncrement = 0;
-bool gIsNoteOn = 0;
-int gVelocity = 0;
-float gSamplingPeriod = 0;
-
-void midiMessageCallback(MidiChannelMessage message, void* arg){
-	if(arg != NULL){
-		rt_printf("Message from midi port %d: ", *(int*)arg);
-	}
-	message.prettyPrint();
-	if(message.getType() == kmmNoteOn){
-		gFreq = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
-		gVelocity = message.getDataByte(1);
-		gPhaseIncrement = 2 * M_PI * gFreq * gSamplingPeriod;
-		gIsNoteOn = gVelocity > 0;
-		rt_printf("v0:%f, ph: %6.5f, gVelocity: %d\n", gFreq, gPhaseIncrement, gVelocity);
-	}
-}
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-Midi midi;
-int gMidiPort0 = 0;
-bool setup(BelaContext *context, void *userData)
-{
-	midi.readFrom(gMidiPort0);
-	midi.writeTo(gMidiPort0);
-	midi.enableParser(true);
-	midi.setParserCallback(midiMessageCallback, &gMidiPort0);
-	if(context->analogFrames == 0) {
-		rt_printf("Error: this example needs the analog I/O to be enabled\n");
-		return false;
-	}
-	gSamplingPeriod = 1/context->audioSampleRate;
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-
-enum {kVelocity, kNoteOn, kNoteNumber};
-void render(BelaContext *context, void *userData)
-{
-// one way of getting the midi data is to parse them yourself
-//	(you should set midi.enableParser(false) above):
-/*
-	static midi_byte_t noteOnStatus = 0x90; //on channel 1
-	static int noteNumber = 0;
-	static int waitingFor = kNoteOn;
-	static int playingNote = -1;
-	int message;
-	while ((message = midi.getInput()) >= 0){
-		rt_printf("%d\n", message);
-		switch(waitingFor){
-		case kNoteOn:
-			if(message == noteOnStatus){
-				waitingFor = kNoteNumber;
-			}
-			break;
-		case kNoteNumber:
-			if((message & (1<<8)) == 0){
-				noteNumber = message;
-				waitingFor = kVelocity;
-			}
-			break;
-		case kVelocity:
-			if((message & (1<<8)) == 0){
-				int _velocity = message;
-				waitingFor = kNoteOn;
-				// "monophonic" behaviour, with priority to the latest note on
-				// i.e.: a note off from a previous note does not stop the current note
-				// still you might end up having a key down and no note being played if you pressed and released another
-				// key in the meantime
-				if(_velocity == 0 && noteNumber == playingNote){
-					noteOn = false;
-					playingNote = -1;
-					velocity = _velocity;
-				} else if (_velocity > 0) {
-					noteOn = true;
-					velocity = _velocity;
-					playingNote = noteNumber;
-					f0 = powf(2, (playingNote-69)/12.0f) * 440;
-					phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
-				}
-				rt_printf("NoteOn: %d, NoteNumber: %d, velocity: %d\n", noteOn, noteNumber, velocity);
-			}
-			break;
-		}
-	}
-*/
-	/*
-	int num;
-	//alternatively, you can use the built-in parser (only processes channel messages at the moment).
-	while((num = midi.getParser()->numAvailableMessages()) > 0){
-		static MidiChannelMessage message;
-		message = midi.getParser()->getNextChannelMessage();
-		message.prettyPrint();
-		if(message.getType() == kmmNoteOn){
-			f0 = powf(2, (message.getDataByte(0)-69)/12.0f) * 440;
-			velocity = message.getDataByte(1);
-			phaseIncrement = 2 * M_PI * f0 / context->audioSampleRate;
-			noteOn = velocity > 0;
-			rt_printf("v0:%f, ph: %6.5f, velocity: %d\n", f0, phaseIncrement, gVelocity);
-		}
-	}
-	 */
-	// the following block toggles the LED on an Owl pedal
-	// and asks the pedal to return the status of the LED
-	// using MIDI control changes
-	for(unsigned int n = 0; n < context->analogFrames; n++){
-		static int count = 0;
-		static bool state = 0;
-		analogWriteOnce(context, n, 1, state);
-		if(count % 40000 == 0){
-			state = !state;
-			midi_byte_t bytes[6] = {176, 30, (char)(state*127), 176, 67, 30}; // toggle the OWL led and ask for the led status
-			midi.writeOutput(bytes, 6);
-		}
-		count++;
-	}
-	for(unsigned int n = 0; n < context->audioFrames; n++){
-		if(gIsNoteOn == 1){
-			static float phase = 0;
-			phase += gPhaseIncrement;
-			if(phase > 2 * M_PI)
-				phase -= 2 * M_PI;
-			float value = sinf(phase) * gVelocity/128.0f;
-			audioWrite(context, n, 0, value);
-			audioWrite(context, n, 1, value);
-		} else {
-			audioWrite(context, n, 0, 0);
-			audioWrite(context, n, 1, 0);
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/basic_network/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	float frequency = 440.0;		// Frequency of oscillator
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				frequency = atof(optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &frequency) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/basic_passthru/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --help [-h]:             Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "h", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, 0) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/basic_passthru/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,127 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
- /*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-/**
-\example 1_basic_audio_analog_passthrough
-
-Audio and analog passthrough: input to output
------------------------------------------
-
-This sketch demonstrates how to read from and write to the audio and analog input and output buffers.
-
-In `render()` you'll see a nested for loop structure. You'll see this in all Bela projects. 
-The first for loop cycles through `audioFrames`, the second through 
-`audioChannels` (in this case left 0 and right 1).
-
-You can access any information about current audio and sensor settings you can do the following: 
-`context->name_of_item`. For example `context->audioChannels` returns current number of channels,
-`context->audioFrames` returns the current number of audio frames, 
-`context->audioSampleRate` returns the audio sample rate.
-
-You can look at all the information you can access in ::BeagleRTContext.
-
-Reading and writing from the audio buffers
-------------------------------------------
-
-The simplest way to read samples from the audio input buffer is with
-`audioRead()` which we pass three arguments: context, current audio 
-frame and current channel. In this example we have 
-`audioRead(context, n, ch)` where both `n` and `ch` are provided by 
-the nested for loop structure.
-
-We can write samples to the audio output buffer in a similar way using 
-`audioWrite()`. This has a fourth argument which is the value of the output.
-For example `audioWrite(context, n, ch, value_to_output)`.
-
-Reading and writing from the analog buffers
--------------------------------------------
-
-The same is true for `analogRead()` and `analogWrite()`.
-
-Note that for the analog channels we write to and read from the buffers in a separate set 
-of nested for loops. This is because the they are sampled at half audio rate by default. 
-The first of these for loops cycles through `analogFrames`, the second through
-`analogChannels`.
-
-By setting `audioWriteFrame(context, n, ch, audioReadFrame(context, n, ch))` and
-`analogWrite(context, n, ch, analogReadFrame(context, n, ch))` we have a simple 
-passthrough of audio input to output and analog input to output.
-
-
-It is also possible to address the buffers directly, for example: 
-`context->audioOut[n * context->audioChannels + ch]`.
-*/
-
-#include <Bela.h>
-#include <rtdk.h>
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	// Nothing to do here...
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	// Simplest possible case: pass inputs through to outputs
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		for(unsigned int ch = 0; ch < context->audioChannels; ch++){
-			// Two equivalent ways to write this code
-
-			// The long way, using the buffers directly:
-			// context->audioOut[n * context->audioChannels + ch] =
-			// 		context->audioIn[n * context->audioChannels + ch];
-
-			// Or using the macros:
-			audioWrite(context, n, ch, audioRead(context, n, ch));
-		}
-	}
-
-	// Same with analog channelss
-	for(unsigned int n = 0; n < context->analogFrames; n++) {
-		for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
-			// Two equivalent ways to write this code
-
-			// The long way, using the buffers directly:
-			// context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch];
-
-			// Or using the macros:
-			analogWrite(context, n, ch, analogRead(context, n, ch));
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/basic_pulseIn/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <Bela.h>
-#include <PulseIn.h>
-#include <stdlib.h>
-#include <rtdk.h>
-#include <cmath>
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-PulseIn pulseIn;
-int gPulseInPin = 0;
-int gDigitalOutPin = 1;
-int gPulseLength = 1234;
-int gSamplesBetweenPulses = 10000;
-
-bool setup(BelaContext *context, void *userData)
-{
-	pinMode(context, 0, gDigitalOutPin, OUTPUT);
-	pulseIn.init(context, gPulseInPin, 1); //third parameter is direction
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	static bool pulseOut = 0;
-	static int count = 0;
-	for(unsigned int n = 0; n < context->digitalFrames; n++){
-		// detect if a pulse just ended
-		int duration = pulseIn.hasPulsed(context, n);
-		if(duration > 0){
-			rt_printf("duration = %d\n", duration);
-		}
-
-		// generate a rectangular waveform as a test signal.
-		// Connect gDigitalOutPin to gPulseInPin
-		// to verify that the detected pulse length is gPulseLength
-		if(count == gPulseLength ){
-			pulseOut = false;
-		}
-		if(count == (gPulseLength + gSamplesBetweenPulses)){
-			pulseOut = true;
-			count = 0;
-		}
-		digitalWrite(context, n, gDigitalOutPin, pulseOut);
-		count++;
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/basic_writeFile/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-#include <unistd.h>
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	float frequency = 440.0;	// Frequency of oscillator
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				frequency = atof(optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &frequency) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/basic_writeFile/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-#include <Bela.h> 
-#include <cmath>
-#include <WriteFile.h>
-
-float gPhase1, gPhase2;
-float gFrequency1, gFrequency2;
-float gInverseSampleRate;
-
-WriteFile file1;
-WriteFile file2;
-
-bool setup(BelaContext *context, void *userData)
-{
-	gInverseSampleRate = 1.0/context->audioSampleRate;
-	file1.init("out1.m"); //set the file name to write to
-	file1.setHeader("myvar=[\n"); //set a line to be printed at the beginning of the file
-	file1.setFooter("];\n"); //set a line to be printed at the end of the file
-	file1.setEcho(true); // enable echo to the console (as well as to the file)
-	file1.setFormat("%.5f %.10f %f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers)
-	file2.init("out2.m");
-	file2.setHeader("input=[\n");
-	file2.setFooter("];\n");
-	file2.setEcho(false);
-	file2.setFormat("%f\n");
-	gPhase1 = 0.0;
-	gPhase2 = 0.0;
-
-	gFrequency1 = 200.0;
-	gFrequency2 = 201.0;
-	return true; 
-}
-
-void render(BelaContext *context, void *userData)
-{
-	static int count = 0;
-	if((count&16383) == 0){
-    	file2.log(context->audioIn, context->audioFrames); //write the input buffer every so often
-	}
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-	    float chn1 = sinf(gPhase1);
-	    float chn2 = sinf(gPhase2);
-	    gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate;
-	    gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
-		if(gPhase1 > 2.0 * M_PI)
-			gPhase1 -= 2.0 * M_PI;
-		if(gPhase2 > 2.0 * M_PI)
-			gPhase2 -= 2.0 * M_PI;
-		if( (count&511) == 0){
-			file1.log(chn1);
-			file1.log(chn2);
-			file1.log(count);
-		}
-		count++;
-	}
-}
-
-// cleanup_render() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in initialise_render().
-
-void cleanup(BelaContext *context, void *userData)
-{
-    
-}
--- a/examples/bucket_brigade_chorus/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-#include <Bela.h> 
-#include <Scope.h>
-#include <cmath>
-
-float gPhase1, gPhase2;
-float gFrequency1, gFrequency2;
-float gInverseSampleRate;
-
-// initialise_render() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-#include <I2c_Codec.h>
-#include <PRU.h>
-extern I2c_Codec *gAudioCodec;
-extern PRU *gPRU;
-float D=5264;
-#define delayLength 256
-float delay[delayLength];
-int writePointer=0;
-int readPointer=writePointer+1;
-AuxiliaryTask updatePll;
-
-void updatePllFunction(){
-//	gPRU->setGPIOTestPin();
-	static int count = 0;
-	while(!gShouldStop){
-		gAudioCodec->setPllD(D);
-		count++;
-		if((count&4095)==0)
-			printf("sampling rate: %f\n",gAudioCodec->getAudioSamplingRate());
-		usleep(100);
-	}
-//	gPRU->clearGPIOTestPin();
-}
-
-bool setup(BelaContext *context, void *userData)
-{
-	gInverseSampleRate = 1.0/context->audioSampleRate;
-	
-	gPhase1 = 0.0;
-	gPhase2 = 0.0;
-	
-	gFrequency1 = 200.0;
-	gFrequency2 = 201.0;
-	updatePll=Bela_createAuxiliaryTask(&updatePllFunction, 91, "update PLL");
-	for(int n=0; n<delayLength; n++){
-		delay[n]=0;
-	}
-	return true; 
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-//	printf("here\n");
-	static bool init = false;
-	if(init == false){
-		Bela_scheduleAuxiliaryTask(updatePll);
-//		gAudioCodec->setPllP(2);
-//		gAudioCodec->setPllR();
-//		gAudioCodec->setAudioSamplingRate(43600);
-//		printf("samplingRate: %f, k: %f\n", gAudioCodec->getAudioSamplingRate(), gAudioCodec->getPllK());
-		init = true;
-	}
-	static int count=0;
-	static float lfoPhase=0;
-	static float feedback=0;
-	int updateRate=1;
-	if((count&(updateRate-1))==0){
-		float amplitude = 8000;
-		float rate = 2;
-		lfoPhase+=rate*2*M_PI*updateRate*context->analogFrames/context->audioSampleRate;
-		D=amplitude+amplitude*sinf(lfoPhase);
-		if((count&255)==0){
-//			rt_printf("frequency: %f\n", gAudioCodec->getAudioSamplingRate());
-//			rt_printf("D: %.0f\n", D);
-//			rt_printf("rate: %f\n", rate);
-//			rt_printf("amplitude: %.3f\n", amplitude);
-//			rt_printf("feedback: %.3f\n\n", feedback);
-		}
-	}
-	count++;
-
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		feedback = 0.4;
-		float input = audioRead(context, n, 0) + audioRead(context, n, 1);
-	    delay[writePointer++] = input + delay[readPointer]*feedback;
-	    float output = (input + 0.9*delay[readPointer++] ) * 0.5;
-		audioWrite(context, n, 0, output);
-		audioWrite(context, n, 1, output);
-		if(writePointer>=delayLength)
-			writePointer-=delayLength;
-		if(readPointer>=delayLength)
-			readPointer-=delayLength;
-
-		gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate;
-	    gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
-		if(gPhase1 > 2.0 * M_PI)
-			gPhase1 -= 2.0 * M_PI;
-		if(gPhase2 > 2.0 * M_PI)
-			gPhase2 -= 2.0 * M_PI;
-	}
-}
-
-// cleanup_render() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in initialise_render().
-
-void cleanup(BelaContext *context, void *userData)
-{
-    
-}
--- a/examples/cape_test/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-#include <unistd.h>
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	float frequency = 440.0;	// Frequency of oscillator
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				frequency = atof(optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &frequency) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/cape_test/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-
-#include <Bela.h>
-#include <cmath>
-
-#define ANALOG_LOW	(2048.0 / 65536.0)
-#define ANALOG_HIGH (50000.0 / 65536.0)
-
-const int gDACPinOrder[] = {6, 4, 2, 0, 1, 3, 5, 7};
-
-enum {
-	kStateTestingAudioLeft = 0,
-	kStateTestingAudioRight,
-	kStateTestingAudioDone
-};
-
-uint64_t gLastErrorFrame = 0;
-uint32_t gEnvelopeSampleCount = 0;
-float gEnvelopeValueL = 0.5, gEnvelopeValueR = 0.5;
-float gEnvelopeDecayRate = 0.9995;
-int gEnvelopeLastChannel = 0;
-
-float gPositivePeakLevels[2] = {0, 0};
-float gNegativePeakLevels[2] = {0, 0};
-float gPeakLevelDecayRate = 0.999;
-const float gPeakLevelLowThreshold = 0.02;
-const float gPeakLevelHighThreshold = 0.2;
-const float gDCOffsetThreshold = 0.1;
-int gAudioTestState = kStateTestingAudioLeft;
-int gAudioTestStateSampleCount = 0;
-int gAudioTestSuccessCounter = 0;
-const int gAudioTestSuccessCounterThreshold = 64;
-const int gAudioTestStateSampleThreshold = 16384;
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	static float phase = 0.0;
-	static int sampleCounter = 0;
-	static int invertChannel = 0;
-	float frequency = 0;
-
-	// Play a sine wave on the audio output
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		
-		// Peak detection on the audio inputs, with offset to catch
-		// DC errors
-		for(int ch = 0; ch < 2; ch++) {
-			if(context->audioIn[2*n + ch] > gPositivePeakLevels[ch])
-				gPositivePeakLevels[ch] = context->audioIn[2*n + ch];
-			gPositivePeakLevels[ch] += 0.1;
-			gPositivePeakLevels[ch] *= gPeakLevelDecayRate;
-			gPositivePeakLevels[ch] -= 0.1;
-			if(context->audioIn[2*n + ch] < gNegativePeakLevels[ch])
-				gNegativePeakLevels[ch] = context->audioIn[2*n + ch];
-			gNegativePeakLevels[ch] -= 0.1;			
-			gNegativePeakLevels[ch] *= gPeakLevelDecayRate;
-			gNegativePeakLevels[ch] += 0.1;
-		}
-		
-		if(gAudioTestState == kStateTestingAudioLeft) {
-			context->audioOut[2*n] = 0.2 * sinf(phase);
-			context->audioOut[2*n + 1] = 0;		
-			
-			frequency = 3000.0;
-			phase += 2.0 * M_PI * frequency / 44100.0;
-			if(phase >= 2.0 * M_PI)
-				phase -= 2.0 * M_PI;
-			
-			gAudioTestStateSampleCount++;
-			if(gAudioTestStateSampleCount >= gAudioTestStateSampleThreshold) {
-				// Check if we have the expected input: signal on the left but not
-				// on the right. Also check that there is not too much DC offset on the
-				// inactive signal
-				if((gPositivePeakLevels[0] - gNegativePeakLevels[0]) >= gPeakLevelHighThreshold 
-					&& (gPositivePeakLevels[1] -  gNegativePeakLevels[1]) <= gPeakLevelLowThreshold &&
-					fabsf(gPositivePeakLevels[1]) < gDCOffsetThreshold &&
-					fabsf(gNegativePeakLevels[1]) < gDCOffsetThreshold) {
-					// Successful test: increment counter
-					gAudioTestSuccessCounter++;
-					if(gAudioTestSuccessCounter >= gAudioTestSuccessCounterThreshold) {
-						gAudioTestState = kStateTestingAudioRight;
-						gAudioTestStateSampleCount = 0;
-						gAudioTestSuccessCounter = 0;
-					}
-
-				}
-				else {
-					if(!((context->audioFramesElapsed + n) % 22050)) {
-						// Debugging print messages
-						if((gPositivePeakLevels[0] - gNegativePeakLevels[0]) < gPeakLevelHighThreshold)
-							rt_printf("Left Audio In FAIL: insufficient signal: %f\n", 
-										gPositivePeakLevels[0] - gNegativePeakLevels[0]);
-						else if(gPositivePeakLevels[1] -  gNegativePeakLevels[1] > gPeakLevelLowThreshold)
-							rt_printf("Right Audio In FAIL: signal present when it should not be: %f\n",
-										gPositivePeakLevels[1] -  gNegativePeakLevels[1]);
-						else if(fabsf(gPositivePeakLevels[1]) >= gDCOffsetThreshold ||
-								fabsf(gNegativePeakLevels[1]) >= gDCOffsetThreshold)
-							rt_printf("Right Audio In FAIL: DC offset: (%f, %f)\n",
-										gPositivePeakLevels[1], gNegativePeakLevels[1]);						
-					}
-					gAudioTestSuccessCounter--;
-					if(gAudioTestSuccessCounter <= 0)
-						gAudioTestSuccessCounter = 0;
-				}
-			}
-		}
-		else if(gAudioTestState == kStateTestingAudioRight) {
-			context->audioOut[2*n] = 0;
-			context->audioOut[2*n + 1] = 0.2 * sinf(phase);
-			
-			frequency = 3000.0;
-			phase += 2.0 * M_PI * frequency / 44100.0;
-			if(phase >= 2.0 * M_PI)
-				phase -= 2.0 * M_PI;
-			
-			gAudioTestStateSampleCount++;
-			if(gAudioTestStateSampleCount >= gAudioTestStateSampleThreshold) {
-				// Check if we have the expected input: signal on the left but not
-				// on the right
-				if((gPositivePeakLevels[1] - gNegativePeakLevels[1]) >= gPeakLevelHighThreshold 
-					&& (gPositivePeakLevels[0] -  gNegativePeakLevels[0]) <= gPeakLevelLowThreshold &&
-					fabsf(gPositivePeakLevels[0]) < gDCOffsetThreshold &&
-					fabsf(gNegativePeakLevels[0]) < gDCOffsetThreshold) {
-					// Successful test: increment counter
-					gAudioTestSuccessCounter++;
-					if(gAudioTestSuccessCounter >= gAudioTestSuccessCounterThreshold) {
-						gAudioTestSuccessCounter = 0;							
-						gAudioTestStateSampleCount = 0;
-						gAudioTestState = kStateTestingAudioDone;
-					}
-				}
-				else {
-					if(!((context->audioFramesElapsed + n) % 22050)) {
-						// Debugging print messages
-						if((gPositivePeakLevels[1] - gNegativePeakLevels[1]) < gPeakLevelHighThreshold)
-							rt_printf("Right Audio In FAIL: insufficient signal: %f\n", 
-										gPositivePeakLevels[1] - gNegativePeakLevels[1]);
-						else if(gPositivePeakLevels[0] -  gNegativePeakLevels[0] > gPeakLevelLowThreshold)
-							rt_printf("Left Audio In FAIL: signal present when it should not be: %f\n",
-										gPositivePeakLevels[0] -  gNegativePeakLevels[0]);
-						else if(fabsf(gPositivePeakLevels[0]) >= gDCOffsetThreshold ||
-								fabsf(gNegativePeakLevels[0]) >= gDCOffsetThreshold)
-							rt_printf("Left Audio In FAIL: DC offset: (%f, %f)\n",
-										gPositivePeakLevels[0], gNegativePeakLevels[0]);						
-					}
-					gAudioTestSuccessCounter--;
-					if(gAudioTestSuccessCounter <= 0)
-						gAudioTestSuccessCounter = 0;
-				}
-			}			
-		}
-		else {
-			// Audio input testing finished. Play tones depending on status of
-			// analog testing
-			context->audioOut[2*n] = gEnvelopeValueL * sinf(phase);
-			context->audioOut[2*n + 1] = gEnvelopeValueR * sinf(phase);
-
-			// If one second has gone by with no error, play one sound, else
-			// play another
-			if(context->audioFramesElapsed + n - gLastErrorFrame > 44100) {
-				gEnvelopeValueL *= gEnvelopeDecayRate;
-				gEnvelopeValueR *= gEnvelopeDecayRate;
-				gEnvelopeSampleCount++;
-				if(gEnvelopeSampleCount > 22050) {
-					if(gEnvelopeLastChannel == 0)
-						gEnvelopeValueR = 0.5;
-					else
-						gEnvelopeValueL = 0.5;
-					gEnvelopeLastChannel = !gEnvelopeLastChannel;
-					gEnvelopeSampleCount = 0;
-				}
-				frequency = 880.0;
-			}
-			else {
-				gEnvelopeValueL = gEnvelopeValueR = 0.5;
-				gEnvelopeLastChannel = 0;
-				frequency = 220.0;
-			}
-
-			phase += 2.0 * M_PI * frequency / 44100.0;
-			if(phase >= 2.0 * M_PI)
-				phase -= 2.0 * M_PI;
-		}
-	}
-
-	for(unsigned int n = 0; n < context->analogFrames; n++) {
-		// Change outputs every 512 samples
-		if(sampleCounter < 512) {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel)
-					context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH;
-				else
-					context->analogOut[n*8 + gDACPinOrder[k]] = 0;
-			}
-		}
-		else {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel)
-					context->analogOut[n*8 + gDACPinOrder[k]] = 0;
-				else
-					context->analogOut[n*8 + gDACPinOrder[k]] = ANALOG_HIGH;
-			}
-		}
-
-		// Read after 256 samples: input should be low
-		if(sampleCounter == 256) {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel) {
-					if(context->analogIn[n*8 + k] < ANALOG_HIGH) {
-						rt_printf("FAIL [output %d, input %d] -- output HIGH input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
-						gLastErrorFrame = context->audioFramesElapsed + n;
-					}
-				}
-				else {
-					if(context->analogIn[n*8 + k] > ANALOG_LOW) {
-						rt_printf("FAIL [output %d, input %d] -- output LOW --> input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
-						gLastErrorFrame = context->audioFramesElapsed + n;
-					}
-				}
-			}
-		}
-		else if(sampleCounter == 768) {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel) {
-					if(context->analogIn[n*8 + k] > ANALOG_LOW) {
-						rt_printf("FAIL [output %d, input %d] -- output LOW input %f (inverted)\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
-						gLastErrorFrame = context->audioFramesElapsed + n;
-					}
-				}
-				else {
-					if(context->analogIn[n*8 + k] < ANALOG_HIGH) {
-						rt_printf("FAIL [output %d, input %d] -- output HIGH input %f\n", gDACPinOrder[k], k, context->analogIn[n*8 + k]);
-						gLastErrorFrame = context->audioFramesElapsed + n;
-					}
-				}
-			}
-		}
-
-		if(++sampleCounter >= 1024) {
-			sampleCounter = 0;
-			invertChannel++;
-			if(invertChannel >= 8)
-				invertChannel = 0;
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/core/link_core.sh	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-#!/bin/sh
-ln -f -s ../../core/ source
-ln -f -s ../../include/ include
--- a/examples/core/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-#include <Bela.h>
-
-bool setup(BelaContext *context, void *userData)
-{
-	return true;
-}
-
-void render(BelaContext *context, void *userData)
-{
-
-}
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
\ No newline at end of file
--- a/examples/d-box/ADSR.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-//
-//  ADSR.cpp
-//
-//  Created by Nigel Redmon on 12/18/12.
-//  EarLevel Engineering: earlevel.com
-//  Copyright 2012 Nigel Redmon
-//
-//  For a complete explanation of the ADSR envelope generator and code,
-//  read the series of articles by the author, starting here:
-//  http://www.earlevel.com/main/2013/06/01/envelope-generators/
-//
-//  License:
-//
-//  This source code is provided as is, without warranty.
-//  You may copy and distribute verbatim copies of this document.
-//  You may modify and use this source code to create binary code for your own purposes, free or commercial.
-//
-
-#include "ADSR.h"
-#include <math.h>
-
-
-ADSR::ADSR(void) {
-    reset();
-    setAttackRate(0);
-    setDecayRate(0);
-    setReleaseRate(0);
-    setSustainLevel(1.0);
-    setTargetRatioA(0.3);
-    setTargetRatioDR(0.0001);
-}
-
-ADSR::~ADSR(void) {
-}
-
-void ADSR::setAttackRate(float rate) {
-    attackRate = rate;
-    attackCoef = calcCoef(rate, targetRatioA);
-    attackBase = (1.0 + targetRatioA) * (1.0 - attackCoef);
-}
-
-void ADSR::setDecayRate(float rate) {
-    decayRate = rate;
-    decayCoef = calcCoef(rate, targetRatioDR);
-    decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
-}
-
-void ADSR::setReleaseRate(float rate) {
-    releaseRate = rate;
-    releaseCoef = calcCoef(rate, targetRatioDR);
-    releaseBase = -targetRatioDR * (1.0 - releaseCoef);
-}
-
-float ADSR::calcCoef(float rate, float targetRatio) {
-    return exp(-log((1.0 + targetRatio) / targetRatio) / rate);
-}
-
-void ADSR::setSustainLevel(float level) {
-    sustainLevel = level;
-    decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
-}
-
-void ADSR::setTargetRatioA(float targetRatio) {
-    if (targetRatio < 0.000000001)
-        targetRatio = 0.000000001;  // -180 dB
-    targetRatioA = targetRatio;
-    attackBase = (1.0 + targetRatioA) * (1.0 - attackCoef);
-}
-
-void ADSR::setTargetRatioDR(float targetRatio) {
-    if (targetRatio < 0.000000001)
-        targetRatio = 0.000000001;  // -180 dB
-    targetRatioDR = targetRatio;
-    decayBase = (sustainLevel - targetRatioDR) * (1.0 - decayCoef);
-    releaseBase = -targetRatioDR * (1.0 - releaseCoef);
-}
--- a/examples/d-box/ADSR.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-//
-//  ADRS.h
-//
-//  Created by Nigel Redmon on 12/18/12.
-//  EarLevel Engineering: earlevel.com
-//  Copyright 2012 Nigel Redmon
-//
-//  For a complete explanation of the ADSR envelope generator and code,
-//  read the series of articles by the author, starting here:
-//  http://www.earlevel.com/main/2013/06/01/envelope-generators/
-//
-//  License:
-//
-//  This source code is provided as is, without warranty.
-//  You may copy and distribute verbatim copies of this document.
-//  You may modify and use this source code to create binary code for your own purposes, free or commercial.
-//
-
-#ifndef ADRS_h
-#define ADRS_h
-
-#include <stdio.h>
-#include <string>
-
-using namespace std;
-
-enum envState {
-	env_idle = 0,
-	env_attack,
-	env_decay,
-	env_sustain,
-	env_release
-};
-
-class ADSR {
-public:
-	ADSR(void);
-	~ADSR(void);
-	float process(void);
-	float process(int sampleCount);
-    float getOutput(void);
-    int getState(void);
-	void gate(int on);
-    void setAttackRate(float rate);
-    void setDecayRate(float rate);
-    void setReleaseRate(float rate);
-	void setSustainLevel(float level);
-    void setTargetRatioA(float targetRatio);
-    void setTargetRatioDR(float targetRatio);
-    void reset(void);
-
-protected:
-	int state;
-	float output;
-	float attackRate;
-	float decayRate;
-	float releaseRate;
-	float attackCoef;
-	float decayCoef;
-	float releaseCoef;
-	float sustainLevel;
-    float targetRatioA;
-    float targetRatioDR;
-    float attackBase;
-    float decayBase;
-    float releaseBase;
-	string name;
-    float calcCoef(float rate, float targetRatio);
-};
-
-inline float ADSR::process() {
-	switch (state) {
-        case env_idle:
-            break;
-        case env_attack:
-            output = attackBase + output * attackCoef;
-            if (output >= 1.0) {
-                output = 1.0;
-                state = env_decay;
-            }
-            break;
-        case env_decay:
-            output = decayBase + output * decayCoef;
-            if (output <= sustainLevel) {
-                output = sustainLevel;
-                state = env_sustain;
-            }
-            break;
-        case env_sustain:
-            break;
-        case env_release:
-            output = releaseBase + output * releaseCoef;
-            if (output <= 0.0) {
-                output = 0.0;
-                state = env_idle;
-            }
-            break;
-	}
-	return output;
-}
-
-inline float ADSR::process(int sampleCount)
-{
-	float retVal = 0;
-
-	if(state != env_idle)
-	{
-		for(int i=0; i<sampleCount; i++)
-			retVal = process();
-	}
-
-	return retVal;
-}
-
-inline void ADSR::gate(int gate) {
-
-	if (gate)
-		state = env_attack;
-	else if (state != env_idle)
-        state = env_release;
-}
-
-inline int ADSR::getState() {
-    return state;
-}
-
-inline void ADSR::reset() {
-    state = env_idle;
-    output = 0.0;
-}
-
-inline float ADSR::getOutput() {
-	return output;
-}
-
-
-#endif
--- a/examples/d-box/AnalogInput.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * AnalogInput.cpp
- *
- *  Created on: Oct 17, 2013
- *      Author: Victor Zappi
- */
-
-
-#include "AnalogInput.h"
-
-using namespace std;
-
-
-AnalogInput::AnalogInput()
-{
-	ActivateAnalogHnd  = NULL;
-	activateAnalogPath = "";
-	analogIsSet        = false;
-
-	AnalogInHnd    = NULL;
-	analogInPath   = "";
-	helperNumFound = false;
-
-	// support var for init
-	// these are fixed for BBB
-	startPath = "/sys/devices/bone_capemgr.*/slots";
-	readPath = "";
-
-	buffer = (char*) malloc (sizeof(char)*lSize); // reading buffer
-
-	verbose = false;
-}
-
-
-AnalogInput::~AnalogInput()
-{
-	free(buffer);
-}
-
-int AnalogInput::initAnalogInputs()
-{
-	 if(analogIsSet)
-	 {
-		 if(verbose)
-			 cout << "Fine, but Analog Input already active..."<< endl;
-		 return 0;
-	 }
-
-	// title
-	 if(verbose)
-	 	cout << "Init Analog Input"<< endl;
-
-
-	  // first: activate analog pins on cape manager
-	  // cape-bone-iio > /sys/devices/bone_capemgr.*/slots
-
-	  // we have to look for the semi-random number the BBB has initialized the bone_capemgr with [value of *]
-	  // to reach /slots and set cape-bone-iio.
-	  // to do so, we use glob lib, which translates wildcards [*] into all the values found in paths
-
-
-	  glob( startPath.c_str(), 0, NULL, &globbuf);
-
-	  if(globbuf.gl_pathc >0)
-	  {
-	    if (globbuf.gl_pathc == 1 )
-	    {
-	      activateAnalogPath = globbuf.gl_pathv[0];
-
-	      // check if file is existing
-	      if((ActivateAnalogHnd = fopen(activateAnalogPath.c_str(), "r+")) != NULL)
-	      {
-	        // we found that current capemgr num
-
-			fwrite("cape-bone-iio", sizeof(char), 13, ActivateAnalogHnd); // activate pins
-
-	        analogIsSet = true;
-
-			if(verbose)
-				cout << "Analog Pins activated via cape-bone-iio at path " << activateAnalogPath << endl;
-
-			fclose(ActivateAnalogHnd); // close file
-	      }
-	    }
-	    //else
-	      //printf("toomany", );
-	  }
-
-	  globfree(&globbuf); // self freeing
-
-
-	  if(!analogIsSet)
-	  {
-	    cout << "cannot find bone_capemgr" << endl;
-	    cout << "------Init failed------" << endl;
-	    return 1;
-	  }
-
-
-	  // build read path
-	  startPath = "/sys/devices/ocp.2/helper.*";
-
-	  glob( startPath.c_str(), 0, NULL, &globbuf);
-
-	  if(globbuf.gl_pathc >0)
-	  {
-		if (globbuf.gl_pathc == 1 )
-		{
-		  analogInPath = globbuf.gl_pathv[0] + (string)"/AIN";
-		}
-	    else
-	      cout << "Too many analog inputs with this name! [I am puzzled...]" << endl;
-	  }
-	  else
-	    cout << "Cannot find analog input dir...puzzled" << endl;
-
-
-	  return 0;
-}
-
-
-int AnalogInput::read(int index)
-{
-	  // convert int index into string
-	  stringstream ss;
-	  ss << index;
-
-	  readPath = analogInPath + ss.str(); // create pin0 file path
-
-
-	  // check if file is existing
-	  if((AnalogInHnd = fopen(readPath.c_str(), "rb")) != NULL)
-	  {
-		// we found that current helper num
-
-		// prepare read buffer to reading
-		fseek (AnalogInHnd , 0 , SEEK_END);
-		lSize = ftell (AnalogInHnd);
-		rewind (AnalogInHnd);
-
-		result = fread (buffer, 1, lSize, AnalogInHnd);
-
-		fclose(AnalogInHnd); // close file
-
-		helperNumFound = true;
-
-		//cout << "Analog Pins can be read at path " << analogInPath << endl;
-		//cout << "Test reading of Pin0 gives: " << buffer << endl;
-	  }
-
-	  if(!helperNumFound)
-	  {
-	    cout << "cannot find helper" << endl;
-	    cout << "------Analog Read failed------" << endl;
-	    return -1;
-	  }
-
-	  return atoi(buffer);
-
-}
-
-
-
--- a/examples/d-box/AnalogInput.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * AnalogInput.h
- *
- *  Created on: Oct 17, 2013
- *      Author: Victor Zappi
- */
-
-#ifndef ANALOGINPUT_H_
-#define ANALOGINPUT_H_
-
-#include <iostream>
-#include <sstream>
-#include <stdio.h>
-#include <stdlib.h>
-#include <glob.h>
-
-using namespace std;
-
-class AnalogInput
-{
-private:
-	FILE *ActivateAnalogHnd;
-	string activateAnalogPath;
-	bool analogIsSet;
-
-	FILE *AnalogInHnd;
-	string analogInPath;
-	bool helperNumFound;
-
-	// suport var for init
-	string startPath;
-	string readPath;
-
-	glob_t  globbuf;
-
-	// support vars for pin reading
-	long lSize;
-	char * buffer;
-	size_t result;
-
-	bool verbose;
-
-public:
-	AnalogInput();
-	~AnalogInput();
-
-	int initAnalogInputs();
-	int read(int index);
-
-};
-
-
-
-
-#endif /* ANALOGINPUT_H_ */
--- a/examples/d-box/Biquad.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-//
-//  Biquad.cpp
-//
-//  Created by Nigel Redmon on 11/24/12
-//  EarLevel Engineering: earlevel.com
-//  Copyright 2012 Nigel Redmon
-//
-//  For a complete explanation of the Biquad code:
-//  http://www.earlevel.com/main/2012/11/26/biquad-c-source-code/
-//
-//  License:
-//
-//  This source code is provided as is, without warranty.
-//  You may copy and distribute verbatim copies of this document.
-//  You may modify and use this source code to create binary code
-//  for your own purposes, free or commercial.
-//
-
-#include <math.h>
-#include "Biquad.h"
-#include <iostream>
-
-Biquad::Biquad() {
-    type = bq_type_lowpass;
-    a0 = 1.0;
-    a1 = a2 = b1 = b2 = 0.0;
-    Fc = 0.50;
-    Q = 0.707;
-    peakGain = 0.0;
-    z1 = z2 = 0.0;
-}
-
-Biquad::Biquad(int type, double Fc, double Q, double peakGainDB) {
-    setBiquad(type, Fc, Q, peakGainDB);
-    z1 = z2 = 0.0;
-}
-
-Biquad::~Biquad() {
-}
-
-void Biquad::setType(int type) {
-    this->type = type;
-    calcBiquad();
-}
-
-void Biquad::setQ(double Q) {
-    this->Q = Q;
-    calcBiquad();
-}
-
-void Biquad::setFc(double Fc) {
-    this->Fc = Fc;
-    calcBiquad();
-}
-
-void Biquad::setPeakGain(double peakGainDB) {
-    this->peakGain = peakGainDB;
-    calcBiquad();
-}
-    
-void Biquad::setBiquad(int type, double Fc, double Q, double peakGainDB) {
-    this->type = type;
-    this->Q = Q;
-    this->Fc = Fc;
-    startFc = Fc;
-    startQ = Q;
-    startPeakGain = peakGainDB;
-    setPeakGain(peakGainDB);
-}
-
-void Biquad::calcBiquad(void) {
-    double norm;
-    double V = pow(10, fabs(peakGain) / 20.0);
-    double K = tan(M_PI * Fc);
-    switch (this->type) {
-        case bq_type_lowpass:
-            norm = 1 / (1 + K / Q + K * K);
-            a0 = K * K * norm;
-            a1 = 2 * a0;
-            a2 = a0;
-            b1 = 2 * (K * K - 1) * norm;
-            b2 = (1 - K / Q + K * K) * norm;
-            break;
-            
-        case bq_type_highpass:
-            norm = 1 / (1 + K / Q + K * K);
-            a0 = 1 * norm;
-            a1 = -2 * a0;
-            a2 = a0;
-            b1 = 2 * (K * K - 1) * norm;
-            b2 = (1 - K / Q + K * K) * norm;
-            break;
-            
-        case bq_type_bandpass:
-            norm = 1 / (1 + K / Q + K * K);
-            a0 = K / Q * norm;
-            a1 = 0;
-            a2 = -a0;
-            b1 = 2 * (K * K - 1) * norm;
-            b2 = (1 - K / Q + K * K) * norm;
-            break;
-            
-        case bq_type_notch:
-            norm = 1 / (1 + K / Q + K * K);
-            a0 = (1 + K * K) * norm;
-            a1 = 2 * (K * K - 1) * norm;
-            a2 = a0;
-            b1 = a1;
-            b2 = (1 - K / Q + K * K) * norm;
-            break;
-            
-        case bq_type_peak:
-            if (peakGain >= 0) {    // boost
-                norm = 1 / (1 + 1/Q * K + K * K);
-                a0 = (1 + V/Q * K + K * K) * norm;
-                a1 = 2 * (K * K - 1) * norm;
-                a2 = (1 - V/Q * K + K * K) * norm;
-                b1 = a1;
-                b2 = (1 - 1/Q * K + K * K) * norm;
-            }
-            else {    // cut
-                norm = 1 / (1 + V/Q * K + K * K);
-                a0 = (1 + 1/Q * K + K * K) * norm;
-                a1 = 2 * (K * K - 1) * norm;
-                a2 = (1 - 1/Q * K + K * K) * norm;
-                b1 = a1;
-                b2 = (1 - V/Q * K + K * K) * norm;
-            }
-            break;
-        case bq_type_lowshelf:
-            if (peakGain >= 0) {    // boost
-                norm = 1 / (1 + sqrt(2) * K + K * K);
-                a0 = (1 + sqrt(2*V) * K + V * K * K) * norm;
-                a1 = 2 * (V * K * K - 1) * norm;
-                a2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
-                b1 = 2 * (K * K - 1) * norm;
-                b2 = (1 - sqrt(2) * K + K * K) * norm;
-            }
-            else {    // cut
-                norm = 1 / (1 + sqrt(2*V) * K + V * K * K);
-                a0 = (1 + sqrt(2) * K + K * K) * norm;
-                a1 = 2 * (K * K - 1) * norm;
-                a2 = (1 - sqrt(2) * K + K * K) * norm;
-                b1 = 2 * (V * K * K - 1) * norm;
-                b2 = (1 - sqrt(2*V) * K + V * K * K) * norm;
-            }
-            break;
-        case bq_type_highshelf:
-            if (peakGain >= 0) {    // boost
-                norm = 1 / (1 + sqrt(2) * K + K * K);
-                a0 = (V + sqrt(2*V) * K + K * K) * norm;
-                a1 = 2 * (K * K - V) * norm;
-                a2 = (V - sqrt(2*V) * K + K * K) * norm;
-                b1 = 2 * (K * K - 1) * norm;
-                b2 = (1 - sqrt(2) * K + K * K) * norm;
-            }
-            else {    // cut
-                norm = 1 / (V + sqrt(2*V) * K + K * K);
-                a0 = (1 + sqrt(2) * K + K * K) * norm;
-                a1 = 2 * (K * K - 1) * norm;
-                a2 = (1 - sqrt(2) * K + K * K) * norm;
-                b1 = 2 * (K * K - V) * norm;
-                b2 = (V - sqrt(2*V) * K + K * K) * norm;
-            }
-            break;
-    }
-    
-    return;
-}
--- a/examples/d-box/Biquad.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-//
-//  Biquad.h
-//
-//  Created by Nigel Redmon on 11/24/12
-//  EarLevel Engineering: earlevel.com
-//  Copyright 2012 Nigel Redmon
-//
-//  For a complete explanation of the Biquad code:
-//  http://www.earlevel.com/main/2012/11/25/biquad-c-source-code/
-//
-//  License:
-//
-//  This source code is provided as is, without warranty.
-//  You may copy and distribute verbatim copies of this document.
-//  You may modify and use this source code to create binary code
-//  for your own purposes, free or commercial.
-//
-
-#ifndef Biquad_h
-#define Biquad_h
-
-enum {
-    bq_type_lowpass = 0,
-    bq_type_highpass,
-    bq_type_bandpass,
-    bq_type_notch,
-    bq_type_peak,
-    bq_type_lowshelf,
-    bq_type_highshelf
-};
-
-class Biquad {
-public:
-    Biquad();
-    Biquad(int type, double Fc, double Q, double peakGainDB);
-    ~Biquad();
-    void setType(int type);
-    void setQ(double Q);
-    void setFc(double Fc);
-    void setPeakGain(double peakGainDB);
-    void setBiquad(int type, double Fc, double Q, double peakGain);
-    float process(float in);
-    
-    double getQ();
-    double getFc();
-    double getPeakGain();
-
-    double getStartingQ();
-	double getStartingFc();
-	double getStartingPeakGain();
-
-protected:
-    void calcBiquad(void);
-
-    int type;
-    double a0, a1, a2, b1, b2;
-    double Fc, Q, peakGain;
-    double startFc, startQ, startPeakGain;
-    double z1, z2;
-};
-
-inline double Biquad::getQ()
-{
-	return Q;
-}
-
-inline double Biquad::getFc()
-{
-	return Fc;
-}
-
-inline double Biquad::getPeakGain()
-{
-	return peakGain;
-}
-
-inline double Biquad::getStartingQ()
-{
-	return startQ;
-}
-
-inline double Biquad::getStartingFc()
-{
-	return startFc;
-}
-
-inline double Biquad::getStartingPeakGain()
-{
-	return startPeakGain;
-}
-
-inline float Biquad::process(float in) {
-    double out = in * a0 + z1;
-    z1 = in * a1 + z2 - b1 * out;
-    z2 = in * a2 - b2 * out;
-    return out;
-}
-
-#endif // Biquad_h
--- a/examples/d-box/DBoxSynth.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * SimpleSynth.h
- *
- *  Created on: Oct 22, 2013
- *      Author: Victor Zappi
- */
-
-#ifndef DBOXSYNTH_H_
-#define DBOXSYNTH_H_
-
-#include <iostream>
-#include <string>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "Synth.h"
-
-
-class DBoxSynth : public Synth
-{
-public:
-	DBoxSynth(unsigned int rate, unsigned long buffer_size);
-	double getSample();
-	double *getBlock(int block_size);
-
-
-private:
-	Sampler *smp;
-
-};
-
-
-
-
-#endif /* DBOXSYNTH_H_ */
--- a/examples/d-box/DboxSensors.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,157 +0,0 @@
-/*
- * DboxSensors.cpp
- *
- *  Created on: May 19, 2014
- *      Author: Victor Zappi
- */
-
-
-#include "DboxSensors.h"
-#include "config.h"
-
-using namespace std;
-
-
-
-int DboxSensors::initSensors(int tk0_bus, int tk0_address, int tk1_bus, int tk1_address, int tk_file, int fsr_pin, int fsrmax, int sensorTypeToUse, int gpio_0, int gpio_1)
-{
-	sensorType = sensorTypeToUse;
-	// init first touch key on i2c bus
-	if(tk0_address >= 0) {
-		if(TK0.initI2C_RW(tk0_bus, tk0_address, tk_file)>0)
-			return 1;
-		if(TK0.initTouchKey(sensorType)>0)
-			return 2;
-	}
-
-	// init second touch key on i2c bus
-	if(tk1_address >= 0) {
-		if(TK1.initI2C_RW(tk1_bus, tk1_address, tk_file)>0)
-			return 1;
-		if(TK1.initTouchKey(sensorType)>0)
-			return 2;
-	}
-
-	// init fsr on analog input pin
-	fsr_pinNum	= fsr_pin;
-	fsr_max	  	= fsrmax;
-
-	if(FSR.initAnalogInputs()>0)
-		return 3;
-
-	gpio[0] = gpio_0;
-	if(gpio[0]!=-1)
-	{
-		fdDi[0] = gpio_export(gpio[0]);
-		if(fdDi[0] == -1)
-			return 4;
-	}
-	digitalIn[0] = 1;
-
-	return 0;
-}
-
-
-int DboxSensors::readSensors()
-{
-	// write data into first touch key
-	if(TK0.ready()) {
-		if(TK0.readI2C()>0)
-			return 1;
-
-		// retrieve data from first touch key
-		tk0_touchCnt = TK0.getTouchCount();
-	}
-	else
-		tk0_touchCnt = 0;
-
-	// write data into second touch key
-	if(TK1.ready()) {
-		if(TK1.readI2C()>0)
-			return 1;
-		// retrieve data from second touch key
-		tk1_touchCnt = TK1.getTouchCount();
-	}
-	else
-		tk1_touchCnt = 0;
-
-
-	int max = 3;
-	if(sensorType != kSensorTypeTouchKey)
-		max = 5;
-	// if touches detected on main touch key
-	if(tk0_touchCnt == 0 && tk1_touchCnt == 0)
-		resetSensorsData();
-	else
-	{
-		for(int i=0; i<max; i++)
-		{
-			tk0_touchPosX[i] = TK0.getSliderPosition()[i];
-			tk0_touchSize[i] = TK0.getSlidersize()[i];
-
-			tk1_touchPosX[i] = TK1.getSliderPosition()[i];
-			tk1_touchSize[i] = TK1.getSlidersize()[i];
-		}
-		tk0_touchPosY 	 = TK0.getSliderPositionH();
-		tk1_touchPosY 	 = TK1.getSliderPositionH();
-		fsr_read		 = (double)FSR.read(fsr_pinNum);
-	}
-
-	if(gpio[0]!=-1)
-	{
-		if(gpio_read(fdDi[0], &digitalIn[0])==-1)
-			return 1;
-	}
-
-	return 0;
-}
-
-
-
-DboxSensors::DboxSensors()
-{
-	resetSensorsData();
-}
-
-
-
-DboxSensors::~DboxSensors()
-{
-	if(gpio[0]!=-1)
-		gpio_dismiss(fdDi[0], gpio[0]);
-}
-
-
-
-//--------------------------------------------------------------------------------------------------------
-// private methods
-//--------------------------------------------------------------------------------------------------------
-
-// idle values
-void DboxSensors::resetSensorsData()
-{
-	int max = 3;
-	if(sensorType != kSensorTypeTouchKey)
-		max = 5;
-
-	for(int i=0; i<max; i++)
-	{
-		tk0_touchPosX[i] = -1;
-		tk0_touchPosY	 = -1;
-		tk0_touchSize[i] = 0;
-
-		tk1_touchPosX[i] = -1;
-		tk1_touchPosY	 = -1;
-		tk1_touchSize[i] = 0;
-
-		fsr_read		 = 0;
-	}
-
-	return;
-}
-
-
-
-
-
-
--- a/examples/d-box/DboxSensors.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/*
- * DboxSensors.h
- *
- *  Created on: May 19, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef DBOXSENSORS_H_
-#define DBOXSENSORS_H_
-
-#include <stdio.h>
-#include <sys/mount.h>	// mount()
-#include <string.h> 	// strerror()
-#include <fstream> 		// fstream
-#include <iostream>
-#include <unistd.h> 	// usleep()
-#include <glob.h>		// glob()
-#include <sys/time.h>	// elapsed time
-#include <sys/stat.h>	// mkdir()
-#include <algorithm>	// reverse() [string...]
-
-#include "I2c_TouchKey.h"
-#include "AnalogInput.h"
-#include <GPIOcontrol.h>	// TODO wrap this into a class
-
-/*---------------------------------------------------------------------------------------------------------------------------------------------------
- * This class retrieves data from all the connected sensors,
- * logs them
- * and exposes to the main only the values needed to synthesize sound
- *
- * The simple instrument has:
- *
- *
- *
- *---------------------------------------------------------------------------------------------------------------------------------------------------
- */
-class DboxSensors
-{
-public:
-	int initSensors(int tk0_bus, int tk0_address, int tk1_bus, int tk1_address, int tk_file, int fsr_pin, int fsrmax, int sensorTypeToUse, int gpio0=-1, int gpio1=-1);
-	int readSensors();
-	int getTKTouchCount(int index);
-	float *getTKXPositions(int index);
-	float getTKYPosition(int index);
-	float *getTKTouchSize(int index);
-	double getFSRVAlue();
-	int getDigitalIn(int index);
-
-	DboxSensors();
-	~DboxSensors();
-
-private:
-	int sensorType;
-
-	I2c_TouchKey TK0;
-	int tk0_touchCnt;
-	float tk0_touchPosX[5];
-	float tk0_touchPosY;
-	float tk0_touchSize[5];
-
-	I2c_TouchKey TK1;
-	int tk1_touchCnt;
-	float tk1_touchPosX[5];
-	float tk1_touchPosY;
-	float tk1_touchSize[5];
-
-	AnalogInput FSR;
-	int fsr_pinNum;
-	double fsr_read;
-	int fsr_max;
-
-	unsigned int digitalIn[2];
-	int fdDi[2];
-	int gpio[2];
-
-	void resetSensorsData();
-
-};
-
-
-
-//--------------------------------------------------------------------------------
-// read interface
-inline int DboxSensors::getTKTouchCount(int index)
-{
-	if(index==0)
-		return tk0_touchCnt;
-	else
-		return tk1_touchCnt;
-}
-
-inline float *DboxSensors::getTKXPositions(int index)
-{
-	if(index==0)
-		return tk0_touchPosX;
-	else
-		return tk1_touchPosX;
-}
-
-inline float DboxSensors::getTKYPosition(int index)
-{
-	if(index==0)
-		return tk0_touchPosY;
-	else
-		return tk1_touchPosY;
-}
-
-inline float *DboxSensors::getTKTouchSize(int index)
-{
-	if(index==0)
-		return tk0_touchSize;
-	else
-		return tk1_touchSize;
-}
-
-inline double DboxSensors::getFSRVAlue()
-{
-	return fsr_read;
-}
-
-inline int DboxSensors::getDigitalIn(int index)
-{
-	return digitalIn[index];
-}
-//--------------------------------------------------------------------------------
-
-
-#endif /* DBOXSENSORS_H_ */
--- a/examples/d-box/FIRfilter.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * FIRfilter.h
- *
- *  Created on: Aug 5, 2014
- *      Author: Victor Zappi and Andrew McPherson
- */
-
-#ifndef FIRFILTER_H_
-#define FIRFILTER_H_
-
-#define ENABLE_NE10_FIR_FLOAT_NEON	// Define needed for Ne10 library
-#include <ne10/NE10.h>
-
-//#define FILTER_TAP_NUM 21
-//ne10_float32_t filterTaps[FILTER_TAP_NUM] = {
-//	0.000350,
-//	0.001133,
-//	0.002407,
-//	0.004203,
-//	0.006468,
-//	0.009057,
-//	0.011748,
-//	0.014265,
-//	0.016323,
-//	0.017671,
-//	0.018141,
-//	0.017671,
-//	0.016323,
-//	0.014265,
-//	0.011748,
-//	0.009057,
-//	0.006468,
-//	0.004203,
-//	0.002407,
-//	0.001133,
-//	0.000350
-//};
-#define FILTER_TAP_NUM 31
-ne10_float32_t filterTaps[FILTER_TAP_NUM] = {
-		0.000018,
-		0.000043,
-		0.000078,
-		0.000125,
-		0.000183,
-		0.000252,
-		0.000330,
-		0.000415,
-		0.000504,
-		0.000592,
-		0.000677,
-		0.000754,
-		0.000818,
-		0.000866,
-		0.000897,
-		0.000907,
-		0.000897,
-		0.000866,
-		0.000818,
-		0.000754,
-		0.000677,
-		0.000592,
-		0.000504,
-		0.000415,
-		0.000330,
-		0.000252,
-		0.000183,
-		0.000125,
-		0.000078,
-		0.000043,
-		0.000018
-};
-
-#endif /* FIRFILTER_H_ */
--- a/examples/d-box/FeedbackOscillator.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * FeedbackOscillator.cpp
- *
- * Recursive phase-shift oscillator implemented
- * on the matrix
- *
- * Andrew McPherson 2014
- */
-
-#include "FeedbackOscillator.h"
-#include <cstdlib>
-#include <cmath>
-
-#define COEFF_B0 	0
-#define COEFF_B1	1
-#define COEFF_A1	2
-
-FeedbackOscillator::FeedbackOscillator()
-: wavetable1(0), wavetable2(0)
-{
-
-}
-
-FeedbackOscillator::~FeedbackOscillator() {
-	if(wavetable1 != 0)
-		free(wavetable1);
-	if(wavetable2 != 0)
-		free(wavetable2);
-
-}
-
-// Initialise the settings for the feedback oscillator
-void FeedbackOscillator::initialise(int maxTableSize, float hpfCutoffFrequency, float matrixSampleRate) {
-	wavetableMaxLength = maxTableSize;
-	if(wavetable1 != 0)
-		free(wavetable1);
-	if(wavetable2 != 0)
-		free(wavetable2);
-
-	wavetable1 = (float *)malloc(maxTableSize * sizeof(float));
-	wavetable2 = (float *)malloc(maxTableSize * sizeof(float));
-
-	float omega = tan(M_PI * hpfCutoffFrequency / matrixSampleRate);
-	float n = 1.0f / (1.0f + omega);
-
-	coeffs[COEFF_A1] = (omega - 1.0f) * n;
-	coeffs[COEFF_B0] = n;
-	coeffs[COEFF_B1] = -n;
-
-	for(int n = 0; n < maxTableSize; n++)
-		wavetable1[n] = wavetable2[n] = 0;
-
-	wavetableRead = wavetable1;
-	wavetableWrite = wavetable2;
-	wavetableWritePointer = 0;
-	sampleCount = lastTriggerCount = 0;
-}
-
-// Process one sample and store the output value
-// Returns true if the wavetable needs rendering
-int FeedbackOscillator::process(float input, float *output) {
-	float outFloat = coeffs[COEFF_B0] * input + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput;
-	int requestRenderLength = 0;
-
-	if(outFloat < -0.5)
-		*output = 0;
-	else if(outFloat > 0.5)
-		*output = 1;
-	else
-		*output = outFloat + 0.5;
-
-	if(canTrigger && outFloat > 0 && lastOutput <= 0) {
-		triggered = true;
-		requestRenderLength = wavetableWritePointer;	// How many samples stored thus far?
-		if(requestRenderLength < 4)
-			requestRenderLength = 0;	// Ignore anything with fewer than 4 points
-
-		lastTriggerCount = sampleCount;
-		canTrigger = false;
-		wavetableWritePointer = 0;
-
-		// Swap buffers
-		float *temp = wavetableWrite;
-		wavetableWrite = wavetableRead;
-		wavetableRead = temp;
-	}
-
-	if(triggered) {
-		wavetableWrite[wavetableWritePointer] = outFloat;
-		if(++wavetableWritePointer >= wavetableMaxLength) {
-			triggered = false;
-			wavetableWritePointer = 0;
-		}
-	}
-
-	if(sampleCount - lastTriggerCount > 40)
-		canTrigger = true;
-
-	sampleCount++;
-
-	lastOutput = outFloat;
-	lastInput = input;
-
-	return requestRenderLength;
-}
--- a/examples/d-box/FeedbackOscillator.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * FeedbackOscillator.h
- *
- *  Created on: June 8, 2014
- *      Author: Andrew McPherson
- */
-
-#ifndef FEEDBACKOSCILLATOR_H
-#define FEEDBACKOSCILLATOR_H
-
-class FeedbackOscillator
-{
-public:
-	FeedbackOscillator();
-	~FeedbackOscillator();
-
-	// Initialise the settings for the feedback oscillator
-	void initialise(int maxTableSize, float hpfCutoffFrequency, float matrixSampleRate);
-
-	// Process one sample and store the output value
-	// Returns the length of table to interpolate; or 0 if nothing to process further
-	int process(float input, float *output);
-
-	float *wavetable() { return wavetableRead; }
-
-private:
-	float coeffs[3];			// Coefficients of first-order high-pass filter
-	float lastInput;			// last input sample for HPF
-	float lastOutput;			// last output sample of HPF
-	bool triggered;				// whether we are currently saving samples
-	bool canTrigger;			// whether we are able to begin saving samples
-	int wavetableMaxLength;		// how long the stored wavetable can be
-	int sampleCount;			// how many samples have elapsed
-	int lastTriggerCount;		// sample count when we last triggered
-
-	float *wavetable1, *wavetable2;			// Two wavetables where we record samples
-	float *wavetableRead, *wavetableWrite;	// Pointers to the above wavetables
-	int wavetableWritePointer;				// Where we are currently writing
-};
-
-#endif
--- a/examples/d-box/OscillatorBank.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1016 +0,0 @@
-/*
- * OscillatorBank.cpp
- *
- *  Created on: May 23, 2014
- *      Author: Victor Zappi and Andrew McPherson
- */
-
-
-/*
- * There is a problem with name consistency between this class and the Parser class in spear_parser files.
- * There, a "frame" is each of the time values where partials are sampled, while a "hop" is the actual jump between frames [calculated in samples]
- * Here, "hop" is used with the meaning of "frame", while "frame" became the local frame of a partial
- *
- * example
- *
- * frames:	0		1		2
- * p0				p0_0 	p0_1
- * p1		p1_0	p1_1 	p1_2
- * p2		p2_0	p2_1
- *
- * 	In this case:
- * 		 in Parser there are 2 hops, 3 total frames and the 3 partials have respectively 2, 3 and 2 local frames
- *
- * 		 here there are 3 total hops [the concept of jumps is discarded, cos not in use] and the 3 partials have respectively 2, 3 and 2 frames
- *
- * 	This must be fixed
-*/
-
-// TODO: fix hop-frame name consistency
-
-
-#include <stdlib.h>
-
-#include "OscillatorBank.h"
-
-OscillatorBank::OscillatorBank() {
-	loaded = false;
-}
-
-OscillatorBank::OscillatorBank(string filename, int hopsize, int samplerate) {
-	loaded = false;
-	loadFile(filename.c_str(), hopsize, samplerate);
-}
-
-OscillatorBank::OscillatorBank(char *filename, int hopsize, int samplerate) {
-	loaded = false;
-	loadFile(filename, hopsize, samplerate);
-}
-
-OscillatorBank::~OscillatorBank() {
-	free(oscillatorPhases);
-	free(oscillatorNextNormFreq);
-	free(oscillatorNextAmp);
-	free(oscillatorNormFrequencies);
-	free(oscillatorAmplitudes);
-	free(oscillatorNormFreqDerivatives);
-	free(oscillatorAmplitudeDerivatives);
-	free(phaseCopies);
-	free(nextNormFreqCopies);
-	free(nextAmpCopies);
-
-	delete[] oscStatNormFrequenciesMean;
-	delete[] oscStatNumHops;
-	delete[] lookupTable;
-	delete[] indicesMapping;
-	delete[] freqFixedDeltas;
-	delete[] ampFixedDeltas;
-	delete[] nyquistCut;
-}
-
-bool OscillatorBank::initBank(int oversamp) {
-	if (!loaded)
-		return false;
-
-	//---prepare look-up table
-	lookupTableSize = 1024;
-	lookupTable		= new float[lookupTableSize + 1];
-	for (int n = 0; n < (lookupTableSize + 1); n++)
-		lookupTable[n] = sin(2.0 * M_PI * (float) n / (float) lookupTableSize);
-	frequencyScaler = (float) lookupTableSize / rate;
-	nyqNorm			= rate / 2 * frequencyScaler;
-
-	if (oversamp < 1)
-		oversamp = 1;
-
-	//---prepare oscillators
-	partials = &(parser.partials); // pointer to paser's partials
-	partialsHopSize = parser.getHopSize();
-	lastHop = partials->getHopNum(); // last bank hop is equal to last partial frame, which is equal to partial hop num
-	overSampling = oversamp;
-	hopSize = partialsHopSize / overSampling; // if oversampling, osc bank hop num > partials hop num
-	hopSizeReminder = partialsHopSize % overSampling;
-	oscBankHopSize = hopSize;
-	numOfPartials = partials->getPartialNum();
-	numOfOscillators = partials->getMaxActivePartialNum(); // get the maximum number of active partials at the same time
-
-	// set to next multiple of 4 [NEON]
-	numOfOscillators = (numOfOscillators + 3) & ~0x3; // to be sure we can add up to 3 fake oscillators
-
-	int err;
-	//---allocate buffers
-	// alligned buffers [NEON]
-	err = posix_memalign((void**) &oscillatorPhases, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &oscillatorNextNormFreq, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &oscillatorNextAmp, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &oscillatorNormFrequencies, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &oscillatorAmplitudes, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &oscillatorNormFreqDerivatives, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &oscillatorAmplitudeDerivatives, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &phaseCopies, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &nextNormFreqCopies, 16,
-			numOfOscillators * sizeof(float));
-	err += posix_memalign((void**) &nextAmpCopies, 16,
-			numOfOscillators * sizeof(float));
-
-	// regular ones
-	oscStatNormFrequenciesMean	= new float[numOfPartials];
-	oscStatNumHops				= new float[numOfPartials];
-	indicesMapping				= new int[numOfPartials];
-	freqFixedDeltas				= new float[numOfPartials];
-	ampFixedDeltas				= new float[numOfPartials];
-	nyquistCut 					= new bool[numOfPartials];
-
-	if (err > 0) {
-		dbox_printf("Failed memory allocations %@#!\n");
-		return false;
-	}
-
-	// copy stats [they do not change]
-	for (int n = 0; n < numOfPartials; n++) {
-		oscStatNormFrequenciesMean[n] = partials->partialFreqMean[n]
-				* frequencyScaler;
-		oscStatNumHops[n] = partials->partialNumFrames[n]; // in Parser and Partials "frames" are what we call here "hops" [see comment at top of file]
-	}
-
-	// deafult values
-	actPartNum		= 0;
-	loopStartHop	= 0;
-	loopEndHop		= (parser.partials.getHopNum() - 2) * overSampling;
-	ampTh			= 0.0001;
-	hopNumTh		= 0;
-	pitchMultiplier = 1;
-	freqMovement	= 1;
-	filterNum		= 0;
-	note			= false;
-	speed			= 1;
-	nextSpeed		= -1;
-	maxSpeed 		= 10;
-	minSpeed 		= 0.1;
-	jumpHop 		= -1;
-
-	// filter
-	filterMaxF		= 22000;
-	filterAmpMinF	= 10 * frequencyScaler;
-	filterAmpMaxF	= 5000 * frequencyScaler;
-	filterAmpMul	= 10.0;
-
-	// adsr
-	minAttackTime	= .0001;
-	deltaAttackTime = 2.;
-	minReleaseTime	= 1;
-	deltaReleaseTime = 2.5;
-
-	adsr.setAttackRate(minAttackTime * rate);
-	adsr.setDecayRate(.0001 * rate);
-	adsr.setSustainLevel(1);
-	adsr.setReleaseRate(minReleaseTime * rate);
-
-	state = bank_stopped;
-	return true;
-}
-
-void OscillatorBank::resetOscillators() {
-	currentHop			= -1;
-	loopDir				= 1;
-	loopDirShift 		= 0;
-	fill(nyquistCut, nyquistCut + numOfPartials, false);
-	prevAdsrVal			= 0;
-	prevAmpTh			= ampTh;
-	prevHopNumTh		= hopNumTh;
-	prevPitchMultiplier = pitchMultiplier;
-	prevFreqMovement 	= freqMovement;
-	prevFilterNum = filterNum;
-	memcpy(prevFilterFreqs, filterFreqs, filterNum * sizeof(float));
-	memcpy(prevFilterQ, filterQ, filterNum * sizeof(float));
-
-	int activePNum		= partials->activePartialNum[0];
-	unsigned int *activeP = partials->activePartials[0];
-	for (int i = 0; i < activePNum; i++) {
-		freqFixedDeltas[activeP[i]] = partials->partialFreqDelta[activeP[i]][0]
-				/ overSampling;
-		ampFixedDeltas[activeP[i]]	= partials->partialAmpDelta[activeP[i]][0]
-				/ overSampling;
-	}
-	// attack!
-	adsr.gate(1);
-	note = true;
-
-	nextHop();
-
-	state = bank_playing;
-}
-
-void OscillatorBank::nextHop() {
-	hopSize = oscBankHopSize;
-
-	// copy phases, next freqs and next amps from previous frame
-	memcpy(phaseCopies, oscillatorPhases, actPartNum * sizeof(float));
-	memcpy(nextNormFreqCopies, oscillatorNextNormFreq,
-			actPartNum * sizeof(float));
-	memcpy(nextAmpCopies, oscillatorNextAmp, actPartNum * sizeof(float));
-
-	// next frame is forward or backwards, cos we could be in the loop
-	currentHop += loopDir;
-
-	checkDirection();
-
-//	if((currentHop/overSampling)%100 == 0)
-//		dbox_printf("currentHop %d, direction: %d\n", currentHop/overSampling, loopDir);
-
-	// if needs jump, end here this method, cos jumpToHop() will do tee rest
-	if (checkJump() == 0)
-		return;
-	// otherwise, if jump is not needed or fails, continue regular stuff
-
-	if (nextEnvState() != 0)
-		return; // release has ended!
-
-	checkSpeed();
-
-	// now let's decide how to calculate next hop
-	if (!checkOversampling())
-		nextOscBankHop();
-	else
-		nextPartialHop();
-}
-
-void OscillatorBank::nextOscBankHop() {
-	int parIndex, localHop;
-	float parDamp = 1;
-	int currentPartialHop = (currentHop / overSampling) + loopDirShift;
-
-	// if going backwards in the loop, get previous frame active partials...
-	actPartNum = partials->activePartialNum[currentPartialHop - loopDirShift];
-	actPart = partials->activePartials[currentPartialHop - loopDirShift];
-	//cout << "actPartNum: " << actPartNum << endl;
-
-	envState = adsr.getState(); // to determine what state we will be in next hop [attack, decay, sustain, release]
-
-	int parCnt = 0;
-	int currentHopReminder = currentHop % overSampling;
-	// steps to reach next bank hop from previous partial hop
-	int steps = currentHopReminder + 1;
-	if (loopDir < 0)
-		steps = overSampling - currentHopReminder + 1;
-
-	for (int i = 0; i < actPartNum; i++) {
-		// find partial and frame
-		parIndex = actPart[i];
-		//localHop	= partials->localPartialFrames[currentPartialHop][parIndex];
-		localHop = currentPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
-
-		//float delta = partials->partialFrequencies[parIndex][localHop+loopDir] - partials->partialFrequencies[parIndex][localHop];
-
-		// if this partial was over nyquist on previous hop...
-		if (nyquistCut[parIndex]) {
-			// ...restart from safe values
-			oscillatorPhases[parCnt] = 0;
-			//TODO add freqmove dependency
-			oscillatorNextNormFreq[parCnt] =
-					(partials->partialFrequencies[parIndex][localHop]
-							+ freqFixedDeltas[parIndex] * (steps - 1))
-							* frequencyScaler * prevPitchMultiplier;
-			oscillatorNextAmp[parCnt] = 0;
-		} else if (loopDir == 1) // otherwise recover phase, target freq and target amp from previous frame
-				{
-			if ((localHop != 0) || (currentHopReminder != 0)) {
-				oscillatorPhases[parCnt] =
-						phaseCopies[indicesMapping[parIndex]];
-				oscillatorNextNormFreq[parCnt] =
-						nextNormFreqCopies[indicesMapping[parIndex]];
-				oscillatorNextAmp[parCnt] =
-						nextAmpCopies[indicesMapping[parIndex]];
-			} else // first oscillator hop [both for bank and partial], so no previous data are available
-			{
-				oscillatorPhases[parCnt] = 0;
-				//TODO add freqmove dependency
-				oscillatorNextNormFreq[parCnt] =
-						partials->partialFrequencies[parIndex][localHop]
-								* frequencyScaler * prevPitchMultiplier;
-				parDamp = calculateParDamping(parIndex, prevHopNumTh,
-						prevAdsrVal, oscillatorNextNormFreq[parCnt],
-						prevFilterNum, prevFilterFreqs, prevFilterQ);
-				oscillatorNextAmp[parCnt] =
-						partials->partialAmplitudes[parIndex][localHop]
-								* parDamp;
-				if(oscillatorNextAmp[parCnt] > 1)
-						oscillatorNextAmp[parCnt] = 1;
-				freqFixedDeltas[parIndex] =
-						partials->partialFreqDelta[parIndex][localHop + loopDir]
-								* loopDir / overSampling;
-				ampFixedDeltas[parIndex] =
-						partials->partialAmpDelta[parIndex][localHop + loopDir]
-								* loopDir / overSampling;
-			}
-		} else {
-			oscillatorPhases[parCnt] = phaseCopies[indicesMapping[parIndex]];
-			oscillatorNextNormFreq[parCnt] =
-					nextNormFreqCopies[indicesMapping[parIndex]];
-			oscillatorNextAmp[parCnt] = nextAmpCopies[indicesMapping[parIndex]];
-		}
-
-		// remove aliasing, skipping partial over nyquist freq
-		if (oscillatorNextNormFreq[parCnt] > nyqNorm) {
-			nyquistCut[parIndex] = true;
-			continue;
-		}
-		nyquistCut[parIndex] = false;
-
-		// first set up freq, cos filter affects amplitude damping according to freq content
-		oscillatorNormFrequencies[parCnt] = oscillatorNextNormFreq[parCnt]; // to fix any possible drifts
-		// save next values, current for next round
-		oscillatorNextNormFreq[parCnt] = (freqMovement
-				* (partials->partialFrequencies[parIndex][localHop]
-						+ freqFixedDeltas[parIndex] * steps) * frequencyScaler
-				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
-				* pitchMultiplier;
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
-				- oscillatorNormFrequencies[parCnt]) / hopCounter;
-		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
-		oscillatorNormFreqDerivatives[parCnt] = freqMovement
-				* oscillatorNormFreqDerivatives[parCnt]
-				+ (1 - freqMovement)
-						* ((oscStatNormFrequenciesMean[parIndex]
-								* pitchMultiplier)
-								- oscillatorNormFrequencies[parCnt])
-						/ hopCounter;
-
-		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
-				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
-
-		// now amplitudes
-		oscillatorAmplitudes[parCnt] = oscillatorNextAmp[parCnt]; // to fix any possible drifts
-		// save next values, current for next round
-		//delta = partials->partialAmplitudes[parIndex][localHop+loopDir] - partials->partialAmplitudes[parIndex][localHop];
-		oscillatorNextAmp[parCnt] =
-				(partials->partialAmplitudes[parIndex][localHop]
-						+ ampFixedDeltas[parIndex] * steps) * parDamp;
-		if(oscillatorNextAmp[parCnt] > 1)
-				oscillatorNextAmp[parCnt] = 1;
-		if ((loopDir == -1) && (localHop = 1) && (currentHopReminder == 1))
-			oscillatorNextAmp[parCnt] = 0;
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
-				- oscillatorAmplitudes[parCnt]) / hopCounter;
-
-		// finally update current mapping between oscillators and partials
-		indicesMapping[parIndex] = parCnt;
-		parCnt++;
-	}
-	actPartNum = parCnt;
-	// [NEON] if not multiple of 4...
-	if (actPartNum % 4 != 0)
-		addFakeOsc();
-}
-
-void OscillatorBank::nextPartialHop() {
-	unsigned int parIndex, localHop;
-	float parDamp = 1;
-	int currentPartialHop = currentHop / overSampling;
-
-	// if going backwards in the loop, get previous frame active partials...
-	actPartNum = partials->activePartialNum[currentPartialHop - loopDirShift];
-	actPart    = partials->activePartials[currentPartialHop - loopDirShift];
-
-	envState = adsr.getState(); // to determine what state we will be in next hop [attack, decay, sustain, release]
-
-	int parCnt = 0;
-	int steps = overSampling - 1; // steps to reach next hop [partial or bank] from previous partial hop
-
-	for (int i = 0; i < actPartNum; i++) {
-		// find partial and frame
-		parIndex = actPart[i];
-		//localHop	= partials->localPartialFrames[currentPartialHop][parIndex];
-		localHop = currentPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
-
-		// if this partial was over nyquist on previous hop...
-		if (nyquistCut[parIndex]) {
-			// ...restart from safe values
-			oscillatorPhases[parCnt] = 0;
-			//TODO add freqmove dependency
-			oscillatorNextNormFreq[parCnt] =
-					(partials->partialFrequencies[parIndex][localHop]
-							+ freqFixedDeltas[parIndex] * steps
-									* (1 - loopDirShift)) * frequencyScaler
-							* prevPitchMultiplier;
-			oscillatorNextAmp[parCnt] = 0;
-		} else if (loopDir == 1) // otherwise recover phase, target freq and target amp from previous frame
-		{
-			if ((localHop != 0) || (overSampling > 1)) {
-				oscillatorPhases[parCnt] =
-						phaseCopies[indicesMapping[parIndex]];
-				oscillatorNextNormFreq[parCnt] =
-						nextNormFreqCopies[indicesMapping[parIndex]];
-				oscillatorNextAmp[parCnt] =
-						nextAmpCopies[indicesMapping[parIndex]];
-			} else // first oscillator hop [both for bank and partial], so no previous data are available
-			{
-				oscillatorPhases[parCnt] = 0;
-				//TODO add freqmove dependency
-				oscillatorNextNormFreq[parCnt] =
-						partials->partialFrequencies[parIndex][localHop]
-								* frequencyScaler * prevPitchMultiplier;
-				parDamp = calculateParDamping(parIndex, prevHopNumTh,
-						prevAdsrVal, oscillatorNextNormFreq[parCnt],
-						prevFilterNum, prevFilterFreqs, prevFilterQ);
-				oscillatorNextAmp[parCnt] =
-						partials->partialAmplitudes[parIndex][localHop]
-								* parDamp;
-				if(oscillatorNextAmp[parCnt] > 1)
-						oscillatorNextAmp[parCnt] = 1;
-				freqFixedDeltas[parIndex] =
-						partials->partialFreqDelta[parIndex][localHop + loopDir]
-								* loopDir / overSampling;
-				ampFixedDeltas[parIndex] =
-						partials->partialAmpDelta[parIndex][localHop + loopDir]
-								* loopDir / overSampling;
-			}
-		} else {
-			if (localHop != partials->partialNumFrames[parIndex] - 1) {
-				oscillatorPhases[parCnt] =
-						phaseCopies[indicesMapping[parIndex]];
-				oscillatorNextNormFreq[parCnt] =
-						nextNormFreqCopies[indicesMapping[parIndex]];
-				oscillatorNextAmp[parCnt] =
-						nextAmpCopies[indicesMapping[parIndex]];
-			} else // first oscillator hop [going backwards - both for bank and partial] , so no previous data are available
-			{
-				oscillatorPhases[parCnt] = 0;
-				//TODO add freqmove dependency
-				oscillatorNextNormFreq[parCnt] =
-						partials->partialFrequencies[parIndex][localHop]
-								* frequencyScaler * prevPitchMultiplier;
-				parDamp = calculateParDamping(parIndex, prevHopNumTh,
-						prevAdsrVal, oscillatorNextNormFreq[parCnt],
-						prevFilterNum, prevFilterFreqs, prevFilterQ);
-				oscillatorNextAmp[parCnt] =
-						partials->partialAmplitudes[parIndex][localHop]
-								* parDamp;
-				if(oscillatorNextAmp[parCnt] > 1)
-						oscillatorNextAmp[parCnt] = 1;
-				freqFixedDeltas[parIndex] =
-						partials->partialFreqDelta[parIndex][localHop + loopDir]
-								* loopDir / overSampling;
-				ampFixedDeltas[parIndex] =
-						partials->partialAmpDelta[parIndex][localHop + loopDir]
-								* loopDir / overSampling;
-			}
-		}
-		// remove aliasing, skipping partial over nyquist freq
-		if (oscillatorNextNormFreq[parCnt] > nyqNorm) {
-			//cout << nyqNorm << endl;
-			nyquistCut[parIndex] = true;
-			continue;
-		}
-		nyquistCut[parIndex] = false;
-
-		// first set up freq, cos filter affects amplitude damping according to freq content
-		oscillatorNormFrequencies[parCnt] = oscillatorNextNormFreq[parCnt]; // to fix any possible drifts
-		// save next values, current for next round
-		oscillatorNextNormFreq[parCnt] = (freqMovement
-				* (partials->partialFrequencies[parIndex][localHop + loopDir]
-						- freqFixedDeltas[parIndex] * steps * loopDirShift)
-				* frequencyScaler
-				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
-				* pitchMultiplier;
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
-				- oscillatorNormFrequencies[parCnt]) / hopCounter;
-		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
-		oscillatorNormFreqDerivatives[parCnt] = freqMovement
-				* oscillatorNormFreqDerivatives[parCnt]
-				+ (1 - freqMovement)
-						* ((oscStatNormFrequenciesMean[parIndex]
-								* pitchMultiplier)
-								- oscillatorNormFrequencies[parCnt])
-						/ hopCounter;
-
-		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
-				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
-
-		// now amplitudes
-		oscillatorAmplitudes[parCnt] = oscillatorNextAmp[parCnt]; // to fix any possible drifts
-		// save next values, current for next round
-		//delta = partials->partialAmplitudes[parIndex][localHop+loopDir] - partials->partialAmplitudes[parIndex][localHop];
-		oscillatorNextAmp[parCnt] =
-				(partials->partialAmplitudes[parIndex][localHop + loopDir]
-						- (ampFixedDeltas[parIndex]) * steps * loopDirShift)
-						* parDamp;
-		if(oscillatorNextAmp[parCnt] > 1)
-			oscillatorNextAmp[parCnt] = 1;
-
-		// to avoid bursts when transients are played backwards
-		if ((loopDir == -1) && (localHop - 1 == 0) && (overSampling == 1)) {
-			oscillatorNextAmp[parCnt] = 0;
-		}
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
-				- oscillatorAmplitudes[parCnt]) / hopCounter;
-
-		// if next is not going to loop boundaries, get next deltas [same direction]
-		if ((((currentPartialHop + loopDir) * overSampling != loopEndHop)
-				|| (loopDir == -1))
-				&& (((currentPartialHop + loopDir) * overSampling + loopDir
-						!= loopStartHop) || (loopDir == 1))) {
-			freqFixedDeltas[parIndex] =
-					partials->partialFreqDelta[parIndex][localHop + loopDir]
-							* loopDir / overSampling;
-			ampFixedDeltas[parIndex] =
-					partials->partialAmpDelta[parIndex][localHop + loopDir]
-							* loopDir / overSampling;
-		} else // .. otherwise, keep deltas but change sign [co swe change direction]
-		{
-			freqFixedDeltas[parIndex] = -freqFixedDeltas[parIndex];
-			ampFixedDeltas[parIndex] = -ampFixedDeltas[parIndex];
-		}
-
-		// finally update current mapping between oscillators and partials
-		indicesMapping[parIndex] = parCnt;
-		parCnt++;
-	}
-	actPartNum = parCnt;
-	// [NEON] if not multiple of 4...
-	if (actPartNum % 4 != 0)
-		addFakeOsc();
-
-	updatePrevControls();
-}
-
-void OscillatorBank::addFakeOsc() {
-	// ...calculate difference
-	int newPartNum = (actPartNum + 3) & ~0x3;
-	// ...add fake oscillators until total num is multiple of 4
-	for (int i = actPartNum; i < newPartNum; i++) {
-		oscillatorAmplitudes[i] = 0;
-		oscillatorNormFrequencies[i] = 0;
-		oscillatorAmplitudeDerivatives[i] = 0;
-		oscillatorNormFreqDerivatives[i] = 0;
-		oscillatorPhases[i] = 0;
-	}
-	// ...and update num of active partials
-	actPartNum = newPartNum;
-}
-
-void OscillatorBank::play(float vel) {
-	// set attack and release params according to velocity
-	//adsr.setAttackRate((minAttackTime + ((1 - vel) * deltaAttackTime)) * rate);
-	adsr.setAttackRate(minAttackTime * rate);
-	//adsr.setReleaseRate((minReleaseTime + (1 - vel) * deltaReleaseTime) * rate);
-	adsr.setReleaseRate(minReleaseTime * rate);
-
-	// set timbre
-	hopNumTh = log((1 - vel) + 1) / log(2) * 20000;
-
-	state = bank_toreset;
-}
-
-//---------------------------------------------------------------------------------------------------------------------------
-// private methods
-//---------------------------------------------------------------------------------------------------------------------------
-
-bool OscillatorBank::loader(char *filename, int hopsize, int samplerate) {
-	rate = samplerate;
-	loaded = parser.parseFile(filename, hopsize, samplerate);
-	return loaded;
-}
-
-int OscillatorBank::jumpToHop() {
-	int jumpGap = abs(jumpHop - currentHop / overSampling); // gaps in partial reference
-
-	// can't jump to self dude
-	if (jumpGap == 0)
-		return 1;
-
-	// direction is in general maintained with jump
-	if (jumpHop == 0)
-		setDirection(1);
-	else if (jumpHop == lastHop)
-		setDirection(-1);
-
-	dbox_printf("\tJump from %d to %d\n", currentHop / overSampling, jumpHop);
-	dbox_printf("\tdirection %d\n", loopDir);
-
-	currentHop = jumpHop * overSampling;
-
-	if (nextEnvState() != 0)
-		return 0; // release has ended!
-
-	checkSpeed();
-
-	int parIndex, localHop, targetHop;
-	float parDamp = 1;
-	int currentPartialHop = currentHop / overSampling;
-	int targetPartialHop = jumpHop;
-
-	actPartNum = partials->activePartialNum[currentPartialHop];
-	actPart = partials->activePartials[currentPartialHop];
-	int targetActParNum = partials->activePartialNum[targetPartialHop];
-	unsigned int *targetActPar = partials->activePartials[targetPartialHop];
-
-	envState = adsr.getState(); // to determine what state we will be in next hop [attack, decay, sustain, release]
-
-	int parCnt = 0;
-	int currentHopReminder = currentHop % overSampling;
-
-	// steps to walk where i am [bank of partial hop] from previous partial hop
-	int steps = currentHopReminder * (overSampling != 1); // no oversampling 0, oversampling and going ff currentHopReminder
-
-	for (int i = 0; i < actPartNum; i++) {
-		// find partial and frame
-		parIndex = actPart[i];
-		//localHop	= partials->localPartialFrames[currentPartialHop][parIndex];
-		localHop = currentPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
-
-		// if this partial was over nyquist on previous hop...
-		if (nyquistCut[parIndex]) {
-			// ...restart from safe values
-			oscillatorPhases[parCnt] = 0;
-			//TODO add freqmove dependency
-			oscillatorNextNormFreq[parCnt] =
-					(partials->partialFrequencies[parIndex][localHop]
-							+ freqFixedDeltas[parIndex] * steps * loopDir)
-							* frequencyScaler * prevPitchMultiplier;
-			oscillatorNextAmp[parCnt] = 0;
-		} else if (loopDir == 1) {// otherwise recover phase, target freq and target amp from previous frame
-			if ((localHop != 0)
-					|| ((overSampling > 1) && (currentHopReminder != 0))) {
-				oscillatorPhases[parCnt] =
-						phaseCopies[indicesMapping[parIndex]];
-				oscillatorNextNormFreq[parCnt] =
-						nextNormFreqCopies[indicesMapping[parIndex]];
-				oscillatorNextAmp[parCnt] =
-						nextAmpCopies[indicesMapping[parIndex]];
-			} else { // first oscillator hop [both for bank and partial], so no previous data are available
-				oscillatorPhases[parCnt] = 0;
-				//TODO add freqmove dependency
-				oscillatorNextNormFreq[parCnt] =
-						partials->partialFrequencies[parIndex][localHop]
-								* frequencyScaler * prevPitchMultiplier;
-				parDamp = calculateParDamping(parIndex, prevHopNumTh,
-						prevAdsrVal, oscillatorNextNormFreq[parCnt],
-						prevFilterNum, prevFilterFreqs, prevFilterQ);
-				oscillatorNextAmp[parCnt] =
-						partials->partialAmplitudes[parIndex][localHop]
-								* parDamp;
-				if(oscillatorNextAmp[parCnt] > 1)
-						oscillatorNextAmp[parCnt] = 1;
-			}
-		} else {
-			if (( (unsigned)localHop != partials->partialNumFrames[parIndex] - 1)
-					|| ((overSampling > 1) && (currentHopReminder != 0))) {
-				oscillatorPhases[parCnt] =
-						phaseCopies[indicesMapping[parIndex]];
-				oscillatorNextNormFreq[parCnt] =
-						nextNormFreqCopies[indicesMapping[parIndex]];
-				oscillatorNextAmp[parCnt] =
-						nextAmpCopies[indicesMapping[parIndex]];
-			} else // first oscillator hop [going backwards - both for bank and partial] , so no previous data are available, so retrieve where i am
-			{
-				oscillatorPhases[parCnt] = 0;
-				//TODO add freqmove dependency
-				oscillatorNextNormFreq[parCnt] =
-						partials->partialFrequencies[parIndex][localHop]
-								* frequencyScaler * prevPitchMultiplier;
-				parDamp = calculateParDamping(parIndex, prevHopNumTh,
-						prevAdsrVal, oscillatorNextNormFreq[parCnt],
-						prevFilterNum, prevFilterFreqs, prevFilterQ);
-				oscillatorNextAmp[parCnt] =
-						partials->partialAmplitudes[parIndex][localHop]
-								* parDamp;
-				if(oscillatorNextAmp[parCnt] > 1)
-						oscillatorNextAmp[parCnt] = 1;
-			}
-		}
-		// remove aliasing, skipping partial over nyquist freq
-		if (oscillatorNextNormFreq[parCnt] > nyqNorm) {
-			//cout << nyqNorm << endl;
-			nyquistCut[parIndex] = true;
-			continue;
-		}
-		nyquistCut[parIndex] = false;
-
-		// check what happens of this partial at target hop
-		float targetFreqVal, targetAmpVal;
-		//targetHop = partials->localPartialFrames[targetPartialHop][parIndex];
-		targetHop = targetPartialHop - partials->partialStartFrame[parIndex];
-
-		if (targetHop == -1)
-			targetFreqVal = targetAmpVal = 0;
-		else {
-			targetFreqVal = partials->partialFrequencies[parIndex][targetHop]
-					* frequencyScaler; // pitch shift will be multiplied later!!!
-			targetAmpVal = partials->partialFrequencies[parIndex][targetHop]; // parDamp will be multiplied later!!!
-		}
-
-		// first set up freq, cos filter affects amplitude damping according to freq content
-		oscillatorNormFrequencies[parCnt] = oscillatorNextNormFreq[parCnt]; // to fix any possible drifts
-		// save next values, current for next round
-		oscillatorNextNormFreq[parCnt] = (freqMovement * targetFreqVal
-				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
-				* pitchMultiplier;
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
-				- oscillatorNormFrequencies[parCnt]) / hopCounter;
-		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
-		oscillatorNormFreqDerivatives[parCnt] = freqMovement
-				* oscillatorNormFreqDerivatives[parCnt]
-				+ (1 - freqMovement)
-						* ((oscStatNormFrequenciesMean[parIndex]
-								* pitchMultiplier)
-								- oscillatorNormFrequencies[parCnt])
-						/ hopCounter;
-
-		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
-				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
-
-		// now amplitudes
-		oscillatorAmplitudes[parCnt] = oscillatorNextAmp[parCnt]; // to fix any possible drifts
-		// save next values, current for next round
-		oscillatorNextAmp[parCnt] = targetAmpVal * parDamp;
-		if(oscillatorNextAmp[parCnt] > 1)
-				oscillatorNextAmp[parCnt] = 1;
-		// to avoid bursts when transients are played backwards
-		if ((loopDir == -1) && (targetHop == 0)
-				&& ((overSampling == 1) || (currentHopReminder == 0))) {
-			oscillatorNextAmp[parCnt] = 0;
-		}
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
-				- oscillatorAmplitudes[parCnt]) / hopCounter;
-
-		//if partial does not die at target, calculate deltas according to direction
-		if (targetHop != -1) {
-			freqFixedDeltas[parIndex] =
-					partials->partialFreqDelta[parIndex][targetHop] * loopDir
-							/ overSampling;
-			ampFixedDeltas[parIndex] =
-					partials->partialAmpDelta[parIndex][targetHop] * loopDir
-							/ overSampling;
-		}
-
-		// finally update current mapping between oscillators and partials
-		indicesMapping[parIndex] = parCnt;
-		parCnt++;
-	}
-	actPartNum = parCnt;
-
-	// now add the ones that start at target hop!
-	for (int i = 0; i < targetActParNum; i++) {
-		// find partial and frame
-		parIndex = targetActPar[i];
-		//targetHop	= partials->localPartialFrames[targetPartialHop][parIndex];
-		targetHop = targetPartialHop - partials->partialStartFrame[parIndex]; // in Parser and Partials "frames" are what we call here "hops". These particular ones are local frames [see comment at top of file]
-
-		// check if this partials was already active before the jump
-		//localHop = partials->localPartialFrames[currentPartialHop][parIndex];
-		localHop = currentPartialHop - partials->partialStartFrame[parIndex];
-
-		// if yes, skip it
-		if (localHop != -1)
-			continue;
-
-		// otherwise add it to active bunch and calcucalte values
-
-		// first set up freq, cos filter affects amplitude damping according to freq content
-		oscillatorNormFrequencies[parCnt] = 0;
-		// save next values, current for next round
-		oscillatorNextNormFreq[parCnt] = (freqMovement
-				* partials->partialFrequencies[parIndex][targetHop]
-				* frequencyScaler
-				+ (1 - freqMovement) * oscStatNormFrequenciesMean[parIndex])
-				* pitchMultiplier;
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorNormFreqDerivatives[parCnt] = (oscillatorNextNormFreq[parCnt]
-				- oscillatorNormFrequencies[parCnt]) / hopCounter;
-		// this second weird passage handles dissonance control, morphing between regular and mean frequencies
-		oscillatorNormFreqDerivatives[parCnt] = freqMovement
-				* oscillatorNormFreqDerivatives[parCnt]
-				+ (1 - freqMovement)
-						* ((oscStatNormFrequenciesMean[parIndex]
-								* pitchMultiplier)
-								- oscillatorNormFrequencies[parCnt])
-						/ hopCounter;
-
-		parDamp = calculateParDamping(parIndex, hopNumTh, adsrVal,
-				oscillatorNextNormFreq[parCnt], filterNum, filterFreqs, filterQ);
-
-		// now amplitudes
-		oscillatorAmplitudes[parCnt] = 0;
-		// save next values, current for next round
-		oscillatorNextAmp[parCnt] =
-				partials->partialFrequencies[parIndex][targetHop] * parDamp;
-		if(oscillatorNextAmp[parCnt] > 1)
-				oscillatorNextAmp[parCnt] = 1;
-		// derivatives are (next hop value*next damping) - (current hop value*current damping)  ---> next hop must be available, in both directions, because of control on active partials
-		oscillatorAmplitudeDerivatives[parCnt] = (oscillatorNextAmp[parCnt]
-				- oscillatorAmplitudes[parCnt]) / hopCounter;
-
-		//calculate deltas according to direction
-		freqFixedDeltas[parIndex] =
-				partials->partialFreqDelta[parIndex][targetHop] * loopDir
-						/ overSampling;
-		ampFixedDeltas[parIndex] =
-				partials->partialAmpDelta[parIndex][targetHop] * loopDir
-						/ overSampling;
-
-		// finally update current mapping between oscillators and partials
-		indicesMapping[parIndex] = parCnt;
-		parCnt++;
-
-	}
-	// [NEON] if not multiple of 4...
-	if (actPartNum % 4 != 0)
-		addFakeOsc();
-
-	updatePrevControls();
-
-	jumpHop = -1;
-
-	return 0;
-}
-
-int OscillatorBank::nextEnvState() {
-	/*
-	 envState = Attack.getState();	// to determine what state we are in [attack, decay, sustain, release]
-
-	 // osc bank is playing the tail and the tail ends...
-	 if( (state == bank_playing)&&(envState == env_idle) )
-	 {
-	 state = bank_stopped;	// ...stop bank
-	 return 1;					// and return immediately
-	 }
-	 else if( (envState == env_attack) || (envState == env_decay) )
-	 {
-	 // run envelopes until next frame
-	 dampWeight	= Attack.process(hopSize);
-	 }
-	 else if(envState == env_release)
-	 {
-	 // run envelopes until next frame
-	 dampWeight 	= Attack.process(hopSize);
-	 releaseDamp = Release.process(hopSize);
-	 }*/
-
-	envState = adsr.getState();
-	// osc bank is playing the tail and the tail ends...
-	if ((state == bank_playing) && (envState == env_idle)) {
-		state = bank_stopped; // ...stop bank
-		adsrVal = 0;
-		return 1; // and return immediately
-	} else
-		adsrVal = adsr.process(hopSize);
-
-	return 0;
-}
-
-void OscillatorBank::checkDirection() {
-	// end of the loop or end of file
-	if (((currentHop >= loopEndHop) && (loopDir == 1))
-			|| ((currentHop >= lastHop) && (loopDir == 1))) {
-		// move backwards
-		setDirection(-1);
-		//dbox_printf("backward from %d\n", loopEndHop);
-	} else if (((currentHop <= loopStartHop) && (loopDir == -1))
-			|| ((currentHop <= 0) && (loopDir == -1))) // start of the loop or start of file
-			{
-		// move forward
-		setDirection(1);
-		//dbox_printf("forward from %d\n", loopStartHop);
-	}
-}
-
-void OscillatorBank::checkSpeed() {
-	// speed control [alike on highways, LOL]
-	if (nextSpeed > 0) {
-		nextSpeed = (nextSpeed < maxSpeed) ? nextSpeed : maxSpeed;
-		nextSpeed = (nextSpeed > minSpeed) ? nextSpeed : minSpeed;
-		speed = nextSpeed;
-		nextSpeed = -1;
-	}
-	hopCounter = hopSize / speed;
-}
-
-int OscillatorBank::checkJump() {
-	//check if has to jump somewhere
-	if (jumpHop > -1) {
-		// needs to jump!
-		if (jumpToHop() == 0)
-			return 0;
-	}
-	return 1; // no jump
-}
-
-bool OscillatorBank::checkOversampling() {
-	//TODO fix this, but need andrew to fix oversampling multiple of period size
-	// if partialsHopSize is not a multiple of oversampling, change hop size to periodically match next partial hop
-	if (hopSizeReminder > 0) {
-		// if next osc bank hop overtakes next partial hop...
-		if ((currentHop + loopDir) * hopSize > partialsHopSize) {
-			hopSize = hopSizeReminder; // ...shrink osc bank hop size to match partial hop
-			return true; // and set next hop as matching with next partial hop
-		}
-	} else if (((currentHop + (1 - loopDirShift)) % overSampling) == 0) // if next osc bank hop matches next partial hop
-		return true; // ...mark next hop as partial hop
-
-	return false; // ,otherwise mark next hop as osc bank hop
-}
-
-void OscillatorBank::updatePrevControls() {
-	prevAdsrVal = adsrVal;
-	prevAmpTh = ampTh;
-	prevHopNumTh = hopNumTh;
-	prevPitchMultiplier = pitchMultiplier;
-	prevFreqMovement = freqMovement;
-	prevFilterNum = filterNum;
-	memcpy(prevFilterFreqs, filterFreqs, filterNum * sizeof(float));
-	memcpy(prevFilterQ, filterQ, filterNum * sizeof(float));
-}
-
-float OscillatorBank::calculateParDamping(int parIndex, int hopNTh,
-		float adsrVl, float nextFreq, int filNum, float *filFreq, float *filQ) {
-	float parDamp = 1;
-
-	// timbre
-	parDamp = ((float) (oscStatNumHops[parIndex] + 1)) / (hopNTh + 1);
-	parDamp = (parDamp > 1) ? 1 : parDamp;
-	parDamp = adsrVl * parDamp;
-
-	//filters
-
-	float filterWeights[MAX_TOUCHES];
-	float filterDamp[MAX_TOUCHES];
-	float filDist;
-	float filterWeightsAcc;
-	float filDmp;
-	float filAmp;
-
-// 		band reject notch filter
-//		float dist, dmp;
-//		for(int k=0; k<filterNum; k++)
-//		{
-//			dist = fabs(oscillatorNextNormFreq[parCnt]-filterFreqs[k]);
-//			if(dist<=filterQ[k])
-//			{
-//				dmp 	= dist/filterQ[k];
-//				parDamp *= dmp*dmp*dmp;
-//			}
-//		}
-
-
-	// each filter is a band pass notch filter
-
-	// if at least one is active
-	if (filNum > 0) {
-		// reset values
-		filDist = 0;
-		filterWeightsAcc = 0;
-		filDmp = 0;
-		filAmp = 0;
-		// for each filter
-		for (int k = 0; k < filNum; k++) {
-			// here are a couple of kludges to boost sound output of hi freq filters
-
-			// damping effect of filter increases with distance, but decreases with filter frequency [kludge]
-			float mul = ((filterMaxF-nextFreq)/filterMaxF) * 0.9 + 0.1 ;
-			//filDist = fabs(nextFreq - filFreq[k])*( ((exp(a*4)-1)/EXP_DENOM) * 0.9 + 0.1 );
-			filDist = fabs(nextFreq - filFreq[k])*mul;
-
-			// these to merge all filters contributions according to distance
-			filterWeights[k] = filterMaxF - filDist;
-			filterWeightsAcc += filterWeights[k];
-			// freqs very close to filter center are slightly amplified
-			// the size of this amp area and the effect of amplification increase with frequency [kludge]
-			if (filDist
-					< filterAmpMinF
-							+ (filterAmpMaxF*(1-mul) - filterAmpMinF) * (1 - filQ[k]) )
-				filAmp = filQ[k] * filterAmpMul*(1-mul);
-			else
-				filAmp = 0;
-			// actual damping
-			filDmp = 1 / (filDist * filQ[k]);
-			filDmp = (filDmp > 1) ? 1 : filDmp;
-			// sum damp+amplification
-			filterDamp[k] = filDmp + filAmp;
-		}
-		// do weighted mean to merge all filters contributions
-		filDmp = 0;
-		for (int k = 0; k < filNum; k++)
-			filDmp += filterDamp[k] * filterWeights[k];
-		filDmp /= filterWeightsAcc;
-		// apply
-		parDamp *= filDmp;
-	}
-
-
-	return parDamp;
-}
--- a/examples/d-box/OscillatorBank.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/*
- * OscillatorBank.h
- *
- *  Created on: May 23, 2014
- *      Author: Victor Zappi and Andrew McPherson
- */
-
-#ifndef OSCILLATORBANK_H_
-#define OSCILLATORBANK_H_
-
-
-#include <string>
-
-#include "spear_parser.h"
-#include "ADSR.h"
-#include "config.h"
-
-using namespace std;
-
-enum OscBankstates {bank_stopped, bank_playing, bank_toreset};
-
-class OscillatorBank
-{
-public:
-	OscillatorBank();
-	OscillatorBank(string filename, int hopsize=-1, int samplerate=44100);
-	OscillatorBank(char *filename, int hopsize=-1, int samplerate=44100);
-	~OscillatorBank();
-	float *oscillatorPhases;
-	float *oscillatorNormFrequencies;
-	float *oscillatorNormFreqDerivatives;
-	float *oscillatorAmplitudes;
-	float *oscillatorAmplitudeDerivatives;
-	float *oscStatNormFrequenciesMean;
-	float *oscStatNumHops;
-	OscBankstates state;
-	bool note;
-	int actPartNum;
-	unsigned int *actPart;
-	int hopCounter;
-	int lookupTableSize;
-	float *lookupTable;
-	float ampTh;
-	int hopNumTh;
-	float pitchMultiplier;
-	float freqMovement;
-	int filterNum;
-	float filterFreqs[5];
-	float filterQ[5];
-	float filterMaxF;
-	float filterAmpMinF;
-	float filterAmpMaxF;
-	float filterAmpMul;
-
-	bool loadFile(string filename, int hopsize=-1, int samplerate=44100);
-	bool loadFile(char *filename, int hopsize=-1, int samplerate=44100);
-	bool initBank(int oversamp=1);
-	void resetOscillators();
-	int getHopSize() { return hopSize; }
-	void nextHop();
-	void setLoopHops(int start, int end);
-	void play(float vel);
-	void stop();
-	void afterTouch(float vel);
-	int getEnvelopeState();
-	float getFrequencyScaler();
-	void setSpeed(float sp);
-	float getSpeed();
-	float getMaxSpeed();
-	float getMinSpeed();
-	void setJumpHop(int hop);
-	int getLastHop();
-	int getCurrentHop() { return currentHop; }
-
-private:
-
-	bool loaded;
-	int numOfPartials;
-	int numOfOscillators;
-	int partialsHopSize;
-	int overSampling;
-	int hopSize;
-	int hopSizeReminder;
-	int oscBankHopSize;
-	float frequencyScaler;
-	float nyqNorm;
-	int lastHop;
-	int currentHop;
-	int	loopDir;
-	int loopDirShift;
-	int loopStartHop;
-	int loopEndHop;
-	int *indicesMapping;
-	float *phaseCopies;
-	float *oscillatorNextNormFreq;
-	float *oscillatorNextAmp;
-	float *nextNormFreqCopies;
-	float *nextAmpCopies;
-	float *freqFixedDeltas;
-	float *ampFixedDeltas;
-	bool *nyquistCut;
-	Spear_parser parser;
-	Partials *partials;
-	ADSR adsr;
-	float minAttackTime;
-	float deltaAttackTime;
-	float minReleaseTime;
-	float deltaReleaseTime;
-	int envState;
-	int rate;
-	float speed;
-	float nextSpeed;
-	float maxSpeed;
-	float minSpeed;
-	int jumpHop;
-	float adsrVal;
-	float prevAdsrVal;
-	float prevAmpTh;
-	int prevHopNumTh;
-	float prevPitchMultiplier;
-	float prevFreqMovement;
-	int prevFilterNum;
-	float prevFilterFreqs[5];
-	float prevFilterQ[5];
-
-	bool loader(char *filename, int hopsize=-1, int samplerate=44100);
-	void addFakeOsc();
-	void nextOscBankHop();
-	void nextPartialHop();
-	int jumpToHop();
-	void setDirection(int dir);
-	int nextEnvState();
-	void checkDirection();
-	void checkSpeed();
-	int checkJump();
-	bool checkOversampling();
-	void updatePrevControls();
-	float calculateParDamping(int parIndex, int hopNTh, float adsrVl, float nextFreq,
-							  int filNum, float *filFreq, float *filQ);
-};
-
-inline bool OscillatorBank::loadFile(string filename, int hopsize, int samplerate)
-{
-	return loader((char *)filename.c_str(), hopsize, samplerate);
-}
-
-inline bool OscillatorBank::loadFile(char *filename, int hopsize, int samplerate)
-{
-	return loader(filename, hopsize, samplerate);
-}
-
-inline void OscillatorBank::setLoopHops(int start, int end)
-{
-	if(start > end)
-		end = start;
-
-	if(start<0)
-		start = 0;
-	else if(start>lastHop)
-		start = 0;
-	if(end < 1)
-		end = 1;
-	end = (end<=lastHop) ? end : lastHop;
-
-	// set it, take into consideration hop oversampling
-	loopStartHop = start*overSampling;
-	loopEndHop	 = end*overSampling;
-}
-
-inline void OscillatorBank::stop()
-{
-	note = false;
-	adsr.gate(0);
-}
-
-inline float OscillatorBank::getFrequencyScaler()
-{
-	return frequencyScaler;
-}
-
-inline void OscillatorBank::afterTouch(float vel)
-{
-	hopNumTh = log((1-vel)+1)/log(2)*20000;
-	if(adsr.getState()==env_attack)
-		adsr.setAttackRate( (minAttackTime + ( (1-vel)*deltaAttackTime )) * rate );
-	adsr.setReleaseRate( (minReleaseTime+(1-vel)*deltaReleaseTime)* rate );
-}
-
-inline int OscillatorBank::getEnvelopeState()
-{
-	return envState;
-}
-
-inline void OscillatorBank::setSpeed(float sp)
-{
-	nextSpeed = sp;
-}
-
-inline float OscillatorBank::getSpeed()
-{
-	return speed;
-}
-
-inline float OscillatorBank::getMaxSpeed()
-{
-	return maxSpeed;
-}
-
-inline float OscillatorBank::getMinSpeed()
-{
-	return minSpeed;
-}
-
-inline void OscillatorBank::setJumpHop(int hop)
-{
-	if(hop<0)
-		return;
-	hop = (hop<=lastHop) ? hop : lastHop;
-	jumpHop = hop;
-}
-
-inline void OscillatorBank::setDirection(int dir)
-{
-	if(dir>=0)
-	{
-		loopDir			= 1;
-		loopDirShift	= 0;
-	}
-	else
-	{
-		loopDir			= -1;
-		loopDirShift	= 1;
-	}
-}
-
-inline int OscillatorBank::getLastHop()
-{
-	return lastHop;
-}
-#endif /* OSCILLATORBANK_H_ */
--- a/examples/d-box/PinkNoise.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-/*
- * PinkNoise.cpp
- *
- *  Created on: Oct 15, 2013
- *      Author: Victor Zappi
- */
-
-#include "PinkNoise.h"
-
-// miserable definition to init static const array members...otherwise gets error when PinkNoise.h is included into another header file
-const float PinkNoise::A[] = { 0.02109238, 0.07113478, 0.68873558 }; // rescaled by (1+P)/(1-P)
-const float PinkNoise::P[] = { 0.3190,  0.7756,  0.9613  };
-
-
-
-
--- a/examples/d-box/PinkNoise.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-#ifndef _PinkNoise_H
-#define _PinkNoise_H
-
-// Technique by Larry "RidgeRat" Trammell 3/2006
-// http://home.earthlink.net/~ltrammell/tech/pinkalg.htm
-// implementation and optimization by David Lowenfels
-
-#include <cstdlib>
-#include <ctime>
-#include <stdlib.h>
-
-#define PINK_NOISE_NUM_STAGES 3
-
-class PinkNoise {
-public:
-  PinkNoise() {
-  srand ( time(NULL) ); // initialize random generator
-    clear();
-  }
-
-  void clear() {
-    for( size_t i=0; i< PINK_NOISE_NUM_STAGES; i++ )
-      state[ i ] = 0.0;
-    }
-
-  float tick() {
-    static const float RMI2 = 2.0 / float(RAND_MAX); // + 1.0; // change for range [0,1)
-    static const float offset = A[0] + A[1] + A[2];
-
-  // unrolled loop
-    float temp = float( rand() );
-    state[0] = P[0] * (state[0] - temp) + temp;
-    temp = float( rand() );
-    state[1] = P[1] * (state[1] - temp) + temp;
-    temp = float( rand() );
-    state[2] = P[2] * (state[2] - temp) + temp;
-    return ( A[0]*state[0] + A[1]*state[1] + A[2]*state[2] )*RMI2 - offset;
-  }
-
-protected:
-  float state[ PINK_NOISE_NUM_STAGES ];
-  static const float A[ PINK_NOISE_NUM_STAGES ];
-  static const float P[ PINK_NOISE_NUM_STAGES ];
-};
-
-//const float PinkNoise::A[] = { 0.02109238, 0.07113478, 0.68873558 }; // rescaled by (1+P)/(1-P)
-//const float PinkNoise::P[] = { 0.3190,  0.7756,  0.9613  };
-
-#endif
--- a/examples/d-box/StatusLED.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * StatusLED.cpp
- *
- * Routines for manipulating the status LED
- *
- * (c) 2014 Andrew McPherson and Victor Zappi
- * QMUL, Centre for Digital Music
- */
-
-#include <iostream>
-#include "StatusLED.h"
-#include <GPIOcontrol.h>
-
-extern int gShouldStop;
-extern int gVerbose;
-
-using namespace std;
-
-StatusLED::StatusLED() {
-	gpio_number = -1;
-	milliseconds_on = 0;
-	milliseconds_off = 100;
-	blink_thread = -1;
-}
-
-StatusLED::~StatusLED() {
-	if(gpio_number >= 0) {
-		this_should_stop = true;
-		pthread_join(blink_thread, NULL);
-		gpio_unexport(gpio_number);
-	}
-}
-
-bool StatusLED::init(int gpio_pin) {
-	gpio_number = gpio_pin;
-	this_should_stop = false;
-
-	if(gpio_export(gpio_number)) {
-		if(gVerbose)
-			cout << "Warning: couldn't export status LED pin\n";
-	}
-	if(gpio_set_dir(gpio_number, OUTPUT_PIN)) {
-		if(gVerbose)
-			cout << "Couldn't set direction on status LED pin\n";
-		return false;
-	}
-	if(gpio_set_value(gpio_number, LOW)) {
-		if(gVerbose)
-			cout << "Couldn't set value on status LED pin\n";
-		return false;
-	}
-
-
-	if ( pthread_create(&blink_thread, NULL, static_blink_loop, this) )
-	{
-		cout << "Error:unable to create status LED thread" << endl;
-		return false;
-	}
-
-	return true;
-}
-
-void StatusLED::on() {
-	milliseconds_on = 100;
-	milliseconds_off = 0;
-}
-
-void StatusLED::off() {
-	milliseconds_on = 0;
-	milliseconds_off = 100;
-}
-
-void StatusLED::blink(int ms_on, int ms_off) {
-	milliseconds_on = ms_on;
-	milliseconds_off = ms_off;
-}
-
-void* StatusLED::blink_loop(void *) {
-	while(!gShouldStop && !this_should_stop) {
-		if(milliseconds_on != 0)
-			gpio_set_value(gpio_number, HIGH);
-		usleep(1000 * milliseconds_on);
-		if(gShouldStop)
-			break;
-		if(milliseconds_off != 0)
-			gpio_set_value(gpio_number, LOW);
-		usleep(1000 * milliseconds_off);
-	}
-	pthread_exit(NULL);
-}
--- a/examples/d-box/StatusLED.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * StatusLED.h
- *
- *
- */
-
-#ifndef STATUSLED_H_
-#define STATUSLED_H_
-
-#include <pthread.h>
-#include <unistd.h>
-
-class StatusLED
-{
-public:
-	StatusLED();
-	~StatusLED();
-
-	bool init(int gpio_pin);
-
-	void on();
-	void off();
-	void blink(int ms_on, int ms_off);
-
-	static void *static_blink_loop(void *data) {
-		((StatusLED*)data)->blink_loop(NULL);
-		return 0;
-	}
-
-	void* blink_loop(void *);
-
-private:
-	int gpio_number;
-	int milliseconds_on, milliseconds_off;
-	bool this_should_stop;
-	pthread_t blink_thread;
-};
-
-#endif // STATUSLED_H_
--- a/examples/d-box/audio_routines.S	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-@
-@ audio_routines.S
-@
-@ NEON-based functions for time-critical audio processing
-@
-@ Andrew McPherson 2014
-@ Queen Mary University of London
-@
-
-	.syntax unified
-	.arch armv7-a
-	.fpu neon
-
-@ 	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
-@							  int activePartialNum, int lookupTableSize,
-@							  float *phases, float *frequencies, float *amplitudes,
-@							  float *freqDerivatives, float *ampDerivatives,
-@							  float *lookupTable);
-
-@ Registers:
-@    r0: numAudioFrames        How many frames to render
-@    r1: audioOut              Buffer for audio output samples [stereo]
-@    r2: activePartialNum      How many active partials to render
-@    r3: lookupTableSize       Size of lookup table
-@    ---- other arguments start on the stack and are moved: -----
-@    r4: phases                Phase of each oscillator (pointer)
-@    r5: frequencies           Normalised frequency of each oscillator (pointer)
-@    r6: amplitudes            Normalised amplitude of each oscillator (pointer)
-@    r7: freqDerivatives       Derivative of frequency for each oscillator (pointer)
-@    r8: ampDerivatives        Derivative of amplitude for each oscillator (pointer)
-@    r9: lookupTable           Lookup table containing one oscillation
-@
-@ Alignment requirements:
-@    audioOut: 8-byte boundary
-@    phases: 16-byte boundary
-@    frequencies: 16-byte boundary
-@    amplitudes: 16-byte boundary
-@    freqDerivatives: 16-byte bounary
-@    ampDerivatives: 16-byte boundary
-@    lookupTable: 4-byte boundary (TODO: check this)
-
-	.align	2
-	.global	oscillator_bank_neon
-	.thumb
-	.thumb_func
-	.type	oscillator_bank_neon, %function
-oscillator_bank_neon:
-
-
-dSample		.dn		D6.F32
-qPhases		.qn		Q8.F32
-dPhases_0	.dn		D16.F32
-dPhases_1	.dn		D17.F32
-qFreqs		.qn		Q9.F32
-dFreqs_0	.dn		D18.F32
-dFreqs_1	.dn		D19.F32
-qAmps		.qn		Q10.F32
-dAmps_0		.dn		D20.F32
-dAmps_1		.dn		D21.F32
-qFreqDs		.qn		Q11.F32
-dFreqDs_0	.dn		D22.F32
-dFreqDs_1	.dn		D23.F32
-qAmpDs		.qn		Q12.F32
-dAmpDs_0	.dn		D24.F32
-dAmpDs_1	.dn		D25.F32
-
-qBaseInts	.qn		Q13.U32		@ Base indexes: unsigned ints x4
-dBaseInts_0	.dn		D26.U32
-dBaseInts_1	.dn		D27.U32
-qFractions  .qn     Q14.F32		@ Fraction indexes: floats x4
-qTableBase	.qn		Q15.U32		@ Base of lookup table
-
-	cmp r0, #0					@ Check for trivial case 1: zero frames
-	it eq
-	bxeq lr						@ Return if that's the case (otherwise might have odd behaviour)
-	cmp r2, #4					@ Check for trivial case 2: zero oscillators
-	it lt
-	bxlt lr						@ Return if that's the case
-
-	push {r4-r11}				@ Now arguments start 32 bytes above SP
-    add r11, sp, #32			@ Pointer to 32 bytes into the stack
-    ldm r11, {r4-r9}			@ Load 6 arguments into registers
-
-	vdup qTableBase, r9			@ Move lookup table base index into 4 ints
-
-	@ Outer loop: iterate over the number of oscillators, choosing 4 at a
-	@ time to work with.
-oscbank_oscillator_loop:
-	vld1 {dPhases_0, dPhases_1}, [r4]		@ no increment; will store at end of sample loop
-	vld1 {dFreqs_0, dFreqs_1}, [r5]
-	vld1 {dAmps_0, dAmps_1}, [r6]
-	vld1 {dFreqDs_0, dFreqDs_1}, [r7]!		@ increment; won't update at end of sample loop
-	vld1 {dAmpDs_0, dAmpDs_1}, [r8]!
-
-	push {r0-r1,r4-r8}
-	@ --- inner loop: iterate over the number of samples ---
-oscbank_sample_loop:
-	vcvt qBaseInts, qPhases		     		@ Take floor(phases)
-	vmov q2.f32, #1.0						@ Load 1.0 into every slot of q2
-	vshl q0.U32, qBaseInts, #2				@ Shift the indexes left 2 (*4 for float addressing)
-	vcvt qFractions, qBaseInts				@ int back to float
-	vadd q0.U32, q0.U32, qTableBase			@ Find memory addresses
-
-	vmov r4, r5, d0							@ Move two indexes to ARM registers
-	vmov r6, r7, d1							@ Move two more indexes to ARM registers
-	vsub qFractions, qPhases, qFractions	@ fraction = phase - floor(phase)
-
-	vldr.64	d0, [r4]						@ Load two consecutive floats at each location
-	vldr.64 d1, [r5]						@ These hold the previous and following samples in the table
-	vldr.64	d2, [r6]						@ TODO: check whether these work at 4-byte alignment
-	vldr.64 d3, [r7]
-
-	@ Format at this point:
-	@ Osc0(before) Osc0(after) Osc1(before) Osc1(after) Osc2(before) Osc2(after) Osc3(before) Osc3(after)
-	@ We want:
-	@ Osc0(before) Osc1(before) Osc2(before) Osc3(before) Osc0(after) Osc1(after) Osc2(after) Osc3(after)
-
-	vuzp.32 q0, q1							@ Now q0 contains before, q1 contains after
-	vsub q2.f32, q2.f32, qFractions			@ q2 = 1.0 - fraction
-	vmul q1.f32, q1.f32, qFractions			@ q1 = fraction * after
-	vmul q0.f32, q0.f32, q2.f32				@ q0 = (1.0 - fraction) * before
-
-	vadd qPhases, qPhases, qFreqs			@ Update phases
-	vadd qFreqs, qFreqs, qFreqDs			@ Update frequencies
-
-	vadd q0.f32, q0.f32, q1.f32				@ Add two interpolated components to get the final sample
-	vdup q2.u32, r3							@ Put lookup table size into each element of q2
-	vcvt qBaseInts, qPhases					@ Take floor of new phases
-	vmul q0.f32, q0.f32, qAmps				@ Multiply samples by current amplitude
-
-	vld1 dSample, [r1]						@ Load the current stereo samples
-	vpadd d2.f32, d0.f32, d1.f32			@ Pairwise accumulate q0 (output sample) into d2
-
-	vand q2, q2, qBaseInts					@ Logical AND of new phase int leaves 1 bit set only if phase >= table size
-	vpadd d3.f32, d2.f32, d2.f32			@ Pairwise accumulate d2 into d0 --> d0[0] and d0[1] both hold total of 4 oscillators
-	vadd qAmps, qAmps, qAmpDs				@ Update amplitudes
-	vcvt q0.f32, q2.u32						@ Convert int back to float after AND operation
-
-	vadd  dSample, dSample, d3.f32			@ Add oscillator outputs to each channel
-
-	subs r0, r0, #1							@ numFrames--
-	vsub qPhases, qPhases, q0.f32			@ Keep phases in table range
-	vst1 dSample, [r1]!						@ Store back in buffer and increment by 8
-
-	it gt
-	bgt oscbank_sample_loop					@ Loop if numFrames > 0
-
-	@ --- end inner loop ---
-	pop {r0-r1,r4-r8}						@ Restore registers: restores audioOut and numFrames, among others
-
-	vst1 {dPhases_0, dPhases_1}, [r4]!		@ Store phases back to array
-	vst1 {dFreqs_0, dFreqs_1}, [r5]!		@ Store frequencies back to array
-	vst1 {dAmps_0, dAmps_1}, [r6]!			@ Store amplitudes back to array
-											@ No need to update r7, r8
-
-	subs r2, r2, #4							@ numPartials -= 4
-	it  gt
-	bgt oscbank_oscillator_loop	@ Loop if numPartials > 0
-
-    pop {r4-r11}
-	bx lr
-
-
-@   void wavetable_interpolate_neon(int numSamplesIn, int numSamplesOut,
-@                              float *tableIn, float *tableOut);
-
-@ Registers:
-@    r0: numSamplesIn          Size of the input table
-@    r1: numSamplesOut         Size of the output table
-@    r2: tableIn               Pointer to input table
-@    r3: tableOut              Pointer to output table
-
-@ Alignment requirements:
-@    tableIn: 8-byte boundary
-@    tableOut: 8-byte boundary
-
-	.align	2
-	.global	wavetable_interpolate_neon
-	.thumb
-	.thumb_func
-	.type	wavetable_interpolate_neon, %function
-wavetable_interpolate_neon:
-    @ TODO
-
-    bx lr
--- a/examples/d-box/config.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * config.h
- *
- * Global settings for D-Box project
- *
- * Andrew McPherson and Victor Zappi 2014
- */
-
-
-#ifndef DBOX_CONFIG_H_
-#define DBOX_CONFIG_H_
-
-
-/* Number of maximum touches used by the TouchKey sensors */
-#define MAX_TOUCHES 5
-
-// for sensor 1 filter
-#define EXP_DENOM 53.5981500331			// exp(4)-1
-
-/* Define this to use Xenomai real-time extensions */
-#define DBOX_USE_XENOMAI
-//#define OLD_OSCBANK
-
-#ifdef DBOX_USE_XENOMAI
-// Xenomai-specific includes
-#include <sys/mman.h>
-
-#include <native/task.h>
-#include <native/timer.h>
-#include <rtdk.h>
-#endif
-
-#ifdef DBOX_USE_XENOMAI
-
-#define dbox_printf rt_printf
-
-#else
-
-#define dbox_printf printf
-
-#endif
-
-#endif /* DBOX_CONFIG_H */
--- a/examples/d-box/how_to_build_dbox.txt	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-The D-Box code can be built on the board using the scripts included with
-Bela. To build the code, do the following from the scripts/ directory:
-
-./setup_board.sh    # Only if Bela is not already copied to the board
-./build_project.sh -n ../projects/d-box  # -n means don't run yet
-
-You will now need to copy the .dbx sound files to the box. These need to
-be in a directory: /root/d-box/sounds
-
-Log into the board via ssh to create the d-box directory, or run:
-
-ssh root@192.168.7.2 "mkdir /root/d-box"
-
-Now copy the .dbx files from a source of your choice to the board. Assuming
-they are in a directory called "sounds":
-
-scp -r sounds root@192.168.7.2:/root/d-box/
-
-Now you can run the D-Box program to make sure it plays. You will need the
-sensors and matrix connected to the box (i.e. a complete hardware D-Box).
-From the scripts/ directory:
-
-./run_project.sh -f -c "-q 24 -r 25 -t 2 -s -p 2 -l 0 -u 0 -i 1 -n f -g 3 -v"
-
-If this plays properly, the D-Box can then be set to run automatically on boot:
-
-./set_startup.sh -l -c "-q 24 -r 25 -t 2 -s -p 2 -l 0 -u 0 -i 1 -n f -g 3 -v"
-
-If at any time you want to stop the D-Box program running, you can run:
-
-./stop_running.sh
-
-To turn off further autoboot, run:
-
-./set_startup.sh -n
--- a/examples/d-box/logger.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * logger.cpp
- *
- *  Created on: Aug 6, 2014
- *      Author: VIctor Zappi and Andrew McPherson
- */
-
-#include "logger.h"
-
-// main extern vars
-extern int gShouldStop;
-extern int gVerbose;
-
-// file nanme extern vars
-extern char gId;
-extern char gGroup;
-
-
-// logged extern vars
-extern int s0TouchNum;
-extern float s0Touches_[MAX_TOUCHES];
-extern float s0Size_[MAX_TOUCHES];
-extern int s0LastIndex;
-
-extern int s1TouchNum;
-extern float s1Touches_[MAX_TOUCHES];
-extern float s1Size_[MAX_TOUCHES];
-extern int s1LastIndex;
-
-extern int fsr;
-
-
-
-string logPath			= "/boot/uboot/instrumentLog";
-string logFileIncipit	= "/datalog";
-string logFileName		= "";
-ofstream logFile;
-timeval logTimeVal;
-unsigned long long logTimeOrig;
-int logCnt				= 0;	// counts how many lines so far
-int logCntSwap			= 50;	// how many log lines before closing and re-opening the file
-
-
-// create the log file, using incremental name convention
-int initLogLoop()
-{
-	if(gVerbose==1)
-		cout << "---------------->Init Log Thread" << endl;
-
-
-	// transform chars into strings via stringstream objs
-	stringstream id_ss, group_ss, freedom_ss;
-	id_ss 		<< gId;
-	group_ss 	<< gGroup;
-
-	int logNum	= -1;
-	int logMax	= -1;
-	int pathLen	= logPath.length() + logFileIncipit.length() + 4;	// + 4 is: "_", id, group, "_"
-	glob_t globbuf;
-
-	// check how many log files are already there, and choose name according to this
-	glob( (logPath + logFileIncipit + "*").c_str(), 0, NULL, &globbuf);
-
-	// cycle through all and find the highest index
-	for(unsigned int i=0; i<globbuf.gl_pathc; i++)
-	{
-		// playing with 0-9 char digits, forming a number from 0 to 9999
-		logNum  = (globbuf.gl_pathv[i][pathLen]-48)   * 1000;	// 42 to 45 are the indices of the chars forming the file index
-		logNum += (globbuf.gl_pathv[i][pathLen+1]-48) * 100;
-		logNum += (globbuf.gl_pathv[i][pathLen+2]-48) * 10;
-		logNum +=  globbuf.gl_pathv[i][pathLen+3]-48;
-		if(logNum > logMax)
-			logMax = logNum;
-	}
-	logNum = logMax + 1;	// new index
-
-	globfree(&globbuf);
-
-	ostringstream numString;
-	numString << setw (4) << setfill ('0') << logNum;	// set integer with 4 figures
-
-	// here are the new names: PATH + DIR + INCIPIT + _ + id + group + freedom + _ + NUM (4figures) + _A.txt
-	logFileName	= logPath + logFileIncipit;
-	logFileName	+= "_" + id_ss.str() + group_ss.str() + freedom_ss.str();
-	logFileName	+= "_" + numString.str();	 //static_cast<ostringstream*>( &(ostringstream() << logNum) )->str();
-	logFileName	+= ".txt";
-
-
-	// create new files
-	FILE *fp_a		= fopen(logFileName.c_str(), "wb");
-	if(!fp_a)
-	{
-		dbox_printf("Cannot create files...\n");
-		return 2;
-	}
-	fclose(fp_a);
-
-	// ready to append
-	logFile.open(logFileName.c_str(), ios::out | ios::app);
-
-	dbox_printf("Logging on file %s\n", logFileName.c_str());
-
-	return 0;
-}
-
-
-void writeData(unsigned long long time)
-{
-
-	float fsr_ = ((float)(1799-fsr)/1799.0);
-	logFile << time 				<< "\t"		// timestamp
-			<< s0TouchNum			<< "\t";	// sensor 0 touch count
-	for(int i=0; i<MAX_TOUCHES; i++)
-		logFile << s0Touches_[i] 	<< "\t";	// sensor 0 touch pos x
-	for(int i=0; i<MAX_TOUCHES; i++)
-		logFile << s0Size_[i] 		<< "\t";	// sensor 0 touch size
-	logFile << s0LastIndex 			<< "\t"		// sensor 0 last index
-			<< fsr_					<< "\t"		// sensor 0 FSR pressure
-			<< s1TouchNum			<< "\t";	// sensor 1 touch count
-	for(int i=0; i<MAX_TOUCHES; i++)
-		logFile << s1Touches_[i] 	<< "\t";	// sensor 1 touch pos x
-	for(int i=0; i<MAX_TOUCHES; i++)
-		logFile	<< s1Size_[i] 		<< "\t";	// sensor 1 touch size
-	logFile << s1LastIndex 			<< "\t"		// sensor 1 last index
-	//... AND SO ON
-			<< "\n";
-
-	//dbox_printf("%d\n", s0LastIndex);
-	//dbox_printf("s0TouchNum: %d\t s0Touches[0]: %f\t s0Size[0]: %f\t s0LastIndex: %d\n", s0TouchNum, s0Touches_[0], s0Size_[0], s0LastIndex);
-
-}
-
-void logData(unsigned long long time)
-{
-	// if it's time to change write-file
-	if(logCnt >= logCntSwap)
-	{
-		logFile.close();	// close file, dump stream
-		logCnt = 0;		// ready for another whole round
-
-		// open again, ready to append
-		logFile.open(logFileName.c_str(), ios::out | ios::app);
-	}
-
-	writeData(time);
-
-	logCnt++;
-}
-
-
-
-
-void *logLoop(void *)
-{
-	set_realtime_priority(10);
-
-	if(gVerbose==1)
-		dbox_printf("_________________Log Thread!\n");
-
-	// get time reference
-	gettimeofday(&logTimeVal, NULL);
-	logData(0);
-
-	logTimeOrig = logTimeVal.tv_usec;
-	logTimeOrig *= 0.001;					// from usec to msec
-	logTimeOrig += logTimeVal.tv_sec*1000;	// from sec to msec
-
-	usleep(5000);
-
-	while(!gShouldStop)
-	{
-		gettimeofday(&logTimeVal, NULL);
-		unsigned long long currentTime = logTimeVal.tv_usec;
-		currentTime *= 0.001;					// from usec to msec
-		currentTime += logTimeVal.tv_sec*1000;	// from sec to msec
-
-		logData(currentTime-logTimeOrig);
-
-		usleep(5000);
-	}
-
-	if(logFile!=NULL)
-		logFile.close();
-
-	dbox_printf("log thread ended\n");
-
-	return (void *)0;
-}
--- a/examples/d-box/logger.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * logger.h
- *
- *  Created on: Aug 6, 2014
- *      Author: Victor Zappi and Andrew McPherson
- */
-
-#ifndef LOGGER_H_
-#define LOGGER_H_
-
-#include <string.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <fstream>		// file handle
-#include <iostream>		// stringstream
-#include <sstream>		// stringstream
-#include <glob.h>		// alternative to dirent.h to handle files in dirs
-#include <iomanip>		// setfill
-#include <sys/time.h>	// elapsed time
-
-#include "config.h"
-#include "prio.h"
-
-using namespace std;
-
-int initLogLoop();
-void *logLoop(void *);
-
-
-#endif /* LOGGER_H_ */
--- a/examples/d-box/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
- *  RTAudio.cpp
- *
- *  Central control code for hard real-time audio on BeagleBone Black
- *  using PRU and Xenomai Linux extensions. This code began as part
- *  of the Hackable Instruments project (EPSRC) at Queen Mary University
- *  of London, 2013-14.
- *
- *  (c) 2014 Victor Zappi and Andrew McPherson
- *  Queen Mary University of London
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <math.h>
-#include <iostream>
-#include <signal.h>		// interrupt handler
-#include <assert.h>
-#include <vector>
-#include <dirent.h>		// to handle files in dirs
-#include <mntent.h>		// to check if device is mounted
-#include <sys/mount.h>	// mount()
-#include <sys/time.h>	// elapsed time
-#include <ne10/NE10.h>	// neon library
-
-// thread priority
-#include <pthread.h>
-#include <sched.h>
-
-// get_opt_long
-#include <getopt.h>
-
-#include <Bela.h>
-#include "config.h"
-#include "sensors.h"
-#include "OscillatorBank.h"
-#include "StatusLED.h"
-#include "logger.h"
-
-using namespace std;
-
-//----------------------------------------
-// main variables
-//----------------------------------------
-vector<OscillatorBank*> gOscBanks;
-int gCurrentOscBank = 0;
-int gNextOscBank = 0;
-int oscBnkOversampling 				 = 1;	// oscillator bank frame oversampling
-
-const int kStatusLEDPin 	 = 30;	// P9-11 controls status LED
-StatusLED gStatusLED;
-
-pthread_t keyboardThread;
-pthread_t logThread;
-
-// general settings
-int gVerbose		= 0;        			// verbose flag
-bool forceKeyboard 	= true;					// activate/deactivate keyboard control
-bool forceSensors	= false;				// activate/deactivate sensor control
-bool forceLog		= true;					// activate/deactivate log on boot partition
-bool useSD   		= true;    				// activate/deactivate file loading from SD [as opposed to emmc]
-bool useAudioTest   = false;    			// activate/deactivate sensors and test audio only
-
-// audio settings
-unsigned int gPeriodSize = 8;				// period size for audio
-char* gPartialFilename = 0;					// name of the partials file to load
-bool gAudioIn = false;						// stereo audio in status
-
-int touchSensor0Address = 0x0C;				// I2C addresses of touch sensors
-int touchSensor1Address = 0x0B;
-int sensorType = 0;
-
-char sdPath[256]			= "/dev/mmcblk0p2";			// system path of the SD, partition 2
-char mountPath[256]			= "/root/d-box/usersounds";	// mount point of SD partition 2 [where user files are]
-char gUserDirName[256] 		= "usersounds";				// Directory in which user analysis files can be found [dir of mountPath]
-char gDefaultDirName[256] 	= "/root/d-box/sounds";		// Directory in which built in analysis files can be found
-char *gDirName;
-bool gIsLoading 			= false;
-int fileCnt 				= 0;
-std::vector <std::string> files;
-
-char gId	= 'f';	// from 0 to 14, hexadecimal [0-d]! f means not set
-char gGroup	= '2';	// 0 is no info, 1 info.   2 is not set
-
-// audio in filter
-extern ne10_float32_t *filterState[2];
-extern ne10_float32_t *filterIn[2];
-extern ne10_float32_t *filterOut[2];
-
-struct arg_data
-{
-   int  argc;
-   char **argv;
-};
-
-arg_data args;
-
-
-int readFiles()
-{
-	if(useSD)
-		gDirName = gUserDirName;
-	else
-		gDirName = gDefaultDirName;
-	DIR *dir;
-	struct dirent *ent;
-
-	// From http://stackoverflow.com/questions/612097/how-can-i-get-a-list-of-files-in-a-directory-using-c-or-c
-	if ((dir = opendir (gDirName)) != NULL) {
-		/* print all the files and directories within directory */
-		while ((ent = readdir (dir)) != NULL) {
-			// Ignore dotfiles and . and .. paths
-			if(!strncmp(ent->d_name, ".", 1))
-				continue;
-
-			//dbox_printf("%s\n", ent->d_name);
-
-			// take only .dbx and .txt files
-			string name = string(ent->d_name);
-			int len		= name.length();
-
-			bool dboxFile = false;
-
-			if( (name[len-4]=='.') && (name[len-3]=='d') && (name[len-2]=='b') && (name[len-1]=='x') )
-				dboxFile = true;
-			if( (name[len-4]=='.') && (name[len-3]=='t') && (name[len-2]=='x') && (name[len-1]=='t') )
-				dboxFile = true;
-
-			if(dboxFile)
-			{
-				fileCnt++;
-				//dbox_printf("%s\n", ent->d_name);
-				files.push_back( std::string( ent->d_name ) );
-			}
-		}
-		closedir (dir);
-	} else {
-		/* could not open directory */
-		printf("Could not open directory %s\n", gDirName);
-		return 1;
-	}
-
-	// order by name
-	std::sort( files.begin(), files.end() );
-
-	if(fileCnt==0)
-	{
-		printf("No .dbx or .txt files in %s!\n", gDirName);
-		return 1;
-	}
-
-	return 0;
-}
-
-/* Load sounds from the directory */
-void loadAudioFiles(bool loadFirstFile)
-{
-	char fullFileName[256];
-
-	if(loadFirstFile) {
-		strcpy(fullFileName, gDirName);
-		strcat(fullFileName, "/");
-		strncat(fullFileName, files[0].c_str(), 255 - strlen(gDirName));
-		dbox_printf("Loading first file %s...\n", fullFileName);
-		OscillatorBank *bank = new OscillatorBank(fullFileName);
-		if(bank->initBank(oscBnkOversampling)) {
-			bank->setLoopHops(100, bank->getLastHop());
-			gOscBanks.push_back(bank);
-		}
-	}
-
-	else {
-		for(int i=1; i<fileCnt; i++){
-			strcpy(fullFileName, gDirName);
-			strcat(fullFileName, "/");
-			strncat(fullFileName, files[i].c_str(), 255 - strlen(gDirName));
-			dbox_printf("Loading file %s...\n", fullFileName);
-			OscillatorBank *bank = new OscillatorBank(fullFileName);
-			if(bank->initBank(oscBnkOversampling)) {
-				bank->setLoopHops(100, bank->getLastHop());
-				gOscBanks.push_back(bank);
-			}
-		}
-	}
-}
-
-// adapted from http://program-nix.blogspot.co.uk/2008/08/c-language-check-filesystem-is-mounted.html
-int checkIfMounted (char * dev_path)
-{
-	FILE * mtab				= NULL;
-	struct mntent * part	= NULL;
-	int is_mounted			= 0;
-
-	if ( ( mtab = setmntent ("/etc/mtab", "r") ) != NULL)
-	{
-		while ( ( part = getmntent ( mtab) ) != NULL)
-		{
-			if ( ( part->mnt_fsname != NULL ) && ( strcmp ( part->mnt_fsname, dev_path ) ) == 0 )
-			   is_mounted = 1;
-		}
-	endmntent(mtab);
-	}
-	return is_mounted;
-}
-
-int mountSDuserPartition()
-{
-	if(checkIfMounted(sdPath))
-	{
-		printf("device %s already mounted, fair enough, let's move on\n", sdPath);
-		return 0;
-	}
-	// if mount rootfs from SD [rootfs eMMC not used] or from eMMC via properly formatted SD [SD rootfs used as storage volume]
-	// we always use rootfs on SD as storage volume ----> "/dev/mmcblk0p2"
-	int ret = mount(sdPath, "/root/d-box/usersounds", "vfat",  0, NULL);
-	if (ret!=0)
-	{
-			printf("Error in mount...%s\n", strerror(ret));
-			return 1;
-	}
-	return 0;
-}
-
-int initSoundFiles()
-{
-	if(gVerbose==1)
-		cout << "---------------->Init Audio Thread" << endl;
-
-	if(useSD)
-	{
-		// mount the SD partition where user sounds are located
-		// [this is p2, p1 is already mounted and we will log data there]
-		if(mountSDuserPartition()!=0)
-			return -1;
-	}
-
-	gIsLoading = true;
-
-	// read files from SD and order them alphabetically
-	if(readFiles()!=0)
-		return 1;
-
-	// load first file into oscBank
-	loadAudioFiles(true);
-
-	return 0;
-}
-
-//---------------------------------------------------------------------------------------------------------
-
-// Handle Ctrl-C
-void interrupt_handler(int var)
-{
-	// kill keyboard thread mercilessly
-	if(forceKeyboard)
-		pthread_cancel(keyboardThread);
-
-	gShouldStop = true;
-}
-
-
-void parseArguments(arg_data args, BelaInitSettings *settings)
-{
-	// Default filename;
-	gPartialFilename = strdup("D-Box_sound_250_60_40_h88_2.txt");
-
-	const int kOptionAudioTest = 1000;
-
-	// TODO: complete this
-	struct option long_option[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"audioin", 1, NULL, 'i'},
-		{"file", 1, NULL, 'f'},
-		{"keyboard", 1, NULL, 'k'},
-		{"audio-test", 0, NULL, kOptionAudioTest},
-		{"sensor-type", 1, NULL, 't'},
-		{"sensor0", 1, NULL, 'q'},
-		{"sensor1", 1, NULL, 'r'},
-		{"log", 1, NULL, 'l'},
-		{"usesd", 1, NULL, 'u'},
-		{"oversamp", 1, NULL, 'o'},
-		{"boxnumber", 1, NULL, 'n'},
-		{"group", 1, NULL, 'g'},
-		{NULL, 0, NULL, 0},
-	};
-	int morehelp = 0;
-	int tmp = -1;
-
-	Bela_defaultSettings(settings);
-
-	while (1)
-	{
-		int c;
-		if ((c = Bela_getopt_long(args.argc, args.argv, "hf:ki:sq:r:t:l:u:o:n:g:", long_option, settings)) < 0)
-				break;
-		switch (c)
-		{
-		case 'h':
-				morehelp++;
-				break;
-		case 'f':
-				free(gPartialFilename);
-				gPartialFilename = strdup(optarg);
-				break;
-		case 'k':
-				forceKeyboard = true;
-				break;
-		case 'i':
-				gAudioIn = (atoi(optarg)==0) ? false : true;
-				break;
-		case 's':
-				forceSensors = true;
-				break;
-		case kOptionAudioTest:
-				useAudioTest = true;
-				break;
-		case 't':
-				sensorType = atoi(optarg);
-				break;
-		case 'q':
-				touchSensor0Address = atoi(optarg);
-				break;
-		case 'r':
-				touchSensor1Address = atoi(optarg);
-				break;
-		case 'l':
-				tmp = atoi(optarg);
-				if(tmp==0)
-					forceLog = false;
-				else if(tmp>0)
-					forceLog = true;
-				break;
-		case 'u':
-				tmp = atoi(optarg);
-				if(tmp==0)
-					useSD = false;
-				else if(tmp>0)
-					useSD = true;
-				break;
-		case 'o':
-				oscBnkOversampling = atoi(optarg);
-				break;
-		case 'n':
-				gId = *optarg;
-				cout << "-set box number to: " << gId << endl;
-				break;
-		case 'g':
-				gGroup = *optarg;
-				cout << "-set group to: " << gId << endl;
-				break;
-		default:
-				break;
-		}
-	}
-
-	gPeriodSize = settings->periodSize;
-	gVerbose = settings->verbose;
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	RT_TASK rtSensorThread;
-	const char rtSensorThreadName[] = "dbox-sensor";
-	int oscBankHopSize;
-
-	// Parse command-line arguments
-	args.argc = argc;
-	args.argv = argv;
-	parseArguments(args, &settings);
-
-	Bela_setVerboseLevel(gVerbose);
-	if(gVerbose == 1 && useAudioTest)
-		cout << "main() : running in audio test mode" << endl;
-
-	// Load sound files from directory
-	if(initSoundFiles() != 0)
-		return -1;
-
-	oscBankHopSize = gOscBanks[gCurrentOscBank]->getHopSize()/gOscBanks[gCurrentOscBank]->getMinSpeed();
-
-	// Initialise the audio device
-	if(Bela_initAudio(&settings, &oscBankHopSize) != 0)
-		return -1;
-
-	// Initialise the status LED
-	if(!gStatusLED.init(kStatusLEDPin)) {
-		if(gVerbose)
-			cout << "Couldn't initialise status LED pin\n";
-	}
-
-	// Free file name string which is no longer needed
-	if(gPartialFilename != 0)
-		free(gPartialFilename);
-
-	if(!useAudioTest) {
-		if(initSensorLoop(touchSensor0Address, touchSensor1Address, sensorType) != 0)
-			return -1;
-	}
-
-	if(gVerbose == 1)
-		cout << "main() : creating audio thread" << endl;
-
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// LED on...
-	gStatusLED.on();
-
-	if(forceSensors && !useAudioTest) {
-		if(gVerbose==1)
-			cout << "main() : creating control thread" << endl;
-
-		if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, BELA_AUDIO_PRIORITY - 5, T_JOINABLE | T_FPU)) {
-			  cout << "Error:unable to create Xenomai control thread" << endl;
-			  return -1;
-		}
-		if(rt_task_start(&rtSensorThread, &sensorLoop, 0)) {
-			  cout << "Error:unable to start Xenomai control thread" << endl;
-			  return -1;
-		}
-	}
-
-	if(forceKeyboard) {
-		if(gVerbose==1)
-			cout << "main() : creating keyboard thread" << endl;
-
-		if ( pthread_create(&keyboardThread, NULL, keyboardLoop, NULL) ) {
-		  cout << "Error:unable to create keyboard thread" << endl;
-		  return -1;
-		}
-	}
-
-	if(forceLog) {
-		if(gVerbose==1)
-			cout << "main() : creating log thread" << endl;
-
-		if(initLogLoop()!=0) {
-			cout << "Error:unable to create log thread" << endl;
-			return -1;
-		}
-
-		if ( pthread_create(&logThread, NULL, logLoop, NULL) ) {
-		  cout << "Error:unable to create keyboard thread" << endl;
-		  return -1;
-		}
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// load all other files into oscBanks
-	loadAudioFiles(false);
-	cout << "Finished loading analysis files\n";
-	gIsLoading = false;
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	Bela_stopAudio();
-
-	if(!useAudioTest)
-		rt_task_join(&rtSensorThread);
-
-	Bela_cleanupAudio();
-
-	pthread_join( keyboardThread, NULL);
-	pthread_join( logThread, NULL);
-
-	for(unsigned int i = 0; i < gOscBanks.size(); i++)
-		delete gOscBanks[i];
-
-	NE10_FREE(filterState[0]);
-	NE10_FREE(filterState[1]);
-	NE10_FREE(filterIn[0]);
-	NE10_FREE(filterIn[1]);
-	NE10_FREE(filterOut[0]);
-	NE10_FREE(filterOut[1]);
-
-	printf("Program ended\nBye bye\n");
-	return 0;
-}
--- a/examples/d-box/prio.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * prio.cpp
- *
- *  Created on: May 14, 2014
- *      Author: Victor Zappi
- */
-
-#include "prio.h"
-using namespace std;
-//-----------------------------------------------------------------------------------------------------------
-// set wanted real-time priority to this thread
-//-----------------------------------------------------------------------------------------------------------
-void set_realtime_priority(int order)
-{
-    int ret;
-
-    // We'll operate on the currently running thread.
-    pthread_t this_thread = pthread_self();
-    // struct sched_param is used to store the scheduling priority
-	struct sched_param params;
-	// We'll set the priority to the maximum.
-	params.sched_priority = sched_get_priority_max(SCHED_FIFO) - order;
-
-	// Attempt to set thread real-time priority to the SCHED_FIFO policy
-	ret = pthread_setschedparam(this_thread, SCHED_FIFO, &params);
-	if (ret != 0) {
-		// Print the error
-		cout << "Unsuccessful in setting thread realtime prio" << endl;
-		return;
-	}
-
-	// Now verify the change in thread priority
-    int policy = 0;
-    ret = pthread_getschedparam(this_thread, &policy, &params);
-    if (ret != 0) {
-        cout << "Couldn't retrieve real-time scheduling parameters" << endl;
-        return;
-    }
-
-    // Check the correct policy was applied
-    if(policy != SCHED_FIFO) {
-        cout << "Scheduling is NOT SCHED_FIFO!" << endl;
-    }
-}
-
-//-----------------------------------------------------------------------------------------------------------
-
-
--- a/examples/d-box/prio.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-/*
- * prio.h
- *
- *  Created on: May 14, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef PRIO_H_
-#define PRIO_H_
-
-
-#include <pthread.h>
-#include <sched.h>
-#include <iostream>
-
-//-----------------------------------------------------------------------------------------------------------
-// set maximum real-time priority to this thread
-//-----------------------------------------------------------------------------------------------------------
-void set_realtime_priority(int order);
-//-----------------------------------------------------------------------------------------------------------
-
-#endif /* PRIO_H_ */
--- a/examples/d-box/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,870 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: May 28, 2014
- *      Author: Victor Zappi
- */
-
-#include <Bela.h>
-#include <PRU.h>
-
-#include "StatusLED.h"
-#include "config.h"
-#include "OscillatorBank.h"
-#include "FeedbackOscillator.h"
-#include "ADSR.h"
-#include "FIRfilter.h"
-#include <assert.h>
-#include <cmath>
-#include <vector>
-
-#undef DBOX_CAPE_TEST
-
-// Mappings from pin numbers on PCB to actual DAC channels
-// This gives the DAC and ADC connectors the same effective pinout
-// Update June 2016: this is no longer needed in the latest Bela
-// release, but is kept here for convenience: it used to be 
-// 6 4 2 0 1 3 5 7 for the DAC pins
-#define DAC_PIN0	0
-#define DAC_PIN1	1
-#define DAC_PIN2	2
-#define DAC_PIN3	3
-#define DAC_PIN4	4
-#define DAC_PIN5	5
-#define DAC_PIN6	6
-#define DAC_PIN7	7
-
-#define ADC_PIN0	0
-#define ADC_PIN1	1
-#define ADC_PIN2	2
-#define ADC_PIN3	3
-#define ADC_PIN4	4
-#define ADC_PIN5	5
-#define ADC_PIN6	6
-#define ADC_PIN7	7
-
-#define N_OCT		4.0	// maximum number of octaves on sensor 1
-
-extern vector<OscillatorBank*> gOscBanks;
-extern int gCurrentOscBank;
-extern int gNextOscBank;
-extern PRU *gPRU;
-extern StatusLED gStatusLED;
-extern bool gIsLoading;
-extern bool gAudioIn;
-
-float *gOscillatorBuffer1, *gOscillatorBuffer2;
-float *gOscillatorBufferRead, *gOscillatorBufferWrite;
-int gOscillatorBufferReadPointer		= 0;
-int gOscillatorBufferReadCurrentSize	= 0;
-int gOscillatorBufferWriteCurrentSize	= 0;
-bool gOscillatorNeedsRender				= false;
-
-int gMatrixSampleCount = 0;		// How many samples have elapsed on the matrix
-
-// Wavetable which changes in response to an oscillator
-float *gDynamicWavetable;
-int gDynamicWavetableLength;
-bool gDynamicWavetableNeedsRender = false;
-
-// These variables handle the hysteresis oscillator used for setting the playback speed
-bool gSpeedHysteresisOscillatorRising	= false;
-int gSpeedHysteresisLastTrigger			= 0;
-
-// These variables handle the feedback oscillator used for controlling the wavetable
-FeedbackOscillator gFeedbackOscillator;
-float *gFeedbackOscillatorTable;
-int gFeedbackOscillatorTableLength;
-
-// This comes from sensor.cpp where it records the most recent touch location on
-// sensor 0.
-extern float gSensor0LatestTouchPos;
-extern int gSensor0LatestTouchNum;
-float gPitchLatestInput = 0;
-
-extern float gSensor1LatestTouchPos[];
-//extern float gSensor1LatestTouchSizes[];
-extern int gSensor1LatestTouchCount;
-extern int gSensor1LatestTouchIndex;
-int gSensor1LastTouchIndex		= -1;
-int gSensor1InputDelayCounter	= -1;
-int gSensor1InputIndex			= 0;
-float gSensor1MatrixTouchPos[5]	= {0};
-
-// FSR value from matrix input
-extern int gLastFSRValue;
-
-// Loop points from matrix input 4
-const int gLoopPointsInputBufferSize	= 256;
-float gLoopPointsInputBuffer[gLoopPointsInputBufferSize];
-int gLoopPointsInputBufferPointer		= 0;
-float gLoopPointMin = 0, gLoopPointMax	= 0;
-
-// multiplier to activate or mute audio in
-int audioInStatus = 0;
-
-// xenomai timer
-SRTIME prevChangeNs = 0;
-
-// pitch vars
-float octaveSplitter;
-float semitones[((int)N_OCT*12)+1];
-float deltaTouch	= 0;
-float deltaWeightP	= 0.5 / 65536.0;
-float deltaWeightI	= 0.0005 / 65536.0;
-
-// filter vars
-ne10_fir_instance_f32_t filter[2];
-ne10_float32_t *filterIn[2];
-ne10_float32_t *filterOut[2];
-ne10_uint32_t blockSize;
-ne10_float32_t *filterState[2];
-ne10_float32_t prevFiltered[2];
-int filterGain = 80;
-ADSR PeakBurst[2];
-float peak[2];
-float peakThresh = 0.2;
-
-// Tasks for lower-priority calculation
-AuxiliaryTask gMediumPriorityRender, gLowPriorityRender;
-
-
-extern "C" {
-	// Function prototype for ARM assembly implementation of oscillator bank
-	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
-							  int activePartialNum, int lookupTableSize,
-							  float *phases, float *frequencies, float *amplitudes,
-							  float *freqDerivatives, float *ampDerivatives,
-							  float *lookupTable);
-
-	void wavetable_interpolate_neon(int numSamplesIn, int numSamplesOut,
-	                              float *tableIn, float *tableOut);
-}
-
-void wavetable_interpolate(int numSamplesIn, int numSamplesOut,
-                              float *tableIn, float *tableOut,
-                              float *sineTable, float sineMix);
-
-inline float hysteresis_oscillator(float input, float risingThreshold,
-									float fallingThreshold, bool *rising);
-
-void render_medium_prio();
-void render_low_prio();
-
-#ifdef DBOX_CAPE_TEST
-void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
-			uint16_t *matrixIn, uint16_t *matrixOut);
-#endif
-
-bool setup(BelaContext *context, void *userData) {
-	int oscBankHopSize = *(int *)userData;
-
-	if(context->analogChannels != 8) {
-		printf("Error: D-Box needs matrix enabled with 8 channels.\n");
-		return false;
-	}
-
-	// Allocate two buffers for rendering oscillator bank samples
-	// One will be used for writing in the background while the other is used for reading
-	// on the audio thread. 8-byte alignment needed for the NEON code.
-	if(posix_memalign((void **)&gOscillatorBuffer1, 8, oscBankHopSize * context->audioChannels * sizeof(float))) {
-		printf("Error allocating render buffers\n");
-		return false;
-	}
-	if(posix_memalign((void **)&gOscillatorBuffer2, 8, oscBankHopSize * context->audioChannels * sizeof(float))) {
-		printf("Error allocating render buffers\n");
-		return false;
-	}
-	gOscillatorBufferWrite	= gOscillatorBuffer1;
-	gOscillatorBufferRead	= gOscillatorBuffer2;
-
-	memset(gOscillatorBuffer1, 0, oscBankHopSize * context->audioChannels * sizeof(float));
-	memset(gOscillatorBuffer2, 0, oscBankHopSize * context->audioChannels * sizeof(float));
-
-	// Initialise the dynamic wavetable used by the oscillator bank
-	// It should match the size of the static one already allocated in the OscillatorBank object
-	// Don't forget a guard point at the end of the table
-	gDynamicWavetableLength = gOscBanks[gCurrentOscBank]->lookupTableSize;
-	if(posix_memalign((void **)&gDynamicWavetable, 8, (gDynamicWavetableLength + 1) * sizeof(float))) {
-		printf("Error allocating wavetable\n");
-		return false;
-	}
-
-	gFeedbackOscillator.initialise(8192, 10.0, context->analogSampleRate);
-
-	for(int n = 0; n < gDynamicWavetableLength + 1; n++)
-		gDynamicWavetable[n] = 0;
-
-	// pitch
-	float midPos		= 0.5;
-	octaveSplitter		= 1.0 / N_OCT;
-	int numOfSemi		= 12*N_OCT;
-	int middleSemitone	= 12*N_OCT/2;
-	int lastSemitone	= middleSemitone+numOfSemi/2;
-	float inc 			= 1.0 / (N_OCT*12.0);
-	int i 				= -1;
-	for(int semi=middleSemitone; semi<=lastSemitone; semi++)
-		semitones[semi] = ( midPos + (++i)*inc) + 0.5;
-	i 					= 0;
-	for(int semi=middleSemitone-1; semi>=0; semi--)
-		semitones[semi] = ( midPos - (++i)*inc) + 0.5;
-
-	if(gAudioIn)
-		audioInStatus = 1;
-
-	// filter
-	blockSize		= context->audioFrames;
-	filterState[0]	= (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
-	filterState[1]	= (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
-	filterIn[0]		= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
-	filterIn[1]		= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
-	filterOut[0]	= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
-	filterOut[1]	= (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
-	ne10_fir_init_float(&filter[0], FILTER_TAP_NUM, filterTaps, filterState[0], blockSize);
-	ne10_fir_init_float(&filter[1], FILTER_TAP_NUM, filterTaps, filterState[1], blockSize);
-
-	// peak outputs
-	PeakBurst[0].setAttackRate(.00001 * context->analogSampleRate);
-	PeakBurst[1].setAttackRate(.00001 * context->analogSampleRate);
-	PeakBurst[0].setDecayRate(.5 * context->analogSampleRate);
-	PeakBurst[1].setDecayRate(.5 * context->analogSampleRate);
-	PeakBurst[0].setSustainLevel(0.0);
-	PeakBurst[1].setSustainLevel(0.0);
-
-	// Initialise auxiliary tasks
-	if((gMediumPriorityRender = Bela_createAuxiliaryTask(&render_medium_prio, BELA_AUDIO_PRIORITY - 10, "dbox-calculation-medium")) == 0)
-		return false;
-	if((gLowPriorityRender = Bela_createAuxiliaryTask(&render_low_prio, BELA_AUDIO_PRIORITY - 15, "dbox-calculation-low")) == 0)
-		return false;
-
-	return true;
-}
-
-void render(BelaContext *context, void *userData)
-{
-#ifdef DBOX_CAPE_TEST
-	render_capetest(numMatrixFrames, numAudioFrames, audioIn, audioOut, matrixIn, matrixOut);
-#else
-	if(gOscBanks[gCurrentOscBank]->state==bank_toreset)
-		gOscBanks[gCurrentOscBank]->resetOscillators();
-
-	if(gOscBanks[gCurrentOscBank]->state==bank_playing)
-	{
-		assert(context->audioChannels == 2);
-
-#ifdef OLD_OSCBANK
-		memset(audioOut, 0, numAudioFrames *  * sizeof(float));
-
-		/* Render the oscillator bank. The oscillator bank function is written in NEON assembly
-		 * and it strips out all extra checks, so find out in advance whether we can render a whole
-		 * block or whether the frame will increment in the middle of this buffer.
-		 */
-
-		int framesRemaining = numAudioFrames;
-		float *audioOutWithOffset = audioOut;
-
-		while(framesRemaining > 0) {
-			if(gOscBanks[gCurrentOscBank]->hopCounter >= framesRemaining) {
-				/* More frames left in this hop than we need this time. Render and finish */
-				oscillator_bank_neon(framesRemaining, audioOutWithOffset,
-									 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize,
-									 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies,
-									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
-									 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
-									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
-									 gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/);
-				gOscBanks[gCurrentOscBank]->hopCounter -= framesRemaining;
-				if(gOscBanks[gCurrentOscBank]->hopCounter <= 0)
-					gOscBanks[gCurrentOscBank]->nextHop();
-				framesRemaining = 0;
-			}
-			else {
-				/* More frames to render than are left in this hop. Render and decrement the
-				 * number of remaining frames; then advance to the next oscillator frame.
-				 */
-				oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, audioOutWithOffset,
-									 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize,
-									 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies,
-									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
-									 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
-									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
-									 gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/);
-				framesRemaining -= gOscBanks[gCurrentOscBank]->hopCounter;
-				audioOutWithOffset +=  * gOscBanks[gCurrentOscBank]->hopCounter;
-				gOscBanks[gCurrentOscBank]->sampleCount += gOscBanks[gCurrentOscBank]->hopCounter;
-				gOscBanks[gCurrentOscBank]->nextHop();
-			}
-		}
-#else
-		for(unsigned int n = 0; n < context->audioFrames; n++) {
-			context->audioOut[2*n] 	  = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n]*audioInStatus;
-			context->audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+context->audioIn[2*n+1]*audioInStatus;
-
-			filterIn[0][n] = fabs(context->audioIn[2*n]);	// rectify for peak detection in 1
-			filterIn[1][n] = fabs(context->audioIn[2*n+1]);	// rectify for peak detection in 2
-
-			/* FIXME why doesn't this work? */
-			/*
-			if(gOscillatorBufferReadPointer == gOscillatorBufferCurrentSize/2) {
-				gOscillatorNeedsRender = true;
-				scheduleAuxiliaryTask(gLowPriorityRender);
-			} */
-
-			if(gOscillatorBufferReadPointer >= gOscillatorBufferReadCurrentSize) {
-				// Finished reading from the buffer: swap to the next buffer
-				if(gOscillatorBufferRead == gOscillatorBuffer1) {
-					gOscillatorBufferRead = gOscillatorBuffer2;
-					gOscillatorBufferWrite = gOscillatorBuffer1;
-				}
-				else {
-					gOscillatorBufferRead = gOscillatorBuffer1;
-					gOscillatorBufferWrite = gOscillatorBuffer2;
-				}
-
-				// New buffer size is whatever finished writing last hop
-				gOscillatorBufferReadCurrentSize = gOscillatorBufferWriteCurrentSize;
-				gOscillatorBufferReadPointer = 0;
-
-				gOscillatorNeedsRender = true;
-				Bela_scheduleAuxiliaryTask(gMediumPriorityRender);
-			}
-		}
-#endif
-	}
-	else
-	{
-		for(unsigned int n = 0; n < context->audioFrames; n++) {
-			context->audioOut[2*n] 	  = context->audioIn[2*n]*audioInStatus;
-			context->audioOut[2*n + 1] = context->audioIn[2*n+1]*audioInStatus;
-
-			filterIn[0][n] = fabs(context->audioIn[2*n]);	// rectify for peak detection in 1
-			filterIn[1][n] = fabs(context->audioIn[2*n+1]);	// rectify for peak detection in 2
-		}
-	}
-
-	// low pass filter audio in 1 and 2 for peak detection
-	ne10_fir_float_neon(&filter[0], filterIn[0], filterOut[0], blockSize);
-	ne10_fir_float_neon(&filter[1], filterIn[1], filterOut[1], blockSize);
-
-	for(unsigned int n = 0; n < context->analogFrames; n++) {
-
-
-		/* Matrix Out 0, In 0
-		 *
-		 * CV loop
-		 * Controls pitch of sound
-		 */
-		float touchPosInt = gSensor0LatestTouchPos;
-		if(touchPosInt < 0) touchPosInt = 0;
-		if(touchPosInt > 1.0) touchPosInt = 1.0;
-		context->analogOut[n*8 + DAC_PIN0] = touchPosInt;
-
-		gPitchLatestInput = context->analogIn[n*8 + ADC_PIN0];
-
-
-		/* Matrix Out 7
-		 *
-		 * Loop feedback with Matrix In 0
-		 * Controls discreet pitch
-		 */
-		float deltaTarget = 0;
-		int semitoneIndex = 0;
-		if(gSensor0LatestTouchNum>0)
-		{
-			// current pitch is gPitchLatestInput, already retrieved
-			semitoneIndex	= ( gPitchLatestInput * 12 * N_OCT  )+0.5;	// closest semitone
-			deltaTarget		= (semitones[semitoneIndex]-gPitchLatestInput);				// delta between pitch and target
-			deltaTouch 		+= deltaTarget*(deltaWeightI);								// update feedback [previous + current]
-		}
-		else
-			deltaTouch = 0;
-
-		float nextOut = touchPosInt  + deltaTarget*deltaWeightP + deltaTouch;			// add feedback to touch -> next out
-		if(nextOut < 0) nextOut = 0;												// clamp
-		if(nextOut > 1.0) nextOut = 1.0;										// clamp
-		context->analogOut[n*8 + DAC_PIN7] = nextOut;										// send next nextOut
-
-
-		/*
-		 * Matrix Out 1, In 1
-		 *
-		 * Hysteresis (comparator) oscillator
-		 * Controls speed of playback
-		 */
-		bool wasRising = gSpeedHysteresisOscillatorRising;
-		context->analogOut[n*8 + DAC_PIN1] = hysteresis_oscillator(context->analogIn[n*8 + ADC_PIN1], 48000.0/65536.0,
-																	16000.0/65536.0, &gSpeedHysteresisOscillatorRising);
-
-		// Find interval of zero crossing
-		if(wasRising && !gSpeedHysteresisOscillatorRising) {
-			int interval = gMatrixSampleCount - gSpeedHysteresisLastTrigger;
-
-			// Interval since last trigger will be the new hop size; calculate to set speed
-			if(interval < 1)
-				interval = 1;
-			//float speed = (float)gOscBanks[gCurrentOscBank]->getHopSize() / (float)interval;
-			float speed = 144.0 / interval;	// Normalise to a fixed expected speed
-			gOscBanks[gCurrentOscBank]->setSpeed(speed);
-
-			gSpeedHysteresisLastTrigger = gMatrixSampleCount;
-		}
-
-		/*
-		 * Matrix Out 2, In 2
-		 *
-		 * Feedback (phase shift) oscillator
-		 * Controls wavetable used for oscillator bank
-		 */
-
-		int tableLength = gFeedbackOscillator.process(context->analogIn[n*8 + ADC_PIN2], &context->analogOut[n*8 + DAC_PIN2]);
-		if(tableLength != 0) {
-			gFeedbackOscillatorTableLength = tableLength;
-			gFeedbackOscillatorTable = gFeedbackOscillator.wavetable();
-			gDynamicWavetableNeedsRender = true;
-			Bela_scheduleAuxiliaryTask(gLowPriorityRender);
-		}
-
-		/*
-		 * Matrix Out 3, In 3
-		 *
-		 * CV loop with delay for time alignment
-		 * Touch positions from sensor 1
-		 * Change every 32 samples (ca. 1.5 ms)
-		 */
-		volatile int touchCount = gSensor1LatestTouchCount;
-		if(touchCount == 0)
-			context->analogOut[n*8 + DAC_PIN3] = 0;
-		else {
-			int touchIndex = (gMatrixSampleCount >> 5) % touchCount;
-			context->analogOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f / 65536.0f;
-			if(touchIndex != gSensor1LastTouchIndex) {
-				// Just changed to a new touch output. Reset the counter.
-				// It will take 2*matrixFrames samples for this output to come back to the
-				// ADC input. But we also want to read near the end of the 32 sample block;
-				// let's say 24 samples into it.
-
-				// FIXME this won't work for p > 2
-				gSensor1InputDelayCounter = 24 + 2*context->analogFrames;
-				gSensor1InputIndex = touchIndex;
-			}
-			gSensor1LastTouchIndex = touchIndex;
-		}
-
-		if(gSensor1InputDelayCounter-- >= 0 && touchCount > 0) {
-			gSensor1MatrixTouchPos[gSensor1InputIndex] = context->analogIn[n*8 + ADC_PIN3];
-		}
-
-		/* Matrix Out 4
-		 *
-		 * Sensor 1 last pos
-		 */
-		touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex];
-		if(touchPosInt < 0) touchPosInt = 0;
-		if(touchPosInt > 1.0) touchPosInt = 1.0;
-		context->analogOut[n*8 + DAC_PIN4] = touchPosInt;
-
-		/* Matrix In 4
-		 *
-		 * Loop points selector
-		 */
-		gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = context->analogIn[n*8 + ADC_PIN4];
-		if(gLoopPointsInputBufferPointer >= gLoopPointsInputBufferSize) {
-			// Find min and max values
-			float loopMax = 0, loopMin = 1.0;
-			for(int i = 0; i < gLoopPointsInputBufferSize; i++) {
-				if(gLoopPointsInputBuffer[i] < loopMin)
-					loopMin = gLoopPointsInputBuffer[i];
-				if(gLoopPointsInputBuffer[i] > loopMax/* && gLoopPointsInputBuffer[i] != 65535*/)
-					loopMax = gLoopPointsInputBuffer[i];
-			}
-
-			if(loopMin >= loopMax)
-				loopMax = loopMin;
-
-			gLoopPointMax = loopMax;
-			gLoopPointMin = loopMin;
-			gLoopPointsInputBufferPointer = 0;
-		}
-
-		/* Matrix Out 5
-		 *
-		 * Audio In 1 peak detection and peak burst output
-		 */
-
-		filterOut[0][n*2+1]	*= filterGain;
-		float burstOut		= PeakBurst[0].getOutput();
-		if( burstOut < 0.1)
-		{
-			if( (prevFiltered[0]>=peakThresh) && (prevFiltered[0]>=filterOut[0][n*2+1]) )
-			{
-				peak[0] = prevFiltered[0];
-				PeakBurst[0].gate(1);
-			}
-		}
-
-		PeakBurst[0].process(1);
-
-		float convAudio = burstOut*peak[0];
-		context->analogOut[n*8 + DAC_PIN5] = convAudio;
-		prevFiltered[0] = filterOut[0][n*2+1];
-		if(prevFiltered[0]>1)
-			prevFiltered[0] = 1;
-
-		/* Matrix In 5
-		 *
-		 * Dissonance, via changing frequency motion of partials
-		 */
-		float amount = (float)context->analogIn[n*8 + ADC_PIN5];
-		gOscBanks[gCurrentOscBank]->freqMovement = 1.0 - amount;
-
-
-
-
-		/* Matrix Out 6
-		 *
-		 * Audio In 2 peak detection and peak burst output
-		 */
-
-		filterOut[1][n*2+1]	*= filterGain;
-		burstOut			= PeakBurst[1].getOutput();
-		if( burstOut < 0.1)
-		{
-			if( (prevFiltered[1]>=peakThresh) && (prevFiltered[1]>=filterOut[1][n*2+1]) )
-			{
-				peak[1] = prevFiltered[1];
-				PeakBurst[1].gate(1);
-			}
-		}
-
-		PeakBurst[1].process(1);
-
-		convAudio = burstOut*peak[1];
-		context->analogOut[n*8 + DAC_PIN6] = convAudio;
-		prevFiltered[1] = filterOut[1][n*2+1];
-		if(prevFiltered[1]>1)
-			prevFiltered[1] = 1;
-
-		/* Matrix In 6
-		 *
-		 * Sound selector
-		 */
-		if(!gIsLoading) {
-			// Use hysteresis to avoid jumping back and forth between sounds
-			if(gOscBanks.size() > 1) {
-				float input = context->analogIn[n*8 + ADC_PIN6];
-				const float hystValue = 16000.0 / 65536.0;
-
-				float upHysteresisValue = ((gCurrentOscBank + 1) + hystValue) / gOscBanks.size();
-				float downHysteresisValue = (gCurrentOscBank - hystValue) / gOscBanks.size();
-
-				if(input > upHysteresisValue || input < downHysteresisValue) {
-					gNextOscBank = input * gOscBanks.size();
-					if(gNextOscBank < 0)
-						gNextOscBank = 0;
-					if((unsigned)gNextOscBank >= gOscBanks.size())
-						gNextOscBank = gOscBanks.size() - 1;
-				}
-			}
-		}
-
-		/*
-		 * Matrix In 7
-		 *
-		 * FSR from primary touch sensor
-		 * Value ranges from 0-1799
-		 */
-		gLastFSRValue = context->analogIn[n*8 + ADC_PIN7] * 1799.0;
-		//gLastFSRValue = 1799 - context->analogIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0);
-		//dbox_printf("%i\n",gLastFSRValue);
-
-		gMatrixSampleCount++;
-	}
-
-#endif /* DBOX_CAPE_TEST */
-}
-
-// Medium-priority render function used for audio hop calculations
-void render_medium_prio()
-{
-
-	if(gOscillatorNeedsRender) {
-		gOscillatorNeedsRender = false;
-
-		/* Render one frame into the write buffer */
-		memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * 2 * sizeof(float)); /* assumes 2 audio channels */
-
-		oscillator_bank_neon(gOscBanks[gCurrentOscBank]->hopCounter, gOscillatorBufferWrite,
-							 gOscBanks[gCurrentOscBank]->actPartNum, gOscBanks[gCurrentOscBank]->lookupTableSize,
-							 gOscBanks[gCurrentOscBank]->oscillatorPhases, gOscBanks[gCurrentOscBank]->oscillatorNormFrequencies,
-							 gOscBanks[gCurrentOscBank]->oscillatorAmplitudes,
-							 gOscBanks[gCurrentOscBank]->oscillatorNormFreqDerivatives,
-							 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
-							 /*gOscBanks[gCurrentOscBank]->lookupTable*/gDynamicWavetable);
-
-		gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * 2;
-
-		/* Update the pitch right before the hop
-		 * Total CV range +/- N_OCT octaves
-		 */
-		float pitch = (float)gPitchLatestInput / octaveSplitter - N_OCT/2;
-		//gOscBanks[gCurrentOscBank]->pitchMultiplier = powf(2.0f, pitch);
-		gOscBanks[gCurrentOscBank]->pitchMultiplier = pow(2.0f, pitch);
-
-#ifdef FIXME_LATER // This doesn't work very well yet
-		gOscBanks[gCurrentOscBank]->filterNum = gSensor1LatestTouchCount;
-		float freqScaler = gOscBanks[gCurrentOscBank]->getFrequencyScaler();
-		for(int i=0; i < gOscBanks[gCurrentOscBank]->filterNum; i++)
-		{
-			// touch pos is linear but freqs are log
-			gOscBanks[gCurrentOscBank]->filterFreqs[i] = ((expf(gSensor1MatrixTouchPos[i]*4)-1)/(expf(4)-1))*gOscBanks[gCurrentOscBank]->filterMaxF*freqScaler;
-			gOscBanks[gCurrentOscBank]->filterQ[i] = gSensor1LatestTouchSizes[i];
-			if(gOscBanks[gCurrentOscBank]->filterFreqs[i]>500*freqScaler)
-				gOscBanks[gCurrentOscBank]->filterPadding[i] = 1+100000*( (gOscBanks[gCurrentOscBank]->filterFreqs[i]-500*freqScaler)/(gOscBanks[gCurrentOscBank]->filterMaxF-500)*freqScaler );
-			else
-				gOscBanks[gCurrentOscBank]->filterPadding[i] = 1;
-		}
-#endif
-
-		RTIME ticks		= rt_timer_read();
-		SRTIME ns		= rt_timer_tsc2ns(ticks);
-		SRTIME delta 	= ns-prevChangeNs;
-
-		// switch to next bank cannot be too frequent, to avoid seg fault! [for example sef fault happens when removing both VDD and GND from breadboard]
-		if(gNextOscBank != gCurrentOscBank && delta>100000000) {
-
-			/*printf("ticks %llu\n", (unsigned long long)ticks);
-			printf("ns %llu\n", (unsigned long long)ns);
-			printf("prevChangeNs %llu\n", (unsigned long long)prevChangeNs);
-			printf("-------------------------->%llud\n", (unsigned long long)(ns-prevChangeNs));*/
-
-			prevChangeNs = ns;
-			dbox_printf("Changing to bank %d...\n", gNextOscBank);
-			if(gOscBanks[gCurrentOscBank]->state==bank_playing){
-				gOscBanks[gCurrentOscBank]->stop();
-			}
-
-			gCurrentOscBank = gNextOscBank;
-			gOscBanks[gCurrentOscBank]->hopNumTh = 0;
-		}
-		else {
-			/* Advance to the next oscillator frame */
-			gOscBanks[gCurrentOscBank]->nextHop();
-		}
-	}
-}
-
-// Lower-priority render function which performs matrix calculations
-// State should be transferred in via global variables
-void render_low_prio()
-{
-	gPRU->setGPIOTestPin();
-	if(gDynamicWavetableNeedsRender) {
-		// Find amplitude of wavetable
-		float meanAmplitude = 0;
-		float sineMix;
-
-		for(int i = 0; i < gFeedbackOscillatorTableLength; i++) {
-			//meanAmplitude += fabsf(gFeedbackOscillatorTable[i]);
-			meanAmplitude += fabs(gFeedbackOscillatorTable[i]);
-		}
-		meanAmplitude /= (float)gFeedbackOscillatorTableLength;
-
-		if(meanAmplitude > 0.35)
-			sineMix = 0;
-		else
-			sineMix = (.35 - meanAmplitude) / .35;
-
-		//dbox_printf("amp %f mix %f\n", meanAmplitude, sineMix);
-
-		// Copy to main wavetable
-		wavetable_interpolate(gFeedbackOscillatorTableLength, gDynamicWavetableLength,
-				gFeedbackOscillatorTable, gDynamicWavetable,
-				gOscBanks[gCurrentOscBank]->lookupTable, sineMix);
-	}
-
-	if(gLoopPointMin >= 60000.0/65536.0 && gLoopPointMax >= 60000.0/65536.0) {
-		// KLUDGE!
-		if(gCurrentOscBank == 0)
-			gOscBanks[gCurrentOscBank]->setLoopHops(50, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.6) - 1);
-		else
-			gOscBanks[gCurrentOscBank]->setLoopHops(5, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.7) - 1);
-	}
-	else {
-		float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop();
-		float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop();
-
-		int intLoopPointMin = normLoopPointMin;
-		if(intLoopPointMin < 1)
-			intLoopPointMin = 1;
-		int intLoopPointMax = normLoopPointMax;
-		if(intLoopPointMax <= intLoopPointMin)
-			intLoopPointMax = intLoopPointMin + 1;
-		if(intLoopPointMax > gOscBanks[gCurrentOscBank]->getLastHop() - 1)
-			intLoopPointMax =  gOscBanks[gCurrentOscBank]->getLastHop() - 1;
-
-		//dbox_printf("Loop points %d-%d / %d-%d\n", gLoopPointMin, gLoopPointMax, intLoopPointMin, intLoopPointMax);
-
-		/* WORKS, jsut need to fix the glitch when jumps!
-		 * *int currentHop = gOscBanks[gCurrentOscBank]->getCurrentHop();
-		if(currentHop < intLoopPointMin -1 )
-			gOscBanks[gCurrentOscBank]->setJumpHop(intLoopPointMin + 1);
-		else if(currentHop > intLoopPointMax + 1)
-			gOscBanks[gCurrentOscBank]->setJumpHop(intLoopPointMax - 1);*/
-		gOscBanks[gCurrentOscBank]->setLoopHops(intLoopPointMin, intLoopPointMax);
-	}
-
-	if(gIsLoading)
-		gStatusLED.blink(25, 75);	// Blink quickly until load finished
-	else
-		gStatusLED.blink(250 / gOscBanks[gCurrentOscBank]->getSpeed(), 250 / gOscBanks[gCurrentOscBank]->getSpeed());
-	gPRU->clearGPIOTestPin();
-
-//	static int counter = 32;
-//	if(--counter == 0) {
-//		for(int i = 0; i < gLoopPointsInputBufferSize; i++) {
-//			dbox_printf("%d ", gLoopPointsInputBuffer[i]);
-//			if(i % 32 == 31)
-//				dbox_printf("\n");
-//		}
-//		dbox_printf("\n\n");
-//		counter = 32;
-//	}
-
-	//dbox_printf("min %d max %d\n", gLoopPointMin, gLoopPointMax);
-}
-
-// Clean up at the end of render
-void cleanup(BelaContext *context, void *userData)
-{
-	free(gOscillatorBuffer1);
-	free(gOscillatorBuffer2);
-	free(gDynamicWavetable);
-}
-
-// Interpolate one wavetable into another. The output size
-// does not include the guard point at the end which will be identical
-// to the first point
-void wavetable_interpolate(int numSamplesIn, int numSamplesOut,
-                           float *tableIn, float *tableOut,
-                           float *sineTable, float sineMix)
-{
-	float fractionalScaler = (float)numSamplesIn / (float)numSamplesOut;
-
-	for(int k = 0; k < numSamplesOut; k++) {
-		float fractionalIndex = (float) k * fractionalScaler;
-		//int sB = (int)floorf(fractionalIndex);
-		int sB = (int)floor(fractionalIndex);
-		int sA = sB + 1;
-		if(sA >= numSamplesIn)
-			sA = 0;
-		float fraction = fractionalIndex - sB;
-		tableOut[k] = fraction * tableIn[sA] + (1.0f - fraction) * tableIn[sB];
-		tableOut[k] = sineMix * sineTable[k] + (1.0 - sineMix) * tableOut[k];
-	}
-
-	tableOut[numSamplesOut] = tableOut[0];
-}
-
-// Create a hysteresis oscillator with a matrix input and output
-inline float hysteresis_oscillator(float input, float risingThreshold, float fallingThreshold, bool *rising)
-{
-	float value;
-
-	if(*rising) {
-		if(input > risingThreshold) {
-			*rising = false;
-			value = 0;
-		}
-		else
-			value = 1.0;
-	}
-	else {
-		if(input < fallingThreshold) {
-			*rising = true;
-			value = 1.0;
-		}
-		else
-			value = 0;
-	}
-
-	return value;
-}
-
-#ifdef DBOX_CAPE_TEST
-// Test the functionality of the D-Box cape by checking each input and output
-// Loopback cable from ADC to DAC needed
-void render_capetest(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
-			uint16_t *matrixIn, uint16_t *matrixOut)
-{
-	static float phase = 0.0;
-	static int sampleCounter = 0;
-	static int invertChannel = 0;
-
-	// Play a sine wave on the audio output
-	for(int n = 0; n < numAudioFrames; n++) {
-		audioOut[2*n] = audioOut[2*n + 1] = 0.5*sinf(phase);
-		phase += 2.0 * M_PI * 440.0 / 44100.0;
-		if(phase >= 2.0 * M_PI)
-			phase -= 2.0 * M_PI;
-	}
-
-	for(int n = 0; n < numMatrixFrames; n++) {
-		// Change outputs every 512 samples
-		if(sampleCounter < 512) {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel)
-					matrixOut[n*8 + k] = 50000;
-				else
-					matrixOut[n*8 + k] = 0;
-			}
-		}
-		else {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel)
-					matrixOut[n*8 + k] = 0;
-				else
-					matrixOut[n*8 + k] = 50000;
-			}
-		}
-
-		// Read after 256 samples: input should be low
-		if(sampleCounter == 256) {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel) {
-					if(matrixIn[n*8 + k] < 50000) {
-						dbox_printf("FAIL channel %d -- output HIGH input %d (inverted)\n", k, matrixIn[n*8 + k]);
-					}
-				}
-				else {
-					if(matrixIn[n*8 + k] > 2048) {
-						dbox_printf("FAIL channel %d -- output LOW input %d\n", k, matrixIn[n*8 + k]);
-					}
-				}
-			}
-		}
-		else if(sampleCounter == 768) {
-			for(int k = 0; k < 8; k++) {
-				if(k == invertChannel) {
-					if(matrixIn[n*8 + k] > 2048) {
-						dbox_printf("FAIL channel %d -- output LOW input %d (inverted)\n", k, matrixIn[n*8 + k]);
-					}
-				}
-				else {
-					if(matrixIn[n*8 + k] < 50000) {
-						dbox_printf("FAIL channel %d -- output HIGH input %d\n", k, matrixIn[n*8 + k]);
-					}
-				}
-			}
-		}
-
-		if(++sampleCounter >= 1024) {
-			sampleCounter = 0;
-			invertChannel++;
-			if(invertChannel >= 8)
-				invertChannel = 0;
-		}
-	}
-}
-#endif
-
-
--- a/examples/d-box/sensors.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,642 +0,0 @@
-/*
- * sensors.cpp
- *
- *  Created on: May 28, 2014
- *      Author: Victor Zappi
- */
-
-#include <stdio.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <math.h>
-#include <vector>
-#include "prio.h"
-#include "sensors.h"
-#include "OscillatorBank.h"
-#include "DboxSensors.h"
-
-
-//----------------------------------------
-// main extern variables
-//----------------------------------------
-extern vector<OscillatorBank*> gOscBanks;
-extern int gCurrentOscBank;
-extern int gNextOscBank;
-extern int gShouldStop;
-extern int gVerbose;
-
-float gSensor0LatestTouchPos = 0;	// most recent pitch touch location [0-1] on sensor 0, used by render.cpp
-int gSensor0LatestTouchNum	 = 0;	// most recent num of touches on sensor 0, used by render.cpp
-float gSensor1LatestTouchPos[5];	// most recent touche locations on sensor 1, used by render.cpp
-//float gSensor1LatestTouchSizes[5];
-int gSensor1LatestTouchCount;		// most recent number touches on sensor 1, used by render.cpp
-int gSensor1LatestTouchIndex = 0;	// index of last touch in gSensor1LatestTouchPos[5], used by render.cpp
-int gLastFSRValue = 1799;			// most recent fsr value, used by render.cpp
-
-
-DboxSensors Sensors;
-
-
-//----------------------------------------
-// var shared with logger
-//----------------------------------------
-int s0TouchNum	 	= 0;
-float s0Touches_[MAX_TOUCHES];
-float s0Size_[MAX_TOUCHES];
-int s0LastIndex;
-
-int s1TouchNum	 	= 0;
-float s1Touches_[MAX_TOUCHES];
-float s1Size_[MAX_TOUCHES];
-int s1LastIndex;
-
-int fsr				= 1799;
-
-
-
-using namespace std;
-
-int initSensorLoop(int sensorAddress0, int sensorAddress1, int sensorType)
-{
-	int tk0_bus			= 1;
-	int tk0_address		= sensorAddress0;
-	int tk1_bus			= 1;
-	int tk1_address		= sensorAddress1;
-	int tk_file			= 0;
-	int fsr_max			= 1799;
-	int fsr_pinNum		= 4;
-
-	if(gVerbose==1)
-		cout << "---------------->Init Control Thread" << endl;
-
-	if(Sensors.initSensors(tk0_bus, tk0_address, tk1_bus, tk1_address, tk_file, fsr_pinNum, fsr_max, sensorType)>0)
-	{
-		gShouldStop = 1;
-		cout << "control cannot start" << endl;
-		return -1;
-	}
-
-	for(int i=0; i<MAX_TOUCHES; i++)
-	{
-		s0Touches_[i]	= 0.0;
-		s0Size_[i]		= 0.0;
-
-		s1Touches_[i]	= 0.0;
-		s1Size_[i]	= 0.0;
-	}
-
-	return 0;
-}
-
-void sensorLoop(void *)
-{
-	timeval start, end;
-	unsigned long elapsedTime;
-	//float touchSize		= 0;	// once used for timbre
-
-
-
-	float *s0Touches;
-	float *s0Size;
-	int s0PrevTouchNum 	= 0;
-	int s0SortedTouchIndices[MAX_TOUCHES];
-	float s0SortedTouches[MAX_TOUCHES];
-	float s0PrevSortedTouches[MAX_TOUCHES];
-
-	float *s1Touches;
-	float *s1Size;
-	int s1PrevTouchNum 	= 0;
-	int s1SortedTouchIndices[MAX_TOUCHES];
-	float s1SortedTouches[MAX_TOUCHES];
-	float s1PrevSortedTouches[MAX_TOUCHES];
-
-	float freqScaler	= 0;
-	int fsrMin			= 0;//50; // was 200
-	int fsrMax			= 1799;//1300; // was 800
-	float vel			= 0;
-	float prevVel		= 0;
-	float filterMaxF	= 0;
-	if(gVerbose==1)
-		dbox_printf("__________set Control Thread priority\n");
-
-	if(gVerbose==1)
-		dbox_printf("_________________Control Thread!\n");
-
-	// get freq scaler, cos freqs must be scaled according to the wavetable used in the oscillator bank
-	freqScaler 		= gOscBanks[gCurrentOscBank]->getFrequencyScaler();
-	filterMaxF		= gOscBanks[gCurrentOscBank]->filterMaxF;
-
-	// init time vals
-	gettimeofday(&start, NULL);
-
-	// here we go, sensor loop until the end of the application
-	while(!gShouldStop)
-	{
-		gettimeofday(&end, NULL);
-		elapsedTime = ( (end.tv_sec*1000000+end.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
-		if( elapsedTime<4000 )
-			usleep(4000-elapsedTime);
-		else
-			dbox_printf("%d\n", (int)elapsedTime); // this print happens when something's gone bad...
-
-		if(Sensors.readSensors()==0)
-		{
-			s0TouchNum	= Sensors.getTKTouchCount(0);
-			s0Touches	= Sensors.getTKXPositions(0);
-			s0Size 		= Sensors.getTKTouchSize(0);
-
-			s1TouchNum	= Sensors.getTKTouchCount(1);
-			s1Touches	= Sensors.getTKXPositions(1);
-			s1Size 		= Sensors.getTKTouchSize(1);
-
-			for(int i=0; i<MAX_TOUCHES; i++)
-			{
-				s0Touches_[i]	= s0Touches[i];
-				s0Size_[i]		= s0Size[i];
-
-				s1Touches_[i]	= s1Touches[i];
-				s1Size_[i]		= s1Size[i];
-			}
-
-			gSensor0LatestTouchNum	= s0TouchNum;
-			if(s0TouchNum > 0)
-			{
-				//-----------------------------------------------------------------------------------
-				// timbre, speed and  pitch
-				//touchSize	 = 0;	\\ once used for timbre
-
-				// if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison]
-				if(s0PrevTouchNum!=s0TouchNum)
-				{
-					float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches
-					int ids[MAX_TOUCHES*(MAX_TOUCHES-1)];
-					// calculate all distance permutations between previous and current touches
-					for(int i=0; i<s0TouchNum; i++)
-					{
-						for(int p=0; p<s0PrevTouchNum; p++)
-						{
-							int index			= i*s0PrevTouchNum+p;	// permutation id [says between which touches we are calculating distance]
-							distances[index]	= fabs(s0Touches[i]-s0PrevSortedTouches[p]);
-							ids[index]			= index;
-							if(index>0)
-							{
-								// sort, from min to max distance
-								float tmp;
-								while(distances[index]<distances[index-1])
-								{
-									tmp				= ids[index-1];
-									ids[index-1]	= ids[index];
-									ids[index]		= tmp;
-
-									tmp				= distances[index-1];
-									distances[index-1] = distances[index];
-									distances[index] = tmp;
-
-									index--;
-
-									if(index == 0)
-										break;
-								}
-							}
-						}
-					}
-
-					int sorted = 0;
-					bool currAssigned[MAX_TOUCHES] = {false};
-					bool prevAssigned[MAX_TOUCHES] = {false};
-
-					// track touches assigning index according to shortest distance
-					for(int i=0; i<s0TouchNum*s0PrevTouchNum; i++)
-					{
-						int currentIndex	= ids[i]/s0PrevTouchNum;
-						int prevIndex		= ids[i]%s0PrevTouchNum;
-						// avoid double assignment
-						if(!currAssigned[currentIndex] && !prevAssigned[prevIndex])
-						{
-							currAssigned[currentIndex]	= true;
-							prevAssigned[prevIndex]		= true;
-							s0SortedTouchIndices[currentIndex] = prevIndex;
-							sorted++;
-						}
-					}
-					// we still have to assign a free index to new touches
-					if(s0PrevTouchNum<s0TouchNum)
-					{
-						for(int i=0; i<s0TouchNum; i++)
-						{
-							if(!currAssigned[i])
-								s0SortedTouchIndices[i] = sorted++; // assign next free index
-
-							// update tracked value
-							s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
-							s0PrevSortedTouches[i]			         = s0SortedTouches[i];
-							if(s0SortedTouchIndices[i]==s0TouchNum-1)
-								s0LastIndex = i;
-
-							// accumulate sizes for timbre
-							//touchSize += s0Size[i];
-						}
-					}
-					else // some touches have disappeared...
-					{
-						// ...we have to shift all indices...
-						for(int i=s0PrevTouchNum-1; i>=0; i--)
-						{
-							if(!prevAssigned[i])
-							{
-								for(int j=0; j<s0TouchNum; j++)
-								{
-									// ...only if touches that disappeared were before the current one
-									if(s0SortedTouchIndices[j]>i)
-										s0SortedTouchIndices[j]--;
-								}
-							}
-						}
-						// done! now update
-						for(int i=0; i<s0TouchNum; i++)
-						{
-							// update tracked value
-							s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
-							s0PrevSortedTouches[i]			         = s0SortedTouches[i];
-							if(s0SortedTouchIndices[i]==s0TouchNum-1)
-								s0LastIndex = i;
-
-							// accumulate sizes for timbre
-							//touchSize += s0Size[i];
-						}
-					}
-				}
-				else // nothing's changed since last round
-				{
-					for(int i=0; i<s0TouchNum; i++)
-					{
-						// update tracked value
-						s0SortedTouches[s0SortedTouchIndices[i]] = s0Touches[i];
-						s0PrevSortedTouches[i]			         = s0SortedTouches[i];
-
-						// accumulate sizes for timbre
-						//touchSize += s0Size[i];
-					}
-				}
-
-				if(s0TouchNum == 0)
-					s0LastIndex = -1;
-
-				// timbre
-				//touchSize = (touchSize > 0.7) ? 1 : touchSize/0.7;
-				//gOscBanks[gCurrentOscBank]->hopNumTh = log((1-touchSize)+1)/log(2)*20000;
-				//gOscBanks[gCurrentOscBank]->hopNumTh = 0;
-
-
-				// pitch, controlled by last touch
-				//prevTouchPos 				= touch[touchIndex];
-				//touchPos	 			 	= (s0SortedTouches[s0TouchNum-1]-0.5)/0.5;	// from [0,1] to [-1,1]
-				gSensor0LatestTouchPos      = s0SortedTouches[s0TouchNum-1];
-				//touchPos					= s0Touches[0];
-				//gOscBanks[gCurrentOscBank]->pitchMultiplier 	= pow(2, touchPos);
-				//-----------------------------------------------------------------------------------
-
-
-
-				//-----------------------------------------------------------------------------------
-				// note on
-				//if(s0PrevTouchNum == 0)
-				//	gOscBanks[gCurrentOscBank]->play();
-				// fsr = Sensors.getFSRVAlue();
-				fsr = gLastFSRValue;
-				//dbox_printf("fsr: %d\n", fsr);
-				if(!gOscBanks[gCurrentOscBank]->note)
-				{
-					vel = fsr;
-					vel /= (float)(fsrMax-fsrMin);
-
-					vel = 1-vel;
-					dbox_printf("Attack vel: %f\n", vel);
-					gOscBanks[gCurrentOscBank]->play(vel);
-					prevVel = vel;
-				}
-				else if(gOscBanks[gCurrentOscBank]->getEnvelopeState() != env_release)
-				{
-					fsr = (fsr > fsrMax) ? fsrMax : fsr;
-					vel = (fsr < fsrMin) ? fsrMin : fsr;
-					vel -= fsrMin;
-					vel /= (float)(fsrMax-fsrMin);
-					vel = 1-vel;
-					if(vel > prevVel)
-					{
-						gOscBanks[gCurrentOscBank]->afterTouch(vel);
-						prevVel = vel;
-					}
-				}
-				//-----------------------------------------------------------------------------------
-			}
-			else
-			{
-				//prevFsr = 1799;
-				//prevTouchPos = -1;
-				//-----------------------------------------------------------------------------------
-				// note off
-				if(s0PrevTouchNum > 0)
-				{
-					if(gOscBanks[gCurrentOscBank]->state==bank_playing)
-						gOscBanks[gCurrentOscBank]->stop();
-				}
-				//-----------------------------------------------------------------------------------
-			}
-
-
-
-			// sensor 2
-			//-----------------------------------------------------------------------------------
-			//filter - calculated even when no touches on first sensor, to filter also release tail
-			gOscBanks[gCurrentOscBank]->filterNum	= s1TouchNum;
-
-			gSensor1LatestTouchCount = gOscBanks[gCurrentOscBank]->filterNum;
-			for(int i = 0; i < gSensor1LatestTouchCount; i++) {
-				gSensor1LatestTouchPos[i] = s1Touches[i];
-				//gSensor1LatestTouchSizes[i] = s1Size[i];
-			}
-
-/*			for(int i=0; i<gOscBanks[gCurrentOscBank]->filterNum; i++)
-			{
-				// touch pos is linear but freqs are log
-				gOscBanks[gCurrentOscBank]->filterFreqs[i] = ((exp(s0Touches[i]*4)-1)/(exp(4)-1))*filterMaxF*freqScaler;
-				//gOscBanks[gCurrentOscBank]->filterQ[i] = size[i]*5*(1+touch[i]*1000)*freqScaler;
-				gOscBanks[gCurrentOscBank]->filterQ[i] = s0Size[i];
-				if(gOscBanks[gCurrentOscBank]->filterFreqs[i]>500*freqScaler)
-					gOscBanks[gCurrentOscBank]->filterPadding[i] = 1+100000*( (gOscBanks[gCurrentOscBank]->filterFreqs[i]-500*freqScaler)/(filterMaxF-500)*freqScaler );
-				else
-					gOscBanks[gCurrentOscBank]->filterPadding[i] = 1;
-			}*/
-
-			// each touch on sensor 2 is a notch filter, whose Q is determined by touch size
-			for(int i=0; i<gOscBanks[gCurrentOscBank]->filterNum; i++)
-			{
-				// map touch pos [which is linear] on freqs exponentially
-				float freq = ((exp(s1Touches[i]*4)-1)/EXP_DENOM)*filterMaxF;
-				gOscBanks[gCurrentOscBank]->filterFreqs[i] = freq*freqScaler;
-				// also size is mapped exponentially on Q
-				float siz = (exp(s1Size[i])-1)/1.71828;
-				gOscBanks[gCurrentOscBank]->filterQ[i] = siz*( (filterMaxF-freq)/filterMaxF * 0.9 + 0.1 );	// size weight on Q decreases with frequency
-			}
-			//-----------------------------------------------------------------------------------
-
-
-
-			//-----------------------------------------------------------------------------------
-			// sort touches on sensor 2
-			if(s1TouchNum > 0)
-			{
-				// if we have a number of touches different from previous round, track their order of arrival [calculated using distance comparison]
-				if(s1PrevTouchNum!=s1TouchNum)
-				{
-					float distances[MAX_TOUCHES*(MAX_TOUCHES-1)]; // maximum number of current+previous touches between rounds with different num of touches
-					int ids[MAX_TOUCHES*(MAX_TOUCHES-1)];
-					// calculate all distance permutations between previous and current touches
-					for(int i=0; i<s1TouchNum; i++)
-					{
-						for(int p=0; p<s1PrevTouchNum; p++)
-						{
-							int index 			= i*s1PrevTouchNum+p;	// permutation id [says between which touches we are calculating distance]
-							distances[index]	= fabs(s1Touches[i]-s1PrevSortedTouches[p]);
-							ids[index]			= index;
-							if(index>0)
-							{
-								// sort, from min to max distance
-								float tmp;
-								while(distances[index]<distances[index-1])
-								{
-									tmp 				= ids[index-1];
-									ids[index-1] 		= ids[index];
-									ids[index] 			= tmp;
-
-									tmp					= distances[index-1];
-									distances[index-1]	= distances[index];
-									distances[index] 	= tmp;
-
-									index--;
-
-									if(index == 0)
-										break;
-								}
-							}
-						}
-					}
-
-					int sorted = 0;
-					bool currAssigned[MAX_TOUCHES] = {false};
-					bool prevAssigned[MAX_TOUCHES] = {false};
-
-					// track touches assigning index according to shortest distance
-					for(int i=0; i<s1TouchNum*s1PrevTouchNum; i++)
-					{
-						int currentIndex	= ids[i]/s1PrevTouchNum;
-						int prevIndex		= ids[i]%s1PrevTouchNum;
-						// avoid double assignment
-						if(!currAssigned[currentIndex] && !prevAssigned[prevIndex])
-						{
-							currAssigned[currentIndex]			= true;
-							prevAssigned[prevIndex]				= true;
-							s1SortedTouchIndices[currentIndex] = prevIndex;
-							sorted++;
-						}
-					}
-					// we still have to assign a free index to new touches
-					if(s1PrevTouchNum<s1TouchNum)
-					{
-						for(int i=0; i<s1TouchNum; i++)
-						{
-							if(!currAssigned[i])
-								s1SortedTouchIndices[i] = sorted++; // assign next free index
-
-							// update tracked value
-							s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
-							s1PrevSortedTouches[i]			       	 = s1SortedTouches[i];
-							if(s1SortedTouchIndices[i]==s1TouchNum-1)
-								s1LastIndex = i;
-						}
-					}
-					else // some touches have disappeared...
-					{
-						// ...we have to shift all indices...
-						for(int i=s1PrevTouchNum-1; i>=0; i--)
-						{
-							if(!prevAssigned[i])
-							{
-								for(int j=0; j<s1TouchNum; j++)
-								{
-									// ...only if touches that disappeared were before the current one
-									if(s1SortedTouchIndices[j]>i)
-										s1SortedTouchIndices[j]--;
-								}
-							}
-						}
-						// done! now update
-						for(int i=0; i<s1TouchNum; i++)
-						{
-							// update tracked value
-							s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
-							s1PrevSortedTouches[i]			       	 = s1SortedTouches[i];
-							if(s1SortedTouchIndices[i]==s1TouchNum-1)
-								s1LastIndex = i;
-						}
-					}
-				}
-				else // nothing's changed since last round
-				{
-					for(int i=0; i<s1TouchNum; i++)
-					{
-						// update tracked value
-						s1SortedTouches[s1SortedTouchIndices[i]] = s1Touches[i];
-						s1PrevSortedTouches[i]			       	 = s1SortedTouches[i];
-					}
-				}
-			}
-
-			if(s1TouchNum > 0)
-			{
-				gSensor1LatestTouchIndex = s1LastIndex;
-			}
-			else
-				s1LastIndex = -1;
-
-/*			dbox_printf("-----------------------------\nnum: %d, latest: %d\n", s1TouchNum, gSensor1LatestTouchIndex);
-			for(int i=0; i<s1TouchNum; i++)
-				dbox_printf("\t%f\n", gSensor1LatestTouchPos[i]);
-			dbox_printf("------\n");
-			for(int i=0; i<s1TouchNum; i++)
-				dbox_printf("\t%f\n", s1SortedTouches[i]);*/
-
-
-
-			// update variables for both sensors
-			s0PrevTouchNum	= s0TouchNum;
-			s1PrevTouchNum	= s1TouchNum;
-		}
-		else
-			dbox_printf("Come on instrument!\n");	//break
-
-		gettimeofday(&start, NULL);
-	}
-
-	dbox_printf("sensor thread ended\n");
-}
-
-void *keyboardLoop(void *)
-{
-	if(gVerbose==1)
-		cout << "_________________Keyboard Control Thread!" << endl;
-
-	char keyStroke = '.';
-	cout << "Press q to quit." << endl;
-
-	float speed;
-
-	do
-	{
-		keyStroke =	getchar();
-		while(getchar()!='\n'); // to read the first stroke
-
-		switch (keyStroke)
-		{
-			//----------------------------------------------------------------------------
-			case 'a':
-				gOscBanks[gCurrentOscBank]->hopNumTh = 0;
-				gOscBanks[gCurrentOscBank]->play(1);
-				//cout << "Note on" << endl;
-				break;
-			case 's':
-				if(gOscBanks[gCurrentOscBank]->state==bank_playing)
-				{
-					gOscBanks[gCurrentOscBank]->stop();
-					//cout << "Note off" << endl;
-				}
-				break;
-			//----------------------------------------------------------------------------
-			case '[':
-				gOscBanks[gCurrentOscBank]->freqMovement-=0.05;
-				if(gOscBanks[gCurrentOscBank]->freqMovement<0)
-					gOscBanks[gCurrentOscBank]->freqMovement = 0;
-				//cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl;
-				break;
-			case ']':
-				gOscBanks[gCurrentOscBank]->freqMovement+=0.05;
-				if(gOscBanks[gCurrentOscBank]->freqMovement>1)
-					gOscBanks[gCurrentOscBank]->freqMovement = 1;
-				//cout << "gOscBanks[gCurrentOscBank]->FreqMov: " << gOscBanks[gCurrentOscBank]->freqMovement << endl;
-				break;
-			//----------------------------------------------------------------------------
-			case '<':
-				speed = gOscBanks[gCurrentOscBank]->getSpeed() - 0.1 ;
-				gOscBanks[gCurrentOscBank]->setSpeed(speed);
-				dbox_printf("Speed: %f\n", speed);
-
-				break;
-			case '>':
-				speed = gOscBanks[gCurrentOscBank]->getSpeed() + 0.1 ;
-				gOscBanks[gCurrentOscBank]->setSpeed(speed);
-				dbox_printf("Speed: %f\n", speed);
-				break;
-			case '0':
-				speed = 0.1;
-				gOscBanks[gCurrentOscBank]->setSpeed(speed);
-				dbox_printf("Speed: %f\n", speed);
-				break;
-			case '1':
-				speed = 0.5;
-				gOscBanks[gCurrentOscBank]->setSpeed(speed);
-				dbox_printf("Speed: %f\n", speed);
-				break;
-			case '2':
-				speed = 1;
-				gOscBanks[gCurrentOscBank]->setSpeed(speed);
-				dbox_printf("Speed: %f\n", speed);
-				break;
-			case '3':
-				speed = 2;
-				gOscBanks[gCurrentOscBank]->setSpeed(speed);
-				dbox_printf("Speed: %f\n", speed);
-				break;
-			case '4':
-				speed = 3;
-				gOscBanks[gCurrentOscBank]->setSpeed(speed);
-				dbox_printf("Speed: %f\n", speed);
-				break;
-			//----------------------------------------------------------------------------
-			case 'z':
-				gOscBanks[gCurrentOscBank]->setJumpHop(0);
-				break;
-			case 'x':
-				gOscBanks[gCurrentOscBank]->setJumpHop(100);
-				break;
-			case 'c':
-				gOscBanks[gCurrentOscBank]->setJumpHop(600);
-				break;
-			case 'v':
-				gOscBanks[gCurrentOscBank]->setJumpHop(1100);
-				break;
-			case 'b':
-				gOscBanks[gCurrentOscBank]->setJumpHop(2000);
-				break;
-			case 'n':
-				gOscBanks[gCurrentOscBank]->setJumpHop(gOscBanks[gCurrentOscBank]->getLastHop());
-				break;
-			//----------------------------------------------------------------------------
-			case 'q':
-				gShouldStop = true;
-				break;
-			case 'o':
-				gNextOscBank = (gCurrentOscBank + 1) % gOscBanks.size();
-				break;
-			default:
-				break;
-			//----------------------------------------------------------------------------
-		}
-		usleep(1000); /* Wait 1ms to avoid checking too quickly */
-	}
-	while (keyStroke!='q');
-
-	cout << "keyboard thread ended" << endl;
-
-	return (void *)0;
-}
--- a/examples/d-box/sensors.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/*
- * sensors.h
- *
- *  Created on: May 28, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef SENSORS_H_
-#define SENSORS_H_
-
-#include "config.h"
-
-int initSensorLoop(int sensorAddress0, int sensorAddress1, int sensorType);
-
-void sensorLoop(void *);
-void *keyboardLoop(void *);
-
-
-#endif /* SENSORS_H_ */
--- a/examples/d-box/spear_parser.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,641 +0,0 @@
-/*
- * spear_parser.cpp v1.2
- *
- *  Created on: May 6, 2014
- *      Author: Victor Zappi
- */
-
-#include "spear_parser.h"
-
-using namespace std;
-
-//#define DO_CHECKS
-
-//------------------------------------------------------------------------------------------------
-// partials
-//------------------------------------------------------------------------------------------------
-
-Partials::Partials()
-{
-	partialFrequencies	= NULL;
-//	partialAmplitudes	= NULL;
-//	partialNumFrames	= NULL;
-//	partialStartSample	= NULL;
-//	partialEndSample	= NULL;
-//	partialCurrentFrame	= NULL;
-//	partialFreqDelta	= NULL;
-//	partialAmpDelta	= NULL;
-
-
-	activePartialNum	= NULL;
-//	activePartials		= NULL;
-
-	currentSample = -1;
-}
-
-Partials::~Partials()
-{
-	if(partialFrequencies != NULL)			// check on one is enough
-	{
-		if(partialFrequencies[0] != NULL)	// check on one is enough
-		{
-			for(unsigned int i=0; i<parNum; i++)
-			{
-				delete[] partialFrequencies[i];
-				delete[] partialAmplitudes[i];
-				delete[] partialFreqDelta[i];
-				delete[] partialAmpDelta[i];
-
-			}
-		}
-
-		delete[] partialFrequencies;
-		delete[] partialAmplitudes;
-		delete[] partialNumFrames;
-		delete[] partialFreqDelta;
-		delete[] partialAmpDelta;
-		delete[] partialFreqMean;
-	}
-
-	if(activePartialNum != NULL)
-	{
-		for(unsigned int i=0; i<hopNum+1; i++)
-			delete[] activePartials[i];
-
-		delete[] activePartialNum;
-		delete[] activePartials ;
-	}
-}
-
-void Partials::init(int parN, int hopS, bool isDBX)
-{
-	if(!isDBX)
-	{
-		parNum	= parN;
-		hopSize	= hopS;
-
-		partialFrequencies	= new float *[parNum];
-		partialAmplitudes	= new float *[parNum];
-		partialNumFrames	= new unsigned int[parNum];
-		partialStartFrame	= new unsigned int[parNum];
-		partialStartSample	= new unsigned int[parNum];
-		partialEndSample	= new unsigned int[parNum];
-		partialFreqDelta	= new float *[parNum];
-		partialAmpDelta		= new float *[parNum];
-		partialFreqMean		= new float[parNum];
-
-
-
-		// init in one shot
-		fill(partialFreqMean, partialFreqMean+parNum, 0);			// mean is zero
-
-		partialFrequencies[0] 	= NULL;								// for free check
-	}
-	else
-	{
-		parNum	= parN;
-		hopSize	= hopS;
-
-		partialFrequencies	= new float *[parNum];
-		partialAmplitudes	= new float *[parNum];
-		partialNumFrames	= new unsigned int[parNum];
-		partialStartFrame	= new unsigned int[parNum];
-		partialFreqDelta	= new float *[parNum];
-		partialAmpDelta		= new float *[parNum];
-		partialFreqMean		= new float[parNum];
-
-		partialFrequencies[0] 	= NULL;								// for free check
-	}
-}
-
-
-
-void Partials::update(int parIndex, int frameNum)
-{
-	partialFrequencies[parIndex] = new float[frameNum];
-	partialAmplitudes[parIndex]	 = new float[frameNum];
-	partialFreqDelta[parIndex]	 = new float[frameNum];
-	partialAmpDelta[parIndex]	 = new float[frameNum];
-
-	fill(partialFreqDelta[parIndex], partialFreqDelta[parIndex]+frameNum, 99999.0);	// in the end, only the last one will have 99999
-	fill(partialAmpDelta[parIndex], partialAmpDelta[parIndex]+frameNum, 99999.0);	// in the end, only the last one will have 99999
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//------------------------------------------------------------------------------------------------
-// spear parser
-//------------------------------------------------------------------------------------------------
-Spear_parser::Spear_parser()
-{
-	// some default values
-	hopSize			= -1;
-	fileSampleRate	= -1;
-}
-
-Spear_parser::~Spear_parser()
-{
-}
-
-void Spear_parser::calculateHopSize(char *filename)
-{
-	int index 		= 0;
-	bool prevWas_ 	= false;
-	bool found_h	= false;
-	int n 			= 0;
-
-	hopSize 		= 0;
-
-	do
-	{
-		// check if '_'
-		if(filename[index] == '_')
-			prevWas_ = true;
-		else if( (filename[index] == 'h') && prevWas_) // if it is not, but it is 'h' and previous was '_', found "_h"!
-		{
-			found_h = true;
-			while(filename[index] != '\0')
-			{
-				index++;
-				if( (filename[index] == '.') || (filename[index] == '_'))
-					break;
-				else // i am not checking if char are digits...!
-				{
-					n = filename[index];
-					hopSize =  hopSize*10+(n-48);
-				}
-			}
-		}
-		else	// else, nothing
-			prevWas_ = false;
-		index++;
-	}
-	while( (filename[index] != '\0') && !found_h );
-
-	if( !found_h || (hopSize<1) )
-		hopSize = 551;	// default val
-
-}
-
-
-bool Spear_parser::parser(char *filename, int hopsize, int samplerate)
-{
-	string name = string(filename);
-	int len		= name.length();
-	// invoke correct parser according to the type of file...just checking the extension, crude but functional
-	if( (name[len-4]=='.') && (name[len-3]=='d') && (name[len-2]=='b') && (name[len-1]=='x') )
-		return DBXparser(filename, samplerate);				// .dbox
-	else
-		return TXTparser(filename, hopSize, samplerate);	// .txt, or whatever
-}
-
-
-bool Spear_parser::DBXparser(char *filename, int samplerate)
-{
-	fileSampleRate 	= samplerate;
-
-	// working vars
-	int parNum		= 0;	// total num of partials
-	int hopNum		= 0;	// total num of hops
-
-	//----------------------------------------------------------------------------------------
-	// open a file
-	ifstream fin;
-	fin.open(filename, ios::in | ios::binary);
-	if (!fin.good())
-	{
-		cout << "Parser Error: file not found" << endl;	// exit if file not found
-		return false;
-	}
-
-	gettimeofday(&start, NULL);
-	//----------------------------------------------------------------------------------------
-	// general data
-
-	// look for partial count
-	fin.read((char *) &parNum, sizeof(int));
-	partials.parNum 		= parNum;
-
-	// look for hop count
-	fin.read((char *) &hopNum, sizeof(int));
-	partials.setHopNum(hopNum);
-
-	// look for hop size
-	fin.read((char *) &hopSize, sizeof(int));
-	partials.hopSize 		= hopSize;		// it's handy for both classes to know it
-
-	// init partials data structure
-	partials.init(parNum, hopSize, true);
-
-	// look for max active par num
-	fin.read((char *) &(partials.maxActiveParNum), sizeof(int));
-
-
-
-	// partial data
-
-	// start frame of each partial
-	fin.read((char *) partials.partialStartFrame, sizeof(int)*parNum);
-
-	// num of frames of each partial
-	fin.read((char *) partials.partialNumFrames, sizeof(int)*parNum);
-
-	// frequency mean of each partial
-	fin.read((char *) partials.partialFreqMean, sizeof(int)*parNum);
-
-	for(int par=0; par<parNum; par++)
-	{
-		int frameNum = partials.partialNumFrames[par];
-		partials.update(par, frameNum);
-		fin.read((char *)partials.partialAmplitudes[par], sizeof(float)*frameNum);		// amplitude of each partial in each frame
-		fin.read((char *)partials.partialFrequencies[par], sizeof(float)*frameNum);		// frequency of each partial in each frame
-		fin.read((char *)partials.partialAmpDelta[par], sizeof(float)*frameNum);			// amplitude delta of each partial in each frame
-		fin.read((char *)partials.partialFreqDelta[par], sizeof(float)*frameNum);			// frequency delta of each partial in each frame
-	}
-
-
-
-
-	// frame data
-
-	// number of active partial per each frame
-	fin.read((char *) partials.activePartialNum, sizeof(short)*(hopNum+1));
-	// init array
-	for(int frame=0; frame<hopNum+1; frame++)
-	{
-		partials.activePartials[frame] = new unsigned int[partials.activePartialNum[frame]];
-		fin.read((char *)partials.activePartials[frame], sizeof(int)*partials.activePartialNum[frame]);			// active partials per each frame
-	}
-
-
-
-
-
-	gettimeofday(&stop, NULL);
-	parserT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
-
-
-	printf("\n-----------------------\n");
-	printf("\nFile: %s\n", filename);
-	printf("\n-----------------------\n");
-	printf("Profiler\n");
-	printf("-----------------------\n");
-	printf("File parser:\t\t\t%lu usec\n", parserT);
-	printf("\n\nTotal:\t\t%lu usec\n", parserT);
-	printf("-----------------------\n");
-
-	fin.close();
-
-	return true;
-}
-
-
-
-
-bool Spear_parser::TXTparser(char *filename, int hopsize, int samplerate)
-{
-	hopSize 		= hopsize;
-	fileSampleRate 	= samplerate;
-	if(hopsize<0)
-	{
-		gettimeofday(&start, NULL);
-		calculateHopSize(filename);
-		gettimeofday(&stop, NULL);
-		hopSizeT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
-	}
-	else
-		hopSizeT = 0;
-
-	calculateDeltaTime();
-
-	// working vars
-	char * token;			// where to save single figures from file
-	string s		= "";	// where to save lines from file
-	int parNum		= 0;	// total num of partials
-	int parIndex	= -1;	// index of current partial
-	int frameNum	= 0;	// total num of frames
-	int frameIndex	= -1;	// index of current frame
-	int startSample	= -1;	// sample value for first frame of partials
-	int endSample	= -1;	// sample value for last frame of partials
-	int maxSample	= 0;	// to calculate total number of hops in file
-	int missSampCnt = 0;	// number of mising samples
-	double freq		= 0;	// to calculate frequency delta
-	double prevFreq	= 0;	// to calculate frequency delta
-	double amp		= 0;	// to calculate amplitude delta
-	double prevAmp	= 0;	// to calculate amplitude delta
-
-
-	//----------------------------------------------------------------------------------------
-	// open a file
-	ifstream fin;
-	fin.open(filename);
-	if (!fin.good())
-	{
-		cout << "Parser Error: file not found" << endl;	// exit if file not found
-		return false;
-	}
-
-	gettimeofday(&start, NULL);
-	//----------------------------------------------------------------------------------------
-	// init partials data structure
-	getline(fin, s);
-	getline(fin, s);
-	getline(fin, s);	// third line is the first we are interested into
-
-	// look for partial count
-	token = strtok((char *)s.c_str(), " ");
-	// check if first token is there
-	if(token)
-	{
-		token = strtok(0, " ");
-		// check if second token is there
-		if(token)
-			parNum = atoi(token);
-		#ifdef DO_CHECKS
-		else
-		{
-			cout << "Parser Error: partial count not found, bad file format" << endl;	// exit if value not found
-			return false;
-		}
-		#endif
-	}
-	#ifdef DO_CHECKS
-	else
-	{
-		cout << "Parser Error: partial count not found, bad file format" << endl;		// exit if value not found
-		return false;
-	}
-	#endif
-	// from now on we take for granted that format is correct
-
-	// init partials data structure
-	partials.init(parNum, hopSize);
-
-	//----------------------------------------------------------------------------------------
-	// fill in partials data structure
-	getline(fin, s);		// get rid of intro line "partials-data"
-	getline(fin, s);		// first important line
-
-	while (!fin.eof())
-	{
-		//-------------------------------------
-		// partial specific info
-		token		= strtok((char *)s.c_str(), " ");
-		parIndex	= atoi(token);						// partial index
-
-		token		= strtok(0, " ");					// num of frames, not used, cos we will do linear interpolation for missing frames
-//		frameNum	= atoi(token);
-//		partials.partialNumFrames[parIndex]	= frameNum;
-
-		token		= strtok(0, " ");					// time of first frame, still char *
-		startSample = fromTimeToSamples(atof(token));	// convert time to samples
-		partials.partialStartSample[parIndex]	= startSample;
-
-		token		= strtok(0, " ");					// time of last frame, still char *
-		endSample	= fromTimeToSamples(atof(token)); 	// convert time to samples
-		partials.partialEndSample[parIndex]		= endSample;
-
-		frameNum	= ((endSample-startSample)/hopSize) + 1;	// num of frames, including missing consecutive ones [+1 one cos we count frames, not hops]
-		partials.partialNumFrames[parIndex]		= frameNum;
-
-
-		// check if this is the highest sample value so far
-		if(endSample > maxSample)
-			maxSample = endSample;
-
-		// update data structure
-		partials.update(parIndex, frameNum);
-
-
-		//-------------------------------------
-		// frames
-		getline(fin, s);
-		token		= strtok((char *)s.c_str(), " ");	// frame time
-		frameIndex	= -1;
-
-		// unroll first iteration, so that in the following loop we save the check on the last frame to calculate increments
-		if(token)						// all frames data are on one line, in groups of 3 entries
-		{
-			frameIndex++;
-
-			endSample	= fromTimeToSamples(atof(token));
-
-			token		= strtok(0, " ");	// frame frequency
-			prevFreq	= atof(token);
-			partials.partialFrequencies[parIndex][frameIndex]	= (float)prevFreq;
-			partials.partialFreqMean[parIndex] 					+= prevFreq;		// for frequency mean
-
-			token	 	= strtok(0, " ");	// frame amplitude
-			prevAmp  	= atof(token);
-			partials.partialAmplitudes[parIndex][frameIndex]	= (float)prevAmp;
-
-			token 		= strtok(0, " ");	// next frame frequency, to be checked
-		}
-
-		// here the loop starts
-		while(token)						// all frames data are on one line, in groups of 3 entries
-		{
-			frameIndex++;
-			missSampCnt 	= 0;
-
-			startSample		= fromTimeToSamples(atof(token));
-
-			token			= strtok(0, " ");	// frame frequency
-			freq			= atof(token);
-
-			token			= strtok(0, " ");	// frame amplitude
-			amp				= atof(token);
-			// now we know all about the current frame, but we want to know if some frames are missing between this and the last one
-
-			// while current frame sample is farther than one hopsize...
-			while(startSample > endSample+hopSize)
-			{
-				missSampCnt++;				// ...one sample is missing
-				endSample += hopSize;		// move to next hop
-			}
-
-			// if frames are missing do interpolation and update indices
-			if(missSampCnt>0)
-				startSample = interpolateSamples(parIndex, &frameIndex, missSampCnt, endSample+hopSize, freq, amp, &prevFreq, &prevAmp);
-
-			partials.partialFrequencies[parIndex][frameIndex]	= (float)freq;
-			partials.partialFreqMean[parIndex] 					+= freq;			// for frequency mean
-			partials.setFreqDelta(parIndex, frameIndex-1, (freq-prevFreq)/hopSize);	// freq delta between prev and current frame
-			prevFreq 	= freq;
-
-			partials.partialAmplitudes[parIndex][frameIndex]	= (float)amp;
-			partials.setAmpDelta(parIndex, frameIndex-1, (amp-prevAmp)/hopSize);	// amp delta between prev and current frame
-			prevAmp		= amp;
-
-			endSample	= startSample;
-			token		= strtok(0, " ");	// next frame frequency, to be checked
-		}
-		#ifdef DO_CHECKS
-		if(frameIndex != (frameNum-1))
-		{
-			cout << "Parser Error: frame count mismatch on partial " << parIndex << ", bad file format"  << endl;	// exit if mismatch
-			cout << "frameIndex: " << frameIndex << endl;
-			cout << "frameNum: " << frameNum << endl;
-			return false;
-		}
-		#endif
-
-		partials.partialFreqMean[parIndex] /= partials.partialNumFrames[parIndex];									// frequency mean
-
-		getline(fin, s);					// next partial line, to check
-	}
-	#ifdef DO_CHECKS
-	if(parIndex != (parNum-1))
-	{
-		cout << "Parser Error: partial count mismatch, bad file format"  << endl;									// exit if mismatch
-		return false;
-	}
-	#endif
-
-	partials.setHopNum(maxSample/hopSize);
-
-	gettimeofday(&stop, NULL);
-	parserT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
-
-	gettimeofday(&start, NULL);
-	staticCalculations();
-	gettimeofday(&stop, NULL);
-	staticT = ( (stop.tv_sec*1000000+stop.tv_usec) - (start.tv_sec*1000000+start.tv_usec) );
-
-	fin.close();
-
-
-	printf("\n-----------------------\n");
-	printf("\nFile: %s\n", filename);
-	printf("\n-----------------------\n");
-	printf("Profiler\n");
-	printf("-----------------------\n");
-	printf("Hop size parser:\t\t%lu usec\n", hopSizeT);
-	printf("File parser:\t\t\t%lu usec\n", parserT);
-	printf("Static calculations:\t\t%lu usec\n", staticT);
-	printf("\n\nTotal:\t\t%lu usec\n", hopSizeT+parserT+staticT);
-	printf("-----------------------\n");
-
-	return true;
-}
-
-
-int Spear_parser::interpolateSamples(int parIndex, int *frameIndex, int missCnt, int nextSample, double nextFreq, double nextAmp, double *prevFreq, double *prevAmp)
-{
-	int frame			= *frameIndex;						// current frame index
-	int sample			= nextSample - (hopSize*(missCnt)); // move from next real frame sample to first missing frame sample
-	double freq			= *prevFreq;						// freq of the prev real frame
-	double freqStep		= (nextFreq-*prevFreq)/(missCnt+1);	// fixed freq step between hops, for missing frames [linear interpolation]
-	double deltaFreq	= freqStep/hopSize;					// fixed hop freq step in samples
-	double amp			= *prevAmp;							// same for amp...
-	double ampStep		= (nextAmp-*prevAmp)/(missCnt+1);
-	double deltaAmp		= ampStep/hopSize;
-
-	// for each missing frame
-	for(int i=0; i<missCnt; i++)
-	{
-		// calculate values for current missing frame
-		freq	+= freqStep;
-		amp		+= ampStep;
-		// save values
-		partials.partialFrequencies[parIndex][frame]	= freq;
-		partials.partialAmplitudes[parIndex][frame]		= amp;
-		partials.partialFreqMean[parIndex]				+= freq;	// for frequency mean
-		// set deltas of previous frame [real or missing]
-		partials.setFreqDelta(parIndex, frame-1, deltaFreq);
-		partials.setAmpDelta(parIndex, frame-1, deltaAmp);
-		// move to next frame [missing or real]
-		sample += hopSize;
-		frame++;
-	}
-
-	// update global values
-	*frameIndex	= frame;
-	*prevFreq	= freq;
-	*prevAmp	= amp;
-
-	return sample;	// return the frame sample of the next real frame
-}
-
-
-
-// for each frame, statically calculate:
-// - which partial is active [and the total num of active partials]
-// - at which local frame each partial is
-void Spear_parser::staticCalculations()
-{
-	partials.maxActiveParNum = 0;				// init to find maximum
-
-	unsigned short *indices	= new unsigned short[partials.parNum];	// temp array to store up to the maximum num of active partial indices
-	unsigned int activeCnt	= 0;						// counts the num of active partials in each frame
-
-	unsigned int frameSample = 0;						// current frame in samples
-
-	char *partialStarted = new char [partials.parNum];	// index of the last local frame found per each partial
-	fill(partialStarted, partialStarted+partials.parNum, 0);
-
-	for(unsigned int i=0; i<partials.hopNum+1; i++)		// for each frame [not hops, this explains the +1]
-	{
-		//partials.localPartialFrames[i] = new int[partials.parNum];	// init all local frames to -1
-		//fill(partials.localPartialFrames[i], partials.localPartialFrames[i]+partials.parNum, -1);
-
-		frameSample = i*hopSize;	// current frame, expressed in samples
-		activeCnt	  = 0;			// reset a each frame
-
-		for(unsigned int j=0; j<partials.parNum; j++)	// for each partial
-		{
-			// check if inside active time region [expressed in samples]
-			if( (frameSample>=partials.partialStartSample[j]) && (frameSample<partials.partialEndSample[j]) )	// frame sample not equal to end sample, this filters out last frames and partials with one frame only
-			{
-				// activity
-				indices[activeCnt] = j;	// save active index
-				activeCnt++;			// increase counter
-
-				// partial local frames
-				if(partialStarted[j]==0)	// this partial has just started, so current local frame is first frame
-				{
-					partialStarted[j] 		 		= 1;
-					partials.partialStartFrame[j]	= i;	// here is the number of the first frame
-				}
-			}
-		}
-
-		// activity
-		partials.activePartialNum[i] = activeCnt;							// save number of active partials for this frame
-		partials.activePartials[i]	 = new unsigned int[activeCnt];					// set correct size to save all indices
-
-		// look for maximum number of active partials at the same time
-		if(activeCnt > partials.maxActiveParNum)
-			partials.maxActiveParNum = activeCnt;
-
-		// copy indices
-		for(unsigned int k=0; k<activeCnt; k++)
-			partials.activePartials[i][k] = indices[k];
-	}
-
-	delete[] indices;
-	delete[] partialStarted;
-
-	delete[] partials.partialStartSample;
-	delete[] partials.partialEndSample;
-}
-
-
-
--- a/examples/d-box/spear_parser.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/*
- * spear_parser.h v1.2
- *
- *  Created on: May 6, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef SPEAR_PARSER_H_
-#define SPEAR_PARSER_H_
-
-#include <iostream>
-#include <fstream>
-#include <cstring>
-#include <string>
-#include <stdlib.h>		// atoi, atof
-#include <math.h>
-#include <algorithm>	// std::fill
-
-#include <sys/time.h>
-
-using namespace std;
-
-
-//------------------------------------------------------------------------------------------------
-// partials
-//------------------------------------------------------------------------------------------------
-
-class Spear_parser; // for class friendship
-
-class Partials
-{
-	friend class Spear_parser;
-	friend class Dbox_parser;
-
-public:
-	int **partialSamples;				// sample at which each frame is
-	float **partialFrequencies;			// frequencies at each frame
-	float **partialAmplitudes;			// amplitudes at each frame
-	unsigned int *partialNumFrames;		// Length of each partial in frames
-	unsigned int *partialStartFrame;	// frame at which each partial begins
-	float **partialFreqDelta;			// constant frequency slope for each partial in each frame interval
-	float **partialAmpDelta;			// constant amplitude slope for each partial in each frame interval
-	float *partialFreqMean;				// frequency mean for each partial, over all its frames
-
-	unsigned short *activePartialNum;	// num of each active partial at each frame
-	unsigned int **activePartials;		// indices of all active partials at each frame
-
-
-	int getPartialNum();
-	int getHopNum();
-	int getMaxActivePartialNum();
-
-private:
-	Partials();
-	~Partials();
-
-	unsigned int *partialStartSample;	// sample at which each partial begins
-	unsigned int *partialEndSample;		// sample at which each partial ends [sample gap between 2 consecutive frames can be an integer multiple of hopSize]
-	unsigned int parNum;
-	unsigned int currentSample;
-	unsigned int hopSize;
-	unsigned int hopNum;
-	unsigned int maxActiveParNum;
-
-	void init(int parNum, int hopSize, bool isDBX=false);
-	void update(int parIndex, int frameNum);
-	void setFreqDelta(int parIndex, int frameNum, double delta);
-	void setAmpDelta(int parIndex, int frameNum, double delta);
-	void setHopNum(int hopNum);
-};
-
-inline int Partials::getPartialNum()
-{
-	return parNum;
-}
-
-inline void Partials::setHopNum(int hopN)
-{
-	hopNum = hopN;
-
-	// prepare data structures
-	activePartialNum 	= new unsigned short[hopNum+1];	// +1 cos total num of frames = num of hops+1
-	activePartials	 	= new unsigned int *[hopNum+1];
-}
-
-// useful to increase current sample using a modulo on the total number of samples [easy to be deduced from the total num or hops]
-inline int Partials::getHopNum()
-{
-	return hopNum;
-}
-
-inline void Partials::setFreqDelta(int parIndex, int frameNum, double delta)
-{
-	partialFreqDelta[parIndex][frameNum] = delta;
-}
-
-inline void Partials::setAmpDelta(int parIndex, int frameNum, double delta)
-{
-	partialAmpDelta[parIndex][frameNum] = delta;
-}
-
-inline int Partials::getMaxActivePartialNum()
-{
-	return maxActiveParNum;
-}
-
-
-
-
-
-
-
-//------------------------------------------------------------------------------------------------
-// spear parser
-//------------------------------------------------------------------------------------------------
-
-class Spear_parser
-{
-public:
-	Spear_parser();
-	~Spear_parser();
-
-	Partials partials;
-
-	bool parseFile(string filename, int hopsize=-1, int samplerate = 44100);
-	bool parseFile(char *filename, int hopsize=-1, int samplerate = 44100);
-	int getHopSize();
-	int getFileSampleRate();
-	double getDeltaTime();
-
-private:
-
-	int hopSize;
-	int fileSampleRate;
-	double deltaTime;	// min time gap between consecutive frames
-
-	timeval start, stop;
-	unsigned long hopSizeT, parserT, staticT;
-
-	void calculateDeltaTime();
-	void calculateHopSize(char *filename);
-	bool parser(char *filename, int hopsize=-1, int samplerate=44100);
-	bool DBXparser(char *filename, int samplerate=44100);
-	bool TXTparser(char *filename, int hopsize=-1, int samplerate=44100);
-	int fromTimeToSamples(float time);
-	int interpolateSamples(int parIndex, int *frameIndex, int missCnt, int nextSample,
-							double nextFreq, double nextAmp, double *prevFreq, double *prevAmp);
-	void staticCalculations();
-
-};
-
-inline bool Spear_parser::parseFile(string filename, int hopsize, int samplerate)
-{
-	return parser((char *)filename.c_str(), hopsize, samplerate);
-}
-
-inline bool Spear_parser::parseFile(char *filename, int hopsize, int samplerate)
-{
-	return parser(filename, hopsize, samplerate);
-}
-
-inline void Spear_parser::calculateDeltaTime()
-{
-	deltaTime = (double)hopSize/ (double)fileSampleRate;
-}
-
-// each time value in the file is rounded, and 2 consecutive frames can differ of a time gap = i*deltaTime, where i is a positive integer
-inline int Spear_parser::fromTimeToSamples(float time)
-{
-	return round(time/deltaTime)*hopSize;	// round is necessary since in the file log time values are rounded, so they do not apparently look like integer multiples of deltaTime
-}
-
-inline int Spear_parser::getHopSize()
-{
-	return hopSize;
-}
-
-inline int Spear_parser::getFileSampleRate()
-{
-	return fileSampleRate;
-}
-
-inline double Spear_parser::getDeltaTime()
-{
-	return deltaTime;
-}
-
-#endif /* SPEAR_PARSER_H_ */
--- a/examples/filter_FIR/FIRfilter.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * FIRfilter.h
- *
- *  Created on: Aug 5, 2014
- *      Author: Victor Zappi and Andrew McPherson
- */
-
-#ifndef FIRFILTER_H_
-#define FIRFILTER_H_
-
-
-#include <ne10/NE10.h>
-
-#define FILTER_TAP_NUM 31
-
-// Coefficients for FIR High Pass Filter at 3 KHz
-ne10_float32_t filterTaps[FILTER_TAP_NUM] = {
-		-0.000055,
-		0.000318,
-		0.001401,
-		0.003333,
-		0.005827,
-		0.007995,
-		0.008335,
-		0.004991,
-		-0.003764,
-		-0.018906,
-		-0.040112,
-		-0.065486,
-		-0.091722,
-		-0.114710,
-		-0.130454,
-		0.863946,
-		-0.130454,
-		-0.114710,
-		-0.091722,
-		-0.065486,
-		-0.040112,
-		-0.018906,
-		-0.003764,
-		0.004991,
-		0.008335,
-		0.007995,
-		0.005827,
-		0.003333,
-		0.001401,
-		0.000318,
-		-0.000055
-};
-
-#endif /* FIRFILTER_H_ */
--- a/examples/filter_FIR/SampleData.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/*
- * SampleData.h
- *
- *  Created on: Nov 5, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef SAMPLEDATA_H_
-#define SAMPLEDATA_H_
-
-// User defined structure to pass between main and rendere complex data retrieved from file
-struct SampleData {
-	float *samples;	// Samples in file
-	int sampleLen;	// Total nume of samples
-};
-
-
-
-#endif /* SAMPLEDATA_H_ */
Binary file examples/filter_FIR/longsample.wav has changed
--- a/examples/filter_FIR/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: Andrew McPherson and Victor Zappi
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <string>
-#include <getopt.h>
-#include <sndfile.h>				// to load audio files
-
-#include <Bela.h>
-#include "SampleData.h"
-
-using namespace std;
-
-// Load samples from file
-int initFile(string file, SampleData *smp)//float *& smp)
-{
-	SNDFILE *sndfile ;
-	SF_INFO sfinfo ;
-
-	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
-		cout << "Couldn't open file " << file << endl;
-		return 1;
-	}
-
-	int numChan = sfinfo.channels;
-	if(numChan != 1)
-	{
-		cout << "Error: " << file << " is not a mono file" << endl;
-		return 1;
-	}
-
-	smp->sampleLen = sfinfo.frames * numChan;
-	smp->samples = new float[smp->sampleLen];
-	if(smp == NULL){
-		cout << "Could not allocate buffer" << endl;
-		return 1;
-	}
-
-	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
-	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
-
-	// Pad with zeros in case we couldn't read whole file
-	for(int k = readcount; k <smp->sampleLen; k++)
-		smp->samples[k] = 0;
-
-	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
-		double	scale ;
-		int 	m ;
-
-		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
-		if (scale < 1e-10)
-			scale = 1.0 ;
-		else
-			scale = 32700.0 / scale ;
-		cout << "File samples scale = " << scale << endl;
-
-		for (m = 0; m < smp->sampleLen; m++)
-			smp->samples[m] *= scale;
-	}
-
-	sf_close(sndfile);
-
-	return 0;
-}
-
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	//rt_task_delete ((RT_TASK *) &gTriggerSamplesTask);
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --file [-f] filename:    Name of the file to load (default is \"longsample.wav\")\n";
-	cerr << "   --help [-h]:             Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	string fileName;			// Name of the sample to load
-
-	SampleData sampleData;		// User define structure to pass data retrieved from file to render function
-	sampleData.samples = 0;
-	sampleData.sampleLen = -1;
-
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"file", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				fileName = string((char *)optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	if(fileName.empty()){
-		fileName = "filter/longsample.wav";
-	}
-
-	if(settings.verbose) {
-		cout << "Loading file " << fileName << endl;
-	}
-
-	// Load file
-	if(initFile(fileName, &sampleData) != 0)
-	{
-		cout << "Error: unable to load samples " << endl;
-		return -1;
-	}
-
-	if(settings.verbose)
-		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
-
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &sampleData) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
-
--- a/examples/filter_FIR/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,180 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
-*/
-
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: Andrew McPherson and Victor Zappi
- */
-
-/**
-\example 4_filter_FIR
-
-Finite Impulse Response Filter
-------------------------------
-
-This is an example of a finite impulse response filter implementation.
-*/
-
-#define ENABLE_NE10_FIR_FLOAT_NEON	// Define needed for Ne10 library
-
-#include <Bela.h>
-#include <cmath>
-#include <ne10/NE10.h>					// neon library
-#include "SampleData.h"
-#include "FIRfilter.h"
-
-SampleData gSampleData;	// User defined structure to get complex data from main
-int gReadPtr;			// Position of last read sample from file
-
-// filter vars
-ne10_fir_instance_f32_t gFIRfilter;
-ne10_float32_t *gFIRfilterIn;
-ne10_float32_t *gFIRfilterOut;
-ne10_uint32_t blockSize;
-ne10_float32_t *gFIRfilterState;
-
-void initialise_filter(BelaContext *context);
-
-// Task for handling the update of the frequencies using the matrix
-AuxiliaryTask gTriggerSamplesTask;
-
-bool initialise_trigger();
-void trigger_samples();
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-
-	// Retrieve a parameter passed in from the initAudio() call
-	gSampleData = *(SampleData *)userData;
-
-	gReadPtr = -1;
-
-	initialise_filter(context);
-
-	// Initialise auxiliary tasks
-	if(!initialise_trigger())
-		return false;
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		float in = 0;
-
-		// If triggered...
-		if(gReadPtr != -1)
-			in += gSampleData.samples[gReadPtr++];	// ...read each sample...
-
-		if(gReadPtr >= gSampleData.sampleLen)
-			gReadPtr = -1;
-
-		gFIRfilterIn[n] = in;
-	}
-
-	ne10_fir_float_neon(&gFIRfilter, gFIRfilterIn, gFIRfilterOut, blockSize);
-
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-				context->audioOut[n * context->audioChannels + channel] = gFIRfilterOut[n];	// ...and put it in both left and right channel
-	}
-
-
-	// Request that the lower-priority task run at next opportunity
-	Bela_scheduleAuxiliaryTask(gTriggerSamplesTask);
-}
-
-// Initialise NE10 data structures to define FIR filter
-
-void initialise_filter(BelaContext *context)
-{
-	blockSize = context->audioFrames;
-	gFIRfilterState	= (ne10_float32_t *) NE10_MALLOC ((FILTER_TAP_NUM+blockSize-1) * sizeof (ne10_float32_t));
-	gFIRfilterIn = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
-	gFIRfilterOut = (ne10_float32_t *) NE10_MALLOC (blockSize * sizeof (ne10_float32_t));
-	ne10_fir_init_float(&gFIRfilter, FILTER_TAP_NUM, filterTaps, gFIRfilterState, blockSize);
-}
-
-
-// Initialise the auxiliary task
-// and print info
-
-bool initialise_trigger()
-{
-	if((gTriggerSamplesTask = Bela_createAuxiliaryTask(&trigger_samples, 50, "bela-trigger-samples")) == 0)
-		return false;
-
-	rt_printf("Press 'a' to trigger sample, 's' to stop\n");
-	rt_printf("Press 'q' to quit\n");
-
-	return true;
-}
-
-// This is a lower-priority call to periodically read keyboard input
-// and trigger samples. By placing it at a lower priority,
-// it has minimal effect on the audio performance but it will take longer to
-// complete if the system is under heavy audio load.
-
-void trigger_samples()
-{
-	// This is not a real-time task!
-	// Cos getchar is a system call, not handled by Xenomai.
-	// This task will be automatically down graded.
-
-	char keyStroke = '.';
-
-	keyStroke =	getchar();
-	while(getchar()!='\n'); // to read the first stroke
-
-	switch (keyStroke)
-	{
-		case 'a':
-			gReadPtr = 0;
-			break;
-		case 's':
-			gReadPtr = -1;
-			break;
-		case 'q':
-			gShouldStop = true;
-			break;
-		default:
-			break;
-	}
-}
-
-
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	delete[] gSampleData.samples;
-
-	NE10_FREE(gFIRfilterState);
-	NE10_FREE(gFIRfilterIn);
-	NE10_FREE(gFIRfilterOut);
-}
--- a/examples/filter_IIR/SampleData.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/*
- * SampleData.h
- *
- *  Created on: Nov 5, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef SAMPLEDATA_H_
-#define SAMPLEDATA_H_
-
-// User defined structure to pass between main and rendere complex data retrieved from file
-struct SampleData {
-	float *samples;	// Samples in file
-	int sampleLen;	// Total nume of samples
-};
-
-
-
-#endif /* SAMPLEDATA_H_ */
Binary file examples/filter_IIR/longsample.wav has changed
--- a/examples/filter_IIR/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: Andrew McPherson and Victor Zappi
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <string>
-#include <getopt.h>
-#include <sndfile.h>				// to load audio files
-
-#include <Bela.h>
-#include "SampleData.h"
-
-using namespace std;
-
-float gCutFreq = 100;
-
-// Load samples from file
-int initFile(string file, SampleData *smp)//float *& smp)
-{
-	SNDFILE *sndfile ;
-	SF_INFO sfinfo ;
-
-	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
-		cout << "Couldn't open file " << file << endl;
-		return 1;
-	}
-
-	int numChan = sfinfo.channels;
-	if(numChan != 1)
-	{
-		cout << "Error: " << file << " is not a mono file" << endl;
-		return 1;
-	}
-
-	smp->sampleLen = sfinfo.frames * numChan;
-	smp->samples = new float[smp->sampleLen];
-	if(smp == NULL){
-		cout << "Could not allocate buffer" << endl;
-		return 1;
-	}
-
-	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
-	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
-
-	// Pad with zeros in case we couldn't read whole file
-	for(int k = readcount; k <smp->sampleLen; k++)
-		smp->samples[k] = 0;
-
-	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
-		double	scale ;
-		int 	m ;
-
-		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
-		if (scale < 1e-10)
-			scale = 1.0 ;
-		else
-			scale = 32700.0 / scale ;
-		cout << "File samples scale = " << scale << endl;
-
-		for (m = 0; m < smp->sampleLen; m++)
-			smp->samples[m] *= scale;
-	}
-
-	sf_close(sndfile);
-
-	return 0;
-}
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	//rt_task_delete ((RT_TASK *) &gTriggerSamplesTask);
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --file [-f] filename:    Name of the file to load (default is \"longsample.wav\")\n";
-	cerr << "   --cutfreq [-c] freq:     Set the cut off frequency of the filter in Hz\n";
-	cerr << "   --help [-h]:             Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	string fileName;			// Name of the sample to load
-
-	SampleData sampleData;		// User define structure to pass data retrieved from file to render function
-	sampleData.samples = 0;
-	sampleData.sampleLen = -1;
-
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"cutfreq", 1, NULL, 'c'},
-		{"file", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:c:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				fileName = string((char *)optarg);
-				break;
-		case 'c':
-				gCutFreq = atof(optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	if(fileName.empty()){
-		fileName = "filter/longsample.wav";
-	}
-
-	if(settings.verbose) {
-		cout << "Loading file " << fileName << endl;
-	}
-
-	// Load file
-	if(initFile(fileName, &sampleData) != 0)
-	{
-		cout << "Error: unable to load samples " << endl;
-		return -1;
-	}
-
-	if(settings.verbose)
-		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
-
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &sampleData) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
-
--- a/examples/filter_IIR/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
-*/
-
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: Andrew McPherson and Victor Zappi
- */
-
-/**
-\example 4_filter_IIR
-
-Infinite Impulse Response Filter
-------------------------------
-
-This is an example of a infinite impulse response filter implementation.
-*/
-
-#include <Bela.h>	// to schedule lower prio parallel process
-#include <rtdk.h>
-#include <cmath>
-#include <stdio.h>
-#include "SampleData.h"
-
-SampleData gSampleData;	// User defined structure to get complex data from main
-int gReadPtr;			// Position of last read sample from file
-
-// filter vars
-float gLastX[2];
-float gLastY[2];
-double lb0, lb1, lb2, la1, la2 = 0.0;
-
-// communication vars between the 2 auxiliary tasks
-int gChangeCoeff = 0;
-int gFreqDelta = 0;
-
-void initialise_filter(float freq);
-
-void calculate_coeff(float cutFreq);
-
-bool initialise_aux_tasks();
-
-// Task for handling the update of the frequencies using the matrix
-AuxiliaryTask gChangeCoeffTask;
-
-void check_coeff();
-
-// Task for handling the update of the frequencies using the matrix
-AuxiliaryTask gInputTask;
-
-void read_input();
-
-
-extern float gCutFreq;
-
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-
-	// Retrieve a parameter passed in from the initAudio() call
-	gSampleData = *(SampleData *)userData;
-
-	gReadPtr = -1;
-
-	initialise_filter(200);
-
-	// Initialise auxiliary tasks
-	if(!initialise_aux_tasks())
-		return false;
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		float sample = 0;
-		float out = 0;
-
-		// If triggered...
-		if(gReadPtr != -1)
-			sample += gSampleData.samples[gReadPtr++];	// ...read each sample...
-
-		if(gReadPtr >= gSampleData.sampleLen)
-			gReadPtr = -1;
-
-		out = lb0*sample+lb1*gLastX[0]+lb2*gLastX[1]-la1*gLastY[0]-la2*gLastY[1];
-
-		gLastX[1] = gLastX[0];
-		gLastX[0] = out;
-		gLastY[1] = gLastY[0];
-		gLastY[0] = out;
-
-		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-			context->audioOut[n * context->audioChannels + channel] = out;	// ...and put it in both left and right channel
-
-	}
-
-	// Request that the lower-priority tasks run at next opportunity
-	Bela_scheduleAuxiliaryTask(gChangeCoeffTask);
-	Bela_scheduleAuxiliaryTask(gInputTask);
-}
-
-// First calculation of coefficients
-
-void initialise_filter(float freq)
-{
-	calculate_coeff(freq);
-}
-
-
-// Calculate the filter coefficients
-// second order low pass butterworth filter
-
-void calculate_coeff(float cutFreq)
-{
-	// Initialise any previous state (clearing buffers etc.)
-	// to prepare for calls to render()
-	float sampleRate = 44100;
-	double f = 2*M_PI*cutFreq/sampleRate;
-	double denom = 4+2*sqrt(2)*f+f*f;
-	lb0 = f*f/denom;
-	lb1 = 2*lb0;
-	lb2 = lb0;
-	la1 = (2*f*f-8)/denom;
-	la2 = (f*f+4-2*sqrt(2)*f)/denom;
-	gLastX[0] = gLastX [1] = 0;
-	gLastY[0] = gLastY[1] = 0;
-
-}
-
-
-// Initialise the auxiliary tasks
-// and print info
-
-bool initialise_aux_tasks()
-{
-	if((gChangeCoeffTask = Bela_createAuxiliaryTask(&check_coeff, 90, "bela-check-coeff")) == 0)
-		return false;
-
-	if((gInputTask = Bela_createAuxiliaryTask(&read_input, 50, "bela-read-input")) == 0)
-		return false;
-
-	rt_printf("Press 'a' to trigger sample, 's' to stop\n");
-	rt_printf("Press 'z' to low down cut-off freq of 100 Hz, 'x' to raise it up\n");
-	rt_printf("Press 'q' to quit\n");
-
-	return true;
-}
-
-// Check if cut-off freq has been changed
-// and new coefficients are needed
-
-void check_coeff()
-{
-	if(gChangeCoeff == 1)
-	{
-		gCutFreq += gFreqDelta;
-		gCutFreq = gCutFreq < 0 ? 0 : gCutFreq;
-		gCutFreq = gCutFreq > 22050 ? 22050 : gCutFreq;
-
-		rt_printf("Cut-off frequency: %f\n", gCutFreq);
-
-		calculate_coeff(gCutFreq);
-		gChangeCoeff = 0;
-	}
-}
-
-// This is a lower-priority call to periodically read keyboard input
-// and trigger samples. By placing it at a lower priority,
-// it has minimal effect on the audio performance but it will take longer to
-// complete if the system is under heavy audio load.
-
-void read_input()
-{
-	// This is not a real-time task!
-	// Cos getchar is a system call, not handled by Xenomai.
-	// This task will be automatically down graded.
-
-	char keyStroke = '.';
-
-	keyStroke =	getchar();
-	while(getchar()!='\n'); // to read the first stroke
-
-	switch (keyStroke)
-	{
-		case 'a':
-			gReadPtr = 0;
-			break;
-		case 's':
-			gReadPtr = -1;
-			break;
-		case 'z':
-			gChangeCoeff = 1;
-			gFreqDelta = -100;
-			break;
-		case 'x':
-			gChangeCoeff = 1;
-			gFreqDelta = 100;
-			break;
-		case 'q':
-			gShouldStop = true;
-			break;
-		default:
-			break;
-	}
-}
-
-
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	delete[] gSampleData.samples;
-}
--- a/examples/gpioAnalogLoopbackTest/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,209 +0,0 @@
-#include <Bela.h>
-#include <cmath>
-#include <rtdk.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stats.hpp>
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-
-// digital inputs can be changed at will (as they are all being processed at the same time)
-// analog channels must be as per below
-int gAnalogOutCh = 1;
-int gDigitalOutCh = 2;
-int gDigitalInACh = 0;
-int gDigitalInDCh = 3;
-int gAnalogOutLoopDelay;
-int gDigitalOutLoopDelay;
-bool setup(BelaContext *context, void *userData)
-{
-	rt_printf("For this test you need the following connections:\n"
-			"analog%d out->digital%d in, analog%d out->analog%d in, "
-			"digital%d out -> digital%d in, digital%d out-> analog%d in\n",
-			gAnalogOutCh, gDigitalInACh, gAnalogOutCh, 0, gDigitalOutCh, gDigitalInDCh, gDigitalOutCh, 0);
-	rt_printf("Running test with %d analog channels and a buffer size of %d\n",
-			context->analogChannels, context->audioFrames);
-
-	for(unsigned int n = 0; n < context->digitalFrames; n++){
-		pinMode(context, n, gDigitalInACh, INPUT);
-		pinMode(context, n, gDigitalInDCh, INPUT);
-		pinMode(context, n, gDigitalOutCh, OUTPUT);
-	}
-	switch (context->analogChannels){
-		case 2:
-			gAnalogOutLoopDelay = context->audioFrames*2 + 3;
-			gDigitalOutLoopDelay = context->audioFrames*2 + 2;
-			break;
-		case 4:
-			gAnalogOutLoopDelay = context->audioFrames*2 + 3;
-			gDigitalOutLoopDelay = context->audioFrames*2 + 2;
-			break;
-		case 8:
-			gAnalogOutLoopDelay = context->audioFrames + 3;
-			gDigitalOutLoopDelay = context->audioFrames + 1;
-			break;
-		default:
-			exit(2);
-	}
-
-    return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numAnalogFrames
-// will be 0.
-
-const int patternLength = 31;
-static int anaErrorCount = 0;
-static int digErrorCount = 0;
-void render(BelaContext *context, void *userData)
-{
-	static bool writePattern[patternLength] = {
-									0,1,0,1,0,0,1,1,
-									0,0,0,1,1,1,0,0,
-									1,1,1,1,0,0,0,0,
-									1,1,1,1,1,0,0};
-//	for(int n = 0; n < patternLength; n++){
-//		writePattern[n]=1;
-//	}
-	static int inPointer = 0;
-	static int outPointer = 0;
-	static int digitalOutPointer = 0;
-	static int digitalInPointer = 0;
-	static int analogOut = 1;
-	/** Checking offset between analog and digital
-	 * how it should be :
-	 * The PRU loop does the following (the loop runs at 88.2kHz):
-	 * - Read/write audio sample (once for the left channel, once for the right channel)
-	 * - Write DAC 0 or 0/2 or 0/2/4/6
-	 * - Read ADC 0 or 0/2 or 0/2/4/6, 2 samples (@176.4) older than NOW
-	 * - /During/ the line above, every two loops we also Read/Write GPIO,
-	 * therefore reading on ADC 0/2/4/6 a value that is being output from GPIO will lead to undefined results
-	 * - Write DAC 1 or 1/3 or 1/3/5/7
-	 * - Read ADC 1 or 1/3 or 1/3/5/7, 2 samples (@176.4) older than NOW
-	 */
-	if(1)
-	for(unsigned int n = 0; n < context->audioFrames; n++){
-		static bool analog0In = false;
-		static bool digitalAIn = false;
-		static int count = 0;
-		bool doReadWrite = context->analogChannels<=4 ? true : ((context->analogChannels == 8) && (n&1)==0);
-		if(doReadWrite){
-			digitalAIn = digitalRead(context, n, gDigitalInACh);
-			switch(context->analogChannels){
-			case 8:
-				analog0In = analogRead(context, n/2, 0) > 0.5;
-				analogWrite(context, n/2, analogOut, writePattern[outPointer]);
-				break;
-			case 4:
-				analog0In = analogRead(context, n, 0) > 0.5;
-				analogWrite(context, n, analogOut, writePattern[outPointer]);
-				break;
-			case 2:
-				analog0In = analogRead(context, n * 2 + 1, 0) > 0.5;
-				analogWrite(context, 2 * n, analogOut, writePattern[outPointer]);
-				analogWrite(context, 2 * n + 1, analogOut, writePattern[outPointer]);
-				break;
-			}
-			gAnalogOutLoopDelay--;
-			outPointer++;
-			if(gAnalogOutLoopDelay <= 0){
-				if(++inPointer == patternLength){
-					inPointer = 0;
-				}
-			}
-		}
-		bool expectedIn = writePattern[inPointer];
-		if(gAnalogOutLoopDelay <= 0 && doReadWrite == true){
-			if(analog0In != expectedIn || digitalAIn != expectedIn){
-				rt_printf("expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n",
-					expectedIn, analog0In, digitalAIn, inPointer, gAnalogOutLoopDelay, count);
-				anaErrorCount++;
-			}
-		}
-		count++;
-		if(analog0In != digitalAIn){ // at any time the analog and digital in should be the same
-			rt_printf("ana %d_%d %d,\n", analog0In, digitalAIn, n);
-		}
-		if(outPointer == patternLength){
-			outPointer = 0;
-		}
-	}
-	if(1)
-	for(unsigned int n = 0; n < context->audioFrames; n++){
-		static int count = 0;
-		static bool analog1In = false;
-		static bool digitalDIn = false;
-/* we need to remember the pastAnalog1In because
- *  reading GPIO takes place before writing to it, therefore
- *  when reading a GPIOout, the GPIOin samples will always be one sample late
- */
-		bool doReadWrite = false;
-		static bool pastAnalog1In = false;
-		digitalWriteOnce(context, n, gDigitalOutCh,  writePattern[digitalOutPointer]);
-		if(context->analogChannels == 8){
-			if((n&1) == 0){ //do it every other sample
-				pastAnalog1In = analogRead(context, n/2, 1) > 0.5;
-				digitalDIn = digitalRead(context, n, gDigitalInDCh);
-				doReadWrite = true;
-			}
-		}
-		if(context->analogChannels == 4){
-			pastAnalog1In = analogRead(context, n, 1) > 0.5;
-			digitalDIn = digitalRead(context, n, gDigitalInDCh);
-			digitalWriteOnce(context, n, gDigitalOutCh,  writePattern[digitalOutPointer]);
-			doReadWrite = true;
-		}
-		if(context->analogChannels == 2){
-			pastAnalog1In = analogRead(context, n * 2, 1) > 0.5;
-			digitalDIn = digitalRead(context, n, gDigitalInDCh);
-			digitalWriteOnce(context, n, gDigitalOutCh,  writePattern[digitalOutPointer]);
-			doReadWrite = true;
-		}
-		bool expectedDigitalIn = writePattern[digitalInPointer];
-		if(doReadWrite == true){
-			gDigitalOutLoopDelay--;
-			if(gDigitalOutLoopDelay <= 0){
-				if(expectedDigitalIn != pastAnalog1In || expectedDigitalIn != digitalDIn){
-					rt_printf("D expected: %d, received: %d %d, pointer: %d, delay: %d, count: %d\n",
-						expectedDigitalIn, pastAnalog1In, digitalDIn, inPointer, gDigitalOutLoopDelay, count);
-					digErrorCount++;
-				}
-				if(++digitalInPointer == patternLength){
-					digitalInPointer = 0;
-				}
-			}
-			pastAnalog1In = analog1In;
-			if(++digitalOutPointer == patternLength){
-				digitalOutPointer = 0;
-			}
-		}
-		count++;
-	}
-	if(context->audioFramesElapsed > 30000){
-		gShouldStop = true;
-	}
-}
-
-
-void cleanup(BelaContext *context, void *userData)
-{
-	if(anaErrorCount == 0 && digErrorCount == 0){
-		rt_printf("Test was succesful with %d analog channels and a buffer size of %d\n", context->analogChannels, context->audioFrames);
-	} else {
-		rt_printf("------------------------\n%danalog %ddigital errors over %dsamples while running test with ",
-				anaErrorCount, digErrorCount, context->audioFramesElapsed);
-		rt_printf("%d analog channels and a buffer size of %d \n\n\n",
-				context->analogChannels, context->audioFrames);
-		exit(1);
-	}
-}
--- a/examples/level_meter/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-
-#include <Bela.h>
-#include <cmath>
-
-#define NUMBER_OF_SEGMENTS	10
-
-// Two levels of audio: one follows current value, the other holds
-// peaks for longer
-float gAudioLocalLevel = 0, gAudioPeakLevel = 0;
-
-// Decay rates for detecting levels
-float gLocalDecayRate = 0.99, gPeakDecayRate = 0.999;
-
-// Thresholds for LEDs: set in setup()
-float gThresholds[NUMBER_OF_SEGMENTS + 1];
-int gSamplesToLight[NUMBER_OF_SEGMENTS];
-
-// High-pass filter on the input
-float gLastX[2] = {0};
-float gLastY[2] = {0};
-
-// These coefficients make a high-pass filter at 5Hz for 44.1kHz sample rate
-double gB0 = 0.99949640;
-double gB1 = -1.99899280;
-double gB2 = gB0;
-double gA1 = -1.99899254;
-double gA2 = 0.99899305;
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{	
-	// This project makes the assumption that the audio and digital
-	// sample rates are the same. But check it to be sure!
-	if(context->audioFrames != context->digitalFrames) {
-		rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
-		return false;
-	}
-	
-	// Initialise threshold levels in -3dB steps. One extra for efficiency in render()
-	// Level = 10^(dB/20)
-	for(int i = 0; i < NUMBER_OF_SEGMENTS + 1; i++) {
-		gThresholds[i] = powf(10.0f, (-1.0 * (NUMBER_OF_SEGMENTS - i)) * .05);
-	}
-	
-	for(int i = 0; i < NUMBER_OF_SEGMENTS; i++) {
-		gSamplesToLight[i] = 0;
-		pinMode(context, 0, i, OUTPUT);
-	}
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		// Get average of audio input channels
-		float sample = 0;
-		for(unsigned int ch = 0; ch < context->audioChannels; ch++) {
-			context->audioOut[n * context->audioChannels + ch] = 
-				context->audioIn[n * context->audioChannels + ch];
-			sample += context->audioIn[n * context->audioChannels + ch];
-		}
-		
-		// Do DC-blocking on the sum
-		float out = gB0 * sample + gB1 * gLastX[0] + gB2 * gLastX[1]
-						- gA1 * gLastY[0] - gA2 * gLastY[1];
-
-		gLastX[1] = gLastX[0];
-		gLastX[0] = sample;
-		gLastY[1] = gLastY[0];
-		gLastY[0] = out;
-		
-		out = fabsf(out / (float)context->audioChannels);
-		
-		// Do peak detection: fast-responding local level
-		if(out > gAudioLocalLevel)
-			gAudioLocalLevel = out;
-		else
-			gAudioLocalLevel *= gLocalDecayRate;
-		
-		// Do peak detection: slow-responding peak level
-		if(out > gAudioPeakLevel)
-			gAudioPeakLevel = out;
-		else {
-			// Make peak decay slowly by only multiplying
-			// every few samples
-			if(((context->audioFramesElapsed + n) & 31) == 0)
-				gAudioPeakLevel *= gPeakDecayRate;
-		}	
-		// LED bargraph on digital outputs 0-9
-		for(int led = 0; led < NUMBER_OF_SEGMENTS; led++) {
-			// All LEDs up to the local level light up. The LED
-			// for the peak level also remains lit.
-			int state = LOW;
-				
-			if(gAudioLocalLevel > gThresholds[led]) {
-				state = HIGH;
-				gSamplesToLight[led] = 1000;
-			}
-			/*else if(gAudioPeakLevel > gThresholds[led] && gAudioPeakLevel <= gThresholds[led + 1]) {
-				state = HIGH;
-				gSamplesToLight[led] = 1000;
-			}*/
-			else if(--gSamplesToLight[led] > 0)
-				state = HIGH;
-			
-			// Write LED
-			digitalWriteOnce(context, n, led, state);
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/loggingSensors/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-#include <unistd.h>
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --frequency [-f] frequency: Set the frequency of the oscillator\n";
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	float frequency = 440.0;	// Frequency of oscillator
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"frequency", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				frequency = atof(optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &frequency) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/loggingSensors/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-#include <Bela.h> 
-#include <cmath>
-#include <WriteFile.h>
-
-WriteFile file1;
-WriteFile file2;
-
-bool setup(BelaContext *context, void *userData)
-{
-	file1.init("out.bin"); //set the file name to write to
-	file1.setEchoInterval(1000);
-	file1.setFileType(kBinary);
-	file1.setFormat("%.4f %.4f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers). When in binary mode, this is used only for echoing to console
-	file2.init("out.m"); //set the file name to write to
-	file2.setHeader("myvar=[\n"); //set one or more lines to be printed at the beginning of the file
-	file2.setFooter("];\n"); //set one or more lines to be printed at the end of the file
-	file2.setFormat("%.4f\n"); // set the format that you want to use for your output. Please use %f only (with modifiers)
-	file2.setFileType(kText);
-	file2.setEchoInterval(10000); // only print to the console 1 line every other 10000
-	return true; 
-}
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->analogFrames; n++) {
-			file1.log(&(context->analogIn[n*context->analogFrames]), 2); // log an array of values
-			file2.log(context->analogIn[n*context->analogFrames]); // log a single value
-	}
-}
-
-// cleanup_render() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in initialise_render().
-
-void cleanup(BelaContext *context, void *userData)
-{
-    
-}
--- a/examples/measure_noisefloor/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-extern int gBufferSize;
-
-using namespace std;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --buffer-size [-b] size  Set the analysis buffer size\n";
-	cerr << "   --help [-h]:             Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"buffer-size", 1, NULL, 'b'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// By default use a longer period size because latency is not an issue
-	settings.periodSize = 32;
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hb:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'b':
-				gBufferSize = atoi(optarg);
-				break;
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-	
-	if(gBufferSize < settings.periodSize)
-		gBufferSize = settings.periodSize;
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, 0) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/measure_noisefloor/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-
-#include <Bela.h>
-#include <cmath>
-
-int gBufferSize = 8192;
-
-// Double buffers to hold samples for noise analysis
-float *gReadBuffers[10], *gWriteBuffers[10];
-float *gBuffers0[10], *gBuffers1[10];
-
-int gWriteBufferPointers[10], gReadBufferPointers[10];
-
-// Task to analyse and print results which would otherwise be too slow for render()
-AuxiliaryTask gAnalysisTask;
-
-void analyseResults();
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{	
-	// Clear the filter data structures
-	for(int i = 0; i < 10; i++) {
-		gReadBufferPointers[i] = gWriteBufferPointers[i] = 0;
-		gBuffers0[i] = new float[gBufferSize];
-		gBuffers1[i] = new float[gBufferSize];		
-		gWriteBuffers[i] = gBuffers0[i];
-		gReadBuffers[i] = gBuffers1[i];
-		if(gBuffers0[i] == 0 || gBuffers1[i] == 0) {
-			rt_printf("Error allocating buffer %d\n", i);
-			return false;
-		}
-	}
-	
-	gAnalysisTask = Bela_createAuxiliaryTask(analyseResults, 50, "bela-analyse-results");
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	bool bufferIsFull = false;	// Whether at least one buffer has filled
-	
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		// Store audio inputs in buffer
-		for(unsigned int ch = 0; ch < context->audioChannels; ch++) {
-			if(gWriteBufferPointers[ch] < gBufferSize) {
-				gWriteBuffers[ch][gWriteBufferPointers[ch]] = 
-					context->audioIn[n * context->audioChannels + ch];
-				gWriteBufferPointers[ch]++;
-				if(gWriteBufferPointers[ch] >= gBufferSize)
-					bufferIsFull = true;
-			}
-		}
-	}
-	
-	if(context->analogChannels != 0) {
-		for(unsigned int n = 0; n < context->analogFrames; n++) {
-			// Store analog inputs in buffer, starting at channel 2
-			for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
-				if(gWriteBufferPointers[ch + 2] < gBufferSize) {
-					gWriteBuffers[ch + 2][gWriteBufferPointers[ch + 2]] = 
-						context->analogIn[n * context->analogChannels + ch];
-					gWriteBufferPointers[ch + 2]++;
-					if(gWriteBufferPointers[ch + 2] >= gBufferSize)
-						bufferIsFull = true;
-				}
-				
-				// Set all analog outputs to halfway point so they can be more
-				// easily measured for noise
-				context->analogOut[n * context->analogChannels + ch] = 0.5;
-			}
-		}	
-	}
-	
-
-	if(bufferIsFull) {
-		// Swap buffers and reset write pointers
-		for(int ch = 0; ch < 10; ch++) {
-			gReadBufferPointers[ch] = gWriteBufferPointers[ch];
-			gWriteBufferPointers[ch] = 0;
-			
-			if(gReadBuffers[ch] == gBuffers0[ch]) {
-				gReadBuffers[ch] = gBuffers1[ch];
-				gWriteBuffers[ch] = gBuffers0[ch];
-			}
-			else {
-				gReadBuffers[ch] = gBuffers0[ch];
-				gWriteBuffers[ch] = gBuffers1[ch];				
-			}
-		}
-		
-		Bela_scheduleAuxiliaryTask(gAnalysisTask);
-	}
-}
-
-void analyseResults()
-{
-	rt_printf("\e[1;1H\e[2J");	// Command to clear the screen
-
-	// Print the analysis results. channels 0-1 are audio, channels 2-9 are analog
-	for(int ch = 0; ch < 10; ch++) {
-		// Skip unused channels
-		if(gReadBufferPointers[ch] == 0)
-			continue;
-		
-		float mean = 0;
-		for(int n = 0; n < gReadBufferPointers[ch]; n++) {
-			mean += gReadBuffers[ch][n];
-		}
-		mean /= (float)gReadBufferPointers[ch];
-		
-		float rms = 0;
-		for(int n = 0; n < gReadBufferPointers[ch]; n++) {
-			rms += (gReadBuffers[ch][n] - mean) * (gReadBuffers[ch][n] - mean);
-		}				
-		rms = sqrtf(rms / (float)gReadBufferPointers[ch]);
-		
-		if(ch == 0)
-			rt_printf("Audio In L:  ");
-		else if(ch == 1)
-			rt_printf("Audio In R:  ");
-		else
-			rt_printf("Analog In %d: ", ch - 2);
-		
-		rt_printf("Noise %6.1fdB    DC offset %6.4f (%6.1fdB)    window size: %d\n", 
-					20.0f * log10f(rms),
-					mean, 
-					20.0f * log10f(fabsf(mean)),
-					gReadBufferPointers[ch]);
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	for(int i = 0; i < 10; i++) {
-		delete gBuffers0[i];
-		delete gBuffers1[i];
-	}
-}
--- a/examples/minimal/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-#include <Bela.h>
-
-bool setup(BelaContext *context, void *userData)
-{
-	return true;
-}
-
-void render(BelaContext *context, void *userData)
-{
-
-}
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
\ No newline at end of file
--- a/examples/mpr121/I2C_MPR121.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * I2C_MPR121.cpp
- *
- *  Created on: Oct 14, 2013
- *      Author: Victor Zappi
- */
-
-
-#include "I2C_MPR121.h"
-
-I2C_MPR121::I2C_MPR121() {
-
-}
-
-boolean I2C_MPR121::begin(uint8_t bus, uint8_t i2caddr) {
-  _i2c_address = i2caddr;
-	
-  if(initI2C_RW(bus, i2caddr, 0) > 0)
-	  return false;
-
-  // soft reset
-  writeRegister(MPR121_SOFTRESET, 0x63);
-  usleep(1000);
-  //delay(1);
-  for (uint8_t i=0; i<0x7F; i++) {
-  //  Serial.print("$"); Serial.print(i, HEX); 
-  //  Serial.print(": 0x"); Serial.println(readRegister8(i));
-  }
-  
-
-  writeRegister(MPR121_ECR, 0x0);
-
-  uint8_t c = readRegister8(MPR121_CONFIG2);
-  
-  if (c != 0x24) {
-	  rt_printf("MPR121 read 0x%x instead of 0x24\n", c);
-	  return false;
-  }
-
-  setThresholds(12, 6);
-  writeRegister(MPR121_MHDR, 0x01);
-  writeRegister(MPR121_NHDR, 0x01);
-  writeRegister(MPR121_NCLR, 0x0E);
-  writeRegister(MPR121_FDLR, 0x00);
-
-  writeRegister(MPR121_MHDF, 0x01);
-  writeRegister(MPR121_NHDF, 0x05);
-  writeRegister(MPR121_NCLF, 0x01);
-  writeRegister(MPR121_FDLF, 0x00);
-
-  writeRegister(MPR121_NHDT, 0x00);
-  writeRegister(MPR121_NCLT, 0x00);
-  writeRegister(MPR121_FDLT, 0x00);
-
-  writeRegister(MPR121_DEBOUNCE, 0);
-  writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
-  writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
-
-//  writeRegister(MPR121_AUTOCONFIG0, 0x8F);
-
-//  writeRegister(MPR121_UPLIMIT, 150);
-//  writeRegister(MPR121_TARGETLIMIT, 100); // should be ~400 (100 shifted)
-//  writeRegister(MPR121_LOWLIMIT, 50);
-  // enable all electrodes
-  writeRegister(MPR121_ECR, 0x8F);  // start with first 5 bits of baseline tracking
-
-  return true;
-}
-
-void I2C_MPR121::setThresholds(uint8_t touch, uint8_t release) {
-  for (uint8_t i=0; i<12; i++) {
-    writeRegister(MPR121_TOUCHTH_0 + 2*i, touch);
-    writeRegister(MPR121_RELEASETH_0 + 2*i, release);
-  }
-}
-
-uint16_t  I2C_MPR121::filteredData(uint8_t t) {
-  if (t > 12) return 0;
-  return readRegister16(MPR121_FILTDATA_0L + t*2);
-}
-
-uint16_t  I2C_MPR121::baselineData(uint8_t t) {
-  if (t > 12) return 0;
-  uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
-  return (bl << 2);
-}
-
-uint16_t  I2C_MPR121::touched(void) {
-  uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
-  return t & 0x0FFF;
-}
-
-/*********************************************************************/
-
-
-uint8_t I2C_MPR121::readRegister8(uint8_t reg) {
-    unsigned char inbuf, outbuf;
-    struct i2c_rdwr_ioctl_data packets;
-    struct i2c_msg messages[2];
-
-    /*
-     * In order to read a register, we first do a "dummy write" by writing
-     * 0 bytes to the register we want to read from.  This is similar to
-     * the packet in set_i2c_register, except it's 1 byte rather than 2.
-     */
-    outbuf = reg;
-    messages[0].addr  = 0x5A;
-    messages[0].flags = 0;
-    messages[0].len   = sizeof(outbuf);
-    messages[0].buf   = &outbuf;
-
-    /* The data will get returned in this structure */
-    messages[1].addr  = 0x5A;
-    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
-    messages[1].len   = sizeof(inbuf);
-    messages[1].buf   = &inbuf;
-
-    /* Send the request to the kernel and get the result back */
-    packets.msgs      = messages;
-    packets.nmsgs     = 2;
-    if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
-        rt_printf("Unable to send data");
-        return 0;
-    }
-
-    return inbuf;
-}
-
-uint16_t I2C_MPR121::readRegister16(uint8_t reg) {
-    unsigned char inbuf[2], outbuf;
-    struct i2c_rdwr_ioctl_data packets;
-    struct i2c_msg messages[2];
-
-    /*
-     * In order to read a register, we first do a "dummy write" by writing
-     * 0 bytes to the register we want to read from.  This is similar to
-     * the packet in set_i2c_register, except it's 1 byte rather than 2.
-     */
-    outbuf = reg;
-    messages[0].addr  = _i2c_address;
-    messages[0].flags = 0;
-    messages[0].len   = sizeof(outbuf);
-    messages[0].buf   = &outbuf;
-
-    /* The data will get returned in this structure */
-    messages[1].addr  = _i2c_address;
-    messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
-    messages[1].len   = sizeof(inbuf);
-    messages[1].buf   = inbuf;
-
-    /* Send the request to the kernel and get the result back */
-    packets.msgs      = messages;
-    packets.nmsgs     = 2;
-    if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
-        rt_printf("Unable to send data");
-        return 0;
-    }
-
-    return (uint16_t)inbuf[0] | (((uint16_t)inbuf[1]) << 8);
-}
-
-/**************************************************************************/
-/*!
-    @brief  Writes 8-bits to the specified destination register
-*/
-/**************************************************************************/
-void I2C_MPR121::writeRegister(uint8_t reg, uint8_t value) {
-	uint8_t buf[2] = { reg, value };
-
-	if(write(i2C_file, buf, 2) != 2)
-	{
-		cout << "Failed to write register " << (int)reg << " on MPR121\n";
-		return;
-	}
-}
-
--- a/examples/mpr121/I2C_MPR121.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * MPR121 Bela demo
- * 
- * Andrew McPherson
- * Based on Adafruit library by Limor Fried/Ladyada
- */
-
-#ifndef I2CTK_H_
-#define I2CTK_H_
-
-#include <I2c.h>
-#include "Utilities.h"
-
-typedef bool boolean;
-
-#define MPR121_I2CADDR_DEFAULT 0x5A
-
-#define MPR121_TOUCHSTATUS_L 0x00
-#define MPR121_TOUCHSTATUS_H 0x01
-#define MPR121_FILTDATA_0L  0x04
-#define MPR121_FILTDATA_0H  0x05
-#define MPR121_BASELINE_0   0x1E
-#define MPR121_MHDR         0x2B
-#define MPR121_NHDR         0x2C
-#define MPR121_NCLR         0x2D
-#define MPR121_FDLR         0x2E
-#define MPR121_MHDF         0x2F
-#define MPR121_NHDF         0x30
-#define MPR121_NCLF         0x31
-#define MPR121_FDLF         0x32
-#define MPR121_NHDT         0x33
-#define MPR121_NCLT         0x34
-#define MPR121_FDLT         0x35
-
-#define MPR121_TOUCHTH_0    0x41
-#define MPR121_RELEASETH_0    0x42
-#define MPR121_DEBOUNCE 0x5B
-#define MPR121_CONFIG1 0x5C
-#define MPR121_CONFIG2 0x5D
-#define MPR121_CHARGECURR_0 0x5F
-#define MPR121_CHARGETIME_1 0x6C
-#define MPR121_ECR 0x5E
-#define MPR121_AUTOCONFIG0 0x7B
-#define MPR121_AUTOCONFIG1 0x7C
-#define MPR121_UPLIMIT   0x7D
-#define MPR121_LOWLIMIT  0x7E
-#define MPR121_TARGETLIMIT  0x7F
-
-#define MPR121_GPIODIR  0x76
-#define MPR121_GPIOEN  0x77
-#define MPR121_GPIOSET  0x78
-#define MPR121_GPIOCLR  0x79
-#define MPR121_GPIOTOGGLE  0x7A
-
-#define MPR121_SOFTRESET 0x80
-
-class I2C_MPR121 : public I2c
-{
-public:
-	// Hardware I2C
-	I2C_MPR121();
-
-	boolean begin(uint8_t bus = 1, uint8_t i2caddr = MPR121_I2CADDR_DEFAULT);
-
-	uint16_t filteredData(uint8_t t);
-	uint16_t  baselineData(uint8_t t);
-
-	uint8_t readRegister8(uint8_t reg);
-	uint16_t readRegister16(uint8_t reg);
-	void writeRegister(uint8_t reg, uint8_t value);
-	uint16_t touched(void);
- 
- 	void setThresholds(uint8_t touch, uint8_t release);
-	
-	int readI2C() { return 0; } // Unused
-	
-private:
-	int _i2c_address;
-};
-
-
-#endif /* I2CTK_H_ */
--- a/examples/mpr121/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-#include <Bela.h>
-#include <cmath>
-#include <rtdk.h>
-#include "I2C_MPR121.h"
-
-// How many pins there are
-#define NUM_TOUCH_PINS 12
-
-// Define this to print data to terminal
-#undef DEBUG_MPR121
-
-// Change this to change how often the MPR121 is read (in Hz)
-int readInterval = 50;
-
-// Change this threshold to set the minimum amount of touch
-int threshold = 40;
-
-// This array holds the continuous sensor values
-int sensorValue[NUM_TOUCH_PINS];
-
-// ---- test code stuff -- can be deleted for your example ----
-
-// 12 notes of a C major scale...
-float gFrequencies[NUM_TOUCH_PINS] = {261.63, 293.66, 329.63, 349.23, 392.00, 440.00, 493.88, 523.25, 587.33, 659.25, 698.25, 783.99};
-
-// This is internal stuff for the demo
-float gNormFrequencies[NUM_TOUCH_PINS];
-float gPhases[NUM_TOUCH_PINS] = {0};
-
-// ---- internal stuff -- do not change -----
-
-I2C_MPR121 mpr121;			// Object to handle MPR121 sensing
-AuxiliaryTask i2cTask;		// Auxiliary task to read I2C
-
-int readCount = 0;			// How long until we read again...
-int readIntervalSamples = 0; // How many samples between reads
-
-void readMPR121();
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	if(!mpr121.begin(1, 0x5A)) {
-		rt_printf("Error initialising MPR121\n");
-		return false;
-	}
-	
-	i2cTask = Bela_createAuxiliaryTask(readMPR121, 50, "bela-mpr121");
-	readIntervalSamples = context->audioSampleRate / readInterval;
-	
-	for(int i = 0; i < NUM_TOUCH_PINS; i++) {
-		gNormFrequencies[i] = 2.0 * M_PI * gFrequencies[i] / context->audioSampleRate;
-	}
-	
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numAnalogFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(int n = 0; n < context->audioFrames; n++) {
-		// Keep this code: it schedules the touch sensor readings
-		if(++readCount >= readIntervalSamples) {
-			readCount = 0;
-			Bela_scheduleAuxiliaryTask(i2cTask);
-		}
-		
-		float sample = 0.0;
-		
-		// This code can be replaced with your favourite audio code
-		for(int i = 0; i < NUM_TOUCH_PINS; i++) {
-			float amplitude = sensorValue[i] / 400.0;
-			
-			// Prevent clipping
-			if(amplitude > 0.5)
-				amplitude = 0.5;
-			
-			sample += amplitude * sinf(gPhases[i]);
-			gPhases[i] += gNormFrequencies[i];
-			if(gPhases[i] > 2.0 * M_PI)
-				gPhases[i] -= 2.0 * M_PI;
-		}
-		
-		for(int ch = 0; ch < context->audioChannels; ch++)
-			context->audioOut[context->audioChannels * n + ch] = sample;
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	// Nothing to do here
-}
-
-
-// Auxiliary task to read the I2C board
-void readMPR121()
-{
-	for(int i = 0; i < NUM_TOUCH_PINS; i++) {
-		sensorValue[i] = -(mpr121.filteredData(i) - mpr121.baselineData(i));
-		sensorValue[i] -= threshold;
-		if(sensorValue[i] < 0)
-			sensorValue[i] = 0;
-#ifdef DEBUG_MPR121
-		rt_printf("%d ", sensorValue[i]);
-#endif
-	}
-#ifdef DEBUG_MPR121
-	rt_printf("\n");
-#endif
-	
-	// You can use this to read binary on/off touch state more easily
-	//rt_printf("Touched: %x\n", mpr121.touched());
-}
--- a/examples/osc/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/**
-\example 5_osc
-
-Open Sound Control
-------------------
-
-This example shows an implementation of OSC (Open Sound Control) which was 
-developed at UC Berkeley Center for New Music and Audio Technology (CNMAT).
-
-It is designed to be run alongside resources/osc/osc.js
-
-The OSC server port on which to receive is set in `setup()` 
-via `oscServer.setup()`. Likewise the OSC client port on which to 
-send is set in `oscClient.setup()`.
-
-In `setup()` an OSC message to address `/osc-setup`, it then waits 
-1 second for a reply on `/osc-setup-reply`.
-
-in `render()` the code receives OSC messages, parses them, and sends 
-back an acknowledgment.
-*/
-
-#include <Bela.h>
-#include <OSCServer.h>
-#include <OSCClient.h>
-
-OSCServer oscServer;
-OSCClient oscClient;
-
-// this example is designed to be run alongside resources/osc/osc.js
-
-// parse messages recieved by OSC Server
-// msg is Message class of oscpkt: http://gruntthepeon.free.fr/oscpkt/
-void parseMessage(oscpkt::Message msg){
-    
-    rt_printf("recieved message to: %s\n", msg.addressPattern().c_str());
-    
-    int intArg;
-    float floatArg;
-    if (msg.match("/osc-test").popInt32(intArg).popFloat(floatArg).isOkNoMoreArgs()){
-        rt_printf("recieved int %i and float %f\n", intArg, floatArg);
-    }
-    
-}
-
-bool setup(BelaContext *context, void *userData)
-{
-    // setup the OSC server to recieve on port 7562
-    oscServer.setup(7562);
-    // setup the OSC client to send on port 7563
-    oscClient.setup(7563);
-    
-    // the following code sends an OSC message to address /osc-setup
-    // then waits 1 second for a reply on /osc-setup-reply
-    bool handshakeRecieved = false;
-    oscClient.sendMessageNow(oscClient.newMessage.to("/osc-setup").end());
-    oscServer.recieveMessageNow(1000);
-    while (oscServer.messageWaiting()){
-        if (oscServer.popMessage().match("/osc-setup-reply")){
-            handshakeRecieved = true;
-        }
-    }
-    
-    if (handshakeRecieved){
-        rt_printf("handshake recieved!\n");
-    } else {
-        rt_printf("timeout!\n");
-    }
-    
-	return true;
-}
-
-void render(BelaContext *context, void *userData)
-{
-    // recieve OSC messages, parse them, and send back an acknowledgment
-    while (oscServer.messageWaiting()){
-        parseMessage(oscServer.popMessage());
-        oscClient.queueMessage(oscClient.newMessage.to("/osc-acknowledge").add(5).add(4.2f).add(std::string("OSC message recieved")).end());
-    }
-}
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/oscillator_bank/audio_routines.S	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-@
-@ audio_routines.S
-@
-@ NEON-based functions for time-critical audio processing
-@
-@ Andrew McPherson 2014
-@ Queen Mary University of London
-@
-
-	.syntax unified
-	.arch armv7-a
-	.fpu neon
-
-@ 	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
-@							  int activePartialNum, int lookupTableSize,
-@							  float *phases, float *frequencies, float *amplitudes,
-@							  float *freqDerivatives, float *ampDerivatives,
-@							  float *lookupTable);
-
-@ Registers:
-@    r0: numAudioFrames        How many frames to render
-@    r1: audioOut              Buffer for audio output samples [stereo]
-@    r2: activePartialNum      How many active partials to render
-@    r3: lookupTableSize       Size of lookup table
-@    ---- other arguments start on the stack and are moved: -----
-@    r4: phases                Phase of each oscillator (pointer)
-@    r5: frequencies           Normalised frequency of each oscillator (pointer)
-@    r6: amplitudes            Normalised amplitude of each oscillator (pointer)
-@    r7: freqDerivatives       Derivative of frequency for each oscillator (pointer)
-@    r8: ampDerivatives        Derivative of amplitude for each oscillator (pointer)
-@    r9: lookupTable           Lookup table containing one oscillation
-@
-@ Alignment requirements:
-@    audioOut: 8-byte boundary
-@    phases: 16-byte boundary
-@    frequencies: 16-byte boundary
-@    amplitudes: 16-byte boundary
-@    freqDerivatives: 16-byte bounary
-@    ampDerivatives: 16-byte boundary
-@    lookupTable: 4-byte boundary (TODO: check this)
-
-	.align	2
-	.global	oscillator_bank_neon
-	.thumb
-	.thumb_func
-	.type	oscillator_bank_neon, %function
-oscillator_bank_neon:
-
-
-dSample		.dn		D6.F32
-qPhases		.qn		Q8.F32
-dPhases_0	.dn		D16.F32
-dPhases_1	.dn		D17.F32
-qFreqs		.qn		Q9.F32
-dFreqs_0	.dn		D18.F32
-dFreqs_1	.dn		D19.F32
-qAmps		.qn		Q10.F32
-dAmps_0		.dn		D20.F32
-dAmps_1		.dn		D21.F32
-qFreqDs		.qn		Q11.F32
-dFreqDs_0	.dn		D22.F32
-dFreqDs_1	.dn		D23.F32
-qAmpDs		.qn		Q12.F32
-dAmpDs_0	.dn		D24.F32
-dAmpDs_1	.dn		D25.F32
-
-qBaseInts	.qn		Q13.U32		@ Base indexes: unsigned ints x4
-dBaseInts_0	.dn		D26.U32
-dBaseInts_1	.dn		D27.U32
-qFractions  .qn     Q14.F32		@ Fraction indexes: floats x4
-qTableBase	.qn		Q15.U32		@ Base of lookup table
-
-	cmp r0, #0					@ Check for trivial case 1: zero frames
-	it eq
-	bxeq lr						@ Return if that's the case (otherwise might have odd behaviour)
-	cmp r2, #4					@ Check for trivial case 2: zero oscillators
-	it lt
-	bxlt lr						@ Return if that's the case
-
-	push {r4-r11}				@ Now arguments start 32 bytes above SP
-    add r11, sp, #32			@ Pointer to 32 bytes into the stack
-    ldm r11, {r4-r9}			@ Load 6 arguments into registers
-
-	vdup qTableBase, r9			@ Move lookup table base index into 4 ints
-
-	@ Outer loop: iterate over the number of oscillators, choosing 4 at a
-	@ time to work with.
-oscbank_oscillator_loop:
-	vld1 {dPhases_0, dPhases_1}, [r4]		@ no increment; will store at end of sample loop
-	vld1 {dFreqs_0, dFreqs_1}, [r5]
-	vld1 {dAmps_0, dAmps_1}, [r6]
-	vld1 {dFreqDs_0, dFreqDs_1}, [r7]!		@ increment; won't update at end of sample loop
-	vld1 {dAmpDs_0, dAmpDs_1}, [r8]!
-
-	push {r0-r1,r4-r8}
-	@ --- inner loop: iterate over the number of samples ---
-oscbank_sample_loop:
-	vcvt qBaseInts, qPhases		     		@ Take floor(phases)
-	vmov q2.f32, #1.0						@ Load 1.0 into every slot of q2
-	vshl q0.U32, qBaseInts, #2				@ Shift the indexes left 2 (*4 for float addressing)
-	vcvt qFractions, qBaseInts				@ int back to float
-	vadd q0.U32, q0.U32, qTableBase			@ Find memory addresses
-
-	vmov r4, r5, d0							@ Move two indexes to ARM registers
-	vmov r6, r7, d1							@ Move two more indexes to ARM registers
-	vsub qFractions, qPhases, qFractions	@ fraction = phase - floor(phase)
-
-	vldr.64	d0, [r4]						@ Load two consecutive floats at each location
-	vldr.64 d1, [r5]						@ These hold the previous and following samples in the table
-	vldr.64	d2, [r6]						@ TODO: check whether these work at 4-byte alignment
-	vldr.64 d3, [r7]
-
-	@ Format at this point:
-	@ Osc0(before) Osc0(after) Osc1(before) Osc1(after) Osc2(before) Osc2(after) Osc3(before) Osc3(after)
-	@ We want:
-	@ Osc0(before) Osc1(before) Osc2(before) Osc3(before) Osc0(after) Osc1(after) Osc2(after) Osc3(after)
-
-	vuzp.32 q0, q1							@ Now q0 contains before, q1 contains after
-	vsub q2.f32, q2.f32, qFractions			@ q2 = 1.0 - fraction
-	vmul q1.f32, q1.f32, qFractions			@ q1 = fraction * after
-	vmul q0.f32, q0.f32, q2.f32				@ q0 = (1.0 - fraction) * before
-
-	vadd qPhases, qPhases, qFreqs			@ Update phases
-	vadd qFreqs, qFreqs, qFreqDs			@ Update frequencies
-
-	vadd q0.f32, q0.f32, q1.f32				@ Add two interpolated components to get the final sample
-	vdup q2.u32, r3							@ Put lookup table size into each element of q2
-	vcvt qBaseInts, qPhases					@ Take floor of new phases
-	vmul q0.f32, q0.f32, qAmps				@ Multiply samples by current amplitude
-
-	vld1 dSample, [r1]						@ Load the current stereo samples
-	vpadd d2.f32, d0.f32, d1.f32			@ Pairwise accumulate q0 (output sample) into d2
-
-	vand q2, q2, qBaseInts					@ Logical AND of new phase int leaves 1 bit set only if phase >= table size
-	vpadd d3.f32, d2.f32, d2.f32			@ Pairwise accumulate d2 into d0 --> d0[0] and d0[1] both hold total of 4 oscillators
-	vadd qAmps, qAmps, qAmpDs				@ Update amplitudes
-	vcvt q0.f32, q2.u32						@ Convert int back to float after AND operation
-
-	vadd  dSample, dSample, d3.f32			@ Add oscillator outputs to each channel
-
-	subs r0, r0, #1							@ numFrames--
-	vsub qPhases, qPhases, q0.f32			@ Keep phases in table range
-	vst1 dSample, [r1]!						@ Store back in buffer and increment by 8
-
-	it gt
-	bgt oscbank_sample_loop					@ Loop if numFrames > 0
-
-	@ --- end inner loop ---
-	pop {r0-r1,r4-r8}						@ Restore registers: restores audioOut and numFrames, among others
-
-	vst1 {dPhases_0, dPhases_1}, [r4]!		@ Store phases back to array
-	vst1 {dFreqs_0, dFreqs_1}, [r5]!		@ Store frequencies back to array
-	vst1 {dAmps_0, dAmps_1}, [r6]!			@ Store amplitudes back to array
-											@ No need to update r7, r8
-
-	subs r2, r2, #4							@ numPartials -= 4
-	it  gt
-	bgt oscbank_oscillator_loop	@ Loop if numPartials > 0
-
-    pop {r4-r11}
-	bx lr
--- a/examples/oscillator_bank/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <Bela.h>
-
-using namespace std;
-
-int gNumOscillators = 32;
-int gWavetableLength = 1024;
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --num-oscillators [-n] oscs: Set the number of oscillators to use (default: 32)\n";
-	cerr << "   --wavetable [-w] length:     Set the wavetable length in samples (default: 1024)\n";
-	cerr << "   --help [-h]:                 Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"num-oscillators", 1, NULL, 'n'},
-		{"wavetable", 1, NULL, 'w'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hn:w:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'n':
-				gNumOscillators = atoi(optarg);
-				if(gNumOscillators <= 0) {
-					usage(basename(argv[0]));
-					exit(0);
-				}
-				break;
-		case 'w':
-				gWavetableLength = atoi(optarg);
-				if(gWavetableLength < 4)
-					gWavetableLength = 4;
-				if(gWavetableLength > 16384)
-					gWavetableLength = 16384;
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, 0) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	if(settings.verbose) {
-		cout << "--> Using " << gNumOscillators << " oscillators and wavetable of " << gWavetableLength << " samples\n";
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/oscillator_bank/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-/**
-\example 4_oscillator_bank
-
-Oscillator Bank
-----------------------
-
-These files demonstrate an oscillator bank implemented in assembly code 
-that is used as part of the d-box project.
-*/
-
-#include <Bela.h>
-#include <rtdk.h>
-#include <cstdlib>
-#include <cmath>
-#include <cstring>
-#include <time.h>
-
-const float kMinimumFrequency = 20.0f;
-const float kMaximumFrequency = 8000.0f;
-
-float *gWavetable;		// Buffer holding the precalculated sine lookup table
-float *gPhases;			// Buffer holding the phase of each oscillator
-float *gFrequencies;	// Buffer holding the frequencies of each oscillator
-float *gAmplitudes;		// Buffer holding the amplitudes of each oscillator
-float *gDFrequencies;	// Buffer holding the derivatives of frequency
-float *gDAmplitudes;	// Buffer holding the derivatives of amplitude
-
-float gAudioSampleRate;
-int gSampleCount;		// Sample counter for indicating when to update frequencies
-float gNewMinFrequency;
-float gNewMaxFrequency;
-
-// Task for handling the update of the frequencies using the matrix
-AuxiliaryTask gFrequencyUpdateTask;
-
-// These settings are carried over from main.cpp
-// Setting global variables is an alternative approach
-// to passing a structure to userData in setup()
-
-extern int gNumOscillators;
-extern int gWavetableLength;
-
-void recalculate_frequencies();
-
-extern "C" {
-	// Function prototype for ARM assembly implementation of oscillator bank
-	void oscillator_bank_neon(int numAudioFrames, float *audioOut,
-							  int activePartialNum, int lookupTableSize,
-							  float *phases, float *frequencies, float *amplitudes,
-							  float *freqDerivatives, float *ampDerivatives,
-							  float *lookupTable);
-}
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-bool setup(BelaContext *context, void *userData)
-{
-	srandom(time(NULL));
-
-	if(context->audioChannels != 2) {
-		rt_printf("Error: this example needs stereo audio enabled\n");
-		return false;
-	}
-
-	// Initialise the sine wavetable
-	if(posix_memalign((void **)&gWavetable, 8, (gWavetableLength + 1) * sizeof(float))) {
-		rt_printf("Error allocating wavetable\n");
-		return false;
-	}
-	for(int n = 0; n < gWavetableLength + 1; n++)
-		gWavetable[n] = sinf(2.0 * M_PI * (float)n / (float)gWavetableLength);
-
-	// Allocate the other buffers
-	if(posix_memalign((void **)&gPhases, 16, gNumOscillators * sizeof(float))) {
-		rt_printf("Error allocating phase buffer\n");
-		return false;
-	}
-	if(posix_memalign((void **)&gFrequencies, 16, gNumOscillators * sizeof(float))) {
-		rt_printf("Error allocating frequency buffer\n");
-		return false;
-	}
-	if(posix_memalign((void **)&gAmplitudes, 16, gNumOscillators * sizeof(float))) {
-		rt_printf("Error allocating amplitude buffer\n");
-		return false;
-	}
-	if(posix_memalign((void **)&gDFrequencies, 16, gNumOscillators * sizeof(float))) {
-		rt_printf("Error allocating frequency derivative buffer\n");
-		return false;
-	}
-	if(posix_memalign((void **)&gDAmplitudes, 16, gNumOscillators * sizeof(float))) {
-		rt_printf("Error allocating amplitude derivative buffer\n");
-		return false;
-	}
-
-	// Initialise buffer contents
-
-	float freq = kMinimumFrequency;
-	float increment = (kMaximumFrequency - kMinimumFrequency) / (float)gNumOscillators;
-
-	for(int n = 0; n < gNumOscillators; n++) {
-		gPhases[n] = 0.0;
-
-		if(context->analogFrames == 0) {
-			// Random frequencies when used without matrix
-			gFrequencies[n] = kMinimumFrequency + (kMaximumFrequency - kMinimumFrequency) * ((float)random() / (float)RAND_MAX);
-		}
-		else {
-			// Constant spread of frequencies when used with matrix
-			gFrequencies[n] = freq;
-			freq += increment;
-		}
-
-		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
-		gFrequencies[n] *= (float)gWavetableLength / context->audioSampleRate;
-		gAmplitudes[n] = ((float)random() / (float)RAND_MAX) / (float)gNumOscillators;
-		gDFrequencies[n] = gDAmplitudes[n] = 0.0;
-	}
-
-	increment = 0;
-	freq = 440.0;
-
-	for(int n = 0; n < gNumOscillators; n++) {
-		// Update the frequencies to a regular spread, plus a small amount of randomness
-		// to avoid weird phase effects
-		float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
-		float newFreq = freq * randScale;
-
-		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
-		gFrequencies[n] = newFreq * (float)gWavetableLength / context->audioSampleRate;
-
-		freq += increment;
-	}
-
-	// Initialise auxiliary tasks
-	if((gFrequencyUpdateTask = Bela_createAuxiliaryTask(&recalculate_frequencies, 85, "bela-update-frequencies")) == 0)
-		return false;
-
-	//for(int n = 0; n < gNumOscillators; n++)
-	//	rt_printf("%f\n", gFrequencies[n]);
-
-	gAudioSampleRate = context->audioSampleRate;
-	gSampleCount = 0;
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	// Initialise buffer to 0
-	memset(context->audioOut, 0, 2 * context->audioFrames * sizeof(float));
-
-	// Render audio frames
-	oscillator_bank_neon(context->audioFrames, context->audioOut,
-			gNumOscillators, gWavetableLength,
-			gPhases, gFrequencies, gAmplitudes,
-			gDFrequencies, gDAmplitudes,
-			gWavetable);
-
-	if(context->analogFrames != 0 && (gSampleCount += context->audioFrames) >= 128) {
-		gSampleCount = 0;
-		gNewMinFrequency = map(context->analogIn[0], 0, 1.0, 1000.0f, 8000.0f);
-		gNewMaxFrequency = map(context->analogIn[1], 0, 1.0, 1000.0f, 8000.0f);
-
-		// Make sure max >= min
-		if(gNewMaxFrequency < gNewMinFrequency) {
-			float temp = gNewMaxFrequency;
-			gNewMaxFrequency = gNewMinFrequency;
-			gNewMinFrequency = temp;
-		}
-
-		// Request that the lower-priority task run at next opportunity
-		//Bela_scheduleAuxiliaryTask(gFrequencyUpdateTask);
-	}
-}
-
-// This is a lower-priority call to update the frequencies which will happen
-// periodically when the matrix is enabled. By placing it at a lower priority,
-// it has minimal effect on the audio performance but it will take longer to
-// complete if the system is under heavy audio load.
-
-void recalculate_frequencies()
-{
-	float freq = gNewMinFrequency;
-	float increment = (gNewMaxFrequency - gNewMinFrequency) / (float)gNumOscillators;
-
-	for(int n = 0; n < gNumOscillators; n++) {
-		// Update the frequencies to a regular spread, plus a small amount of randomness
-		// to avoid weird phase effects
-		float randScale = 0.99 + .02 * (float)random() / (float)RAND_MAX;
-		float newFreq = freq * randScale;
-
-		// For efficiency, frequency is expressed in change in wavetable position per sample, not Hz or radians
-		gFrequencies[n] = newFreq * (float)gWavetableLength / gAudioSampleRate;
-
-		freq += increment;
-	}
-}
-
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	free(gWavetable);
-	free(gPhases);
-	free(gFrequencies);
-	free(gAmplitudes);
-	free(gDFrequencies);
-	free(gDAmplitudes);
-}
--- a/examples/pd/basicAnalogIn/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#N canvas 203 356 637 339 10;
-#X obj 63 170 osc~ 440;
-#X obj 63 223 dac~;
-#X obj 63 191 *~;
-#X text 440 95 ADC 3: Analog In 0;
-#X text 34 41 Basic analog in (or 'theremin');
-#X text 34 51 ===============================;
-#X text 121 105 << Use first two analog in's;
-#X text 440 49 ADC routing:;
-#X text 440 57 ------------;
-#X text 440 105 ADC 4: Analog In 1;
-#X text 440 115 ADC 5: Analog In 2;
-#X text 440 125 ADC 6: Analog In 3;
-#X text 440 135 ADC 7: Analog In 4;
-#X text 440 145 ADC 8: Analog In 5;
-#X text 440 155 ADC 9: Analog In 6;
-#X text 440 165 ADC 10: Analog In 7;
-#X text 440 75 ADC 1: Audio In L;
-#X text 440 85 ADC 2: Audio In R;
-#X obj 63 149 *~ 880;
-#X obj 63 106 adc~ 3 4;
-#X text 355 277 ---------------------------------;
-#X text 355 267 @krighxz / BELA / heavy / 12/2015;
-#X text 379 286 beaglert.cc / enzienaudio.com;
-#X connect 0 0 2 0;
-#X connect 2 0 1 0;
-#X connect 2 0 1 1;
-#X connect 18 0 0 0;
-#X connect 19 0 18 0;
-#X connect 19 1 2 1;
--- a/examples/pd/basicAnalogOut/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#N canvas 275 504 679 362 10;
-#X text 148 124 << Use first two analog in's;
-#X text 431 57 ------------;
-#X text 44 51 Basic analog out;
-#X text 44 61 ================;
-#X text 431 95 DAC 3: Analog Out 0;
-#X text 431 105 DAC 4: Analog Out 1;
-#X text 431 115 DAC 5: Analog Out 2;
-#X text 431 125 DAC 6: Analog Out 3;
-#X text 431 145 DAC 8: Analog Out 5;
-#X text 431 135 DAC 7: Analog Out 4;
-#X text 431 155 DAC 9: Analog Out 6;
-#X text 431 165 DAC 10: Analog Out 7;
-#X text 431 85 DAC 2: Audio Out R;
-#X text 431 75 DAC 1: Audio Out L;
-#X obj 92 201 *~;
-#X obj 92 159 *~ 10;
-#X obj 92 180 osc~ 1;
-#X obj 35 242 dac~ 1 2 3;
-#X text 143 241 << Output to first analog out;
-#X text 431 49 DAC routing:;
-#X text 432 289 ---------------------------------;
-#X text 432 279 @krighxz / BELA / heavy / 12/2015;
-#X text 456 298 beaglert.cc / enzienaudio.com;
-#X obj 92 125 adc~ 3 4;
-#X connect 14 0 17 2;
-#X connect 15 0 16 0;
-#X connect 16 0 14 0;
-#X connect 23 0 15 0;
-#X connect 23 1 14 1;
--- a/examples/pd/circularBuffer/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#N canvas 436 490 738 494 10;
-#X obj 135 167 loadbang;
-#X msg 135 212 1;
-#X obj 183 234 / 44.1;
-#X obj 135 253 metro;
-#X obj 135 286 f;
-#X obj 160 286 + 64;
-#X obj 160 308 % 65536, f 8;
-#X msg 160 329 start \$1;
-#X obj 160 351 tabwrite~ circbuf;
-#X obj 363 303 - 32768;
-#X obj 363 325 + 65536;
-#X obj 363 347 % 65536;
-#X obj 342 371 +~ 0;
-#X msg 381 236 0;
-#X obj 342 258 phasor~;
-#X obj 342 392 tabread4~ circbuf;
-#X obj 341 415 dac~;
-#N canvas 422 781 312 126 buf 0;
-#N canvas 0 22 450 278 (subpatch) 0;
-#X array circbuf 65536 float 2;
-#X coords 0 1 65535 -1 256 64 1 0 0;
-#X restore 23 28 graph;
-#X restore 129 441 pd buf;
-#X obj 32 101 osc~ 440;
-#X obj 342 213 samplerate~;
-#X obj 134 189 t b b b b;
-#X text 30 82 audio input;
-#X text 219 310 write pointer;
-#X text 412 349 read pointer;
-#X obj 342 282 *~ 16;
-#X obj 342 236 / 16;
-#X obj 183 214 f 16;
-#X obj 363 189 r \$0-blocksize;
-#X obj 204 186 r \$0-blocksize;
-#X obj 394 259 r \$0-blocksize;
-#X obj 390 123 s \$0-blocksize;
-#X text 34 13 VIRTUAL CIRCULAR BUFFER;
-#X text 34 23 =======================;
-#X obj 390 55 loadbang;
-#X msg 390 77 16;
-#X text 517 454 ---------------------------------;
-#X text 517 444 @krighxz / BELA / heavy / 12/2015;
-#X text 541 463 beaglert.cc / enzienaudio.com;
-#X text 426 78 << replace with target blocksize;
-#X text 446 90 BELA default: 16;
-#X text 446 102 PD default: 64;
-#X connect 0 0 20 0;
-#X connect 1 0 3 0;
-#X connect 2 0 3 1;
-#X connect 3 0 4 0;
-#X connect 4 0 5 0;
-#X connect 5 0 6 0;
-#X connect 5 0 9 0;
-#X connect 6 0 7 0;
-#X connect 6 0 4 1;
-#X connect 7 0 8 0;
-#X connect 9 0 10 0;
-#X connect 10 0 11 0;
-#X connect 11 0 12 1;
-#X connect 12 0 15 0;
-#X connect 13 0 14 1;
-#X connect 14 0 24 0;
-#X connect 15 0 16 0;
-#X connect 15 0 16 1;
-#X connect 18 0 8 0;
-#X connect 19 0 25 0;
-#X connect 20 0 1 0;
-#X connect 20 1 26 0;
-#X connect 20 2 13 0;
-#X connect 20 3 19 0;
-#X connect 24 0 12 0;
-#X connect 25 0 14 0;
-#X connect 26 0 2 0;
-#X connect 27 0 25 1;
-#X connect 28 0 26 1;
-#X connect 29 0 24 1;
-#X connect 33 0 34 0;
-#X connect 34 0 30 0;
--- a/examples/pd/digital/bela_digital-help.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-#N canvas 121 46 877 628 10;
-#X obj 64 94 r bela_digitalIn11;
-#X obj 219 94 r bela_digitalIn12;
-#X obj 386 107 adc~ 13 14;
-#X text 49 64 Digital in \, message rate;
-#X text 214 69 Digital in \, message rate;
-#X text 394 85 Digital ins \, signal rate;
-#X obj 32 283 s bela_digitalOut15;
-#X text 13 309 Digital out \, message rate;
-#X obj 396 593 s bela_setDigital;
-#X obj 396 533 loadbang;
-#X msg 431 401 in 11;
-#X text 524 390 First argument is the pin direction Second argument
-is the pin number Third argument is the rate \, can be "~" or "sig"
-for signal-rate or "message" for message-rate. Defaults to message-rate.
-;
-#X msg 431 458 in 13 ~;
-#X msg 432 429 in 12 message;
-#X msg 517 506 disable 17;
-#X obj 386 139 snapshot~;
-#X obj 500 134 snapshot~;
-#X obj 529 56 loadbang;
-#X obj 384 181 print digitalIn13;
-#X obj 500 183 print digitalIn14;
-#X obj 497 105 metro 200;
-#X text 525 474 To stop using a pin (e.g.: to save CPU) \, send a disable
-message containing the pin number;
-#X obj 224 280 dac~ 16;
-#X obj 22 232 metro 500;
-#X obj 32 257 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
-1;
-#X obj 224 253 phasor~ 300;
-#X text 160 234 Nice \, anti-aliased square wave;
-#X obj 22 207 loadbang;
-#X text 15 181 Blink that LED!;
-#X obj 411 306 dac~ 17;
-#X obj 405 248 osc~ 300;
-#X obj 470 248 phasor~ 169;
-#X obj 457 278 -~ 0.5;
-#X text 403 210 Sum signals together for unpredictable effects;
-#X obj 612 303 dac~ 18;
-#X text 198 305 Digital out \, signal rate;
-#X text 378 325 Digital out \, signal rate;
-#X text 588 325 Digital out \, signal rate;
-#X obj 608 222 adc~;
-#X obj 612 249 *~ 0.5;
-#X obj 612 276 +~ 0.5;
-#X text 585 203 The ultimate bit-crusher;
-#X msg 426 555 in 11 \, in 12 \, in 13 ~ \, in 14 ~ \, out 15 \, out
-16 ~ \, out 17 ~ \, out 18 ~;
-#X text 23 377 Each digital channel can be configured as either an
-input or an output. Send messages to bela_setDigital to configure the
-digitalPins (needed before using them). Pins settings can be modified
-at will during execution. Message-rate input pins receive messages
-only when the input changes. Message-rate output pins will write to
-the output the most recent value you send them. Signal-rate inputs
-and outputs are handled as regular audio channels. Outputs are thresholded
-to 0.5 before being written to the actual output. Note that each pin
-that is managed adds to the CPU usage \, so only activate the pins
-you actually need.;
-#X text 34 19 Digital channels are numbered 11 to 26 \, which corresponds
-to Bela's 0 to 15 digital channels. They can be set to respond at message
-rate or at signal rate;
-#X obj 415 271 osc~ 1;
-#X obj 385 157 change;
-#X obj 500 158 change;
-#X obj 64 116 print digitalIn11;
-#X obj 219 117 print digitalIn12;
-#X connect 0 0 48 0;
-#X connect 1 0 49 0;
-#X connect 2 0 15 0;
-#X connect 2 1 16 0;
-#X connect 9 0 42 0;
-#X connect 10 0 8 0;
-#X connect 12 0 8 0;
-#X connect 13 0 8 0;
-#X connect 14 0 8 0;
-#X connect 15 0 46 0;
-#X connect 16 0 47 0;
-#X connect 17 0 20 0;
-#X connect 20 0 16 0;
-#X connect 20 0 15 0;
-#X connect 23 0 24 0;
-#X connect 24 0 6 0;
-#X connect 25 0 22 0;
-#X connect 27 0 23 0;
-#X connect 30 0 29 0;
-#X connect 31 0 32 0;
-#X connect 32 0 29 0;
-#X connect 38 0 39 0;
-#X connect 38 1 39 0;
-#X connect 39 0 40 0;
-#X connect 40 0 34 0;
-#X connect 42 0 8 0;
-#X connect 45 0 29 0;
-#X connect 46 0 18 0;
-#X connect 47 0 19 0;
--- a/examples/pd/digital/digital_example.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-#N canvas 279 78 857 690 10;
-#X obj 18 477 osc~ 200;
-#X obj 57 522 *~;
-#X obj 112 405 line~ 1;
-#X msg 116 372 1 \, 0 200;
-#X obj 205 472 line~ 1;
-#X msg 209 439 1 \, 0 200;
-#X obj 210 405 select 1;
-#X obj 140 531 *~;
-#X obj 484 601 s bela_setDigital;
-#X obj 484 532 loadbang;
-#X msg 65 445 0;
-#X obj 116 332 r bela_digitalIn12;
-#X obj 422 217 r bela_digitalIn14;
-#X obj 422 243 s bela_digitalOut13;
-#X obj 285 218 r bela_digitalIn12;
-#X obj 285 243 s bela_digitalOut11;
-#X obj 374 339 timer;
-#X msg 404 304 bang;
-#X msg 368 304 bang;
-#X obj 555 184 metro 1000;
-#X obj 575 304 s bela_digitalOut15;
-#X obj 374 366 print sourceto12;
-#X obj 488 351 timer;
-#X msg 518 316 bang;
-#X msg 482 316 bang;
-#X obj 487 380 print sourceto14;
-#X obj 663 15 r bela_digitalIn16;
-#X msg 553 265 1;
-#X obj 577 214 delay 500;
-#X obj 480 275 select 1;
-#X obj 346 268 select 1;
-#X msg 584 281 0;
-#X obj 634 251 select 1 0;
-#X obj 80 622 dac~ 3 4;
-#X obj 65 566 expr~ $v1*0.5 + 0.5;
-#X obj 138 588 expr~ $v1*0.5 + 0.5;
-#X obj 65 202 dac~ 11;
-#X obj 114 83 osc~ 300;
-#X obj 176 179 dac~ 1 3;
-#X obj 34 136 adc~ 17;
-#X obj 423 504 delay 3000;
-#X msg 388 552 disable 12;
-#X msg 484 552 out 11 ~ \, out 13 \, in 14 \, out 15 \, in 16 \, in
-17 ~;
-#X connect 0 0 1 0;
-#X connect 0 0 7 0;
-#X connect 1 0 34 0;
-#X connect 2 0 1 1;
-#X connect 3 0 2 0;
-#X connect 4 0 7 1;
-#X connect 5 0 4 0;
-#X connect 6 0 5 0;
-#X connect 6 0 10 0;
-#X connect 7 0 35 0;
-#X connect 9 0 42 0;
-#X connect 9 0 40 0;
-#X connect 10 0 0 1;
-#X connect 11 0 3 0;
-#X connect 12 0 13 0;
-#X connect 12 0 29 0;
-#X connect 14 0 15 0;
-#X connect 14 0 30 0;
-#X connect 16 0 21 0;
-#X connect 17 0 16 1;
-#X connect 18 0 16 0;
-#X connect 19 0 27 0;
-#X connect 19 0 28 0;
-#X connect 22 0 25 0;
-#X connect 23 0 22 1;
-#X connect 24 0 22 0;
-#X connect 26 0 32 0;
-#X connect 27 0 20 0;
-#X connect 27 0 24 0;
-#X connect 27 0 18 0;
-#X connect 28 0 31 0;
-#X connect 29 0 23 0;
-#X connect 30 0 17 0;
-#X connect 31 0 20 0;
-#X connect 32 0 27 0;
-#X connect 32 1 31 0;
-#X connect 34 0 33 0;
-#X connect 35 0 33 1;
-#X connect 37 0 38 0;
-#X connect 37 0 38 1;
-#X connect 39 0 36 0;
-#X connect 40 0 41 0;
-#X connect 41 0 8 0;
-#X connect 42 0 8 0;
--- a/examples/pd/envelopeTrigger/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-#N canvas 646 209 359 287 10;
-#X obj 28 207 dac~;
-#N canvas 324 380 556 621 env 0;
-#N canvas 886 1001 131 207 >~ 0;
-#X obj 19 -37 -~;
-#X obj 19 -58 min~;
-#X obj 19 26 *~ 1e+37;
-#X obj 19 5 +~ 1e-37;
-#X obj 19 -16 clip~ -1e-37 0;
-#X obj 19 -83 inlet~;
-#X obj 62 -83 inlet~;
-#X obj 19 48 outlet~;
-#X connect 0 0 4 0;
-#X connect 1 0 0 0;
-#X connect 2 0 7 0;
-#X connect 3 0 2 0;
-#X connect 4 0 3 0;
-#X connect 5 0 1 0;
-#X connect 6 0 0 1;
-#X connect 6 0 1 1;
-#X restore 199 106 pd >~;
-#X obj 23 173 /~ 44100;
-#X obj 68 153 samplerate~;
-#X obj 68 133 loadbang;
-#X obj 199 128 biquad~ 0 0 -1 1 0;
-#X obj 23 209 rpole~;
-#X obj 23 153 sig~ 1;
-#X obj 226 171 sig~ 0.5;
-#N canvas 0 22 110 231 <~ 0;
-#X obj 11 -41 -~;
-#X obj 11 29 +~ 1e-37;
-#X obj 11 8 clip~ -1e-37 0;
-#X obj 11 -86 inlet~;
-#X obj 55 -85 inlet~;
-#X obj 11 -62 max~;
-#X obj 11 -17 *~ -1;
-#X obj 11 81 outlet~;
-#X obj 11 50 *~ 1e+37;
-#X connect 0 0 6 0;
-#X connect 1 0 8 0;
-#X connect 2 0 1 0;
-#X connect 3 0 5 0;
-#X connect 4 0 0 1;
-#X connect 4 0 5 1;
-#X connect 5 0 0 0;
-#X connect 6 0 2 0;
-#X connect 8 0 7 0;
-#X restore 199 192 pd <~;
-#X text 237 193 (x != x);
-#X obj 23 467 *~;
-#X obj 199 150 *~ -1;
-#X obj 23 331 *~ 512;
-#X obj 23 229 clip~ 0 1;
-#X obj 23 352 tabread4~ env1;
-#X obj 23 310 *~;
-#X obj 199 64 abs~;
-#X obj 199 43 hip~ 1;
-#X obj 199 22 inlet~ excitationSignal;
-#X obj 218 269 sig~ 1;
-#X obj 218 292 /~;
-#X obj 226 86 inlet~ threshold;
-#X obj 262 229 inlet~ envDuration;
-#X obj 38 445 osc~ 220;
-#X obj 38 425 +~ 50;
-#X obj 38 385 *~;
-#X obj 38 405 *~ 1000;
-#X obj 262 269 clip~ 1e-05 100000;
-#X obj 23 487 outlet~;
-#N canvas 0 22 450 278 (subpatch) 0;
-#X array env1 512 float 3;
-#A 0 0 0.0625 0.0883883 0.108253 0.125 0.139754 0.153093 0.165359 0.176777
-0.1875 0.197642 0.207289 0.216506 0.225347 0.233854 0.242061 0.25 0.257694
-0.265165 0.272431 0.279509 0.286411 0.293151 0.299739 0.306186 0.3125
-0.318689 0.32476 0.330719 0.336573 0.342327 0.347985 0.353553 0.359035
-0.364434 0.369755 0.375 0.380173 0.385276 0.390312 0.395285 0.400195
-0.405046 0.40984 0.414578 0.419263 0.423896 0.428478 0.433013 0.4375
-0.441942 0.446339 0.450694 0.455007 0.459279 0.463512 0.467707 0.471865
-0.475986 0.480072 0.484123 0.488141 0.492125 0.496078 0.5 0.503891
-0.507752 0.511585 0.515388 0.519164 0.522913 0.526634 0.53033 0.534
-0.537645 0.541266 0.544862 0.548435 0.551985 0.555512 0.559017 0.5625
-0.565962 0.569402 0.572822 0.576222 0.579601 0.582961 0.586302 0.589624
-0.592927 0.596212 0.599479 0.602728 0.60596 0.609175 0.612372 0.615554
-0.618718 0.621867 0.625 0.628117 0.631219 0.634306 0.637377 0.640434
-0.643477 0.646505 0.649519 0.652519 0.655506 0.658478 0.661438 0.664384
-0.667317 0.670238 0.673146 0.676041 0.678924 0.681795 0.684653 0.6875
-0.690335 0.693159 0.695971 0.698771 0.701561 0.704339 0.707107 0.709864
-0.71261 0.715345 0.71807 0.720785 0.72349 0.726184 0.728869 0.731544
-0.734209 0.736864 0.73951 0.742146 0.744773 0.747391 0.75 0.7526 0.75519
-0.757772 0.760345 0.76291 0.765466 0.768013 0.770552 0.773082 0.775605
-0.778119 0.780625 0.783123 0.785613 0.788095 0.790569 0.793036 0.795495
-0.797947 0.800391 0.802827 0.805256 0.807678 0.810093 0.8125 0.8149
-0.817294 0.81968 0.822059 0.824432 0.826797 0.829156 0.831508 0.833854
-0.836193 0.838525 0.840851 0.843171 0.845484 0.847791 0.850092 0.852386
-0.854675 0.856957 0.859233 0.861503 0.863767 0.866025 0.868278 0.870524
-0.872765 0.875 0.877229 0.879453 0.881671 0.883883 0.88609 0.888292
-0.890488 0.892679 0.894864 0.897044 0.899218 0.901388 0.903552 0.905711
-0.907865 0.910014 0.912157 0.914296 0.91643 0.918559 0.920682 0.922801
-0.924916 0.927025 0.929129 0.931229 0.933324 0.935414 0.9375 0.939581
-0.941657 0.943729 0.945797 0.947859 0.949918 0.951972 0.954021 0.956066
-0.958107 0.960143 0.962175 0.964203 0.966227 0.968246 0.970261 0.972272
-0.974279 0.976281 0.97828 0.980274 0.982265 0.984251 0.986233 0.988212
-0.990186 0.992157 0.994123 0.996086 0.998045 1 0.992172 0.984375 0.976609
-0.968874 0.961169 0.953495 0.945852 0.938239 0.930657 0.923106 0.915586
-0.908097 0.900638 0.89321 0.885813 0.878447 0.871111 0.863806 0.856532
-0.849289 0.842076 0.834894 0.827743 0.820623 0.813533 0.806474 0.799446
-0.792449 0.785483 0.778547 0.771642 0.764767 0.757924 0.751111 0.744329
-0.737578 0.730857 0.724168 0.717509 0.71088 0.704283 0.697716 0.69118
-0.684675 0.678201 0.671757 0.665344 0.658962 0.652611 0.64629 0.64
-0.633741 0.627513 0.621315 0.615148 0.609012 0.602907 0.596832 0.590788
-0.584775 0.578793 0.572841 0.56692 0.56103 0.555171 0.549343 0.543545
-0.537778 0.532041 0.526336 0.520661 0.515017 0.509404 0.503822 0.49827
-0.492749 0.487259 0.481799 0.476371 0.470973 0.465605 0.460269 0.454963
-0.449689 0.444444 0.439231 0.434048 0.428897 0.423775 0.418685 0.413625
-0.408597 0.403599 0.398631 0.393695 0.388789 0.383914 0.37907 0.374256
-0.369473 0.364721 0.36 0.355309 0.35065 0.346021 0.341423 0.336855
-0.332318 0.327812 0.323337 0.318893 0.314479 0.310096 0.305744 0.301423
-0.297132 0.292872 0.288643 0.284444 0.280277 0.27614 0.272034 0.267958
-0.263914 0.2599 0.255917 0.251965 0.248043 0.244152 0.240292 0.236463
-0.232664 0.228897 0.22516 0.221453 0.217778 0.214133 0.210519 0.206936
-0.203383 0.199862 0.196371 0.19291 0.189481 0.186082 0.182714 0.179377
-0.176071 0.172795 0.16955 0.166336 0.163153 0.16 0.156878 0.153787
-0.150727 0.147697 0.144698 0.14173 0.138793 0.135886 0.13301 0.130165
-0.127351 0.124567 0.121815 0.119093 0.116401 0.113741 0.111111 0.108512
-0.105944 0.103406 0.1009 0.0984237 0.0959785 0.093564 0.0911803 0.0888274
-0.0865052 0.0842138 0.0819531 0.0797232 0.077524 0.0753556 0.073218
-0.0711111 0.069035 0.0669896 0.064975 0.0629911 0.0610381 0.0591157
-0.0572241 0.0553633 0.0535332 0.0517339 0.0499654 0.0482276 0.0465206
-0.0448443 0.0431988 0.041584 0.04 0.0384467 0.0369243 0.0354325 0.0339715
-0.0325413 0.0311419 0.0297732 0.0284352 0.027128 0.0258516 0.0246059
-0.023391 0.0222068 0.0210534 0.0199308 0.0188389 0.0177778 0.0167474
-0.0157478 0.0147789 0.0138408 0.0129335 0.0120569 0.0112111 0.010396
-0.00961169 0.00885813 0.00813533 0.00744329 0.00678201 0.00615148 0.00555171
-0.0049827 0.00444444 0.00393695 0.00346021 0.00301423 0.002599 0.00221453
-0.00186082 0.00153787 0.00124567 0.000984237 0.000753556 0.000553633
-0.000384467 0.000246059 0.000138408 6.15148e-05 1.53787e-05 0;
-#X coords 0 1 512 0 512 64 1 0 0;
-#X restore 24 536 graph;
-#X text 244 55 centre signal around zero and take abs value;
-#X text 243 107 if greater than threshold output 1;
-#X text 313 129 differentiator;
-#X text 238 150 (generates impulse on positive trigger (0->1);
-#X text 67 210 signal-rate counter;
-#X text 296 193 -> resets counter by briefly setting;
-#X text 314 204 rpole~ coeff to 0;
-#X text 96 416 kickdrum 101 :P;
-#X text 400 514 pre-generated envelope;
-#X obj 262 249 *~;
-#X text 127 352 << use envelope value for volume and frequency;
-#X connect 0 0 4 0;
-#X connect 1 0 5 0;
-#X connect 2 0 1 1;
-#X connect 3 0 2 0;
-#X connect 4 0 11 0;
-#X connect 5 0 13 0;
-#X connect 6 0 1 0;
-#X connect 7 0 8 1;
-#X connect 8 0 5 1;
-#X connect 10 0 28 0;
-#X connect 11 0 8 0;
-#X connect 12 0 14 0;
-#X connect 13 0 15 0;
-#X connect 14 0 10 0;
-#X connect 14 0 25 0;
-#X connect 14 0 25 1;
-#X connect 15 0 12 0;
-#X connect 16 0 0 0;
-#X connect 17 0 16 0;
-#X connect 18 0 17 0;
-#X connect 19 0 20 0;
-#X connect 20 0 15 1;
-#X connect 21 0 0 1;
-#X connect 22 0 39 0;
-#X connect 22 0 39 1;
-#X connect 23 0 10 1;
-#X connect 24 0 23 0;
-#X connect 25 0 26 0;
-#X connect 26 0 24 0;
-#X connect 27 0 20 1;
-#X connect 39 0 27 0;
-#X restore 28 174 pd env;
-#X obj 79 110 adc~ 9;
-#X obj 129 130 adc~ 10;
-#X text 72 90 piezo input for excitation;
-#X text 123 110 fader 1 sets threshold;
-#X text 183 130 fader 2 sets duration;
-#X text 29 17 SAMPLE-ACCURATE ENVELOPE TRIGGER;
-#X text 29 27 ================================;
-#X obj 28 90 adc~ 8;
-#X text 141 236 ---------------------------------;
-#X text 141 226 @krighxz / BELA / heavy / 12/2015;
-#X text 165 245 beaglert.cc / enzienaudio.com;
-#X connect 1 0 0 0;
-#X connect 1 0 0 1;
-#X connect 2 0 1 1;
-#X connect 3 0 1 2;
-#X connect 9 0 1 0;
--- a/examples/pd/hello-midi/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#N canvas 85 58 1280 685 10;
-#X obj 19 396 dac~ 1 2;
-#X text 39 1 Hello world!;
-#X text 37 11 ============;
-#X obj 31 353 *~ 0.1;
-#X text 202 448 ---------------------------------;
-#X text 202 438 @krighxz / BELA / heavy / 12/2015;
-#X text 226 457 beaglert.cc / enzienaudio.com;
-#X obj 39 132 mtof;
-#X floatatom 79 59 5 0 0 0 - - -, f 5;
-#X floatatom 122 59 5 0 0 0 - - -, f 5;
-#X floatatom 41 63 5 0 0 0 - - -, f 5;
-#X obj 26 170 phasor~ 440;
-#X text 100 363 (the harsh sound of success);
-#X obj 260 83 * 20;
-#X obj 261 112 + 200;
-#X obj 132 85 loadbang;
-#X msg 131 111 1000;
-#X obj 125 166 sig~;
-#X text 673 121 [pgmin];
-#X obj 218 178 * 10;
-#X obj 30 250 hip~;
-#X obj 26 275 hip~;
-#X obj 20 302 hip~;
-#X obj 19 323 hip~;
-#X obj 87 192 lop~ 4;
-#X obj 152 256 line;
-#X obj 200 200 + 50;
-#X msg 170 227 \$1 200;
-#X msg 93 114 0;
-#X msg 185 112 0;
-#X obj 29 224 vcf~ 4;
-#X obj 70 333 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
-1;
-#X obj 42 92 mono;
-#X obj 40 28 bela_notein 0;
-#X obj 260 60 bela_ctlin 5 0;
-#X obj 220 151 bela_ctlin 6 0;
-#X text 537 58 [ctlin];
-#X text 332 27 [notein];
-#X text 140 29 <== the bela equivalent of ==>;
-#X text 349 59 <== the bela equivalent of ==>;
-#X text 483 121 <== the bela equivalent of ==>;
-#X obj 405 175 print pgmin;
-#X obj 408 121 bela_pgmin 0;
-#X connect 3 0 0 1;
-#X connect 3 0 0 0;
-#X connect 7 0 11 0;
-#X connect 8 0 32 1;
-#X connect 10 0 32 0;
-#X connect 11 0 30 0;
-#X connect 13 0 14 0;
-#X connect 14 0 17 0;
-#X connect 15 0 16 0;
-#X connect 15 0 29 0;
-#X connect 15 0 28 0;
-#X connect 16 0 17 0;
-#X connect 17 0 24 0;
-#X connect 19 0 26 0;
-#X connect 20 0 21 0;
-#X connect 21 0 22 0;
-#X connect 22 0 23 0;
-#X connect 23 0 3 0;
-#X connect 24 0 30 1;
-#X connect 25 0 20 1;
-#X connect 25 0 21 1;
-#X connect 25 0 22 1;
-#X connect 25 0 23 1;
-#X connect 26 0 27 0;
-#X connect 27 0 25 0;
-#X connect 29 0 19 0;
-#X connect 30 0 20 0;
-#X connect 31 0 3 1;
-#X connect 32 0 7 0;
-#X connect 32 1 31 0;
-#X connect 33 0 10 0;
-#X connect 33 1 8 0;
-#X connect 33 2 9 0;
-#X connect 34 0 13 0;
-#X connect 35 0 19 0;
-#X connect 42 0 41 0;
--- a/examples/pd/hello-midi/countTo.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-#N canvas 584 255 450 300 10;
-#X obj 65 196 outlet;
-#X obj 98 8 inlet;
-#X text 189 49 counts from 0 to the given number -1;
-#X text 214 95 inlet:N;
-#X text 212 112 outlet: 0 \, 1 \, 2 \, ... \, N-1;
-#X obj 143 61 f;
-#X obj 100 138 spigot;
-#X obj 129 89 <;
-#X obj 129 113 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
-1;
-#X obj 95 28 t b f b;
-#X obj 92 74 + 1;
-#X obj 43 73 f;
-#X obj 63 104 t b f f f;
-#X msg 92 53 0;
-#X obj 16 144 delay 0;
-#X connect 1 0 9 0;
-#X connect 5 0 7 1;
-#X connect 6 0 11 0;
-#X connect 7 0 8 0;
-#X connect 8 0 6 1;
-#X connect 9 0 11 0;
-#X connect 9 1 5 0;
-#X connect 9 1 13 0;
-#X connect 10 0 11 1;
-#X connect 11 0 12 0;
-#X connect 12 0 14 0;
-#X connect 12 1 0 0;
-#X connect 12 2 7 0;
-#X connect 12 3 10 0;
-#X connect 13 0 11 1;
-#X connect 14 0 6 0;
--- a/examples/pd/hello-midi/maxArray.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-#N canvas 464 23 1002 583 10;
-#X obj 224 202 max;
-#X obj 265 200 f;
-#X obj 223 229 change;
-#X obj 223 251 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
--1 -1;
-#X obj 223 271 f;
-#X obj 259 323 f;
-#X obj 187 315 f;
-#X obj 268 282 t b b;
-#X obj 183 364 outlet;
-#X obj 269 379 outlet;
-#X obj 179 17 inlet;
-#X obj 225 177 tabread \$1;
-#X obj 230 88 t f f b;
-#X text 376 37 Finds a maximum value in an array;
-#X text 531 112 \$2 arrayLength;
-#X obj 292 10 inlet;
-#X text 425 146 inlets:;
-#X text 473 144 1 bang to find the maximum;
-#X text 475 157 2 arrayLength;
-#X text 407 90 creation arguments: \$1 arrayName;
-#X obj 246 38 \$2;
-#X obj 202 40 bang;
-#X obj 230 65 f;
-#X obj 224 6 loadbang;
-#X text 444 216 outlets: 1 maximum value;
-#X text 498 231 2 index of the maximum value;
-#X msg 276 141 -1e+15;
-#X obj 222 142 t f f f;
-#X floatatom 158 266 5 0 0 0 - - -, f 5;
-#X obj 332 302 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
--1 -1;
-#X obj 288 253 select 127;
-#X floatatom 301 324 5 0 0 0 - - -, f 5;
-#X text 362 256 heavy does not support the second inlet of select so
-I have to hard code 127 in here;
-#X obj 223 110 countTo;
-#X connect 0 0 1 0;
-#X connect 0 0 2 0;
-#X connect 0 0 6 1;
-#X connect 0 0 28 0;
-#X connect 1 0 0 1;
-#X connect 2 0 3 0;
-#X connect 3 0 4 0;
-#X connect 4 0 5 1;
-#X connect 4 0 31 0;
-#X connect 5 0 9 0;
-#X connect 6 0 8 0;
-#X connect 7 0 6 0;
-#X connect 7 1 5 0;
-#X connect 10 0 21 0;
-#X connect 11 0 0 0;
-#X connect 12 0 33 0;
-#X connect 12 2 26 0;
-#X connect 15 0 22 1;
-#X connect 20 0 22 1;
-#X connect 21 0 22 0;
-#X connect 22 0 12 0;
-#X connect 23 0 20 0;
-#X connect 26 0 0 1;
-#X connect 27 0 30 0;
-#X connect 27 1 11 0;
-#X connect 27 2 4 1;
-#X connect 30 0 7 0;
-#X connect 30 0 29 0;
-#X connect 33 0 27 0;
--- a/examples/pd/hello-midi/mono.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-#N canvas 69 182 1020 452 10;
-#N canvas 0 23 450 278 (subpatch) 0;
-#X array \$0-activeNotes 127 float 2;
-#X coords 0 100 127 -1 200 140 1 0 0;
-#X restore 537 25 graph;
-#N canvas 89 91 450 300 resetArray 1;
-#X obj 121 145 tabwrite \$0-activeNotes;
-#X msg 123 115 -0.5;
-#X obj 154 90 t b f;
-#X msg 129 45 128;
-#X obj 103 14 inlet;
-#X text 212 71 countto;
-#X obj 153 69 countTo;
-#X connect 1 0 0 0;
-#X connect 2 0 1 0;
-#X connect 2 1 0 1;
-#X connect 3 0 6 0;
-#X connect 4 0 3 0;
-#X connect 6 0 2 0;
-#X restore 83 49 pd resetArray;
-#X obj 83 3 loadbang;
-#X obj 88 25 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
--1;
-#X obj 39 188 maxArray \$0-activeNotes 128;
-#X obj 183 219 f;
-#X obj 39 237 >= 0;
-#X floatatom 148 313 5 0 0 0 - - -, f 5;
-#X obj 70 262 select 1;
-#X obj 366 87 f;
-#X obj 426 60 f;
-#X text 334 39 note;
-#X text 424 16 velocity;
-#X obj 423 87 > 0;
-#X obj 344 281 tabwrite \$0-activeNotes;
-#X obj 330 207 f;
-#X floatatom 303 178 5 0 0 0 - - -, f 5;
-#X obj 265 163 f;
-#X obj 304 150 + 1;
-#X msg 277 130 -1;
-#X msg 371 207 -0.5;
-#X obj 400 116 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
-1;
-#X obj 367 137 spigot;
-#X obj 447 134 spigot;
-#X obj 460 86 == 0;
-#X obj 470 109 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
-1;
-#X obj 434 163 t b f;
-#X obj 337 60 inlet;
-#X obj 426 32 inlet;
-#X obj 148 350 outlet;
-#X obj 275 89 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
--1;
-#X obj 41 163 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
--1;
-#X obj 363 172 t b f;
-#X obj 334 240 t b f;
-#X text 578 211 pass in velocity/note pairs (velocity first) and obtain
-as an output the most recent note still active;
-#X text 581 268 outlet 2 gate;
-#X obj 330 366 outlet;
-#X text 583 251 outlet 1 most recent note active (-1 otherwise);
-#X text 155 329 most recent note active;
-#X msg 338 338 0;
-#X msg 378 339 1;
-#X connect 2 0 3 0;
-#X connect 3 0 1 0;
-#X connect 3 0 19 0;
-#X connect 4 0 6 0;
-#X connect 4 1 5 1;
-#X connect 5 0 7 0;
-#X connect 5 0 40 0;
-#X connect 6 0 8 0;
-#X connect 7 0 29 0;
-#X connect 8 0 5 0;
-#X connect 8 1 39 0;
-#X connect 9 0 22 0;
-#X connect 9 0 23 0;
-#X connect 10 0 13 0;
-#X connect 10 0 24 0;
-#X connect 13 0 21 0;
-#X connect 15 0 33 0;
-#X connect 16 0 15 1;
-#X connect 17 0 18 0;
-#X connect 18 0 16 0;
-#X connect 18 0 17 1;
-#X connect 19 0 17 1;
-#X connect 20 0 33 0;
-#X connect 21 0 22 1;
-#X connect 22 0 32 0;
-#X connect 23 0 26 0;
-#X connect 24 0 25 0;
-#X connect 25 0 23 1;
-#X connect 26 0 20 0;
-#X connect 26 1 14 1;
-#X connect 27 0 9 0;
-#X connect 28 0 10 0;
-#X connect 28 0 30 0;
-#X connect 30 0 17 0;
-#X connect 31 0 4 0;
-#X connect 32 0 15 0;
-#X connect 32 1 14 1;
-#X connect 33 0 31 0;
-#X connect 33 1 14 0;
-#X connect 39 0 36 0;
-#X connect 40 0 36 0;
--- a/examples/pd/hello-world/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-#N canvas 275 573 461 212 10;
-#X obj 39 143 dac~ 1 2;
-#X text 35 32 Hello world!;
-#X text 35 42 ============;
-#X text 95 79 (the sweet sound of success);
-#X obj 39 102 *~ 0.1;
-#X obj 39 81 osc~ 440;
-#X text 238 160 ---------------------------------;
-#X text 238 150 @krighxz / BELA / heavy / 12/2015;
-#X text 262 169 beaglert.cc / enzienaudio.com;
-#X connect 4 0 0 1;
-#X connect 4 0 0 0;
-#X connect 5 0 4 0;
--- a/examples/pd/karplusStrong/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-#N canvas 440 516 715 490 10;
-#X obj 38 370 dac~ 1 2;
-#X text 470 442 ---------------------------------;
-#X text 470 432 @krighxz / BELA / heavy / 12/2015;
-#X text 494 451 beaglert.cc / enzienaudio.com;
-#X text 33 22 Karplus Strong;
-#X text 33 32 ==============;
-#X obj 38 323 vd~ \$0-wg1;
-#X obj 118 345 lop~ 1000;
-#X obj 118 367 *~ 0.99;
-#X obj 118 389 s~ \$0-fb1;
-#X obj 38 94 adc~ 3;
-#X obj 38 116 hip~ 100;
-#X obj 98 176 r~ \$0-fb1;
-#X obj 38 198 delwrite~ \$0-wg1 100;
-#X obj 38 268 *~;
-#X obj 38 290 *~ 10;
-#X text 99 116 <<< centre (i.e. DC block) signal with high-pass filter
-;
-#X text 100 94 <<< use accelerometer \, piezo or FSR on first analog
-in;
-#X text 105 245 <<< use potentiometer or fader on second analog in
-;
-#X text 100 75 EXCITATION INPUT:;
-#X text 100 225 DELAY PERIOD:;
-#X text 182 365 <<< and decay here [0-0.9999];
-#X text 182 345 <<< set damping here [~100-20000];
-#N canvas 335 566 461 274 gate 0;
-#N canvas 0 22 450 278 (subpatch) 0;
-#X array \$0-xfer 1024 float 3;
-#A 0 0 -0.808242 -0.804734 -0.801234 -0.797741 -0.794256 -0.790778
--0.787309 -0.783846 -0.780392 -0.776945 -0.773506 -0.770074 -0.76665
--0.763233 -0.759824 -0.756423 -0.75303 -0.749644 -0.746266 -0.742895
--0.739532 -0.736176 -0.732829 -0.729488 -0.726156 -0.722831 -0.719514
--0.716204 -0.712902 -0.709608 -0.706321 -0.703042 -0.69977 -0.696507
--0.69325 -0.690002 -0.686761 -0.683527 -0.680302 -0.677084 -0.673873
--0.67067 -0.667475 -0.664288 -0.661108 -0.657935 -0.654771 -0.651614
--0.648464 -0.645323 -0.642188 -0.639062 -0.635943 -0.632832 -0.629728
--0.626632 -0.623544 -0.620463 -0.61739 -0.614324 -0.611266 -0.608216
--0.605174 -0.602139 -0.599111 -0.596092 -0.59308 -0.590075 -0.587078
--0.584089 -0.581107 -0.578134 -0.575167 -0.572209 -0.569257 -0.566314
--0.563378 -0.56045 -0.55753 -0.554617 -0.551711 -0.548814 -0.545924
--0.543041 -0.540167 -0.537299 -0.53444 -0.531588 -0.528744 -0.525907
--0.523078 -0.520257 -0.517443 -0.514637 -0.511839 -0.509048 -0.506265
--0.503489 -0.500721 -0.497961 -0.495208 -0.492463 -0.489726 -0.486996
--0.484274 -0.481559 -0.478852 -0.476153 -0.473461 -0.470777 -0.468101
--0.465432 -0.462771 -0.460117 -0.457472 -0.454833 -0.452203 -0.44958
--0.446964 -0.444357 -0.441757 -0.439164 -0.436579 -0.434002 -0.431432
--0.42887 -0.426316 -0.42377 -0.42123 -0.418699 -0.416175 -0.413659
--0.41115 -0.40865 -0.406156 -0.403671 -0.401193 -0.398722 -0.396259
--0.393804 -0.391357 -0.388917 -0.386485 -0.38406 -0.381643 -0.379234
--0.376832 -0.374438 -0.372051 -0.369673 -0.367301 -0.364938 -0.362582
--0.360233 -0.357893 -0.35556 -0.353234 -0.350916 -0.348606 -0.346304
--0.344009 -0.341721 -0.339442 -0.33717 -0.334905 -0.332649 -0.330399
--0.328158 -0.325924 -0.323698 -0.321479 -0.319268 -0.317065 -0.314869
--0.312681 -0.3105 -0.308328 -0.306162 -0.304005 -0.301855 -0.299713
--0.297578 -0.295451 -0.293331 -0.291219 -0.289115 -0.287019 -0.28493
--0.282848 -0.280775 -0.278709 -0.27665 -0.2746 -0.272556 -0.270521
--0.268493 -0.266473 -0.26446 -0.262455 -0.260458 -0.258468 -0.256486
--0.254511 -0.252545 -0.250585 -0.248634 -0.24669 -0.244753 -0.242825
--0.240904 -0.23899 -0.237084 -0.235186 -0.233296 -0.231413 -0.229537
--0.22767 -0.22581 -0.223957 -0.222112 -0.220275 -0.218446 -0.216624
--0.21481 -0.213003 -0.211204 -0.209413 -0.207629 -0.205853 -0.204084
--0.202323 -0.20057 -0.198824 -0.197086 -0.195356 -0.193633 -0.191918
--0.190211 -0.188511 -0.186819 -0.185134 -0.183457 -0.181788 -0.180126
--0.178472 -0.176826 -0.175187 -0.173556 -0.171932 -0.170316 -0.168708
--0.167108 -0.165515 -0.163929 -0.162351 -0.160781 -0.159219 -0.157664
--0.156117 -0.154577 -0.153045 -0.151521 -0.150004 -0.148495 -0.146993
--0.1455 -0.144013 -0.142535 -0.141064 -0.139601 -0.138145 -0.136697
--0.135256 -0.133824 -0.132398 -0.130981 -0.129571 -0.128169 -0.126774
--0.125387 -0.124008 -0.122636 -0.121272 -0.119915 -0.118566 -0.117225
--0.115891 -0.114565 -0.113247 -0.111936 -0.110633 -0.109338 -0.10805
--0.10677 -0.105497 -0.104232 -0.102975 -0.101725 -0.100483 -0.0992487
--0.0980219 -0.0968027 -0.0955911 -0.0943872 -0.0931909 -0.0920023 -0.0908212
--0.0896478 -0.0884821 -0.0873239 -0.0861734 -0.0850305 -0.0838953 -0.0827676
--0.0816476 -0.0805353 -0.0794305 -0.0783334 -0.077244 -0.0761621 -0.0750879
--0.0740213 -0.0729623 -0.071911 -0.0708673 -0.0698312 -0.0688028 -0.067782
--0.0667688 -0.0657632 -0.0647653 -0.063775 -0.0627924 -0.0618173 -0.0608499
--0.0598901 -0.058938 -0.0579935 -0.0570566 -0.0561273 -0.0552057 -0.0542917
--0.0533853 -0.0524866 -0.0515955 -0.050712 -0.0498361 -0.0489679 -0.0481073
--0.0472543 -0.046409 -0.0455713 -0.0447412 -0.0439188 -0.0431039 -0.0422968
--0.0414972 -0.0407053 -0.039921 -0.0391443 -0.0383752 -0.0376138 -0.03686
--0.0361139 -0.0353754 -0.0346445 -0.0339212 -0.0332056 -0.0324976 -0.0317972
--0.0311044 -0.0304193 -0.0297418 -0.029072 -0.0284097 -0.0277551 -0.0271082
--0.0264688 -0.0258371 -0.025213 -0.0245966 -0.0239877 -0.0233865 -0.022793
--0.022207 -0.0216287 -0.021058 -0.020495 -0.0199396 -0.0193918 -0.0188516
--0.0183191 -0.0177942 -0.0172769 -0.0167673 -0.0162653 -0.0157709 -0.0152841
--0.014805 -0.0143335 -0.0138696 -0.0134134 -0.0129648 -0.0125238 -0.0120905
--0.0116647 -0.0112466 -0.0108362 -0.0104333 -0.0100381 -0.00965057
--0.00927063 -0.00889832 -0.00853363 -0.00817657 -0.00782715 -0.00748535
--0.00715118 -0.00682465 -0.00650574 -0.00619446 -0.00589081 -0.00559479
--0.0053064 -0.00502563 -0.0047525 -0.004487 -0.00422913 -0.00397888
--0.00373627 -0.00350128 -0.00327393 -0.0030542 -0.0028421 -0.00263763
--0.0024408 -0.00225159 -0.00207001 -0.00189606 -0.00172974 -0.00157104
--0.00141998 -0.00127655 -0.00114075 -0.00101257 -0.000892029 -0.000779114
--0.000673828 -0.000576172 -0.000486145 -0.000403747 -0.000328979 -0.000261841
--0.000202332 -0.000150452 -0.000106201 -6.95801e-05 -4.05884e-05 -1.92261e-05
--5.49316e-06 0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0
--0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0 -0
--0 -0 -0 -0 -0 -0 -0 -0 -0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5.49316e-06
-1.92261e-05 4.05884e-05 6.95801e-05 0.000106201 0.000150452 0.000202332
-0.000261841 0.000328979 0.000403747 0.000486145 0.000576172 0.000673828
-0.000779114 0.000892029 0.00101257 0.00114075 0.00127655 0.00141998
-0.00157104 0.00172974 0.00189606 0.00207001 0.00225159 0.0024408 0.00263763
-0.0028421 0.0030542 0.00327393 0.00350128 0.00373627 0.00397888 0.00422913
-0.004487 0.0047525 0.00502563 0.0053064 0.00559479 0.00589081 0.00619446
-0.00650574 0.00682465 0.00715118 0.00748535 0.00782715 0.00817657 0.00853363
-0.00889832 0.00927063 0.00965057 0.0100381 0.0104333 0.0108362 0.0112466
-0.0116647 0.0120905 0.0125238 0.0129648 0.0134134 0.0138696 0.0143335
-0.014805 0.0152841 0.0157709 0.0162653 0.0167673 0.0172769 0.0177942
-0.0183191 0.0188516 0.0193918 0.0199396 0.020495 0.021058 0.0216287
-0.022207 0.022793 0.0233865 0.0239877 0.0245966 0.025213 0.0258371
-0.0264688 0.0271082 0.0277551 0.0284097 0.029072 0.0297418 0.0304193
-0.0311044 0.0317972 0.0324976 0.0332056 0.0339212 0.0346445 0.0353754
-0.0361139 0.03686 0.0376138 0.0383752 0.0391443 0.039921 0.0407053
-0.0414972 0.0422968 0.0431039 0.0439188 0.0447412 0.0455713 0.046409
-0.0472543 0.0481073 0.0489679 0.0498361 0.050712 0.0515955 0.0524866
-0.0533853 0.0542917 0.0552057 0.0561273 0.0570566 0.0579935 0.058938
-0.0598901 0.0608499 0.0618173 0.0627924 0.063775 0.0647653 0.0657632
-0.0667688 0.067782 0.0688028 0.0698312 0.0708673 0.071911 0.0729623
-0.0740213 0.0750879 0.0761621 0.077244 0.0783334 0.0794305 0.0805353
-0.0816476 0.0827676 0.0838953 0.0850305 0.0861734 0.0873239 0.0884821
-0.0896478 0.0908212 0.0920023 0.0931909 0.0943872 0.0955911 0.0968027
-0.0980219 0.0992487 0.100483 0.101725 0.102975 0.104232 0.105497 0.10677
-0.10805 0.109338 0.110633 0.111936 0.113247 0.114565 0.115891 0.117225
-0.118566 0.119915 0.121272 0.122636 0.124008 0.125387 0.126774 0.128169
-0.129571 0.130981 0.132398 0.133824 0.135256 0.136697 0.138145 0.139601
-0.141064 0.142535 0.144013 0.1455 0.146993 0.148495 0.150004 0.151521
-0.153045 0.154577 0.156117 0.157664 0.159219 0.160781 0.162351 0.163929
-0.165515 0.167108 0.168708 0.170316 0.171932 0.173556 0.175187 0.176826
-0.178472 0.180126 0.181788 0.183457 0.185134 0.186819 0.188511 0.190211
-0.191918 0.193633 0.195356 0.197086 0.198824 0.20057 0.202323 0.204084
-0.205853 0.207629 0.209413 0.211204 0.213003 0.21481 0.216624 0.218446
-0.220275 0.222112 0.223957 0.22581 0.22767 0.229537 0.231413 0.233296
-0.235186 0.237084 0.23899 0.240904 0.242825 0.244753 0.24669 0.248634
-0.250585 0.252545 0.254511 0.256486 0.258468 0.260458 0.262455 0.26446
-0.266473 0.268493 0.270521 0.272556 0.2746 0.27665 0.278709 0.280775
-0.282848 0.28493 0.287019 0.289115 0.291219 0.293331 0.295451 0.297578
-0.299713 0.301855 0.304005 0.306162 0.308328 0.3105 0.312681 0.314869
-0.317065 0.319268 0.321479 0.323698 0.325924 0.328158 0.330399 0.332649
-0.334905 0.33717 0.339442 0.341721 0.344009 0.346304 0.348606 0.350916
-0.353234 0.35556 0.357893 0.360233 0.362582 0.364938 0.367301 0.369673
-0.372051 0.374438 0.376832 0.379234 0.381643 0.38406 0.386485 0.388917
-0.391357 0.393804 0.396259 0.398722 0.401193 0.403671 0.406156 0.40865
-0.41115 0.413659 0.416175 0.418699 0.42123 0.42377 0.426316 0.42887
-0.431432 0.434002 0.436579 0.439164 0.441757 0.444357 0.446964 0.44958
-0.452203 0.454833 0.457472 0.460117 0.462771 0.465432 0.468101 0.470777
-0.473461 0.476153 0.478852 0.481559 0.484274 0.486996 0.489726 0.492463
-0.495208 0.497961 0.500721 0.503489 0.506265 0.509048 0.511839 0.514637
-0.517443 0.520257 0.523078 0.525907 0.528744 0.531588 0.53444 0.537299
-0.540167 0.543041 0.545924 0.548814 0.551711 0.554617 0.55753 0.56045
-0.563378 0.566314 0.569257 0.572209 0.575167 0.578134 0.581107 0.584089
-0.587078 0.590075 0.59308 0.596092 0.599111 0.602139 0.605174 0.608216
-0.611266 0.614324 0.61739 0.620463 0.623544 0.626632 0.629728 0.632832
-0.635943 0.639062 0.642188 0.645323 0.648464 0.651614 0.654771 0.657935
-0.661108 0.664288 0.667475 0.67067 0.673873 0.677084 0.680302 0.683527
-0.686761 0.690002 0.69325 0.696507 0.69977 0.703042 0.706321 0.709608
-0.712902 0.716204 0.719514 0.722831;
-#A 1000 0.726156 0.729488 0.732829 0.736176 0.739532 0.742895 0.746266
-0.749644 0.75303 0.756423 0.759824 0.763233 0.76665 0.770074 0.773506
-0.776945 0.780392 0.783846 0.787309 0.790778 0.794256 0.797741 0.801234
-0.804734;
-#X coords 0 1 1023 -1 200 200 1 0 0;
-#X restore 230 34 graph;
-#X obj 25 27 inlet~;
-#X obj 25 49 clip~ -1 1;
-#X obj 25 71 *~ 512;
-#X obj 25 93 +~ 512;
-#X obj 25 115 tabread4~ \$0-xfer;
-#X obj 25 137 outlet~;
-#N canvas 0 22 334 332 generate-xfer 0;
-#X obj 8 290 tabwrite \$0-xfer;
-#X obj 8 109 / 1024;
-#X obj 8 129 * 2;
-#X obj 8 149 - 1;
-#X obj 8 169 moses 0;
-#X obj 8 191 + 0.1;
-#X obj 8 213 clip -1 0;
-#X obj 68 191 - 0.1;
-#X obj 68 213 clip 0 1;
-#X obj 101 16 inlet threshold;
-#X obj 101 78 count 1024;
-#X obj 128 58 s \$0-thresh;
-#X obj 95 169 r \$0-thresh;
-#X obj 101 38 t b f;
-#X obj 68 236 *;
-#X obj 8 236 *;
-#X obj 8 258 * -1;
-#X text 140 203 <<< deadzone;
-#X text 140 253 <<< smooth by taking exponent;
-#X connect 1 0 2 0;
-#X connect 2 0 3 0;
-#X connect 3 0 4 0;
-#X connect 4 0 5 0;
-#X connect 4 1 7 0;
-#X connect 5 0 6 0;
-#X connect 6 0 15 0;
-#X connect 6 0 15 1;
-#X connect 7 0 8 0;
-#X connect 8 0 14 0;
-#X connect 8 0 14 1;
-#X connect 9 0 13 0;
-#X connect 10 0 0 1;
-#X connect 10 0 1 0;
-#X connect 12 0 5 1;
-#X connect 12 0 7 1;
-#X connect 13 0 10 0;
-#X connect 13 1 11 0;
-#X connect 14 0 0 0;
-#X connect 15 0 16 0;
-#X connect 16 0 0 0;
-#X restore 26 217 pd generate-xfer;
-#X text 58 196 <<< threshold;
-#X obj 26 173 loadbang;
-#X msg 26 195 0.1;
-#X connect 1 0 2 0;
-#X connect 2 0 3 0;
-#X connect 3 0 4 0;
-#X connect 4 0 5 0;
-#X connect 5 0 6 0;
-#X connect 9 0 10 0;
-#X connect 10 0 7 0;
-#X restore 38 137 pd gate;
-#X obj 38 246 adc~ 10;
-#X text 98 137 <<< thresholding to remove any consistent noise in the
-excitation signal;
-#X connect 6 0 7 0;
-#X connect 6 0 0 0;
-#X connect 6 0 0 1;
-#X connect 7 0 8 0;
-#X connect 8 0 9 0;
-#X connect 10 0 11 0;
-#X connect 11 0 23 0;
-#X connect 12 0 13 0;
-#X connect 14 0 15 0;
-#X connect 15 0 6 0;
-#X connect 23 0 13 0;
-#X connect 24 0 14 0;
-#X connect 24 0 14 1;
--- a/examples/pd/karplusStrong/count.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#N canvas 592 177 306 227 10;
-#X obj 32 111 f;
-#X obj 57 111 + 1;
-#X obj 57 151 sel 0;
-#X obj 57 171 del 1e-36;
-#X obj 57 131 > 1023;
-#X msg 32 90 0;
-#X obj 19 171 - 1;
-#X obj 19 193 outlet;
-#X obj 90 87 \$1;
-#X obj 90 109 - 1;
-#X obj 90 66 loadbang;
-#X obj 32 48 inlet;
-#X obj 32 69 t b;
-#X text 33 14 temporary replacement for [until] object;
-#X text 67 195 outputs index (0->[N-1]);
-#X connect 0 0 1 0;
-#X connect 1 0 0 1;
-#X connect 1 0 4 0;
-#X connect 1 0 6 0;
-#X connect 2 0 3 0;
-#X connect 3 0 0 0;
-#X connect 4 0 2 0;
-#X connect 5 0 0 0;
-#X connect 6 0 7 0;
-#X connect 8 0 9 0;
-#X connect 9 0 4 1;
-#X connect 10 0 8 0;
-#X connect 11 0 12 0;
-#X connect 12 0 5 0;
--- a/examples/pd/rubberDuckie/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-#N canvas 275 573 442 207 10;
-#X obj 39 149 dac~ 1 2;
-#X text 218 143 ---------------------------------;
-#X text 218 133 @krighxz / BELA / heavy / 12/2015;
-#X text 242 152 beaglert.cc / enzienaudio.com;
-#X text 35 32 Rubber Duckie;
-#X text 35 42 =============;
-#N canvas 325 86 823 605 duckie 0;
-#X obj 186 510 *~;
-#X obj 306 517 *~;
-#X obj 372 468 noise~;
-#X obj 372 492 bp~ 3000 10;
-#X obj 366 162 abs~;
-#X obj 509 158 sig~ 0;
-#X obj 467 371 +~;
-#X obj 411 210 -~ 0.55;
-#X obj 411 231 /~ 0.2;
-#X obj 411 252 clip~ 0 1;
-#X obj 411 282 *~;
-#X obj 411 308 *~ 1000;
-#X obj 366 334 +~;
-#X obj 366 308 +~ 800;
-#X obj 186 536 *~ 0.2;
-#X obj 366 282 *~ 800;
-#N canvas 568 775 135 226 <~ 0;
-#X obj 20 -43 -~;
-#X obj 20 27 +~ 1e-37;
-#X obj 20 6 clip~ -1e-37 0;
-#X obj 20 -88 inlet~;
-#X obj 64 -87 inlet~;
-#X obj 20 -64 max~;
-#X obj 20 -19 *~ -1;
-#X obj 20 79 outlet~;
-#X obj 20 48 *~ 1e+37;
-#X connect 0 0 6 0;
-#X connect 1 0 8 0;
-#X connect 2 0 1 0;
-#X connect 3 0 5 0;
-#X connect 4 0 0 1;
-#X connect 4 0 5 1;
-#X connect 5 0 0 0;
-#X connect 6 0 2 0;
-#X connect 8 0 7 0;
-#X restore 186 367 pd <~ 0;
-#N canvas 568 775 135 226 <~ 0;
-#X obj 20 -43 -~;
-#X obj 20 27 +~ 1e-37;
-#X obj 20 6 clip~ -1e-37 0;
-#X obj 20 -88 inlet~;
-#X obj 64 -87 inlet~;
-#X obj 20 -64 max~;
-#X obj 20 -19 *~ -1;
-#X obj 20 79 outlet~;
-#X obj 20 48 *~ 1e+37;
-#X connect 0 0 6 0;
-#X connect 1 0 8 0;
-#X connect 2 0 1 0;
-#X connect 3 0 5 0;
-#X connect 4 0 0 1;
-#X connect 4 0 5 1;
-#X connect 5 0 0 0;
-#X connect 6 0 2 0;
-#X connect 8 0 7 0;
-#X restore 482 181 pd <~;
-#X obj 186 428 *~;
-#X obj 225 345 sig~ 1;
-#X obj 186 394 lop~ 10;
-#X text 524 393 << band-limited pulse;
-#X text 10 367 reed stops when overblown >>;
-#X obj 186 460 *~;
-#X obj 186 480 *~;
-#X text 25 470 exp amplitude response >>;
-#X text 537 238 << detune frequency on change of direction;
-#X obj 482 236 *~ -300;
-#X obj 306 485 *~;
-#X obj 306 449 *~ 0.1;
-#X text 448 493 << noise simulates non-oscillating airflow when overblown
-;
-#X obj 186 561 outlet~;
-#N canvas 58 1286 407 525 pulse 0;
-#X obj 83 340 *~;
-#X obj 83 366 *~;
-#X obj 31 366 sig~ 1;
-#X obj 52 419 /~;
-#X obj 67 393 +~;
-#X text 116 366 X^2;
-#X text 97 396 1+X^2;
-#X text 84 421 1/(1+X^2);
-#X obj 83 317 osc~;
-#X obj 167 320 clip~ 0 999999;
-#X obj 52 483 outlet~;
-#X text 271 218 << tweak all this;
-#X text 25 14 based on F04.waveshaping.pulse.pd;
-#X obj 83 84 /~ 2;
-#X obj 167 148 -~;
-#X obj 167 170 /~ 127;
-#X obj 52 452 hip~ 5;
-#X obj 167 202 *~;
-#X obj 167 232 *~;
-#X obj 167 262 *~;
-#X obj 167 294 *~ 1000;
-#X obj 118 125 sig~ 139;
-#X obj 83 58 inlet~;
-#N canvas 331 1377 215 174 _ftom 0;
-#X obj -482 -776 tabread4~ _ftom;
-#X obj -482 -818 /~ 10000;
-#X obj -482 -797 *~ 256;
-#N canvas 0 23 450 278 (subpatch) 0;
-#X array _ftom 256 float 3;
-#A 0 0 27.0762 39.0762 46.0958 51.0762 54.9394 58.0958 60.7645 63.0762
-65.1153 66.9394 68.5894 70.0958 71.4815 72.7645 73.9589 75.0762 76.1258
-77.1153 78.0514 78.9394 79.784 80.5894 81.359 82.0958 82.8025 83.4815
-84.1349 84.7645 85.372 85.9589 86.5266 87.0762 87.609 88.1258 88.6276
-89.1153 89.5897 90.0514 90.5011 90.9394 91.3669 91.784 92.1914 92.5894
-92.9785 93.359 93.7313 94.0958 94.4528 94.8025 95.1453 95.4815 95.8113
-96.1349 96.4525 96.7645 97.0709 97.372 97.6679 97.9589 98.2451 98.5266
-98.8036 99.0762 99.3446 99.609 99.8693 100.126 100.379 100.628 100.873
-101.115 101.354 101.59 101.822 102.051 102.278 102.501 102.722 102.939
-103.154 103.367 103.577 103.784 103.989 104.191 104.392 104.589 104.785
-104.978 105.17 105.359 105.546 105.731 105.914 106.096 106.275 106.453
-106.629 106.803 106.975 107.145 107.314 107.482 107.647 107.811 107.974
-108.135 108.294 108.453 108.609 108.764 108.918 109.071 109.222 109.372
-109.521 109.668 109.814 109.959 110.103 110.245 110.386 110.527 110.666
-110.804 110.94 111.076 111.211 111.345 111.477 111.609 111.74 111.869
-111.998 112.126 112.253 112.379 112.504 112.628 112.751 112.873 112.995
-113.115 113.235 113.354 113.472 113.59 113.706 113.822 113.937 114.051
-114.165 114.278 114.39 114.501 114.612 114.722 114.831 114.939 115.047
-115.154 115.261 115.367 115.472 115.577 115.681 115.784 115.887 115.989
-116.09 116.191 116.292 116.392 116.491 116.589 116.688 116.785 116.882
-116.978 117.074 117.17 117.265 117.359 117.453 117.546 117.639 117.731
-117.823 117.915 118.005 118.096 118.186 118.275 118.364 118.453 118.541
-118.629 118.716 118.803 118.889 118.975 119.06 119.145 119.23 119.314
-119.398 119.482 119.565 119.647 119.729 119.811 119.893 119.974 120.055
-120.135 120.215 120.294 120.374 120.453 120.531 120.609 120.687 120.764
-120.842 120.918 120.995 121.071 121.147 121.222 121.297 121.372 121.446
-121.521 121.594 121.668 121.741 121.814 121.887 121.959 122.031 122.103
-122.174 122.245 122.316 122.386 122.457 122.527 122.596 122.666 122.735
-122.804 122.872 122.94 123.008;
-#X coords 0 127 256 -12 50 50 1 0 0;
-#X restore -546 -793 graph;
-#X obj -482 -838 clip~ 0 10000;
-#X obj -482 -858 inlet~;
-#X obj -482 -755 outlet~;
-#X text -567 -722 shoddy temp replacement for ftom~;
-#X connect 0 0 6 0;
-#X connect 1 0 2 0;
-#X connect 2 0 0 0;
-#X connect 4 0 1 0;
-#X connect 5 0 4 0;
-#X restore 182 125 pd _ftom;
-#X connect 0 0 1 0;
-#X connect 0 0 1 1;
-#X connect 1 0 4 1;
-#X connect 2 0 3 0;
-#X connect 2 0 4 0;
-#X connect 3 0 16 0;
-#X connect 4 0 3 1;
-#X connect 8 0 0 0;
-#X connect 9 0 0 1;
-#X connect 13 0 8 0;
-#X connect 13 0 23 0;
-#X connect 14 0 15 0;
-#X connect 15 0 17 0;
-#X connect 15 0 17 1;
-#X connect 16 0 10 0;
-#X connect 17 0 18 0;
-#X connect 17 0 18 1;
-#X connect 18 0 19 0;
-#X connect 18 0 19 1;
-#X connect 19 0 20 0;
-#X connect 20 0 9 0;
-#X connect 21 0 14 0;
-#X connect 22 0 13 0;
-#X connect 23 0 14 1;
-#X restore 467 394 pd pulse;
-#X obj 366 105 inlet~;
-#X text 295 104 airflow >>;
-#X text 218 118 ('squeeze pressure');
-#X text 13 20 Sound model of a rubber duckie toy;
-#X text 14 51 Hint: use the differential of a continuous signal as
-input for a realistic response;
-#X text 13 29 ==================================;
-#X obj 366 133 lop~ 0.5;
-#X text 423 132 << airflow resistance;
-#X connect 0 0 14 0;
-#X connect 1 0 14 0;
-#X connect 2 0 3 0;
-#X connect 3 0 1 1;
-#X connect 4 0 7 0;
-#X connect 4 0 15 0;
-#X connect 4 0 29 0;
-#X connect 4 0 18 1;
-#X connect 4 0 16 0;
-#X connect 5 0 17 1;
-#X connect 6 0 32 0;
-#X connect 7 0 8 0;
-#X connect 8 0 9 0;
-#X connect 9 0 10 0;
-#X connect 9 0 10 1;
-#X connect 10 0 11 0;
-#X connect 11 0 12 1;
-#X connect 12 0 6 0;
-#X connect 13 0 12 0;
-#X connect 14 0 31 0;
-#X connect 15 0 13 0;
-#X connect 16 0 20 0;
-#X connect 17 0 27 0;
-#X connect 18 0 23 0;
-#X connect 18 0 23 1;
-#X connect 19 0 16 1;
-#X connect 20 0 18 0;
-#X connect 23 0 24 1;
-#X connect 23 0 24 0;
-#X connect 24 0 0 0;
-#X connect 27 0 6 1;
-#X connect 28 0 1 0;
-#X connect 29 0 28 1;
-#X connect 29 0 28 0;
-#X connect 32 0 0 1;
-#X connect 33 0 39 0;
-#X connect 39 0 4 0;
-#X connect 39 0 17 0;
-#X restore 39 127 pd duckie;
-#X obj 39 77 adc~ 10;
-#N canvas 0 22 504 229 differential 0;
-#X obj 27 80 rzero~ 1;
-#X obj 72 57 sig~ 1;
-#X obj 27 152 *~ 44100;
-#X obj 72 131 samplerate~;
-#X obj 72 110 loadbang;
-#X obj 27 25 inlet~;
-#X obj 27 190 outlet~;
-#X text 84 83 y[n] = x[n] - x[n-1];
-#X text 121 57 <<< heavy currently requires signal input to set coefficient
-;
-#X text 91 151 <<< multiply by samplerate to get velocity;
-#X connect 0 0 2 0;
-#X connect 1 0 0 1;
-#X connect 2 0 6 0;
-#X connect 3 0 2 1;
-#X connect 4 0 3 0;
-#X connect 5 0 0 0;
-#X restore 39 101 pd differential;
-#X connect 6 0 0 0;
-#X connect 6 0 0 1;
-#X connect 7 0 8 0;
-#X connect 8 0 6 0;
--- a/examples/pd/samphold/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-#N canvas 275 504 414 247 10;
-#X obj 55 212 dac~ 1 2;
-#X obj 55 171 *~ 0.1;
-#X obj 55 150 osc~ 440;
-#X obj 55 61 noise~;
-#X obj 55 128 samphold~;
-#X text 51 21 ==================;
-#X text 51 11 Sample and hold FM;
-#X obj 55 85 lop~ 1;
-#X obj 122 107 phasor~ 880;
-#X obj 55 107 *~ 1e+06;
-#X text 193 199 ---------------------------------;
-#X text 193 189 @krighxz / BELA / heavy / 12/2015;
-#X text 217 208 beaglert.cc / enzienaudio.com;
-#X connect 1 0 0 1;
-#X connect 1 0 0 0;
-#X connect 2 0 1 0;
-#X connect 3 0 7 0;
-#X connect 4 0 2 0;
-#X connect 7 0 9 0;
-#X connect 8 0 4 1;
-#X connect 9 0 4 0;
--- a/examples/pd/simple-fm/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#N canvas 275 573 409 282 10;
-#X obj 37 230 dac~ 1 2;
-#X text 175 222 ---------------------------------;
-#X obj 37 102 *~ 1000;
-#X obj 37 199 *~ 0.1;
-#X obj 37 79 adc~ 3;
-#X obj 65 125 adc~ 4;
-#X obj 94 147 adc~ 5;
-#N canvas 81 574 322 252 FMvoice 1;
-#X obj 20 174 +~;
-#X obj 93 116 osc~;
-#X obj 93 157 *~;
-#X obj 93 76 *~;
-#X obj 158 98 *~;
-#X obj 20 225 outlet~;
-#X obj 20 200 osc~;
-#X obj 20 39 inlet~ freq;
-#X obj 108 39 inlet~ harmRatio~;
-#X obj 173 69 inlet~ modIndex~;
-#X connect 0 0 6 0;
-#X connect 1 0 2 0;
-#X connect 2 0 0 1;
-#X connect 3 0 4 0;
-#X connect 3 0 1 0;
-#X connect 4 0 2 1;
-#X connect 6 0 5 0;
-#X connect 7 0 3 0;
-#X connect 7 0 0 0;
-#X connect 8 0 3 1;
-#X connect 9 0 4 1;
-#X restore 37 169 pd FMvoice;
-#X text 33 22 Simple FM;
-#X text 33 32 =========;
-#X text 175 212 @krighxz / BELA / heavy / 12/2015;
-#X text 199 231 beaglert.cc / enzienaudio.com;
-#X connect 2 0 7 0;
-#X connect 3 0 0 1;
-#X connect 3 0 0 0;
-#X connect 4 0 2 0;
-#X connect 5 0 7 1;
-#X connect 6 0 7 2;
-#X connect 7 0 3 0;
--- a/examples/pd/tableScrubbing/_main.pd	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#N canvas 503 319 861 473 10;
-#N canvas 0 22 450 278 (subpatch) 0;
-#X array exampleTable 65238 float 2;
-#X coords 0 1 65238 -1 200 140 1 0 0;
-#X restore 21 213 graph;
-#X obj 243 329 adc~ 1 2 3;
-#X obj 300 426 dac~;
-#X text 317 264 <<< delete this object before compiling!;
-#X obj 300 392 tabread4~ exampleTable;
-#X msg 243 218 read -resize rt.wav exampleTable;
-#X obj 300 350 lop~ 1;
-#X obj 300 371 *~ 65238;
-#X obj 243 266 soundfiler;
-#X text 489 229 right-click array -> properties -> toggle "save contents"
-;
-#X text 463 216 <<< after loading a file:;
-#X text 17 23 Load sample into table and scrub using analog input;
-#X text 17 33 ===================================================;
-#X text 362 351 <<< avoid zipper noise;
-#X text 362 371 <<< length of sample;
-#X text 317 328 <<< analog input 0 (range 0-1);
-#X text 631 419 ---------------------------------;
-#X text 631 409 @krighxz / BELA / heavy / 12/2015;
-#X text 655 428 beaglert.cc / enzienaudio.com;
-#X text 30 61 N.B. the patch cannot be bigger than 512kb in size \;
-only use this for *very small soundfiles*;
-#X text 29 99 You can modify the render.cpp file to load samples into
-tables using the Heavy API: https://enzienaudio.com/docs/c.html#api-hv-table
-;
-#X connect 1 2 6 0;
-#X connect 4 0 2 0;
-#X connect 4 0 2 1;
-#X connect 5 0 8 0;
-#X connect 6 0 7 0;
-#X connect 7 0 4 0;
Binary file examples/pd/tableScrubbing/rt.wav has changed
--- a/examples/samples/SampleData.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-/*
- * SampleData.h
- *
- *  Created on: Nov 5, 2014
- *      Author: Victor Zappi
- */
-
-#ifndef SAMPLEDATA_H_
-#define SAMPLEDATA_H_
-
-// User defined structure to pass between main and rendere complex data retrieved from file
-struct SampleData {
-	float *samples;	// Samples in file
-	int sampleLen;	// Total nume of samples
-};
-
-
-
-#endif /* SAMPLEDATA_H_ */
--- a/examples/samples/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: Andrew McPherson and Victor Zappi
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <string>
-#include <getopt.h>
-#include <sndfile.h>				// to load audio files
-
-#include <Bela.h>
-#include "SampleData.h"
-
-using namespace std;
-
-// Load samples from file
-int initFile(string file, SampleData *smp)//float *& smp)
-{
-	SNDFILE *sndfile ;
-	SF_INFO sfinfo ;
-
-	if (!(sndfile = sf_open (file.c_str(), SFM_READ, &sfinfo))) {
-		cout << "Couldn't open file " << file << endl;
-		return 1;
-	}
-
-	int numChan = sfinfo.channels;
-	if(numChan != 1)
-	{
-		cout << "Error: " << file << " is not a mono file" << endl;
-		return 1;
-	}
-
-	smp->sampleLen = sfinfo.frames * numChan;
-	smp->samples = new float[smp->sampleLen];
-	if(smp == NULL){
-		cout << "Could not allocate buffer" << endl;
-		return 1;
-	}
-
-	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
-	int readcount = sf_read_float(sndfile, smp->samples, smp->sampleLen);
-
-	// Pad with zeros in case we couldn't read whole file
-	for(int k = readcount; k <smp->sampleLen; k++)
-		smp->samples[k] = 0;
-
-	if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
-		double	scale ;
-		int 	m ;
-
-		sf_command (sndfile, SFC_CALC_SIGNAL_MAX, &scale, sizeof (scale)) ;
-		if (scale < 1e-10)
-			scale = 1.0 ;
-		else
-			scale = 32700.0 / scale ;
-		cout << "File samples scale = " << scale << endl;
-
-		for (m = 0; m < smp->sampleLen; m++)
-			smp->samples[m] *= scale;
-	}
-
-	sf_close(sndfile);
-
-	return 0;
-}
-
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	//rt_task_delete ((RT_TASK *) &gTriggerSamplesTask);
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --file [-f] filename:    Name of the file to load (default is \"sample.wav\")\n";
-	cerr << "   --help [-h]:             Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	string fileName;			// Name of the sample to load
-
-	SampleData sampleData;		// User define structure to pass data retrieved from file to render function
-	sampleData.samples = 0;
-	sampleData.sampleLen = -1;
-
-
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"file", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case 'f':
-				fileName = string((char *)optarg);
-				break;
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	if(fileName.empty()){
-		fileName = "samples/sample.wav";
-	}
-
-	if(settings.verbose) {
-		cout << "Loading file " << fileName << endl;
-	}
-
-	// Load file
-	if(initFile(fileName, &sampleData) != 0)
-	{
-		cout << "Error: unable to load samples " << endl;
-		return -1;
-	}
-
-	if(settings.verbose)
-		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
-
-
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, &sampleData) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// All done!
-	return 0;
-}
--- a/examples/samples/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/*
- *
- * Andrew McPherson and Victor Zappi
- * Queen Mary, University of London
- */
-
-/**
-\example 4_audio_samples
-
-Playback WAV files
-------------------
-
-This sketch shows how to playback audio samples from a buffer.
-
-An audio file is loaded into a buffer `SampleData` as `gSampleData`. This is 
-accessed with a read pointer that is incremented at audio rate within the render 
-function: `out += gSampleData.samples[gReadPtr++]`.
-
-Note that the read pointer is stopped from incrementing past the length of the 
-`gSampleData`. This is achieved by comparing the read pointer value against the 
-sample length which we can access as follows: `gSampleData.sampleLen`.
-
-The sample is triggered by keyboard input: (a) starts sample playback, (s) 
-stops sample playback. The triggering is treated as a lower priority task than 
-the audio. You can see this at the bottom of the render function: 
-`Bela_scheduleAuxiliaryTask(gTriggerSamplesTask)`;
-*/
-
-#include <Bela.h>
-#include <cmath>
-#include "SampleData.h"
-
-SampleData gSampleData;	// User defined structure to get complex data from main
-int gReadPtr;			// Position of last read sample from file
-
-// Task for handling the update of the frequencies using the matrix
-AuxiliaryTask gTriggerSamplesTask;
-
-bool initialise_trigger();
-void trigger_samples();
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-
-	// Retrieve a parameter passed in from the initAudio() call
-	gSampleData = *(SampleData *)userData;
-
-	gReadPtr = -1;
-
-	// Initialise auxiliary tasks
-	if(!initialise_trigger())
-		return false;
-
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		float out = 0;
-
-		// If triggered...
-		if(gReadPtr != -1)
-			out += gSampleData.samples[gReadPtr++];	// ...read each sample...
-
-		if(gReadPtr >= gSampleData.sampleLen)
-			gReadPtr = -1;
-
-		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-			context->audioOut[n * context->audioChannels + channel] = out;	// ...and put it in both left and right channel
-	}
-
-	// Request that the lower-priority task run at next opportunity
-	Bela_scheduleAuxiliaryTask(gTriggerSamplesTask);
-}
-
-// Initialise the auxiliary task
-// and print info
-
-bool initialise_trigger()
-{
-	if((gTriggerSamplesTask = Bela_createAuxiliaryTask(&trigger_samples, 50, "bela-trigger-samples")) == 0)
-		return false;
-
-	rt_printf("Press 'a' to trigger sample, 's' to stop\n");
-	rt_printf("Press 'q' to quit\n");
-
-	return true;
-}
-
-// This is a lower-priority call to periodically read keyboard input
-// and trigger samples. By placing it at a lower priority,
-// it has minimal effect on the audio performance but it will take longer to
-// complete if the system is under heavy audio load.
-
-void trigger_samples()
-{
-	// This is not a real-time task!
-	// Cos getchar is a system call, not handled by Xenomai.
-	// This task will be automatically down graded.
-
-	char keyStroke = '.';
-
-	keyStroke =	getchar();
-	while(getchar()!='\n'); // to read the first stroke
-
-	switch (keyStroke)
-	{
-		case 'a':
-			gReadPtr = 0;
-			break;
-		case 's':
-			gReadPtr = -1;
-			break;
-		case 'q':
-			gShouldStop = true;
-			break;
-		default:
-			break;
-	}
-}
-
-
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	delete[] gSampleData.samples;
-}
Binary file examples/samples/sample.wav has changed
--- a/examples/scope_analogue/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/**
-\example 3_scope_analog
-
-Connecting potentiometers
--------------------------
-
-This example reads from analogue inputs 0 and 1 via `analogReadFrame()` and 
-generates a sine wave with amplitude and frequency determined by their values. 
-It's best to connect a 10K potentiometer to each of these analog inputs. Far 
-left and far right pins of the pot go to 3.3V and GND, the middle should be 
-connected to the analog in pins.
-
-The sine wave is then plotted on the oscilloscope. Click the Open Scope button to 
-view the results. As you turn the potentiometers you will see the amplitude and 
-frequency of the sine wave change.
-
-This project also shows as example of `map()` which allows you to re-scale a number 
-from one range to another. Note that `map()` does not constrain your variable 
-within the upper and lower limits. If you want to do this use the `constrain()`
-function.
-*/
-
-#include <Bela.h>
-#include <cmath>
-#include <Scope.h>
-
-Scope scope;
-
-float gInverseSampleRate;
-float gPhase;
-
-bool setup(BelaContext *context, void *userData)
-{
-
-    // setup the scope with 3 channels at the audio sample rate
-	scope.setup(3, context->audioSampleRate);
-	
-	gInverseSampleRate = 1.0 / context->audioSampleRate;
-	gPhase = 0.0;
-
-	return true;
-}
-
-void render(BelaContext *context, void *userData)
-{
-
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-	    
-	    // read analogIn channels 0 and 1
-	    float in1 = analogRead(context, n, 0);
-	    float in2 = analogRead(context, n, 1);
-	    
-	    // map in1 to amplitude and in2 to frequency
-	    float amplitude = in1 * 0.8f;
-	    float frequency = map(in2, 0, 1, 100, 1000);
-	    
-	    // generate a sine wave with the amplitude and frequency 
-	    float out = amplitude * sinf(gPhase);
-	    gPhase += 2.0 * M_PI * frequency * gInverseSampleRate;
-		if(gPhase > 2.0 * M_PI)
-			gPhase -= 2.0 * M_PI;
-	    
-	    // log the sine wave and sensor values on the scope
-	    scope.log(out, in1, in2);
-	    
-	    // pass the sine wave to the audio outputs
-	    for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-			context->audioOut[n * context->audioChannels + channel] = out;
-
-	}
-}
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/scope_basic/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*
- ____  _____ _        _    
-| __ )| ____| |      / \   
-|  _ \|  _| | |     / _ \  
-| |_) | |___| |___ / ___ \ 
-|____/|_____|_____/_/   \_\.io
-
- */
-
-/**
-\example 1_scope_basic
-
-Oscilloscope in-browser
------------------------
-
-This example demonstrates the scope feature of the IDE.
-
-The scope is instantiated at the top of the file via `Scope scope;`
-
-In `setup()` we define how many channels the scope should have and the sample 
-rate that it should run at via `scope.setup(3, context->audioSampleRate)`.
-
-In `render()` we choose what the scope log via `scope.log(out, out2, out3)`. 
-In this example the scope is logging three sine waves with different phases. To see
-the output click on the <b>Open Scope</b> button.
-
-An additional option is to set the trigger of the oscilloscope from within `render()`.
-In this example we are triggering the scope when oscillator 1 becomes less than 
-oscillator 2 via `scope.trigger()`. Note that this functionality only takes effect
-when the triggering mode is set to custom in the scope UI.
-*/
-
-#include <Bela.h>
-#include <Scope.h>
-#include <cmath>
-
-// set the frequency of the oscillators
-float gFrequency = 110.0;
-float gPhase;
-float gInverseSampleRate;
-
-// instantiate the scope
-Scope scope;
-
-bool setup(BelaContext *context, void *userData)
-{
-    // tell the scope how many channels and the sample rate
-    scope.setup(3, context->audioSampleRate);
-
-    gPhase = 0;
-    gInverseSampleRate = 1.0f/context->audioSampleRate;
-    
-	return true;
-}
-
-float lastOut = 0.0;
-float lastOut2 = 0.0;
-void render(BelaContext *context, void *userData)
-{
-    // iterate over the audio frames and create three oscillators, seperated in phase by PI/2
-    for (unsigned int n=0; n<context->audioFrames; n++){
-        float out = 0.8f * sinf(gPhase);
-        float out2 = 0.8f * sinf(gPhase - M_PI/2);
-		float out3 = 0.8f * sinf(gPhase + M_PI/2);
-		gPhase += 2.0 * M_PI * gFrequency * gInverseSampleRate;
-		if(gPhase > 2.0 * M_PI)
-			gPhase -= 2.0 * M_PI;
-			
-		// log the three oscillators to the scope
-        scope.log(out, out2, out3);
-        
-        // optional - tell the scope to trigger when oscillator 1 becomes less than oscillator 2
-        // note this has no effect unless trigger mode is set to custom in the scope UI
-        if (lastOut >= lastOut2 && out < out2){
-            scope.trigger();
-        }
-        
-        lastOut = out;
-        lastOut2 = out2;
-    }
-}
-
-void cleanup(BelaContext *context, void *userData)
-{
-
-}
--- a/examples/stepper/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-
-#include <Bela.h>
-
-const int kStepLengthSlow = 1000;
-const int kStepLengthFast = 500;
-
-int gStepLengthSamples = kStepLengthSlow;
-
-const int gPinA1 = P8_27;
-const int gPinA2 = P8_28;
-const int gPinB1 = P8_29;
-const int gPinB2 = P8_30;
-const int gPinServo = P9_16;
-
-int gStepCounter = 0;
-int gPhase = 0;
-
-int gServoCounter = 0;
-
-
-enum {
-	kStateMoveRight1 = 0,
-	kStateMoveLeft1,
-	kStateMoveRight2,
-	kStateMoveLeft2,
-	kStateMoveRight3,
-	kStateMoveLeft3,
-	kStateSpin,
-	kStateMax
-};
-
-int gState = 0;
-int gStateCounter = 0;
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{	
-	// This project makes the assumption that the audio and digital
-	// sample rates are the same. But check it to be sure!
-	if(context->audioFrames != context->digitalFrames) {
-		rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n");
-		return false;
-	}
-	
-	pinMode(context, 0, gPinA1, OUTPUT);
-	pinMode(context, 0, gPinA2, OUTPUT);
-	pinMode(context, 0, gPinB1, OUTPUT);
-	pinMode(context, 0, gPinB2, OUTPUT);
-	pinMode(context, 0, gPinServo, OUTPUT);
-		
-	return true;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		if(gPhase == 0 || gPhase == 1) {
-			digitalWriteOnce(context, n, gPinB1, HIGH);
-			digitalWriteOnce(context, n, gPinB2, LOW);
-		}
-		else {
-			digitalWriteOnce(context, n, gPinB1, LOW);
-			digitalWriteOnce(context, n, gPinB2, HIGH);			
-		}
-		
-		if(gPhase == 1 || gPhase == 2) {
-			digitalWriteOnce(context, n, gPinA1, HIGH);
-			digitalWriteOnce(context, n, gPinA2, LOW);
-		}
-		else {
-			digitalWriteOnce(context, n, gPinA1, LOW);
-			digitalWriteOnce(context, n, gPinA2, HIGH);			
-		}
-		
-		if(--gServoCounter > 0) 
-			digitalWriteOnce(context, n, gPinServo, HIGH);
-		else
-			digitalWriteOnce(context, n, gPinServo, LOW);
-		
-		if(++gStepCounter >= gStepLengthSamples) {
-			gStateCounter++;
-			
-			switch(gState) {
-				case kStateMoveRight1:
-				case kStateMoveRight2:
-				case kStateMoveRight3:
-					gPhase = (gPhase + 1) & 3;
-					break;
-				case kStateMoveLeft1:
-				case kStateMoveLeft2:
-				case kStateMoveLeft3:				
-					gPhase = (gPhase + 3) & 3;	
-					break;
-				case kStateSpin:
-					gPhase = (gPhase + 1) & 3;
-					break;		
-			}
-			
-			if(gState == kStateSpin) {
-				if(gStateCounter >= 48) {
-					gStateCounter = 0;
-					gState = 0;
-					gStepLengthSamples = kStepLengthSlow;
-				}				
-			}
-			else {
-				if(gStateCounter >= 16) {
-					gStateCounter = 0;
-					gState++;
-					if(gState & 1)
-						gServoCounter = 120;
-					else
-						gServoCounter = 80;
-					if(gState == kStateSpin)
-						gStepLengthSamples = kStepLengthFast;
-				}
-			}
-			
-			gStepCounter = 0;
-		}
-	}
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	
-}
--- a/examples/tank_wars/game.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/*
- * game.cpp
- *
- *  Created on: Nov 10, 2014
- *      Author: parallels
- */
-
-#include <cmath>
-#include <cstdlib>
-#include "vector_graphics.h"
-#include <Utilities.h>
-
-// Virtual screen size
-int screenWidth, screenHeight;
-
-// Basic information on the terrain and the tanks
-float *groundLevel;  // Y coordinate of the ground for each X coordinate
-float tank1X, tank1Y, tank2X, tank2Y; // Positions of the two tanks
-float tankRadius = 20;  // Radius of the tanks
-float cannonLength = 40;   // How long the cannon on each tank extends
-float gravity = 0.05;      // Strength of gravity
-
-// Current state of the game
-int playerHasWon = 0; // 1 if player 1 wins, 2 if player 2 wins, 0 if game in progress
-bool player1Turn = true;  // true if it's player 1's turn; false otherwise
-float tank1CannonAngle = M_PI/2;
-float tank2CannonAngle = M_PI/2; // Direction the tank cannons are pointing
-float tank1CannonStrength = 3;
-float tank2CannonStrength = 3; // Strength of intended projectile launch
-
-// Location of the projectile
-bool projectileInMotion = false;
-float projectilePositionX, projectilePositionY;
-float projectileVelocityX, projectileVelocityY;
-
-// Infor needed for sound rendering
-bool collisionJustOccurred = false;
-bool tankHitJustOccurred = false;
-
-// Useful utility function for generating random floating-point values
-float randomFloat(float low, float hi)
-{
-	float r = (float)random() / (float)RAND_MAX;
-	return map(r, 0, 1, low, hi);
-}
-
-// Restart the game, without reallocating memory
-void restartGame()
-{
-	float player1Height = screenHeight * 3/4; // randomFloat(screenHeight/2, screenHeight-5);
-	float player2Height = screenHeight - 5; // randomFloat(screenHeight/2, screenHeight-5);
-	for(int i = 0; i < screenWidth * 0.2; i++) {
-		groundLevel[i] = player1Height;
-	}
-	for(int i = screenWidth * 0.2; i < screenWidth * 0.8; i++) {
-		groundLevel[i] = player1Height + (player2Height - player1Height) * (i - screenWidth*0.2)/(screenWidth*0.6);
-	}
-	for(int i = screenWidth * 0.8; i < screenWidth; i++) {
-		groundLevel[i] = player2Height;
-	}
-
-	// Set the location of the two tanks so they rest on the ground at opposite sides
-	tank1X = screenWidth * 0.1;
-	tank1Y = player1Height;
-	tank2X = screenWidth * 0.9;
-	tank2Y = player2Height;
-
-	playerHasWon = 0;
-	projectileInMotion = false;
-}
-
-// Initialise the game
-void setupGame(int width, int height)
-{
-	// Set the screen size
-	screenWidth = width;
-	screenHeight = height;
-
-	// Initialize the ground level
-	groundLevel = new float[screenWidth];
-
-	restartGame();
-}
-
-// Advance the turn to the next player
-void nextPlayersTurn() {
-	player1Turn = !player1Turn;
-}
-
-
-// Move forward one frame on the game physics
-void nextGameFrame()
-{
-	if(!projectileInMotion)
-		return;
-
-	// Update position of projectile
-	projectilePositionX += projectileVelocityX;
-	projectilePositionY += projectileVelocityY;
-	projectileVelocityY += gravity;
-
-	// Check collision with tanks first: a collision with tank 1 means player 2 wins and vice-versa
-	if((tank1X - projectilePositionX)*(tank1X - projectilePositionX) +
-		(tank1Y - projectilePositionY)*(tank1Y - projectilePositionY)
-		<= tankRadius * tankRadius)
-	{
-		projectileInMotion = false;
-		collisionJustOccurred = false;
-		tankHitJustOccurred = true;
-		playerHasWon = 2;
-	}
-	else if((tank2X - projectilePositionX)*(tank2X - projectilePositionX) +
-		(tank2Y - projectilePositionY)*(tank2Y - projectilePositionY)
-		<= tankRadius * tankRadius)
-	{
-		projectileInMotion = false;
-		collisionJustOccurred = false;
-		tankHitJustOccurred = true;
-		playerHasWon = 1;
-	}
-	else if(projectilePositionX < 0 || projectilePositionX >= screenWidth) {
-		// Check collision whether projectile has exited the screen to the left or right
-		projectileInMotion = false;
-		collisionJustOccurred = true;
-		nextPlayersTurn();
-	}
-	else if(projectilePositionY >= groundLevel[(int)floorf(projectilePositionX)]) {
-		// Check for projectile collision with ground
-		projectileInMotion = false;
-		collisionJustOccurred = true;
-		nextPlayersTurn();
-	}
-}
-
-// Updates for game state
-void setTank1CannonAngle(float angle)
-{
-	tank1CannonAngle = angle;
-}
-
-void setTank2CannonAngle(float angle)
-{
-	tank2CannonAngle = angle;
-}
-
-void setTank1CannonStrength(float strength)
-{
-	tank1CannonStrength = strength;
-}
-
-void setTank2CannonStrength(float strength)
-{
-	tank2CannonStrength = strength;
-}
-
-// FIRE!
-void fireProjectile()
-{
-	// Can't fire while projectile is already moving, or if someone has won
-	if(projectileInMotion)
-		return;
-	if(playerHasWon != 0)
-		return;
-
-    if(player1Turn) {
-		projectilePositionX = tank1X + cannonLength * cosf(tank1CannonAngle);
-		projectilePositionY = tank1Y - cannonLength * sinf(tank1CannonAngle);
-		projectileVelocityX = tank1CannonStrength * cosf(tank1CannonAngle);
-		projectileVelocityY = -tank1CannonStrength * sinf(tank1CannonAngle);
-    }
-    else {
-		projectilePositionX = tank2X + cannonLength * cosf(tank2CannonAngle);
-		projectilePositionY = tank2Y - cannonLength * sinf(tank2CannonAngle);
-		projectileVelocityX = tank2CannonStrength * cosf(tank2CannonAngle);
-		projectileVelocityY = -tank2CannonStrength * sinf(tank2CannonAngle);
-    }
-
-    // GO!
-    projectileInMotion = true;
-}
-
-// Game state queries
-bool gameStatusPlayer1Turn()
-{
-	return player1Turn;
-}
-
-bool gameStatusProjectileInMotion()
-{
-	return projectileInMotion;
-}
-
-int gameStatusWinner()
-{
-	return playerHasWon;
-}
-
-bool gameStatusCollisionOccurred()
-{
-	if(collisionJustOccurred) {
-		collisionJustOccurred = false;
-		return true;
-	}
-	return false;
-}
-
-bool gameStatusTankHitOccurred()
-{
-	if(tankHitJustOccurred) {
-		tankHitJustOccurred = false;
-		return true;
-	}
-	return false;
-}
-
-
-float gameStatusProjectileHeight()
-{
-	return projectilePositionY / (float)screenHeight;
-}
-
-// Clean up any allocated memory for the game
-void cleanupGame()
-{
-	delete groundLevel;
-}
-
-// Drawing routines. Arguments are (interleaved) buffer to render
-// into, the available size, and the target for how many samples
-// to use (actual usage might vary slightly). Regardless of
-// lengthTarget, never use more than bufferSize samples.
-
-int drawGround(float *buffer, int bufferSize, int framesTarget)
-{
-	int length;
-
-	// Calculate total length of ground line, to arrive at a speed calculation
-	float totalLineLength = 0.4f*screenWidth
-							+ sqrtf(0.36f*screenWidth*screenWidth
-									+ (tank2Y-tank1Y)*(tank2Y-tank1Y));
-
-	// Speed is calculated in pixels per frame
-	float speed = totalLineLength / (float)framesTarget;
-
-	// Draw three lines: platforms for tanks and the connecting line.
-	// Eventually, render a more complex ground from the array.
-	length = renderLine(0, tank1Y, screenWidth * 0.2, tank1Y,
-						speed, buffer, bufferSize);
-	length += renderLine(screenWidth * 0.2, tank1Y, screenWidth * 0.8, tank2Y,
-						speed, &buffer[length], bufferSize - length);
-	length += renderLine(screenWidth * 0.8, tank2Y, screenWidth, tank2Y,
-						speed, &buffer[length], bufferSize - length);
-
-	return length;
-}
-
-int drawTanks(float *buffer, int bufferSize, int framesTarget)
-{
-	int length = 0;
-
-	// Calculate total length of tank lines, to arrive at a speed calculation
-	float totalLineLength = 2.0*M_PI*tankRadius + 2.0*(cannonLength - tankRadius);
-
-	// Speed is calculated in pixels per frame
-	float speed = totalLineLength / (float)framesTarget;
-
-	if(playerHasWon != 2) {
-		// Tank 1 body = semicircle + line
-		length += renderArc(tank1X, tank1Y, tankRadius, M_PI, 2.0 * M_PI,
-							speed, buffer, bufferSize);
-		length += renderLine(tank1X + tankRadius, tank1Y,
-							 tank1X - tankRadius, tank1Y,
-							speed, &buffer[length], bufferSize - length);
-		// Tank 1 cannon (line depending on angle)
-		length += renderLine(tank1X + tankRadius * cosf(tank1CannonAngle),
-			 tank1Y - tankRadius * sinf(tank1CannonAngle),
-			 tank1X + cannonLength * cosf(tank1CannonAngle),
-			 tank1Y - cannonLength * sinf(tank1CannonAngle),
-			 speed, &buffer[length], bufferSize - length);
-	}
-
-	if(playerHasWon != 1) {
-		// Same idea for tank 2
-		length += renderArc(tank2X, tank2Y, tankRadius, M_PI, 2.0 * M_PI,
-							speed, &buffer[length], bufferSize - length);
-		length += renderLine(tank2X + tankRadius, tank2Y,
-							 tank2X - tankRadius, tank2Y,
-							 speed, &buffer[length], bufferSize - length);
-		length += renderLine(tank2X + tankRadius * cosf(tank2CannonAngle),
-			 tank2Y - tankRadius * sinf(tank2CannonAngle),
-			 tank2X + cannonLength * cosf(tank2CannonAngle),
-			 tank2Y - cannonLength * sinf(tank2CannonAngle),
-			 speed, &buffer[length], bufferSize - length);
-	}
-
-	return length;
-}
-
-int drawProjectile(float *buffer, int bufferSize, int framesTarget)
-{
-	if(!projectileInMotion)
-		return 0;
-
-	// Draw a point for a specified number of frames (each containing X and Y)
-	// Return the number of items used in the buffer, which will be twice
-	// the number of frames unless the buffer is full
-
-	if(bufferSize/2 < framesTarget) {
-		renderPoint(projectilePositionX, projectilePositionY, buffer, bufferSize/2);
-		return bufferSize;
-	}
-	else {
-		renderPoint(projectilePositionX, projectilePositionY, buffer, framesTarget);
-		return framesTarget*2;
-	}
-}
-
-// Main drawing routine entry point
-int drawGame(float *buffer, int bufferSize)
-{
-	int length;
-
-	// Based on buffer size, come up with speeds for each of the elements
-	// 50% of time to ground; 30% to the tanks and 20% to the projectile
-	// Give a margin of 25% beyond so we don't run out of buffer space
-	// if things take longer to draw than we guess they will
-	const float amountToUse = 0.375; // 0.75/2 because two samples per frame
-	const float groundFraction = 0.5 * amountToUse;
-	const float tankFraction = 0.3 * amountToUse;
-	const float projectileFraction = 0.2 * amountToUse;
-
-	length = drawGround(buffer, bufferSize, bufferSize * groundFraction);
-	length += drawTanks(&buffer[length], bufferSize - length,
-						bufferSize * tankFraction);
-	length += drawProjectile(&buffer[length], bufferSize - length,
-						bufferSize * projectileFraction);
-
-	return length;
-}
--- a/examples/tank_wars/game.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-/*
- * game.h
- *
- *  Created on: Nov 10, 2014
- *      Author: parallels
- */
-
-#ifndef GAME_H_
-#define GAME_H_
-
-// Initialisation
-void setupGame(int width, int height);
-void restartGame();
-
-// Update physics
-void nextGameFrame();
-
-// State updaters
-void setTank1CannonAngle(float angle);
-void setTank2CannonAngle(float angle);
-void setTank1CannonStrength(float strength);
-void setTank2CannonStrength(float strength);
-void fireProjectile();
-
-// State queries
-bool gameStatusPlayer1Turn();
-bool gameStatusProjectileInMotion();
-int gameStatusWinner();
-bool gameStatusCollisionOccurred();
-bool gameStatusTankHitOccurred();
-float gameStatusProjectileHeight();
-
-// Render screen; returns length of buffer used
-int drawGame(float *buffer, int bufferSize);
-
-// Cleanup and memory release
-void cleanupGame();
-
-#endif /* GAME_H_ */
--- a/examples/tank_wars/main.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,169 +0,0 @@
-/*
- * main.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <libgen.h>
-#include <signal.h>
-#include <getopt.h>
-#include <sndfile.h>
-#include <Bela.h>
-
-extern int gScreenFramesPerSecond;
-
-float *gMusicBuffer = 0;
-int gMusicBufferLength = 0;
-float *gSoundBoomBuffer = 0;
-int gSoundBoomBufferLength = 0;
-float *gSoundHitBuffer = 0;
-int gSoundHitBufferLength = 0;
-
-
-using namespace std;
-
-// Load a sound sample from file
-int loadSoundFile(const string& path, float **buffer, int *bufferLength)
-{
-	SNDFILE *sndfile ;
-	SF_INFO sfinfo ;
-
-	if (!(sndfile = sf_open (path.c_str(), SFM_READ, &sfinfo))) {
-		cout << "Couldn't open file " << path << endl;
-		return 1;
-	}
-
-	int numChan = sfinfo.channels;
-	if(numChan != 1)
-	{
-		cout << "Error: " << path << " is not a mono file" << endl;
-		return 1;
-	}
-
-	*bufferLength = sfinfo.frames * numChan;
-	*buffer = new float[*bufferLength];
-	if(*buffer == 0){
-		cout << "Could not allocate buffer" << endl;
-		return 1;
-	}
-
-	int subformat = sfinfo.format & SF_FORMAT_SUBMASK;
-	int readcount = sf_read_float(sndfile, *buffer, *bufferLength);
-
-	// Pad with zeros in case we couldn't read whole file
-	for(int k = readcount; k < *bufferLength; k++)
-		(*buffer)[k] = 0;
-
-	sf_close(sndfile);
-	return 0;
-}
-
-// Handle Ctrl-C by requesting that the audio rendering stop
-void interrupt_handler(int var)
-{
-	gShouldStop = true;
-}
-
-// Print usage information
-void usage(const char * processName)
-{
-	cerr << "Usage: " << processName << " [options]" << endl;
-
-	Bela_usage();
-
-	cerr << "   --fps [-f] value:           Set target frames per second\n";
-	cerr << "   --help [-h]:                Print this menu\n";
-}
-
-int main(int argc, char *argv[])
-{
-	BelaInitSettings settings;	// Standard audio settings
-	string musicFileName = "music.wav";
-	string soundBoomFileName = "boom.wav";
-	string soundHitFileName = "hit.wav";
-	
-	struct option customOptions[] =
-	{
-		{"help", 0, NULL, 'h'},
-		{"fps", 1, NULL, 'f'},
-		{NULL, 0, NULL, 0}
-	};
-
-	// Set default settings
-	Bela_defaultSettings(&settings);
-
-	// Parse command-line arguments
-	while (1) {
-		int c;
-		if ((c = Bela_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
-				break;
-		switch (c) {
-		case 'f':
-				gScreenFramesPerSecond = atoi(optarg);
-				if(gScreenFramesPerSecond < 1)
-					gScreenFramesPerSecond = 1;
-				if(gScreenFramesPerSecond > 100)
-					gScreenFramesPerSecond = 100;
-				break;
-		case 'h':
-				usage(basename(argv[0]));
-				exit(0);
-		case '?':
-		default:
-				usage(basename(argv[0]));
-				exit(1);
-		}
-	}
-
-	// Load the sound files
-	if(loadSoundFile(musicFileName, &gMusicBuffer, &gMusicBufferLength) != 0) {
-		cout << "Warning: unable to load sound file " << musicFileName << endl;
-	}
-	if(loadSoundFile(soundBoomFileName, &gSoundBoomBuffer, &gSoundBoomBufferLength) != 0) {
-		cout << "Warning: unable to load sound file " << soundBoomFileName << endl;
-	}
-	if(loadSoundFile(soundHitFileName, &gSoundHitBuffer, &gSoundHitBufferLength) != 0) {
-		cout << "Warning: unable to load sound file " << soundHitFileName << endl;
-	}
-	
-	// Initialise the PRU audio device
-	if(Bela_initAudio(&settings, 0) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
-	// Start the audio device running
-	if(Bela_startAudio()) {
-		cout << "Error: unable to start real-time audio" << endl;
-		return -1;
-	}
-
-	// Set up interrupt handler to catch Control-C and SIGTERM
-	signal(SIGINT, interrupt_handler);
-	signal(SIGTERM, interrupt_handler);
-
-	// Run until told to stop
-	while(!gShouldStop) {
-		usleep(100000);
-	}
-
-	// Stop the audio device
-	Bela_stopAudio();
-
-	// Clean up any resources allocated for audio
-	Bela_cleanupAudio();
-
-	// Release sound files
-	if(gMusicBuffer != 0)
-		free(gMusicBuffer);
-	if(gSoundBoomBuffer != 0)
-		free(gSoundBoomBuffer);
-	if(gSoundHitBuffer != 0)
-		free(gSoundHitBuffer);
-	
-	// All done!
-	return 0;
-}
--- a/examples/tank_wars/render.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-/*
- * render.cpp
- *
- *  Created on: Oct 24, 2014
- *      Author: parallels
- */
-
-
-#include <Bela.h>
-#include "game.h"
-#include <rtdk.h>
-#include <cmath>
-#include <cstdlib>
-#include <time.h>
-
-int gAudioFramesPerMatrixFrame = 2; // Ratio in audio to matrix sample rate
-
-int gInputTank1Angle = 0;		// Inputs for the cannon angles
-int gInputTank2Angle = 1;
-int gInputLauncher = 2;			// Input for launcher FSR
-
-int gOutputX = 0;				// Outputs for the scope
-int gOutputY = 1;
-int gOutputPlayer1LED = 2;
-int gOutputPlayer2LED = 3;
-
-int gGameFramesPerSecond = 60;	// How often the physics are updated
-int gGameFrameInterval;			// ...and in frames
-int gSamplesUntilNextFrame;		// Counter until next update
-int gSamplesSinceFinish = 0;	// How long since somebody won?
-bool gGameShouldRestart = false;// Whether we need to reinitiliase the game
-
-// Counter for overall number of samples that have elapsed
-unsigned int gSampleCounter = 0;
-
-// 1st-order filter and peak detector for launcher input
-float gLauncherLastSample = 0;
-float gLauncherFilterPole = 0.8;
-float gLauncherPeakValue = 0;
-float gLauncherPeakFilterPole = 0.999;
-float gLauncherNoiseThreshold = 0.01;
-float gLauncherMinimumPeak = 0.1;
-bool gLauncherTriggered = false;
-
-// Screen update rate; affects buffer size. Actual contents of buffer
-// may be smaller than this
-int gScreenWidth = 512;
-int gScreenHeight = 512;
-int gScreenFramesPerSecond = 25;
-
-// Double buffer for rendering screen. Each is an interleaved buffer
-// of XY data.
-float *gScreenBuffer1, *gScreenBuffer2;
-float *gScreenBufferWrite, *gScreenBufferRead;
-int gScreenBufferMaxLength;				// What is the total buffer allocated?
-int gScreenBufferReadLength;			// How long is the read buffer?
-int gScreenBufferWriteLength;			// How long is the write (next) buffer?
-int gScreenBufferReadPointer;			// Where are we in the read buffer now?
-int gScreenBufferNextUpdateLocation;	// When should we render the next buffer?
-bool gScreenNextBufferReady;			// Is the next buffer ready to go?
-
-// Auxiliary (low-priority) task for updating the screen
-AuxiliaryTask gScreenUpdateTask;
-
-// Buffers for music and sound effects
-extern float *gMusicBuffer;
-extern int gMusicBufferLength;
-extern float *gSoundBoomBuffer;
-extern int gSoundBoomBufferLength;
-extern float *gSoundHitBuffer;
-extern int gSoundHitBufferLength;
-
-// Current state for sound and music
-int gMusicBufferPointer = 0;	  // 0 means start of buffer...
-int gSoundBoomBufferPointer = -1; // -1 means don't play...
-int gSoundHitBufferPointer = -1;
-float gSoundProjectileOscillatorPhase = 0;
-float gSoundProjectileOscillatorGain = 0.2;
-float gOscillatorPhaseScaler = 0;
-
-void screen_update();
-
-// setup() is called once before the audio rendering starts.
-// Use it to perform any initialisation and allocation which is dependent
-// on the period size or sample rate.
-//
-// userData holds an opaque pointer to a data structure that was passed
-// in from the call to initAudio().
-//
-// Return true on success; returning false halts the program.
-
-bool setup(BelaContext *context, void *userData)
-{
-	srandom(time(NULL));
-
-	// Verify we are running with matrix enabled
-	if(context->analogFrames == 0 || context->analogChannels < 4) {
-		rt_printf("Error: this example needs the matrix enabled with at least 4 channels\n");
-		return false;
-	}
-
-	// Initialise audio variables
-	gAudioFramesPerMatrixFrame = context->audioFrames / context->analogFrames;
-	gOscillatorPhaseScaler = 2.0 * M_PI / context->audioSampleRate;
-
-	// Initialise the screen buffers
-	gScreenBufferMaxLength = 2 * context->analogSampleRate / gScreenFramesPerSecond;
-	gScreenBuffer1 = new float[gScreenBufferMaxLength];
-	gScreenBuffer2 = new float[gScreenBufferMaxLength];
-	if(gScreenBuffer1 == 0 || gScreenBuffer2 == 0) {
-		rt_printf("Error initialising screen buffers\n");
-		return false;
-	}
-
-	gScreenBufferRead = gScreenBuffer1;
-	gScreenBufferWrite = gScreenBuffer2;
-	gScreenBufferReadLength = gScreenBufferWriteLength = 0;
-	gScreenBufferReadPointer = 0;
-	gScreenBufferNextUpdateLocation = 0;
-	gScreenNextBufferReady = false;
-
-	// Initialise the game
-	setupGame(gScreenWidth, gScreenHeight);
-	gGameFrameInterval = context->analogSampleRate / gGameFramesPerSecond;
-	gSamplesUntilNextFrame = gGameFrameInterval;
-
-	// Initialise auxiliary tasks
-	if((gScreenUpdateTask = Bela_createAuxiliaryTask(&screen_update, 90,
-														 "bela-screen-update")) == 0)
-		return false;
-
-	return true;
-}
-
-// Swap buffers on the screen
-void swap_buffers()
-{
-	if(gScreenBufferRead == gScreenBuffer1) {
-		gScreenBufferRead = gScreenBuffer2;
-		gScreenBufferWrite = gScreenBuffer1;
-	}
-	else {
-		gScreenBufferRead = gScreenBuffer1;
-		gScreenBufferWrite = gScreenBuffer2;
-	}
-
-	gScreenBufferReadLength = gScreenBufferWriteLength;
-	gScreenBufferReadPointer = 0;
-
-	// Schedule next update for 3/4 of the way through the buffer
-	gScreenBufferNextUpdateLocation = gScreenBufferReadLength * 0.75;
-	gScreenNextBufferReady = false;
-}
-
-// render() is called regularly at the highest priority by the audio engine.
-// Input and output are given from the audio hardware and the other
-// ADCs and DACs (if available). If only audio is available, numMatrixFrames
-// will be 0.
-
-void render(BelaContext *context, void *userData)
-{
-	int audioIndex = 0;
-
-	for(unsigned int n = 0; n < context->analogFrames; n++) {
-		for(int k = 0; k < gAudioFramesPerMatrixFrame; k++) {
-			// Render music and sound
-			float audioSample = 0;
-
-			// Music plays in a loop
-			if(gMusicBuffer != 0 && gMusicBufferPointer >= 0) {
-				audioSample += gMusicBuffer[gMusicBufferPointer++];
-				if(gMusicBufferPointer >= gMusicBufferLength)
-					gMusicBufferPointer = 0;
-			}
-
-			// Sound effect plays until finished, then stops
-			if(gSoundBoomBuffer != 0 && gSoundBoomBufferPointer >= 0) {
-				audioSample += gSoundBoomBuffer[gSoundBoomBufferPointer++];
-				if(gSoundBoomBufferPointer >= gSoundBoomBufferLength)
-					gSoundBoomBufferPointer = -1;
-			}
-
-			if(gSoundHitBuffer != 0 && gSoundHitBufferPointer >= 0) {
-				audioSample += gSoundHitBuffer[gSoundHitBufferPointer++];
-				if(gSoundHitBufferPointer >= gSoundHitBufferLength)
-					gSoundHitBufferPointer = -1;
-			}
-
-			// Oscillator plays to indicate projectile height
-			if(gameStatusProjectileInMotion()) {
-				audioSample += gSoundProjectileOscillatorGain * sinf(gSoundProjectileOscillatorPhase);
-
-				gSoundProjectileOscillatorPhase += gOscillatorPhaseScaler * constrain(map(gameStatusProjectileHeight(),
-						1.0, 0, 300, 2000), 200, 6000);
-				if(gSoundProjectileOscillatorPhase > 2.0 * M_PI)
-					gSoundProjectileOscillatorPhase -= 2.0 * M_PI;
-			}
-
-			context->audioOut[2*audioIndex] = context->audioOut[2*audioIndex + 1] = audioSample;
-			audioIndex++;
-		}
-
-		// First-order lowpass filter to remove noise on launch FSR
-		float rawSample = analogRead(context, n, gInputLauncher);
-		float launchSample = gLauncherFilterPole * gLauncherLastSample +
-							(1.0f - gLauncherFilterPole) * rawSample;
-		gLauncherLastSample = launchSample;
-
-		// Peak-detect on launch signal
-		if(launchSample >= gLauncherPeakValue) {
-			gLauncherPeakValue = launchSample;
-			gLauncherTriggered = false;
-		}
-		else {
-			if(gLauncherPeakValue - launchSample > gLauncherNoiseThreshold && !gLauncherTriggered) {
-				// Detected a peak; is it big enough overall?
-				if(gLauncherPeakValue >= gLauncherMinimumPeak) {
-					gLauncherTriggered = true;
-					// Peak detected-- fire!!
-					// Set both cannon strengths but only one will
-					// fire depending on whose turn it is
-					float strength = map(gLauncherPeakValue,
-									     gLauncherMinimumPeak, 1.0,
-										 0.5f, 10.0f);
-					setTank1CannonStrength(strength);
-					setTank2CannonStrength(strength);
-					fireProjectile();
-				}
-			}
-
-			gLauncherPeakValue *= gLauncherPeakFilterPole;
-		}
-
-		if(--gSamplesUntilNextFrame <= 0) {
-			// Update game physics and cannon angles
-			gSamplesUntilNextFrame = gGameFrameInterval;
-
-			setTank1CannonAngle(map(analogRead(context, n, gInputTank1Angle),
-									0, 1.0, M_PI, 0));
-			setTank2CannonAngle(map(analogRead(context, n, gInputTank2Angle),
-									0, 1.0, M_PI, 0));
-			nextGameFrame();
-
-			// Check for collision and start sound accordingly
-			if(gameStatusCollisionOccurred()) {
-				gSoundBoomBufferPointer = 0;
-			}
-			
-			if(gameStatusTankHitOccurred()) {
-				gSoundHitBufferPointer = 0;
-			}
-		}
-
-		if(gScreenBufferReadPointer >= gScreenBufferReadLength - 1
-			&& gScreenNextBufferReady) {
-			// Got to the end; swap buffers
-			swap_buffers();
-		}
-
-		// Push current screen buffer to the matrix output
-		if(gScreenBufferReadPointer < gScreenBufferReadLength - 1) {
-			float x = gScreenBufferRead[gScreenBufferReadPointer++];
-			float y = gScreenBufferRead[gScreenBufferReadPointer++];
-
-			// Rescale screen coordinates to matrix ranges; invert the Y
-			// coordinate to go from normal screen coordinates to scope coordinates
-			analogWriteOnce(context, n, gOutputX, constrain(map(x, 0, gScreenWidth, 0, 1.0), 0, 1.0));
-			analogWriteOnce(context, n, gOutputY, constrain(map(y, 0, gScreenHeight, 1.0, 0), 0, 1.0));
-		}
-		else {
-			// Still not ready! Write 0 until something happens
-			analogWriteOnce(context, n, gOutputX, 0);
-			analogWriteOnce(context, n, gOutputY, 0);
-		}
-
-		if(gameStatusWinner() != 0) {
-			// Blink one LED to show who won
-			// Blink both LEDs when projectile is in motion
-			float val = (gSampleCounter % 4000 > 2000) ? 1.0 : 0;
-			analogWriteOnce(context, n, gOutputPlayer1LED, gameStatusWinner() == 1 ? val : 0);
-			analogWriteOnce(context, n, gOutputPlayer2LED, gameStatusWinner() == 2 ? val : 0);
-
-			// After 5 seconds, restart the game
-			gSamplesSinceFinish++;
-			if(gSamplesSinceFinish > 22050*5)
-				gGameShouldRestart = true;
-		}
-		else if(gameStatusProjectileInMotion()) {
-			// Blink both LEDs when projectile is in motion
-			float val = (gSampleCounter % 2000 > 1000) ? 1.0 : 0;
-			analogWriteOnce(context, n, gOutputPlayer1LED, val);
-			analogWriteOnce(context, n, gOutputPlayer2LED, val);
-		}
-		else if(gameStatusPlayer1Turn()) {
-			analogWriteOnce(context, n, gOutputPlayer1LED, 1.0);
-			analogWriteOnce(context, n, gOutputPlayer2LED, 0);
-		}
-		else {
-			analogWriteOnce(context, n, gOutputPlayer2LED, 1.0);
-			analogWriteOnce(context, n, gOutputPlayer1LED, 0);
-		}
-
-		// Check if we have reached the point where we should next update
-		if(gScreenBufferReadPointer >= gScreenBufferNextUpdateLocation &&
-		   !gScreenNextBufferReady) {
-			// Update the screen at lower priority than the audio thread
-			Bela_scheduleAuxiliaryTask(gScreenUpdateTask);
-		}
-
-		gSampleCounter++;
-	}
-}
-
-void screen_update()
-{
-	// If we should restart, reinitialise the game
-	if(gGameShouldRestart) {
-		restartGame();
-		gGameShouldRestart = false;
-		gSamplesSinceFinish = 0;
-	}
-
-	// Render the game based on the current state
-	gScreenBufferWriteLength = drawGame(gScreenBufferWrite, gScreenBufferMaxLength);
-
-	// Flag it as ready to go
-	gScreenNextBufferReady = true;
-}
-
-// cleanup() is called once at the end, after the audio has stopped.
-// Release any resources that were allocated in setup().
-
-void cleanup(BelaContext *context, void *userData)
-{
-	// Clean up the game state
-	cleanupGame();
-}
--- a/examples/tank_wars/vector_graphics.cpp	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * vector_graphics.cpp
- *
- *  Created on: Nov 10, 2014
- *      Author: parallels
- */
-
-#include <cmath>
-
-// Draw a line between two points at a specified rate in
-// pixels per buffer sample. Indicate maximum available space.
-// Returns space used
-int renderLine(float x1, float y1, float x2, float y2, float speed,
-			   float *buffer, int maxLength) {
-	// Figure out length of line and therefore how many samples
-	// are needed to represent it based on the speed (rounded to nearest int)
-	float totalLineLength = sqrtf((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));
-	int samplesNeeded = floorf(totalLineLength / speed + 0.5);
-
-	// Now render into the buffer
-	int length = 0;
-	float scaleFactor = 1.0f / samplesNeeded;
-	for(int n = 0; n < samplesNeeded; n++) {
-		if(length >= maxLength - 1)
-			return length;
-		// X coordinate
-		*buffer++ = x1 + (float)n * scaleFactor * (x2 - x1);
-		// Y coordinate
-		*buffer++ = y1 + (float)n * scaleFactor * (y2 - y1);
-		length += 2;
-	}
-
-	return length;
-}
-
-// Draw an arc around a centre point at a specified rate of pixels
-// per buffer sample. Indicate maximum available space.
-// Returns space used
-int renderArc(float x, float y, float radius, float thetaMin, float thetaMax,
-			  float speed, float *buffer, int maxLength) {
-	// Figure out circumference of arc and therefore how many samples
-	// are needed to represent it based on the speed (rounded to nearest int)
-	float circumference = (thetaMax - thetaMin) * radius;
-	int samplesNeeded = floorf(circumference / speed + 0.5);
-
-	// Now render into the buffer
-	int length = 0;
-	float scaleFactor = 1.0f / samplesNeeded;
-	for(int n = 0; n < samplesNeeded; n++) {
-		if(length >= maxLength - 1)
-			return length;
-		// Get current angle
-		float theta = thetaMin + (float)n * scaleFactor * (thetaMax - thetaMin);
-
-		// Convert polar to cartesian coordinates
-		*buffer++ = x + radius * cosf(theta);
-		*buffer++ = y + radius * sinf(theta);
-
-		length += 2;
-	}
-
-	return length;
-}
-
-// Draw a single point for a specified number of frames
-void renderPoint(float x, float y, float *buffer, float length) {
-	while(length > 0) {
-		*buffer++ = x;
-		*buffer++ = y;
-		length--;
-	}
-}
--- a/examples/tank_wars/vector_graphics.h	Mon Jun 20 16:57:35 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-/*
- * vector_graphics.h
- *
- *  Created on: Nov 10, 2014
- *      Author: parallels
- */
-
-#ifndef VECTOR_GRAPHICS_H_
-#define VECTOR_GRAPHICS_H_
-
-int renderLine(float x1, float y1, float x2, float y2, float speed,
-			   float *buffer, int maxLength);
-int renderArc(float x, float y, float radius, float thetaMin, float thetaMax,
-			  float speed, float *buffer, int maxLength);
-void renderPoint(float x, float y, float *buffer, float length);
-
-
-#endif /* VECTOR_GRAPHICS_H_ */