diff core/RTAudio.cpp @ 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 8a575ba3ab52
children a6beeba3a648
line wrap: on
line diff
--- 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)
 {