changeset 528:5c8f46fcd4d0 API-update

Updated BelaContext to use separate values for in/ou channels
author Giulio Moro <giuliomoro@yahoo.it>
date Thu, 23 Jun 2016 18:17:35 +0100
parents 1c68ad13bbe4
children bfcbeb437869
files core/PRU.cpp core/RTAudio.cpp examples/01-Basics/passthrough/render.cpp include/Bela.h include/PRU.h include/Utilities.h
diffstat 6 files changed, 125 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/core/PRU.cpp	Thu Jun 23 18:15:26 2016 +0100
+++ b/core/PRU.cpp	Thu Jun 23 18:17:35 2016 +0100
@@ -334,7 +334,7 @@
 		pru_buffer_spi_dac = (uint16_t *)&pruMem[PRU_MEM_DAC_OFFSET/sizeof(uint32_t)];
 
 		/* ADC memory starts after N(ch)*2(buffers)*bufsize samples */
-		pru_buffer_spi_adc = &pru_buffer_spi_dac[2 * context->analogChannels * context->analogFrames];
+		pru_buffer_spi_adc = &pru_buffer_spi_dac[2 * context->analogInChannels * context->analogFrames];
 	}
 	else {
 		pru_buffer_spi_dac = pru_buffer_spi_adc = 0;
@@ -376,7 +376,12 @@
     }
     if(analog_enabled) {
     	pru_buffer_comm[PRU_USE_SPI] = 1;
-    	pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = context->analogChannels;
+    	if(context->analogInChannels != context->analogOutChannels){
+    		printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n");
+    		return 1;
+    	}
+    	unsigned int analogChannels = context->analogInChannels;
+    	pru_buffer_comm[PRU_SPI_NUM_CHANNELS] = analogChannels;
     }
     else {
     	pru_buffer_comm[PRU_USE_SPI] = 0;
@@ -460,9 +465,9 @@
 			return 1;
 		}		
 #else
-		context->analogIn = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float));
-		context->analogOut = (float *)malloc(context->analogChannels * context->analogFrames * sizeof(float));
-		last_analog_out_frame = (float *)malloc(context->analogChannels * sizeof(float));
+		context->analogIn = (float *)malloc(context->analogInChannels * context->analogFrames * sizeof(float));
+		context->analogOut = (float *)malloc(context->analogOutChannels * context->analogFrames * sizeof(float));
+		last_analog_out_frame = (float *)malloc(context->analogOutChannels * sizeof(float));
 
 		if(context->analogIn == 0 || context->analogOut == 0 || last_analog_out_frame == 0) {
 			rt_printf("Error: couldn't allocate analog buffers\n");
@@ -470,7 +475,7 @@
 		}
 #endif
 		
-		memset(last_analog_out_frame, 0, context->analogChannels * sizeof(float));
+		memset(last_analog_out_frame, 0, context->analogOutChannels * sizeof(float));
 	}
 
 	// Allocate digital buffers
@@ -528,7 +533,12 @@
 	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;
+	if(context->analogInChannels != context->analogOutChannels){
+		printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n");
+		return;
+	}
+	unsigned int analogChannels = context->analogInChannels;
+	RTIME sleepTime = PRU_SAMPLE_INTERVAL_NS * (analogChannels / 2) * context->analogFrames / 4;
 #endif
 
 	uint32_t pru_audio_offset, pru_spi_offset;
@@ -540,8 +550,8 @@
 	if(analog_enabled) {
 		if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) {
 			// Remember the content of the last_analog_out_frame
-			for(unsigned int ch = 0; ch < context->analogChannels; ch++){
-				last_analog_out_frame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch];
+			for(unsigned int ch = 0; ch < context->analogOutChannels; ch++){
+				last_analog_out_frame[ch] = context->analogOut[context->analogOutChannels * (context->analogFrames - 1) + ch];
 			}
 		}
 	}
@@ -605,8 +615,18 @@
 		}
 		else {
 			// PRU is on buffer 0. We read and write to buffer 1
-			pru_audio_offset = context->audioFrames * 2;
-			pru_spi_offset = context->analogFrames * context->analogChannels;
+			if(context->audioInChannels != context->audioOutChannels){
+				printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n");
+				return;
+			}
+			unsigned int audioChannels = context->audioInChannels;
+			pru_audio_offset = context->audioFrames * audioChannels;
+			if(context->analogInChannels != context->analogOutChannels){
+				printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n");
+				return;
+			}
+	    	unsigned int analogChannels = context->analogInChannels;
+			pru_spi_offset = context->analogFrames * analogChannels;
 			if(digital_enabled)
 				context->digital = digital_buffer1;
 		}
@@ -644,22 +664,22 @@
 			int16_to_float_analog(context->analogChannels * context->analogFrames, 
 									&pru_buffer_spi_adc[pru_spi_offset], context->analogIn);
 #else	
-			for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) {
+			for(unsigned int n = 0; n < context->analogInChannels * context->analogFrames; n++) {
 				context->analogIn[n] = (float)pru_buffer_spi_adc[n + pru_spi_offset] / 65536.0f;
 			}
 #endif
 
 			if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) {
 				// Initialize the output buffer with the values that were in the last frame of the previous output
-				for(unsigned int ch = 0; ch < context->analogChannels; ch++){
+				for(unsigned int ch = 0; ch < context->analogOutChannels; ch++){
 					for(unsigned int n = 0; n < context->analogFrames; n++){
-						context->analogOut[n * context->analogChannels + ch] = last_analog_out_frame[ch];
+						context->analogOut[n * context->analogOutChannels + ch] = last_analog_out_frame[ch];
 					}
 				}
 			}
 			else {
 				// Outputs are 0 unless set otherwise
-				memset(context->analogOut, 0, context->analogChannels * context->analogFrames * sizeof(float));
+				memset(context->analogOut, 0, context->analogOutChannels * context->analogFrames * sizeof(float));
 			}
 		}
 
@@ -688,8 +708,8 @@
 		if(analog_enabled) {
 			if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) {
 				// Remember the content of the last_analog_out_frame
-				for(unsigned int ch = 0; ch < context->analogChannels; ch++){
-					last_analog_out_frame[ch] = context->analogOut[context->analogChannels * (context->analogFrames - 1) + ch];
+				for(unsigned int ch = 0; ch < context->analogOutChannels; ch++){
+					last_analog_out_frame[ch] = context->analogOut[context->analogOutChannels * (context->analogFrames - 1) + ch];
 				}
 			}
 
@@ -698,7 +718,7 @@
 			float_to_int16_analog(context->analogChannels * context->analogFrames, 
 								  context->analogOut, (uint16_t*)&pru_buffer_spi_dac[pru_spi_offset]);
 #else		
-			for(unsigned int n = 0; n < context->analogChannels * context->analogFrames; n++) {
+			for(unsigned int n = 0; n < context->analogOutChannels * context->analogFrames; n++) {
 				int out = context->analogOut[n] * 65536.0f;
 				if(out < 0) out = 0;
 				else if(out > 65535) out = 65535;
@@ -717,7 +737,7 @@
 #ifdef USE_NEON_FORMAT_CONVERSION
 		float_to_int16_audio(2 * context->audioFrames, context->audioOut, &pru_buffer_audio_dac[pru_audio_offset]);
 #else	
-		for(unsigned int n = 0; n < 2 * context->audioFrames; n++) {
+		for(unsigned int n = 0; n < context->audioOutChannels * context->audioFrames; n++) {
 			int out = context->audioOut[n] * 32768.0f;
 			if(out < -32768) out = -32768;
 			else if(out > 32767) out = 32767;
@@ -735,9 +755,6 @@
 		
 		Bela_autoScheduleAuxiliaryTasks();
 
-		// FIXME: TESTING!!
-		// if(testCount > 100000)
-		//	break;
 	}
 
 #ifdef BELA_USE_XENOMAI_INTERRUPTS
@@ -745,11 +762,6 @@
 	rt_intr_disable(pru_interrupt);
 #endif
 
-	// FIXME: TESTING
-	// RTIME endTime = rt_timer_read();
-	// RTIME diffTime = endTime - startTime;
-	// rt_printf("%d blocks elapsed in %f seconds, %f Hz block rate\n", testCount, ((float)diffTime / 1.0e9), (float)testCount / ((float)diffTime / 1.0e9));
-
 	// Tell PRU to stop
 	pru_buffer_comm[PRU_SHOULD_STOP] = 1;
 
--- a/core/RTAudio.cpp	Thu Jun 23 18:15:26 2016 +0100
+++ b/core/RTAudio.cpp	Thu Jun 23 18:17:35 2016 +0100
@@ -177,28 +177,39 @@
 
 	// Initialise the rendering environment: sample rates, frame counts, numbers of channels
 	gContext.audioSampleRate = 44100.0;
-	gContext.audioChannels = 2;
+
+	// TODO: settings a different number of channels for inputs and outputs is not yet supported
+	gContext.audioInChannels = 2;
+	gContext.audioOutChannels = 2;
 
 	if(settings->useAnalog) {
 		gContext.audioFrames = settings->periodSize;
 
 		gContext.analogFrames = gContext.audioFrames * 4 / settings->numAnalogChannels;
-		gContext.analogChannels = settings->numAnalogChannels;
+		// TODO: settings a different number of channels for inputs and outputs is not yet supported
+		gContext.analogInChannels = settings->numAnalogChannels;
+		gContext.analogOutChannels = settings->numAnalogChannels;
 		gContext.analogSampleRate = gContext.audioSampleRate * 4.0 / (float)settings->numAnalogChannels;
 	}
 	else {
 		gContext.audioFrames = settings->periodSize;
 
 		gContext.analogFrames = 0;
-		gContext.analogChannels = 0;
+		gContext.analogInChannels = 0;
+		gContext.analogOutChannels = 0;
 		gContext.analogSampleRate = 0;
 	}
 
+	if(gContext.analogInChannels != gContext.analogOutChannels){
+		printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n");
+		return -1;
+	}
+	unsigned int analogChannels = gContext.analogInChannels;
 	// Sanity check the combination of channels and period size
-	if( gContext.analogChannels != 0 && ((gContext.analogChannels <= 4 && gContext.analogFrames < 2) ||
-			(gContext.analogChannels <= 2 && gContext.analogFrames < 4)) )
+	if( analogChannels != 0 && ((analogChannels <= 4 && gContext.analogFrames < 2) ||
+			(analogChannels <= 2 && gContext.analogFrames < 4)) )
 	{
-		cout << "Error: " << gContext.analogChannels << " channels and period size of " << gContext.analogFrames << " not supported.\n";
+		cout << "Error: " << analogChannels << " channels and period size of " << gContext.analogFrames << " not supported.\n";
 		return 1;
 	}
 
@@ -231,7 +242,12 @@
 	}
 	
 	// Get the PRU memory buffers ready to go
-	if(gPRU->initialise(settings->pruNumber, gContext.analogFrames, gContext.analogChannels,
+	if(gContext.analogInChannels != gContext.analogOutChannels){
+		printf("Error: TODO: a different number of channels for inputs and outputs is not yet supported\n");
+		return 1;
+	}
+
+	if(gPRU->initialise(settings->pruNumber, gContext.analogFrames, analogChannels,
 		 				settings->numMuxChannels, true)) {
 		cout << "Error: unable to initialise PRU\n";
 		return 1;
--- a/examples/01-Basics/passthrough/render.cpp	Thu Jun 23 18:15:26 2016 +0100
+++ b/examples/01-Basics/passthrough/render.cpp	Thu Jun 23 18:17:35 2016 +0100
@@ -22,37 +22,45 @@
 */
 
 #include <Bela.h>
-#include <rtdk.h>
+#include <Scope.h>
+
+Scope scope;
 
 bool setup(BelaContext *context, void *userData)
 {
 	// Nothing to do here...
+	printf("%d %d\n", context->audioInChannels, context->audioOutChannels);
+	scope.setup(8, 44100);
 	return true;
 }
 
 void render(BelaContext *context, void *userData)
 {
+	static const unsigned int audioChannels = min(context->audioInChannels, context->audioOutChannels);
+	static const unsigned int analogChannels = min(context->analogInChannels, context->analogOutChannels);
+
 	// Simplest possible case: pass inputs through to outputs
 	for(unsigned int n = 0; n < context->audioFrames; n++) {
-		for(unsigned int ch = 0; ch < context->audioChannels; ch++){
+		for(unsigned int ch = 0; ch < audioChannels; ch++){
 			// Two equivalent ways to write this code
 
 			// The long way, using the buffers directly:
-			// context->audioOut[n * context->audioChannels + ch] =
-			// 		context->audioIn[n * context->audioChannels + ch];
+			// context->audioOut[n * context->audioOutChannels + ch] =
+			// 		context->audioIn[n * context->audioInChannels + ch];
 
 			// Or using the macros:
 			audioWrite(context, n, ch, audioRead(context, n, ch));
 		}
 	}
 
-	// Same with analog channelss
+	// Same with analog channels
 	for(unsigned int n = 0; n < context->analogFrames; n++) {
-		for(unsigned int ch = 0; ch < context->analogChannels; ch++) {
+		for(unsigned int ch = 0; ch < analogChannels; ch++) {
 			// Two equivalent ways to write this code
 
 			// The long way, using the buffers directly:
-			// context->analogOut[n * context->analogChannels + ch] = context->analogIn[n * context->analogChannels + ch];
+			// context->analogOut[n * context->analogOutChannels + ch] =
+			//  	context->analogIn[n * context->analogInChannels + ch];
 
 			// Or using the macros:
 			analogWrite(context, n, ch, analogRead(context, n, ch));
--- a/include/Bela.h	Thu Jun 23 18:15:26 2016 +0100
+++ b/include/Bela.h	Thu Jun 23 18:17:35 2016 +0100
@@ -206,8 +206,10 @@
 
 	/// Number of audio frames per period
 	const uint32_t audioFrames;
-	/// Number of audio channels (currently always 2)
-	const uint32_t audioChannels;
+	/// Number of input audio channels
+	const uint32_t audioInChannels;
+	/// Number of output audio channels
+	const uint32_t audioOutChannels;
 	/// Audio sample rate in Hz (currently always 44100.0)
 	const float audioSampleRate;
 
@@ -216,10 +218,15 @@
 	/// This will be 0 if analog I/O is disabled.
 	const uint32_t analogFrames;
 
-	/// \brief Number of analog channels
+	/// \brief Number of input analog channels
 	///
-	/// This could take a value of 8, 4 or 2. This will be 0 if analog I/O is disabled.
-	const uint32_t analogChannels;
+	/// This will be 0 if analog I/O is disabled.
+	const uint32_t analogInChannels;
+
+	/// \brief Number of output analog channels
+	///
+	/// This will be 0 if analog I/O is disabled.
+	const uint32_t analogOutChannels;
 
 	/// \brief Analog sample rate in Hz
 	///
--- a/include/PRU.h	Thu Jun 23 18:15:26 2016 +0100
+++ b/include/PRU.h	Thu Jun 23 18:17:35 2016 +0100
@@ -55,8 +55,10 @@
 
 	/// Number of audio frames per period
 	uint32_t audioFrames;
-	/// Number of audio channels (currently always 2)
-	uint32_t audioChannels;
+	/// Number of input audio channels
+	uint32_t audioInChannels;
+	/// Number of output audio channels
+	uint32_t audioOutChannels;
 	/// Audio sample rate in Hz (currently always 44100.0)
 	float audioSampleRate;
 
@@ -65,10 +67,15 @@
 	/// This will be 0 if analog I/O is disabled.
 	uint32_t analogFrames;
 
-	/// \brief Number of analog channels
+	/// \brief Number of input analog channels
 	///
-	/// This could take a value of 8, 4 or 2. This will be 0 if analog I/O is disabled.
-	uint32_t analogChannels;
+	/// This will be 0 if analog I/O is disabled.
+	uint32_t analogInChannels;
+
+	/// \brief Number of output analog channels
+	///
+	/// This will be 0 if analog I/O is disabled.
+	uint32_t analogOutChannels;
 
 	/// \brief Analog sample rate in Hz
 	///
--- a/include/Utilities.h	Thu Jun 23 18:15:26 2016 +0100
+++ b/include/Utilities.h	Thu Jun 23 18:17:35 2016 +0100
@@ -294,26 +294,36 @@
  */
 static inline float constrain(float x, float min_val, float max_val);
 
+/**
+ * Returns the maximum of two numbers
+ */
+static inline float min(float x, float y);
+
+/**
+ * Returns the minimum of two numbers
+ */
+static inline float max(float x, float y);
+
 /** @} */
 // audioRead()
 //
 // Returns the value of the given audio input at the given frame number.
 static inline float audioRead(BelaContext *context, int frame, int channel) {
-	return context->audioIn[frame * context->audioChannels + channel];
+	return context->audioIn[frame * context->audioInChannels + channel];
 }
 
 // audioWrite()
 //
 // Sets a given audio output channel to a value for the current frame
 static inline void audioWrite(BelaContext *context, int frame, int channel, float value) {
-	context->audioOut[frame * context->audioChannels + channel] = value;
+	context->audioOut[frame * context->audioOutChannels + channel] = value;
 }
 
 // analogRead()
 //
 // Returns the value of the given analog input at the given frame number.
 static inline float analogRead(BelaContext *context, int frame, int channel) {
-	return context->analogIn[frame * context->analogChannels + channel];
+	return context->analogIn[frame * context->analogInChannels + channel];
 }
 
 // analogWrite()
@@ -323,17 +333,17 @@
 static inline void analogWrite(BelaContext *context, int frame, int channel, float value) {
 	if(context->flags & BELA_FLAG_ANALOG_OUTPUTS_PERSIST) {
 		for(unsigned int f = frame; f < context->analogFrames; f++)
-			context->analogOut[frame * context->analogChannels + channel] = value;
+			context->analogOut[frame * context->analogOutChannels + channel] = value;
 	}
 	else
-		context->analogOut[frame * context->analogChannels + channel] = value;
+		context->analogOut[frame * context->analogOutChannels + channel] = value;
 }
 
 // analogWriteOnce()
 //
 // Sets a given channel to a value for only the current frame
 static inline void analogWriteOnce(BelaContext *context, int frame, int channel, float value) {
-	context->analogOut[frame * context->analogChannels + channel] = value;
+	context->analogOut[frame * context->analogOutChannels + channel] = value;
 }
 
 // digitalRead()
@@ -412,4 +422,12 @@
 	return x;
 }
 
+static inline float max(float x, float y){
+	return x > y ? x : y;
+}
+
+static inline float min(float x, float y){
+	return x < y ? x : y;
+}
+
 #endif /* UTILITIES_H_ */