1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// signal1~ - a flext tutorial external written by Frank Barknecht
//
// This is a commented port of the pan~ example from the PD-Externals-Howto to
// illustrate the usage of flext. You can get the original code at
// http://iem.kug.ac.at/pd/externals-HOWTO/
#include <flext.h>
#include <math.h>
#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 300)
#error You need at least flext version 0.3.0
#endif
// A flext dsp external ("tilde object") inherits from the class flext_dsp
class signal1:
public flext_dsp
{
// Each external that is written in C++ needs to use #defines
// from flbase.h
//
// The define
//
// FLEXT_HEADER(NEW_CLASS, PARENT_CLASS)
//
// should be somewhere in your dsp file.
// A good place is here:
FLEXT_HEADER(signal1, flext_dsp)
public:
signal1():
f_pan(0) // initialize f_pan
{
// The constructor of your class is responsible for
// setting up inlets and outlets and for registering
// inlet-methods:
AddInSignal(2); // 2 audio ins
AddInFloat(); // 1 float in
AddOutSignal(); // 1 audio out [ == AddOutSignal(1) ]
SetupInOut(); // set up inlets and outlets.
// Must be called once!
// Now we need to bind the handler function to our
// panning inlet, which is inlet 2 (counting all inlets
// from 0). We want the function "setPan" to get
// called on incoming float messages:
FLEXT_ADDMETHOD(2,setPan);
// We're done constructing:
post("-- pan~ with flext ---");
} // end of constructor
protected:
// here we declare the virtual DSP function
virtual void m_signal(int n, float *const *in, float *const *out);
private:
float f_pan; // holds our panning factor
// Before we can use "setPan" as a handler, we must register this
// function as a callback to PD or Max. This is done using the
// FLEXT_CALLBACK* macros. There are several of them.
//
// FLEXT_CALLBACK_F is a shortcut, that registers a function
// expecting one float arg (thus ending in "_F"). There are
// other shortcuts that register other types of functions. Look
// into flext.h. No semicolon at the end of line!!!
FLEXT_CALLBACK_F(setPan)
// Now setPan can get declared and defined here.
void setPan(float f)
{
// set our private panning factor "f_pan" to the inlet
// value float "f" in the intervall [0,1]
f_pan = (f<0) ? 0.0f : (f>1) ? 1.0f : f ;
// if you want to debug if this worked, comment out the
// following line:
//post("Set panning to %.2f, maybe clipped from %.2f", f_pan,f);
} // end setPan
}; // end of class declaration for signal1
// Before we can run our signal1-class in PD, the object has to be registered as a
// PD object. Otherwise it would be a simple C++-class, and what good would
// that be for? Registering is made easy with the FLEXT_NEW_* macros defined
// in flext.h. For tilde objects without arguments call:
FLEXT_NEW_DSP("signal1~ signal1~", signal1)
// T.Grill: there are two names for the object: signal1~ as main name and pan~ as its alias
// Now we define our DSP function. It gets this arguments:
//
// int n: length of signal vector. Loop over this for your signal processing.
// float *const *in, float *const *out:
// These are arrays of the signals in the objects signal inlets rsp.
// oulets. We come to that later inside the function.
void signal1::m_signal(int n, float *const *in, float *const *out)
{
const float *ins1 = in[0];
const float *ins2 = in[1];
// As said above "in" holds a list of the signal vectors in all inlets.
// After these two lines, ins1 holds the signal vector ofthe first
// inlet, index 0, and ins2 holds the signal vector of the second
// inlet, with index 1.
float *outs = out[0];
// Now outs holds the signal vector at the one signal outlet we have.
// We are now ready for the main signal loop
while (n--)
{
// The "++" after the pointers outs, ins1 and ins2 walks us
// through the signal vector with each n, of course. Before
// each step we change the signal value in the outlet *outs
// according to our panning factor "f_pan" and according to the
// signals at the two signal inlets, *ins1 and *ins2
*outs++ = (*ins1++) * (1-f_pan) + (*ins2++) * f_pan;
}
} // end m_signal
|