1 /************************************************************************
3 IMPORTANT NOTE : this file contains two clearly delimited sections :
4 the ARCHITECTURE section (in two parts) and the USER section. Each section
5 is governed by its own copyright and license. Please check individually
6 each section for license and copyright information.
7 *************************************************************************/
9 /*******************BEGIN ARCHITECTURE SECTION (part 1/2)****************/
11 /************************************************************************
12 FAUST Architecture File
13 Copyright (C) 2004-2011 GRAME, Centre National de Creation Musicale
14 ---------------------------------------------------------------------
15 This Architecture section is free software; you can redistribute it
16 and/or modify it under the terms of the GNU Lesser General Public
17 License as published by the Free Software Foundation; either version 3
18 of the License, or (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU Lesser General Public License for more details.
25 You should have received a copy of the GNU Lesser General Public License
26 along with this program; If not, see <http://www.gnu.org/licenses/>.
28 EXCEPTION : As a special exception, you may create a larger work
29 that contains this FAUST architecture section and distribute
30 that work under terms of your choice, so long as this FAUST
31 architecture section is not modified.
33 MAX MSP SDK : in order to compile a MaxMSP external with this
34 architecture file you will need the official MaxMSP SDK from
35 cycling'74. Please check the corresponding license.
37 ************************************************************************
38 ************************************************************************/
56 #include <Carbon/Carbon.h>
61 #include "audio/dsp.h"
66 // There is a bug with powf() when cross compiling with mingw
67 // the following macro avoid the problem
69 #define powf(x,y) pow(x,y)
70 #define expf(x) exp(x)
75 //-------------------------------------------------------------------
76 // Generic min and max using gcc extensions
77 //-------------------------------------------------------------------
79 #define max(x,y) (((x)>(y)) ? (x) : (y))
80 #define min(x,y) (((x)<(y)) ? (x) : (y))
84 //-------------------------------------------------------------------
85 // Generic min and max using c++ inline
86 //-------------------------------------------------------------------
88 inline int max(unsigned int a
, unsigned int b
) { return (a
>b
) ? a
: b
; }
89 inline int max(int a
, int b
) { return (a
>b
) ? a
: b
; }
91 inline long max(long a
, long b
) { return (a
>b
) ? a
: b
; }
92 inline long max(int a
, long b
) { return (a
>b
) ? a
: b
; }
93 inline long max(long a
, int b
) { return (a
>b
) ? a
: b
; }
95 inline float max(float a
, float b
) { return (a
>b
) ? a
: b
; }
96 inline float max(int a
, float b
) { return (a
>b
) ? a
: b
; }
97 inline float max(float a
, int b
) { return (a
>b
) ? a
: b
; }
98 inline float max(long a
, float b
) { return (a
>b
) ? a
: b
; }
99 inline float max(float a
, long b
) { return (a
>b
) ? a
: b
; }
101 inline double max(double a
, double b
) { return (a
>b
) ? a
: b
; }
102 inline double max(int a
, double b
) { return (a
>b
) ? a
: b
; }
103 inline double max(double a
, int b
) { return (a
>b
) ? a
: b
; }
104 inline double max(long a
, double b
) { return (a
>b
) ? a
: b
; }
105 inline double max(double a
, long b
) { return (a
>b
) ? a
: b
; }
106 inline double max(float a
, double b
) { return (a
>b
) ? a
: b
; }
107 inline double max(double a
, float b
) { return (a
>b
) ? a
: b
; }
110 inline int min(int a
, int b
) { return (a
<b
) ? a
: b
; }
112 inline long min(long a
, long b
) { return (a
<b
) ? a
: b
; }
113 inline long min(int a
, long b
) { return (a
<b
) ? a
: b
; }
114 inline long min(long a
, int b
) { return (a
<b
) ? a
: b
; }
116 inline float min(float a
, float b
) { return (a
<b
) ? a
: b
; }
117 inline float min(int a
, float b
) { return (a
<b
) ? a
: b
; }
118 inline float min(float a
, int b
) { return (a
<b
) ? a
: b
; }
119 inline float min(long a
, float b
) { return (a
<b
) ? a
: b
; }
120 inline float min(float a
, long b
) { return (a
<b
) ? a
: b
; }
122 inline double min(double a
, double b
) { return (a
<b
) ? a
: b
; }
123 inline double min(int a
, double b
) { return (a
<b
) ? a
: b
; }
124 inline double min(double a
, int b
) { return (a
<b
) ? a
: b
; }
125 inline double min(long a
, double b
) { return (a
<b
) ? a
: b
; }
126 inline double min(double a
, long b
) { return (a
<b
) ? a
: b
; }
127 inline double min(float a
, double b
) { return (a
<b
) ? a
: b
; }
128 inline double min(double a
, float b
) { return (a
<b
) ? a
: b
; }
132 /******************************************************************************
133 *******************************************************************************
137 *******************************************************************************
138 *******************************************************************************/
142 /********************END ARCHITECTURE SECTION (part 1/2)****************/
144 /**************************BEGIN USER SECTION **************************/
148 /***************************END USER SECTION ***************************/
150 /*******************BEGIN ARCHITECTURE SECTION (part 2/2)***************/
153 /* Faust code wrapper ------- */
159 #define ASSIST_INLET 1 /* should be defined somewhere ?? */
160 #define ASSIST_OUTLET 2 /* should be defined somewhere ?? */
164 /*--------------------------------------------------------------------------*/
168 t_atom
*m_seen
,*m_want
;
177 /*--------------------------------------------------------------------------*/
185 float range(float min
, float max
, float val
) {return (val
< min
) ? min
: (val
> max
) ? max
: val
;}
189 mspUIObject(const char* label
, float* zone
):fLabel(label
),fZone(zone
) {}
190 virtual ~mspUIObject() {}
192 virtual void SetValue(double f
) {*fZone
= range(0.0,1.0,f
);}
193 virtual void toString(char* buffer
) {}
194 virtual string
GetName() {return fLabel
;}
197 /*--------------------------------------------------------------------------*/
198 class mspToggleButton
: public mspUIObject
{
202 mspToggleButton(const char* label
, float* zone
):mspUIObject(label
,zone
) {}
203 virtual ~mspToggleButton() {}
205 void toString(char* buffer
)
208 sprintf(buffer
, "ToggleButton(float): %s", fLabel
.c_str());
210 std::sprintf(buffer
, "ToggleButton(float): %s", fLabel
.c_str());
215 /*--------------------------------------------------------------------------*/
216 class mspCheckButton
: public mspUIObject
{
220 mspCheckButton(const char* label
, float* zone
):mspUIObject(label
,zone
) {}
221 virtual ~mspCheckButton() {}
223 void toString(char* buffer
)
226 sprintf(buffer
, "CheckButton(float): %s", fLabel
.c_str());
228 std::sprintf(buffer
, "CheckButton(float): %s", fLabel
.c_str());
233 /*--------------------------------------------------------------------------*/
234 class mspButton
: public mspUIObject
{
238 mspButton(const char* label
, float* zone
):mspUIObject(label
,zone
) {}
239 virtual ~mspButton() {}
241 void toString(char* buffer
)
244 sprintf(buffer
, "Button(float): %s", fLabel
.c_str());
246 std::sprintf(buffer
, "Button(float): %s", fLabel
.c_str());
251 /*--------------------------------------------------------------------------*/
252 class mspSlider
: public mspUIObject
{
263 mspSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
264 :mspUIObject(label
,zone
),fInit(init
),fMin(min
),fMax(max
),fStep(step
) {}
265 virtual ~mspSlider() {}
267 void toString(char* buffer
)
270 sprintf(buffer
, "Slider(float): %s [%.1f:%.1f:%.1f]", fLabel
.c_str(), fMin
, fInit
, fMax
);
272 std::sprintf(buffer
, "Slider(float): %s [%.1f:%.1f:%.1f]", fLabel
.c_str(), fMin
, fInit
, fMax
);
276 void SetValue(double f
) {*fZone
= range(fMin
,fMax
,f
);}
279 /*--------------------------------------------------------------------------*/
280 class mspUI
: public UI
284 map
<string
,mspUIObject
*> fUITable
;
287 typedef map
<string
,mspUIObject
*>::iterator iterator
;
292 for (iterator iter
= fUITable
.begin(); iter
!= fUITable
.end(); iter
++)
293 delete (iter
->second
);
296 void addButton(const char* label
, float* zone
) {fUITable
[string(label
)] = new mspButton(label
, zone
);}
298 void addToggleButton(const char* label
, float* zone
) {fUITable
[string(label
)] = new mspToggleButton(label
, zone
);}
300 void addCheckButton(const char* label
, float* zone
) {fUITable
[string(label
)] = new mspCheckButton(label
, zone
);}
302 void addVerticalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
304 fUITable
[string(label
)] = new mspSlider(label
, zone
, init
, min
, max
, step
);
307 void addHorizontalSlider(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
309 fUITable
[string(label
)] = new mspSlider(label
, zone
, init
, min
, max
, step
);
312 void addNumEntry(const char* label
, float* zone
, float init
, float min
, float max
, float step
)
314 fUITable
[string(label
)] = new mspSlider(label
, zone
, init
, min
, max
, step
);
317 void openFrameBox(const char* label
) {}
318 void openTabBox(const char* label
) {}
319 void openHorizontalBox(const char* label
) {}
320 void openVerticalBox(const char* label
) {}
323 void SetValue(string name
, double f
)
325 if(fUITable
.count(name
))
326 fUITable
[name
]->SetValue(f
);
328 iterator
begin() {return fUITable
.begin();}
329 iterator
end() {return fUITable
.end();}
332 void addNumDisplay(const char* label
, float* zone
, int precision
) {}
333 void addTextDisplay(const char* label
, float* zone
, const char* names
[], float min
, float max
) {}
334 void addHorizontalBargraph(const char* label
, float* zone
, float min
, float max
) {}
335 void addVerticalBargraph(const char* label
, float* zone
, float min
, float max
) {}
338 //--------------------------------------------------------------------------
339 void faust_method(t_faust
*obj
, t_symbol
*s
, short ac
, t_atom
*at
)
342 if(at
[0].a_type
!= A_FLOAT
) return;
344 string name
= string( (s
)->s_name
);
345 float value
= at
[0].a_w
.w_float
;
347 // lookup du nom dans une std::map<string,mspUIObject *>
348 // ou une std::map<string,float *>
349 // et affectation de value;
350 obj
->dspUI
->SetValue(name
,value
); // doesn't have any effect if name is unknown
353 /*--------------------------------------------------------------------------*/
354 void *faust_new(t_symbol
*s
, short ac
, t_atom
*av
)
356 t_faust
*x
= (t_faust
*)newobject(faust_class
);
358 x
->dsp
= new mydsp();
359 x
->dspUI
= new mspUI();
361 x
->dsp
->init(long(sys_getsr()));
362 x
->dsp
->buildUserInterface(x
->dspUI
);
364 x
->args
= (void**)calloc((x
->dsp
->getNumInputs()+x
->dsp
->getNumOutputs())+2, sizeof(void*));
367 dsp_setup((t_pxobject
*)x
, x
->dsp
->getNumInputs());
370 for (int i
= 0; i
< x
->dsp
->getNumOutputs(); i
++)
371 outlet_new((t_pxobject
*)x
, (char*)"signal");
373 ((t_pxobject
*)x
)->z_misc
= Z_NO_INPLACE
; // To assure input and output buffers are actually different
377 /*--------------------------------------------------------------------------*/
378 void faust_assist(t_faust
*x
, void *b
, long msg
, long a
, char *dst
)
380 if (msg
== ASSIST_INLET
) {
382 if (x
->dsp
->getNumInputs() == 0) {
384 sprintf(dst
, "(signal) : Unused Input");
386 std::sprintf(dst
, "(signal) : Unused Input");
390 sprintf(dst
, "(signal) : Audio Input %ld", (a
+1));
392 std::sprintf(dst
, "(signal) : Audio Input %ld", (a
+1));
395 post((char*)"------------------");
396 for (mspUI::iterator it
= x
->dspUI
->begin(); it
!= x
->dspUI
->end(); ++it
) {
398 it
->second
->toString(param
);
401 } else if (a
< x
->dsp
->getNumInputs()) {
403 sprintf(dst
, "(signal) : Audio Input %ld", (a
+1));
405 std::sprintf(dst
, "(signal) : Audio Input %ld", (a
+1));
408 } else if (msg
== ASSIST_OUTLET
) {
410 sprintf(dst
, "(signal) : Audio Output %ld", (a
+1));
412 std::sprintf(dst
, "(signal) : Audio Output %ld", (a
+1));
417 /*--------------------------------------------------------------------------*/
418 void faust_free(t_faust
*x
)
420 dsp_free((t_pxobject
*)x
);
421 if (x
->dsp
) delete x
->dsp
;
422 if (x
->dspUI
) delete x
->dspUI
;
423 if (x
->args
)free(x
->args
);
426 /*--------------------------------------------------------------------------*/
427 t_int
*faust_perform(t_int
*w
)
429 t_faust
* x
= (t_faust
*) (w
[1]);
433 x
->dsp
->compute(n
, ((float**)&w
[offset
]), ((float**)&w
[offset
+x
->dsp
->getNumInputs()]));
434 return (w
+ (x
->dsp
->getNumInputs()+x
->dsp
->getNumOutputs())+2+1);
437 /*--------------------------------------------------------------------------*/
438 void faust_dsp(t_faust
*x
, t_signal
**sp
, short *count
)
441 x
->args
[1] = (void*)sp
[0]->s_n
;
442 for (int i
= 0; i
<(x
->dsp
->getNumInputs()+x
->dsp
->getNumOutputs()); i
++)
443 x
->args
[i
+2] = sp
[i
]->s_vec
;
444 dsp_addv(faust_perform
, (x
->dsp
->getNumInputs()+x
->dsp
->getNumOutputs())+2, x
->args
);
447 /*--------------------------------------------------------------------------*/
450 setup((t_messlist
**)&faust_class
, (method
)faust_new
, (method
)faust_free
,
451 (short)sizeof(t_faust
), 0L, A_DEFFLOAT
, 0);
453 dsp
*thedsp
= new mydsp();
454 mspUI
*dspUI
= new mspUI();
455 thedsp
->buildUserInterface(dspUI
);
457 // Add the same method for every parameters and use the symbol as a selector
458 // inside thid method
459 for (mspUI::iterator it
= dspUI
->begin(); it
!= dspUI
->end(); ++it
) {
460 char *name
= const_cast<char *>(it
->second
->GetName().c_str());
461 addmess((method
)faust_method
, name
, A_GIMME
, 0);
464 addmess((method
)faust_dsp
, (char*)"dsp", A_CANT
, 0);
465 addmess((method
)faust_assist
, (char*)"assist", A_CANT
, 0);
470 post((char*)"Faust DSP object");
474 /********************END ARCHITECTURE SECTION (part 2/2)****************/