Jamoma API  0.6.0.a19
j.envexp.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.envexp - Create envelope with linear attack and exponential decay.
6  *
7  * @details This object replaces tl.envexp, previously a part of the tl.objects distribution.
8  *
9  * @authors Trond Lossius, Tim Place, Peter Castine, Jan Schacher, François-Eudes Chanfrault, Jeremy Bernstein
10  *
11  * @copyright Copyright © 2006, Trond Lossius @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
17 /* ****************************************************************************
18 *
19 * Input:
20 * list: Maximum amplitude, attack time, decay time
21 * bang: Trigger new amplitude using stored values
22 * set: Set envelope properties without triggering
23 * threshold (float):
24 * Change low threshold value
25 * steal (int):
26 * Enable/disable note stealing
27 *
28 * Arguments:
29 * int: Threshold amplitude. Envelope is terminated when this low
30 * threshold is reached. Defaults to -90 dB.
31 * int: Note stealing properties.
32 * If 0: Note stealing disabled. When a envelope is
33 * triggered, a "0" is sent first so that amplitude
34 * immediately is set to 0.
35 * If non-zero: "0" is not sent. Hence the attack section
36 * of the envelope takes of from current amplitude
37 * value.
38 * Defaults to 1 (non-zero)
39 * Output:
40 * list: Envelope in line~ format.
41 * int: If note-stealing is disabled, the value "0" is transmitted
42 * prior to list of envelope data.
43 *
44 * Trond Lossius 2000-06-26
45 ********************************************************************************/
46 
47 #include "JamomaForMax.h" // include Jamoma lib
48 
49 
50 #define NUM_OF_POINTS 128 ///< maximum number of points that line~ accepts
51 
52 typedef struct _envExp { ///< Data structure for this object
53  t_object ob; ///< REQUIRED: Our object
54  void *outlet; ///< pointer to outlet. Need one for each outlet
55  t_atom envelope[NUM_OF_POINTS * 2]; ///< array of envelope points in line~ format
56  double attr_coeff; ///< exponential coeffisient. Depends on threshold, decay rate and number of points that envelope is made from
57  double attr_amplitude; ///< ATTRIBUTE: peak amplitude
58  double attr_attack; ///< ATTRIBUTE: attack time in ms
59  double attr_decayrate; ///< ATTRIBUTE: how many dB amplitude decrease per second during the decay
60  double attr_threshold; ///< ATTRIBUTE: low threshold for forcing amplitude to zero
61  long attr_steal; ///< ATTRIBUTE: note stealing enabled/disabled (boolean)
62 } t_envExp;
63 
64 
65 
66 // Prototypes for methods: need a method for each incoming message
67 
68 /** Creates new instance */
69 void *envExp_new(Symbol *s, long argc, t_atom *argv);
70 
71 /** Trigger new amplitude envelope using currenlty stored values
72  * @return array of data points for envelope
73  */
74 void envExp_bang(t_envExp *x);
75 
76 /** Set peak amplitude attribute and trigger output
77  * @return array of data points for envelope
78  */
79 void envExp_float(t_envExp *x, double f);
80 
81 /** Provides assistance cues
82  * @return pointer to assistance cue
83  */
84 void envExp_assist(t_envExp *x, void *b, long msg, long arg, char *dst);
85 
86 /** Set attack time in ms */
87 void envExp_setattack(t_envExp *x, void *attr, long argc, t_atom *argv);
88 
89 /** Sets the peak amplitude */
90 void envExp_setamplitude(t_envExp *x, void *attr, long argc, t_atom *argv);
91 
92 /** Sets the decay rate attribute */
93 void envExp_setdecayrate(t_envExp *x, void *attr, long argc, t_atom *argv);
94 
95 /** Sets the threshold attribute */
96 void envExp_setthreshold(t_envExp *x, void *attr, long argc, t_atom *argv);
97 
98 /** Sets the note stealing attribute */
99 void envExp_steal(t_envExp *x, long var);
100 
101 /** Calculates array of envelope points
102  */
103 void envExp_calculate(t_envExp *x);
104 
105 
106 
107 // Globals
108 t_class *this_class; ///< Required. Global pointing to this class
109 t_symbol *jps_symbol;
110 t_symbol *jps_long;
111 t_symbol *jps_float32;
112 t_symbol *jps_dumpout;
113 
114 
115 /** Class Definition
116  */
117 int JAMOMA_EXPORT_MAXOBJ main(void)
118 {
119  //post("main");
120 
121  long attrflags = 0;
122  t_class *c;
123  t_object *attr;
124 
125  common_symbols_init();
126  jps_symbol = gensym("symbol");
127  jps_long = gensym("long");
128  jps_float32 = gensym("float32");
129  jps_dumpout = gensym("dumpout");
130 
131  // Define our class
132  c = class_new("j.envexp",(method)envExp_new, 0L, sizeof(t_envExp), (method)0L, A_GIMME, 0);
133 
134  // Make methods accessible for our class:
135  class_addmethod(c, (method)envExp_bang, "bang", A_CANT, 0);
136  class_addmethod(c, (method)envExp_float, "float", A_FLOAT, 0);
137  class_addmethod(c, (method)envExp_assist, "assist", A_CANT, 0);
138  class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
139 
140  // ATTRIBUTE: attack
141  attr = attr_offset_new("attack", jps_float32, attrflags,
142  (method)0L, (method)envExp_setattack, calcoffset(t_envExp, attr_attack));
143  class_addattr(c, attr);
144 
145  // ATTRIBUTE: maximum amplitude
146  attr = attr_offset_new("amplitude", jps_float32, attrflags,
147  (method)0L, (method)envExp_setamplitude, calcoffset(t_envExp, attr_amplitude));
148  class_addattr(c, attr);
149 
150  // ATTRIBUTE: decay rate
151  attr = attr_offset_new("decayrate", jps_float32, attrflags,
152  (method)0L, (method)envExp_setdecayrate, calcoffset(t_envExp, attr_decayrate));
153  class_addattr(c, attr);
154 
155  // ATTRIBUTE: low threshold
156  attr = attr_offset_new("threshold", jps_float32, attrflags,
157  (method)0L, (method)envExp_setthreshold, calcoffset(t_envExp, attr_threshold));
158  class_addattr(c, attr);
159 
160  // ATTRIBUTE: note stealing
161  attr = attr_offset_new("steal", jps_long, attrflags,
162  (method)0L, (method)0L, calcoffset(t_envExp, attr_steal));
163  class_addattr(c, attr);
164 
165  // Finalize our class
166  class_register(CLASS_BOX, c);
167  this_class = c;
168 
169  return 0;
170 }
171 
172 
173 /************************************************************************************/
174 #pragma mark -
175 #pragma mark life cycle
176 
177 
178 void *envExp_new(Symbol *s, long argc, t_atom *argv)
179 {
180  //create the new instance and returns a pointer to it
181  t_envExp *x = (t_envExp *)object_alloc(this_class);
182 
183  //post("new");
184  if (x) {
185  //post("new_x");
186  // dumpout
187  object_obex_store((void *)x, jps_dumpout, (object *)outlet_new(x,NULL));
188  // create outlet
189  x->outlet =outlet_new(x, 0L);
190 
191  //Initialisation of attributes
192  x->attr_attack = 10;
193  x->attr_amplitude = 1.;
194  x->attr_decayrate = 90.;
195  x->attr_threshold = -90;
196  x->attr_steal = 1;
197  // handle attribute args
198  attr_args_process(x,argc,argv);
199  envExp_calculate(x);
200  }
201  return(x); //must return a pointer to the new instance
202 }
203 
204 
205 /************************************************************************************/
206 // Methods bound to input/inlets
207 #pragma mark -
208 #pragma mark methods
209 
210 
211 void envExp_bang(t_envExp *x)
212 {
213  if (!x->attr_steal)
214  outlet_float(x->outlet, 0.);
215  outlet_list(x->outlet, 0L, NUM_OF_POINTS * 2, x->envelope);
216 }
217 
218 
219 // Set peak amplitude and trigger output
220 void envExp_float(t_envExp *x, double f)
221 {
222  x->attr_amplitude = f;
223  envExp_calculate(x);
224  envExp_bang(x);
225 }
226 
227 
228 // Set attack
229 void envExp_setattack(t_envExp *x, void *attr, long argc, t_atom *argv)
230 {
231  double f;
232 
233  if (argc)
234  {
235  f = atom_getfloat(argv);
236  if (f>=0)
237  x->attr_attack = f;
238  envExp_calculate(x);
239  }
240 }
241 
242 
243 // Set amplitude
244 void envExp_setamplitude(t_envExp *x, void *attr, long argc, t_atom *argv)
245 {
246  if (argc)
247  {
248  x->attr_amplitude = atom_getfloat(argv);
249  envExp_calculate(x);
250  }
251 }
252 
253 
254 // Set decay rate
255 void envExp_setdecayrate(t_envExp *x, void *attr, long argc, t_atom *argv)
256 {
257  double f;
258 
259  if (argc)
260  {
261  f = atom_getfloat(argv);
262  if (f>0)
263  {
264  x->attr_decayrate = f;
265  envExp_calculate(x);
266  }
267  }
268 }
269 
270 
271 // Set threshold
272 void envExp_setthreshold(t_envExp *x, void *attr, long argc, t_atom *argv)
273 {
274  double f;
275  if (argc) {
276  f = atom_getfloat(argv);
277  if (f >= 0)
278  error ("j.envexp: Invalid threshold value");
279  else {
280  x->attr_threshold = f;
281  envExp_calculate(x);
282  }
283  }
284 }
285 
286 
287 /* Display assistance messages */
288 void envExp_assist(t_envExp *x, void *b, long msg, long arg, char *dst)
289 {
290  if (msg==1) {
291  switch(arg) {
292  case 0: strcpy(dst, "(List) Max. ampl, attack time, decay time");
293  break;
294  }
295  }
296  else if (msg==2) {
297  strcpy(dst, "Envelope data in line~ format");
298  }
299 }
300 
301 
302 
303 
304 /************************************************************************************/
305 // Internal methods used to calculate envelope
306 #pragma mark -
307 #pragma mark calculations
308 
309 
310 void envExp_calculate(t_envExp *x)
311 {
312  long i, j;
313  double timestep, k;
314 
315  // write delta time steps to array
316  j = 1;
317  atom_setfloat(&x->envelope[j], x->attr_attack);
318  timestep = (-1000.*x->attr_threshold) /(x->attr_decayrate*(NUM_OF_POINTS - 2.));
319  for (i=1; i<NUM_OF_POINTS; i++)
320  {
321  j = j+2;
322  atom_setfloat(&x->envelope[j], timestep);
323  }
324 
325  /* write amplitude values to array */
326  k = pow(10.,-0.05*x->attr_decayrate);
327  for (i=0; i<(NUM_OF_POINTS-1); i++)
328  {
329  j = 2*i;
330  atom_setfloat(&x->envelope[j], x->attr_amplitude*pow(k,i*timestep*0.001) );
331  }
332  j = (NUM_OF_POINTS-1)*2;
333  atom_setfloat(&x->envelope[j], 0.);
334 }
335 
void envExp_bang(t_envExp *x)
Trigger new amplitude envelope using currenlty stored values.
Definition: j.envexp.cpp:211
int JAMOMA_EXPORT_MAXOBJ main(void)
Class Definition.
Definition: j.envexp.cpp:117
void envExp_setattack(t_envExp *x, void *attr, long argc, t_atom *argv)
Set attack time in ms.
Definition: j.envexp.cpp:229
void envExp_setthreshold(t_envExp *x, void *attr, long argc, t_atom *argv)
Sets the threshold attribute.
Definition: j.envexp.cpp:272
void envExp_steal(t_envExp *x, long var)
Sets the note stealing attribute.
void envExp_calculate(t_envExp *x)
Calculates array of envelope points.
Definition: j.envexp.cpp:310
void envExp_setamplitude(t_envExp *x, void *attr, long argc, t_atom *argv)
Sets the peak amplitude.
Definition: j.envexp.cpp:244
Various utilities for interfacing with Max that are not specific to JamomaModular as such...
void envExp_float(t_envExp *x, double f)
Set peak amplitude attribute and trigger output.
Definition: j.envexp.cpp:220
#define NUM_OF_POINTS
maximum number of points that line~ accepts
Definition: j.envexp.cpp:50
void * envExp_new(Symbol *s, long argc, t_atom *argv)
Creates new instance.
Definition: j.envexp.cpp:178
void envExp_assist(t_envExp *x, void *b, long msg, long arg, char *dst)
Provides assistance cues.
Definition: j.envexp.cpp:288
t_class * this_class
Required. Global pointing to this class.
Definition: j.envexp.cpp:108
void envExp_setdecayrate(t_envExp *x, void *attr, long argc, t_atom *argv)
Sets the decay rate attribute.
Definition: j.envexp.cpp:255