~ubuntu-branches/debian/sid/python-pyo/sid

« back to all changes in this revision

Viewing changes to src/objects/analysismodule.c

  • Committer: Package Import Robot
  • Author(s): Tiago Bortoletto Vaz
  • Date: 2012-06-08 20:35:45 UTC
  • Revision ID: package-import@ubuntu.com-20120608203545-4z7kcf2lgvpsk18y
Tags: upstream-0.6.1
ImportĀ upstreamĀ versionĀ 0.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*************************************************************************
 
2
 * Copyright 2010 Olivier Belanger                                        *                  
 
3
 *                                                                        * 
 
4
 * This file is part of pyo, a python module to help digital signal       *
 
5
 * processing script creation.                                            *  
 
6
 *                                                                        * 
 
7
 * pyo is free software: you can redistribute it and/or modify            *
 
8
 * it under the terms of the GNU General Public License as published by   *
 
9
 * the Free Software Foundation, either version 3 of the License, or      *
 
10
 * (at your option) any later version.                                    * 
 
11
 *                                                                        *
 
12
 * pyo is distributed in the hope that it will be useful,                 *
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 
15
 * GNU General Public License for more details.                           *
 
16
 *                                                                        *
 
17
 * You should have received a copy of the GNU General Public License      *
 
18
 * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
 
19
 *************************************************************************/
 
20
#include <Python.h>
 
21
#include "structmember.h"
 
22
#include <math.h>
 
23
#include "pyomodule.h"
 
24
#include "streammodule.h"
 
25
#include "servermodule.h"
 
26
#include "dummymodule.h"
 
27
 
 
28
/************/
 
29
/* Follower */
 
30
/************/
 
31
typedef struct {
 
32
    pyo_audio_HEAD
 
33
    PyObject *input;
 
34
    Stream *input_stream;
 
35
    PyObject *freq;
 
36
    Stream *freq_stream;
 
37
    int modebuffer[3]; // need at least 2 slots for mul & add 
 
38
    MYFLT follow;
 
39
    MYFLT last_freq;
 
40
    MYFLT factor;
 
41
} Follower;
 
42
 
 
43
static void
 
44
Follower_filters_i(Follower *self) {
 
45
    MYFLT absin, freq;
 
46
    int i;
 
47
 
 
48
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
49
    freq = PyFloat_AS_DOUBLE(self->freq);
 
50
 
 
51
    if (freq != self->last_freq) {
 
52
        self->factor = MYEXP(-1.0 / (self->sr / freq));
 
53
        self->last_freq = freq;
 
54
    }
 
55
    
 
56
    for (i=0; i<self->bufsize; i++) {
 
57
        absin = in[i];
 
58
        if (absin < 0.0)
 
59
            absin = -absin;
 
60
        self->follow = self->data[i] = absin + self->factor * (self->follow - absin);
 
61
    }
 
62
}
 
63
 
 
64
static void
 
65
Follower_filters_a(Follower *self) {
 
66
    MYFLT freq, absin;
 
67
    int i;
 
68
    
 
69
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
70
    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
 
71
    
 
72
    for (i=0; i<self->bufsize; i++) {
 
73
        freq = fr[i];
 
74
        if (freq != self->last_freq) {
 
75
            self->factor = MYEXP(-1.0 / (self->sr / freq));
 
76
            self->last_freq = freq;
 
77
        }
 
78
        absin = in[i];
 
79
        if (absin < 0.0)
 
80
            absin = -absin;
 
81
        self->follow = self->data[i] = absin + self->factor * (self->follow - absin);        
 
82
    }
 
83
}
 
84
 
 
85
static void Follower_postprocessing_ii(Follower *self) { POST_PROCESSING_II };
 
86
static void Follower_postprocessing_ai(Follower *self) { POST_PROCESSING_AI };
 
87
static void Follower_postprocessing_ia(Follower *self) { POST_PROCESSING_IA };
 
88
static void Follower_postprocessing_aa(Follower *self) { POST_PROCESSING_AA };
 
89
static void Follower_postprocessing_ireva(Follower *self) { POST_PROCESSING_IREVA };
 
90
static void Follower_postprocessing_areva(Follower *self) { POST_PROCESSING_AREVA };
 
91
static void Follower_postprocessing_revai(Follower *self) { POST_PROCESSING_REVAI };
 
92
static void Follower_postprocessing_revaa(Follower *self) { POST_PROCESSING_REVAA };
 
93
static void Follower_postprocessing_revareva(Follower *self) { POST_PROCESSING_REVAREVA };
 
94
 
 
95
static void
 
96
Follower_setProcMode(Follower *self)
 
97
{
 
98
    int procmode, muladdmode;
 
99
    procmode = self->modebuffer[2];
 
100
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
101
    
 
102
        switch (procmode) {
 
103
        case 0:    
 
104
            self->proc_func_ptr = Follower_filters_i;
 
105
            break;
 
106
        case 1:    
 
107
            self->proc_func_ptr = Follower_filters_a;
 
108
            break;
 
109
    } 
 
110
        switch (muladdmode) {
 
111
        case 0:        
 
112
            self->muladd_func_ptr = Follower_postprocessing_ii;
 
113
            break;
 
114
        case 1:    
 
115
            self->muladd_func_ptr = Follower_postprocessing_ai;
 
116
            break;
 
117
        case 2:    
 
118
            self->muladd_func_ptr = Follower_postprocessing_revai;
 
119
            break;
 
120
        case 10:        
 
121
            self->muladd_func_ptr = Follower_postprocessing_ia;
 
122
            break;
 
123
        case 11:    
 
124
            self->muladd_func_ptr = Follower_postprocessing_aa;
 
125
            break;
 
126
        case 12:    
 
127
            self->muladd_func_ptr = Follower_postprocessing_revaa;
 
128
            break;
 
129
        case 20:        
 
130
            self->muladd_func_ptr = Follower_postprocessing_ireva;
 
131
            break;
 
132
        case 21:    
 
133
            self->muladd_func_ptr = Follower_postprocessing_areva;
 
134
            break;
 
135
        case 22:    
 
136
            self->muladd_func_ptr = Follower_postprocessing_revareva;
 
137
            break;
 
138
    }   
 
139
}
 
140
 
 
141
static void
 
142
Follower_compute_next_data_frame(Follower *self)
 
143
{
 
144
    (*self->proc_func_ptr)(self); 
 
145
    (*self->muladd_func_ptr)(self);
 
146
}
 
147
 
 
148
static int
 
149
Follower_traverse(Follower *self, visitproc visit, void *arg)
 
150
{
 
151
    pyo_VISIT
 
152
    Py_VISIT(self->input);
 
153
    Py_VISIT(self->input_stream);
 
154
    Py_VISIT(self->freq);    
 
155
    Py_VISIT(self->freq_stream);    
 
156
    return 0;
 
157
}
 
158
 
 
159
static int 
 
160
Follower_clear(Follower *self)
 
161
{
 
162
    pyo_CLEAR
 
163
    Py_CLEAR(self->input);
 
164
    Py_CLEAR(self->input_stream);
 
165
    Py_CLEAR(self->freq);    
 
166
    Py_CLEAR(self->freq_stream);    
 
167
    return 0;
 
168
}
 
169
 
 
170
static void
 
171
Follower_dealloc(Follower* self)
 
172
{
 
173
    free(self->data);
 
174
    Follower_clear(self);
 
175
    self->ob_type->tp_free((PyObject*)self);
 
176
}
 
177
 
 
178
static PyObject * Follower_deleteStream(Follower *self) { DELETE_STREAM };
 
179
 
 
180
static PyObject *
 
181
Follower_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
182
{
 
183
    int i;
 
184
    Follower *self;
 
185
    self = (Follower *)type->tp_alloc(type, 0);
 
186
    
 
187
    self->freq = PyFloat_FromDouble(20);
 
188
    self->follow = 0.0;
 
189
    self->last_freq = -1.0;
 
190
    self->factor = 0.99;
 
191
        self->modebuffer[0] = 0;
 
192
        self->modebuffer[1] = 0;
 
193
        self->modebuffer[2] = 0;
 
194
    
 
195
    INIT_OBJECT_COMMON
 
196
    Stream_setFunctionPtr(self->stream, Follower_compute_next_data_frame);
 
197
    self->mode_func_ptr = Follower_setProcMode;
 
198
    return (PyObject *)self;
 
199
}
 
200
 
 
201
static int
 
202
Follower_init(Follower *self, PyObject *args, PyObject *kwds)
 
203
{
 
204
    PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
 
205
    
 
206
    static char *kwlist[] = {"input", "freq", "mul", "add", NULL};
 
207
    
 
208
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp))
 
209
        return -1; 
 
210
    
 
211
    INIT_INPUT_STREAM
 
212
    
 
213
    if (freqtmp) {
 
214
        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
 
215
    }
 
216
    
 
217
    if (multmp) {
 
218
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
219
    }
 
220
    
 
221
    if (addtmp) {
 
222
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
223
    }
 
224
    
 
225
    Py_INCREF(self->stream);
 
226
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
227
    
 
228
    (*self->mode_func_ptr)(self);
 
229
        
 
230
    Py_INCREF(self);
 
231
    return 0;
 
232
}
 
233
 
 
234
static PyObject * Follower_getServer(Follower* self) { GET_SERVER };
 
235
static PyObject * Follower_getStream(Follower* self) { GET_STREAM };
 
236
static PyObject * Follower_setMul(Follower *self, PyObject *arg) { SET_MUL };   
 
237
static PyObject * Follower_setAdd(Follower *self, PyObject *arg) { SET_ADD };   
 
238
static PyObject * Follower_setSub(Follower *self, PyObject *arg) { SET_SUB };   
 
239
static PyObject * Follower_setDiv(Follower *self, PyObject *arg) { SET_DIV };   
 
240
 
 
241
static PyObject * Follower_play(Follower *self, PyObject *args, PyObject *kwds) { PLAY };
 
242
static PyObject * Follower_stop(Follower *self) { STOP };
 
243
 
 
244
static PyObject * Follower_multiply(Follower *self, PyObject *arg) { MULTIPLY };
 
245
static PyObject * Follower_inplace_multiply(Follower *self, PyObject *arg) { INPLACE_MULTIPLY };
 
246
static PyObject * Follower_add(Follower *self, PyObject *arg) { ADD };
 
247
static PyObject * Follower_inplace_add(Follower *self, PyObject *arg) { INPLACE_ADD };
 
248
static PyObject * Follower_sub(Follower *self, PyObject *arg) { SUB };
 
249
static PyObject * Follower_inplace_sub(Follower *self, PyObject *arg) { INPLACE_SUB };
 
250
static PyObject * Follower_div(Follower *self, PyObject *arg) { DIV };
 
251
static PyObject * Follower_inplace_div(Follower *self, PyObject *arg) { INPLACE_DIV };
 
252
 
 
253
static PyObject *
 
254
Follower_setFreq(Follower *self, PyObject *arg)
 
255
{
 
256
        PyObject *tmp, *streamtmp;
 
257
        
 
258
        if (arg == NULL) {
 
259
                Py_INCREF(Py_None);
 
260
                return Py_None;
 
261
        }
 
262
    
 
263
        int isNumber = PyNumber_Check(arg);
 
264
        
 
265
        tmp = arg;
 
266
        Py_INCREF(tmp);
 
267
        Py_DECREF(self->freq);
 
268
        if (isNumber == 1) {
 
269
                self->freq = PyNumber_Float(tmp);
 
270
        self->modebuffer[2] = 0;
 
271
        }
 
272
        else {
 
273
                self->freq = tmp;
 
274
        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
 
275
        Py_INCREF(streamtmp);
 
276
        Py_XDECREF(self->freq_stream);
 
277
        self->freq_stream = (Stream *)streamtmp;
 
278
                self->modebuffer[2] = 1;
 
279
        }
 
280
    
 
281
    (*self->mode_func_ptr)(self);
 
282
    
 
283
        Py_INCREF(Py_None);
 
284
        return Py_None;
 
285
}
 
286
 
 
287
static PyMemberDef Follower_members[] = {
 
288
{"server", T_OBJECT_EX, offsetof(Follower, server), 0, "Pyo server."},
 
289
{"stream", T_OBJECT_EX, offsetof(Follower, stream), 0, "Stream object."},
 
290
{"input", T_OBJECT_EX, offsetof(Follower, input), 0, "Input sound object."},
 
291
{"freq", T_OBJECT_EX, offsetof(Follower, freq), 0, "Cutoff frequency in cycle per second."},
 
292
{"mul", T_OBJECT_EX, offsetof(Follower, mul), 0, "Mul factor."},
 
293
{"add", T_OBJECT_EX, offsetof(Follower, add), 0, "Add factor."},
 
294
{NULL}  /* Sentinel */
 
295
};
 
296
 
 
297
static PyMethodDef Follower_methods[] = {
 
298
{"getServer", (PyCFunction)Follower_getServer, METH_NOARGS, "Returns server object."},
 
299
{"_getStream", (PyCFunction)Follower_getStream, METH_NOARGS, "Returns stream object."},
 
300
{"deleteStream", (PyCFunction)Follower_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
301
{"play", (PyCFunction)Follower_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
302
{"stop", (PyCFunction)Follower_stop, METH_NOARGS, "Stops computing."},
 
303
{"setFreq", (PyCFunction)Follower_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."},
 
304
{"setMul", (PyCFunction)Follower_setMul, METH_O, "Sets oscillator mul factor."},
 
305
{"setAdd", (PyCFunction)Follower_setAdd, METH_O, "Sets oscillator add factor."},
 
306
{"setSub", (PyCFunction)Follower_setSub, METH_O, "Sets inverse add factor."},
 
307
{"setDiv", (PyCFunction)Follower_setDiv, METH_O, "Sets inverse mul factor."},
 
308
{NULL}  /* Sentinel */
 
309
};
 
310
 
 
311
static PyNumberMethods Follower_as_number = {
 
312
(binaryfunc)Follower_add,                         /*nb_add*/
 
313
(binaryfunc)Follower_sub,                         /*nb_subtract*/
 
314
(binaryfunc)Follower_multiply,                    /*nb_multiply*/
 
315
(binaryfunc)Follower_div,                                              /*nb_divide*/
 
316
0,                                              /*nb_remainder*/
 
317
0,                                              /*nb_divmod*/
 
318
0,                                              /*nb_power*/
 
319
0,                                              /*nb_neg*/
 
320
0,                                              /*nb_pos*/
 
321
0,                                              /*(unaryfunc)array_abs,*/
 
322
0,                                              /*nb_nonzero*/
 
323
0,                                              /*nb_invert*/
 
324
0,                                              /*nb_lshift*/
 
325
0,                                              /*nb_rshift*/
 
326
0,                                              /*nb_and*/
 
327
0,                                              /*nb_xor*/
 
328
0,                                              /*nb_or*/
 
329
0,                                              /*nb_coerce*/
 
330
0,                                              /*nb_int*/
 
331
0,                                              /*nb_long*/
 
332
0,                                              /*nb_float*/
 
333
0,                                              /*nb_oct*/
 
334
0,                                              /*nb_hex*/
 
335
(binaryfunc)Follower_inplace_add,                 /*inplace_add*/
 
336
(binaryfunc)Follower_inplace_sub,                 /*inplace_subtract*/
 
337
(binaryfunc)Follower_inplace_multiply,            /*inplace_multiply*/
 
338
(binaryfunc)Follower_inplace_div,                                              /*inplace_divide*/
 
339
0,                                              /*inplace_remainder*/
 
340
0,                                              /*inplace_power*/
 
341
0,                                              /*inplace_lshift*/
 
342
0,                                              /*inplace_rshift*/
 
343
0,                                              /*inplace_and*/
 
344
0,                                              /*inplace_xor*/
 
345
0,                                              /*inplace_or*/
 
346
0,                                              /*nb_floor_divide*/
 
347
0,                                              /*nb_true_divide*/
 
348
0,                                              /*nb_inplace_floor_divide*/
 
349
0,                                              /*nb_inplace_true_divide*/
 
350
0,                                              /* nb_index */
 
351
};
 
352
 
 
353
PyTypeObject FollowerType = {
 
354
PyObject_HEAD_INIT(NULL)
 
355
0,                                              /*ob_size*/
 
356
"_pyo.Follower_base",                                   /*tp_name*/
 
357
sizeof(Follower),                                 /*tp_basicsize*/
 
358
0,                                              /*tp_itemsize*/
 
359
(destructor)Follower_dealloc,                     /*tp_dealloc*/
 
360
0,                                              /*tp_print*/
 
361
0,                                              /*tp_getattr*/
 
362
0,                                              /*tp_setattr*/
 
363
0,                                              /*tp_compare*/
 
364
0,                                              /*tp_repr*/
 
365
&Follower_as_number,                              /*tp_as_number*/
 
366
0,                                              /*tp_as_sequence*/
 
367
0,                                              /*tp_as_mapping*/
 
368
0,                                              /*tp_hash */
 
369
0,                                              /*tp_call*/
 
370
0,                                              /*tp_str*/
 
371
0,                                              /*tp_getattro*/
 
372
0,                                              /*tp_setattro*/
 
373
0,                                              /*tp_as_buffer*/
 
374
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
375
"Follower objects. Envelope follower.",           /* tp_doc */
 
376
(traverseproc)Follower_traverse,                  /* tp_traverse */
 
377
(inquiry)Follower_clear,                          /* tp_clear */
 
378
0,                                              /* tp_richcompare */
 
379
0,                                              /* tp_weaklistoffset */
 
380
0,                                              /* tp_iter */
 
381
0,                                              /* tp_iternext */
 
382
Follower_methods,                                 /* tp_methods */
 
383
Follower_members,                                 /* tp_members */
 
384
0,                                              /* tp_getset */
 
385
0,                                              /* tp_base */
 
386
0,                                              /* tp_dict */
 
387
0,                                              /* tp_descr_get */
 
388
0,                                              /* tp_descr_set */
 
389
0,                                              /* tp_dictoffset */
 
390
(initproc)Follower_init,                          /* tp_init */
 
391
0,                                              /* tp_alloc */
 
392
Follower_new,                                     /* tp_new */
 
393
};
 
394
 
 
395
/************/
 
396
/* Follower2 */
 
397
/************/
 
398
typedef struct {
 
399
    pyo_audio_HEAD
 
400
    PyObject *input;
 
401
    Stream *input_stream;
 
402
    PyObject *risetime;
 
403
    Stream *risetime_stream;
 
404
    PyObject *falltime;
 
405
    Stream *falltime_stream;
 
406
    int modebuffer[4]; // need at least 2 slots for mul & add 
 
407
    MYFLT follow;
 
408
    MYFLT last_risetime;
 
409
    MYFLT last_falltime;
 
410
    MYFLT risefactor;
 
411
    MYFLT fallfactor;
 
412
} Follower2;
 
413
 
 
414
static void
 
415
Follower2_filters_ii(Follower2 *self) {
 
416
    MYFLT absin, risetime, falltime;
 
417
    int i;
 
418
    
 
419
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
420
    risetime = PyFloat_AS_DOUBLE(self->risetime);
 
421
    if (risetime <= 0.0)
 
422
        risetime = 0.001;
 
423
    falltime = PyFloat_AS_DOUBLE(self->falltime);
 
424
    if (falltime <= 0.0)
 
425
        falltime = 0.001;
 
426
    
 
427
    if (risetime != self->last_risetime) {
 
428
        self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
 
429
        self->last_risetime = risetime;
 
430
    }
 
431
 
 
432
    if (falltime != self->last_falltime) {
 
433
        self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
 
434
        self->last_falltime = falltime;
 
435
    }
 
436
    
 
437
    for (i=0; i<self->bufsize; i++) {
 
438
        absin = in[i];
 
439
        if (absin < 0.0)
 
440
            absin = -absin;
 
441
        if (self->follow < absin)
 
442
            self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin);
 
443
        else
 
444
            self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin);
 
445
    }
 
446
}
 
447
 
 
448
static void
 
449
Follower2_filters_ai(Follower2 *self) {
 
450
    MYFLT absin, risetime, falltime;
 
451
    int i;
 
452
    
 
453
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
454
    MYFLT *rise = Stream_getData((Stream *)self->risetime_stream);
 
455
    falltime = PyFloat_AS_DOUBLE(self->falltime);
 
456
    if (falltime <= 0.0)
 
457
        falltime = 0.001;
 
458
 
 
459
    if (falltime != self->last_falltime) {
 
460
        self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
 
461
        self->last_falltime = falltime;
 
462
    }
 
463
    
 
464
    for (i=0; i<self->bufsize; i++) {
 
465
        risetime = rise[i];
 
466
        if (risetime <= 0.0)
 
467
            risetime = 0.001;
 
468
        if (risetime != self->last_risetime) {
 
469
            self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
 
470
            self->last_risetime = risetime;
 
471
        }
 
472
        absin = in[i];
 
473
        if (absin < 0.0)
 
474
            absin = -absin;
 
475
        if (self->follow < absin)
 
476
            self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin);
 
477
        else
 
478
            self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin);
 
479
    }
 
480
}
 
481
 
 
482
static void
 
483
Follower2_filters_ia(Follower2 *self) {
 
484
    MYFLT absin, risetime, falltime;
 
485
    int i;
 
486
    
 
487
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
488
    risetime = PyFloat_AS_DOUBLE(self->risetime);
 
489
    if (risetime <= 0.0)
 
490
        risetime = 0.001;
 
491
    MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
 
492
    
 
493
    if (risetime != self->last_risetime) {
 
494
        self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
 
495
        self->last_risetime = risetime;
 
496
    }
 
497
 
 
498
    for (i=0; i<self->bufsize; i++) {
 
499
        falltime = fall[i];
 
500
        if (falltime <= 0.0)
 
501
            falltime = 0.001;
 
502
        if (falltime != self->last_falltime) {
 
503
            self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
 
504
            self->last_falltime = falltime;
 
505
        }        
 
506
        absin = in[i];
 
507
        if (absin < 0.0)
 
508
            absin = -absin;
 
509
        if (self->follow < absin)
 
510
            self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin);
 
511
        else
 
512
            self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin);
 
513
    }
 
514
}
 
515
 
 
516
static void
 
517
Follower2_filters_aa(Follower2 *self) {
 
518
    MYFLT absin, risetime, falltime;
 
519
    int i;
 
520
    
 
521
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
522
    MYFLT *rise = Stream_getData((Stream *)self->risetime_stream);
 
523
    MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
 
524
 
 
525
    for (i=0; i<self->bufsize; i++) {
 
526
        risetime = rise[i];
 
527
        if (risetime <= 0.0)
 
528
            risetime = 0.001;
 
529
        if (risetime != self->last_risetime) {
 
530
            self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
 
531
            self->last_risetime = risetime;
 
532
        }
 
533
        falltime = fall[i];
 
534
        if (falltime <= 0.0)
 
535
            falltime = 0.001;
 
536
        if (falltime != self->last_falltime) {
 
537
            self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
 
538
            self->last_falltime = falltime;
 
539
        }        
 
540
        absin = in[i];
 
541
        if (absin < 0.0)
 
542
            absin = -absin;
 
543
        if (self->follow < absin)
 
544
            self->follow = self->data[i] = absin + self->risefactor * (self->follow - absin);
 
545
        else
 
546
            self->follow = self->data[i] = absin + self->fallfactor * (self->follow - absin);
 
547
    }
 
548
}
 
549
 
 
550
static void Follower2_postprocessing_ii(Follower2 *self) { POST_PROCESSING_II };
 
551
static void Follower2_postprocessing_ai(Follower2 *self) { POST_PROCESSING_AI };
 
552
static void Follower2_postprocessing_ia(Follower2 *self) { POST_PROCESSING_IA };
 
553
static void Follower2_postprocessing_aa(Follower2 *self) { POST_PROCESSING_AA };
 
554
static void Follower2_postprocessing_ireva(Follower2 *self) { POST_PROCESSING_IREVA };
 
555
static void Follower2_postprocessing_areva(Follower2 *self) { POST_PROCESSING_AREVA };
 
556
static void Follower2_postprocessing_revai(Follower2 *self) { POST_PROCESSING_REVAI };
 
557
static void Follower2_postprocessing_revaa(Follower2 *self) { POST_PROCESSING_REVAA };
 
558
static void Follower2_postprocessing_revareva(Follower2 *self) { POST_PROCESSING_REVAREVA };
 
559
 
 
560
static void
 
561
Follower2_setProcMode(Follower2 *self)
 
562
{
 
563
    int procmode, muladdmode;
 
564
    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
 
565
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
566
    
 
567
        switch (procmode) {
 
568
        case 0:    
 
569
            self->proc_func_ptr = Follower2_filters_ii;
 
570
            break;
 
571
        case 1:    
 
572
            self->proc_func_ptr = Follower2_filters_ai;
 
573
            break;
 
574
        case 10:    
 
575
            self->proc_func_ptr = Follower2_filters_ia;
 
576
            break;
 
577
        case 11:    
 
578
            self->proc_func_ptr = Follower2_filters_aa;
 
579
            break;
 
580
    } 
 
581
        switch (muladdmode) {
 
582
        case 0:        
 
583
            self->muladd_func_ptr = Follower2_postprocessing_ii;
 
584
            break;
 
585
        case 1:    
 
586
            self->muladd_func_ptr = Follower2_postprocessing_ai;
 
587
            break;
 
588
        case 2:    
 
589
            self->muladd_func_ptr = Follower2_postprocessing_revai;
 
590
            break;
 
591
        case 10:        
 
592
            self->muladd_func_ptr = Follower2_postprocessing_ia;
 
593
            break;
 
594
        case 11:    
 
595
            self->muladd_func_ptr = Follower2_postprocessing_aa;
 
596
            break;
 
597
        case 12:    
 
598
            self->muladd_func_ptr = Follower2_postprocessing_revaa;
 
599
            break;
 
600
        case 20:        
 
601
            self->muladd_func_ptr = Follower2_postprocessing_ireva;
 
602
            break;
 
603
        case 21:    
 
604
            self->muladd_func_ptr = Follower2_postprocessing_areva;
 
605
            break;
 
606
        case 22:    
 
607
            self->muladd_func_ptr = Follower2_postprocessing_revareva;
 
608
            break;
 
609
    }   
 
610
}
 
611
 
 
612
static void
 
613
Follower2_compute_next_data_frame(Follower2 *self)
 
614
{
 
615
    (*self->proc_func_ptr)(self); 
 
616
    (*self->muladd_func_ptr)(self);
 
617
}
 
618
 
 
619
static int
 
620
Follower2_traverse(Follower2 *self, visitproc visit, void *arg)
 
621
{
 
622
    pyo_VISIT
 
623
    Py_VISIT(self->input);
 
624
    Py_VISIT(self->input_stream);
 
625
    Py_VISIT(self->risetime);    
 
626
    Py_VISIT(self->risetime_stream);    
 
627
    Py_VISIT(self->falltime);    
 
628
    Py_VISIT(self->falltime_stream);    
 
629
    return 0;
 
630
}
 
631
 
 
632
static int 
 
633
Follower2_clear(Follower2 *self)
 
634
{
 
635
    pyo_CLEAR
 
636
    Py_CLEAR(self->input);
 
637
    Py_CLEAR(self->input_stream);
 
638
    Py_CLEAR(self->risetime);    
 
639
    Py_CLEAR(self->risetime_stream);    
 
640
    Py_CLEAR(self->falltime);    
 
641
    Py_CLEAR(self->falltime_stream);    
 
642
    return 0;
 
643
}
 
644
 
 
645
static void
 
646
Follower2_dealloc(Follower2* self)
 
647
{
 
648
    free(self->data);
 
649
    Follower2_clear(self);
 
650
    self->ob_type->tp_free((PyObject*)self);
 
651
}
 
652
 
 
653
static PyObject * Follower2_deleteStream(Follower2 *self) { DELETE_STREAM };
 
654
 
 
655
static PyObject *
 
656
Follower2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
657
{
 
658
    int i;
 
659
    Follower2 *self;
 
660
    self = (Follower2 *)type->tp_alloc(type, 0);
 
661
    
 
662
    self->risetime = PyFloat_FromDouble(0.01);
 
663
    self->falltime = PyFloat_FromDouble(0.1);
 
664
    self->follow = 0.0;
 
665
    self->last_risetime = -1.0;
 
666
    self->last_falltime = -1.0;
 
667
    self->risefactor = self->fallfactor = 0.99;
 
668
        self->modebuffer[0] = 0;
 
669
        self->modebuffer[1] = 0;
 
670
        self->modebuffer[2] = 0;
 
671
        self->modebuffer[3] = 0;
 
672
    
 
673
    INIT_OBJECT_COMMON
 
674
    Stream_setFunctionPtr(self->stream, Follower2_compute_next_data_frame);
 
675
    self->mode_func_ptr = Follower2_setProcMode;
 
676
    return (PyObject *)self;
 
677
}
 
678
 
 
679
static int
 
680
Follower2_init(Follower2 *self, PyObject *args, PyObject *kwds)
 
681
{
 
682
    PyObject *inputtmp, *input_streamtmp, *risetimetmp=NULL, *falltimetmp=NULL, *multmp=NULL, *addtmp=NULL;
 
683
    
 
684
    static char *kwlist[] = {"input", "risetime", "falltime", "mul", "add", NULL};
 
685
    
 
686
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &risetimetmp, &falltimetmp, &multmp, &addtmp))
 
687
        return -1; 
 
688
    
 
689
    INIT_INPUT_STREAM
 
690
    
 
691
    if (risetimetmp) {
 
692
        PyObject_CallMethod((PyObject *)self, "setRisetime", "O", risetimetmp);
 
693
    }
 
694
    
 
695
    if (falltimetmp) {
 
696
        PyObject_CallMethod((PyObject *)self, "setFalltime", "O", falltimetmp);
 
697
    }
 
698
    
 
699
    if (multmp) {
 
700
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
701
    }
 
702
    
 
703
    if (addtmp) {
 
704
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
705
    }
 
706
    
 
707
    Py_INCREF(self->stream);
 
708
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
709
    
 
710
    (*self->mode_func_ptr)(self);
 
711
    
 
712
    Py_INCREF(self);
 
713
    return 0;
 
714
}
 
715
 
 
716
static PyObject * Follower2_getServer(Follower2* self) { GET_SERVER };
 
717
static PyObject * Follower2_getStream(Follower2* self) { GET_STREAM };
 
718
static PyObject * Follower2_setMul(Follower2 *self, PyObject *arg) { SET_MUL }; 
 
719
static PyObject * Follower2_setAdd(Follower2 *self, PyObject *arg) { SET_ADD }; 
 
720
static PyObject * Follower2_setSub(Follower2 *self, PyObject *arg) { SET_SUB }; 
 
721
static PyObject * Follower2_setDiv(Follower2 *self, PyObject *arg) { SET_DIV }; 
 
722
 
 
723
static PyObject * Follower2_play(Follower2 *self, PyObject *args, PyObject *kwds) { PLAY };
 
724
static PyObject * Follower2_stop(Follower2 *self) { STOP };
 
725
 
 
726
static PyObject * Follower2_multiply(Follower2 *self, PyObject *arg) { MULTIPLY };
 
727
static PyObject * Follower2_inplace_multiply(Follower2 *self, PyObject *arg) { INPLACE_MULTIPLY };
 
728
static PyObject * Follower2_add(Follower2 *self, PyObject *arg) { ADD };
 
729
static PyObject * Follower2_inplace_add(Follower2 *self, PyObject *arg) { INPLACE_ADD };
 
730
static PyObject * Follower2_sub(Follower2 *self, PyObject *arg) { SUB };
 
731
static PyObject * Follower2_inplace_sub(Follower2 *self, PyObject *arg) { INPLACE_SUB };
 
732
static PyObject * Follower2_div(Follower2 *self, PyObject *arg) { DIV };
 
733
static PyObject * Follower2_inplace_div(Follower2 *self, PyObject *arg) { INPLACE_DIV };
 
734
 
 
735
static PyObject *
 
736
Follower2_setRisetime(Follower2 *self, PyObject *arg)
 
737
{
 
738
        PyObject *tmp, *streamtmp;
 
739
        
 
740
        if (arg == NULL) {
 
741
                Py_INCREF(Py_None);
 
742
                return Py_None;
 
743
        }
 
744
    
 
745
        int isNumber = PyNumber_Check(arg);
 
746
        
 
747
        tmp = arg;
 
748
        Py_INCREF(tmp);
 
749
        Py_DECREF(self->risetime);
 
750
        if (isNumber == 1) {
 
751
                self->risetime = PyNumber_Float(tmp);
 
752
        self->modebuffer[2] = 0;
 
753
        }
 
754
        else {
 
755
                self->risetime = tmp;
 
756
        streamtmp = PyObject_CallMethod((PyObject *)self->risetime, "_getStream", NULL);
 
757
        Py_INCREF(streamtmp);
 
758
        Py_XDECREF(self->risetime_stream);
 
759
        self->risetime_stream = (Stream *)streamtmp;
 
760
                self->modebuffer[2] = 1;
 
761
        }
 
762
    
 
763
    (*self->mode_func_ptr)(self);
 
764
    
 
765
        Py_INCREF(Py_None);
 
766
        return Py_None;
 
767
}
 
768
 
 
769
static PyObject *
 
770
Follower2_setFalltime(Follower2 *self, PyObject *arg)
 
771
{
 
772
        PyObject *tmp, *streamtmp;
 
773
        
 
774
        if (arg == NULL) {
 
775
                Py_INCREF(Py_None);
 
776
                return Py_None;
 
777
        }
 
778
    
 
779
        int isNumber = PyNumber_Check(arg);
 
780
        
 
781
        tmp = arg;
 
782
        Py_INCREF(tmp);
 
783
        Py_DECREF(self->falltime);
 
784
        if (isNumber == 1) {
 
785
                self->falltime = PyNumber_Float(tmp);
 
786
        self->modebuffer[3] = 0;
 
787
        }
 
788
        else {
 
789
                self->falltime = tmp;
 
790
        streamtmp = PyObject_CallMethod((PyObject *)self->falltime, "_getStream", NULL);
 
791
        Py_INCREF(streamtmp);
 
792
        Py_XDECREF(self->falltime_stream);
 
793
        self->falltime_stream = (Stream *)streamtmp;
 
794
                self->modebuffer[3] = 1;
 
795
        }
 
796
    
 
797
    (*self->mode_func_ptr)(self);
 
798
    
 
799
        Py_INCREF(Py_None);
 
800
        return Py_None;
 
801
}
 
802
 
 
803
static PyMemberDef Follower2_members[] = {
 
804
    {"server", T_OBJECT_EX, offsetof(Follower2, server), 0, "Pyo server."},
 
805
    {"stream", T_OBJECT_EX, offsetof(Follower2, stream), 0, "Stream object."},
 
806
    {"input", T_OBJECT_EX, offsetof(Follower2, input), 0, "Input sound object."},
 
807
    {"risetime", T_OBJECT_EX, offsetof(Follower2, risetime), 0, "Risetime in second."},
 
808
    {"falltime", T_OBJECT_EX, offsetof(Follower2, falltime), 0, "Falltime in second."},
 
809
    {"mul", T_OBJECT_EX, offsetof(Follower2, mul), 0, "Mul factor."},
 
810
    {"add", T_OBJECT_EX, offsetof(Follower2, add), 0, "Add factor."},
 
811
    {NULL}  /* Sentinel */
 
812
};
 
813
 
 
814
static PyMethodDef Follower2_methods[] = {
 
815
    {"getServer", (PyCFunction)Follower2_getServer, METH_NOARGS, "Returns server object."},
 
816
    {"_getStream", (PyCFunction)Follower2_getStream, METH_NOARGS, "Returns stream object."},
 
817
    {"deleteStream", (PyCFunction)Follower2_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
818
    {"play", (PyCFunction)Follower2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
819
    {"stop", (PyCFunction)Follower2_stop, METH_NOARGS, "Stops computing."},
 
820
    {"setRisetime", (PyCFunction)Follower2_setRisetime, METH_O, "Sets filter risetime in second."},
 
821
    {"setFalltime", (PyCFunction)Follower2_setFalltime, METH_O, "Sets filter falltime in second."},
 
822
    {"setMul", (PyCFunction)Follower2_setMul, METH_O, "Sets oscillator mul factor."},
 
823
    {"setAdd", (PyCFunction)Follower2_setAdd, METH_O, "Sets oscillator add factor."},
 
824
    {"setSub", (PyCFunction)Follower2_setSub, METH_O, "Sets inverse add factor."},
 
825
    {"setDiv", (PyCFunction)Follower2_setDiv, METH_O, "Sets inverse mul factor."},
 
826
    {NULL}  /* Sentinel */
 
827
};
 
828
 
 
829
static PyNumberMethods Follower2_as_number = {
 
830
    (binaryfunc)Follower2_add,                         /*nb_add*/
 
831
    (binaryfunc)Follower2_sub,                         /*nb_subtract*/
 
832
    (binaryfunc)Follower2_multiply,                    /*nb_multiply*/
 
833
    (binaryfunc)Follower2_div,                                              /*nb_divide*/
 
834
    0,                                              /*nb_remainder*/
 
835
    0,                                              /*nb_divmod*/
 
836
    0,                                              /*nb_power*/
 
837
    0,                                              /*nb_neg*/
 
838
    0,                                              /*nb_pos*/
 
839
    0,                                              /*(unaryfunc)array_abs,*/
 
840
    0,                                              /*nb_nonzero*/
 
841
    0,                                              /*nb_invert*/
 
842
    0,                                              /*nb_lshift*/
 
843
    0,                                              /*nb_rshift*/
 
844
    0,                                              /*nb_and*/
 
845
    0,                                              /*nb_xor*/
 
846
    0,                                              /*nb_or*/
 
847
    0,                                              /*nb_coerce*/
 
848
    0,                                              /*nb_int*/
 
849
    0,                                              /*nb_long*/
 
850
    0,                                              /*nb_float*/
 
851
    0,                                              /*nb_oct*/
 
852
    0,                                              /*nb_hex*/
 
853
    (binaryfunc)Follower2_inplace_add,                 /*inplace_add*/
 
854
    (binaryfunc)Follower2_inplace_sub,                 /*inplace_subtract*/
 
855
    (binaryfunc)Follower2_inplace_multiply,            /*inplace_multiply*/
 
856
    (binaryfunc)Follower2_inplace_div,                                              /*inplace_divide*/
 
857
    0,                                              /*inplace_remainder*/
 
858
    0,                                              /*inplace_power*/
 
859
    0,                                              /*inplace_lshift*/
 
860
    0,                                              /*inplace_rshift*/
 
861
    0,                                              /*inplace_and*/
 
862
    0,                                              /*inplace_xor*/
 
863
    0,                                              /*inplace_or*/
 
864
    0,                                              /*nb_floor_divide*/
 
865
    0,                                              /*nb_true_divide*/
 
866
    0,                                              /*nb_inplace_floor_divide*/
 
867
    0,                                              /*nb_inplace_true_divide*/
 
868
    0,                                              /* nb_index */
 
869
};
 
870
 
 
871
PyTypeObject Follower2Type = {
 
872
    PyObject_HEAD_INIT(NULL)
 
873
    0,                                              /*ob_size*/
 
874
    "_pyo.Follower2_base",                                   /*tp_name*/
 
875
    sizeof(Follower2),                                 /*tp_basicsize*/
 
876
    0,                                              /*tp_itemsize*/
 
877
    (destructor)Follower2_dealloc,                     /*tp_dealloc*/
 
878
    0,                                              /*tp_print*/
 
879
    0,                                              /*tp_getattr*/
 
880
    0,                                              /*tp_setattr*/
 
881
    0,                                              /*tp_compare*/
 
882
    0,                                              /*tp_repr*/
 
883
    &Follower2_as_number,                              /*tp_as_number*/
 
884
    0,                                              /*tp_as_sequence*/
 
885
    0,                                              /*tp_as_mapping*/
 
886
    0,                                              /*tp_hash */
 
887
    0,                                              /*tp_call*/
 
888
    0,                                              /*tp_str*/
 
889
    0,                                              /*tp_getattro*/
 
890
    0,                                              /*tp_setattro*/
 
891
    0,                                              /*tp_as_buffer*/
 
892
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
893
    "Follower2 objects. Envelope follower.",           /* tp_doc */
 
894
    (traverseproc)Follower2_traverse,                  /* tp_traverse */
 
895
    (inquiry)Follower2_clear,                          /* tp_clear */
 
896
    0,                                              /* tp_richcompare */
 
897
    0,                                              /* tp_weaklistoffset */
 
898
    0,                                              /* tp_iter */
 
899
    0,                                              /* tp_iternext */
 
900
    Follower2_methods,                                 /* tp_methods */
 
901
    Follower2_members,                                 /* tp_members */
 
902
    0,                                              /* tp_getset */
 
903
    0,                                              /* tp_base */
 
904
    0,                                              /* tp_dict */
 
905
    0,                                              /* tp_descr_get */
 
906
    0,                                              /* tp_descr_set */
 
907
    0,                                              /* tp_dictoffset */
 
908
    (initproc)Follower2_init,                          /* tp_init */
 
909
    0,                                              /* tp_alloc */
 
910
    Follower2_new,                                     /* tp_new */
 
911
};
 
912
 
 
913
/************/
 
914
/* ZCross */
 
915
/************/
 
916
typedef struct {
 
917
    pyo_audio_HEAD
 
918
    PyObject *input;
 
919
    Stream *input_stream;
 
920
    MYFLT thresh;
 
921
    MYFLT lastValue;
 
922
    MYFLT lastSample;
 
923
    int modebuffer[2]; // need at least 2 slots for mul & add
 
924
} ZCross;
 
925
 
 
926
static void
 
927
ZCross_process(ZCross *self) {
 
928
    int i;
 
929
    int count = 0;
 
930
    MYFLT inval;
 
931
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
932
    
 
933
    for (i=0; i<self->bufsize; i++) {
 
934
        self->data[i] = self->lastValue;
 
935
        inval = in[i];
 
936
        if (self->lastSample >= 0.0) {
 
937
            if (inval < 0.0 && (self->lastSample-inval) > self->thresh)
 
938
                count++;
 
939
        }
 
940
        else {
 
941
            if (inval >= 0.0 && (inval-self->lastSample) > self->thresh)
 
942
                count++;
 
943
        }
 
944
        self->lastSample = inval;
 
945
    }
 
946
    self->lastValue = (MYFLT)count / self->bufsize;
 
947
}
 
948
 
 
949
static void ZCross_postprocessing_ii(ZCross *self) { POST_PROCESSING_II };
 
950
static void ZCross_postprocessing_ai(ZCross *self) { POST_PROCESSING_AI };
 
951
static void ZCross_postprocessing_ia(ZCross *self) { POST_PROCESSING_IA };
 
952
static void ZCross_postprocessing_aa(ZCross *self) { POST_PROCESSING_AA };
 
953
static void ZCross_postprocessing_ireva(ZCross *self) { POST_PROCESSING_IREVA };
 
954
static void ZCross_postprocessing_areva(ZCross *self) { POST_PROCESSING_AREVA };
 
955
static void ZCross_postprocessing_revai(ZCross *self) { POST_PROCESSING_REVAI };
 
956
static void ZCross_postprocessing_revaa(ZCross *self) { POST_PROCESSING_REVAA };
 
957
static void ZCross_postprocessing_revareva(ZCross *self) { POST_PROCESSING_REVAREVA };
 
958
 
 
959
static void
 
960
ZCross_setProcMode(ZCross *self)
 
961
{
 
962
    int muladdmode;
 
963
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
964
    
 
965
    self->proc_func_ptr = ZCross_process;
 
966
 
 
967
        switch (muladdmode) {
 
968
        case 0:        
 
969
            self->muladd_func_ptr = ZCross_postprocessing_ii;
 
970
            break;
 
971
        case 1:    
 
972
            self->muladd_func_ptr = ZCross_postprocessing_ai;
 
973
            break;
 
974
        case 2:    
 
975
            self->muladd_func_ptr = ZCross_postprocessing_revai;
 
976
            break;
 
977
        case 10:        
 
978
            self->muladd_func_ptr = ZCross_postprocessing_ia;
 
979
            break;
 
980
        case 11:    
 
981
            self->muladd_func_ptr = ZCross_postprocessing_aa;
 
982
            break;
 
983
        case 12:    
 
984
            self->muladd_func_ptr = ZCross_postprocessing_revaa;
 
985
            break;
 
986
        case 20:        
 
987
            self->muladd_func_ptr = ZCross_postprocessing_ireva;
 
988
            break;
 
989
        case 21:    
 
990
            self->muladd_func_ptr = ZCross_postprocessing_areva;
 
991
            break;
 
992
        case 22:    
 
993
            self->muladd_func_ptr = ZCross_postprocessing_revareva;
 
994
            break;
 
995
    }   
 
996
}
 
997
 
 
998
static void
 
999
ZCross_compute_next_data_frame(ZCross *self)
 
1000
{
 
1001
    (*self->proc_func_ptr)(self); 
 
1002
    (*self->muladd_func_ptr)(self);
 
1003
}
 
1004
 
 
1005
static int
 
1006
ZCross_traverse(ZCross *self, visitproc visit, void *arg)
 
1007
{
 
1008
    pyo_VISIT
 
1009
    Py_VISIT(self->input);
 
1010
    Py_VISIT(self->input_stream);
 
1011
    return 0;
 
1012
}
 
1013
 
 
1014
static int 
 
1015
ZCross_clear(ZCross *self)
 
1016
{
 
1017
    pyo_CLEAR
 
1018
    Py_CLEAR(self->input);
 
1019
    Py_CLEAR(self->input_stream);
 
1020
    return 0;
 
1021
}
 
1022
 
 
1023
static void
 
1024
ZCross_dealloc(ZCross* self)
 
1025
{
 
1026
    free(self->data);
 
1027
    ZCross_clear(self);
 
1028
    self->ob_type->tp_free((PyObject*)self);
 
1029
}
 
1030
 
 
1031
static PyObject * ZCross_deleteStream(ZCross *self) { DELETE_STREAM };
 
1032
 
 
1033
static PyObject *
 
1034
ZCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
1035
{
 
1036
    int i;
 
1037
    ZCross *self;
 
1038
    self = (ZCross *)type->tp_alloc(type, 0);
 
1039
    
 
1040
    self->thresh = 0.0;
 
1041
    self->lastValue = self->lastSample = 0.0;
 
1042
        self->modebuffer[0] = 0;
 
1043
        self->modebuffer[1] = 0;
 
1044
    
 
1045
    INIT_OBJECT_COMMON
 
1046
    Stream_setFunctionPtr(self->stream, ZCross_compute_next_data_frame);
 
1047
    self->mode_func_ptr = ZCross_setProcMode;
 
1048
    return (PyObject *)self;
 
1049
}
 
1050
 
 
1051
static int
 
1052
ZCross_init(ZCross *self, PyObject *args, PyObject *kwds)
 
1053
{
 
1054
    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
 
1055
    
 
1056
    static char *kwlist[] = {"input", "thresh", "mul", "add", NULL};
 
1057
    
 
1058
    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FOO, kwlist, &inputtmp, &self->thresh, &multmp, &addtmp))
 
1059
        return -1; 
 
1060
 
 
1061
    INIT_INPUT_STREAM
 
1062
    
 
1063
    if (multmp) {
 
1064
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
1065
    }
 
1066
    
 
1067
    if (addtmp) {
 
1068
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
1069
    }
 
1070
    
 
1071
    Py_INCREF(self->stream);
 
1072
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
1073
    
 
1074
    (*self->mode_func_ptr)(self);
 
1075
        
 
1076
    Py_INCREF(self);
 
1077
    return 0;
 
1078
}
 
1079
 
 
1080
static PyObject * ZCross_getServer(ZCross* self) { GET_SERVER };
 
1081
static PyObject * ZCross_getStream(ZCross* self) { GET_STREAM };
 
1082
static PyObject * ZCross_setMul(ZCross *self, PyObject *arg) { SET_MUL };       
 
1083
static PyObject * ZCross_setAdd(ZCross *self, PyObject *arg) { SET_ADD };       
 
1084
static PyObject * ZCross_setSub(ZCross *self, PyObject *arg) { SET_SUB };       
 
1085
static PyObject * ZCross_setDiv(ZCross *self, PyObject *arg) { SET_DIV };       
 
1086
 
 
1087
static PyObject * ZCross_play(ZCross *self, PyObject *args, PyObject *kwds) { PLAY };
 
1088
static PyObject * ZCross_stop(ZCross *self) { STOP };
 
1089
 
 
1090
static PyObject * ZCross_multiply(ZCross *self, PyObject *arg) { MULTIPLY };
 
1091
static PyObject * ZCross_inplace_multiply(ZCross *self, PyObject *arg) { INPLACE_MULTIPLY };
 
1092
static PyObject * ZCross_add(ZCross *self, PyObject *arg) { ADD };
 
1093
static PyObject * ZCross_inplace_add(ZCross *self, PyObject *arg) { INPLACE_ADD };
 
1094
static PyObject * ZCross_sub(ZCross *self, PyObject *arg) { SUB };
 
1095
static PyObject * ZCross_inplace_sub(ZCross *self, PyObject *arg) { INPLACE_SUB };
 
1096
static PyObject * ZCross_div(ZCross *self, PyObject *arg) { DIV };
 
1097
static PyObject * ZCross_inplace_div(ZCross *self, PyObject *arg) { INPLACE_DIV };
 
1098
 
 
1099
static PyObject *
 
1100
ZCross_setThresh(ZCross *self, PyObject *arg)
 
1101
{
 
1102
        if (arg == NULL) {
 
1103
                Py_INCREF(Py_None);
 
1104
                return Py_None;
 
1105
        }
 
1106
    
 
1107
        int isNumber = PyNumber_Check(arg);
 
1108
        
 
1109
        if (isNumber == 1) {
 
1110
                self->thresh = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
 
1111
        }
 
1112
  
 
1113
        Py_INCREF(Py_None);
 
1114
        return Py_None;
 
1115
}
 
1116
 
 
1117
static PyMemberDef ZCross_members[] = {
 
1118
{"server", T_OBJECT_EX, offsetof(ZCross, server), 0, "Pyo server."},
 
1119
{"stream", T_OBJECT_EX, offsetof(ZCross, stream), 0, "Stream object."},
 
1120
{"input", T_OBJECT_EX, offsetof(ZCross, input), 0, "Input sound object."},
 
1121
{"mul", T_OBJECT_EX, offsetof(ZCross, mul), 0, "Mul factor."},
 
1122
{"add", T_OBJECT_EX, offsetof(ZCross, add), 0, "Add factor."},
 
1123
{NULL}  /* Sentinel */
 
1124
};
 
1125
 
 
1126
static PyMethodDef ZCross_methods[] = {
 
1127
{"getServer", (PyCFunction)ZCross_getServer, METH_NOARGS, "Returns server object."},
 
1128
{"_getStream", (PyCFunction)ZCross_getStream, METH_NOARGS, "Returns stream object."},
 
1129
{"deleteStream", (PyCFunction)ZCross_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
1130
{"play", (PyCFunction)ZCross_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
1131
{"stop", (PyCFunction)ZCross_stop, METH_NOARGS, "Stops computing."},
 
1132
{"setThresh", (PyCFunction)ZCross_setThresh, METH_O, "Sets the threshold factor."},
 
1133
{"setMul", (PyCFunction)ZCross_setMul, METH_O, "Sets oscillator mul factor."},
 
1134
{"setAdd", (PyCFunction)ZCross_setAdd, METH_O, "Sets oscillator add factor."},
 
1135
{"setSub", (PyCFunction)ZCross_setSub, METH_O, "Sets inverse add factor."},
 
1136
{"setDiv", (PyCFunction)ZCross_setDiv, METH_O, "Sets inverse mul factor."},
 
1137
{NULL}  /* Sentinel */
 
1138
};
 
1139
 
 
1140
static PyNumberMethods ZCross_as_number = {
 
1141
(binaryfunc)ZCross_add,                         /*nb_add*/
 
1142
(binaryfunc)ZCross_sub,                         /*nb_subtract*/
 
1143
(binaryfunc)ZCross_multiply,                    /*nb_multiply*/
 
1144
(binaryfunc)ZCross_div,                                              /*nb_divide*/
 
1145
0,                                              /*nb_remainder*/
 
1146
0,                                              /*nb_divmod*/
 
1147
0,                                              /*nb_power*/
 
1148
0,                                              /*nb_neg*/
 
1149
0,                                              /*nb_pos*/
 
1150
0,                                              /*(unaryfunc)array_abs,*/
 
1151
0,                                              /*nb_nonzero*/
 
1152
0,                                              /*nb_invert*/
 
1153
0,                                              /*nb_lshift*/
 
1154
0,                                              /*nb_rshift*/
 
1155
0,                                              /*nb_and*/
 
1156
0,                                              /*nb_xor*/
 
1157
0,                                              /*nb_or*/
 
1158
0,                                              /*nb_coerce*/
 
1159
0,                                              /*nb_int*/
 
1160
0,                                              /*nb_long*/
 
1161
0,                                              /*nb_float*/
 
1162
0,                                              /*nb_oct*/
 
1163
0,                                              /*nb_hex*/
 
1164
(binaryfunc)ZCross_inplace_add,                 /*inplace_add*/
 
1165
(binaryfunc)ZCross_inplace_sub,                 /*inplace_subtract*/
 
1166
(binaryfunc)ZCross_inplace_multiply,            /*inplace_multiply*/
 
1167
(binaryfunc)ZCross_inplace_div,                                              /*inplace_divide*/
 
1168
0,                                              /*inplace_remainder*/
 
1169
0,                                              /*inplace_power*/
 
1170
0,                                              /*inplace_lshift*/
 
1171
0,                                              /*inplace_rshift*/
 
1172
0,                                              /*inplace_and*/
 
1173
0,                                              /*inplace_xor*/
 
1174
0,                                              /*inplace_or*/
 
1175
0,                                              /*nb_floor_divide*/
 
1176
0,                                              /*nb_true_divide*/
 
1177
0,                                              /*nb_inplace_floor_divide*/
 
1178
0,                                              /*nb_inplace_true_divide*/
 
1179
0,                                              /* nb_index */
 
1180
};
 
1181
 
 
1182
PyTypeObject ZCrossType = {
 
1183
PyObject_HEAD_INIT(NULL)
 
1184
0,                                              /*ob_size*/
 
1185
"_pyo.ZCross_base",                                   /*tp_name*/
 
1186
sizeof(ZCross),                                 /*tp_basicsize*/
 
1187
0,                                              /*tp_itemsize*/
 
1188
(destructor)ZCross_dealloc,                     /*tp_dealloc*/
 
1189
0,                                              /*tp_print*/
 
1190
0,                                              /*tp_getattr*/
 
1191
0,                                              /*tp_setattr*/
 
1192
0,                                              /*tp_compare*/
 
1193
0,                                              /*tp_repr*/
 
1194
&ZCross_as_number,                              /*tp_as_number*/
 
1195
0,                                              /*tp_as_sequence*/
 
1196
0,                                              /*tp_as_mapping*/
 
1197
0,                                              /*tp_hash */
 
1198
0,                                              /*tp_call*/
 
1199
0,                                              /*tp_str*/
 
1200
0,                                              /*tp_getattro*/
 
1201
0,                                              /*tp_setattro*/
 
1202
0,                                              /*tp_as_buffer*/
 
1203
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
1204
"ZCross objects. Returns number of zero crossing.",           /* tp_doc */
 
1205
(traverseproc)ZCross_traverse,                  /* tp_traverse */
 
1206
(inquiry)ZCross_clear,                          /* tp_clear */
 
1207
0,                                              /* tp_richcompare */
 
1208
0,                                              /* tp_weaklistoffset */
 
1209
0,                                              /* tp_iter */
 
1210
0,                                              /* tp_iternext */
 
1211
ZCross_methods,                                 /* tp_methods */
 
1212
ZCross_members,                                 /* tp_members */
 
1213
0,                                              /* tp_getset */
 
1214
0,                                              /* tp_base */
 
1215
0,                                              /* tp_dict */
 
1216
0,                                              /* tp_descr_get */
 
1217
0,                                              /* tp_descr_set */
 
1218
0,                                              /* tp_dictoffset */
 
1219
(initproc)ZCross_init,                          /* tp_init */
 
1220
0,                                              /* tp_alloc */
 
1221
ZCross_new,                                     /* tp_new */
 
1222
};