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@152
|
7 #include <Pid.h>
|
giuliomoro@94
|
8
|
giuliomoro@94
|
9 float gPhase1, gPhase2;
|
giuliomoro@94
|
10 float gFrequency1, gFrequency2;
|
giuliomoro@94
|
11 float gInverseSampleRate;
|
giuliomoro@94
|
12
|
giuliomoro@128
|
13 //Scope scope(2); //create a scope object with 2 channels
|
giuliomoro@135
|
14 //NetworkSend networkSend;
|
giuliomoro@94
|
15
|
giuliomoro@94
|
16 // initialise_render() is called once before the audio rendering starts.
|
giuliomoro@94
|
17 // Use it to perform any initialisation and allocation which is dependent
|
giuliomoro@94
|
18 // on the period size or sample rate.
|
giuliomoro@94
|
19 //
|
giuliomoro@94
|
20 // userData holds an opaque pointer to a data structure that was passed
|
giuliomoro@94
|
21 // in from the call to initAudio().
|
giuliomoro@94
|
22 //
|
giuliomoro@94
|
23 // Return true on success; returning false halts the program.
|
giuliomoro@135
|
24 //ReceiveAudioThread receiveAudio0;
|
giuliomoro@128
|
25 //ReceiveAudioThread receiveAudio1;
|
giuliomoro@132
|
26 ClockSynchronizer clockSynchronizer;
|
giuliomoro@132
|
27 extern I2c_Codec* gAudioCodec;
|
giuliomoro@135
|
28 VirtualClock virtualClock;
|
giuliomoro@135
|
29 ClockSyncThread clockSyncThread;
|
giuliomoro@141
|
30 AuxiliaryTask testTime;
|
giuliomoro@141
|
31 void testTimeFunction(){
|
giuliomoro@141
|
32 rt_printf("time=[");
|
giuliomoro@141
|
33 while(!gShouldStop){
|
giuliomoro@141
|
34 rt_task_sleep(50000*1e3);
|
giuliomoro@141
|
35 rt_printf("%f, ", virtualClock.getNow());
|
giuliomoro@141
|
36 rt_printf("%f, ", virtualClock.getPeriod());
|
giuliomoro@141
|
37 rt_task_sleep(20000);
|
giuliomoro@141
|
38 rt_printf("%f,", virtualClock.getNow());
|
giuliomoro@141
|
39 rt_printf("%f\n", virtualClock.getPeriod());
|
giuliomoro@141
|
40 }
|
giuliomoro@141
|
41 rt_printf("];");
|
giuliomoro@141
|
42 }
|
giuliomoro@94
|
43 bool setup(BeagleRTContext *context, void *userData)
|
giuliomoro@94
|
44 {
|
giuliomoro@135
|
45 // receiveAudio0.init(10000, context->audioFrames, 0);
|
giuliomoro@128
|
46 // receiveAudio1.init(10000, context->audioFrames, 1);
|
giuliomoro@131
|
47
|
giuliomoro@128
|
48 // scope.setup(); //call this once in setup to initialise the scope
|
giuliomoro@128
|
49 // scope.setPort(0, 9999);
|
giuliomoro@128
|
50 // scope.setPort(1, 10000);
|
giuliomoro@135
|
51 // networkSend.setup(context->audioSampleRate, context->audioFrames, 0, 9999, "192.168.7.1");
|
giuliomoro@141
|
52 // clockSynchronizer.setup();
|
giuliomoro@149
|
53 virtualClock.init(context->audioFrames / context->audioSampleRate * 1e6);
|
giuliomoro@135
|
54 clockSyncThread.init(true, 5000, virtualClock); //start as slave
|
giuliomoro@94
|
55 gInverseSampleRate = 1.0/context->audioSampleRate;
|
giuliomoro@94
|
56
|
giuliomoro@94
|
57 gPhase1 = 0.0;
|
giuliomoro@94
|
58 gPhase2 = 0.0;
|
giuliomoro@94
|
59
|
giuliomoro@152
|
60 gFrequency1 = 441.0;
|
giuliomoro@94
|
61 gFrequency2 = 201.0;
|
giuliomoro@111
|
62
|
giuliomoro@141
|
63 // testTime=BeagleRT_createAuxiliaryTask(testTimeFunction, 80, "testTimeTask");
|
giuliomoro@94
|
64 return true;
|
giuliomoro@94
|
65 }
|
giuliomoro@94
|
66
|
giuliomoro@94
|
67 // render() is called regularly at the highest priority by the audio engine.
|
giuliomoro@94
|
68 // Input and output are given from the audio hardware and the other
|
giuliomoro@94
|
69 // ADCs and DACs (if available). If only audio is available, numMatrixFrames
|
giuliomoro@94
|
70 // will be 0.
|
giuliomoro@152
|
71 extern Pid* gClockSyncPid;
|
giuliomoro@152
|
72 extern ClockSync* gClockSync;
|
giuliomoro@94
|
73 void render(BeagleRTContext *context, void *userData)
|
giuliomoro@94
|
74 {
|
giuliomoro@135
|
75 virtualClock.sync(context->audioFrames);
|
giuliomoro@109
|
76 static int count=0;
|
giuliomoro@141
|
77 if(count==0){
|
giuliomoro@141
|
78 // BeagleRT_scheduleAuxiliaryTask(testTime);
|
giuliomoro@141
|
79 clockSyncThread.startThread(); //make sure you uncomment .init in setup()
|
giuliomoro@141
|
80 }
|
giuliomoro@151
|
81 /*
|
giuliomoro@151
|
82 switch (count){
|
giuliomoro@151
|
83 case 5000:
|
giuliomoro@151
|
84 gAudioCodec->setAudioSamplingRate(44101);
|
giuliomoro@151
|
85 printf("0 0 0\n");
|
giuliomoro@151
|
86 break;
|
giuliomoro@151
|
87 case 10000:
|
giuliomoro@151
|
88 gAudioCodec->setAudioSamplingRate(44100);
|
giuliomoro@151
|
89 printf("0 0 0\n");
|
giuliomoro@151
|
90 break;
|
giuliomoro@151
|
91 case 15000:
|
giuliomoro@151
|
92 gAudioCodec->setAudioSamplingRate(44099);
|
giuliomoro@151
|
93 printf("0 0 0\n");
|
giuliomoro@151
|
94 break;
|
giuliomoro@151
|
95 case 20000:
|
giuliomoro@151
|
96 gAudioCodec->setAudioSamplingRate(44100);
|
giuliomoro@151
|
97 printf("0 0 0\n");
|
giuliomoro@151
|
98 count = 0;
|
giuliomoro@151
|
99 break;
|
giuliomoro@151
|
100 }
|
giuliomoro@151
|
101 */
|
giuliomoro@135
|
102 static float phase=0;
|
giuliomoro@144
|
103 float phaseInc=gFrequency1/44100.0*2*M_PI;
|
giuliomoro@135
|
104 // rt_printf("phaseInc: %f, phase: %f\n",phaseInc,phase);
|
giuliomoro@135
|
105 for(unsigned int n=0; n<context->audioFrames; n++){
|
giuliomoro@152
|
106 context->audioOut[n*2]=sinf(phase) > 0 ? 1 : -1;
|
giuliomoro@152
|
107 context->audioOut[n*2+1]=sinf(phase) > 0 ? 1 : -1;
|
giuliomoro@152
|
108 // context->audioOut[n*2]= context->audioIn[n*2];
|
giuliomoro@152
|
109 // context->audioOut[n*2+1]= context->audioIn[n*2+1];
|
giuliomoro@152
|
110 phase+=phaseInc;
|
giuliomoro@135
|
111 if(phase>=2*M_PI)
|
giuliomoro@135
|
112 phase-=2*M_PI;
|
giuliomoro@152
|
113 // context->audioOut[n*2+1]=rand()/(float)RAND_MAX;//context->audioIn[n*2];
|
giuliomoro@135
|
114 }
|
giuliomoro@152
|
115 gClockSyncPid->setProportionalGain(context->analogIn[0]*10);
|
giuliomoro@152
|
116 // gClockSyncPid->setIntegralGain(context->analogIn[1]);
|
giuliomoro@152
|
117 gClockSyncPid->setIntegralGain(0);
|
giuliomoro@152
|
118 // gClockSyncPid->setDerivativeGain(context->analogIn[2]);
|
giuliomoro@152
|
119 gClockSyncPid->setDerivativeGain(0);
|
giuliomoro@152
|
120 gClockSyncPid->setGlobalGain(context->analogIn[3]*1/0.828);
|
giuliomoro@152
|
121 for (int n = 0; n < context->analogFrames; n++){
|
giuliomoro@152
|
122 context->analogOut[n*context->analogChannels + 0] = (gClockSync->getOffset() )/ 100 + 0.5;
|
giuliomoro@152
|
123 context->analogOut[n*context->analogChannels + 1] = (gAudioCodec->getAudioSamplingRate()-44100)/20 + 0.5;
|
giuliomoro@152
|
124 }
|
giuliomoro@152
|
125 static bool pastSwitch = false;
|
giuliomoro@152
|
126 bool thisSwitch = context->analogIn[4]>0.5;
|
giuliomoro@152
|
127 if(thisSwitch && pastSwitch == false){
|
giuliomoro@152
|
128 rt_printf("--------------reset offset\n");
|
giuliomoro@152
|
129 virtualClock.addOffset(gClockSync->getIirOffset());
|
giuliomoro@152
|
130 }
|
giuliomoro@152
|
131 pastSwitch = thisSwitch;
|
giuliomoro@135
|
132 count++;
|
giuliomoro@135
|
133 /*
|
giuliomoro@132
|
134 // if((count&262143)==0){
|
giuliomoro@132
|
135 // static int nextCall=160000;
|
giuliomoro@135
|
136 if( ((count&(2047))==0)){
|
giuliomoro@132
|
137 // rt_printf("b %d\n", count);
|
giuliomoro@132
|
138 clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
|
giuliomoro@132
|
139 // nextCall=count+100000;
|
giuliomoro@132
|
140 // rt_printf("a %d\n", count);
|
giuliomoro@132
|
141 }
|
giuliomoro@132
|
142 // if(count == nextCall){
|
giuliomoro@132
|
143 // clockSynchronizer.update(networkSend.getTimestamp(), receiveAudio0.getTimestamp(), receiveAudio0.getLastTime());
|
giuliomoro@132
|
144 // }
|
giuliomoro@131
|
145 if(count==0){
|
giuliomoro@135
|
146 gAudioCodec->setAudioSamplingRate( 44100);
|
giuliomoro@133
|
147 rt_printf("startHread\n");
|
giuliomoro@131
|
148 ReceiveAudioThread::startThread();
|
giuliomoro@131
|
149 }
|
giuliomoro@94
|
150 for(unsigned int n = 0; n < context->audioFrames; n++) {
|
giuliomoro@94
|
151
|
giuliomoro@111
|
152 float chn0 = sinf(gPhase1);
|
giuliomoro@131
|
153 // float chn1 = sinf(gPhase2);
|
giuliomoro@111
|
154
|
giuliomoro@118
|
155 // float chn2 = context->audioIn[n*2 + 0];
|
giuliomoro@118
|
156 // float chn3 = context->audioIn[n*2 + 1];
|
giuliomoro@111
|
157
|
giuliomoro@118
|
158 // float chn4 = context->analogIn[(int)n/2*8 + 0];
|
giuliomoro@118
|
159 // float chn5 = context->analogIn[(int)n/2*8 + 1];
|
giuliomoro@132
|
160 // networkSend.log(context->audioIn[n]);
|
giuliomoro@132
|
161 networkSend.log(chn0);
|
giuliomoro@131
|
162 // scope.log(0, chn0);
|
giuliomoro@131
|
163 // scope.log(1, chn1);
|
giuliomoro@118
|
164 // scope.log(2, chn2);
|
giuliomoro@118
|
165 // scope.log(3, chn3);
|
giuliomoro@118
|
166 // scope.log(4, chn4);
|
giuliomoro@118
|
167 // scope.log(5, chn5);
|
giuliomoro@94
|
168
|
giuliomoro@94
|
169 // scope.log(chn1, chn2, chn3, chn4, chn5, chn6);
|
giuliomoro@94
|
170 //call this once every audio frame
|
giuliomoro@94
|
171 //takes six or fewer floats as parameters
|
giuliomoro@94
|
172 //first parameter becomes channel 1 etc
|
giuliomoro@94
|
173 //to view, click the 'oscilloscope' button on the toolbar while BeagleRT is NOT running
|
giuliomoro@94
|
174 //then click the big red button on the toolbar on this page
|
giuliomoro@94
|
175
|
giuliomoro@132
|
176 gPhase1 += 2.0 * M_PI * gFrequency1 * gInverseSampleRate * ((count&65535)/65535.0+1);
|
giuliomoro@118
|
177 gPhase2 += 2.0 * M_PI * gFrequency2 * gInverseSampleRate;
|
giuliomoro@94
|
178 if(gPhase1 > 2.0 * M_PI)
|
giuliomoro@94
|
179 gPhase1 -= 2.0 * M_PI;
|
giuliomoro@94
|
180 if(gPhase2 > 2.0 * M_PI)
|
giuliomoro@94
|
181 gPhase2 -= 2.0 * M_PI;
|
giuliomoro@135
|
182 int value=count%1000;
|
giuliomoro@135
|
183 context->audioOut[n*2]=value>=500 ? 1 : -1;
|
giuliomoro@135
|
184 context->audioOut[n*2+1]=context->audioOut[n*2];
|
giuliomoro@132
|
185 count++;
|
giuliomoro@94
|
186 }
|
giuliomoro@118
|
187 if(count>0){
|
giuliomoro@131
|
188 float samplingRateRatio=1;
|
giuliomoro@131
|
189 int channelsInDestinationBuffer=2;
|
giuliomoro@135
|
190 int channelToWriteTo=1;
|
giuliomoro@131
|
191 int length=receiveAudio0.getSamplesSrc(context->audioOut, context->audioFrames,
|
giuliomoro@131
|
192 samplingRateRatio, channelsInDestinationBuffer, channelToWriteTo);
|
giuliomoro@132
|
193 if((unsigned int)length!=context->audioFrames){
|
giuliomoro@131
|
194 rt_printf("Length mismatch: %d\n", length);
|
giuliomoro@131
|
195 }
|
giuliomoro@128
|
196 // int readPointer1=receiveAudio1.getSamplesSrc(context->audioOut, context->audioFrames, 1, 2, 1);
|
giuliomoro@119
|
197 }
|
giuliomoro@132
|
198 for(unsigned int n=0; n<context->audioFrames; n++){
|
giuliomoro@135
|
199 // context->audioOut[n*2+1]=context->audioOut[n*2];
|
giuliomoro@131
|
200 }
|
giuliomoro@135
|
201 */
|
giuliomoro@135
|
202
|
giuliomoro@94
|
203 }
|
giuliomoro@94
|
204
|
giuliomoro@94
|
205 // cleanup_render() is called once at the end, after the audio has stopped.
|
giuliomoro@94
|
206 // Release any resources that were allocated in initialise_render().
|
giuliomoro@94
|
207
|
giuliomoro@94
|
208 void cleanup(BeagleRTContext *context, void *userData)
|
giuliomoro@94
|
209 {
|
giuliomoro@94
|
210
|
giuliomoro@94
|
211 }
|