annotate projects/scope/render.cpp @ 141:44d07fa9bd03 ClockSync

Ultra-basic feedback for clock sync works^CIssues: response time of the IIR filter is too slow, requires PID and better filtering algorithm.
author Giulio Moro <giuliomoro@yahoo.it>
date Mon, 14 Sep 2015 15:42:11 +0100
parents e77e2e712fbc
children 55c1e591cb2e
rev   line source
giuliomoro@94 1 #include <BeagleRT.h>
giuliomoro@112 2 #include <NetworkSend.h>
giuliomoro@117 3 #include <ReceiveAudioThread.h>
giuliomoro@132 4 #include <ClockSynchronizer.h>
giuliomoro@94 5 #include <cmath>
giuliomoro@135 6 #include <ClockSyncThread.h>
giuliomoro@94 7
giuliomoro@94 8 float gPhase1, gPhase2;
giuliomoro@94 9 float gFrequency1, gFrequency2;
giuliomoro@94 10 float gInverseSampleRate;
giuliomoro@94 11
giuliomoro@128 12 //Scope scope(2); //create a scope object with 2 channels
giuliomoro@135 13 //NetworkSend networkSend;
giuliomoro@94 14
giuliomoro@94 15 // initialise_render() is called once before the audio rendering starts.
giuliomoro@94 16 // Use it to perform any initialisation and allocation which is dependent
giuliomoro@94 17 // on the period size or sample rate.
giuliomoro@94 18 //
giuliomoro@94 19 // userData holds an opaque pointer to a data structure that was passed
giuliomoro@94 20 // in from the call to initAudio().
giuliomoro@94 21 //
giuliomoro@94 22 // Return true on success; returning false halts the program.
giuliomoro@135 23 //ReceiveAudioThread receiveAudio0;
giuliomoro@128 24 //ReceiveAudioThread receiveAudio1;
giuliomoro@132 25 ClockSynchronizer clockSynchronizer;
giuliomoro@132 26 extern I2c_Codec* gAudioCodec;
giuliomoro@135 27 VirtualClock virtualClock;
giuliomoro@135 28 ClockSyncThread clockSyncThread;
giuliomoro@141 29 AuxiliaryTask testTime;
giuliomoro@141 30 void testTimeFunction(){
giuliomoro@141 31 rt_printf("time=[");
giuliomoro@141 32 while(!gShouldStop){
giuliomoro@141 33 rt_task_sleep(50000*1e3);
giuliomoro@141 34 rt_printf("%f, ", virtualClock.getNow());
giuliomoro@141 35 rt_printf("%f, ", virtualClock.getPeriod());
giuliomoro@141 36 rt_task_sleep(20000);
giuliomoro@141 37 rt_printf("%f,", virtualClock.getNow());
giuliomoro@141 38 rt_printf("%f\n", virtualClock.getPeriod());
giuliomoro@141 39 }
giuliomoro@141 40 rt_printf("];");
giuliomoro@141 41 }
giuliomoro@94 42 bool setup(BeagleRTContext *context, void *userData)
giuliomoro@94 43 {
giuliomoro@135 44 // receiveAudio0.init(10000, context->audioFrames, 0);
giuliomoro@128 45 // receiveAudio1.init(10000, context->audioFrames, 1);
giuliomoro@131 46
giuliomoro@128 47 // scope.setup(); //call this once in setup to initialise the scope
giuliomoro@128 48 // scope.setPort(0, 9999);
giuliomoro@128 49 // scope.setPort(1, 10000);
giuliomoro@135 50 // networkSend.setup(context->audioSampleRate, context->audioFrames, 0, 9999, "192.168.7.1");
giuliomoro@141 51 // clockSynchronizer.setup();
giuliomoro@135 52 virtualClock.init();
giuliomoro@135 53 clockSyncThread.init(true, 5000, virtualClock); //start as slave
giuliomoro@94 54 gInverseSampleRate = 1.0/context->audioSampleRate;
giuliomoro@94 55
giuliomoro@94 56 gPhase1 = 0.0;
giuliomoro@94 57 gPhase2 = 0.0;
giuliomoro@94 58
giuliomoro@94 59 gFrequency1 = 200.0;
giuliomoro@94 60 gFrequency2 = 201.0;
giuliomoro@111 61
giuliomoro@141 62 // testTime=BeagleRT_createAuxiliaryTask(testTimeFunction, 80, "testTimeTask");
giuliomoro@94 63 return true;
giuliomoro@94 64 }
giuliomoro@94 65
giuliomoro@94 66 // render() is called regularly at the highest priority by the audio engine.
giuliomoro@94 67 // Input and output are given from the audio hardware and the other
giuliomoro@94 68 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
giuliomoro@94 69 // will be 0.
giuliomoro@94 70
giuliomoro@94 71 void render(BeagleRTContext *context, void *userData)
giuliomoro@94 72 {
giuliomoro@135 73 virtualClock.sync(context->audioFrames);
giuliomoro@109 74 static int count=0;
giuliomoro@141 75 if(count==0){
giuliomoro@141 76 // BeagleRT_scheduleAuxiliaryTask(testTime);
giuliomoro@141 77 clockSyncThread.startThread(); //make sure you uncomment .init in setup()
giuliomoro@141 78 }
giuliomoro@135 79 static float phase=0;
giuliomoro@135 80 float phaseInc=200.0/44100.0*2*M_PI;
giuliomoro@135 81 // rt_printf("phaseInc: %f, phase: %f\n",phaseInc,phase);
giuliomoro@135 82 for(unsigned int n=0; n<context->audioFrames; n++){
giuliomoro@135 83 context->audioOut[n*2]=sinf(phaseInc);//context->audioIn[n*2];
giuliomoro@135 84 context->audioOut[n*2+1]=sinf(phaseInc);//context->audioIn[n*2];
giuliomoro@135 85 phase+=200.0/44100.0*2*M_PI;
giuliomoro@135 86 if(phase>=2*M_PI)
giuliomoro@135 87 phase-=2*M_PI;
giuliomoro@135 88 // context->audioOut[n*2+1]=rand()/(float)RAND_MAX;context->audioIn[n*2];
giuliomoro@135 89 }
giuliomoro@135 90 count++;
giuliomoro@135 91 /*
giuliomoro@132 92 // if((count&262143)==0){
giuliomoro@132 93 // static int nextCall=160000;
giuliomoro@135 94 if( ((count&(2047))==0)){
giuliomoro@132 95 // rt_printf("b %d\n", count);
giuliomoro@132 96 clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
giuliomoro@132 97 // nextCall=count+100000;
giuliomoro@132 98 // rt_printf("a %d\n", count);
giuliomoro@132 99 }
giuliomoro@132 100 // if(count == nextCall){
giuliomoro@132 101 // clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
giuliomoro@132 102 // }
giuliomoro@131 103 if(count==0){
giuliomoro@135 104 gAudioCodec->setAudioSamplingRate( 44100);
giuliomoro@133 105 rt_printf("startHread\n");
giuliomoro@131 106 ReceiveAudioThread::startThread();
giuliomoro@131 107 }
giuliomoro@94 108 for(unsigned int n = 0; n < context->audioFrames; n++) {
giuliomoro@94 109
giuliomoro@111 110 float chn0 = sinf(gPhase1);
giuliomoro@131 111 // float chn1 = sinf(gPhase2);
giuliomoro@111 112
giuliomoro@118 113 // float chn2 = context->audioIn[n*2 + 0];
giuliomoro@118 114 // float chn3 = context->audioIn[n*2 + 1];
giuliomoro@111 115
giuliomoro@118 116 // float chn4 = context->analogIn[(int)n/2*8 + 0];
giuliomoro@118 117 // float chn5 = context->analogIn[(int)n/2*8 + 1];
giuliomoro@132 118 // networkSend.log(context->audioIn[n]);
giuliomoro@132 119 networkSend.log(chn0);
giuliomoro@131 120 // scope.log(0, chn0);
giuliomoro@131 121 // scope.log(1, chn1);
giuliomoro@118 122 // scope.log(2, chn2);
giuliomoro@118 123 // scope.log(3, chn3);
giuliomoro@118 124 // scope.log(4, chn4);
giuliomoro@118 125 // scope.log(5, chn5);
giuliomoro@94 126
giuliomoro@94 127 // scope.log(chn1, chn2, chn3, chn4, chn5, chn6);
giuliomoro@94 128 //call this once every audio frame
giuliomoro@94 129 //takes six or fewer floats as parameters
giuliomoro@94 130 //first parameter becomes channel 1 etc
giuliomoro@94 131 //to view, click the 'oscilloscope' button on the toolbar while BeagleRT is NOT running
giuliomoro@94 132 //then click the big red button on the toolbar on this page
giuliomoro@94 133
giuliomoro@132 134 gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate * ((count&65535)/65535.0+1);
giuliomoro@118 135 gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
giuliomoro@94 136 if(gPhase1 > 2.0 * M_PI)
giuliomoro@94 137 gPhase1 -= 2.0 * M_PI;
giuliomoro@94 138 if(gPhase2 > 2.0 * M_PI)
giuliomoro@94 139 gPhase2 -= 2.0 * M_PI;
giuliomoro@135 140 int value=count%1000;
giuliomoro@135 141 context->audioOut[n*2]=value>=500 ? 1 : -1;
giuliomoro@135 142 context->audioOut[n*2+1]=context->audioOut[n*2];
giuliomoro@132 143 count++;
giuliomoro@94 144 }
giuliomoro@118 145 if(count>0){
giuliomoro@131 146 float samplingRateRatio=1;
giuliomoro@131 147 int channelsInDestinationBuffer=2;
giuliomoro@135 148 int channelToWriteTo=1;
giuliomoro@131 149 int length=receiveAudio0.getSamplesSrc(context->audioOut, context->audioFrames,
giuliomoro@131 150 samplingRateRatio, channelsInDestinationBuffer, channelToWriteTo);
giuliomoro@132 151 if((unsigned int)length!=context->audioFrames){
giuliomoro@131 152 rt_printf("Length mismatch: %d\n", length);
giuliomoro@131 153 }
giuliomoro@128 154 // int readPointer1=receiveAudio1.getSamplesSrc(context->audioOut, context->audioFrames, 1, 2, 1);
giuliomoro@119 155 }
giuliomoro@132 156 for(unsigned int n=0; n<context->audioFrames; n++){
giuliomoro@135 157 // context->audioOut[n*2+1]=context->audioOut[n*2];
giuliomoro@131 158 }
giuliomoro@135 159 */
giuliomoro@135 160
giuliomoro@94 161 }
giuliomoro@94 162
giuliomoro@94 163 // cleanup_render() is called once at the end, after the audio has stopped.
giuliomoro@94 164 // Release any resources that were allocated in initialise_render().
giuliomoro@94 165
giuliomoro@94 166 void cleanup(BeagleRTContext *context, void *userData)
giuliomoro@94 167 {
giuliomoro@94 168
giuliomoro@94 169 }