changeset 98:9a413516a1fc

Tweaking the PLL you can obtain a virtual analog Bucket Brigade Device Chorus
author Giulio Moro <giuliomoro@yahoo.it>
date Thu, 23 Jul 2015 02:38:09 +0100
parents c44fa102d02b
children f03d68f18d7f
files projects/bucket_brigade_chorus/render.cpp
diffstat 1 files changed, 112 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/projects/bucket_brigade_chorus/render.cpp	Thu Jul 23 02:38:09 2015 +0100
@@ -0,0 +1,112 @@
+#include <BeagleRT.h> 
+#include <Scope.h>
+#include <cmath>
+#include <Utilities.h>
+
+float gPhase1, gPhase2;
+float gFrequency1, gFrequency2;
+float gInverseSampleRate;
+
+Scope scope;    //create a scope object
+
+// initialise_render() is called once before the audio rendering starts.
+// Use it to perform any initialisation and allocation which is dependent
+// on the period size or sample rate.
+//
+// userData holds an opaque pointer to a data structure that was passed
+// in from the call to initAudio().
+//
+// Return true on success; returning false halts the program.
+#include <I2c_Codec.h>
+#include <PRU.h>
+extern I2c_Codec *gAudioCodec;
+extern PRU *gPRU;
+float D=5264;
+#define delayLength 512
+float delay[delayLength];
+int writePointer=0;
+int readPointer=writePointer+1;
+AuxiliaryTask updatePll;
+
+void updatePllFunction(){
+//	rt_printf("now\n");
+	gPRU->setGPIOTestPin();
+	gAudioCodec->setPllD(D);
+	gPRU->clearGPIOTestPin();
+}
+
+bool setup(BeagleRTContext *context, void *userData)
+{
+	scope.setup(context->audioSampleRate);  //call this once in setup to initialise the scope
+	 
+	gInverseSampleRate = 1.0/context->audioSampleRate;
+	
+	gPhase1 = 0.0;
+	gPhase2 = 0.0;
+	
+	gFrequency1 = 200.0;
+	gFrequency2 = 201.0;
+	updatePll=BeagleRT_createAuxiliaryTask(&updatePllFunction, 98, "update PLL");
+	for(int n=0; n<delayLength; n++){
+		delay[n]=0;
+	}
+	return true; 
+}
+
+// render() is called regularly at the highest priority by the audio engine.
+// Input and output are given from the audio hardware and the other
+// ADCs and DACs (if available). If only audio is available, numMatrixFrames
+// will be 0.
+
+void render(BeagleRTContext *context, void *userData)
+{
+	static int count=0;
+	static float lfoPhase=0;
+	static float feedback=0;
+	int updateRate=8;
+	if((count&(updateRate-1))==0 && digitalReadFrame(context,0,P8_07)==GPIO_HIGH){
+		float amplitude=context->analogIn[0]/0.84*4990;
+		float rate=context->analogIn[1]*20+0.1;
+		lfoPhase+=rate*2*M_PI*updateRate*context->analogFrames/context->audioSampleRate;
+		D=amplitude+amplitude*sinf(lfoPhase);
+		BeagleRT_scheduleAuxiliaryTask(updatePll);
+		if((count&255)==0){
+			rt_printf("gpio: %d\n",digitalReadFrame(context,0,P8_07));
+			rt_printf("D: %.0f\n", D);
+			rt_printf("rate: %f\n", rate/2);
+			rt_printf("amplitude: %.3f\n", amplitude);
+			rt_printf("feedback: %.3f\n\n", feedback);
+		}
+	}
+	count++;
+
+	for(unsigned int n = 0; n < context->audioFrames; n++) {
+		feedback=context->analogIn[n/2*context->analogChannels+2]/0.84*1.2;
+		if(digitalReadFrame(context,n,P8_08)==GPIO_LOW)
+			feedback=0;
+	    delay[writePointer++]=context->audioIn[n*context->audioChannels+0] + delay[readPointer]*feedback;
+		context->audioOut[n*context->audioChannels+0]=context->audioIn[n*context->audioChannels+0]+delay[readPointer++];
+//		context->audioOut[n*context->audioChannels+1]=sinf(gPhase1);
+		context->analogOut[n/2*context->analogChannels+0]=D/10000;
+		if(writePointer>=delayLength)
+			writePointer-=delayLength;
+		if(readPointer>=delayLength)
+			readPointer-=delayLength;
+
+		gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate;
+	    gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
+		if(gPhase1 > 2.0 * M_PI)
+			gPhase1 -= 2.0 * M_PI;
+		if(gPhase2 > 2.0 * M_PI)
+			gPhase2 -= 2.0 * M_PI;
+		
+	}
+}
+
+// cleanup_render() is called once at the end, after the audio has stopped.
+// Release any resources that were allocated in initialise_render().
+
+void cleanup(BeagleRTContext *context, void *userData)
+{
+    
+}