1 /************************************************************************
2 ************************************************************************
3 FAUST Architecture File
4 Copyright (C) 2006-2011 Albert Graef <Dr.Graef@t-online.de>
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 ************************************************************************
21 ************************************************************************/
23 /* Pd architecture file, written by Albert Graef <Dr.Graef@t-online.de>.
24 This was derived from minimal.cpp included in the Faust distribution.
25 Please note that this is to be compiled as a shared library, which is
26 then loaded dynamically by Pd as an external. */
35 // On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
36 // flags to avoid costly denormals
38 #include <xmmintrin.h>
40 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
42 #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
45 #warning *** puredata.cpp: NO SSE FLAG (denormals may slow things down) ***
46 #define AVOIDDENORMALS
51 void declare (const char* key
, const char* value
) {}
54 //-------------------------------------------------------------------
55 // Generic min and max using c++ inline
56 //-------------------------------------------------------------------
58 inline int max (unsigned int a
, unsigned int b
) { return (a
>b
) ? a
: b
; }
59 inline int max (int a
, int b
) { return (a
>b
) ? a
: b
; }
61 inline long max (long a
, long b
) { return (a
>b
) ? a
: b
; }
62 inline long max (int a
, long b
) { return (a
>b
) ? a
: b
; }
63 inline long max (long a
, int b
) { return (a
>b
) ? a
: b
; }
65 inline float max (float a
, float b
) { return (a
>b
) ? a
: b
; }
66 inline float max (int a
, float b
) { return (a
>b
) ? a
: b
; }
67 inline float max (float a
, int b
) { return (a
>b
) ? a
: b
; }
68 inline float max (long a
, float b
) { return (a
>b
) ? a
: b
; }
69 inline float max (float a
, long b
) { return (a
>b
) ? a
: b
; }
71 inline double max (double a
, double b
) { return (a
>b
) ? a
: b
; }
72 inline double max (int a
, double b
) { return (a
>b
) ? a
: b
; }
73 inline double max (double a
, int b
) { return (a
>b
) ? a
: b
; }
74 inline double max (long a
, double b
) { return (a
>b
) ? a
: b
; }
75 inline double max (double a
, long b
) { return (a
>b
) ? a
: b
; }
76 inline double max (float a
, double b
) { return (a
>b
) ? a
: b
; }
77 inline double max (double a
, float b
) { return (a
>b
) ? a
: b
; }
80 inline int min (int a
, int b
) { return (a
<b
) ? a
: b
; }
82 inline long min (long a
, long b
) { return (a
<b
) ? a
: b
; }
83 inline long min (int a
, long b
) { return (a
<b
) ? a
: b
; }
84 inline long min (long a
, int b
) { return (a
<b
) ? a
: b
; }
86 inline float min (float a
, float b
) { return (a
<b
) ? a
: b
; }
87 inline float min (int a
, float b
) { return (a
<b
) ? a
: b
; }
88 inline float min (float a
, int b
) { return (a
<b
) ? a
: b
; }
89 inline float min (long a
, float b
) { return (a
<b
) ? a
: b
; }
90 inline float min (float a
, long b
) { return (a
<b
) ? a
: b
; }
92 inline double min (double a
, double b
) { return (a
<b
) ? a
: b
; }
93 inline double min (int a
, double b
) { return (a
<b
) ? a
: b
; }
94 inline double min (double a
, int b
) { return (a
<b
) ? a
: b
; }
95 inline double min (long a
, double b
) { return (a
<b
) ? a
: b
; }
96 inline double min (double a
, long b
) { return (a
<b
) ? a
: b
; }
97 inline double min (float a
, double b
) { return (a
<b
) ? a
: b
; }
98 inline double min (double a
, float b
) { return (a
<b
) ? a
: b
; }
100 // abs is now predefined
101 //template<typename T> T abs (T a) { return (a<T(0)) ? -a : a; }
104 inline int lsr (int x
, int n
) { return int(((unsigned int)x
) >> n
); }
106 /******************************************************************************
107 *******************************************************************************
111 *******************************************************************************
112 *******************************************************************************/
114 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
115 //inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((size_t)(calloc((nmemb*size)+15,sizeof(char)))+15 & ~15); }
119 /******************************************************************************
120 *******************************************************************************
122 ABSTRACT USER INTERFACE
124 *******************************************************************************
125 *******************************************************************************/
132 UI() : fStopped(false) {}
135 virtual void addButton(const char* label
, float* zone
) = 0;
136 virtual void addToggleButton(const char* label
, float* zone
) = 0;
137 virtual void addCheckButton(const char* label
, float* zone
) = 0;
138 virtual void addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
139 virtual void addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
140 virtual void addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
) = 0;
142 virtual void addNumDisplay(const char* label
, float* zone
, int precision
) = 0;
143 virtual void addTextDisplay(const char* label
, float* zone
, const char* names
[], float min
, float max
) = 0;
144 virtual void addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
) = 0;
145 virtual void addVerticalBargraph(const char* label
, float* zone
, float min
, float max
) = 0;
147 virtual void openFrameBox(const char* label
) = 0;
148 virtual void openTabBox(const char* label
) = 0;
149 virtual void openHorizontalBox(const char* label
) = 0;
150 virtual void openVerticalBox(const char* label
) = 0;
151 virtual void closeBox() = 0;
153 virtual void run() = 0;
155 void stop() { fStopped
= true; }
156 bool stopped() { return fStopped
; }
158 virtual void declare(float* zone
, const char* key
, const char* value
) {}
161 /***************************************************************************
163 ***************************************************************************/
165 enum ui_elem_type_t
{
166 UI_BUTTON
, UI_TOGGLE_BUTTON
, UI_CHECK_BUTTON
,
167 UI_V_SLIDER
, UI_H_SLIDER
, UI_NUM_ENTRY
,
168 UI_V_BARGRAPH
, UI_H_BARGRAPH
,
169 UI_END_GROUP
, UI_V_GROUP
, UI_H_GROUP
, UI_T_GROUP
176 float init
, min
, max
, step
;
179 class PdUI
: public UI
191 void add_elem(ui_elem_type_t type
, const char *label
= NULL
);
192 void add_elem(ui_elem_type_t type
, const char *label
, float *zone
);
193 void add_elem(ui_elem_type_t type
, const char *label
, float *zone
,
194 float init
, float min
, float max
, float step
);
195 void add_elem(ui_elem_type_t type
, const char *label
, float *zone
,
196 float min
, float max
);
199 virtual void addButton(const char* label
, float* zone
);
200 virtual void addToggleButton(const char* label
, float* zone
);
201 virtual void addCheckButton(const char* label
, float* zone
);
202 virtual void addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
);
203 virtual void addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
);
204 virtual void addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
);
206 virtual void addNumDisplay(const char* label
, float* zone
, int precision
);
207 virtual void addTextDisplay(const char* label
, float* zone
, const char* names
[], float min
, float max
);
208 virtual void addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
);
209 virtual void addVerticalBargraph(const char* label
, float* zone
, float min
, float max
);
211 virtual void openFrameBox(const char* label
);
212 virtual void openTabBox(const char* label
);
213 virtual void openHorizontalBox(const char* label
);
214 virtual void openVerticalBox(const char* label
);
215 virtual void closeBox();
220 static string
mangle(const char *s
)
230 while (*s
&& !isalnum(*s
)) ++s
;
231 if (s1
!= s0
&& *s
) t
+= "-";
236 static string
normpath(string path
)
238 path
= string("/")+path
;
239 int pos
= path
.find("//");
242 pos
= path
.find("//");
247 static string
pathcat(string path
, string label
)
250 return normpath(label
);
251 else if (label
.empty())
252 return normpath(path
);
254 return normpath(path
+"/"+label
);
264 PdUI::PdUI(const char *s
)
274 for (int i
= 0; i
< nelems
; i
++)
276 free(elems
[i
].label
);
281 inline void PdUI::add_elem(ui_elem_type_t type
, const char *label
)
283 ui_elem_t
*elems1
= (ui_elem_t
*)realloc(elems
, (nelems
+1)*sizeof(ui_elem_t
));
288 string s
= pathcat(path
, mangle(label
));
289 elems
[nelems
].type
= type
;
290 elems
[nelems
].label
= strdup(s
.c_str());
291 elems
[nelems
].zone
= NULL
;
292 elems
[nelems
].init
= 0.0;
293 elems
[nelems
].min
= 0.0;
294 elems
[nelems
].max
= 0.0;
295 elems
[nelems
].step
= 0.0;
299 inline void PdUI::add_elem(ui_elem_type_t type
, const char *label
, float *zone
)
301 ui_elem_t
*elems1
= (ui_elem_t
*)realloc(elems
, (nelems
+1)*sizeof(ui_elem_t
));
306 string s
= pathcat(path
, mangle(label
));
307 elems
[nelems
].type
= type
;
308 elems
[nelems
].label
= strdup(s
.c_str());
309 elems
[nelems
].zone
= zone
;
310 elems
[nelems
].init
= 0.0;
311 elems
[nelems
].min
= 0.0;
312 elems
[nelems
].max
= 1.0;
313 elems
[nelems
].step
= 1.0;
317 inline void PdUI::add_elem(ui_elem_type_t type
, const char *label
, float *zone
,
318 float init
, float min
, float max
, float step
)
320 ui_elem_t
*elems1
= (ui_elem_t
*)realloc(elems
, (nelems
+1)*sizeof(ui_elem_t
));
325 string s
= pathcat(path
, mangle(label
));
326 elems
[nelems
].type
= type
;
327 elems
[nelems
].label
= strdup(s
.c_str());
328 elems
[nelems
].zone
= zone
;
329 elems
[nelems
].init
= init
;
330 elems
[nelems
].min
= min
;
331 elems
[nelems
].max
= max
;
332 elems
[nelems
].step
= step
;
336 inline void PdUI::add_elem(ui_elem_type_t type
, const char *label
, float *zone
,
337 float min
, float max
)
339 ui_elem_t
*elems1
= (ui_elem_t
*)realloc(elems
, (nelems
+1)*sizeof(ui_elem_t
));
344 string s
= pathcat(path
, mangle(label
));
345 elems
[nelems
].type
= type
;
346 elems
[nelems
].label
= strdup(s
.c_str());
347 elems
[nelems
].zone
= zone
;
348 elems
[nelems
].init
= 0.0;
349 elems
[nelems
].min
= min
;
350 elems
[nelems
].max
= max
;
351 elems
[nelems
].step
= 0.0;
355 void PdUI::addButton(const char* label
, float* zone
)
356 { add_elem(UI_BUTTON
, label
, zone
); }
357 void PdUI::addToggleButton(const char* label
, float* zone
)
358 { add_elem(UI_TOGGLE_BUTTON
, label
, zone
); }
359 void PdUI::addCheckButton(const char* label
, float* zone
)
360 { add_elem(UI_CHECK_BUTTON
, label
, zone
); }
361 void PdUI::addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
362 { add_elem(UI_V_SLIDER
, label
, zone
, init
, min
, max
, step
); }
363 void PdUI::addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
364 { add_elem(UI_H_SLIDER
, label
, zone
, init
, min
, max
, step
); }
365 void PdUI::addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
366 { add_elem(UI_NUM_ENTRY
, label
, zone
, init
, min
, max
, step
); }
368 // FIXME: addNumDisplay and addTextDisplay not implemented in Faust yet?
369 void PdUI::addNumDisplay(const char* label
, float* zone
, int precision
) {}
370 void PdUI::addTextDisplay(const char* label
, float* zone
, const char* names
[], float min
, float max
) {}
371 void PdUI::addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
)
372 { add_elem(UI_H_BARGRAPH
, label
, zone
, min
, max
); }
373 void PdUI::addVerticalBargraph(const char* label
, float* zone
, float min
, float max
)
374 { add_elem(UI_V_BARGRAPH
, label
, zone
, min
, max
); }
376 void PdUI::openFrameBox(const char* label
)
378 if (!path
.empty()) path
+= "/";
379 path
+= mangle(label
);
381 void PdUI::openTabBox(const char* label
)
383 if (!path
.empty()) path
+= "/";
384 path
+= mangle(label
);
386 void PdUI::openHorizontalBox(const char* label
)
388 if (!path
.empty()) path
+= "/";
389 path
+= mangle(label
);
391 void PdUI::openVerticalBox(const char* label
)
393 if (!path
.empty()) path
+= "/";
394 path
+= mangle(label
);
396 void PdUI::closeBox()
398 int pos
= path
.rfind("/");
399 if (pos
< 0) pos
= 0;
405 /******************************************************************************
406 *******************************************************************************
410 *******************************************************************************
411 *******************************************************************************/
415 //----------------------------------------------------------------
416 // abstract definition of a signal processor
417 //----------------------------------------------------------------
425 virtual int getNumInputs() = 0;
426 virtual int getNumOutputs() = 0;
427 virtual void buildUserInterface(UI
* interface
) = 0;
428 virtual void init(int samplingRate
) = 0;
429 virtual void compute(int len
, float** inputs
, float** outputs
) = 0;
432 //----------------------------------------------------------------------------
433 // FAUST generated signal processor
434 //----------------------------------------------------------------------------
443 #define faust_setup(name) xfaust_setup(name)
444 #define xfaust_setup(name) name ## _tilde_setup(void)
445 #define sym(name) xsym(name)
446 #define xsym(name) #name
448 // time for "active" toggle xfades in secs
449 #define XFADE_TIME 0.1f
451 static t_class
*faust_class
;
456 /* This seems to be necessary as some as yet undetermined Pd routine seems
457 to write past the end of x_obj on Windows. */
458 int fence
; /* dummy field (not used) */
463 int active
, xfade
, n_xfade
, rate
, n_in
, n_out
;
464 t_sample
**inputs
, **outputs
, **buf
;
469 static t_symbol
*s_button
, *s_checkbox
, *s_vslider
, *s_hslider
, *s_nentry
,
470 *s_vbargraph
, *s_hbargraph
;
472 static inline void zero_samples(int k
, int n
, t_sample
**out
)
474 for (int i
= 0; i
< k
; i
++)
475 #ifdef __STDC_IEC_559__
476 /* IEC 559 a.k.a. IEEE 754 floats can be initialized faster like this */
477 memset(out
[i
], 0, n
*sizeof(t_sample
));
479 for (int j
= 0; j
< n
; j
++)
484 static inline void copy_samples(int k
, int n
, t_sample
**out
, t_sample
**in
)
486 for (int i
= 0; i
< k
; i
++)
487 memcpy(out
[i
], in
[i
], n
*sizeof(t_sample
));
490 static t_int
*faust_perform(t_int
*w
)
492 t_faust
*x
= (t_faust
*)(w
[1]);
494 if (!x
->dsp
|| !x
->buf
) return (w
+3);
497 float d
= 1.0f
/x
->n_xfade
, f
= (x
->xfade
--)*d
;
499 x
->dsp
->compute(n
, x
->inputs
, x
->buf
);
501 if (x
->n_in
== x
->n_out
)
502 /* xfade inputs -> buf */
503 for (int j
= 0; j
< n
; j
++, f
-= d
)
504 for (int i
= 0; i
< x
->n_out
; i
++)
505 x
->outputs
[i
][j
] = f
*x
->inputs
[i
][j
]+(1.0f
-f
)*x
->buf
[i
][j
];
508 for (int j
= 0; j
< n
; j
++, f
-= d
)
509 for (int i
= 0; i
< x
->n_out
; i
++)
510 x
->outputs
[i
][j
] = (1.0f
-f
)*x
->buf
[i
][j
];
512 if (x
->n_in
== x
->n_out
)
513 /* xfade buf -> inputs */
514 for (int j
= 0; j
< n
; j
++, f
-= d
)
515 for (int i
= 0; i
< x
->n_out
; i
++)
516 x
->outputs
[i
][j
] = f
*x
->buf
[i
][j
]+(1.0f
-f
)*x
->inputs
[i
][j
];
519 for (int j
= 0; j
< n
; j
++, f
-= d
)
520 for (int i
= 0; i
< x
->n_out
; i
++)
521 x
->outputs
[i
][j
] = f
*x
->buf
[i
][j
];
522 } else if (x
->active
) {
523 x
->dsp
->compute(n
, x
->inputs
, x
->buf
);
524 copy_samples(x
->n_out
, n
, x
->outputs
, x
->buf
);
525 } else if (x
->n_in
== x
->n_out
) {
526 copy_samples(x
->n_out
, n
, x
->buf
, x
->inputs
);
527 copy_samples(x
->n_out
, n
, x
->outputs
, x
->buf
);
529 zero_samples(x
->n_out
, n
, x
->outputs
);
533 static void faust_dsp(t_faust
*x
, t_signal
**sp
)
535 int n
= sp
[0]->s_n
, sr
= (int)sp
[0]->s_sr
;
537 /* default sample rate is whatever Pd tells us */
540 if (ui
->nelems
> 0 &&
541 (z
= (float*)malloc(ui
->nelems
*sizeof(float)))) {
542 /* save the current control values */
543 for (int i
= 0; i
< ui
->nelems
; i
++)
544 if (ui
->elems
[i
].zone
)
545 z
[i
] = *ui
->elems
[i
].zone
;
547 /* set the proper sample rate; this requires reinitializing the dsp */
551 /* restore previous control values */
552 for (int i
= 0; i
< ui
->nelems
; i
++)
553 if (ui
->elems
[i
].zone
)
554 *ui
->elems
[i
].zone
= z
[i
];
559 x
->n_xfade
= (int)(x
->rate
*XFADE_TIME
/n
);
560 dsp_add(faust_perform
, 2, x
, n
);
561 for (int i
= 0; i
< x
->n_in
; i
++)
562 x
->inputs
[i
] = sp
[i
+1]->s_vec
;
563 for (int i
= 0; i
< x
->n_out
; i
++)
564 x
->outputs
[i
] = sp
[x
->n_in
+i
+1]->s_vec
;
566 for (int i
= 0; i
< x
->n_out
; i
++) {
567 x
->buf
[i
] = (t_sample
*)malloc(n
*sizeof(t_sample
));
568 if (x
->buf
[i
] == NULL
) {
569 for (int j
= 0; j
< i
; j
++)
578 static int pathcmp(const char *s
, const char *t
)
580 int n
= strlen(s
), m
= strlen(t
);
581 if (n
== 0 || m
== 0)
583 else if (t
[0] == '/')
585 else if (n
<= m
|| s
[n
-m
-1] != '/')
586 return strcmp(s
+1, t
);
588 return strcmp(s
+n
-m
, t
);
591 static void faust_any(t_faust
*x
, t_symbol
*s
, int argc
, t_atom
*argv
)
596 for (int i
= 0; i
< ui
->nelems
; i
++)
597 if (ui
->elems
[i
].label
&& ui
->elems
[i
].zone
) {
600 switch (ui
->elems
[i
].type
) {
604 case UI_TOGGLE_BUTTON
:
605 case UI_CHECK_BUTTON
:
626 SETSYMBOL(&args
[0], gensym(ui
->elems
[i
].label
));
627 SETFLOAT(&args
[1], *ui
->elems
[i
].zone
);
628 SETFLOAT(&args
[2], ui
->elems
[i
].init
);
629 SETFLOAT(&args
[3], ui
->elems
[i
].min
);
630 SETFLOAT(&args
[4], ui
->elems
[i
].max
);
631 SETFLOAT(&args
[5], ui
->elems
[i
].step
);
632 outlet_anything(x
->out
, _s
, 6, args
);
635 const char *label
= s
->s_name
;
637 for (int i
= 0; i
< ui
->nelems
; i
++)
638 if (ui
->elems
[i
].label
&&
639 pathcmp(ui
->elems
[i
].label
, label
) == 0) {
641 if (ui
->elems
[i
].zone
) {
643 SETFLOAT(&arg
, *ui
->elems
[i
].zone
);
644 outlet_anything(x
->out
, gensym(ui
->elems
[i
].label
), 1, &arg
);
647 } else if (argc
== 1 &&
648 (argv
[0].a_type
== A_FLOAT
||
649 argv
[0].a_type
== A_DEFFLOAT
) &&
651 float f
= atom_getfloat(argv
);
652 *ui
->elems
[i
].zone
= f
;
655 pd_error(x
, "[faust] %s: bad control argument: %s",
656 x
->label
->c_str(), label
);
658 if (count
== 0 && strcmp(label
, "active") == 0) {
661 SETFLOAT(&arg
, (float)x
->active
);
662 outlet_anything(x
->out
, gensym((char*)"active"), 1, &arg
);
663 } else if (argc
== 1 &&
664 (argv
[0].a_type
== A_FLOAT
||
665 argv
[0].a_type
== A_DEFFLOAT
)) {
666 float f
= atom_getfloat(argv
);
668 x
->xfade
= x
->n_xfade
;
674 static void faust_free(t_faust
*x
)
676 if (x
->label
) delete x
->label
;
677 if (x
->dsp
) delete x
->dsp
;
678 if (x
->ui
) delete x
->ui
;
679 if (x
->inputs
) free(x
->inputs
);
680 if (x
->outputs
) free(x
->outputs
);
682 for (int i
= 0; i
< x
->n_out
; i
++)
683 if (x
->buf
[i
]) free(x
->buf
[i
]);
688 static void *faust_new(t_symbol
*s
, int argc
, t_atom
*argv
)
690 t_faust
*x
= (t_faust
*)pd_new(faust_class
);
694 for (int i
= 0; i
< argc
; i
++)
695 if (argv
[i
].a_type
== A_FLOAT
|| argv
[i
].a_type
== A_DEFFLOAT
)
696 sr
= (int)argv
[i
].a_w
.w_float
;
697 else if (argv
[i
].a_type
== A_SYMBOL
|| argv
[i
].a_type
== A_DEFSYMBOL
)
698 id
= argv
[i
].a_w
.w_symbol
;
700 if (sr
<= 0) sr
= 44100;
701 x
->xfade
= 0; x
->n_xfade
= (int)(sr
*XFADE_TIME
/64);
702 x
->inputs
= x
->outputs
= x
->buf
= NULL
;
703 x
->label
= new string(sym(mydsp
) "~");
704 x
->dsp
= new mydsp();
705 x
->ui
= new PdUI(id
?id
->s_name
:NULL
);
706 if (!x
->dsp
|| !x
->ui
|| !x
->label
) goto error
;
709 *x
->label
+= id
->s_name
;
711 x
->n_in
= x
->dsp
->getNumInputs();
712 x
->n_out
= x
->dsp
->getNumOutputs();
714 x
->inputs
= (t_sample
**)malloc(x
->n_in
*sizeof(t_sample
*));
716 x
->outputs
= (t_sample
**)malloc(x
->n_out
*sizeof(t_sample
*));
717 x
->buf
= (t_sample
**)malloc(x
->n_out
*sizeof(t_sample
*));
719 if ((x
->n_in
> 0 && x
->inputs
== NULL
) ||
720 (x
->n_out
> 0 && (x
->outputs
== NULL
|| x
->buf
== NULL
)))
722 for (int i
= 0; i
< x
->n_out
; i
++)
725 x
->dsp
->buildUserInterface(x
->ui
);
726 for (int i
= 0; i
< x
->n_in
; i
++)
727 inlet_new(&x
->x_obj
, &x
->x_obj
.ob_pd
, &s_signal
, &s_signal
);
728 x
->out
= outlet_new(&x
->x_obj
, 0);
729 for (int i
= 0; i
< x
->n_out
; i
++)
730 outlet_new(&x
->x_obj
, &s_signal
);
734 x
->dsp
= NULL
; x
->ui
= NULL
;
735 x
->inputs
= x
->outputs
= x
->buf
= NULL
;
739 extern "C" void faust_setup(mydsp
)
741 t_symbol
*s
= gensym(sym(mydsp
) "~");
743 class_new(s
, (t_newmethod
)faust_new
, (t_method
)faust_free
,
744 sizeof(t_faust
), CLASS_DEFAULT
,
746 class_addmethod(faust_class
, (t_method
)faust_dsp
, gensym((char*)"dsp"), A_NULL
);
747 class_addanything(faust_class
, faust_any
);
748 class_addmethod(faust_class
, nullfn
, &s_signal
, A_NULL
);
749 s_button
= gensym((char*)"button");
750 s_checkbox
= gensym((char*)"checkbox");
751 s_vslider
= gensym((char*)"vslider");
752 s_hslider
= gensym((char*)"hslider");
753 s_nentry
= gensym((char*)"nentry");
754 s_vbargraph
= gensym((char*)"vbargraph");
755 s_hbargraph
= gensym((char*)"hbargrap");
756 /* give some indication that we're loaded and ready to go */
758 post("[faust] %s: %d inputs, %d outputs", sym(mydsp
) "~",
759 dsp
.getNumInputs(), dsp
.getNumOutputs());