andrewm@0
|
1 /*
|
andrewm@0
|
2 * RTAudio.cpp
|
andrewm@0
|
3 *
|
andrewm@0
|
4 * Central control code for hard real-time audio on BeagleBone Black
|
andrewm@0
|
5 * using PRU and Xenomai Linux extensions. This code began as part
|
andrewm@0
|
6 * of the Hackable Instruments project (EPSRC) at Queen Mary University
|
andrewm@0
|
7 * of London, 2013-14.
|
andrewm@0
|
8 *
|
andrewm@0
|
9 * (c) 2014 Victor Zappi and Andrew McPherson
|
andrewm@0
|
10 * Queen Mary University of London
|
andrewm@0
|
11 */
|
andrewm@0
|
12
|
andrewm@0
|
13
|
andrewm@0
|
14 #include <stdio.h>
|
andrewm@0
|
15 #include <stdlib.h>
|
andrewm@0
|
16 #include <string.h>
|
andrewm@0
|
17 #include <strings.h>
|
andrewm@0
|
18 #include <math.h>
|
andrewm@0
|
19 #include <iostream>
|
andrewm@0
|
20 #include <signal.h> // interrupt handler
|
andrewm@0
|
21 #include <assert.h>
|
andrewm@0
|
22 #include <vector>
|
andrewm@0
|
23 #include <dirent.h> // to handle files in dirs
|
andrewm@0
|
24 #include <mntent.h> // to check if device is mounted
|
andrewm@0
|
25 #include <sys/mount.h> // mount()
|
andrewm@0
|
26 #include <sys/time.h> // elapsed time
|
andrewm@379
|
27 #include <ne10/NE10.h> // neon library
|
andrewm@0
|
28
|
andrewm@0
|
29 // thread priority
|
andrewm@0
|
30 #include <pthread.h>
|
andrewm@0
|
31 #include <sched.h>
|
andrewm@0
|
32
|
andrewm@0
|
33 // get_opt_long
|
andrewm@0
|
34 #include <getopt.h>
|
andrewm@0
|
35
|
giuliomoro@301
|
36 #include <Bela.h>
|
andrewm@0
|
37 #include "config.h"
|
andrewm@0
|
38 #include "sensors.h"
|
andrewm@0
|
39 #include "OscillatorBank.h"
|
andrewm@0
|
40 #include "StatusLED.h"
|
andrewm@0
|
41 #include "logger.h"
|
andrewm@0
|
42
|
andrewm@0
|
43 using namespace std;
|
andrewm@0
|
44
|
andrewm@0
|
45 //----------------------------------------
|
andrewm@0
|
46 // main variables
|
andrewm@0
|
47 //----------------------------------------
|
andrewm@0
|
48 vector<OscillatorBank*> gOscBanks;
|
andrewm@0
|
49 int gCurrentOscBank = 0;
|
andrewm@0
|
50 int gNextOscBank = 0;
|
andrewm@0
|
51 int oscBnkOversampling = 1; // oscillator bank frame oversampling
|
andrewm@0
|
52
|
andrewm@0
|
53 const int kStatusLEDPin = 30; // P9-11 controls status LED
|
andrewm@0
|
54 StatusLED gStatusLED;
|
andrewm@0
|
55
|
andrewm@0
|
56 pthread_t keyboardThread;
|
andrewm@0
|
57 pthread_t logThread;
|
andrewm@0
|
58
|
andrewm@0
|
59 // general settings
|
andrewm@0
|
60 int gVerbose = 0; // verbose flag
|
andrewm@0
|
61 bool forceKeyboard = true; // activate/deactivate keyboard control
|
andrewm@0
|
62 bool forceSensors = false; // activate/deactivate sensor control
|
andrewm@0
|
63 bool forceLog = true; // activate/deactivate log on boot partition
|
andrewm@0
|
64 bool useSD = true; // activate/deactivate file loading from SD [as opposed to emmc]
|
andrewm@0
|
65 bool useAudioTest = false; // activate/deactivate sensors and test audio only
|
andrewm@0
|
66
|
andrewm@0
|
67 // audio settings
|
andrewm@0
|
68 unsigned int gPeriodSize = 8; // period size for audio
|
andrewm@0
|
69 char* gPartialFilename = 0; // name of the partials file to load
|
andrewm@0
|
70 bool gAudioIn = false; // stereo audio in status
|
andrewm@0
|
71
|
andrewm@0
|
72 int touchSensor0Address = 0x0C; // I2C addresses of touch sensors
|
andrewm@0
|
73 int touchSensor1Address = 0x0B;
|
andrewm@15
|
74 int sensorType = 0;
|
andrewm@0
|
75
|
andrewm@0
|
76 char sdPath[256] = "/dev/mmcblk0p2"; // system path of the SD, partition 2
|
andrewm@0
|
77 char mountPath[256] = "/root/d-box/usersounds"; // mount point of SD partition 2 [where user files are]
|
andrewm@0
|
78 char gUserDirName[256] = "usersounds"; // Directory in which user analysis files can be found [dir of mountPath]
|
andrewm@68
|
79 char gDefaultDirName[256] = "/root/d-box/sounds"; // Directory in which built in analysis files can be found
|
andrewm@0
|
80 char *gDirName;
|
andrewm@0
|
81 bool gIsLoading = false;
|
andrewm@0
|
82 int fileCnt = 0;
|
andrewm@0
|
83 std::vector <std::string> files;
|
andrewm@0
|
84
|
andrewm@0
|
85 char gId = 'f'; // from 0 to 14, hexadecimal [0-d]! f means not set
|
andrewm@0
|
86 char gGroup = '2'; // 0 is no info, 1 info. 2 is not set
|
andrewm@0
|
87
|
andrewm@0
|
88 // audio in filter
|
andrewm@0
|
89 extern ne10_float32_t *filterState[2];
|
andrewm@0
|
90 extern ne10_float32_t *filterIn[2];
|
andrewm@0
|
91 extern ne10_float32_t *filterOut[2];
|
andrewm@0
|
92
|
andrewm@0
|
93 struct arg_data
|
andrewm@0
|
94 {
|
andrewm@0
|
95 int argc;
|
andrewm@0
|
96 char **argv;
|
andrewm@0
|
97 };
|
andrewm@0
|
98
|
andrewm@0
|
99 arg_data args;
|
andrewm@0
|
100
|
andrewm@0
|
101
|
andrewm@0
|
102 int readFiles()
|
andrewm@0
|
103 {
|
andrewm@0
|
104 if(useSD)
|
andrewm@0
|
105 gDirName = gUserDirName;
|
andrewm@0
|
106 else
|
andrewm@0
|
107 gDirName = gDefaultDirName;
|
andrewm@0
|
108 DIR *dir;
|
andrewm@0
|
109 struct dirent *ent;
|
andrewm@0
|
110
|
andrewm@0
|
111 // From http://stackoverflow.com/questions/612097/how-can-i-get-a-list-of-files-in-a-directory-using-c-or-c
|
andrewm@0
|
112 if ((dir = opendir (gDirName)) != NULL) {
|
andrewm@0
|
113 /* print all the files and directories within directory */
|
andrewm@0
|
114 while ((ent = readdir (dir)) != NULL) {
|
andrewm@0
|
115 // Ignore dotfiles and . and .. paths
|
andrewm@0
|
116 if(!strncmp(ent->d_name, ".", 1))
|
andrewm@0
|
117 continue;
|
andrewm@0
|
118
|
andrewm@0
|
119 //dbox_printf("%s\n", ent->d_name);
|
andrewm@0
|
120
|
andrewm@0
|
121 // take only .dbx and .txt files
|
andrewm@0
|
122 string name = string(ent->d_name);
|
andrewm@0
|
123 int len = name.length();
|
andrewm@0
|
124
|
andrewm@0
|
125 bool dboxFile = false;
|
andrewm@0
|
126
|
andrewm@0
|
127 if( (name[len-4]=='.') && (name[len-3]=='d') && (name[len-2]=='b') && (name[len-1]=='x') )
|
andrewm@0
|
128 dboxFile = true;
|
andrewm@0
|
129 if( (name[len-4]=='.') && (name[len-3]=='t') && (name[len-2]=='x') && (name[len-1]=='t') )
|
andrewm@0
|
130 dboxFile = true;
|
andrewm@0
|
131
|
andrewm@0
|
132 if(dboxFile)
|
andrewm@0
|
133 {
|
andrewm@0
|
134 fileCnt++;
|
andrewm@0
|
135 //dbox_printf("%s\n", ent->d_name);
|
andrewm@0
|
136 files.push_back( std::string( ent->d_name ) );
|
andrewm@0
|
137 }
|
andrewm@0
|
138 }
|
andrewm@0
|
139 closedir (dir);
|
andrewm@0
|
140 } else {
|
andrewm@0
|
141 /* could not open directory */
|
andrewm@0
|
142 printf("Could not open directory %s\n", gDirName);
|
andrewm@0
|
143 return 1;
|
andrewm@0
|
144 }
|
andrewm@0
|
145
|
andrewm@0
|
146 // order by name
|
andrewm@0
|
147 std::sort( files.begin(), files.end() );
|
andrewm@0
|
148
|
andrewm@0
|
149 if(fileCnt==0)
|
andrewm@0
|
150 {
|
andrewm@0
|
151 printf("No .dbx or .txt files in %s!\n", gDirName);
|
andrewm@0
|
152 return 1;
|
andrewm@0
|
153 }
|
andrewm@0
|
154
|
andrewm@0
|
155 return 0;
|
andrewm@0
|
156 }
|
andrewm@0
|
157
|
andrewm@0
|
158 /* Load sounds from the directory */
|
andrewm@0
|
159 void loadAudioFiles(bool loadFirstFile)
|
andrewm@0
|
160 {
|
andrewm@0
|
161 char fullFileName[256];
|
andrewm@0
|
162
|
andrewm@0
|
163 if(loadFirstFile) {
|
andrewm@0
|
164 strcpy(fullFileName, gDirName);
|
andrewm@0
|
165 strcat(fullFileName, "/");
|
andrewm@0
|
166 strncat(fullFileName, files[0].c_str(), 255 - strlen(gDirName));
|
andrewm@0
|
167 dbox_printf("Loading first file %s...\n", fullFileName);
|
andrewm@0
|
168 OscillatorBank *bank = new OscillatorBank(fullFileName);
|
andrewm@0
|
169 if(bank->initBank(oscBnkOversampling)) {
|
andrewm@0
|
170 bank->setLoopHops(100, bank->getLastHop());
|
andrewm@0
|
171 gOscBanks.push_back(bank);
|
andrewm@0
|
172 }
|
andrewm@0
|
173 }
|
andrewm@0
|
174
|
andrewm@0
|
175 else {
|
andrewm@0
|
176 for(int i=1; i<fileCnt; i++){
|
andrewm@0
|
177 strcpy(fullFileName, gDirName);
|
andrewm@0
|
178 strcat(fullFileName, "/");
|
andrewm@0
|
179 strncat(fullFileName, files[i].c_str(), 255 - strlen(gDirName));
|
andrewm@0
|
180 dbox_printf("Loading file %s...\n", fullFileName);
|
andrewm@0
|
181 OscillatorBank *bank = new OscillatorBank(fullFileName);
|
andrewm@0
|
182 if(bank->initBank(oscBnkOversampling)) {
|
andrewm@0
|
183 bank->setLoopHops(100, bank->getLastHop());
|
andrewm@0
|
184 gOscBanks.push_back(bank);
|
andrewm@0
|
185 }
|
andrewm@0
|
186 }
|
andrewm@0
|
187 }
|
andrewm@0
|
188 }
|
andrewm@0
|
189
|
andrewm@0
|
190 // adapted from http://program-nix.blogspot.co.uk/2008/08/c-language-check-filesystem-is-mounted.html
|
andrewm@0
|
191 int checkIfMounted (char * dev_path)
|
andrewm@0
|
192 {
|
andrewm@0
|
193 FILE * mtab = NULL;
|
andrewm@0
|
194 struct mntent * part = NULL;
|
andrewm@0
|
195 int is_mounted = 0;
|
andrewm@0
|
196
|
andrewm@0
|
197 if ( ( mtab = setmntent ("/etc/mtab", "r") ) != NULL)
|
andrewm@0
|
198 {
|
andrewm@0
|
199 while ( ( part = getmntent ( mtab) ) != NULL)
|
andrewm@0
|
200 {
|
andrewm@0
|
201 if ( ( part->mnt_fsname != NULL ) && ( strcmp ( part->mnt_fsname, dev_path ) ) == 0 )
|
andrewm@0
|
202 is_mounted = 1;
|
andrewm@0
|
203 }
|
andrewm@0
|
204 endmntent(mtab);
|
andrewm@0
|
205 }
|
andrewm@0
|
206 return is_mounted;
|
andrewm@0
|
207 }
|
andrewm@0
|
208
|
andrewm@0
|
209 int mountSDuserPartition()
|
andrewm@0
|
210 {
|
andrewm@0
|
211 if(checkIfMounted(sdPath))
|
andrewm@0
|
212 {
|
andrewm@0
|
213 printf("device %s already mounted, fair enough, let's move on\n", sdPath);
|
andrewm@0
|
214 return 0;
|
andrewm@0
|
215 }
|
andrewm@0
|
216 // if mount rootfs from SD [rootfs eMMC not used] or from eMMC via properly formatted SD [SD rootfs used as storage volume]
|
andrewm@0
|
217 // we always use rootfs on SD as storage volume ----> "/dev/mmcblk0p2"
|
andrewm@0
|
218 int ret = mount(sdPath, "/root/d-box/usersounds", "vfat", 0, NULL);
|
andrewm@0
|
219 if (ret!=0)
|
andrewm@0
|
220 {
|
andrewm@0
|
221 printf("Error in mount...%s\n", strerror(ret));
|
andrewm@0
|
222 return 1;
|
andrewm@0
|
223 }
|
andrewm@0
|
224 return 0;
|
andrewm@0
|
225 }
|
andrewm@0
|
226
|
andrewm@0
|
227 int initSoundFiles()
|
andrewm@0
|
228 {
|
andrewm@0
|
229 if(gVerbose==1)
|
andrewm@0
|
230 cout << "---------------->Init Audio Thread" << endl;
|
andrewm@0
|
231
|
andrewm@0
|
232 if(useSD)
|
andrewm@0
|
233 {
|
andrewm@0
|
234 // mount the SD partition where user sounds are located
|
andrewm@0
|
235 // [this is p2, p1 is already mounted and we will log data there]
|
andrewm@0
|
236 if(mountSDuserPartition()!=0)
|
andrewm@0
|
237 return -1;
|
andrewm@0
|
238 }
|
andrewm@0
|
239
|
andrewm@0
|
240 gIsLoading = true;
|
andrewm@0
|
241
|
andrewm@0
|
242 // read files from SD and order them alphabetically
|
andrewm@0
|
243 if(readFiles()!=0)
|
andrewm@0
|
244 return 1;
|
andrewm@0
|
245
|
andrewm@0
|
246 // load first file into oscBank
|
andrewm@0
|
247 loadAudioFiles(true);
|
andrewm@0
|
248
|
andrewm@0
|
249 return 0;
|
andrewm@0
|
250 }
|
andrewm@0
|
251
|
andrewm@0
|
252 //---------------------------------------------------------------------------------------------------------
|
andrewm@0
|
253
|
andrewm@0
|
254 // Handle Ctrl-C
|
andrewm@0
|
255 void interrupt_handler(int var)
|
andrewm@0
|
256 {
|
andrewm@0
|
257 // kill keyboard thread mercilessly
|
andrewm@0
|
258 if(forceKeyboard)
|
andrewm@0
|
259 pthread_cancel(keyboardThread);
|
andrewm@0
|
260
|
andrewm@0
|
261 gShouldStop = true;
|
andrewm@0
|
262 }
|
andrewm@0
|
263
|
andrewm@0
|
264
|
giuliomoro@301
|
265 void parseArguments(arg_data args, BelaInitSettings *settings)
|
andrewm@0
|
266 {
|
andrewm@0
|
267 // Default filename;
|
andrewm@0
|
268 gPartialFilename = strdup("D-Box_sound_250_60_40_h88_2.txt");
|
andrewm@0
|
269
|
andrewm@50
|
270 const int kOptionAudioTest = 1000;
|
andrewm@50
|
271
|
andrewm@0
|
272 // TODO: complete this
|
andrewm@0
|
273 struct option long_option[] =
|
andrewm@0
|
274 {
|
andrewm@0
|
275 {"help", 0, NULL, 'h'},
|
andrewm@0
|
276 {"audioin", 1, NULL, 'i'},
|
andrewm@0
|
277 {"file", 1, NULL, 'f'},
|
andrewm@0
|
278 {"keyboard", 1, NULL, 'k'},
|
andrewm@50
|
279 {"audio-test", 0, NULL, kOptionAudioTest},
|
andrewm@50
|
280 {"sensor-type", 1, NULL, 't'},
|
andrewm@50
|
281 {"sensor0", 1, NULL, 'q'},
|
andrewm@50
|
282 {"sensor1", 1, NULL, 'r'},
|
andrewm@0
|
283 {"log", 1, NULL, 'l'},
|
andrewm@0
|
284 {"usesd", 1, NULL, 'u'},
|
andrewm@0
|
285 {"oversamp", 1, NULL, 'o'},
|
andrewm@0
|
286 {"boxnumber", 1, NULL, 'n'},
|
andrewm@0
|
287 {"group", 1, NULL, 'g'},
|
andrewm@0
|
288 {NULL, 0, NULL, 0},
|
andrewm@0
|
289 };
|
andrewm@0
|
290 int morehelp = 0;
|
andrewm@0
|
291 int tmp = -1;
|
andrewm@0
|
292
|
giuliomoro@301
|
293 Bela_defaultSettings(settings);
|
andrewm@5
|
294
|
andrewm@0
|
295 while (1)
|
andrewm@0
|
296 {
|
andrewm@0
|
297 int c;
|
giuliomoro@301
|
298 if ((c = Bela_getopt_long(args.argc, args.argv, "hf:ki:sq:r:t:l:u:o:n:g:", long_option, settings)) < 0)
|
andrewm@0
|
299 break;
|
andrewm@0
|
300 switch (c)
|
andrewm@0
|
301 {
|
andrewm@0
|
302 case 'h':
|
andrewm@0
|
303 morehelp++;
|
andrewm@0
|
304 break;
|
andrewm@0
|
305 case 'f':
|
andrewm@0
|
306 free(gPartialFilename);
|
andrewm@0
|
307 gPartialFilename = strdup(optarg);
|
andrewm@0
|
308 break;
|
andrewm@0
|
309 case 'k':
|
andrewm@0
|
310 forceKeyboard = true;
|
andrewm@0
|
311 break;
|
andrewm@0
|
312 case 'i':
|
andrewm@0
|
313 gAudioIn = (atoi(optarg)==0) ? false : true;
|
andrewm@0
|
314 break;
|
andrewm@0
|
315 case 's':
|
andrewm@0
|
316 forceSensors = true;
|
andrewm@0
|
317 break;
|
andrewm@50
|
318 case kOptionAudioTest:
|
andrewm@0
|
319 useAudioTest = true;
|
andrewm@0
|
320 break;
|
andrewm@50
|
321 case 't':
|
andrewm@15
|
322 sensorType = atoi(optarg);
|
andrewm@0
|
323 break;
|
andrewm@50
|
324 case 'q':
|
andrewm@0
|
325 touchSensor0Address = atoi(optarg);
|
andrewm@0
|
326 break;
|
andrewm@50
|
327 case 'r':
|
andrewm@0
|
328 touchSensor1Address = atoi(optarg);
|
andrewm@0
|
329 break;
|
andrewm@0
|
330 case 'l':
|
andrewm@0
|
331 tmp = atoi(optarg);
|
andrewm@0
|
332 if(tmp==0)
|
andrewm@0
|
333 forceLog = false;
|
andrewm@0
|
334 else if(tmp>0)
|
andrewm@0
|
335 forceLog = true;
|
andrewm@0
|
336 break;
|
andrewm@0
|
337 case 'u':
|
andrewm@0
|
338 tmp = atoi(optarg);
|
andrewm@0
|
339 if(tmp==0)
|
andrewm@0
|
340 useSD = false;
|
andrewm@0
|
341 else if(tmp>0)
|
andrewm@0
|
342 useSD = true;
|
andrewm@0
|
343 break;
|
andrewm@0
|
344 case 'o':
|
andrewm@0
|
345 oscBnkOversampling = atoi(optarg);
|
andrewm@0
|
346 break;
|
andrewm@0
|
347 case 'n':
|
andrewm@0
|
348 gId = *optarg;
|
andrewm@0
|
349 cout << "-set box number to: " << gId << endl;
|
andrewm@0
|
350 break;
|
andrewm@0
|
351 case 'g':
|
andrewm@0
|
352 gGroup = *optarg;
|
andrewm@0
|
353 cout << "-set group to: " << gId << endl;
|
andrewm@0
|
354 break;
|
andrewm@0
|
355 default:
|
andrewm@0
|
356 break;
|
andrewm@0
|
357 }
|
andrewm@0
|
358 }
|
andrewm@5
|
359
|
andrewm@5
|
360 gPeriodSize = settings->periodSize;
|
andrewm@5
|
361 gVerbose = settings->verbose;
|
andrewm@0
|
362 }
|
andrewm@0
|
363
|
andrewm@0
|
364 int main(int argc, char *argv[])
|
andrewm@0
|
365 {
|
giuliomoro@301
|
366 BelaInitSettings settings; // Standard audio settings
|
andrewm@0
|
367 RT_TASK rtSensorThread;
|
andrewm@0
|
368 const char rtSensorThreadName[] = "dbox-sensor";
|
andrewm@0
|
369 int oscBankHopSize;
|
andrewm@0
|
370
|
andrewm@0
|
371 // Parse command-line arguments
|
andrewm@0
|
372 args.argc = argc;
|
andrewm@0
|
373 args.argv = argv;
|
andrewm@5
|
374 parseArguments(args, &settings);
|
andrewm@0
|
375
|
giuliomoro@301
|
376 Bela_setVerboseLevel(gVerbose);
|
andrewm@0
|
377 if(gVerbose == 1 && useAudioTest)
|
andrewm@0
|
378 cout << "main() : running in audio test mode" << endl;
|
andrewm@0
|
379
|
andrewm@0
|
380 // Load sound files from directory
|
andrewm@0
|
381 if(initSoundFiles() != 0)
|
andrewm@0
|
382 return -1;
|
andrewm@0
|
383
|
andrewm@0
|
384 oscBankHopSize = gOscBanks[gCurrentOscBank]->getHopSize()/gOscBanks[gCurrentOscBank]->getMinSpeed();
|
andrewm@0
|
385
|
andrewm@0
|
386 // Initialise the audio device
|
giuliomoro@301
|
387 if(Bela_initAudio(&settings, &oscBankHopSize) != 0)
|
andrewm@0
|
388 return -1;
|
andrewm@0
|
389
|
andrewm@0
|
390 // Initialise the status LED
|
andrewm@0
|
391 if(!gStatusLED.init(kStatusLEDPin)) {
|
andrewm@0
|
392 if(gVerbose)
|
andrewm@0
|
393 cout << "Couldn't initialise status LED pin\n";
|
andrewm@0
|
394 }
|
andrewm@0
|
395
|
andrewm@0
|
396 // Free file name string which is no longer needed
|
andrewm@0
|
397 if(gPartialFilename != 0)
|
andrewm@0
|
398 free(gPartialFilename);
|
andrewm@0
|
399
|
andrewm@0
|
400 if(!useAudioTest) {
|
andrewm@15
|
401 if(initSensorLoop(touchSensor0Address, touchSensor1Address, sensorType) != 0)
|
andrewm@0
|
402 return -1;
|
andrewm@0
|
403 }
|
andrewm@0
|
404
|
andrewm@0
|
405 if(gVerbose == 1)
|
andrewm@0
|
406 cout << "main() : creating audio thread" << endl;
|
andrewm@0
|
407
|
giuliomoro@301
|
408 if(Bela_startAudio()) {
|
andrewm@0
|
409 cout << "Error: unable to start real-time audio" << endl;
|
andrewm@0
|
410 return -1;
|
andrewm@0
|
411 }
|
andrewm@0
|
412
|
andrewm@0
|
413 // LED on...
|
andrewm@0
|
414 gStatusLED.on();
|
andrewm@0
|
415
|
andrewm@0
|
416 if(forceSensors && !useAudioTest) {
|
andrewm@0
|
417 if(gVerbose==1)
|
andrewm@0
|
418 cout << "main() : creating control thread" << endl;
|
andrewm@0
|
419
|
andrewm@303
|
420 if(rt_task_create(&rtSensorThread, rtSensorThreadName, 0, BELA_AUDIO_PRIORITY - 5, T_JOINABLE | T_FPU)) {
|
andrewm@0
|
421 cout << "Error:unable to create Xenomai control thread" << endl;
|
andrewm@0
|
422 return -1;
|
andrewm@0
|
423 }
|
andrewm@0
|
424 if(rt_task_start(&rtSensorThread, &sensorLoop, 0)) {
|
andrewm@0
|
425 cout << "Error:unable to start Xenomai control thread" << endl;
|
andrewm@0
|
426 return -1;
|
andrewm@0
|
427 }
|
andrewm@0
|
428 }
|
andrewm@0
|
429
|
andrewm@0
|
430 if(forceKeyboard) {
|
andrewm@0
|
431 if(gVerbose==1)
|
andrewm@0
|
432 cout << "main() : creating keyboard thread" << endl;
|
andrewm@0
|
433
|
andrewm@0
|
434 if ( pthread_create(&keyboardThread, NULL, keyboardLoop, NULL) ) {
|
andrewm@0
|
435 cout << "Error:unable to create keyboard thread" << endl;
|
andrewm@0
|
436 return -1;
|
andrewm@0
|
437 }
|
andrewm@0
|
438 }
|
andrewm@0
|
439
|
andrewm@0
|
440 if(forceLog) {
|
andrewm@0
|
441 if(gVerbose==1)
|
andrewm@0
|
442 cout << "main() : creating log thread" << endl;
|
andrewm@0
|
443
|
andrewm@0
|
444 if(initLogLoop()!=0) {
|
andrewm@0
|
445 cout << "Error:unable to create log thread" << endl;
|
andrewm@0
|
446 return -1;
|
andrewm@0
|
447 }
|
andrewm@0
|
448
|
andrewm@0
|
449 if ( pthread_create(&logThread, NULL, logLoop, NULL) ) {
|
andrewm@0
|
450 cout << "Error:unable to create keyboard thread" << endl;
|
andrewm@0
|
451 return -1;
|
andrewm@0
|
452 }
|
andrewm@0
|
453 }
|
andrewm@0
|
454
|
andrewm@15
|
455 // Set up interrupt handler to catch Control-C and SIGTERM
|
andrewm@0
|
456 signal(SIGINT, interrupt_handler);
|
andrewm@15
|
457 signal(SIGTERM, interrupt_handler);
|
andrewm@0
|
458
|
andrewm@0
|
459 // load all other files into oscBanks
|
andrewm@0
|
460 loadAudioFiles(false);
|
andrewm@0
|
461 cout << "Finished loading analysis files\n";
|
andrewm@0
|
462 gIsLoading = false;
|
andrewm@0
|
463
|
andrewm@0
|
464 // Run until told to stop
|
andrewm@0
|
465 while(!gShouldStop) {
|
andrewm@0
|
466 usleep(100000);
|
andrewm@0
|
467 }
|
andrewm@0
|
468
|
giuliomoro@301
|
469 Bela_stopAudio();
|
andrewm@0
|
470
|
andrewm@0
|
471 if(!useAudioTest)
|
andrewm@0
|
472 rt_task_join(&rtSensorThread);
|
andrewm@0
|
473
|
giuliomoro@301
|
474 Bela_cleanupAudio();
|
andrewm@0
|
475
|
andrewm@0
|
476 pthread_join( keyboardThread, NULL);
|
andrewm@0
|
477 pthread_join( logThread, NULL);
|
andrewm@0
|
478
|
andrewm@0
|
479 for(unsigned int i = 0; i < gOscBanks.size(); i++)
|
andrewm@0
|
480 delete gOscBanks[i];
|
andrewm@0
|
481
|
andrewm@0
|
482 NE10_FREE(filterState[0]);
|
andrewm@0
|
483 NE10_FREE(filterState[1]);
|
andrewm@0
|
484 NE10_FREE(filterIn[0]);
|
andrewm@0
|
485 NE10_FREE(filterIn[1]);
|
andrewm@0
|
486 NE10_FREE(filterOut[0]);
|
andrewm@0
|
487 NE10_FREE(filterOut[1]);
|
andrewm@0
|
488
|
andrewm@0
|
489 printf("Program ended\nBye bye\n");
|
andrewm@0
|
490 return 0;
|
andrewm@0
|
491 }
|