changeset 5:09f03ac40fcc

API improvements and cleanups. Now all common audio command-line options can be parsed automatically.
author andrewm
date Sat, 08 Nov 2014 16:16:55 +0100
parents f34c63568523
children ab396a08e962 49f22e1246b2
files .cproject core/RTAudio.cpp core/RTAudioCommandLine.cpp include/RTAudio.h include/Utilities.h projects/audio_in_FFT/main.cpp projects/audio_in_FFT/render.cpp projects/basic/main.cpp projects/basic_analog_output/main.cpp projects/basic_analog_output/render.cpp projects/basic_sensor/main.cpp projects/basic_sensor/render.cpp projects/d-box/main.cpp projects/filter_FIR/main.cpp projects/filter_FIR/render.cpp projects/filter_IIR/main.cpp projects/oscillator_bank/main.cpp projects/samples/main.cpp
diffstat 18 files changed, 580 insertions(+), 399 deletions(-) [+]
line wrap: on
line diff
--- a/.cproject	Thu Nov 06 19:02:48 2014 +0000
+++ b/.cproject	Sat Nov 08 16:16:55 2014 +0100
@@ -1,7 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?fileVersion 4.0.0?>
-
-<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
 	<storageModule moduleId="org.eclipse.cdt.core.settings">
 		<cconfiguration id="cdt.managedbuild.config.gnu.exe.debug.528876549">
 			<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.exe.debug.528876549" moduleId="org.eclipse.cdt.core.settings" name="Debug">
@@ -82,9 +80,9 @@
 						</toolChain>
 					</folderInfo>
 					<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 excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
-						<entry excluding="filter_IIR|filter_FIR|oscillator_bank|samples|basic_sensor|d-box|basic_analog_output|basic" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects"/>
+						<entry excluding="basic_sensor|d-box|audio_in_FFT|filter_IIR|filter_FIR|samples|oscillator_bank|basic" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects"/>
 					</sourceEntries>
 				</configuration>
 			</storageModule>
@@ -136,6 +134,7 @@
 								</option>
 								<option id="gnu.cpp.link.option.libs.1930118082" name="Libraries (-l)" superClass="gnu.cpp.link.option.libs" valueType="libs">
 									<listOptionValue builtIn="false" value="rt"/>
+									<listOptionValue builtIn="false" value="sndfile"/>
 									<listOptionValue builtIn="false" value="native"/>
 									<listOptionValue builtIn="false" value="xenomai"/>
 								</option>
@@ -155,9 +154,9 @@
 						</toolChain>
 					</folderInfo>
 					<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 excluding="audio_routines_old.S" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="core"/>
-						<entry excluding="filter_IIR|filter_FIR|oscillator_bank|samples|basic_sensor|d-box|basic_analog_output|basic" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects"/>
+						<entry excluding="basic_sensor|d-box|audio_in_FFT|filter_IIR|filter_FIR|samples|oscillator_bank|basic" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="projects"/>
 					</sourceEntries>
 				</configuration>
 			</storageModule>
--- a/core/RTAudio.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/core/RTAudio.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -44,8 +44,6 @@
 } InternalAuxiliaryTask;
 
 const char gRTAudioThreadName[] = "beaglert-audio";
-const char gRTCalculationThreadNameMedium[] = "dbox-calculation-medium";
-const char gRTCalculationThreadNameLow[] = "dbox-calculation-low";
 
 // Real-time tasks and objects
 RT_TASK gRTAudioThread;
@@ -61,6 +59,7 @@
 int gRTAudioVerbose = 0;   						// Verbosity level for debugging
 char gPRUFilename[256]	 = "pru_rtaudio.bin"; 	// path to PRU binary file
 int gAmplifierMutePin = -1;
+int gAmplifierShouldBeginMuted = 0;
 
 
 // initAudio() prepares the infrastructure for running PRU-based real-time
@@ -74,31 +73,41 @@
 //
 // Returns 0 on success.
 
-int initAudio(int periodSize, int useMatrix,
-			  void *userData,
-			  int codecI2CAddress, int ampMutePin)
+int BeagleRT_initAudio(RTAudioSettings *settings, void *userData)
 {
 	rt_print_auto_init(1);
+	setVerboseLevel(settings->verbose);
+
 	if(gRTAudioVerbose == 1)
 		rt_printf("Running with Xenomai\n");
 
-	if(gRTAudioVerbose == 1)
-		cout << "---------------->Init Audio Thread" << endl;
+	if(gRTAudioVerbose) {
+		cout << "Starting with period size " << settings->periodSize << "; ";
+		if(settings->useMatrix)
+			cout << "matrix enabled\n";
+		else
+			cout << "matrix disabled\n";
+		cout << "DAC level " << settings->dacLevel << "dB; ADC level " << settings->adcLevel;
+		cout << "dB; headphone level " << settings->headphoneLevel << "dB\n";
+		if(settings->beginMuted)
+			cout << "Beginning with speaker muted\n";
+	}
 
 	// Prepare GPIO pins for amplifier mute and status LED
-	if(ampMutePin >= 0) {
-		gAmplifierMutePin = ampMutePin;
+	if(settings->ampMutePin >= 0) {
+		gAmplifierMutePin = settings->ampMutePin;
+		gAmplifierShouldBeginMuted = settings->beginMuted;
 
-		if(gpio_export(ampMutePin)) {
+		if(gpio_export(settings->ampMutePin)) {
 			if(gRTAudioVerbose)
 				cout << "Warning: couldn't export amplifier mute pin\n";
 		}
-		if(gpio_set_dir(ampMutePin, OUTPUT_PIN)) {
+		if(gpio_set_dir(settings->ampMutePin, OUTPUT_PIN)) {
 			if(gRTAudioVerbose)
 				cout << "Couldn't set direction on amplifier mute pin\n";
 			return -1;
 		}
-		if(gpio_set_value(ampMutePin, LOW)) {
+		if(gpio_set_value(settings->ampMutePin, LOW)) {
 			if(gRTAudioVerbose)
 				cout << "Couldn't set value on amplifier mute pin\n";
 			return -1;
@@ -109,15 +118,15 @@
 	gPRU = new PRU();
 	gAudioCodec = new I2c_Codec();
 
-	if(gPRU->prepareGPIO(useMatrix, 1, 1)) {
+	if(gPRU->prepareGPIO(settings->useMatrix, 1, 1)) {
 		cout << "Error: unable to prepare GPIO for PRU audio\n";
 		return 1;
 	}
-	if(gPRU->initialise(0, periodSize, true)) {
+	if(gPRU->initialise(0, settings->periodSize, true)) {
 		cout << "Error: unable to initialise PRU\n";
 		return 1;
 	}
-	if(gAudioCodec->initI2C_RW(2, codecI2CAddress, -1)) {
+	if(gAudioCodec->initI2C_RW(2, settings->codecI2CAddress, -1)) {
 		cout << "Unable to open codec I2C\n";
 		return 1;
 	}
@@ -125,11 +134,13 @@
 		cout << "Error: unable to initialise audio codec\n";
 		return 1;
 	}
-	gAudioCodec->setDACVolume(0);	// Set the DAC volume to full-scale
-	gAudioCodec->setHPVolume(-12);	// Headphones 6dB down
-	gAudioCodec->setADCVolume(-12);	// Set the ADC volume to 6dB down
 
-	if(!initialise_render(2, useMatrix ? periodSize : 0, periodSize * 2, 22050.0, 44100.0, userData)) {
+	// Set default volume levels
+	BeagleRT_setDACLevel(settings->dacLevel);
+	BeagleRT_setADCLevel(settings->adcLevel);
+	BeagleRT_setHeadphoneLevel(settings->headphoneLevel);
+
+	if(!initialise_render(2, settings->useMatrix ? settings->periodSize : 0, settings->periodSize * 2, 22050.0, 44100.0, userData)) {
 		cout << "Couldn't initialise audio rendering\n";
 		return 1;
 	}
@@ -161,10 +172,13 @@
 		}
 		else {
 			// All systems go. Run the loop; it will end when gShouldStop is set to 1
-			// First unmute the amplifier
-			if(gpio_set_value(gAmplifierMutePin, HIGH)) {
-				if(gRTAudioVerbose)
-					rt_printf("Warning: couldn't set value (high) on amplifier mute pin\n");
+
+			if(!gAmplifierShouldBeginMuted) {
+				// First unmute the amplifier
+				if(BeagleRT_muteSpeakers(0)) {
+					if(gRTAudioVerbose)
+						rt_printf("Warning: couldn't set value (high) on amplifier mute pin\n");
+				}
 			}
 
 			gPRU->loop();
@@ -242,7 +256,7 @@
 // It launches the real-time Xenomai task which runs the audio loop. Returns 0
 // on success.
 
-int startAudio()
+int BeagleRT_startAudio()
 {
 	// Create audio thread with the highest priority
 	if(rt_task_create(&gRTAudioThread, gRTAudioThreadName, 0, 99, T_JOINABLE | T_FPU)) {
@@ -273,11 +287,14 @@
 // Stop the PRU-based audio from running and wait
 // for the tasks to complete before returning.
 
-void stopAudio()
+void BeagleRT_stopAudio()
 {
 	// Tell audio thread to stop (if this hasn't been done already)
 	gShouldStop = true;
 
+	if(gRTAudioVerbose)
+		cout << "Stopping audio...\n";
+
 	// Now wait for threads to respond and actually stop...
 	rt_task_join(&gRTAudioThread);
 
@@ -293,7 +310,7 @@
 }
 
 // Free any resources associated with PRU real-time audio
-void cleanupAudio()
+void BeagleRT_cleanupAudio()
 {
 	cleanup_render();
 
@@ -318,6 +335,48 @@
 	gAmplifierMutePin = -1;
 }
 
+// Set the level of the DAC; affects all outputs (headphone, line, speaker)
+// 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps
+int BeagleRT_setDACLevel(float decibels)
+{
+	if(gAudioCodec == 0)
+		return -1;
+	return gAudioCodec->setDACVolume((int)floorf(decibels * 2.0 + 0.5));
+}
+
+// Set the level of the ADC
+// 0dB is the maximum, -12dB is the minimum; 1.5dB steps
+int BeagleRT_setADCLevel(float decibels)
+{
+	if(gAudioCodec == 0)
+		return -1;
+	return gAudioCodec->setADCVolume((int)floorf(decibels * 2.0 + 0.5));
+}
+
+// Set the level of the onboard headphone amplifier; affects headphone
+// output only (not line out or speaker)
+// 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps
+int BeagleRT_setHeadphoneLevel(float decibels)
+{
+	if(gAudioCodec == 0)
+		return -1;
+	return gAudioCodec->setHPVolume((int)floorf(decibels * 2.0 + 0.5));
+}
+
+// Mute or unmute the onboard speaker amplifiers
+// mute == 0 means unmute; otherwise mute
+// Returns 0 on success
+int BeagleRT_muteSpeakers(int mute)
+{
+	int pinValue = mute ? LOW : HIGH;
+
+	// Check that we have an enabled pin for controlling the mute
+	if(gAmplifierMutePin < 0)
+		return -1;
+
+	return gpio_set_value(gAmplifierMutePin, pinValue);
+}
+
 // Set the verbosity level
 void setVerboseLevel(int level)
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/RTAudioCommandLine.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -0,0 +1,156 @@
+/*
+ * RTAudioCommandLine.cpp
+ *
+ *  Created on: Nov 8, 2014
+ *      Author: parallels
+ */
+
+#include <iostream>
+#include <cstdlib>
+#include <cstring>
+#include <getopt.h>
+
+#include "../include/RTAudio.h"
+
+// Default command-line options for RTAudio
+struct option gDefaultLongOptions[] =
+{
+	{"period", 1, NULL, 'p'},
+	{"verbose", 0, NULL, 'v'},
+	{"use-matrix", 1, NULL, 'm'},
+	{"mute-speaker", 1, NULL, 'M'},
+	{"dac-level", 1, NULL, 'D'},
+	{"adc-level", 1, NULL, 'A'},
+	{"hp-level", 1, NULL, 'H'},
+	{NULL, 0, NULL, 0}
+};
+
+const char gDefaultShortOptions[] = "p:vm:M:D:A:H:";
+
+// This function sets the default settings for the RTAudioSettings structure
+void BeagleRT_defaultSettings(RTAudioSettings *settings)
+{
+	// Set default values for settings
+	settings->periodSize = 8;
+	settings->beginMuted = 0;
+	settings->dacLevel = DEFAULT_DAC_LEVEL;
+	settings->adcLevel = DEFAULT_ADC_LEVEL;
+	settings->headphoneLevel = DEFAULT_HP_LEVEL;
+	settings->useMatrix = 1;
+	settings->verbose = 0;
+	settings->codecI2CAddress = CODEC_I2C_ADDRESS;
+	settings->ampMutePin = kAmplifierMutePin;
+}
+
+// This function drops in place of getopt() in the main() function
+// and handles the initialisation of the RTAudio settings using
+// standard command-line arguments. System default arguments will
+// be stored in settings, otherwise arguments will be returned
+// as getopt() normally does.
+
+int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions, const struct option *customLongOptions, RTAudioSettings *settings)
+{
+	static int firstRun = 1;
+	static char totalShortOptions[256];
+	static struct option totalLongOptions[256];
+
+	int c;
+
+	// Prep total option string the first time this is
+	// run. As a getopt() substitute, it will be called repeatedly working its
+	// way through argc and argv.
+	if(firstRun) {
+		firstRun = 0;
+
+		// Copy short options into one string
+		strcpy(totalShortOptions, gDefaultShortOptions);
+		strncat(totalShortOptions, customShortOptions, 256 - strlen(gDefaultShortOptions) - 1);
+
+		// Copy long options into one array
+		int n = 0;
+		while(1) {
+			if(gDefaultLongOptions[n].name == NULL)
+				break;
+			totalLongOptions[n].name = gDefaultLongOptions[n].name;
+			totalLongOptions[n].has_arg = gDefaultLongOptions[n].has_arg;
+			totalLongOptions[n].flag = gDefaultLongOptions[n].flag;
+			totalLongOptions[n].val = gDefaultLongOptions[n].val;
+			n++;
+		}
+
+		// Copy custom options into the array, if present
+		if(customLongOptions == 0) {
+			// Terminate the array
+			totalLongOptions[n].name = NULL;
+			totalLongOptions[n].has_arg = 0;
+			totalLongOptions[n].flag = NULL;
+			totalLongOptions[n].val = 0;
+		}
+		else {
+			int customIndex = 0;
+			while(n < 256) {
+				if(customLongOptions[customIndex].name == NULL)
+					break;
+				totalLongOptions[n].name = customLongOptions[customIndex].name;
+				totalLongOptions[n].has_arg = customLongOptions[customIndex].has_arg;
+				totalLongOptions[n].flag = customLongOptions[customIndex].flag;
+				totalLongOptions[n].val = customLongOptions[customIndex].val;
+				n++;
+				customIndex++;
+			}
+
+			// Terminate the array
+			totalLongOptions[n].name = NULL;
+			totalLongOptions[n].has_arg = 0;
+			totalLongOptions[n].flag = NULL;
+			totalLongOptions[n].val = 0;
+		}
+	}
+
+	while(1) {
+		if ((c = getopt_long(argc, argv, totalShortOptions, totalLongOptions, NULL)) < 0)
+			return c;
+
+		switch (c) {
+		case 'p':
+			settings->periodSize = atoi(optarg);
+			if(settings->periodSize < 1)
+				settings->periodSize = 1;
+			break;
+		case 'v':
+			settings->verbose = 1;
+			break;
+		case 'm':
+			settings->useMatrix = atoi(optarg);
+			break;
+		case 'M':
+			settings->beginMuted = atoi(optarg);
+			break;
+		case 'D':
+			settings->dacLevel = atof(optarg);
+			break;
+		case 'A':
+			settings->adcLevel = atof(optarg);
+			break;
+		case 'H':
+			settings->headphoneLevel = atof(optarg);
+			break;
+		case '?':
+		default:
+			return c;
+		}
+	}
+}
+
+// This function prints standard usage information for default arguments
+// Call from within your own usage function
+void BeagleRT_usage()
+{
+	std::cerr << "   --period [-p] period:    Set the hardware period (buffer) size in matrix samples\n";
+	std::cerr << "   --dac-level [-D] dBs:    Set the DAC output level (0dB max; -63.5dB min)\n";
+	std::cerr << "   --adc-level [-A] dBs:    Set the ADC input level (0dB max; -12dB min)\n";
+	std::cerr << "   --hp-level [-H] dBs:     Set the headphone output level (0dB max; -63.5dB min)\n";
+	std::cerr << "   --mute-speaker [-M] val: Set whether to mute the speaker initially (default: no)\n";
+	std::cerr << "   --use-matrix [-m] val:   Set whether to use ADC/DAC matrix\n";
+	std::cerr << "   --verbose [-v]:          Enable verbose logging information\n";
+}
--- a/include/RTAudio.h	Thu Nov 06 19:02:48 2014 +0000
+++ b/include/RTAudio.h	Sat Nov 08 16:16:55 2014 +0100
@@ -25,22 +25,73 @@
 #define CODEC_I2C_ADDRESS  0x1B		// Address of TLV320AIC3106 codec
 #endif
 
+// Default volume levels
+#define DEFAULT_DAC_LEVEL	0.0
+#define DEFAULT_ADC_LEVEL	-6.0
+#define DEFAULT_HP_LEVEL	-6.0
+
 enum {
 	kAmplifierMutePin = 61	// P8-26 controls amplifier mute
 };
 
+// Structure which contains initialisation parameters for the
+// real-time audio system
+typedef struct {
+	// These items might be adjusted by the user:
+	int periodSize;			// Number of (matrix) frames per period; audio is twice this
+	int beginMuted;			// Whether to begin with the speakers muted
+	float dacLevel;			// Level for the audio DAC output
+	float adcLevel;			// Level for the audio ADC input
+	float headphoneLevel;	// Level for the headphone output
+	int useMatrix;			// Whether to enable the ADC and DAC
+	int verbose;			// Whether to use verbose logging
+
+	// These items are hardware-dependent and should only be changed
+	// to run on different hardware
+	int codecI2CAddress;	// Where the codec can be found on the I2C bus
+	int ampMutePin;			// Pin where amplifier mute can be found
+} RTAudioSettings;
+
 typedef void* AuxiliaryTask;	// Opaque data type to keep track of aux tasks
 
 // Flag that indicates when the audio will stop; can be read or
 // set by other components which should end at the same time as the audio
 extern bool gShouldStop;
 
-int initAudio(int periodSize, int useMatrix, void *userData,
-			  int codecI2CAddress = CODEC_I2C_ADDRESS, int ampMutePin = kAmplifierMutePin);
-int startAudio();
-void stopAudio();
-void cleanupAudio();
+// Command-line settings
+void BeagleRT_defaultSettings(RTAudioSettings *settings);
+int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions,
+				   const struct option *customLongOptions, RTAudioSettings *settings);
+void BeagleRT_usage();
 
+// Basic audio control functions: init, start, stop and clean up
+int BeagleRT_initAudio(RTAudioSettings *settings, void *userData);
+int BeagleRT_startAudio();
+void BeagleRT_stopAudio();
+void BeagleRT_cleanupAudio();
+
+// Volume/level controls
+// These return 0 on success
+
+// Set the level of the DAC; affects all outputs (headphone, line, speaker)
+// 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps
+int BeagleRT_setDACLevel(float decibels);
+
+// Set the level of the ADC
+// 0dB is the maximum, -12dB is the minimum; 1.5dB steps
+int BeagleRT_setADCLevel(float decibels);
+
+// Set the level of the onboard headphone amplifier; affects headphone
+// output only (not line out or speaker)
+// 0dB is the maximum, -63.5dB is the minimum; 0.5dB steps
+int BeagleRT_setHeadphoneLevel(float decibels);
+
+// Mute or unmute the onboard speaker amplifiers
+// mute == 0 means unmute; otherwise mute
+// Returns 0 on success
+int BeagleRT_muteSpeakers(int mute);
+
+// Functions for creating auxiliary tasks
 AuxiliaryTask createAuxiliaryTaskLoop(void (*functionToCall)(void), int priority, const char *name);
 void scheduleAuxiliaryTask(AuxiliaryTask task);
 
--- a/include/Utilities.h	Thu Nov 06 19:02:48 2014 +0000
+++ b/include/Utilities.h	Sat Nov 08 16:16:55 2014 +0100
@@ -8,6 +8,13 @@
 #ifndef UTILITIES_H_
 #define UTILITIES_H_
 
+// Macros for accessing the matrix values: usable _only_ within render()
+
+// Read an analog input from input pin p at frame f
+#define analogRead(p, f) (matrixIn[(f)*8 + (p)])
+// Write an analog output frame at output pin p, frame f, to value v
+#define analogWrite(p, f, v) (matrixOut[(f)*8 + (p)] = (uint16_t)(v))
+
 float map(float x, float in_min, float in_max, float out_min, float out_max);
 float constrain(float x, float min_val, float max_val);
 
--- a/projects/audio_in_FFT/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/audio_in_FFT/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -9,6 +9,7 @@
 #include <cstdlib>
 #include <libgen.h>
 #include <signal.h>
+#include <getopt.h>
 #include "../../include/RTAudio.h"
 
 using namespace std;
@@ -22,44 +23,43 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f frequency]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-	cerr << "   -s fftsize:   Set the fSize of the FFT, in samples\n";
-	cerr << "   -m:           Enable the matrix (ADC and DAC) as well as audio\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int periodSize = 8;			// Period size in sensor frames
-	int verbose = 0;			// Verbose printing level
+	RTAudioSettings settings;	// Standard audio settings
 	int fftSize = 64;		    // Size of the FFT, in samples
-	int useMatrix = 0;			// Whether to use the matrix or just audio
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"fftsize", 1, NULL, 's'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	BeagleRT_defaultSettings(&settings);
+
+	settings.useMatrix = 0;	// No matrix usage by default
 
 	// Parse command-line arguments
 	while (1) {
 		int c;
-		if ((c = getopt(argc, argv, "hp:vf:m")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hs:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				periodSize = atoi(optarg);
-				if(periodSize < 1)
-					periodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
 		case 's':
 				fftSize = atof(optarg);
 				break;
-		case 'm':
-				useMatrix = 1;
-				break;
 		case '?':
 		default:
 				usage(basename(argv[0]));
@@ -67,26 +67,14 @@
 		}
 	}
 
-
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << periodSize << " and FFT size " << fftSize << endl;
-		if(useMatrix)
-			cout << "Matrix enabled\n";
-		else
-			cout << "Matrix disabled\n";
-	}
-
 	// Initialise the PRU audio device
-	if(initAudio(periodSize, useMatrix, &fftSize) != 0) {
+	if(BeagleRT_initAudio(&settings, &fftSize) != 0) {
 		cout << "Error: unable to initialise audio" << endl;
 		return -1;
 	}
 
 	// Start the audio device running
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -100,15 +88,12 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;
 }
+
--- a/projects/audio_in_FFT/render.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/audio_in_FFT/render.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -11,14 +11,16 @@
 #include <NE10.h>					// neon library
 #include <cmath>
 
-int gFftSize;
+int gFFTSize;
+float gFFTScaleFactor = 0;
 int gNumChannels;
 
 int gReadPointer = 0;
 int gWritePointer = 0;
 
 // FFT vars
-ne10_fft_cpx_float32_t* timeDomain;
+ne10_fft_cpx_float32_t* timeDomainIn;
+ne10_fft_cpx_float32_t* timeDomainOut;
 ne10_fft_cpx_float32_t* frequencyDomain;
 ne10_fft_cfg_float32_t cfg;
 
@@ -36,14 +38,16 @@
 					   float audioSampleRate, void *userData)
 {
 	// Retrieve a parameter passed in from the initAudio() call
-	gFftSize = *(int *)userData;
+	gFFTSize = *(int *)userData;
+	gFFTScaleFactor = 1.0f / (float)gFFTSize;
 	gNumChannels = numChannels;
 
-	//memset(outSamples, gFftSize, 0.0); // set all to 0
+	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 (gFFTSize);
 
-	timeDomain = (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 (gFftSize);
+	memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
 
 	return true;
 }
@@ -57,28 +61,26 @@
 			uint16_t *matrixIn, uint16_t *matrixOut)
 {
 	for(int n = 0; n < numAudioFrames; n++) {
-		timeDomain[gReadPointer].r = (ne10_float32_t) ((audioIn[n*gNumChannels] + audioIn[n*gNumChannels+1])/2);
-		timeDomain[gReadPointer].i = 0;
-		gReadPointer++;
-	}
+		timeDomainIn[gReadPointer].r = (ne10_float32_t) ((audioIn[n*gNumChannels] + audioIn[n*gNumChannels+1]) * 0.5);
+		timeDomainIn[gReadPointer].i = 0;
 
-	if(gReadPointer>=gFftSize)
-	{
-		//FFT
-		ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomain, cfg->twiddles, cfg->factors, gFftSize, 0);
+		if(++gReadPointer >= gFFTSize)
+		{
+			//FFT
+			ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg->twiddles, cfg->factors, gFFTSize, 0);
 
-		//Do frequency domain stuff
+			//Do frequency domain stuff
 
-		//IFFT
-		ne10_fft_c2c_1d_float32_neon (timeDomain, frequencyDomain, cfg->twiddles, cfg->factors, gFftSize, 1);
+			//IFFT
+			ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg->twiddles, cfg->factors, gFFTSize, 1);
 
-		gReadPointer = 0;
-		gWritePointer = 0;
-	}
+			gReadPointer = 0;
+			gWritePointer = 0;
+		}
 
-	for(int n = 0; n < numAudioFrames; n++) {
 		for(int channel = 0; channel < gNumChannels; channel++)
-			audioOut[n * gNumChannels + channel] = (float) timeDomain[gWritePointer++].r/gFftSize;
+			audioOut[n * gNumChannels + channel] = (float) timeDomainOut[gWritePointer].r * gFFTScaleFactor;
+		gWritePointer++;
 	}
 }
 
@@ -87,7 +89,8 @@
 
 void cleanup_render()
 {
-	NE10_FREE(timeDomain);
+	NE10_FREE(timeDomainIn);
+	NE10_FREE(timeDomainOut);
 	NE10_FREE(frequencyDomain);
 	NE10_FREE(cfg);
 }
--- a/projects/basic/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/basic/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -9,6 +9,7 @@
 #include <cstdlib>
 #include <libgen.h>
 #include <signal.h>
+#include <getopt.h>
 #include "../../include/RTAudio.h"
 
 using namespace std;
@@ -22,44 +23,41 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f frequency]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-	cerr << "   -f frequency: Set the frequency of the oscillator\n";
-	cerr << "   -m:           Enable the matrix (ADC and DAC) as well as audio\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int periodSize = 8;			// Period size in sensor frames
-	int verbose = 0;			// Verbose printing level
+	RTAudioSettings settings;	// Standard audio settings
 	float frequency = 440.0;	// Frequency of oscillator
-	int useMatrix = 0;			// Whether to use the matrix or just audio
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{"frequency", 1, NULL, 'f'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	BeagleRT_defaultSettings(&settings);
 
 	// Parse command-line arguments
 	while (1) {
 		int c;
-		if ((c = getopt(argc, argv, "hp:vf:m")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				periodSize = atoi(optarg);
-				if(periodSize < 1)
-					periodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
 		case 'f':
 				frequency = atof(optarg);
 				break;
-		case 'm':
-				useMatrix = 1;
-				break;
 		case '?':
 		default:
 				usage(basename(argv[0]));
@@ -67,26 +65,14 @@
 		}
 	}
 
-
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << periodSize << " and frequency " << frequency << endl;
-		if(useMatrix)
-			cout << "Matrix enabled\n";
-		else
-			cout << "Matrix disabled\n";
-	}
-
 	// Initialise the PRU audio device
-	if(initAudio(periodSize, useMatrix, &frequency) != 0) {
+	if(BeagleRT_initAudio(&settings, &frequency) != 0) {
 		cout << "Error: unable to initialise audio" << endl;
 		return -1;
 	}
 
 	// Start the audio device running
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -100,14 +86,10 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;
--- a/projects/basic_analog_output/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/basic_analog_output/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -9,6 +9,7 @@
 #include <cstdlib>
 #include <libgen.h>
 #include <signal.h>
+#include <getopt.h>
 #include "../../include/RTAudio.h"
 
 using namespace std;
@@ -22,36 +23,41 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f input] [-a input]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-	cerr << "   -f frequency: Set frequency of LED fade (default: 1.0)\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int periodSize = 8;			// Period size in sensor frames
-	int verbose = 0;			// Verbose printing level
-	float frequency = 1.0;		// Frequency of LED fades
+	RTAudioSettings 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
+	BeagleRT_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 = getopt(argc, argv, "hp:vf:")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				periodSize = atoi(optarg);
-				if(periodSize < 1)
-					periodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
 		case 'f':
 				frequency = atof(optarg);
 				if(frequency < 0)
@@ -66,22 +72,14 @@
 		}
 	}
 
-
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << periodSize << " and frequency " << frequency <<  endl;
-	}
-
 	// Initialise the PRU audio device
-	if(initAudio(periodSize, 1, &frequency) != 0) {
+	if(BeagleRT_initAudio(&settings, &frequency) != 0) {
 		cout << "Error: unable to initialise audio" << endl;
 		return -1;
 	}
 
 	// Start the audio device running
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -95,14 +93,10 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;
--- a/projects/basic_analog_output/render.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/basic_analog_output/render.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -62,7 +62,7 @@
 			if(out > MATRIX_MAX)
 				out = MATRIX_MAX;
 
-			matrixOut[n * 8 + channel] = (uint16_t)out;
+			analogWrite(channel, n, out);
 
 			// Advance by pi/4 (1/8 of a full rotation) for each channel
 			relativePhase += M_PI * 0.25;
--- a/projects/basic_sensor/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/basic_sensor/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -9,6 +9,7 @@
 #include <cstdlib>
 #include <libgen.h>
 #include <signal.h>
+#include <getopt.h>
 #include "../../include/RTAudio.h"
 
 using namespace std;
@@ -25,36 +26,39 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f input] [-a input]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-	cerr << "   -f input:     Choose the analog input controlling frequency (0-7; default 0)\n";
-	cerr << "   -a input:     Choose the analog input controlling amplitude (0-7; default 1)\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int periodSize = 8;			// Period size in sensor frames
-	int verbose = 0;			// Verbose printing level
+	RTAudioSettings 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
+	BeagleRT_defaultSettings(&settings);
 
 	// Parse command-line arguments
 	while (1) {
 		int c;
-		if ((c = getopt(argc, argv, "hp:vf:a:")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hf:a:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				periodSize = atoi(optarg);
-				if(periodSize < 1)
-					periodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
 		case 'f':
 				gSensorInputFrequency = atoi(optarg);
 				if(gSensorInputFrequency < 0 || gSensorInputFrequency > 7) {
@@ -76,24 +80,19 @@
 		}
 	}
 
+	// Initialise the PRU audio device
+	if(BeagleRT_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
 
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << periodSize << endl;
+	if(settings.verbose) {
 		cout << "--> Frequency on input " << gSensorInputFrequency << endl;
 		cout << "--> Amplitude on input " << gSensorInputAmplitude << endl;
 	}
 
-	// Initialise the PRU audio device
-	if(initAudio(periodSize, 1, 0) != 0) {
-		cout << "Error: unable to initialise audio" << endl;
-		return -1;
-	}
-
 	// Start the audio device running
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -107,14 +106,10 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;
--- a/projects/basic_sensor/render.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/basic_sensor/render.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -64,8 +64,8 @@
 	for(int n = 0; n < numAudioFrames; n++) {
 		if(!(n % 2)) {
 			// Even audio samples: update frequency and amplitude from the matrix
-			frequency = map((float)matrixIn[gSensorInputFrequency], 0, MATRIX_MAX, 100, 1000);
-			amplitude = (float)matrixIn[gSensorInputAmplitude] / MATRIX_MAX;
+			frequency = map((float)analogRead(gSensorInputFrequency, n/2), 0, MATRIX_MAX, 100, 1000);
+			amplitude = (float)analogRead(gSensorInputAmplitude, n/2) / MATRIX_MAX;
 		}
 
 		float out = amplitude * sinf(gPhase);
--- a/projects/d-box/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/d-box/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -262,7 +262,7 @@
 }
 
 
-void parseArguments(arg_data args)
+void parseArguments(arg_data args, RTAudioSettings *settings)
 {
 	// Default filename;
 	gPartialFilename = strdup("D-Box_sound_250_60_40_h88_2.txt");
@@ -271,12 +271,10 @@
 	struct option long_option[] =
 	{
 		{"help", 0, NULL, 'h'},
-		{"period", 1, NULL, 'p'},
-		{"verbose", 1, NULL, 'v'},
 		{"audioin", 1, NULL, 'i'},
 		{"file", 1, NULL, 'f'},
 		{"keyboard", 1, NULL, 'k'},
-		{"audio-test", 0, NULL, 'A'},
+		{"audio-test", 0, NULL, 'T'},
 		{"new-sensors", 0, NULL, 'S'},
 		{"sensor0", 1, NULL, 'Q'},
 		{"sensor1", 1, NULL, 'R'},
@@ -290,22 +288,18 @@
 	int morehelp = 0;
 	int tmp = -1;
 
+	BeagleRT_defaultSettings(settings);
+
 	while (1)
 	{
 		int c;
-		if ((c = getopt_long(args.argc, args.argv, "hp:vf:ki:sAQ:R:Sl:u:o:n:g:", long_option, NULL)) < 0)
+		if ((c = BeagleRT_getopt_long(args.argc, args.argv, "hf:ki:sTQ:R:Sl:u:o:n:g:", long_option, settings)) < 0)
 				break;
 		switch (c)
 		{
 		case 'h':
 				morehelp++;
 				break;
-		case 'p':
-				gPeriodSize = atoi(optarg);
-				break;
-		case 'v':
-				gVerbose = 1;
-				break;
 		case 'f':
 				free(gPartialFilename);
 				gPartialFilename = strdup(optarg);
@@ -319,7 +313,7 @@
 		case 's':
 				forceSensors = true;
 				break;
-		case 'A':
+		case 'T':
 				useAudioTest = true;
 				break;
 		case 'S':
@@ -360,10 +354,14 @@
 				break;
 		}
 	}
+
+	gPeriodSize = settings->periodSize;
+	gVerbose = settings->verbose;
 }
 
 int main(int argc, char *argv[])
 {
+	RTAudioSettings settings;	// Standard audio settings
 	RT_TASK rtSensorThread;
 	const char rtSensorThreadName[] = "dbox-sensor";
 	int oscBankHopSize;
@@ -371,7 +369,7 @@
 	// Parse command-line arguments
 	args.argc = argc;
 	args.argv = argv;
-	parseArguments(args);
+	parseArguments(args, &settings);
 
 	setVerboseLevel(gVerbose);
 	if(gVerbose == 1 && useAudioTest)
@@ -384,7 +382,7 @@
 	oscBankHopSize = gOscBanks[gCurrentOscBank]->getHopSize()/gOscBanks[gCurrentOscBank]->getMinSpeed();
 
 	// Initialise the audio device
-	if(initAudio(gPeriodSize, 1, &oscBankHopSize) != 0)
+	if(BeagleRT_initAudio(&settings, &oscBankHopSize) != 0)
 		return -1;
 
 	// Initialise the status LED
@@ -405,7 +403,7 @@
 	if(gVerbose == 1)
 		cout << "main() : creating audio thread" << endl;
 
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -465,12 +463,12 @@
 		usleep(100000);
 	}
 
-	stopAudio();
+	BeagleRT_stopAudio();
 
 	if(!useAudioTest)
 		rt_task_join(&rtSensorThread);
 
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	pthread_join( keyboardThread, NULL);
 	pthread_join( logThread, NULL);
--- a/projects/filter_FIR/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/filter_FIR/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -10,14 +10,13 @@
 #include <libgen.h>
 #include <signal.h>
 #include <string>
+#include <getopt.h>
 #include <sndfile.h>				// to load audio files
 #include "../../include/RTAudio.h"
 #include "SampleData.h"
 
 using namespace std;
 
-int gPeriodSize = 8;			// Period size in sensor frames
-
 // Load samples from file
 int initFile(string file, SampleData *smp)//float *& smp)
 {
@@ -81,44 +80,43 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f frequency]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-	cerr << "   -m:           Enable the matrix (ADC and DAC) as well as audio\n";
-	cerr << "   -f filename:  Name of the file to load (default is \"sample.wav\")\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int verbose = 0;			// Verbose printing level
-	int useMatrix = 0;			// Whether to use the matrix or just audio
+	RTAudioSettings 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
+	BeagleRT_defaultSettings(&settings);
+
 	// Parse command-line arguments
 	while (1) {
 		int c;
-		if ((c = getopt(argc, argv, "hp:vms:")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				gPeriodSize = atoi(optarg);
-				if(gPeriodSize < 1)
-					gPeriodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
-		case 'm':
-				useMatrix = 1;
-				break;
 		case 'f':
 				fileName = string((char *)optarg);
 				break;
@@ -130,18 +128,10 @@
 	}
 
 	if(fileName.empty()){
-		fileName = "filter/longsample.wav";
+		fileName = "longsample.wav";
 	}
 
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << gPeriodSize << endl;
-		if(useMatrix)
-			cout << "Matrix enabled\n";
-		else
-			cout << "Matrix disabled\n";
+	if(settings.verbose) {
 		cout << "Loading file " << fileName << endl;
 	}
 
@@ -152,17 +142,18 @@
 		return -1;
 	}
 
-	if(verbose)
+	if(settings.verbose)
 		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
 
+
 	// Initialise the PRU audio device
-	if(initAudio(gPeriodSize, useMatrix, &sampleData) != 0) {
+	if(BeagleRT_initAudio(&settings, &sampleData) != 0) {
 		cout << "Error: unable to initialise audio" << endl;
 		return -1;
 	}
 
 	// Start the audio device running
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -176,15 +167,12 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;
 }
+
--- a/projects/filter_FIR/render.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/filter_FIR/render.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -36,7 +36,7 @@
 bool initialise_trigger();
 void trigger_samples();
 
-extern int gPeriodSize;			// Period size in sensor frames
+int gPeriodSize;			// Period size in sensor frames
 
 
 // initialise_render() is called once before the audio rendering starts.
@@ -58,6 +58,7 @@
 
 	gReadPtr = -1;
 	gNumChannels = numChannels;
+	gPeriodSize = numMatrixFramesPerPeriod;
 
 	initialise_filter();
 
--- a/projects/filter_IIR/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/filter_IIR/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -10,6 +10,7 @@
 #include <libgen.h>
 #include <signal.h>
 #include <string>
+#include <getopt.h>
 #include <sndfile.h>				// to load audio files
 #include "../../include/RTAudio.h"
 #include "SampleData.h"
@@ -70,7 +71,6 @@
 	return 0;
 }
 
-
 // Handle Ctrl-C by requesting that the audio rendering stop
 void interrupt_handler(int var)
 {
@@ -81,46 +81,45 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f frequency]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-	cerr << "   -m:           Enable the matrix (ADC and DAC) as well as audio\n";
-	cerr << "   -f filename:  Name of the file to load (default is \"sample.wav\")\n";
-	cerr << "   -c freq:      Set the cut off frequency of the filter in Hz\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int verbose = 0;			// Verbose printing level
-	int periodSize = 8;			// Period size in sensor frames
-	int useMatrix = 0;			// Whether to use the matrix or just audio
+	RTAudioSettings 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
+	BeagleRT_defaultSettings(&settings);
+
 	// Parse command-line arguments
 	while (1) {
 		int c;
-		if ((c = getopt(argc, argv, "hp:vms:")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hf:c:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				periodSize = atoi(optarg);
-				if(periodSize < 1)
-					periodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
-		case 'm':
-				useMatrix = 1;
-				break;
 		case 'f':
 				fileName = string((char *)optarg);
 				break;
@@ -135,18 +134,10 @@
 	}
 
 	if(fileName.empty()){
-		fileName = "filter/longsample.wav";
+		fileName = "longsample.wav";
 	}
 
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << periodSize << " and cut-off frequency" << gCutFreq << endl;
-		if(useMatrix)
-			cout << "Matrix enabled\n";
-		else
-			cout << "Matrix disabled\n";
+	if(settings.verbose) {
 		cout << "Loading file " << fileName << endl;
 	}
 
@@ -157,17 +148,18 @@
 		return -1;
 	}
 
-	if(verbose)
+	if(settings.verbose)
 		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
 
+
 	// Initialise the PRU audio device
-	if(initAudio(periodSize, useMatrix, &sampleData) != 0) {
+	if(BeagleRT_initAudio(&settings, &sampleData) != 0) {
 		cout << "Error: unable to initialise audio" << endl;
 		return -1;
 	}
 
 	// Start the audio device running
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -181,15 +173,12 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;
 }
+
--- a/projects/oscillator_bank/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/oscillator_bank/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -9,6 +9,7 @@
 #include <cstdlib>
 #include <libgen.h>
 #include <signal.h>
+#include <getopt.h>
 #include "../../include/RTAudio.h"
 
 using namespace std;
@@ -16,7 +17,6 @@
 int gNumOscillators = 32;
 int gWavetableLength = 1024;
 
-
 // Handle Ctrl-C by requesting that the audio rendering stop
 void interrupt_handler(int var)
 {
@@ -26,38 +26,39 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f input] [-a input]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-    cerr << "   -n oscs:      Set the number of oscillators to use (default: 32)\n";
-    cerr << "   -w length:    Set the wavetable length in samples (default: 1024)\n";
-	cerr << "   -m:           Enable the matrix (ADC and DAC) for controlling parameters\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int periodSize = 8;			// Period size in sensor frames
-	int verbose = 0;			// Verbose printing level
-	int useMatrix = 0;
+	RTAudioSettings 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
+	BeagleRT_defaultSettings(&settings);
 
 	// Parse command-line arguments
 	while (1) {
 		int c;
-		if ((c = getopt(argc, argv, "hp:vn:w:m")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hn:w:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				periodSize = atoi(optarg);
-				if(periodSize < 1)
-					periodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
 		case 'n':
 				gNumOscillators = atoi(optarg);
 				if(gNumOscillators <= 0) {
@@ -72,9 +73,6 @@
 				if(gWavetableLength > 16384)
 					gWavetableLength = 16384;
 				break;
-		case 'm':
-				useMatrix = 1;
-				break;
 		case '?':
 		default:
 				usage(basename(argv[0]));
@@ -82,26 +80,18 @@
 		}
 	}
 
-
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << periodSize << endl;
-		cout << "--> Using " << gNumOscillators << " oscillators and wavetable of " << gWavetableLength << " samples\n";
-		cout << "--> Matrix ";
-		if(useMatrix) cout << "enabled\n";
-		else cout << "disabled\n";
-	}
-
 	// Initialise the PRU audio device
-	if(initAudio(periodSize, useMatrix, 0) != 0) {
+	if(BeagleRT_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(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -115,14 +105,10 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;
--- a/projects/samples/main.cpp	Thu Nov 06 19:02:48 2014 +0000
+++ b/projects/samples/main.cpp	Sat Nov 08 16:16:55 2014 +0100
@@ -10,6 +10,7 @@
 #include <libgen.h>
 #include <signal.h>
 #include <string>
+#include <getopt.h>
 #include <sndfile.h>				// to load audio files
 #include "../../include/RTAudio.h"
 #include "SampleData.h"
@@ -79,45 +80,43 @@
 // Print usage information
 void usage(const char * processName)
 {
-	cerr << "Usage: " << processName << " [-h] [-v] [-p period] [-f frequency]" << endl;
-	cerr << "   -h:           Print this menu\n";
-	cerr << "   -v:           Enable verbose messages\n";
-	cerr << "   -p period:    Set the period (hardware buffer) size in sensor frames\n";
-	cerr << "   -m:           Enable the matrix (ADC and DAC) as well as audio\n";
-	cerr << "   -f filename:  Name of the file to load (default is \"sample.wav\")\n";
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_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[])
 {
-	int periodSize = 8;			// Period size in sensor frames
-	int verbose = 0;			// Verbose printing level
-	int useMatrix = 0;			// Whether to use the matrix or just audio
+	RTAudioSettings 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
+	BeagleRT_defaultSettings(&settings);
+
 	// Parse command-line arguments
 	while (1) {
 		int c;
-		if ((c = getopt(argc, argv, "hp:vms:")) < 0)
+		if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
 				break;
 		switch (c) {
 		case 'h':
 				usage(basename(argv[0]));
 				exit(0);
-		case 'p':
-				periodSize = atoi(optarg);
-				if(periodSize < 1)
-					periodSize = 1;
-				break;
-		case 'v':
-				verbose = 1;
-				break;
-		case 'm':
-				useMatrix = 1;
-				break;
 		case 'f':
 				fileName = string((char *)optarg);
 				break;
@@ -129,18 +128,10 @@
 	}
 
 	if(fileName.empty()){
-		fileName = "samples/sample.wav";
+		fileName = "sample.wav";
 	}
 
-	// Set verbose logging information (optional by using value > 0; default is 0)
-	setVerboseLevel(verbose);
-
-	if(verbose) {
-		cout << "Starting with period size " << periodSize << endl;
-		if(useMatrix)
-			cout << "Matrix enabled\n";
-		else
-			cout << "Matrix disabled\n";
+	if(settings.verbose) {
 		cout << "Loading file " << fileName << endl;
 	}
 
@@ -151,17 +142,18 @@
 		return -1;
 	}
 
-	if(verbose)
+	if(settings.verbose)
 		cout << "File contains " << sampleData.sampleLen << " samples" << endl;
 
+
 	// Initialise the PRU audio device
-	if(initAudio(periodSize, useMatrix, &sampleData) != 0) {
+	if(BeagleRT_initAudio(&settings, &sampleData) != 0) {
 		cout << "Error: unable to initialise audio" << endl;
 		return -1;
 	}
 
 	// Start the audio device running
-	if(startAudio()) {
+	if(BeagleRT_startAudio()) {
 		cout << "Error: unable to start real-time audio" << endl;
 		return -1;
 	}
@@ -175,14 +167,10 @@
 	}
 
 	// Stop the audio device
-	stopAudio();
-
-	if(verbose) {
-		cout << "Cleaning up..." << endl;
-	}
+	BeagleRT_stopAudio();
 
 	// Clean up any resources allocated for audio
-	cleanupAudio();
+	BeagleRT_cleanupAudio();
 
 	// All done!
 	return 0;