Ignore .o, .a, and .svg files.
[Faustine.git] / interpretor / faust-0.9.47mr3 / benchmark / coreaudio-gtk-bench.cpp
1 /* link with : "" */
2 #include <stdlib.h>
3 #include <libgen.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <limits.h>
7 #include <math.h>
8 #include <errno.h>
9 #include <time.h>
10 #include <sys/ioctl.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <pwd.h>
14 #include <sys/types.h>
15 #include <sys/time.h>
16 #include <assert.h>
17 #include <gtk/gtk.h>
18 #include <pthread.h>
19 #include <sys/wait.h>
20 #include <list>
21
22 #include <iostream>
23 #include <fstream>
24 #include <vector>
25 #include <algorithm>
26
27 #include <AudioToolbox/AudioConverter.h>
28 #include <CoreAudio/CoreAudio.h>
29 #include <AudioUnit/AudioUnit.h>
30 #include <CoreServices/CoreServices.h>
31
32
33 using namespace std;
34
35 // handle 32/64 bits int size issues
36
37 #ifdef __x86_64__
38
39 #define uint32 unsigned int
40 #define uint64 unsigned long int
41
42 #define int32 int
43 #define int64 long int
44
45 #else
46
47 #define uint32 unsigned int
48 #define uint64 unsigned long long int
49
50 #define int32 int
51 #define int64 long long int
52 #endif
53
54 // check 32/64 bits issues are correctly handled
55
56 #define CHECKINTSIZE \
57 assert(sizeof(int32)==4);\
58 assert(sizeof(int64)==8);
59
60
61
62
63 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
64 // flags to avoid costly denormals
65 #ifdef __SSE__
66 #include <xmmintrin.h>
67 #ifdef __SSE2__
68 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
69 #else
70 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
71 #endif
72 #else
73 #define AVOIDDENORMALS
74 #endif
75
76 //#define BENCHMARKMODE
77
78 // g++ -Wall -O3 -lm -lpthread -lasound `gtk-config --cflags --libs` test.cpp -o test
79
80 #define check_error(err) if (err) { printf("%s:%d, alsa error %d : %s\n", __FILE__, __LINE__, err, snd_strerror(err)); exit(1); }
81 #define check_error_msg(err,msg) if (err) { fprintf(stderr, "%s:%d, %s : %s(%d)\n", __FILE__, __LINE__, msg, snd_strerror(err), err); exit(1); }
82 #define display_error_msg(err,msg) if (err) { fprintf(stderr, "%s:%d, %s : %s(%d)\n", __FILE__, __LINE__, msg, snd_strerror(err), err); }
83
84 #define max(x,y) (((x)>(y)) ? (x) : (y))
85 #define min(x,y) (((x)<(y)) ? (x) : (y))
86
87 // abs is now predefined
88 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
89
90
91 inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
92
93
94 inline int int2pow2 (int x) { int r=0; while ((1<<r)<x) r++; return r; }
95
96
97 /******************************************************************************
98 *******************************************************************************
99
100 VECTOR INTRINSICS
101
102 *******************************************************************************
103 *******************************************************************************/
104
105 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
106 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
107
108
109 <<includeIntrinsic>>
110
111 #define BENCHMARKMODE
112
113 #ifdef BENCHMARKMODE
114
115 /**
116 * Returns the number of clock cycles elapsed since the last reset
117 * of the processor
118 */
119 static __inline__ uint64 rdtsc(void)
120 {
121 union {
122 uint32 i32[2];
123 uint64 i64;
124 } count;
125
126 __asm__ __volatile__("rdtsc" : "=a" (count.i32[0]), "=d" (count.i32[1]));
127
128 return count.i64;
129 }
130
131 #define KSKIP 20
132 #define KMESURE 600
133
134 int mesure = 0;
135
136 // these values are used to determine the number of clocks in a second
137 uint64 firstRDTSC;
138 uint64 lastRDTSC;
139
140 // these tables contains the last KMESURE in clocks
141 uint64 starts[KMESURE];
142 uint64 stops [KMESURE];
143
144 #define STARTMESURE starts[mesure%KMESURE] = rdtsc();
145 #define STOPMESURE stops[mesure%KMESURE] = rdtsc(); mesure = mesure+1;
146
147 struct timeval tv1;
148 struct timeval tv2;
149
150 void openMesure()
151 {
152 struct timezone tz;
153 gettimeofday(&tv1, &tz);
154 firstRDTSC = rdtsc();
155 }
156
157 void closeMesure()
158 {
159 struct timezone tz;
160 gettimeofday(&tv2, &tz);
161 lastRDTSC = rdtsc();
162 }
163
164 /**
165 * return the number of RDTSC clocks per seconds
166 */
167 int64 rdtscpersec()
168 {
169 // If the environment variable CLOCKSPERSEC is defined
170 // we use it instead of our own measurement
171 char* str = getenv("CLOCKSPERSEC");
172 if (str) {
173 int64 cps = (int64) atoll(str);
174 if (cps > 1000000000) {
175 return cps;
176 } else {
177 return (lastRDTSC-firstRDTSC) / (tv2.tv_sec - tv1.tv_sec) ;
178 }
179 } else {
180 return (lastRDTSC-firstRDTSC) / (tv2.tv_sec - tv1.tv_sec) ;
181 }
182 }
183
184
185 /**
186 * Converts a duration, expressed in RDTSC clocks, into seconds
187 */
188 double rdtsc2sec( uint64 clk)
189 {
190 return double(clk) / double(rdtscpersec());
191 }
192
193 double rdtsc2sec( double clk)
194 {
195 return clk / double(rdtscpersec());
196 }
197
198
199 /**
200 * Converts RDTSC clocks into Megabytes/seconds according to the
201 * number of frames processed during the period, the number of channels
202 * and 4 bytes samples.
203 */
204 double megapersec(int frames, int chans, uint64 clk)
205 {
206 return double(frames*chans*4)/double(1024*1024*rdtsc2sec(clk));
207 }
208
209
210 /**
211 * Compute the mean value of a vector of measures
212 */
213 static uint64 meanValue( vector<uint64>::const_iterator a, vector<uint64>::const_iterator b)
214 {
215 uint64 r = 0;
216 unsigned int n = 0;
217 while (a!=b) { r += *a++; n++; }
218 return (n>0) ? r/n : 0;
219 }
220
221 /**
222 * Print the median value (in Megabytes/second) of KMESURE
223 * throughputs measurements
224 */
225 void printstats(const char* applname, int bsize, int ichans, int ochans)
226 {
227 assert(mesure > KMESURE);
228 vector<uint64> V(KMESURE);
229
230 for (int i = 0; i<KMESURE; i++) {
231 V[i] = stops[i] - starts[i];
232 }
233
234 sort(V.begin(), V.end());
235
236 // Mean of 10 best values (gives relatively stable results)
237 uint64 meavalx = meanValue(V.begin(), V.begin() + 10);
238
239 //printing
240 cout << megapersec(bsize, ichans+ochans, meavalx) << "\tMB/s"
241 << '\t' << applname
242 << '\t' << "(clocks/sec : " << rdtscpersec() << ")"
243 << endl;
244
245 }
246
247 #else
248
249 #define STARTMESURE
250 #define STOPMESURE
251
252 #endif
253
254
255
256 /******************************************************************************
257 *******************************************************************************
258
259 GRAPHIC USER INTERFACE (v2)
260 abstract interfaces
261
262 *******************************************************************************
263 *******************************************************************************/
264
265 #include <map>
266 #include <list>
267
268 using namespace std;
269
270 struct Meta : map<const char*, const char*>
271 {
272 void declare (const char* key, const char* value) { (*this)[key]=value; }
273 };
274
275
276 struct uiItem;
277 typedef void (*uiCallback)(float val, void* data);
278
279 /**
280 * Graphic User Interface : abstract definition
281 */
282
283 class UI
284 {
285 typedef list<uiItem*> clist;
286 typedef map<float*, clist*> zmap;
287
288 private:
289 static list<UI*> fGuiList;
290 zmap fZoneMap;
291 bool fStopped;
292
293 public:
294
295 UI() : fStopped(false) {
296 fGuiList.push_back(this);
297 }
298
299 virtual ~UI() {
300 // suppression de this dans fGuiList
301 }
302
303 // -- zone management
304
305 void registerZone(float* z, uiItem* c)
306 {
307 if (fZoneMap.find(z) == fZoneMap.end()) fZoneMap[z] = new clist();
308 fZoneMap[z]->push_back(c);
309 }
310
311 // -- saveState(filename) : save the value of every zone to a file
312
313 void saveState(const char* filename)
314 {
315 ofstream f(filename);
316
317 for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) {
318 f << *(i->first) << ' ';
319 }
320
321 f << endl;
322 f.close();
323 }
324
325 // -- recallState(filename) : load the value of every zone from a file
326
327 void recallState(const char* filename)
328 {
329 ifstream f(filename);
330 if (f.good()) {
331 for (zmap::iterator i=fZoneMap.begin(); i!=fZoneMap.end(); i++) {
332 f >> *(i->first);
333 }
334 }
335 f.close();
336 }
337
338 void updateAllZones();
339
340 void updateZone(float* z);
341
342 static void updateAllGuis()
343 {
344 list<UI*>::iterator g;
345 for (g = fGuiList.begin(); g != fGuiList.end(); g++) {
346 (*g)->updateAllZones();
347 }
348 }
349
350 // -- active widgets
351
352 virtual void addButton(const char* label, float* zone) = 0;
353 virtual void addToggleButton(const char* label, float* zone) = 0;
354 virtual void addCheckButton(const char* label, float* zone) = 0;
355 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
356 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
357 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
358
359 // -- passive widgets
360
361 virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
362 virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0;
363 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
364 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
365
366 void addCallback(float* zone, uiCallback foo, void* data);
367
368 // -- widget's layouts
369
370 virtual void openFrameBox(const char* label) = 0;
371 virtual void openTabBox(const char* label) = 0;
372 virtual void openHorizontalBox(const char* label) = 0;
373 virtual void openVerticalBox(const char* label) = 0;
374 virtual void closeBox() = 0;
375
376 virtual void show() = 0;
377 virtual void run() = 0;
378
379 void stop() { fStopped = true; }
380 bool stopped() { return fStopped; }
381
382 virtual void declare(float* zone, const char* key, const char* value) {}
383 };
384
385
386 /**
387 * User Interface Item: abstract definition
388 */
389
390 class uiItem
391 {
392 protected :
393
394 UI* fGUI;
395 float* fZone;
396 float fCache;
397
398 uiItem (UI* ui, float* zone) : fGUI(ui), fZone(zone), fCache(-123456.654321)
399 {
400 ui->registerZone(zone, this);
401 }
402
403
404 public :
405
406 virtual ~uiItem() {}
407
408 void modifyZone(float v)
409 {
410 fCache = v;
411 if (*fZone != v) {
412 *fZone = v;
413 fGUI->updateZone(fZone);
414 }
415 }
416
417 float cache() { return fCache; }
418 virtual void reflectZone() = 0;
419 };
420
421
422 /**
423 * Callback Item
424 */
425
426 struct uiCallbackItem : public uiItem
427 {
428 uiCallback fCallback;
429 void* fData;
430
431 uiCallbackItem(UI* ui, float* zone, uiCallback foo, void* data)
432 : uiItem(ui, zone), fCallback(foo), fData(data) {}
433
434 virtual void reflectZone() {
435 float v = *fZone;
436 fCache = v;
437 fCallback(v, fData);
438 }
439 };
440
441 /**
442 * Update all user items reflecting zone z
443 */
444
445 inline void UI::updateZone(float* z)
446 {
447 float v = *z;
448 clist* l = fZoneMap[z];
449 for (clist::iterator c = l->begin(); c != l->end(); c++) {
450 if ((*c)->cache() != v) (*c)->reflectZone();
451 }
452 }
453
454
455 /**
456 * Update all user items not up to date
457 */
458
459 inline void UI::updateAllZones()
460 {
461 for (zmap::iterator m = fZoneMap.begin(); m != fZoneMap.end(); m++) {
462 float* z = m->first;
463 clist* l = m->second;
464 float v = *z;
465 for (clist::iterator c = l->begin(); c != l->end(); c++) {
466 if ((*c)->cache() != v) (*c)->reflectZone();
467 }
468 }
469 }
470
471 inline void UI::addCallback(float* zone, uiCallback foo, void* data)
472 {
473 new uiCallbackItem(this, zone, foo, data);
474 };
475
476
477 /******************************************************************************
478 *******************************************************************************
479
480 GRAPHIC USER INTERFACE
481 gtk interface
482
483 *******************************************************************************
484 *******************************************************************************/
485
486 #include <gtk/gtk.h>
487
488 #define stackSize 256
489
490 // Insertion modes
491
492 #define kSingleMode 0
493 #define kBoxMode 1
494 #define kTabMode 2
495
496
497 class GTKUI : public UI
498 {
499 private :
500 static bool fInitialized;
501 static list<UI*> fGuiList;
502
503 protected :
504 GtkWidget* fWindow;
505 int fTop;
506 GtkWidget* fBox[stackSize];
507 int fMode[stackSize];
508 bool fStopped;
509
510 GtkWidget* addWidget(const char* label, GtkWidget* w);
511 virtual void pushBox(int mode, GtkWidget* w);
512
513
514 public :
515
516 static const gboolean expand = TRUE;
517 static const gboolean fill = TRUE;
518 static const gboolean homogene = FALSE;
519
520 GTKUI(char * name, int* pargc, char*** pargv);
521
522 // -- layout groups
523
524 virtual void openFrameBox(const char* label);
525 virtual void openTabBox(const char* label = "");
526 virtual void openHorizontalBox(const char* label = "");
527 virtual void openVerticalBox(const char* label = "");
528
529 virtual void closeBox();
530
531 // -- active widgets
532
533 virtual void addButton(const char* label, float* zone);
534 virtual void addToggleButton(const char* label, float* zone);
535 virtual void addCheckButton(const char* label, float* zone);
536 virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step);
537 virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step);
538 virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step);
539
540 // -- passive display widgets
541
542 virtual void addNumDisplay(const char* label, float* zone, int precision);
543 virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max);
544 virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max);
545 virtual void addVerticalBargraph(const char* label, float* zone, float min, float max);
546
547 virtual void show();
548 virtual void run();
549
550 };
551
552
553
554 /******************************************************************************
555 *******************************************************************************
556
557 GRAPHIC USER INTERFACE (v2)
558 gtk implementation
559
560 *******************************************************************************
561 *******************************************************************************/
562
563 // global static fields
564
565 bool GTKUI::fInitialized = false;
566 list<UI*> UI::fGuiList;
567
568
569
570 static gint delete_event( GtkWidget *widget, GdkEvent *event, gpointer data )
571 {
572 return FALSE;
573 }
574
575 static void destroy_event( GtkWidget *widget, gpointer data )
576 {
577 gtk_main_quit ();
578 }
579
580
581 GTKUI::GTKUI(char * name, int* pargc, char*** pargv)
582 {
583 if (!fInitialized) {
584 gtk_init(pargc, pargv);
585 fInitialized = true;
586 }
587
588 fWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
589 //gtk_container_set_border_width (GTK_CONTAINER (fWindow), 10);
590 gtk_window_set_title (GTK_WINDOW (fWindow), name);
591 gtk_signal_connect (GTK_OBJECT (fWindow), "delete_event", GTK_SIGNAL_FUNC (delete_event), NULL);
592 gtk_signal_connect (GTK_OBJECT (fWindow), "destroy", GTK_SIGNAL_FUNC (destroy_event), NULL);
593
594 fTop = 0;
595 fBox[fTop] = gtk_vbox_new (homogene, 4);
596 fMode[fTop] = kBoxMode;
597 gtk_container_add (GTK_CONTAINER (fWindow), fBox[fTop]);
598 fStopped = false;
599 }
600
601 // empilement des boites
602
603 void GTKUI::pushBox(int mode, GtkWidget* w)
604 {
605 assert(++fTop < stackSize);
606 fMode[fTop] = mode;
607 fBox[fTop] = w;
608 }
609
610 void GTKUI::closeBox()
611 {
612 assert(--fTop >= 0);
613 }
614
615
616 // les differentes boites
617
618 void GTKUI::openFrameBox(const char* label)
619 {
620 GtkWidget * box = gtk_frame_new (label);
621 //gtk_container_set_border_width (GTK_CONTAINER (box), 10);
622
623 pushBox(kSingleMode, addWidget(label, box));
624 }
625
626 void GTKUI::openTabBox(const char* label)
627 {
628 pushBox(kTabMode, addWidget(label, gtk_notebook_new ()));
629 }
630
631 void GTKUI::openHorizontalBox(const char* label)
632 {
633 GtkWidget * box = gtk_hbox_new (homogene, 4);
634 gtk_container_set_border_width (GTK_CONTAINER (box), 10);
635
636 if (fMode[fTop] != kTabMode && label[0] != 0) {
637 GtkWidget * frame = addWidget(label, gtk_frame_new (label));
638 gtk_container_add (GTK_CONTAINER(frame), box);
639 gtk_widget_show(box);
640 pushBox(kBoxMode, box);
641 } else {
642 pushBox(kBoxMode, addWidget(label, box));
643 }
644 }
645
646 void GTKUI::openVerticalBox(const char* label)
647 {
648 GtkWidget * box = gtk_vbox_new (homogene, 4);
649 gtk_container_set_border_width (GTK_CONTAINER (box), 10);
650
651 if (fMode[fTop] != kTabMode && label[0] != 0) {
652 GtkWidget * frame = addWidget(label, gtk_frame_new (label));
653 gtk_container_add (GTK_CONTAINER(frame), box);
654 gtk_widget_show(box);
655 pushBox(kBoxMode, box);
656 } else {
657 pushBox(kBoxMode, addWidget(label, box));
658 }
659 }
660
661 GtkWidget* GTKUI::addWidget(const char* label, GtkWidget* w)
662 {
663 switch (fMode[fTop]) {
664 case kSingleMode : gtk_container_add (GTK_CONTAINER(fBox[fTop]), w); break;
665 case kBoxMode : gtk_box_pack_start (GTK_BOX(fBox[fTop]), w, expand, fill, 0); break;
666 case kTabMode : gtk_notebook_append_page (GTK_NOTEBOOK(fBox[fTop]), w, gtk_label_new(label)); break;
667 }
668 gtk_widget_show (w);
669 return w;
670 }
671
672 // --------------------------- Press button ---------------------------
673
674 struct uiButton : public uiItem
675 {
676 GtkButton* fButton;
677
678 uiButton (UI* ui, float* zone, GtkButton* b) : uiItem(ui, zone), fButton(b) {}
679
680 static void pressed( GtkWidget *widget, gpointer data )
681 {
682 uiItem* c = (uiItem*) data;
683 c->modifyZone(1.0);
684 }
685
686 static void released( GtkWidget *widget, gpointer data )
687 {
688 uiItem* c = (uiItem*) data;
689 c->modifyZone(0.0);
690 }
691
692 virtual void reflectZone()
693 {
694 float v = *fZone;
695 fCache = v;
696 if (v > 0.0) gtk_button_pressed(fButton); else gtk_button_released(fButton);
697 }
698 };
699
700 void GTKUI::addButton(const char* label, float* zone)
701 {
702 *zone = 0.0;
703 GtkWidget* button = gtk_button_new_with_label (label);
704 addWidget(label, button);
705
706 uiButton* c = new uiButton(this, zone, GTK_BUTTON(button));
707
708 gtk_signal_connect (GTK_OBJECT (button), "pressed", GTK_SIGNAL_FUNC (uiButton::pressed), (gpointer) c);
709 gtk_signal_connect (GTK_OBJECT (button), "released", GTK_SIGNAL_FUNC (uiButton::released), (gpointer) c);
710
711 }
712
713 // --------------------------- Toggle Buttons ---------------------------
714
715 struct uiToggleButton : public uiItem
716 {
717 GtkToggleButton* fButton;
718
719 uiToggleButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {}
720
721 static void toggled (GtkWidget *widget, gpointer data)
722 {
723 float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0;
724 ((uiItem*)data)->modifyZone(v);
725 }
726
727 virtual void reflectZone()
728 {
729 float v = *fZone;
730 fCache = v;
731 gtk_toggle_button_set_active(fButton, v > 0.0);
732 }
733 };
734
735 void GTKUI::addToggleButton(const char* label, float* zone)
736 {
737 *zone = 0.0;
738 GtkWidget* button = gtk_toggle_button_new_with_label (label);
739 addWidget(label, button);
740
741 uiToggleButton* c = new uiToggleButton(this, zone, GTK_TOGGLE_BUTTON(button));
742 gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC (uiToggleButton::toggled), (gpointer) c);
743 }
744
745
746 // --------------------------- Check Button ---------------------------
747
748 struct uiCheckButton : public uiItem
749 {
750 GtkToggleButton* fButton;
751
752 uiCheckButton(UI* ui, float* zone, GtkToggleButton* b) : uiItem(ui, zone), fButton(b) {}
753
754 static void toggled (GtkWidget *widget, gpointer data)
755 {
756 float v = (GTK_TOGGLE_BUTTON (widget)->active) ? 1.0 : 0.0;
757 ((uiItem*)data)->modifyZone(v);
758 }
759
760 virtual void reflectZone()
761 {
762 float v = *fZone;
763 fCache = v;
764 gtk_toggle_button_set_active(fButton, v > 0.0);
765 }
766 };
767
768 void GTKUI::addCheckButton(const char* label, float* zone)
769 {
770 *zone = 0.0;
771 GtkWidget* button = gtk_check_button_new_with_label (label);
772 addWidget(label, button);
773
774 uiCheckButton* c = new uiCheckButton(this, zone, GTK_TOGGLE_BUTTON(button));
775 gtk_signal_connect (GTK_OBJECT (button), "toggled", GTK_SIGNAL_FUNC(uiCheckButton::toggled), (gpointer) c);
776 }
777
778
779 // --------------------------- Adjustmenty based widgets ---------------------------
780
781 struct uiAdjustment : public uiItem
782 {
783 GtkAdjustment* fAdj;
784
785 uiAdjustment(UI* ui, float* zone, GtkAdjustment* adj) : uiItem(ui, zone), fAdj(adj) {}
786
787 static void changed (GtkWidget *widget, gpointer data)
788 {
789 float v = GTK_ADJUSTMENT (widget)->value;
790 ((uiItem*)data)->modifyZone(v);
791 }
792
793 virtual void reflectZone()
794 {
795 float v = *fZone;
796 fCache = v;
797 gtk_adjustment_set_value(fAdj, v);
798 }
799 };
800
801 static int precision(double n)
802 {
803 if (n < 0.009999) return 3;
804 else if (n < 0.099999) return 2;
805 else if (n < 0.999999) return 1;
806 else return 0;
807 }
808
809 // -------------------------- Vertical Slider -----------------------------------
810
811 void GTKUI::addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
812 {
813 *zone = init;
814 GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0);
815
816 uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj));
817
818 gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c);
819
820 GtkWidget* slider = gtk_vscale_new (GTK_ADJUSTMENT(adj));
821 gtk_range_set_inverted (GTK_RANGE(slider), TRUE);
822 gtk_scale_set_digits(GTK_SCALE(slider), precision(step));
823 gtk_widget_set_usize(slider, -1, 160);
824
825 openFrameBox(label);
826 addWidget(label, slider);
827 closeBox();
828 }
829
830 // -------------------------- Horizontal Slider -----------------------------------
831
832 void GTKUI::addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
833 {
834 *zone = init;
835 GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, 0);
836
837 uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj));
838
839 gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c);
840
841 GtkWidget* slider = gtk_hscale_new (GTK_ADJUSTMENT(adj));
842 gtk_scale_set_digits(GTK_SCALE(slider), precision(step));
843 gtk_widget_set_usize(slider, 160, -1);
844
845 openFrameBox(label);
846 addWidget(label, slider);
847 closeBox();
848 }
849
850
851 // ------------------------------ Num Entry -----------------------------------
852
853 void GTKUI::addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
854 {
855 *zone = init;
856 GtkObject* adj = gtk_adjustment_new(init, min, max, step, 10*step, step);
857
858 uiAdjustment* c = new uiAdjustment(this, zone, GTK_ADJUSTMENT(adj));
859
860 gtk_signal_connect (GTK_OBJECT (adj), "value-changed", GTK_SIGNAL_FUNC (uiAdjustment::changed), (gpointer) c);
861
862 GtkWidget* spinner = gtk_spin_button_new (GTK_ADJUSTMENT(adj), 0.005, precision(step));
863
864 //gtk_widget_set_usize(slider, 160, -1);
865 openFrameBox(label);
866 addWidget(label, spinner);
867 closeBox();
868 }
869
870
871 // ========================== passive widgets ===============================
872
873
874 // ------------------------------ Progress Bar -----------------------------------
875
876 struct uiBargraph : public uiItem
877 {
878 GtkProgressBar* fProgressBar;
879 float fMin;
880 float fMax;
881
882 uiBargraph(UI* ui, float* zone, GtkProgressBar* pbar, float lo, float hi)
883 : uiItem(ui, zone), fProgressBar(pbar), fMin(lo), fMax(hi) {}
884
885 float scale(float v) { return (v-fMin)/(fMax-fMin); }
886
887 virtual void reflectZone()
888 {
889 float v = *fZone;
890 fCache = v;
891 gtk_progress_bar_set_fraction(fProgressBar, scale(v));
892 }
893 };
894
895
896
897 void GTKUI::addVerticalBargraph(const char* label, float* zone, float lo, float hi)
898 {
899 GtkWidget* pb = gtk_progress_bar_new();
900 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_BOTTOM_TO_TOP);
901 gtk_widget_set_size_request(pb, 8, -1);
902 new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi);
903 openFrameBox(label);
904 addWidget(label, pb);
905 closeBox();
906 }
907
908
909 void GTKUI::addHorizontalBargraph(const char* label, float* zone, float lo, float hi)
910 {
911 GtkWidget* pb = gtk_progress_bar_new();
912 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(pb), GTK_PROGRESS_LEFT_TO_RIGHT);
913 gtk_widget_set_size_request(pb, -1, 8);
914 new uiBargraph(this, zone, GTK_PROGRESS_BAR(pb), lo, hi);
915 openFrameBox(label);
916 addWidget(label, pb);
917 closeBox();
918 }
919
920
921 // ------------------------------ Num Display -----------------------------------
922
923 struct uiNumDisplay : public uiItem
924 {
925 GtkLabel* fLabel;
926 int fPrecision;
927
928 uiNumDisplay(UI* ui, float* zone, GtkLabel* label, int precision)
929 : uiItem(ui, zone), fLabel(label), fPrecision(precision) {}
930
931 virtual void reflectZone()
932 {
933 float v = *fZone;
934 fCache = v;
935 char s[64];
936 if (fPrecision <= 0) {
937 snprintf(s, 63, "%d", int(v));
938 } else if (fPrecision>3) {
939 snprintf(s, 63, "%f", v);
940 } else {
941 const char* format[] = {"%.1f", "%.2f", "%.3f"};
942 snprintf(s, 63, format[fPrecision-1], v);
943 }
944 gtk_label_set_text(fLabel, s);
945 }
946 };
947
948
949 void GTKUI::addNumDisplay(const char* label, float* zone, int precision )
950 {
951 GtkWidget* lw = gtk_label_new("");
952 new uiNumDisplay(this, zone, GTK_LABEL(lw), precision);
953 openFrameBox(label);
954 addWidget(label, lw);
955 closeBox();
956 }
957
958
959 // ------------------------------ Text Display -----------------------------------
960
961 struct uiTextDisplay : public uiItem
962 {
963 GtkLabel* fLabel;
964 char** fNames;
965 float fMin;
966 float fMax;
967 int fNum;
968
969
970 uiTextDisplay (UI* ui, float* zone, GtkLabel* label, char* names[], float lo, float hi)
971 : uiItem(ui, zone), fLabel(label), fNames(names), fMin(lo), fMax(hi)
972 {
973 fNum = 0;
974 while (fNames[fNum] != 0) fNum++;
975 }
976
977 virtual void reflectZone()
978 {
979 float v = *fZone;
980 fCache = v;
981
982 int idx = int(fNum*(v-fMin)/(fMax-fMin));
983
984 if (idx < 0) idx = 0;
985 else if (idx >= fNum) idx = fNum-1;
986
987 gtk_label_set_text(fLabel, fNames[idx]);
988 }
989 };
990
991
992 void GTKUI::addTextDisplay(const char* label, float* zone, char* names[], float lo, float hi )
993 {
994 GtkWidget* lw = gtk_label_new("");
995 new uiTextDisplay (this, zone, GTK_LABEL(lw), names, lo, hi);
996 openFrameBox(label);
997 addWidget(label, lw);
998 closeBox();
999 }
1000
1001
1002
1003 void GTKUI::show()
1004 {
1005 assert(fTop == 0);
1006 gtk_widget_show (fBox[0]);
1007 gtk_widget_show (fWindow);
1008 }
1009
1010
1011 /**
1012 * Update all user items reflecting zone z
1013 */
1014
1015 static gboolean callUpdateAllGuis(gpointer)
1016 {
1017 UI::updateAllGuis();
1018 return TRUE;
1019 }
1020
1021
1022 void GTKUI::run()
1023 {
1024 assert(fTop == 0);
1025 gtk_widget_show (fBox[0]);
1026 gtk_widget_show (fWindow);
1027 gtk_timeout_add(40, callUpdateAllGuis, 0);
1028 gtk_main ();
1029 stop();
1030 }
1031
1032
1033 /******************************************************************************
1034 *******************************************************************************
1035
1036 DSP
1037
1038 *******************************************************************************
1039 *******************************************************************************/
1040
1041
1042 //----------------------------------------------------------------
1043 // Definition of a Faust Digital Signal Processor
1044 //----------------------------------------------------------------
1045
1046 class dsp {
1047 protected:
1048 int fSamplingFreq;
1049 int fThreadNum;
1050 public:
1051 dsp() {}
1052 virtual ~dsp() {}
1053
1054 virtual int getNumInputs() = 0;
1055 virtual int getNumOutputs() = 0;
1056 virtual void buildUserInterface(UI* interface) = 0;
1057 virtual void init(int samplingRate) = 0;
1058 virtual void compute(int len, float** inputs, float** outputs) = 0;
1059 virtual void conclude() {}
1060 };
1061
1062
1063 <<includeclass>>
1064
1065
1066 mydsp DSP;
1067
1068
1069
1070 /******************************************************************************
1071 *******************************************************************************
1072
1073 COREAUDIO INTERFACE
1074
1075 *******************************************************************************
1076 *******************************************************************************/
1077
1078
1079 //----------------------------------------------------------------------------
1080 // number of physical input and output channels of the CA device
1081 //----------------------------------------------------------------------------
1082
1083 int gDevNumInChans;
1084 int gDevNumOutChans;
1085
1086 bool running = true;
1087
1088 //----------------------------------------------------------------------------
1089 // tables of noninterleaved input and output channels for FAUST
1090 //----------------------------------------------------------------------------
1091
1092 float* gInChannel[256];
1093 float* gOutChannel[256];
1094
1095 #define OPEN_ERR -1
1096 #define NO_ERR 0
1097
1098 class TCoreAudioRenderer
1099 {
1100
1101 private:
1102
1103 AudioBufferList* fInputData;
1104 AudioDeviceID fDeviceID;
1105 AudioUnit fAUHAL;
1106
1107 OSStatus GetDefaultDevice(int inChan, int outChan, AudioDeviceID* id);
1108
1109 static OSStatus Render(void *inRefCon,
1110 AudioUnitRenderActionFlags *ioActionFlags,
1111 const AudioTimeStamp *inTimeStamp,
1112 UInt32 inBusNumber,
1113 UInt32 inNumberFrames,
1114 AudioBufferList *ioData);
1115
1116 public:
1117
1118 TCoreAudioRenderer()
1119 {}
1120 virtual ~TCoreAudioRenderer()
1121 {}
1122
1123 long OpenDefault(long inChan, long outChan, long bufferSize, long sampleRate);
1124 long Close();
1125
1126 long Start();
1127 long Stop();
1128
1129 };
1130
1131 typedef TCoreAudioRenderer * TCoreAudioRendererPtr;
1132
1133 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
1134 {
1135 printf("- - - - - - - - - - - - - - - - - - - -\n");
1136 printf(" Sample Rate:%f\n", inDesc->mSampleRate);
1137 printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
1138 printf(" Format Flags:%lX\n", inDesc->mFormatFlags);
1139 printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
1140 printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
1141 printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
1142 printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
1143 printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
1144 printf("- - - - - - - - - - - - - - - - - - - -\n");
1145 }
1146
1147 static void printError(OSStatus err)
1148 {
1149 switch (err) {
1150 case kAudioHardwareNoError:
1151 printf("error code : kAudioHardwareNoError\n");
1152 break;
1153 case kAudioConverterErr_FormatNotSupported:
1154 printf("error code : kAudioConverterErr_FormatNotSupported\n");
1155 break;
1156 case kAudioConverterErr_OperationNotSupported:
1157 printf("error code : kAudioConverterErr_OperationNotSupported\n");
1158 break;
1159 case kAudioConverterErr_PropertyNotSupported:
1160 printf("error code : kAudioConverterErr_PropertyNotSupported\n");
1161 break;
1162 case kAudioConverterErr_InvalidInputSize:
1163 printf("error code : kAudioConverterErr_InvalidInputSize\n");
1164 break;
1165 case kAudioConverterErr_InvalidOutputSize:
1166 printf("error code : kAudioConverterErr_InvalidOutputSize\n");
1167 break;
1168 case kAudioConverterErr_UnspecifiedError:
1169 printf("error code : kAudioConverterErr_UnspecifiedError\n");
1170 break;
1171 case kAudioConverterErr_BadPropertySizeError:
1172 printf("error code : kAudioConverterErr_BadPropertySizeError\n");
1173 break;
1174 case kAudioConverterErr_RequiresPacketDescriptionsError:
1175 printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n");
1176 break;
1177 case kAudioConverterErr_InputSampleRateOutOfRange:
1178 printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n");
1179 break;
1180 case kAudioConverterErr_OutputSampleRateOutOfRange:
1181 printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n");
1182 break;
1183 case kAudioHardwareNotRunningError:
1184 printf("error code : kAudioHardwareNotRunningError\n");
1185 break;
1186 case kAudioHardwareUnknownPropertyError:
1187 printf("error code : kAudioHardwareUnknownPropertyError\n");
1188 break;
1189 case kAudioHardwareIllegalOperationError:
1190 printf("error code : kAudioHardwareIllegalOperationError\n");
1191 break;
1192 case kAudioHardwareBadDeviceError:
1193 printf("error code : kAudioHardwareBadDeviceError\n");
1194 break;
1195 case kAudioHardwareBadStreamError:
1196 printf("error code : kAudioHardwareBadStreamError\n");
1197 break;
1198 case kAudioDeviceUnsupportedFormatError:
1199 printf("error code : kAudioDeviceUnsupportedFormatError\n");
1200 break;
1201 case kAudioDevicePermissionsError:
1202 printf("error code : kAudioDevicePermissionsError\n");
1203 break;
1204 default:
1205 printf("error code : unknown\n");
1206 break;
1207 }
1208 }
1209
1210 OSStatus TCoreAudioRenderer::Render(void *inRefCon,
1211 AudioUnitRenderActionFlags *ioActionFlags,
1212 const AudioTimeStamp *inTimeStamp,
1213 UInt32,
1214 UInt32 inNumberFrames,
1215 AudioBufferList *ioData)
1216 {
1217 TCoreAudioRendererPtr renderer = (TCoreAudioRendererPtr)inRefCon;
1218 AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, renderer->fInputData);
1219 for (int i = 0; i < gDevNumInChans; i++) {
1220 gInChannel[i] = (float*)renderer->fInputData->mBuffers[i].mData;
1221 }
1222 for (int i = 0; i < gDevNumOutChans; i++) {
1223 gOutChannel[i] = (float*)ioData->mBuffers[i].mData;
1224 }
1225 STARTMESURE
1226 DSP.compute((int)inNumberFrames, gInChannel, gOutChannel);
1227 STOPMESURE
1228 running = mesure <= (KMESURE + KSKIP);
1229 return 0;
1230 }
1231
1232 OSStatus TCoreAudioRenderer::GetDefaultDevice(int inChan, int outChan, AudioDeviceID* id)
1233 {
1234 UInt32 theSize = sizeof(UInt32);
1235 AudioDeviceID inDefault;
1236 AudioDeviceID outDefault;
1237 OSStatus res;
1238
1239 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
1240 &theSize, &inDefault)) != noErr)
1241 return res;
1242
1243 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
1244 &theSize, &outDefault)) != noErr)
1245 return res;
1246
1247 // Duplex mode
1248 if (inChan > 0 && outChan > 0) {
1249 // Get the device only if default input and output are the same
1250 if (inDefault == outDefault) {
1251 *id = inDefault;
1252 return noErr;
1253 } else {
1254 printf("GetDefaultDevice : error input = %ld and output = %ld are not the same\n", inDefault, outDefault);
1255 return kAudioHardwareBadDeviceError;
1256 }
1257 } else if (inChan > 0) {
1258 *id = inDefault;
1259 return noErr;
1260 } else if (outChan > 0) {
1261 *id = outDefault;
1262 return noErr;
1263 } else {
1264 return kAudioHardwareBadDeviceError;
1265 }
1266
1267 return noErr;
1268 }
1269
1270 long TCoreAudioRenderer::OpenDefault(long inChan, long outChan, long bufferSize, long samplerate)
1271 {
1272 OSStatus err = noErr;
1273 ComponentResult err1;
1274 UInt32 outSize;
1275 UInt32 enableIO;
1276 Boolean isWritable;
1277 AudioStreamBasicDescription srcFormat, dstFormat, sampleRate;
1278 long in_nChannels, out_nChannels;
1279
1280 printf("OpenDefault inChan = %ld outChan = %ld bufferSize = %ld samplerate = %ld\n", inChan, outChan, bufferSize, samplerate);
1281
1282 if (GetDefaultDevice(inChan, outChan, &fDeviceID) != noErr) {
1283 printf("Cannot open default device\n");
1284 return OPEN_ERR;
1285 }
1286
1287 // Setting buffer size
1288 outSize = sizeof(UInt32);
1289 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &bufferSize);
1290 if (err != noErr) {
1291 printf("Cannot set buffer size %ld\n", bufferSize);
1292 printError(err);
1293 return OPEN_ERR;
1294 }
1295
1296 // Setting sample rate
1297 outSize = sizeof(AudioStreamBasicDescription);
1298 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate);
1299 if (err != noErr) {
1300 printf("Cannot get current sample rate\n");
1301 printError(err);
1302 return OPEN_ERR;
1303 }
1304
1305 if (samplerate != long(sampleRate.mSampleRate)) {
1306 sampleRate.mSampleRate = (Float64)(samplerate);
1307 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyStreamFormat, outSize, &sampleRate);
1308 if (err != noErr) {
1309 printf("Cannot set sample rate = %ld\n", samplerate);
1310 printError(err);
1311 return OPEN_ERR;
1312 }
1313 }
1314
1315 // AUHAL
1316 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
1317 Component HALOutput = FindNextComponent(NULL, &cd);
1318
1319 err1 = OpenAComponent(HALOutput, &fAUHAL);
1320 if (err1 != noErr) {
1321 printf("Error calling OpenAComponent\n");
1322 printError(err1);
1323 goto error;
1324 }
1325
1326 err1 = AudioUnitInitialize(fAUHAL);
1327 if (err1 != noErr) {
1328 printf("Cannot initialize AUHAL unit\n");
1329 printError(err1);
1330 goto error;
1331 }
1332
1333 enableIO = 1;
1334 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
1335 if (err1 != noErr) {
1336 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n");
1337 printError(err1);
1338 goto error;
1339 }
1340
1341 enableIO = 1;
1342 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
1343 if (err1 != noErr) {
1344 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n");
1345 printError(err1);
1346 goto error;
1347 }
1348
1349 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
1350 if (err1 != noErr) {
1351 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice\n");
1352 printError(err1);
1353 goto error;
1354 }
1355
1356 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32));
1357 if (err1 != noErr) {
1358 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
1359 printError(err1);
1360 goto error;
1361 }
1362
1363 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32));
1364 if (err1 != noErr) {
1365 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
1366 printError(err1);
1367 goto error;
1368 }
1369
1370 err1 = AudioUnitGetPropertyInfo(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Input, 1, &outSize, &isWritable);
1371 if (err1 != noErr) {
1372 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 1\n");
1373 printError(err1);
1374 }
1375
1376 in_nChannels = (err1 == noErr) ? outSize / sizeof(SInt32) : 0;
1377 printf("in_nChannels = %ld\n", in_nChannels);
1378
1379 err1 = AudioUnitGetPropertyInfo(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, &outSize, &isWritable);
1380 if (err1 != noErr) {
1381 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap-INFO 0\n");
1382 printError(err1);
1383 }
1384
1385 out_nChannels = (err1 == noErr) ? outSize / sizeof(SInt32) : 0;
1386 printf("out_nChannels = %ld\n", out_nChannels);
1387
1388 /*
1389 Just ignore this case : seems to work without any further change...
1390
1391 if (outChan > out_nChannels) {
1392 printf("This device hasn't required output channels\n");
1393 goto error;
1394 }
1395 if (inChan > in_nChannels) {
1396 printf("This device hasn't required input channels\n");
1397 goto error;
1398 }
1399 */
1400
1401 if (outChan < out_nChannels) {
1402 SInt32 chanArr[out_nChannels];
1403 for (int i = 0; i < out_nChannels; i++) {
1404 chanArr[i] = -1;
1405 }
1406 for (int i = 0; i < outChan; i++) {
1407 chanArr[i] = i;
1408 }
1409 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
1410 if (err1 != noErr) {
1411 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0\n");
1412 printError(err1);
1413 }
1414 }
1415
1416 if (inChan < in_nChannels) {
1417 SInt32 chanArr[in_nChannels];
1418 for (int i = 0; i < in_nChannels; i++) {
1419 chanArr[i] = -1;
1420 }
1421 for (int i = 0; i < inChan; i++) {
1422 chanArr[i] = i;
1423 }
1424 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
1425 if (err1 != noErr) {
1426 printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1\n");
1427 printError(err1);
1428 }
1429 }
1430
1431 if (inChan > 0) {
1432 outSize = sizeof(AudioStreamBasicDescription);
1433 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize);
1434 if (err1 != noErr) {
1435 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
1436 printError(err1);
1437 }
1438 PrintStreamDesc(&srcFormat);
1439
1440 srcFormat.mSampleRate = samplerate;
1441 srcFormat.mFormatID = kAudioFormatLinearPCM;
1442 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1443 srcFormat.mBytesPerPacket = sizeof(float);
1444 srcFormat.mFramesPerPacket = 1;
1445 srcFormat.mBytesPerFrame = sizeof(float);
1446 srcFormat.mChannelsPerFrame = inChan;
1447 srcFormat.mBitsPerChannel = 32;
1448
1449 PrintStreamDesc(&srcFormat);
1450
1451 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
1452 if (err1 != noErr) {
1453 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
1454 printError(err1);
1455 }
1456 }
1457
1458 if (outChan > 0) {
1459 outSize = sizeof(AudioStreamBasicDescription);
1460 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize);
1461 if (err1 != noErr) {
1462 printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
1463 printError(err1);
1464 }
1465 PrintStreamDesc(&dstFormat);
1466
1467 dstFormat.mSampleRate = samplerate;
1468 dstFormat.mFormatID = kAudioFormatLinearPCM;
1469 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
1470 dstFormat.mBytesPerPacket = sizeof(float);
1471 dstFormat.mFramesPerPacket = 1;
1472 dstFormat.mBytesPerFrame = sizeof(float);
1473 dstFormat.mChannelsPerFrame = outChan;
1474 dstFormat.mBitsPerChannel = 32;
1475
1476 PrintStreamDesc(&dstFormat);
1477
1478 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
1479 if (err1 != noErr) {
1480 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
1481 printError(err1);
1482 }
1483 }
1484
1485 if (inChan > 0 && outChan == 0) {
1486 AURenderCallbackStruct output;
1487 output.inputProc = Render;
1488 output.inputProcRefCon = this;
1489 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
1490 if (err1 != noErr) {
1491 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n");
1492 printError(err1);
1493 goto error;
1494 }
1495 } else {
1496 AURenderCallbackStruct output;
1497 output.inputProc = Render;
1498 output.inputProcRefCon = this;
1499 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
1500 if (err1 != noErr) {
1501 printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n");
1502 printError(err1);
1503 goto error;
1504 }
1505 }
1506
1507 fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inChan * sizeof(AudioBuffer));
1508 if (fInputData == 0) {
1509 printf("Cannot allocate memory for input buffers\n");
1510 goto error;
1511 }
1512 fInputData->mNumberBuffers = inChan;
1513
1514 // Prepare buffers
1515 for (int i = 0; i < inChan; i++) {
1516 fInputData->mBuffers[i].mNumberChannels = 1;
1517 fInputData->mBuffers[i].mData = malloc(bufferSize * sizeof(float));
1518 fInputData->mBuffers[i].mDataByteSize = bufferSize * sizeof(float);
1519 }
1520
1521 return NO_ERR;
1522
1523 error:
1524 AudioUnitUninitialize(fAUHAL);
1525 CloseComponent(fAUHAL);
1526 return OPEN_ERR;
1527 }
1528
1529 long TCoreAudioRenderer::Close()
1530 {
1531 for (int i = 0; i < gDevNumInChans; i++) {
1532 free(fInputData->mBuffers[i].mData);
1533 }
1534 free(fInputData);
1535 AudioUnitUninitialize(fAUHAL);
1536 CloseComponent(fAUHAL);
1537 return NO_ERR;
1538 }
1539
1540 long TCoreAudioRenderer::Start()
1541 {
1542 OSStatus err = AudioOutputUnitStart(fAUHAL);
1543
1544 if (err != noErr) {
1545 printf("Error while opening device : device open error \n");
1546 return OPEN_ERR;
1547 } else {
1548 return NO_ERR;
1549 }
1550 }
1551
1552 long TCoreAudioRenderer::Stop()
1553 {
1554 OSStatus err = AudioOutputUnitStop(fAUHAL);
1555
1556 if (err != noErr) {
1557 printf("Error while closing device : device close error \n");
1558 return OPEN_ERR;
1559 } else {
1560 return NO_ERR;
1561 }
1562 }
1563
1564
1565 /******************************************************************************
1566 *******************************************************************************
1567
1568 MAIN PLAY THREAD
1569
1570 *******************************************************************************
1571 *******************************************************************************/
1572
1573 // lopt : Scan Command Line long int Arguments
1574
1575 /*
1576 long lopt (int argc, char *argv[], const char* longname, const char* shortname, long def)
1577 {
1578 for (int i=2; i<argc; i++)
1579 if ( strcmp(argv[i-1], shortname) == 0 || strcmp(argv[i-1], longname) == 0 )
1580 return atoi(argv[i]);
1581 return def;
1582 }
1583 */
1584
1585 long lopt (char *argv[], const char *name, long def)
1586 {
1587 int i;
1588 for (i=0; argv[i]; i++) if (!strcmp(argv[i], name)) return atoi(argv[i+1]);
1589 return def;
1590 }
1591
1592 // sopt : Scan Command Line string Arguments
1593
1594 const char* sopt (int argc, char *argv[], const char* longname, const char* shortname, const char* def)
1595 {
1596 for (int i=2; i<argc; i++)
1597 if ( strcmp(argv[i-1], shortname) == 0 || strcmp(argv[i-1], longname) == 0 )
1598 return argv[i];
1599 return def;
1600 }
1601
1602 // fopt : Scan Command Line flag option (without argument), return true if the flag
1603
1604 bool fopt (int argc, char *argv[], const char* longname, const char* shortname)
1605 {
1606 for (int i=1; i<argc; i++)
1607 if ( strcmp(argv[i], shortname) == 0 || strcmp(argv[i], longname) == 0 )
1608 return true;
1609 return false;
1610 }
1611
1612
1613 //-------------------------------------------------------------------------
1614 // MAIN
1615 //-------------------------------------------------------------------------
1616
1617 pthread_t guithread;
1618
1619 void* run_ui(void* ptr)
1620 {
1621 UI* interface = (UI*) ptr;
1622 interface->run();
1623 pthread_exit(0);
1624 return 0;
1625 }
1626
1627 int main(int argc, char *argv[] )
1628 {
1629 CHECKINTSIZE;
1630
1631 UI* interface = new GTKUI(argv[0], &argc, &argv);
1632
1633 // compute rcfilename to (re)store application state
1634 char rcfilename[256];
1635 char* home = getenv("HOME");
1636 snprintf(rcfilename, 255, "%s/.%src", home, basename(argv[0]));
1637
1638 TCoreAudioRenderer audio_device;
1639
1640 long srate = (long)lopt(argv, "--frequency", 44100);
1641 int fpb = lopt(argv, "--buffer", 512);
1642
1643 AVOIDDENORMALS;
1644
1645 DSP.init(srate);
1646 DSP.buildUserInterface(interface);
1647
1648 gDevNumInChans = DSP.getNumInputs();
1649 gDevNumOutChans = DSP.getNumOutputs();
1650
1651 interface->recallState(rcfilename);
1652
1653 pthread_create(&guithread, NULL, run_ui, interface);
1654
1655 openMesure();
1656
1657 if (audio_device.OpenDefault(gDevNumInChans, gDevNumOutChans, fpb, srate) < 0) {
1658 printf("Cannot open CoreAudio device\n");
1659 return 0;
1660 }
1661
1662 if (audio_device.Start() < 0) {
1663 printf("Cannot start CoreAudio device\n");
1664 return 0;
1665 }
1666 while(running) {
1667 usleep(100000);
1668 }
1669 closeMesure();
1670 interface->saveState(rcfilename);
1671
1672 #ifdef BENCHMARKMODE
1673 printstats(argv[0], fpb, DSP.getNumInputs(), DSP.getNumOutputs());
1674 #endif
1675
1676 return 0;
1677 }