changeset 373:3bed6b09223c prerelease

Updated NE10 library to the latest version; needs a corresponding update to the /usr/include/ne10 header files on the SD image. Updated examples to compile against new version, and reordered D-Box channels to account for new PRU-based DAC channel reordering.
author andrewm
date Thu, 09 Jun 2016 20:03:09 +0100
parents db2fe4e1b88e
children 768acdeea362
files core/RTAudio.cpp examples/audio_in_FFT/render.cpp examples/basic_FFT_phase_vocoder/render.cpp examples/d-box/FIRfilter.h examples/d-box/render.cpp examples/filter_FIR/render.cpp libNE10.a
diffstat 7 files changed, 43 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/core/RTAudio.cpp	Thu Jun 09 18:16:05 2016 +0100
+++ b/core/RTAudio.cpp	Thu Jun 09 20:03:09 2016 +0100
@@ -152,12 +152,12 @@
 	}
 
 	// Limit the analog channels to sane values
-	if(settings->numAnalogChannels >= 8)
-		settings->numAnalogChannels = 8;
-	else if(settings->numAnalogChannels >= 4)
-		settings->numAnalogChannels = 4;
-	else
-		settings->numAnalogChannels = 2;
+	if(settings->numAnalogChannels != 2 
+		&& settings->numAnalogChannels != 4
+		&& settings->numAnalogChannels != 8) {
+			cout << "Invalid number of analog channels: " << settings->numAnalogChannels << ". Valid values are 2, 4, 8.\n";
+			return -1;
+	}
 
 	// Initialise the rendering environment: sample rates, frame counts, numbers of channels
 	gContext.audioSampleRate = 44100.0;
--- a/examples/audio_in_FFT/render.cpp	Thu Jun 09 18:16:05 2016 +0100
+++ b/examples/audio_in_FFT/render.cpp	Thu Jun 09 20:03:09 2016 +0100
@@ -11,7 +11,7 @@
  * render.cpp
  *
  *  Created on: Oct 24, 2014
- *      Author: parallels
+ *      Author: Andrew McPherson, C4DM, QMUL
  */
 
 /**
@@ -40,16 +40,15 @@
 #include <cmath>
 
 int gFFTSize;
-float gFFTScaleFactor = 0;
 
 int gReadPointer = 0;
 int gWritePointer = 0;
 
 // FFT vars
-ne10_fft_cpx_float32_t* timeDomainIn;
-ne10_fft_cpx_float32_t* timeDomainOut;
-ne10_fft_cpx_float32_t* frequencyDomain;
-ne10_fft_cfg_float32_t cfg;
+static ne10_fft_cpx_float32_t* timeDomainIn;
+static ne10_fft_cpx_float32_t* timeDomainOut;
+static ne10_fft_cpx_float32_t* frequencyDomain;
+static ne10_fft_cfg_float32_t cfg;
 
 // setup() is called once before the audio rendering starts.
 // Use it to perform any initialisation and allocation which is dependent
@@ -64,12 +63,11 @@
 {
 	// Retrieve a parameter passed in from the initAudio() call
 	gFFTSize = *(int *)userData;
-	gFFTScaleFactor = 1.0f / (float)gFFTSize;
 
 	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);
+	cfg = ne10_fft_alloc_c2c_float32_neon (gFFTSize);
 
 	memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
 
@@ -91,19 +89,19 @@
 		if(++gReadPointer >= gFFTSize)
 		{
 			//FFT
-			ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg->twiddles, cfg->factors, gFFTSize, 0);
+			ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg, 0);
 
 			//Do frequency domain stuff
 
 			//IFFT
-			ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg->twiddles, cfg->factors, gFFTSize, 1);
+			ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg, 1);
 
 			gReadPointer = 0;
 			gWritePointer = 0;
 		}
 
 		for(unsigned int channel = 0; channel < context->audioChannels; channel++)
-			context->audioOut[n * context->audioChannels + channel] = (float) timeDomainOut[gWritePointer].r * gFFTScaleFactor;
+			context->audioOut[n * context->audioChannels + channel] = (float) timeDomainOut[gWritePointer].r;
 		gWritePointer++;
 	}
 }
--- a/examples/basic_FFT_phase_vocoder/render.cpp	Thu Jun 09 18:16:05 2016 +0100
+++ b/examples/basic_FFT_phase_vocoder/render.cpp	Thu Jun 09 20:03:09 2016 +0100
@@ -80,7 +80,10 @@
 float gDryWet = 1; // mix between the unprocessed and processed sound
 float gPlaybackLive = 0.5f; // mix between the file playback and the live audio input
 float gGain = 1; // overall gain
+float *gInputAudio = NULL;
 Midi midi;
+
+
 void midiCallback(MidiChannelMessage message, void* arg){
 	if(message.getType() == kmmNoteOn){
 		if(message.getDataByte(1) > 0){
@@ -133,11 +136,16 @@
 	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);
+	cfg = ne10_fft_alloc_c2c_float32_neon (gFFTSize);
 
 	memset(timeDomainOut, 0, gFFTSize * sizeof (ne10_fft_cpx_float32_t));
 	memset(gOutputBuffer, 0, BUFFER_SIZE * sizeof(float));
 
+	// Allocate buffer to mirror and modify the input
+	gInputAudio = (float *)malloc(context->audioFrames * context->audioChannels * sizeof(float));
+	if(gInputAudio == 0)
+		return false;
+
 	// Allocate the window buffer based on the FFT size
 	gWindowBuffer = (float *)malloc(gFFTSize * sizeof(float));
 	if(gWindowBuffer == 0)
@@ -177,7 +185,7 @@
 	}
 
 	// Run the FFT
-	ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg->twiddles, cfg->factors, gFFTSize, 0);
+	ne10_fft_c2c_1d_float32_neon (frequencyDomain, timeDomainIn, cfg, 0);
 
 	switch (gEffect){
 	  case kRobot :
@@ -202,7 +210,7 @@
 	  }
 
 	// Run the inverse FFT
-	ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg->twiddles, cfg->factors, gFFTSize, 1);
+	ne10_fft_c2c_1d_float32_neon (timeDomainOut, frequencyDomain, cfg, 1);
 	// Overlap-and-add timeDomainOut into the output buffer
 	pointer = outWritePointer;
 	for(int n = 0; n < gFFTSize; n++) {
@@ -226,7 +234,6 @@
 // will be 0.
 void render(BelaContext* context, void* userData)
 {
-	float* audioIn = context->audioIn;
 	float* audioOut = context->audioOut;
 	int numAudioFrames = context->audioFrames;
 	int numAudioChannels = context->audioChannels;
@@ -235,21 +242,21 @@
 	// Prep the "input" to be the sound file played in a loop
 	for(int n = 0; n < numAudioFrames; n++) {
 		if(gReadPtr < gSampleData.sampleLen)
-			audioIn[2*n] = audioIn[2*n+1] = gSampleData.samples[gReadPtr]*(1-gPlaybackLive) +
+			gInputAudio[2*n] = gInputAudio[2*n+1] = gSampleData.samples[gReadPtr]*(1-gPlaybackLive) +
 			gPlaybackLive*0.5f*(audioRead(context,n,0)+audioRead(context,n,1));
 		else
-			audioIn[2*n] = audioIn[2*n+1] = 0;
+			gInputAudio[2*n] = gInputAudio[2*n+1] = 0;
 		if(++gReadPtr >= gSampleData.sampleLen)
 			gReadPtr = 0;
 	}
 	// -------------------------------------------------------------------
 
 	for(int n = 0; n < numAudioFrames; n++) {
-		gInputBuffer[gInputBufferPointer] = ((audioIn[n*numAudioChannels] + audioIn[n*numAudioChannels+1]) * 0.5);
+		gInputBuffer[gInputBufferPointer] = ((gInputAudio[n*numAudioChannels] + gInputAudio[n*numAudioChannels+1]) * 0.5);
 
 		// Copy output buffer to output
 		for(int channel = 0; channel < numAudioChannels; channel++){
-			audioOut[n * numAudioChannels + channel] = gOutputBuffer[gOutputBufferReadPointer] * gGain * gDryWet + (1 - gDryWet) * audioIn[n * numAudioChannels + channel];
+			audioOut[n * numAudioChannels + channel] = gOutputBuffer[gOutputBufferReadPointer] * gGain * gDryWet + (1 - gDryWet) * gInputAudio[n * numAudioChannels + channel];
 		}
 
 		// Clear the output sample in the buffer so it is ready for the next overlap-add
@@ -287,5 +294,6 @@
 	NE10_FREE(timeDomainOut);
 	NE10_FREE(frequencyDomain);
 	NE10_FREE(cfg);
+	free(gInputAudio);
 	free(gWindowBuffer);
 }
--- a/examples/d-box/FIRfilter.h	Thu Jun 09 18:16:05 2016 +0100
+++ b/examples/d-box/FIRfilter.h	Thu Jun 09 20:03:09 2016 +0100
@@ -8,7 +8,7 @@
 #ifndef FIRFILTER_H_
 #define FIRFILTER_H_
 
-
+#define ENABLE_NE10_FIR_FLOAT_NEON	// Define needed for Ne10 library
 #include <NE10.h>
 
 //#define FILTER_TAP_NUM 21
--- a/examples/d-box/render.cpp	Thu Jun 09 18:16:05 2016 +0100
+++ b/examples/d-box/render.cpp	Thu Jun 09 20:03:09 2016 +0100
@@ -22,13 +22,16 @@
 
 // Mappings from pin numbers on PCB to actual DAC channels
 // This gives the DAC and ADC connectors the same effective pinout
-#define DAC_PIN0	6
-#define DAC_PIN1	4
+// Update June 2016: this is no longer needed in the latest Bela
+// release, but is kept here for convenience: it used to be 
+// 6 4 2 0 1 3 5 7 for the DAC pins
+#define DAC_PIN0	0
+#define DAC_PIN1	1
 #define DAC_PIN2	2
-#define DAC_PIN3	0
-#define DAC_PIN4	1
-#define DAC_PIN5	3
-#define DAC_PIN6	5
+#define DAC_PIN3	3
+#define DAC_PIN4	4
+#define DAC_PIN5	5
+#define DAC_PIN6	6
 #define DAC_PIN7	7
 
 #define ADC_PIN0	0
--- a/examples/filter_FIR/render.cpp	Thu Jun 09 18:16:05 2016 +0100
+++ b/examples/filter_FIR/render.cpp	Thu Jun 09 20:03:09 2016 +0100
@@ -23,6 +23,8 @@
 This is an example of a finite impulse response filter implementation.
 */
 
+#define ENABLE_NE10_FIR_FLOAT_NEON	// Define needed for Ne10 library
+
 #include <Bela.h>
 #include <cmath>
 #include <NE10.h>					// neon library
Binary file libNE10.a has changed