changeset 50:be427da6fb9c newapi

Removed old testing code that stopped audio after 10 seconds; command line parameter updates; D-Box updates (not fully working yet)
author andrewm
date Sat, 30 May 2015 12:34:32 -0500
parents bb40e7e06b8c
children 4f8db16f17b5
files .cproject core/PRU.cpp core/RTAudio.cpp core/RTAudioCommandLine.cpp projects/d-box/FeedbackOscillator.cpp projects/d-box/FeedbackOscillator.h projects/d-box/main.cpp projects/d-box/render.cpp
diffstat 8 files changed, 159 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/.cproject	Thu May 28 17:48:42 2015 -0400
+++ b/.cproject	Sat May 30 12:34:32 2015 -0500
@@ -92,7 +92,7 @@
 					<sourceEntries>
 						<entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/>
-						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/d-box"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
@@ -167,6 +167,7 @@
 								<option id="gnu.cpp.link.option.flags.1308374111" name="Linker flags" superClass="gnu.cpp.link.option.flags" value="-pthread -Wpointer-arith" valueType="string"/>
 								<option id="gnu.cpp.link.option.userobjs.1473502069" name="Other objects" superClass="gnu.cpp.link.option.userobjs" valueType="userObjs">
 									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/libprussdrv.a}&quot;"/>
+									<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/libNE10.a}&quot;"/>
 								</option>
 								<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1607203279" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
 									<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
@@ -181,7 +182,7 @@
 					<sourceEntries>
 						<entry excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
 						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="include"/>
-						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/basic"/>
+						<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects/d-box"/>
 						<entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="source"/>
 					</sourceEntries>
 				</configuration>
--- a/core/PRU.cpp	Thu May 28 17:48:42 2015 -0400
+++ b/core/PRU.cpp	Sat May 30 12:34:32 2015 -0500
@@ -420,10 +420,13 @@
 // Main loop to read and write data from/to PRU
 void PRU::loop(RT_INTR *pru_interrupt, void *userData)
 {
+#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS
+	RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024;	// Timeout for PRU interrupt: about 10ms, much longer than any expected period
+#else
 	// Polling interval is 1/4 of the period
-	//RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4;
+	RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (context->analogChannels / 2) * context->analogFrames / 4;
+#endif
 
-	RTIME irqTimeout = PRU_SAMPLE_INTERVAL_NS * 1024;	// Timeout for PRU interrupt: about 10ms, much longer than any expected period
 	float *lastAnalogOutFrame;
 	uint32_t *digitalBuffer0, *digitalBuffer1, *lastDigitalBuffer;
 	uint32_t pru_audio_offset, pru_spi_offset;
@@ -468,10 +471,16 @@
 	}
 
 	// TESTING
-	uint32_t testCount = 0;
+	// uint32_t testCount = 0;
 	// RTIME startTime = rt_timer_read();
 
+#ifndef BEAGLERT_USE_XENOMAI_INTERRUPTS
+	// Which buffer the PRU was last processing
+	uint32_t lastPRUBuffer = 0;
+#endif
+
 	while(!gShouldStop) {
+#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS
 		// Wait for PRU to move to change buffers;
 		// PRU will send an interrupts which we wait for
 		rt_intr_enable(pru_interrupt);
@@ -489,6 +498,14 @@
 
 		// Clear pending PRU interrupt
 		prussdrv_pru_clear_event(PRU_EVTOUT_1, PRU1_ARM_INTERRUPT);
+#else
+		// Poll
+		while(pru_buffer_comm[PRU_CURRENT_BUFFER] == lastPRUBuffer && !gShouldStop) {
+			rt_task_sleep(sleepTime);
+		}
+
+		lastPRUBuffer = pru_buffer_comm[PRU_CURRENT_BUFFER];
+#endif
 
 		if(gShouldStop)
 			break;
@@ -512,7 +529,7 @@
 
 		// FIXME: some sort of margin is needed here to prevent the audio
 		// code from completely eating the Linux system
-		testCount++;
+		// testCount++;
 		//rt_task_sleep(sleepTime*4);
 		//rt_task_sleep(sleepTime/4);
 
@@ -605,12 +622,14 @@
 		}
 
 		// FIXME: TESTING!!
-		if(testCount > 100000)
-			break;
+		// if(testCount > 100000)
+		//	break;
 	}
 
+#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS
 	// Turn off the interrupt for the PRU if it isn't already off
 	rt_intr_disable(pru_interrupt);
+#endif
 
 	// FIXME: TESTING
 	// RTIME endTime = rt_timer_read();
--- a/core/RTAudio.cpp	Thu May 28 17:48:42 2015 -0400
+++ b/core/RTAudio.cpp	Sat May 30 12:34:32 2015 -0500
@@ -52,7 +52,9 @@
 
 // Real-time tasks and objects
 RT_TASK gRTAudioThread;
+#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS
 RT_INTR gRTAudioInterrupt;
+#endif
 PRU *gPRU = 0;
 I2c_Codec *gAudioCodec = 0;
 
@@ -257,8 +259,11 @@
 				}
 			}
 
+#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS
 			gPRU->loop(&gRTAudioInterrupt, gUserData);
-
+#else
+			gPRU->loop(0, gUserData);
+#endif
 			// Now clean up
 			// gPRU->waitForFinish();
 			gPRU->disable();
@@ -341,12 +346,14 @@
 		  return -1;
 	}
 
+#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS
 	// Create an interrupt which the audio thread receives from the PRU
 	int result = 0;
 	if((result = rt_intr_create(&gRTAudioInterrupt, gRTAudioInterruptName, PRU_RTAUDIO_IRQ, I_NOAUTOENA)) != 0) {
 		cout << "Error: unable to create Xenomai interrupt for PRU (error " << result << ")" << endl;
 		return -1;
 	}
+#endif
 
 	// Start all RT threads
 	if(rt_task_start(&gRTAudioThread, &audioLoop, 0)) {
@@ -413,7 +420,9 @@
 	gAuxTasks.clear();
 
 	// Delete the audio task and its interrupt
+#ifdef BEAGLERT_USE_XENOMAI_INTERRUPTS
 	rt_intr_delete(&gRTAudioInterrupt);
+#endif
 	rt_task_delete(&gRTAudioThread);
 
 	if(gPRU != 0)
--- a/core/RTAudioCommandLine.cpp	Thu May 28 17:48:42 2015 -0400
+++ b/core/RTAudioCommandLine.cpp	Sat May 30 12:34:32 2015 -0500
@@ -24,22 +24,22 @@
 {
 	{"period", 1, NULL, 'p'},
 	{"verbose", 0, NULL, 'v'},
-	{"use-analog", 1, NULL, 'm'},
-	{"use-digital-gpio", 1, NULL, 'g'},
+	{"use-analog", 1, NULL, 'N'},
+	{"use-digital", 1, NULL, 'G'},
 	{"analog-channels", 1, NULL, 'C'},
-	{"digital-channels", 1, NULL, 'G'},
+	{"digital-channels", 1, NULL, 'B'},
 	{"mute-speaker", 1, NULL, 'M'},
 	{"dac-level", 1, NULL, 'D'},
 	{"adc-level", 1, NULL, 'A'},
 	{"hp-level", 1, NULL, 'H'},
-	{"receive-port", 1, NULL, 'r'},
-	{"transmit-port", 1, NULL, 't'},
-	{"server-name", 1, NULL, 's'},
+	{"receive-port", 1, NULL, 'R'},
+	{"transmit-port", 1, NULL, 'T'},
+	{"server-name", 1, NULL, 'S'},
 	{"pru-file", 1, NULL, OPT_PRU_FILE},
 	{NULL, 0, NULL, 0}
 };
 
-const char gDefaultShortOptions[] = "p:vm:M:C:D:A:H:g:G:r:t:s:";
+const char gDefaultShortOptions[] = "p:vN:M:C:D:A:H:G:B:R:T:S:";
 
 // This function sets the default settings for the BeagleRTInitSettings structure
 void BeagleRT_defaultSettings(BeagleRTInitSettings *settings)
@@ -150,10 +150,10 @@
 		case 'v':
 			settings->verbose = 1;
 			break;
-		case 'm':
+		case 'N':
 			settings->useAnalog = atoi(optarg);
 			break;
-		case 'g':
+		case 'G':
 			settings->useDigital = atoi(optarg);
 			settings->numDigitalChannels = 0;
 			break;
@@ -166,7 +166,7 @@
 			else
 				settings->numAnalogChannels = 2;
 			break;
-		case 'G':
+		case 'B':
 			settings->numDigitalChannels = atoi(optarg);
 			if(settings->numDigitalChannels >= 16)
 				settings->numDigitalChannels = 16;
@@ -188,13 +188,13 @@
 		case 'H':
 			settings->headphoneLevel = atof(optarg);
 			break;
-		case 'r':
+		case 'R':
 			settings->receivePort = atoi(optarg);
 			break;
-		case 't':
+		case 'T':
 			settings->transmitPort = atoi(optarg);
 			break;
-		case 's':
+		case 'S':
 			if(strlen(optarg)<MAX_SERVERNAME_LENGTH)
 				strcpy(settings->serverName, optarg);
 			else
--- a/projects/d-box/FeedbackOscillator.cpp	Thu May 28 17:48:42 2015 -0400
+++ b/projects/d-box/FeedbackOscillator.cpp	Sat May 30 12:34:32 2015 -0500
@@ -58,23 +58,11 @@
 
 // Process one sample and store the output value
 // Returns true if the wavetable needs rendering
-int FeedbackOscillator::process(uint16_t input, uint16_t *output) {
-	float inFloat = input / 65536.0;
-	float outFloat = coeffs[COEFF_B0] * inFloat + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput;
+int FeedbackOscillator::process(float input, float *output) {
+	float outFloat = coeffs[COEFF_B0] * input + coeffs[COEFF_B1] * lastInput - coeffs[COEFF_A1] * lastOutput;
 	int requestRenderLength = 0;
 
-	//outFloat *= 2.0;
-
-	int intOut = outFloat * 65536.0 + 32768;
-	if(intOut > 65535)
-		intOut = 65535;
-	if(intOut < 0)
-		intOut = 0;
-	//intOut = (intOut & 0xFF) << 8;
-	//if(intOut > 65535)
-	//	intOut = 65535;
-
-	*output = (uint16_t)intOut;
+	*output = outFloat;
 
 	if(canTrigger && outFloat > 0 && lastOutput <= 0) {
 		triggered = true;
@@ -106,7 +94,7 @@
 	sampleCount++;
 
 	lastOutput = outFloat;
-	lastInput = inFloat;
+	lastInput = input;
 
 	return requestRenderLength;
 }
--- a/projects/d-box/FeedbackOscillator.h	Thu May 28 17:48:42 2015 -0400
+++ b/projects/d-box/FeedbackOscillator.h	Sat May 30 12:34:32 2015 -0500
@@ -8,8 +8,6 @@
 #ifndef FEEDBACKOSCILLATOR_H
 #define FEEDBACKOSCILLATOR_H
 
-#include <stdint.h>
-
 class FeedbackOscillator
 {
 public:
@@ -21,7 +19,7 @@
 
 	// Process one sample and store the output value
 	// Returns the length of table to interpolate; or 0 if nothing to process further
-	int process(uint16_t input, uint16_t *output);
+	int process(float input, float *output);
 
 	float *wavetable() { return wavetableRead; }
 
--- a/projects/d-box/main.cpp	Thu May 28 17:48:42 2015 -0400
+++ b/projects/d-box/main.cpp	Sat May 30 12:34:32 2015 -0500
@@ -33,7 +33,7 @@
 // get_opt_long
 #include <getopt.h>
 
-#include "../../include/RTAudio.h"
+#include "../../include/BeagleRT.h"
 #include "config.h"
 #include "sensors.h"
 #include "OscillatorBank.h"
@@ -262,11 +262,13 @@
 }
 
 
-void parseArguments(arg_data args, RTAudioSettings *settings)
+void parseArguments(arg_data args, BeagleRTInitSettings *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[] =
 	{
@@ -274,10 +276,10 @@
 		{"audioin", 1, NULL, 'i'},
 		{"file", 1, NULL, 'f'},
 		{"keyboard", 1, NULL, 'k'},
-		{"audio-test", 0, NULL, 'T'},
-		{"sensor-type", 1, NULL, 'S'},
-		{"sensor0", 1, NULL, 'Q'},
-		{"sensor1", 1, NULL, 'R'},
+		{"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'},
@@ -293,7 +295,7 @@
 	while (1)
 	{
 		int c;
-		if ((c = BeagleRT_getopt_long(args.argc, args.argv, "hf:ki:sTQ:R:S:l:u:o:n:g:", long_option, settings)) < 0)
+		if ((c = BeagleRT_getopt_long(args.argc, args.argv, "hf:ki:sq:r:t:l:u:o:n:g:", long_option, settings)) < 0)
 				break;
 		switch (c)
 		{
@@ -313,16 +315,16 @@
 		case 's':
 				forceSensors = true;
 				break;
-		case 'T':
+		case kOptionAudioTest:
 				useAudioTest = true;
 				break;
-		case 'S':
+		case 't':
 				sensorType = atoi(optarg);
 				break;
-		case 'Q':
+		case 'q':
 				touchSensor0Address = atoi(optarg);
 				break;
-		case 'R':
+		case 'r':
 				touchSensor1Address = atoi(optarg);
 				break;
 		case 'l':
@@ -361,7 +363,7 @@
 
 int main(int argc, char *argv[])
 {
-	RTAudioSettings settings;	// Standard audio settings
+	BeagleRTInitSettings settings;	// Standard audio settings
 	RT_TASK rtSensorThread;
 	const char rtSensorThreadName[] = "dbox-sensor";
 	int oscBankHopSize;
@@ -371,7 +373,7 @@
 	args.argv = argv;
 	parseArguments(args, &settings);
 
-	setVerboseLevel(gVerbose);
+	BeagleRT_setVerboseLevel(gVerbose);
 	if(gVerbose == 1 && useAudioTest)
 		cout << "main() : running in audio test mode" << endl;
 
@@ -415,7 +417,7 @@
 		if(gVerbose==1)
 			cout << "main() : creating control thread" << endl;
 
-		if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, 95, T_JOINABLE | T_FPU)) {
+		if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, BEAGLERT_AUDIO_PRIORITY - 5, T_JOINABLE | T_FPU)) {
 			  cout << "Error:unable to create Xenomai control thread" << endl;
 			  return -1;
 		}
--- a/projects/d-box/render.cpp	Thu May 28 17:48:42 2015 -0400
+++ b/projects/d-box/render.cpp	Sat May 30 12:34:32 2015 -0500
@@ -5,7 +5,7 @@
  *      Author: Victor Zappi
  */
 
-#include "../../include/RTAudio.h"
+#include "../../include/BeagleRT.h"
 #include "../../include/PRU.h"
 #include "StatusLED.h"
 #include "config.h"
@@ -39,7 +39,6 @@
 #define ADC_PIN6	6
 #define ADC_PIN7	7
 
-
 #define N_OCT		4.0	// maximum number of octaves on sensor 1
 
 extern vector<OscillatorBank*> gOscBanks;
@@ -49,7 +48,6 @@
 extern StatusLED gStatusLED;
 extern bool gIsLoading;
 extern bool gAudioIn;
-extern int gPeriodSize;
 
 float *gOscillatorBuffer1, *gOscillatorBuffer2;
 float *gOscillatorBufferRead, *gOscillatorBufferWrite;
@@ -78,7 +76,7 @@
 // sensor 0.
 extern float gSensor0LatestTouchPos;
 extern int gSensor0LatestTouchNum;
-uint16_t gPitchLatestInput = 0;
+float gPitchLatestInput = 0;
 
 extern float gSensor1LatestTouchPos[];
 //extern float gSensor1LatestTouchSizes[];
@@ -94,9 +92,9 @@
 
 // Loop points from matrix input 4
 const int gLoopPointsInputBufferSize	= 256;
-uint16_t gLoopPointsInputBuffer[gLoopPointsInputBufferSize];
+float gLoopPointsInputBuffer[gLoopPointsInputBufferSize];
 int gLoopPointsInputBufferPointer		= 0;
-int gLoopPointMin = 0, gLoopPointMax	= 0;
+float gLoopPointMin = 0, gLoopPointMax	= 0;
 
 // multiplier to activate or mute audio in
 int audioInStatus = 0;
@@ -106,7 +104,7 @@
 
 // pitch vars
 float octaveSplitter;
-u_int16_t semitones[((int)N_OCT*12)+1];
+float semitones[((int)N_OCT*12)+1];
 float deltaTouch	= 0;
 float deltaWeightP	= 0.5;
 float deltaWeightI	= 0.0005;
@@ -143,22 +141,21 @@
                               float *tableIn, float *tableOut,
                               float *sineTable, float sineMix);
 
-inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold,
-									uint16_t fallingThreshold, bool *rising);
+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 initialise_render(int numMatrixChannels, int numAudioChannels,
-					   int numMatrixFramesPerPeriod,
-					   int numAudioFramesPerPeriod,
-					   float matrixSampleRate, float audioSampleRate,
-					   void *userData) {
+bool initialise_render(BeagleRTContext *context, void *userData) {
 	int oscBankHopSize = *(int *)userData;
 
-	if(numMatrixChannels != 8) {
+	if(context->analogChannels != 8) {
 		printf("Error: D-Box needs matrix enabled with 8 channels.\n");
 		return false;
 	}
@@ -166,19 +163,19 @@
 	// 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 * gNumAudioChannels * sizeof(float))) {
+	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 * gNumAudioChannels * sizeof(float))) {
+	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 * gNumAudioChannels * sizeof(float));
-	memset(gOscillatorBuffer2, 0, oscBankHopSize * gNumAudioChannels * sizeof(float));
+	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
@@ -189,18 +186,18 @@
 		return false;
 	}
 
-	gFeedbackOscillator.initialise(8192, 10.0, matrixSampleRate);
+	gFeedbackOscillator.initialise(8192, 10.0, context->analogSampleRate);
 
 	for(int n = 0; n < gDynamicWavetableLength + 1; n++)
 		gDynamicWavetable[n] = 0;
 
 	// pitch
-	float midPos		= (float)65535/2.0;
-	octaveSplitter		= round((float)65535/(N_OCT));
+	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 			= (float)65535/(N_OCT*12.0);
+	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;
@@ -212,7 +209,7 @@
 		audioInStatus = 1;
 
 	// filter
-	blockSize		= 2*gPeriodSize;
+	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));
@@ -223,24 +220,23 @@
 	ne10_fir_init_float(&filter[1], FILTER_TAP_NUM, filterTaps, filterState[1], blockSize);
 
 	// peak outputs
-	PeakBurst[0].setAttackRate(.00001 * matrixSampleRate);
-	PeakBurst[1].setAttackRate(.00001 * matrixSampleRate);
-	PeakBurst[0].setDecayRate(.5 * matrixSampleRate);
-	PeakBurst[1].setDecayRate(.5 * matrixSampleRate);
+	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 = createAuxiliaryTaskLoop(&render_medium_prio, 90, "dbox-calculation-medium")) == 0)
+	if((gMediumPriorityRender = BeagleRT_createAuxiliaryTask(&render_medium_prio, BEAGLERT_AUDIO_PRIORITY - 10, "dbox-calculation-medium")) == 0)
 		return false;
-	if((gLowPriorityRender = createAuxiliaryTaskLoop(&render_low_prio, 85, "dbox-calculation-low")) == 0)
+	if((gLowPriorityRender = BeagleRT_createAuxiliaryTask(&render_low_prio, BEAGLERT_AUDIO_PRIORITY - 15, "dbox-calculation-low")) == 0)
 		return false;
 
 	return true;
 }
 
-void render(int numMatrixFrames, int numAudioFrames, float *audioIn, float *audioOut,
-			uint16_t *matrixIn, uint16_t *matrixOut)
+void render(BeagleRTContext *context, void *userData)
 {
 #ifdef DBOX_CAPE_TEST
 	render_capetest(numMatrixFrames, numAudioFrames, audioIn, audioOut, matrixIn, matrixOut);
@@ -250,10 +246,10 @@
 
 	if(gOscBanks[gCurrentOscBank]->state==bank_playing)
 	{
-		assert(gNumAudioChannels == 2);
+		assert(context->audioChannels == 2);
 
 #ifdef OLD_OSCBANK
-		memset(audioOut, 0, numAudioFrames * gNumAudioChannels * sizeof(float));
+		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
@@ -290,18 +286,18 @@
 									 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
 									 gDynamicWavetable/*gOscBanks[gCurrentOscBank]->lookupTable*/);
 				framesRemaining -= gOscBanks[gCurrentOscBank]->hopCounter;
-				audioOutWithOffset += gNumAudioChannels * gOscBanks[gCurrentOscBank]->hopCounter;
+				audioOutWithOffset +=  * gOscBanks[gCurrentOscBank]->hopCounter;
 				gOscBanks[gCurrentOscBank]->sampleCount += gOscBanks[gCurrentOscBank]->hopCounter;
 				gOscBanks[gCurrentOscBank]->nextHop();
 			}
 		}
 #else
-		for(int n = 0; n < numAudioFrames; n++) {
-			audioOut[2*n] 	  = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n]*audioInStatus;
-			audioOut[2*n + 1] = gOscillatorBufferRead[gOscillatorBufferReadPointer++]+audioIn[2*n+1]*audioInStatus;
+		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(audioIn[2*n]);	// rectify for peak detection in 1
-			filterIn[1][n] = fabs(audioIn[2*n+1]);	// rectify for peak detection in 2
+			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? */
 			/*
@@ -326,19 +322,19 @@
 				gOscillatorBufferReadPointer = 0;
 
 				gOscillatorNeedsRender = true;
-				scheduleAuxiliaryTask(gMediumPriorityRender);
+				BeagleRT_scheduleAuxiliaryTask(gMediumPriorityRender);
 			}
 		}
 #endif
 	}
 	else
 	{
-		for(int n = 0; n < numAudioFrames; n++) {
-			audioOut[2*n] 	  = audioIn[2*n]*audioInStatus;
-			audioOut[2*n + 1] = audioIn[2*n+1]*audioInStatus;
+		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(audioIn[2*n]);	// rectify for peak detection in 1
-			filterIn[1][n] = fabs(audioIn[2*n+1]);	// rectify for peak detection in 2
+			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
 		}
 	}
 
@@ -346,7 +342,7 @@
 	ne10_fir_float_neon(&filter[0], filterIn[0], filterOut[0], blockSize);
 	ne10_fir_float_neon(&filter[1], filterIn[1], filterOut[1], blockSize);
 
-	for(int n = 0; n < numMatrixFrames; n++) {
+	for(unsigned int n = 0; n < context->analogFrames; n++) {
 
 
 		/* Matrix Out 0, In 0
@@ -354,12 +350,12 @@
 		 * CV loop
 		 * Controls pitch of sound
 		 */
-		int touchPosInt = gSensor0LatestTouchPos * 65536.0;
+		float touchPosInt = gSensor0LatestTouchPos;
 		if(touchPosInt < 0) touchPosInt = 0;
-		if(touchPosInt > 65535) touchPosInt = 65535;
-		matrixOut[n*8 + DAC_PIN0] = touchPosInt;
+		if(touchPosInt > 1.0) touchPosInt = 1.0;
+		context->analogOut[n*8 + DAC_PIN0] = touchPosInt;
 
-		gPitchLatestInput = matrixIn[n*8 + ADC_PIN0];
+		gPitchLatestInput = context->analogIn[n*8 + ADC_PIN0];
 
 
 		/* Matrix Out 7
@@ -372,17 +368,17 @@
 		if(gSensor0LatestTouchNum>0)
 		{
 			// current pitch is gPitchLatestInput, already retrieved
-			semitoneIndex	= (  ( (float)gPitchLatestInput / 65535)*12*N_OCT  )+0.5;	// closest semitone
+			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;
 
-		int nextOut = touchPosInt  + deltaTarget*deltaWeightP + deltaTouch;			// add feedback to touch -> next out
+		float nextOut = touchPosInt  + deltaTarget*deltaWeightP + deltaTouch;			// add feedback to touch -> next out
 		if(nextOut < 0) nextOut = 0;												// clamp
-		if(nextOut > 65535) nextOut = 65535;										// clamp
-		matrixOut[n*8 + DAC_PIN7] = nextOut;										// send next nextOut
+		if(nextOut > 1.0) nextOut = 1.0;										// clamp
+		context->analogOut[n*8 + DAC_PIN7] = nextOut;										// send next nextOut
 
 
 		/*
@@ -392,7 +388,8 @@
 		 * Controls speed of playback
 		 */
 		bool wasRising = gSpeedHysteresisOscillatorRising;
-		matrixOut[n*8 + DAC_PIN1] = hysteresis_oscillator(matrixIn[n*8 + ADC_PIN1], 48000, 16000, &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) {
@@ -415,12 +412,12 @@
 		 * Controls wavetable used for oscillator bank
 		 */
 
-		int tableLength = gFeedbackOscillator.process(matrixIn[n*8 + ADC_PIN2], &matrixOut[n*8 + DAC_PIN2]);
+		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;
-			scheduleAuxiliaryTask(gLowPriorityRender);
+			BeagleRT_scheduleAuxiliaryTask(gLowPriorityRender);
 		}
 
 		/*
@@ -432,10 +429,10 @@
 		 */
 		volatile int touchCount = gSensor1LatestTouchCount;
 		if(touchCount == 0)
-			matrixOut[n*8 + DAC_PIN3] = 0;
+			context->analogOut[n*8 + DAC_PIN3] = 0;
 		else {
 			int touchIndex = (gMatrixSampleCount >> 5) % touchCount;
-			matrixOut[n*8 + DAC_PIN3] = gSensor1LatestTouchPos[touchIndex] * 56000.0f;
+			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
@@ -443,33 +440,33 @@
 				// let's say 24 samples into it.
 
 				// FIXME this won't work for p > 2
-				gSensor1InputDelayCounter = 24 + 2*numMatrixFrames;
+				gSensor1InputDelayCounter = 24 + 2*context->analogFrames;
 				gSensor1InputIndex = touchIndex;
 			}
 			gSensor1LastTouchIndex = touchIndex;
 		}
 
 		if(gSensor1InputDelayCounter-- >= 0 && touchCount > 0) {
-			gSensor1MatrixTouchPos[gSensor1InputIndex] = (float)matrixIn[n*8 + ADC_PIN3] / 65536.0f;
+			gSensor1MatrixTouchPos[gSensor1InputIndex] = context->analogIn[n*8 + ADC_PIN3];
 		}
 
 		/* Matrix Out 4
 		 *
 		 * Sensor 1 last pos
 		 */
-		touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex] * 65536.0;
+		touchPosInt = gSensor1LatestTouchPos[gSensor1LatestTouchIndex];
 		if(touchPosInt < 0) touchPosInt = 0;
-		if(touchPosInt > 65535) touchPosInt = 65535;
-		matrixOut[n*8 + DAC_PIN4] = touchPosInt;
+		if(touchPosInt > 1.0) touchPosInt = 1.0;
+		context->analogOut[n*8 + DAC_PIN4] = touchPosInt;
 
 		/* Matrix In 4
 		 *
 		 * Loop points selector
 		 */
-		gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = matrixIn[n*8 + ADC_PIN4];
+		gLoopPointsInputBuffer[gLoopPointsInputBufferPointer++] = context->analogIn[n*8 + ADC_PIN4];
 		if(gLoopPointsInputBufferPointer >= gLoopPointsInputBufferSize) {
 			// Find min and max values
-			uint16_t loopMax = 0, loopMin = 65535;
+			float loopMax = 0, loopMin = 1.0;
 			for(int i = 0; i < gLoopPointsInputBufferSize; i++) {
 				if(gLoopPointsInputBuffer[i] < loopMin)
 					loopMin = gLoopPointsInputBuffer[i];
@@ -503,8 +500,8 @@
 
 		PeakBurst[0].process(1);
 
-		int convAudio = burstOut*peak[0]*65535;
-		matrixOut[n*8 + DAC_PIN5] = convAudio;
+		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;
@@ -513,8 +510,8 @@
 		 *
 		 * Dissonance, via changing frequency motion of partials
 		 */
-		float amount = (float)matrixIn[n*8 + ADC_PIN5] / 65536.0f;
-		gOscBanks[gCurrentOscBank]->freqMovement = 1-amount;
+		float amount = (float)context->analogIn[n*8 + ADC_PIN5];
+		gOscBanks[gCurrentOscBank]->freqMovement = 1.0 - amount;
 
 
 
@@ -537,8 +534,8 @@
 
 		PeakBurst[1].process(1);
 
-		convAudio = burstOut*peak[1]*65535;
-		matrixOut[n*8 + DAC_PIN6] = convAudio;
+		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;
@@ -550,14 +547,14 @@
 		if(!gIsLoading) {
 			// Use hysteresis to avoid jumping back and forth between sounds
 			if(gOscBanks.size() > 1) {
-				int input = matrixIn[n*8 + ADC_PIN6];
-				const int hystValue = 16000;
+				float input = context->analogIn[n*8 + ADC_PIN6];
+				const float hystValue = 16000.0 / 65536.0;
 
-				int upHysteresisValue = ((gCurrentOscBank + 1) * 65536 + hystValue) / gOscBanks.size();
-				int downHysteresisValue = (gCurrentOscBank * 65536 - hystValue) / gOscBanks.size();
+				float upHysteresisValue = ((gCurrentOscBank + 1) + hystValue) / gOscBanks.size();
+				float downHysteresisValue = (gCurrentOscBank - hystValue) / gOscBanks.size();
 
 				if(input > upHysteresisValue || input < downHysteresisValue) {
-					gNextOscBank = input * gOscBanks.size() / 65536;
+					gNextOscBank = input * gOscBanks.size();
 					if(gNextOscBank < 0)
 						gNextOscBank = 0;
 					if((unsigned)gNextOscBank >= gOscBanks.size())
@@ -572,8 +569,8 @@
 		 * FSR from primary touch sensor
 		 * Value ranges from 0-1799
 		 */
-		gLastFSRValue = matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0);
-		//gLastFSRValue = 1799 - matrixIn[n*8 + ADC_PIN7] * (1799.0 / 65535.0);
+		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++;
@@ -590,7 +587,7 @@
 		gOscillatorNeedsRender = false;
 
 		/* Render one frame into the write buffer */
-		memset(gOscillatorBufferWrite, 0, gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels * sizeof(float));
+		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,
@@ -600,7 +597,7 @@
 							 gOscBanks[gCurrentOscBank]->oscillatorAmplitudeDerivatives,
 							 /*gOscBanks[gCurrentOscBank]->lookupTable*/gDynamicWavetable);
 
-		gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * gNumAudioChannels;
+		gOscillatorBufferWriteCurrentSize = gOscBanks[gCurrentOscBank]->hopCounter * 2;
 
 		/* Update the pitch right before the hop
 		 * Total CV range +/- N_OCT octaves
@@ -681,7 +678,7 @@
 				gOscBanks[gCurrentOscBank]->lookupTable, sineMix);
 	}
 
-	if(gLoopPointMin >= 60000 && gLoopPointMax >= 60000) {
+	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);
@@ -689,8 +686,8 @@
 			gOscBanks[gCurrentOscBank]->setLoopHops(5, ((float)gOscBanks[gCurrentOscBank]->getLastHop() * 0.7) - 1);
 	}
 	else {
-		float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0;
-		float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop() / 65535.0;
+		float normLoopPointMin = (float)gLoopPointMin * gOscBanks[gCurrentOscBank]->getLastHop();
+		float normLoopPointMax = (float)gLoopPointMax * gOscBanks[gCurrentOscBank]->getLastHop();
 
 		int intLoopPointMin = normLoopPointMin;
 		if(intLoopPointMin < 1)
@@ -733,7 +730,7 @@
 }
 
 // Clean up at the end of render
-void cleanup_render()
+void cleanup_render(BeagleRTContext *context, void *userData)
 {
 	free(gOscillatorBuffer1);
 	free(gOscillatorBuffer2);
@@ -765,9 +762,9 @@
 }
 
 // Create a hysteresis oscillator with a matrix input and output
-inline uint16_t hysteresis_oscillator(uint16_t input, uint16_t risingThreshold, uint16_t fallingThreshold, bool *rising)
+inline float hysteresis_oscillator(float input, float risingThreshold, float fallingThreshold, bool *rising)
 {
-	uint16_t value;
+	float value;
 
 	if(*rising) {
 		if(input > risingThreshold) {
@@ -775,12 +772,12 @@
 			value = 0;
 		}
 		else
-			value = 65535;
+			value = 1.0;
 	}
 	else {
 		if(input < fallingThreshold) {
 			*rising = true;
-			value = 65535;
+			value = 1.0;
 		}
 		else
 			value = 0;