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

« back to all changes in this revision

Viewing changes to src/objects/distomodule.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
 
 
21
#include <Python.h>
 
22
#include "structmember.h"
 
23
#include <math.h>
 
24
#include "pyomodule.h"
 
25
#include "streammodule.h"
 
26
#include "servermodule.h"
 
27
#include "dummymodule.h"
 
28
 
 
29
typedef struct {
 
30
    pyo_audio_HEAD
 
31
    PyObject *input;
 
32
    Stream *input_stream;
 
33
    PyObject *drive;
 
34
    Stream *drive_stream;
 
35
    PyObject *slope;
 
36
    Stream *slope_stream;
 
37
    int init;
 
38
    int modebuffer[4];
 
39
    MYFLT y1; // sample memory
 
40
} Disto;
 
41
 
 
42
static MYFLT
 
43
_clip(MYFLT x)
 
44
{
 
45
    if (x < 0)
 
46
        return 0;
 
47
    else if (x > 1)
 
48
        return 1;
 
49
    else
 
50
        return x;
 
51
}
 
52
 
 
53
static void
 
54
Disto_transform_ii(Disto *self) {
 
55
    MYFLT val, coeff;
 
56
    int i;
 
57
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
58
 
 
59
    MYFLT drv = .4 - _clip(PyFloat_AS_DOUBLE(self->drive)) * .3999;
 
60
    MYFLT slp = _clip(PyFloat_AS_DOUBLE(self->slope));
 
61
    
 
62
    for (i=0; i<self->bufsize; i++) {
 
63
        val = MYATAN2(in[i], drv);
 
64
        self->data[i] = val;
 
65
    }
 
66
    coeff = 1.0 - slp;
 
67
    for (i=0; i<self->bufsize; i++) {
 
68
        val = self->data[i] * coeff + self->y1 * slp;
 
69
        self->y1 = val;
 
70
        self->data[i] = val;
 
71
    }
 
72
}
 
73
 
 
74
static void
 
75
Disto_transform_ai(Disto *self) {
 
76
    MYFLT val, drv, coeff;
 
77
    int i;
 
78
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
79
 
 
80
    MYFLT *drive = Stream_getData((Stream *)self->drive_stream);
 
81
    MYFLT slp = _clip(PyFloat_AS_DOUBLE(self->slope));
 
82
    
 
83
    for (i=0; i<self->bufsize; i++) {
 
84
        drv = .4 - _clip(drive[i]) * .3999;
 
85
        val = MYATAN2(in[i], drv);
 
86
        self->data[i] = val;
 
87
    }
 
88
    
 
89
    coeff = 1.0 - slp;
 
90
    for (i=0; i<self->bufsize; i++) {
 
91
        val = self->data[i] * coeff + self->y1 * slp;
 
92
        self->y1 = val;
 
93
        self->data[i] = val;
 
94
    }
 
95
}
 
96
 
 
97
static void
 
98
Disto_transform_ia(Disto *self) {
 
99
    MYFLT val, coeff, slp;
 
100
    int i;
 
101
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
102
    
 
103
    MYFLT drv = .4 - _clip(PyFloat_AS_DOUBLE(self->drive)) * .3999;
 
104
    MYFLT *slope = Stream_getData((Stream *)self->slope_stream);
 
105
    
 
106
    for (i=0; i<self->bufsize; i++) {
 
107
        val = MYATAN2(in[i], drv);
 
108
        self->data[i] = val;
 
109
    }
 
110
    for (i=0; i<self->bufsize; i++) {
 
111
        slp = _clip(slope[i]);
 
112
        coeff = 1.0 - slp;
 
113
        val = self->data[i] * coeff + self->y1 * slp;
 
114
        self->y1 = val;
 
115
        self->data[i] = val;
 
116
    }
 
117
}
 
118
 
 
119
static void
 
120
Disto_transform_aa(Disto *self) {
 
121
    MYFLT val, drv, coeff, slp;
 
122
    int i;
 
123
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
124
    
 
125
    MYFLT *drive = Stream_getData((Stream *)self->drive_stream);
 
126
    MYFLT *slope = Stream_getData((Stream *)self->slope_stream);
 
127
    
 
128
    for (i=0; i<self->bufsize; i++) {
 
129
        drv = .4 - _clip(drive[i]) * .3999;
 
130
        val = MYATAN2(in[i], drv);
 
131
        self->data[i] = val;
 
132
    }
 
133
    for (i=0; i<self->bufsize; i++) {
 
134
        slp = _clip(slope[i]);
 
135
        coeff = 1.0 - slp;
 
136
        val = self->data[i] * coeff + self->y1 * slp;
 
137
        self->y1 = val;
 
138
        self->data[i] = val;
 
139
    }
 
140
}
 
141
 
 
142
static void Disto_postprocessing_ii(Disto *self) { POST_PROCESSING_II };
 
143
static void Disto_postprocessing_ai(Disto *self) { POST_PROCESSING_AI };
 
144
static void Disto_postprocessing_ia(Disto *self) { POST_PROCESSING_IA };
 
145
static void Disto_postprocessing_aa(Disto *self) { POST_PROCESSING_AA };
 
146
static void Disto_postprocessing_ireva(Disto *self) { POST_PROCESSING_IREVA };
 
147
static void Disto_postprocessing_areva(Disto *self) { POST_PROCESSING_AREVA };
 
148
static void Disto_postprocessing_revai(Disto *self) { POST_PROCESSING_REVAI };
 
149
static void Disto_postprocessing_revaa(Disto *self) { POST_PROCESSING_REVAA };
 
150
static void Disto_postprocessing_revareva(Disto *self) { POST_PROCESSING_REVAREVA };
 
151
 
 
152
static void
 
153
Disto_setProcMode(Disto *self)
 
154
{
 
155
    int procmode, muladdmode;
 
156
    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
 
157
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
158
 
 
159
        switch (procmode) {
 
160
        case 0:    
 
161
            self->proc_func_ptr = Disto_transform_ii;
 
162
            break;
 
163
        case 1:    
 
164
            self->proc_func_ptr = Disto_transform_ai;
 
165
            break;
 
166
        case 10:        
 
167
            self->proc_func_ptr = Disto_transform_ia;
 
168
            break;
 
169
        case 11:    
 
170
            self->proc_func_ptr = Disto_transform_aa;
 
171
            break;
 
172
    } 
 
173
        switch (muladdmode) {
 
174
        case 0:        
 
175
            self->muladd_func_ptr = Disto_postprocessing_ii;
 
176
            break;
 
177
        case 1:    
 
178
            self->muladd_func_ptr = Disto_postprocessing_ai;
 
179
            break;
 
180
        case 2:    
 
181
            self->muladd_func_ptr = Disto_postprocessing_revai;
 
182
            break;
 
183
        case 10:        
 
184
            self->muladd_func_ptr = Disto_postprocessing_ia;
 
185
            break;
 
186
        case 11:    
 
187
            self->muladd_func_ptr = Disto_postprocessing_aa;
 
188
            break;
 
189
        case 12:    
 
190
            self->muladd_func_ptr = Disto_postprocessing_revaa;
 
191
            break;
 
192
        case 20:        
 
193
            self->muladd_func_ptr = Disto_postprocessing_ireva;
 
194
            break;
 
195
        case 21:    
 
196
            self->muladd_func_ptr = Disto_postprocessing_areva;
 
197
            break;
 
198
        case 22:    
 
199
            self->muladd_func_ptr = Disto_postprocessing_revareva;
 
200
            break;
 
201
    }   
 
202
}
 
203
 
 
204
static void
 
205
Disto_compute_next_data_frame(Disto *self)
 
206
{
 
207
    (*self->proc_func_ptr)(self); 
 
208
    (*self->muladd_func_ptr)(self);
 
209
}
 
210
 
 
211
static int
 
212
Disto_traverse(Disto *self, visitproc visit, void *arg)
 
213
{
 
214
    pyo_VISIT
 
215
    Py_VISIT(self->input);
 
216
    Py_VISIT(self->input_stream);    
 
217
    Py_VISIT(self->drive);    
 
218
    Py_VISIT(self->drive_stream);    
 
219
    Py_VISIT(self->slope);    
 
220
    Py_VISIT(self->slope_stream);    
 
221
    return 0;
 
222
}
 
223
 
 
224
static int 
 
225
Disto_clear(Disto *self)
 
226
{
 
227
    pyo_CLEAR
 
228
    Py_CLEAR(self->input);
 
229
    Py_CLEAR(self->input_stream);
 
230
    Py_CLEAR(self->drive);    
 
231
    Py_CLEAR(self->drive_stream);    
 
232
    Py_CLEAR(self->slope);    
 
233
    Py_CLEAR(self->slope_stream);    
 
234
    return 0;
 
235
}
 
236
 
 
237
static void
 
238
Disto_dealloc(Disto* self)
 
239
{
 
240
    free(self->data);
 
241
    Disto_clear(self);
 
242
    self->ob_type->tp_free((PyObject*)self);
 
243
}
 
244
 
 
245
static PyObject * Disto_deleteStream(Disto *self) { DELETE_STREAM };
 
246
 
 
247
static PyObject *
 
248
Disto_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
249
{
 
250
    int i;
 
251
    Disto *self;
 
252
    self = (Disto *)type->tp_alloc(type, 0);
 
253
 
 
254
    self->drive = PyFloat_FromDouble(.75);
 
255
    self->slope = PyFloat_FromDouble(.5);
 
256
        self->modebuffer[0] = 0;
 
257
        self->modebuffer[1] = 0;
 
258
        self->modebuffer[2] = 0;
 
259
        self->modebuffer[3] = 0;
 
260
    self->y1 = 0;
 
261
 
 
262
    INIT_OBJECT_COMMON
 
263
    Stream_setFunctionPtr(self->stream, Disto_compute_next_data_frame);
 
264
    self->mode_func_ptr = Disto_setProcMode;
 
265
    
 
266
    return (PyObject *)self;
 
267
}
 
268
 
 
269
static int
 
270
Disto_init(Disto *self, PyObject *args, PyObject *kwds)
 
271
{
 
272
    PyObject *inputtmp, *input_streamtmp, *drivetmp=NULL, *slopetmp=NULL, *multmp=NULL, *addtmp=NULL;
 
273
 
 
274
    static char *kwlist[] = {"input", "drive", "slope", "mul", "add", NULL};
 
275
 
 
276
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &drivetmp, &slopetmp, &multmp, &addtmp))
 
277
        return -1; 
 
278
 
 
279
    INIT_INPUT_STREAM
 
280
    
 
281
    if (drivetmp) {
 
282
        PyObject_CallMethod((PyObject *)self, "setDrive", "O", drivetmp);
 
283
    }
 
284
 
 
285
    if (slopetmp) {
 
286
        PyObject_CallMethod((PyObject *)self, "setSlope", "O", slopetmp);
 
287
    }
 
288
    
 
289
    if (multmp) {
 
290
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
291
    }
 
292
 
 
293
    if (addtmp) {
 
294
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
295
    }
 
296
            
 
297
    Py_INCREF(self->stream);
 
298
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
299
 
 
300
    (*self->mode_func_ptr)(self);
 
301
 
 
302
    Py_INCREF(self);
 
303
    return 0;
 
304
}
 
305
 
 
306
static PyObject * Disto_getServer(Disto* self) { GET_SERVER };
 
307
static PyObject * Disto_getStream(Disto* self) { GET_STREAM };
 
308
static PyObject * Disto_setMul(Disto *self, PyObject *arg) { SET_MUL }; 
 
309
static PyObject * Disto_setAdd(Disto *self, PyObject *arg) { SET_ADD }; 
 
310
static PyObject * Disto_setSub(Disto *self, PyObject *arg) { SET_SUB }; 
 
311
static PyObject * Disto_setDiv(Disto *self, PyObject *arg) { SET_DIV }; 
 
312
 
 
313
static PyObject * Disto_play(Disto *self, PyObject *args, PyObject *kwds) { PLAY };
 
314
static PyObject * Disto_out(Disto *self, PyObject *args, PyObject *kwds) { OUT };
 
315
static PyObject * Disto_stop(Disto *self) { STOP };
 
316
 
 
317
static PyObject * Disto_multiply(Disto *self, PyObject *arg) { MULTIPLY };
 
318
static PyObject * Disto_inplace_multiply(Disto *self, PyObject *arg) { INPLACE_MULTIPLY };
 
319
static PyObject * Disto_add(Disto *self, PyObject *arg) { ADD };
 
320
static PyObject * Disto_inplace_add(Disto *self, PyObject *arg) { INPLACE_ADD };
 
321
static PyObject * Disto_sub(Disto *self, PyObject *arg) { SUB };
 
322
static PyObject * Disto_inplace_sub(Disto *self, PyObject *arg) { INPLACE_SUB };
 
323
static PyObject * Disto_div(Disto *self, PyObject *arg) { DIV };
 
324
static PyObject * Disto_inplace_div(Disto *self, PyObject *arg) { INPLACE_DIV };
 
325
 
 
326
static PyObject *
 
327
Disto_setDrive(Disto *self, PyObject *arg)
 
328
{
 
329
        PyObject *tmp, *streamtmp;
 
330
        
 
331
        if (arg == NULL) {
 
332
                Py_INCREF(Py_None);
 
333
                return Py_None;
 
334
        }
 
335
    
 
336
        int isNumber = PyNumber_Check(arg);
 
337
        
 
338
        tmp = arg;
 
339
        Py_INCREF(tmp);
 
340
        Py_DECREF(self->drive);
 
341
        if (isNumber == 1) {
 
342
                self->drive = PyNumber_Float(tmp);
 
343
        self->modebuffer[2] = 0;
 
344
        }
 
345
        else {
 
346
                self->drive = tmp;
 
347
        streamtmp = PyObject_CallMethod((PyObject *)self->drive, "_getStream", NULL);
 
348
        Py_INCREF(streamtmp);
 
349
        Py_XDECREF(self->drive_stream);
 
350
        self->drive_stream = (Stream *)streamtmp;
 
351
                self->modebuffer[2] = 1;
 
352
        }
 
353
    
 
354
    (*self->mode_func_ptr)(self);
 
355
    
 
356
        Py_INCREF(Py_None);
 
357
        return Py_None;
 
358
}       
 
359
 
 
360
static PyObject *
 
361
Disto_setSlope(Disto *self, PyObject *arg)
 
362
{
 
363
        PyObject *tmp, *streamtmp;
 
364
        
 
365
        if (arg == NULL) {
 
366
                Py_INCREF(Py_None);
 
367
                return Py_None;
 
368
        }
 
369
    
 
370
        int isNumber = PyNumber_Check(arg);
 
371
        
 
372
        tmp = arg;
 
373
        Py_INCREF(tmp);
 
374
        Py_DECREF(self->slope);
 
375
        if (isNumber == 1) {
 
376
                self->slope = PyNumber_Float(tmp);
 
377
        self->modebuffer[3] = 0;
 
378
        }
 
379
        else {
 
380
                self->slope = tmp;
 
381
        streamtmp = PyObject_CallMethod((PyObject *)self->slope, "_getStream", NULL);
 
382
        Py_INCREF(streamtmp);
 
383
        Py_XDECREF(self->slope_stream);
 
384
        self->slope_stream = (Stream *)streamtmp;
 
385
                self->modebuffer[3] = 1;
 
386
        }
 
387
    
 
388
    (*self->mode_func_ptr)(self);
 
389
    
 
390
        Py_INCREF(Py_None);
 
391
        return Py_None;
 
392
}       
 
393
 
 
394
static PyMemberDef Disto_members[] = {
 
395
    {"server", T_OBJECT_EX, offsetof(Disto, server), 0, "Pyo server."},
 
396
    {"stream", T_OBJECT_EX, offsetof(Disto, stream), 0, "Stream object."},
 
397
    {"input", T_OBJECT_EX, offsetof(Disto, input), 0, "Input sound object."},
 
398
    {"drive", T_OBJECT_EX, offsetof(Disto, drive), 0, "Cutoff driveuency in cycle per second."},
 
399
    {"slope", T_OBJECT_EX, offsetof(Disto, slope), 0, "Lowpass filter slope factor."},
 
400
    {"mul", T_OBJECT_EX, offsetof(Disto, mul), 0, "Mul factor."},
 
401
    {"add", T_OBJECT_EX, offsetof(Disto, add), 0, "Add factor."},
 
402
    {NULL}  /* Sentinel */
 
403
};
 
404
 
 
405
static PyMethodDef Disto_methods[] = {
 
406
    {"getServer", (PyCFunction)Disto_getServer, METH_NOARGS, "Returns server object."},
 
407
    {"_getStream", (PyCFunction)Disto_getStream, METH_NOARGS, "Returns stream object."},
 
408
    {"deleteStream", (PyCFunction)Disto_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
409
    {"play", (PyCFunction)Disto_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
410
    {"out", (PyCFunction)Disto_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 
411
    {"stop", (PyCFunction)Disto_stop, METH_NOARGS, "Stops computing."},
 
412
        {"setDrive", (PyCFunction)Disto_setDrive, METH_O, "Sets distortion drive factor (0 -> 1)."},
 
413
    {"setSlope", (PyCFunction)Disto_setSlope, METH_O, "Sets lowpass filter slope factor."},
 
414
        {"setMul", (PyCFunction)Disto_setMul, METH_O, "Sets oscillator mul factor."},
 
415
        {"setAdd", (PyCFunction)Disto_setAdd, METH_O, "Sets oscillator add factor."},
 
416
    {"setSub", (PyCFunction)Disto_setSub, METH_O, "Sets inverse add factor."},
 
417
    {"setDiv", (PyCFunction)Disto_setDiv, METH_O, "Sets inverse mul factor."},
 
418
    {NULL}  /* Sentinel */
 
419
};
 
420
 
 
421
static PyNumberMethods Disto_as_number = {
 
422
    (binaryfunc)Disto_add,                      /*nb_add*/
 
423
    (binaryfunc)Disto_sub,                 /*nb_subtract*/
 
424
    (binaryfunc)Disto_multiply,                 /*nb_multiply*/
 
425
    (binaryfunc)Disto_div,                   /*nb_divide*/
 
426
    0,                /*nb_remainder*/
 
427
    0,                   /*nb_divmod*/
 
428
    0,                   /*nb_power*/
 
429
    0,                  /*nb_neg*/
 
430
    0,                /*nb_pos*/
 
431
    0,                  /*(unaryfunc)array_abs,*/
 
432
    0,                    /*nb_nonzero*/
 
433
    0,                    /*nb_invert*/
 
434
    0,               /*nb_lshift*/
 
435
    0,              /*nb_rshift*/
 
436
    0,              /*nb_and*/
 
437
    0,              /*nb_xor*/
 
438
    0,               /*nb_or*/
 
439
    0,                                          /*nb_coerce*/
 
440
    0,                       /*nb_int*/
 
441
    0,                      /*nb_long*/
 
442
    0,                     /*nb_float*/
 
443
    0,                       /*nb_oct*/
 
444
    0,                       /*nb_hex*/
 
445
    (binaryfunc)Disto_inplace_add,              /*inplace_add*/
 
446
    (binaryfunc)Disto_inplace_sub,         /*inplace_subtract*/
 
447
    (binaryfunc)Disto_inplace_multiply,         /*inplace_multiply*/
 
448
    (binaryfunc)Disto_inplace_div,           /*inplace_divide*/
 
449
    0,        /*inplace_remainder*/
 
450
    0,           /*inplace_power*/
 
451
    0,       /*inplace_lshift*/
 
452
    0,      /*inplace_rshift*/
 
453
    0,      /*inplace_and*/
 
454
    0,      /*inplace_xor*/
 
455
    0,       /*inplace_or*/
 
456
    0,             /*nb_floor_divide*/
 
457
    0,              /*nb_true_divide*/
 
458
    0,     /*nb_inplace_floor_divide*/
 
459
    0,      /*nb_inplace_true_divide*/
 
460
    0,                     /* nb_index */
 
461
};
 
462
 
 
463
PyTypeObject DistoType = {
 
464
    PyObject_HEAD_INIT(NULL)
 
465
    0,                         /*ob_size*/
 
466
    "_pyo.Disto_base",         /*tp_name*/
 
467
    sizeof(Disto),         /*tp_basicsize*/
 
468
    0,                         /*tp_itemsize*/
 
469
    (destructor)Disto_dealloc, /*tp_dealloc*/
 
470
    0,                         /*tp_print*/
 
471
    0,                         /*tp_getattr*/
 
472
    0,                         /*tp_setattr*/
 
473
    0,                         /*tp_compare*/
 
474
    0,                         /*tp_repr*/
 
475
    &Disto_as_number,             /*tp_as_number*/
 
476
    0,                         /*tp_as_sequence*/
 
477
    0,                         /*tp_as_mapping*/
 
478
    0,                         /*tp_hash */
 
479
    0,                         /*tp_call*/
 
480
    0,                         /*tp_str*/
 
481
    0,                         /*tp_getattro*/
 
482
    0,                         /*tp_setattro*/
 
483
    0,                         /*tp_as_buffer*/
 
484
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
485
    "Disto objects. Arctan distortion.",           /* tp_doc */
 
486
    (traverseproc)Disto_traverse,   /* tp_traverse */
 
487
    (inquiry)Disto_clear,           /* tp_clear */
 
488
    0,                         /* tp_richcompare */
 
489
    0,                         /* tp_weaklistoffset */
 
490
    0,                         /* tp_iter */
 
491
    0,                         /* tp_iternext */
 
492
    Disto_methods,             /* tp_methods */
 
493
    Disto_members,             /* tp_members */
 
494
    0,                      /* tp_getset */
 
495
    0,                         /* tp_base */
 
496
    0,                         /* tp_dict */
 
497
    0,                         /* tp_descr_get */
 
498
    0,                         /* tp_descr_set */
 
499
    0,                         /* tp_dictoffset */
 
500
    (initproc)Disto_init,      /* tp_init */
 
501
    0,                         /* tp_alloc */
 
502
    Disto_new,                 /* tp_new */
 
503
};
 
504
 
 
505
/*****************/
 
506
/** Clip object **/
 
507
/*****************/
 
508
 
 
509
typedef struct {
 
510
    pyo_audio_HEAD
 
511
    PyObject *input;
 
512
    Stream *input_stream;
 
513
    PyObject *min;
 
514
    Stream *min_stream;
 
515
    PyObject *max;
 
516
    Stream *max_stream;
 
517
    int modebuffer[4];
 
518
} Clip;
 
519
 
 
520
static void
 
521
Clip_transform_ii(Clip *self) {
 
522
    MYFLT val;
 
523
    int i;
 
524
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
525
    MYFLT mi = PyFloat_AS_DOUBLE(self->min);
 
526
    MYFLT ma = PyFloat_AS_DOUBLE(self->max);
 
527
    
 
528
    for (i=0; i<self->bufsize; i++) {
 
529
        val = in[i];
 
530
        if(val < mi)
 
531
            self->data[i] = mi;
 
532
        else if(val > ma)
 
533
            self->data[i] = ma;
 
534
        else
 
535
            self->data[i] = val;
 
536
    }
 
537
}
 
538
 
 
539
static void
 
540
Clip_transform_ai(Clip *self) {
 
541
    MYFLT val, mini;
 
542
    int i;
 
543
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
544
    MYFLT *mi = Stream_getData((Stream *)self->min_stream);
 
545
    MYFLT ma = PyFloat_AS_DOUBLE(self->max);
 
546
    
 
547
    for (i=0; i<self->bufsize; i++) {
 
548
        val = in[i];
 
549
        mini = mi[i];
 
550
        if(val < mini)
 
551
            self->data[i] = mini;
 
552
        else if(val > ma)
 
553
            self->data[i] = ma;
 
554
        else
 
555
            self->data[i] = val;
 
556
    }
 
557
}
 
558
 
 
559
static void
 
560
Clip_transform_ia(Clip *self) {
 
561
    MYFLT val, maxi;
 
562
    int i;
 
563
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
564
    MYFLT mi = PyFloat_AS_DOUBLE(self->min);
 
565
    MYFLT *ma = Stream_getData((Stream *)self->max_stream);
 
566
    
 
567
    for (i=0; i<self->bufsize; i++) {
 
568
        val = in[i];
 
569
        maxi = ma[i];
 
570
        if(val < mi)
 
571
            self->data[i] = mi;
 
572
        else if(val > maxi)
 
573
            self->data[i] = maxi;
 
574
        else
 
575
            self->data[i] = val;
 
576
    }
 
577
}
 
578
    
 
579
static void
 
580
Clip_transform_aa(Clip *self) {
 
581
    MYFLT val, mini, maxi;
 
582
    int i;
 
583
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
584
    MYFLT *mi = Stream_getData((Stream *)self->min_stream);
 
585
    MYFLT *ma = Stream_getData((Stream *)self->max_stream);
 
586
    
 
587
    for (i=0; i<self->bufsize; i++) {
 
588
        val = in[i];
 
589
        mini = mi[i];
 
590
        maxi = ma[i];
 
591
        if(val < mini)
 
592
            self->data[i] = mini;
 
593
        else if(val > maxi)
 
594
            self->data[i] = maxi;
 
595
        else
 
596
            self->data[i] = val;
 
597
    }
 
598
}
 
599
 
 
600
static void Clip_postprocessing_ii(Clip *self) { POST_PROCESSING_II };
 
601
static void Clip_postprocessing_ai(Clip *self) { POST_PROCESSING_AI };
 
602
static void Clip_postprocessing_ia(Clip *self) { POST_PROCESSING_IA };
 
603
static void Clip_postprocessing_aa(Clip *self) { POST_PROCESSING_AA };
 
604
static void Clip_postprocessing_ireva(Clip *self) { POST_PROCESSING_IREVA };
 
605
static void Clip_postprocessing_areva(Clip *self) { POST_PROCESSING_AREVA };
 
606
static void Clip_postprocessing_revai(Clip *self) { POST_PROCESSING_REVAI };
 
607
static void Clip_postprocessing_revaa(Clip *self) { POST_PROCESSING_REVAA };
 
608
static void Clip_postprocessing_revareva(Clip *self) { POST_PROCESSING_REVAREVA };
 
609
 
 
610
static void
 
611
Clip_setProcMode(Clip *self)
 
612
{
 
613
    int procmode, muladdmode;
 
614
    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
 
615
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
616
    
 
617
        switch (procmode) {
 
618
        case 0:    
 
619
            self->proc_func_ptr = Clip_transform_ii;
 
620
            break;
 
621
        case 1:    
 
622
            self->proc_func_ptr = Clip_transform_ai;
 
623
            break;
 
624
        case 10:        
 
625
            self->proc_func_ptr = Clip_transform_ia;
 
626
            break;
 
627
        case 11:    
 
628
            self->proc_func_ptr = Clip_transform_aa;
 
629
            break;
 
630
    } 
 
631
        switch (muladdmode) {
 
632
        case 0:        
 
633
            self->muladd_func_ptr = Clip_postprocessing_ii;
 
634
            break;
 
635
        case 1:    
 
636
            self->muladd_func_ptr = Clip_postprocessing_ai;
 
637
            break;
 
638
        case 2:    
 
639
            self->muladd_func_ptr = Clip_postprocessing_revai;
 
640
            break;
 
641
        case 10:        
 
642
            self->muladd_func_ptr = Clip_postprocessing_ia;
 
643
            break;
 
644
        case 11:    
 
645
            self->muladd_func_ptr = Clip_postprocessing_aa;
 
646
            break;
 
647
        case 12:    
 
648
            self->muladd_func_ptr = Clip_postprocessing_revaa;
 
649
            break;
 
650
        case 20:        
 
651
            self->muladd_func_ptr = Clip_postprocessing_ireva;
 
652
            break;
 
653
        case 21:    
 
654
            self->muladd_func_ptr = Clip_postprocessing_areva;
 
655
            break;
 
656
        case 22:    
 
657
            self->muladd_func_ptr = Clip_postprocessing_revareva;
 
658
            break;
 
659
    }   
 
660
}
 
661
 
 
662
static void
 
663
Clip_compute_next_data_frame(Clip *self)
 
664
{
 
665
    (*self->proc_func_ptr)(self); 
 
666
    (*self->muladd_func_ptr)(self);
 
667
}
 
668
 
 
669
static int
 
670
Clip_traverse(Clip *self, visitproc visit, void *arg)
 
671
{
 
672
    pyo_VISIT
 
673
    Py_VISIT(self->input);
 
674
    Py_VISIT(self->input_stream);    
 
675
    Py_VISIT(self->min);    
 
676
    Py_VISIT(self->min_stream);    
 
677
    Py_VISIT(self->max);    
 
678
    Py_VISIT(self->max_stream);    
 
679
    return 0;
 
680
}
 
681
 
 
682
static int 
 
683
Clip_clear(Clip *self)
 
684
{
 
685
    pyo_CLEAR
 
686
    Py_CLEAR(self->input);
 
687
    Py_CLEAR(self->input_stream);
 
688
    Py_CLEAR(self->min);    
 
689
    Py_CLEAR(self->min_stream);    
 
690
    Py_CLEAR(self->max);    
 
691
    Py_CLEAR(self->max_stream);    
 
692
    return 0;
 
693
}
 
694
 
 
695
static void
 
696
Clip_dealloc(Clip* self)
 
697
{
 
698
    free(self->data);
 
699
    Clip_clear(self);
 
700
    self->ob_type->tp_free((PyObject*)self);
 
701
}
 
702
 
 
703
static PyObject * Clip_deleteStream(Clip *self) { DELETE_STREAM };
 
704
 
 
705
static PyObject *
 
706
Clip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
707
{
 
708
    int i;
 
709
    Clip *self;
 
710
    self = (Clip *)type->tp_alloc(type, 0);
 
711
    
 
712
    self->min = PyFloat_FromDouble(-1.0);
 
713
    self->max = PyFloat_FromDouble(1.0);
 
714
        self->modebuffer[0] = 0;
 
715
        self->modebuffer[1] = 0;
 
716
        self->modebuffer[2] = 0;
 
717
        self->modebuffer[3] = 0;
 
718
    
 
719
    INIT_OBJECT_COMMON
 
720
    Stream_setFunctionPtr(self->stream, Clip_compute_next_data_frame);
 
721
    self->mode_func_ptr = Clip_setProcMode;
 
722
    
 
723
    return (PyObject *)self;
 
724
}
 
725
 
 
726
static int
 
727
Clip_init(Clip *self, PyObject *args, PyObject *kwds)
 
728
{
 
729
    PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
 
730
    
 
731
    static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
 
732
    
 
733
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp))
 
734
        return -1; 
 
735
    
 
736
    INIT_INPUT_STREAM
 
737
    
 
738
    if (mintmp) {
 
739
        PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
 
740
    }
 
741
    
 
742
    if (maxtmp) {
 
743
        PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
 
744
    }
 
745
    
 
746
    if (multmp) {
 
747
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
748
    }
 
749
    
 
750
    if (addtmp) {
 
751
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
752
    }
 
753
    
 
754
    Py_INCREF(self->stream);
 
755
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
756
    
 
757
    (*self->mode_func_ptr)(self);
 
758
        
 
759
    Py_INCREF(self);
 
760
    return 0;
 
761
}
 
762
 
 
763
static PyObject * Clip_getServer(Clip* self) { GET_SERVER };
 
764
static PyObject * Clip_getStream(Clip* self) { GET_STREAM };
 
765
static PyObject * Clip_setMul(Clip *self, PyObject *arg) { SET_MUL };   
 
766
static PyObject * Clip_setAdd(Clip *self, PyObject *arg) { SET_ADD };   
 
767
static PyObject * Clip_setSub(Clip *self, PyObject *arg) { SET_SUB };   
 
768
static PyObject * Clip_setDiv(Clip *self, PyObject *arg) { SET_DIV };   
 
769
 
 
770
static PyObject * Clip_play(Clip *self, PyObject *args, PyObject *kwds) { PLAY };
 
771
static PyObject * Clip_out(Clip *self, PyObject *args, PyObject *kwds) { OUT };
 
772
static PyObject * Clip_stop(Clip *self) { STOP };
 
773
 
 
774
static PyObject * Clip_multiply(Clip *self, PyObject *arg) { MULTIPLY };
 
775
static PyObject * Clip_inplace_multiply(Clip *self, PyObject *arg) { INPLACE_MULTIPLY };
 
776
static PyObject * Clip_add(Clip *self, PyObject *arg) { ADD };
 
777
static PyObject * Clip_inplace_add(Clip *self, PyObject *arg) { INPLACE_ADD };
 
778
static PyObject * Clip_sub(Clip *self, PyObject *arg) { SUB };
 
779
static PyObject * Clip_inplace_sub(Clip *self, PyObject *arg) { INPLACE_SUB };
 
780
static PyObject * Clip_div(Clip *self, PyObject *arg) { DIV };
 
781
static PyObject * Clip_inplace_div(Clip *self, PyObject *arg) { INPLACE_DIV };
 
782
 
 
783
static PyObject *
 
784
Clip_setMin(Clip *self, PyObject *arg)
 
785
{
 
786
        PyObject *tmp, *streamtmp;
 
787
        
 
788
        if (arg == NULL) {
 
789
                Py_INCREF(Py_None);
 
790
                return Py_None;
 
791
        }
 
792
    
 
793
        int isNumber = PyNumber_Check(arg);
 
794
        
 
795
        tmp = arg;
 
796
        Py_INCREF(tmp);
 
797
        Py_DECREF(self->min);
 
798
        if (isNumber == 1) {
 
799
                self->min = PyNumber_Float(tmp);
 
800
        self->modebuffer[2] = 0;
 
801
        }
 
802
        else {
 
803
                self->min = tmp;
 
804
        streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL);
 
805
        Py_INCREF(streamtmp);
 
806
        Py_XDECREF(self->min_stream);
 
807
        self->min_stream = (Stream *)streamtmp;
 
808
                self->modebuffer[2] = 1;
 
809
        }
 
810
    
 
811
    (*self->mode_func_ptr)(self);
 
812
    
 
813
        Py_INCREF(Py_None);
 
814
        return Py_None;
 
815
}       
 
816
 
 
817
static PyObject *
 
818
Clip_setMax(Clip *self, PyObject *arg)
 
819
{
 
820
        PyObject *tmp, *streamtmp;
 
821
        
 
822
        if (arg == NULL) {
 
823
                Py_INCREF(Py_None);
 
824
                return Py_None;
 
825
        }
 
826
    
 
827
        int isNumber = PyNumber_Check(arg);
 
828
        
 
829
        tmp = arg;
 
830
        Py_INCREF(tmp);
 
831
        Py_DECREF(self->max);
 
832
        if (isNumber == 1) {
 
833
                self->max = PyNumber_Float(tmp);
 
834
        self->modebuffer[3] = 0;
 
835
        }
 
836
        else {
 
837
                self->max = tmp;
 
838
        streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL);
 
839
        Py_INCREF(streamtmp);
 
840
        Py_XDECREF(self->max_stream);
 
841
        self->max_stream = (Stream *)streamtmp;
 
842
                self->modebuffer[3] = 1;
 
843
        }
 
844
    
 
845
    (*self->mode_func_ptr)(self);
 
846
    
 
847
        Py_INCREF(Py_None);
 
848
        return Py_None;
 
849
}       
 
850
 
 
851
static PyMemberDef Clip_members[] = {
 
852
{"server", T_OBJECT_EX, offsetof(Clip, server), 0, "Pyo server."},
 
853
{"stream", T_OBJECT_EX, offsetof(Clip, stream), 0, "Stream object."},
 
854
{"input", T_OBJECT_EX, offsetof(Clip, input), 0, "Input sound object."},
 
855
{"min", T_OBJECT_EX, offsetof(Clip, min), 0, "Minimum possible value."},
 
856
{"max", T_OBJECT_EX, offsetof(Clip, max), 0, "Maximum possible value."},
 
857
{"mul", T_OBJECT_EX, offsetof(Clip, mul), 0, "Mul factor."},
 
858
{"add", T_OBJECT_EX, offsetof(Clip, add), 0, "Add factor."},
 
859
{NULL}  /* Sentinel */
 
860
};
 
861
 
 
862
static PyMethodDef Clip_methods[] = {
 
863
{"getServer", (PyCFunction)Clip_getServer, METH_NOARGS, "Returns server object."},
 
864
{"_getStream", (PyCFunction)Clip_getStream, METH_NOARGS, "Returns stream object."},
 
865
{"deleteStream", (PyCFunction)Clip_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
866
{"play", (PyCFunction)Clip_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
867
{"out", (PyCFunction)Clip_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 
868
{"stop", (PyCFunction)Clip_stop, METH_NOARGS, "Stops computing."},
 
869
{"setMin", (PyCFunction)Clip_setMin, METH_O, "Sets the minimum value."},
 
870
{"setMax", (PyCFunction)Clip_setMax, METH_O, "Sets the maximum value."},
 
871
{"setMul", (PyCFunction)Clip_setMul, METH_O, "Sets oscillator mul factor."},
 
872
{"setAdd", (PyCFunction)Clip_setAdd, METH_O, "Sets oscillator add factor."},
 
873
{"setSub", (PyCFunction)Clip_setSub, METH_O, "Sets inverse add factor."},
 
874
{"setDiv", (PyCFunction)Clip_setDiv, METH_O, "Sets inverse mul factor."},
 
875
{NULL}  /* Sentinel */
 
876
};
 
877
 
 
878
static PyNumberMethods Clip_as_number = {
 
879
(binaryfunc)Clip_add,                      /*nb_add*/
 
880
(binaryfunc)Clip_sub,                 /*nb_subtract*/
 
881
(binaryfunc)Clip_multiply,                 /*nb_multiply*/
 
882
(binaryfunc)Clip_div,                   /*nb_divide*/
 
883
0,                /*nb_remainder*/
 
884
0,                   /*nb_divmod*/
 
885
0,                   /*nb_power*/
 
886
0,                  /*nb_neg*/
 
887
0,                /*nb_pos*/
 
888
0,                  /*(unaryfunc)array_abs,*/
 
889
0,                    /*nb_nonzero*/
 
890
0,                    /*nb_invert*/
 
891
0,               /*nb_lshift*/
 
892
0,              /*nb_rshift*/
 
893
0,              /*nb_and*/
 
894
0,              /*nb_xor*/
 
895
0,               /*nb_or*/
 
896
0,                                          /*nb_coerce*/
 
897
0,                       /*nb_int*/
 
898
0,                      /*nb_long*/
 
899
0,                     /*nb_float*/
 
900
0,                       /*nb_oct*/
 
901
0,                       /*nb_hex*/
 
902
(binaryfunc)Clip_inplace_add,              /*inplace_add*/
 
903
(binaryfunc)Clip_inplace_sub,         /*inplace_subtract*/
 
904
(binaryfunc)Clip_inplace_multiply,         /*inplace_multiply*/
 
905
(binaryfunc)Clip_inplace_div,           /*inplace_divide*/
 
906
0,        /*inplace_remainder*/
 
907
0,           /*inplace_power*/
 
908
0,       /*inplace_lshift*/
 
909
0,      /*inplace_rshift*/
 
910
0,      /*inplace_and*/
 
911
0,      /*inplace_xor*/
 
912
0,       /*inplace_or*/
 
913
0,             /*nb_floor_divide*/
 
914
0,              /*nb_true_divide*/
 
915
0,     /*nb_inplace_floor_divide*/
 
916
0,      /*nb_inplace_true_divide*/
 
917
0,                     /* nb_index */
 
918
};
 
919
 
 
920
PyTypeObject ClipType = {
 
921
PyObject_HEAD_INIT(NULL)
 
922
0,                         /*ob_size*/
 
923
"_pyo.Clip_base",         /*tp_name*/
 
924
sizeof(Clip),         /*tp_basicsize*/
 
925
0,                         /*tp_itemsize*/
 
926
(destructor)Clip_dealloc, /*tp_dealloc*/
 
927
0,                         /*tp_print*/
 
928
0,                         /*tp_getattr*/
 
929
0,                         /*tp_setattr*/
 
930
0,                         /*tp_compare*/
 
931
0,                         /*tp_repr*/
 
932
&Clip_as_number,             /*tp_as_number*/
 
933
0,                         /*tp_as_sequence*/
 
934
0,                         /*tp_as_mapping*/
 
935
0,                         /*tp_hash */
 
936
0,                         /*tp_call*/
 
937
0,                         /*tp_str*/
 
938
0,                         /*tp_getattro*/
 
939
0,                         /*tp_setattro*/
 
940
0,                         /*tp_as_buffer*/
 
941
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
942
"Clip objects. Clips a signal to a predefined limit.",           /* tp_doc */
 
943
(traverseproc)Clip_traverse,   /* tp_traverse */
 
944
(inquiry)Clip_clear,           /* tp_clear */
 
945
0,                             /* tp_richcompare */
 
946
0,                             /* tp_weaklistoffset */
 
947
0,                             /* tp_iter */
 
948
0,                             /* tp_iternext */
 
949
Clip_methods,             /* tp_methods */
 
950
Clip_members,             /* tp_members */
 
951
0,                      /* tp_getset */
 
952
0,                         /* tp_base */
 
953
0,                         /* tp_dict */
 
954
0,                         /* tp_descr_get */
 
955
0,                         /* tp_descr_set */
 
956
0,                         /* tp_dictoffset */
 
957
(initproc)Clip_init,      /* tp_init */
 
958
0,                         /* tp_alloc */
 
959
Clip_new,                 /* tp_new */
 
960
};
 
961
 
 
962
/*****************/
 
963
/* Mirror object */
 
964
/*****************/
 
965
 
 
966
typedef struct {
 
967
    pyo_audio_HEAD
 
968
    PyObject *input;
 
969
    Stream *input_stream;
 
970
    PyObject *min;
 
971
    Stream *min_stream;
 
972
    PyObject *max;
 
973
    Stream *max_stream;
 
974
    int modebuffer[4];
 
975
} Mirror;
 
976
 
 
977
static void
 
978
Mirror_transform_ii(Mirror *self) {
 
979
    MYFLT val, avg;
 
980
    int i;
 
981
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
982
    MYFLT mi = PyFloat_AS_DOUBLE(self->min);
 
983
    MYFLT ma = PyFloat_AS_DOUBLE(self->max);
 
984
    
 
985
    if (mi >= ma) {
 
986
        avg = (mi + ma) * 0.5;
 
987
        for (i=0; i<self->bufsize; i++) {
 
988
            self->data[i] = avg;
 
989
        }
 
990
    }
 
991
    else {
 
992
        for (i=0; i<self->bufsize; i++) {
 
993
            val = in[i];
 
994
            while ((val > ma) || (val < mi)) {
 
995
                if (val > ma)
 
996
                    val = ma + ma - val;
 
997
                else
 
998
                    val = mi + mi - val;
 
999
            }
 
1000
            self->data[i] = val;
 
1001
        }
 
1002
    }
 
1003
}
 
1004
 
 
1005
static void
 
1006
Mirror_transform_ai(Mirror *self) {
 
1007
    MYFLT val, avg, mi;
 
1008
    int i;
 
1009
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1010
    MYFLT *mini = Stream_getData((Stream *)self->min_stream);
 
1011
    MYFLT ma = PyFloat_AS_DOUBLE(self->max);
 
1012
    
 
1013
    for (i=0; i<self->bufsize; i++) {
 
1014
        val = in[i];
 
1015
        mi = mini[i];
 
1016
        if (mi >= ma) {
 
1017
            avg = (mi + ma) * 0.5;
 
1018
            self->data[i] = avg;
 
1019
        }
 
1020
        else {
 
1021
            while ((val > ma) || (val < mi)) {
 
1022
                if (val > ma)
 
1023
                    val = ma + ma - val;
 
1024
                else
 
1025
                    val = mi + mi - val;
 
1026
            }
 
1027
            self->data[i] = val;            
 
1028
        }
 
1029
    }
 
1030
}
 
1031
 
 
1032
static void
 
1033
Mirror_transform_ia(Mirror *self) {
 
1034
    MYFLT val, avg, ma;
 
1035
    int i;
 
1036
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1037
    MYFLT mi = PyFloat_AS_DOUBLE(self->min);
 
1038
    MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
 
1039
    
 
1040
    for (i=0; i<self->bufsize; i++) {
 
1041
        val = in[i];
 
1042
        ma = maxi[i];
 
1043
        if (mi >= ma) {
 
1044
            avg = (mi + ma) * 0.5;
 
1045
            self->data[i] = avg;
 
1046
        }
 
1047
        else {
 
1048
            while ((val > ma) || (val < mi)) {
 
1049
                if (val > ma)
 
1050
                    val = ma + ma - val;
 
1051
                else
 
1052
                    val = mi + mi - val;
 
1053
            }
 
1054
            self->data[i] = val;            
 
1055
        }
 
1056
    }
 
1057
}
 
1058
 
 
1059
static void
 
1060
Mirror_transform_aa(Mirror *self) {
 
1061
    MYFLT val, avg, mi, ma;
 
1062
    int i;
 
1063
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1064
    MYFLT *mini = Stream_getData((Stream *)self->min_stream);
 
1065
    MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
 
1066
    
 
1067
    for (i=0; i<self->bufsize; i++) {
 
1068
        val = in[i];
 
1069
        mi = mini[i];
 
1070
        ma = maxi[i];
 
1071
        if (mi >= ma) {
 
1072
            avg = (mi + ma) * 0.5;
 
1073
            self->data[i] = avg;
 
1074
        }
 
1075
        else {
 
1076
            while ((val > ma) || (val < mi)) {
 
1077
                if (val > ma)
 
1078
                    val = ma + ma - val;
 
1079
                else
 
1080
                    val = mi + mi - val;
 
1081
            }
 
1082
            self->data[i] = val;            
 
1083
        }
 
1084
    }
 
1085
}
 
1086
 
 
1087
static void Mirror_postprocessing_ii(Mirror *self) { POST_PROCESSING_II };
 
1088
static void Mirror_postprocessing_ai(Mirror *self) { POST_PROCESSING_AI };
 
1089
static void Mirror_postprocessing_ia(Mirror *self) { POST_PROCESSING_IA };
 
1090
static void Mirror_postprocessing_aa(Mirror *self) { POST_PROCESSING_AA };
 
1091
static void Mirror_postprocessing_ireva(Mirror *self) { POST_PROCESSING_IREVA };
 
1092
static void Mirror_postprocessing_areva(Mirror *self) { POST_PROCESSING_AREVA };
 
1093
static void Mirror_postprocessing_revai(Mirror *self) { POST_PROCESSING_REVAI };
 
1094
static void Mirror_postprocessing_revaa(Mirror *self) { POST_PROCESSING_REVAA };
 
1095
static void Mirror_postprocessing_revareva(Mirror *self) { POST_PROCESSING_REVAREVA };
 
1096
 
 
1097
static void
 
1098
Mirror_setProcMode(Mirror *self)
 
1099
{
 
1100
    int procmode, muladdmode;
 
1101
    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
 
1102
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
1103
    
 
1104
        switch (procmode) {
 
1105
        case 0:    
 
1106
            self->proc_func_ptr = Mirror_transform_ii;
 
1107
            break;
 
1108
        case 1:    
 
1109
            self->proc_func_ptr = Mirror_transform_ai;
 
1110
            break;
 
1111
        case 10:        
 
1112
            self->proc_func_ptr = Mirror_transform_ia;
 
1113
            break;
 
1114
        case 11:    
 
1115
            self->proc_func_ptr = Mirror_transform_aa;
 
1116
            break;
 
1117
    } 
 
1118
        switch (muladdmode) {
 
1119
        case 0:        
 
1120
            self->muladd_func_ptr = Mirror_postprocessing_ii;
 
1121
            break;
 
1122
        case 1:    
 
1123
            self->muladd_func_ptr = Mirror_postprocessing_ai;
 
1124
            break;
 
1125
        case 2:    
 
1126
            self->muladd_func_ptr = Mirror_postprocessing_revai;
 
1127
            break;
 
1128
        case 10:        
 
1129
            self->muladd_func_ptr = Mirror_postprocessing_ia;
 
1130
            break;
 
1131
        case 11:    
 
1132
            self->muladd_func_ptr = Mirror_postprocessing_aa;
 
1133
            break;
 
1134
        case 12:    
 
1135
            self->muladd_func_ptr = Mirror_postprocessing_revaa;
 
1136
            break;
 
1137
        case 20:        
 
1138
            self->muladd_func_ptr = Mirror_postprocessing_ireva;
 
1139
            break;
 
1140
        case 21:    
 
1141
            self->muladd_func_ptr = Mirror_postprocessing_areva;
 
1142
            break;
 
1143
        case 22:    
 
1144
            self->muladd_func_ptr = Mirror_postprocessing_revareva;
 
1145
            break;
 
1146
    }   
 
1147
}
 
1148
 
 
1149
static void
 
1150
Mirror_compute_next_data_frame(Mirror *self)
 
1151
{
 
1152
    (*self->proc_func_ptr)(self); 
 
1153
    (*self->muladd_func_ptr)(self);
 
1154
}
 
1155
 
 
1156
static int
 
1157
Mirror_traverse(Mirror *self, visitproc visit, void *arg)
 
1158
{
 
1159
    pyo_VISIT
 
1160
    Py_VISIT(self->input);
 
1161
    Py_VISIT(self->input_stream);    
 
1162
    Py_VISIT(self->min);    
 
1163
    Py_VISIT(self->min_stream);    
 
1164
    Py_VISIT(self->max);    
 
1165
    Py_VISIT(self->max_stream);    
 
1166
    return 0;
 
1167
}
 
1168
 
 
1169
static int 
 
1170
Mirror_clear(Mirror *self)
 
1171
{
 
1172
    pyo_CLEAR
 
1173
    Py_CLEAR(self->input);
 
1174
    Py_CLEAR(self->input_stream);
 
1175
    Py_CLEAR(self->min);    
 
1176
    Py_CLEAR(self->min_stream);    
 
1177
    Py_CLEAR(self->max);    
 
1178
    Py_CLEAR(self->max_stream);    
 
1179
    return 0;
 
1180
}
 
1181
 
 
1182
static void
 
1183
Mirror_dealloc(Mirror* self)
 
1184
{
 
1185
    free(self->data);
 
1186
    Mirror_clear(self);
 
1187
    self->ob_type->tp_free((PyObject*)self);
 
1188
}
 
1189
 
 
1190
static PyObject * Mirror_deleteStream(Mirror *self) { DELETE_STREAM };
 
1191
 
 
1192
static PyObject *
 
1193
Mirror_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
1194
{
 
1195
    int i;
 
1196
    Mirror *self;
 
1197
    self = (Mirror *)type->tp_alloc(type, 0);
 
1198
    
 
1199
    self->min = PyFloat_FromDouble(0.0);
 
1200
    self->max = PyFloat_FromDouble(1.0);
 
1201
        self->modebuffer[0] = 0;
 
1202
        self->modebuffer[1] = 0;
 
1203
        self->modebuffer[2] = 0;
 
1204
        self->modebuffer[3] = 0;
 
1205
    
 
1206
    INIT_OBJECT_COMMON
 
1207
    Stream_setFunctionPtr(self->stream, Mirror_compute_next_data_frame);
 
1208
    self->mode_func_ptr = Mirror_setProcMode;
 
1209
    
 
1210
    return (PyObject *)self;
 
1211
}
 
1212
 
 
1213
static int
 
1214
Mirror_init(Mirror *self, PyObject *args, PyObject *kwds)
 
1215
{
 
1216
    PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
 
1217
    
 
1218
    static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
 
1219
    
 
1220
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp))
 
1221
        return -1; 
 
1222
    
 
1223
    INIT_INPUT_STREAM
 
1224
    
 
1225
    if (mintmp) {
 
1226
        PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
 
1227
    }
 
1228
    
 
1229
    if (maxtmp) {
 
1230
        PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
 
1231
    }
 
1232
    
 
1233
    if (multmp) {
 
1234
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
1235
    }
 
1236
    
 
1237
    if (addtmp) {
 
1238
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
1239
    }
 
1240
    
 
1241
    Py_INCREF(self->stream);
 
1242
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
1243
    
 
1244
    (*self->mode_func_ptr)(self);
 
1245
    
 
1246
    Py_INCREF(self);
 
1247
    return 0;
 
1248
}
 
1249
 
 
1250
static PyObject * Mirror_getServer(Mirror* self) { GET_SERVER };
 
1251
static PyObject * Mirror_getStream(Mirror* self) { GET_STREAM };
 
1252
static PyObject * Mirror_setMul(Mirror *self, PyObject *arg) { SET_MUL };       
 
1253
static PyObject * Mirror_setAdd(Mirror *self, PyObject *arg) { SET_ADD };       
 
1254
static PyObject * Mirror_setSub(Mirror *self, PyObject *arg) { SET_SUB };       
 
1255
static PyObject * Mirror_setDiv(Mirror *self, PyObject *arg) { SET_DIV };       
 
1256
 
 
1257
static PyObject * Mirror_play(Mirror *self, PyObject *args, PyObject *kwds) { PLAY };
 
1258
static PyObject * Mirror_out(Mirror *self, PyObject *args, PyObject *kwds) { OUT };
 
1259
static PyObject * Mirror_stop(Mirror *self) { STOP };
 
1260
 
 
1261
static PyObject * Mirror_multiply(Mirror *self, PyObject *arg) { MULTIPLY };
 
1262
static PyObject * Mirror_inplace_multiply(Mirror *self, PyObject *arg) { INPLACE_MULTIPLY };
 
1263
static PyObject * Mirror_add(Mirror *self, PyObject *arg) { ADD };
 
1264
static PyObject * Mirror_inplace_add(Mirror *self, PyObject *arg) { INPLACE_ADD };
 
1265
static PyObject * Mirror_sub(Mirror *self, PyObject *arg) { SUB };
 
1266
static PyObject * Mirror_inplace_sub(Mirror *self, PyObject *arg) { INPLACE_SUB };
 
1267
static PyObject * Mirror_div(Mirror *self, PyObject *arg) { DIV };
 
1268
static PyObject * Mirror_inplace_div(Mirror *self, PyObject *arg) { INPLACE_DIV };
 
1269
 
 
1270
static PyObject *
 
1271
Mirror_setMin(Mirror *self, PyObject *arg)
 
1272
{
 
1273
        PyObject *tmp, *streamtmp;
 
1274
        
 
1275
        if (arg == NULL) {
 
1276
                Py_INCREF(Py_None);
 
1277
                return Py_None;
 
1278
        }
 
1279
    
 
1280
        int isNumber = PyNumber_Check(arg);
 
1281
        
 
1282
        tmp = arg;
 
1283
        Py_INCREF(tmp);
 
1284
        Py_DECREF(self->min);
 
1285
        if (isNumber == 1) {
 
1286
                self->min = PyNumber_Float(tmp);
 
1287
        self->modebuffer[2] = 0;
 
1288
        }
 
1289
        else {
 
1290
                self->min = tmp;
 
1291
        streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL);
 
1292
        Py_INCREF(streamtmp);
 
1293
        Py_XDECREF(self->min_stream);
 
1294
        self->min_stream = (Stream *)streamtmp;
 
1295
                self->modebuffer[2] = 1;
 
1296
        }
 
1297
    
 
1298
    (*self->mode_func_ptr)(self);
 
1299
    
 
1300
        Py_INCREF(Py_None);
 
1301
        return Py_None;
 
1302
}       
 
1303
 
 
1304
static PyObject *
 
1305
Mirror_setMax(Mirror *self, PyObject *arg)
 
1306
{
 
1307
        PyObject *tmp, *streamtmp;
 
1308
        
 
1309
        if (arg == NULL) {
 
1310
                Py_INCREF(Py_None);
 
1311
                return Py_None;
 
1312
        }
 
1313
    
 
1314
        int isNumber = PyNumber_Check(arg);
 
1315
        
 
1316
        tmp = arg;
 
1317
        Py_INCREF(tmp);
 
1318
        Py_DECREF(self->max);
 
1319
        if (isNumber == 1) {
 
1320
                self->max = PyNumber_Float(tmp);
 
1321
        self->modebuffer[3] = 0;
 
1322
        }
 
1323
        else {
 
1324
                self->max = tmp;
 
1325
        streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL);
 
1326
        Py_INCREF(streamtmp);
 
1327
        Py_XDECREF(self->max_stream);
 
1328
        self->max_stream = (Stream *)streamtmp;
 
1329
                self->modebuffer[3] = 1;
 
1330
        }
 
1331
    
 
1332
    (*self->mode_func_ptr)(self);
 
1333
    
 
1334
        Py_INCREF(Py_None);
 
1335
        return Py_None;
 
1336
}       
 
1337
 
 
1338
static PyMemberDef Mirror_members[] = {
 
1339
    {"server", T_OBJECT_EX, offsetof(Mirror, server), 0, "Pyo server."},
 
1340
    {"stream", T_OBJECT_EX, offsetof(Mirror, stream), 0, "Stream object."},
 
1341
    {"input", T_OBJECT_EX, offsetof(Mirror, input), 0, "Input sound object."},
 
1342
    {"min", T_OBJECT_EX, offsetof(Mirror, min), 0, "Minimum possible value."},
 
1343
    {"max", T_OBJECT_EX, offsetof(Mirror, max), 0, "Maximum possible value."},
 
1344
    {"mul", T_OBJECT_EX, offsetof(Mirror, mul), 0, "Mul factor."},
 
1345
    {"add", T_OBJECT_EX, offsetof(Mirror, add), 0, "Add factor."},
 
1346
    {NULL}  /* Sentinel */
 
1347
};
 
1348
 
 
1349
static PyMethodDef Mirror_methods[] = {
 
1350
    {"getServer", (PyCFunction)Mirror_getServer, METH_NOARGS, "Returns server object."},
 
1351
    {"_getStream", (PyCFunction)Mirror_getStream, METH_NOARGS, "Returns stream object."},
 
1352
    {"deleteStream", (PyCFunction)Mirror_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
1353
    {"play", (PyCFunction)Mirror_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
1354
    {"out", (PyCFunction)Mirror_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 
1355
    {"stop", (PyCFunction)Mirror_stop, METH_NOARGS, "Stops computing."},
 
1356
    {"setMin", (PyCFunction)Mirror_setMin, METH_O, "Sets the minimum value."},
 
1357
    {"setMax", (PyCFunction)Mirror_setMax, METH_O, "Sets the maximum value."},
 
1358
    {"setMul", (PyCFunction)Mirror_setMul, METH_O, "Sets oscillator mul factor."},
 
1359
    {"setAdd", (PyCFunction)Mirror_setAdd, METH_O, "Sets oscillator add factor."},
 
1360
    {"setSub", (PyCFunction)Mirror_setSub, METH_O, "Sets inverse add factor."},
 
1361
    {"setDiv", (PyCFunction)Mirror_setDiv, METH_O, "Sets inverse mul factor."},
 
1362
    {NULL}  /* Sentinel */
 
1363
};
 
1364
 
 
1365
static PyNumberMethods Mirror_as_number = {
 
1366
    (binaryfunc)Mirror_add,                      /*nb_add*/
 
1367
    (binaryfunc)Mirror_sub,                 /*nb_subtract*/
 
1368
    (binaryfunc)Mirror_multiply,                 /*nb_multiply*/
 
1369
    (binaryfunc)Mirror_div,                   /*nb_divide*/
 
1370
    0,                /*nb_remainder*/
 
1371
    0,                   /*nb_divmod*/
 
1372
    0,                   /*nb_power*/
 
1373
    0,                  /*nb_neg*/
 
1374
    0,                /*nb_pos*/
 
1375
    0,                  /*(unaryfunc)array_abs,*/
 
1376
    0,                    /*nb_nonzero*/
 
1377
    0,                    /*nb_invert*/
 
1378
    0,               /*nb_lshift*/
 
1379
    0,              /*nb_rshift*/
 
1380
    0,              /*nb_and*/
 
1381
    0,              /*nb_xor*/
 
1382
    0,               /*nb_or*/
 
1383
    0,                                          /*nb_coerce*/
 
1384
    0,                       /*nb_int*/
 
1385
    0,                      /*nb_long*/
 
1386
    0,                     /*nb_float*/
 
1387
    0,                       /*nb_oct*/
 
1388
    0,                       /*nb_hex*/
 
1389
    (binaryfunc)Mirror_inplace_add,              /*inplace_add*/
 
1390
    (binaryfunc)Mirror_inplace_sub,         /*inplace_subtract*/
 
1391
    (binaryfunc)Mirror_inplace_multiply,         /*inplace_multiply*/
 
1392
    (binaryfunc)Mirror_inplace_div,           /*inplace_divide*/
 
1393
    0,        /*inplace_remainder*/
 
1394
    0,           /*inplace_power*/
 
1395
    0,       /*inplace_lshift*/
 
1396
    0,      /*inplace_rshift*/
 
1397
    0,      /*inplace_and*/
 
1398
    0,      /*inplace_xor*/
 
1399
    0,       /*inplace_or*/
 
1400
    0,             /*nb_floor_divide*/
 
1401
    0,              /*nb_true_divide*/
 
1402
    0,     /*nb_inplace_floor_divide*/
 
1403
    0,      /*nb_inplace_true_divide*/
 
1404
    0,                     /* nb_index */
 
1405
};
 
1406
 
 
1407
PyTypeObject MirrorType = {
 
1408
    PyObject_HEAD_INIT(NULL)
 
1409
    0,                         /*ob_size*/
 
1410
    "_pyo.Mirror_base",         /*tp_name*/
 
1411
    sizeof(Mirror),         /*tp_basicsize*/
 
1412
    0,                         /*tp_itemsize*/
 
1413
    (destructor)Mirror_dealloc, /*tp_dealloc*/
 
1414
    0,                         /*tp_print*/
 
1415
    0,                         /*tp_getattr*/
 
1416
    0,                         /*tp_setattr*/
 
1417
    0,                         /*tp_compare*/
 
1418
    0,                         /*tp_repr*/
 
1419
    &Mirror_as_number,             /*tp_as_number*/
 
1420
    0,                         /*tp_as_sequence*/
 
1421
    0,                         /*tp_as_mapping*/
 
1422
    0,                         /*tp_hash */
 
1423
    0,                         /*tp_call*/
 
1424
    0,                         /*tp_str*/
 
1425
    0,                         /*tp_getattro*/
 
1426
    0,                         /*tp_setattro*/
 
1427
    0,                         /*tp_as_buffer*/
 
1428
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
1429
    "Mirror objects. Reflects the signal that exceeds the min and max thresholds.",           /* tp_doc */
 
1430
    (traverseproc)Mirror_traverse,   /* tp_traverse */
 
1431
    (inquiry)Mirror_clear,           /* tp_clear */
 
1432
    0,                         /* tp_richcompare */
 
1433
    0,                         /* tp_weaklistoffset */
 
1434
    0,                         /* tp_iter */
 
1435
    0,                         /* tp_iternext */
 
1436
    Mirror_methods,             /* tp_methods */
 
1437
    Mirror_members,             /* tp_members */
 
1438
    0,                      /* tp_getset */
 
1439
    0,                         /* tp_base */
 
1440
    0,                         /* tp_dict */
 
1441
    0,                         /* tp_descr_get */
 
1442
    0,                         /* tp_descr_set */
 
1443
    0,                         /* tp_dictoffset */
 
1444
    (initproc)Mirror_init,      /* tp_init */
 
1445
    0,                         /* tp_alloc */
 
1446
    Mirror_new,                 /* tp_new */
 
1447
};
 
1448
 
 
1449
/*****************/
 
1450
/** Wrap object **/
 
1451
/*****************/
 
1452
 
 
1453
typedef struct {
 
1454
    pyo_audio_HEAD
 
1455
    PyObject *input;
 
1456
    Stream *input_stream;
 
1457
    PyObject *min;
 
1458
    Stream *min_stream;
 
1459
    PyObject *max;
 
1460
    Stream *max_stream;
 
1461
    int modebuffer[4];
 
1462
} Wrap;
 
1463
 
 
1464
static void
 
1465
Wrap_transform_ii(Wrap *self) {
 
1466
    MYFLT val, avg, rng, tmp;
 
1467
    int i;
 
1468
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1469
    MYFLT mi = PyFloat_AS_DOUBLE(self->min);
 
1470
    MYFLT ma = PyFloat_AS_DOUBLE(self->max);
 
1471
    
 
1472
    if (mi >= ma) {
 
1473
        avg = (mi + ma) * 0.5;
 
1474
        for (i=0; i<self->bufsize; i++) {
 
1475
            self->data[i] = avg;
 
1476
        }
 
1477
    }
 
1478
    else {
 
1479
        rng = ma - mi;
 
1480
        for (i=0; i<self->bufsize; i++) {
 
1481
            val = in[i];
 
1482
            tmp = (val - mi) / rng;
 
1483
            if (tmp >= 1.0) {
 
1484
                tmp -= (int)tmp;
 
1485
                val = tmp * rng + mi;
 
1486
            }
 
1487
            else if (tmp < 0) {
 
1488
                tmp += (int)(-tmp) + 1;
 
1489
                val = tmp * rng + mi;
 
1490
            }    
 
1491
            self->data[i] = val;
 
1492
        }
 
1493
    }
 
1494
}
 
1495
 
 
1496
static void
 
1497
Wrap_transform_ai(Wrap *self) {
 
1498
    MYFLT val, avg, rng, tmp, mi;
 
1499
    int i;
 
1500
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1501
    MYFLT *mini = Stream_getData((Stream *)self->min_stream);
 
1502
    MYFLT ma = PyFloat_AS_DOUBLE(self->max);
 
1503
    
 
1504
    for (i=0; i<self->bufsize; i++) {
 
1505
        val = in[i];
 
1506
        mi = mini[i];
 
1507
        if (mi >= ma) {
 
1508
            avg = (mi + ma) * 0.5;
 
1509
            self->data[i] = avg;
 
1510
        }
 
1511
        else {
 
1512
            rng = ma - mi;
 
1513
            tmp = (val - mi) / rng;
 
1514
            if (tmp >= 1.0) {
 
1515
                tmp -= (int)tmp;
 
1516
                val = tmp * rng + mi;
 
1517
            }
 
1518
            else if (tmp < 0) {
 
1519
                tmp += (int)(-tmp) + 1;
 
1520
                val = tmp * rng + mi;
 
1521
            }    
 
1522
            self->data[i] = val;            
 
1523
        }
 
1524
    }
 
1525
}
 
1526
 
 
1527
static void
 
1528
Wrap_transform_ia(Wrap *self) {
 
1529
    MYFLT val, avg, rng, tmp, ma;
 
1530
    int i;
 
1531
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1532
    MYFLT mi = PyFloat_AS_DOUBLE(self->min);
 
1533
    MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
 
1534
    
 
1535
    for (i=0; i<self->bufsize; i++) {
 
1536
        val = in[i];
 
1537
        ma = maxi[i];
 
1538
        if (mi >= ma) {
 
1539
            avg = (mi + ma) * 0.5;
 
1540
            self->data[i] = avg;
 
1541
        }
 
1542
        else {
 
1543
            rng = ma - mi;
 
1544
            tmp = (val - mi) / rng;
 
1545
            if (tmp >= 1.0) {
 
1546
                tmp -= (int)tmp;
 
1547
                val = tmp * rng + mi;
 
1548
            }
 
1549
            else if (tmp < 0) {
 
1550
                tmp += (int)(-tmp) + 1;
 
1551
                val = tmp * rng + mi;
 
1552
            }    
 
1553
            self->data[i] = val;            
 
1554
        }
 
1555
    }
 
1556
}
 
1557
 
 
1558
static void
 
1559
Wrap_transform_aa(Wrap *self) {
 
1560
    MYFLT val, avg, rng, tmp, mi, ma;
 
1561
    int i;
 
1562
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1563
    MYFLT *mini = Stream_getData((Stream *)self->min_stream);
 
1564
    MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
 
1565
    
 
1566
    for (i=0; i<self->bufsize; i++) {
 
1567
        val = in[i];
 
1568
        mi = mini[i];
 
1569
        ma = maxi[i];
 
1570
        if (mi >= ma) {
 
1571
            avg = (mi + ma) * 0.5;
 
1572
            self->data[i] = avg;
 
1573
        }
 
1574
        else {
 
1575
            rng = ma - mi;
 
1576
            tmp = (val - mi) / rng;
 
1577
            if (tmp >= 1.0) {
 
1578
                tmp -= (int)tmp;
 
1579
                val = tmp * rng + mi;
 
1580
            }
 
1581
            else if (tmp < 0) {
 
1582
                tmp += (int)(-tmp) + 1;
 
1583
                val = tmp * rng + mi;
 
1584
            }    
 
1585
            self->data[i] = val;            
 
1586
        }
 
1587
    }
 
1588
}
 
1589
 
 
1590
static void Wrap_postprocessing_ii(Wrap *self) { POST_PROCESSING_II };
 
1591
static void Wrap_postprocessing_ai(Wrap *self) { POST_PROCESSING_AI };
 
1592
static void Wrap_postprocessing_ia(Wrap *self) { POST_PROCESSING_IA };
 
1593
static void Wrap_postprocessing_aa(Wrap *self) { POST_PROCESSING_AA };
 
1594
static void Wrap_postprocessing_ireva(Wrap *self) { POST_PROCESSING_IREVA };
 
1595
static void Wrap_postprocessing_areva(Wrap *self) { POST_PROCESSING_AREVA };
 
1596
static void Wrap_postprocessing_revai(Wrap *self) { POST_PROCESSING_REVAI };
 
1597
static void Wrap_postprocessing_revaa(Wrap *self) { POST_PROCESSING_REVAA };
 
1598
static void Wrap_postprocessing_revareva(Wrap *self) { POST_PROCESSING_REVAREVA };
 
1599
 
 
1600
static void
 
1601
Wrap_setProcMode(Wrap *self)
 
1602
{
 
1603
    int procmode, muladdmode;
 
1604
    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
 
1605
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
1606
    
 
1607
        switch (procmode) {
 
1608
        case 0:    
 
1609
            self->proc_func_ptr = Wrap_transform_ii;
 
1610
            break;
 
1611
        case 1:    
 
1612
            self->proc_func_ptr = Wrap_transform_ai;
 
1613
            break;
 
1614
        case 10:        
 
1615
            self->proc_func_ptr = Wrap_transform_ia;
 
1616
            break;
 
1617
        case 11:    
 
1618
            self->proc_func_ptr = Wrap_transform_aa;
 
1619
            break;
 
1620
    } 
 
1621
        switch (muladdmode) {
 
1622
        case 0:        
 
1623
            self->muladd_func_ptr = Wrap_postprocessing_ii;
 
1624
            break;
 
1625
        case 1:    
 
1626
            self->muladd_func_ptr = Wrap_postprocessing_ai;
 
1627
            break;
 
1628
        case 2:    
 
1629
            self->muladd_func_ptr = Wrap_postprocessing_revai;
 
1630
            break;
 
1631
        case 10:        
 
1632
            self->muladd_func_ptr = Wrap_postprocessing_ia;
 
1633
            break;
 
1634
        case 11:    
 
1635
            self->muladd_func_ptr = Wrap_postprocessing_aa;
 
1636
            break;
 
1637
        case 12:    
 
1638
            self->muladd_func_ptr = Wrap_postprocessing_revaa;
 
1639
            break;
 
1640
        case 20:        
 
1641
            self->muladd_func_ptr = Wrap_postprocessing_ireva;
 
1642
            break;
 
1643
        case 21:    
 
1644
            self->muladd_func_ptr = Wrap_postprocessing_areva;
 
1645
            break;
 
1646
        case 22:    
 
1647
            self->muladd_func_ptr = Wrap_postprocessing_revareva;
 
1648
            break;
 
1649
    }   
 
1650
}
 
1651
 
 
1652
static void
 
1653
Wrap_compute_next_data_frame(Wrap *self)
 
1654
{
 
1655
    (*self->proc_func_ptr)(self); 
 
1656
    (*self->muladd_func_ptr)(self);
 
1657
}
 
1658
 
 
1659
static int
 
1660
Wrap_traverse(Wrap *self, visitproc visit, void *arg)
 
1661
{
 
1662
    pyo_VISIT
 
1663
    Py_VISIT(self->input);
 
1664
    Py_VISIT(self->input_stream);    
 
1665
    Py_VISIT(self->min);    
 
1666
    Py_VISIT(self->min_stream);    
 
1667
    Py_VISIT(self->max);    
 
1668
    Py_VISIT(self->max_stream);    
 
1669
    return 0;
 
1670
}
 
1671
 
 
1672
static int 
 
1673
Wrap_clear(Wrap *self)
 
1674
{
 
1675
    pyo_CLEAR
 
1676
    Py_CLEAR(self->input);
 
1677
    Py_CLEAR(self->input_stream);
 
1678
    Py_CLEAR(self->min);    
 
1679
    Py_CLEAR(self->min_stream);    
 
1680
    Py_CLEAR(self->max);    
 
1681
    Py_CLEAR(self->max_stream);    
 
1682
    return 0;
 
1683
}
 
1684
 
 
1685
static void
 
1686
Wrap_dealloc(Wrap* self)
 
1687
{
 
1688
    free(self->data);
 
1689
    Wrap_clear(self);
 
1690
    self->ob_type->tp_free((PyObject*)self);
 
1691
}
 
1692
 
 
1693
static PyObject * Wrap_deleteStream(Wrap *self) { DELETE_STREAM };
 
1694
 
 
1695
static PyObject *
 
1696
Wrap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
1697
{
 
1698
    int i;
 
1699
    Wrap *self;
 
1700
    self = (Wrap *)type->tp_alloc(type, 0);
 
1701
    
 
1702
    self->min = PyFloat_FromDouble(0.0);
 
1703
    self->max = PyFloat_FromDouble(1.0);
 
1704
        self->modebuffer[0] = 0;
 
1705
        self->modebuffer[1] = 0;
 
1706
        self->modebuffer[2] = 0;
 
1707
        self->modebuffer[3] = 0;
 
1708
    
 
1709
    INIT_OBJECT_COMMON
 
1710
    Stream_setFunctionPtr(self->stream, Wrap_compute_next_data_frame);
 
1711
    self->mode_func_ptr = Wrap_setProcMode;
 
1712
    
 
1713
    return (PyObject *)self;
 
1714
}
 
1715
 
 
1716
static int
 
1717
Wrap_init(Wrap *self, PyObject *args, PyObject *kwds)
 
1718
{
 
1719
    PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
 
1720
    
 
1721
    static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
 
1722
    
 
1723
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp))
 
1724
        return -1; 
 
1725
    
 
1726
    INIT_INPUT_STREAM
 
1727
    
 
1728
    if (mintmp) {
 
1729
        PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
 
1730
    }
 
1731
    
 
1732
    if (maxtmp) {
 
1733
        PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
 
1734
    }
 
1735
    
 
1736
    if (multmp) {
 
1737
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
1738
    }
 
1739
    
 
1740
    if (addtmp) {
 
1741
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
1742
    }
 
1743
    
 
1744
    Py_INCREF(self->stream);
 
1745
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
1746
    
 
1747
    (*self->mode_func_ptr)(self);
 
1748
    
 
1749
    Py_INCREF(self);
 
1750
    return 0;
 
1751
}
 
1752
 
 
1753
static PyObject * Wrap_getServer(Wrap* self) { GET_SERVER };
 
1754
static PyObject * Wrap_getStream(Wrap* self) { GET_STREAM };
 
1755
static PyObject * Wrap_setMul(Wrap *self, PyObject *arg) { SET_MUL };   
 
1756
static PyObject * Wrap_setAdd(Wrap *self, PyObject *arg) { SET_ADD };   
 
1757
static PyObject * Wrap_setSub(Wrap *self, PyObject *arg) { SET_SUB };   
 
1758
static PyObject * Wrap_setDiv(Wrap *self, PyObject *arg) { SET_DIV };   
 
1759
 
 
1760
static PyObject * Wrap_play(Wrap *self, PyObject *args, PyObject *kwds) { PLAY };
 
1761
static PyObject * Wrap_out(Wrap *self, PyObject *args, PyObject *kwds) { OUT };
 
1762
static PyObject * Wrap_stop(Wrap *self) { STOP };
 
1763
 
 
1764
static PyObject * Wrap_multiply(Wrap *self, PyObject *arg) { MULTIPLY };
 
1765
static PyObject * Wrap_inplace_multiply(Wrap *self, PyObject *arg) { INPLACE_MULTIPLY };
 
1766
static PyObject * Wrap_add(Wrap *self, PyObject *arg) { ADD };
 
1767
static PyObject * Wrap_inplace_add(Wrap *self, PyObject *arg) { INPLACE_ADD };
 
1768
static PyObject * Wrap_sub(Wrap *self, PyObject *arg) { SUB };
 
1769
static PyObject * Wrap_inplace_sub(Wrap *self, PyObject *arg) { INPLACE_SUB };
 
1770
static PyObject * Wrap_div(Wrap *self, PyObject *arg) { DIV };
 
1771
static PyObject * Wrap_inplace_div(Wrap *self, PyObject *arg) { INPLACE_DIV };
 
1772
 
 
1773
static PyObject *
 
1774
Wrap_setMin(Wrap *self, PyObject *arg)
 
1775
{
 
1776
        PyObject *tmp, *streamtmp;
 
1777
        
 
1778
        if (arg == NULL) {
 
1779
                Py_INCREF(Py_None);
 
1780
                return Py_None;
 
1781
        }
 
1782
    
 
1783
        int isNumber = PyNumber_Check(arg);
 
1784
        
 
1785
        tmp = arg;
 
1786
        Py_INCREF(tmp);
 
1787
        Py_DECREF(self->min);
 
1788
        if (isNumber == 1) {
 
1789
                self->min = PyNumber_Float(tmp);
 
1790
        self->modebuffer[2] = 0;
 
1791
        }
 
1792
        else {
 
1793
                self->min = tmp;
 
1794
        streamtmp = PyObject_CallMethod((PyObject *)self->min, "_getStream", NULL);
 
1795
        Py_INCREF(streamtmp);
 
1796
        Py_XDECREF(self->min_stream);
 
1797
        self->min_stream = (Stream *)streamtmp;
 
1798
                self->modebuffer[2] = 1;
 
1799
        }
 
1800
    
 
1801
    (*self->mode_func_ptr)(self);
 
1802
    
 
1803
        Py_INCREF(Py_None);
 
1804
        return Py_None;
 
1805
}       
 
1806
 
 
1807
static PyObject *
 
1808
Wrap_setMax(Wrap *self, PyObject *arg)
 
1809
{
 
1810
        PyObject *tmp, *streamtmp;
 
1811
        
 
1812
        if (arg == NULL) {
 
1813
                Py_INCREF(Py_None);
 
1814
                return Py_None;
 
1815
        }
 
1816
    
 
1817
        int isNumber = PyNumber_Check(arg);
 
1818
        
 
1819
        tmp = arg;
 
1820
        Py_INCREF(tmp);
 
1821
        Py_DECREF(self->max);
 
1822
        if (isNumber == 1) {
 
1823
                self->max = PyNumber_Float(tmp);
 
1824
        self->modebuffer[3] = 0;
 
1825
        }
 
1826
        else {
 
1827
                self->max = tmp;
 
1828
        streamtmp = PyObject_CallMethod((PyObject *)self->max, "_getStream", NULL);
 
1829
        Py_INCREF(streamtmp);
 
1830
        Py_XDECREF(self->max_stream);
 
1831
        self->max_stream = (Stream *)streamtmp;
 
1832
                self->modebuffer[3] = 1;
 
1833
        }
 
1834
    
 
1835
    (*self->mode_func_ptr)(self);
 
1836
    
 
1837
        Py_INCREF(Py_None);
 
1838
        return Py_None;
 
1839
}       
 
1840
 
 
1841
static PyMemberDef Wrap_members[] = {
 
1842
    {"server", T_OBJECT_EX, offsetof(Wrap, server), 0, "Pyo server."},
 
1843
    {"stream", T_OBJECT_EX, offsetof(Wrap, stream), 0, "Stream object."},
 
1844
    {"input", T_OBJECT_EX, offsetof(Wrap, input), 0, "Input sound object."},
 
1845
    {"min", T_OBJECT_EX, offsetof(Wrap, min), 0, "Minimum possible value."},
 
1846
    {"max", T_OBJECT_EX, offsetof(Wrap, max), 0, "Maximum possible value."},
 
1847
    {"mul", T_OBJECT_EX, offsetof(Wrap, mul), 0, "Mul factor."},
 
1848
    {"add", T_OBJECT_EX, offsetof(Wrap, add), 0, "Add factor."},
 
1849
    {NULL}  /* Sentinel */
 
1850
};
 
1851
 
 
1852
static PyMethodDef Wrap_methods[] = {
 
1853
    {"getServer", (PyCFunction)Wrap_getServer, METH_NOARGS, "Returns server object."},
 
1854
    {"_getStream", (PyCFunction)Wrap_getStream, METH_NOARGS, "Returns stream object."},
 
1855
    {"deleteStream", (PyCFunction)Wrap_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
1856
    {"play", (PyCFunction)Wrap_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
1857
    {"out", (PyCFunction)Wrap_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 
1858
    {"stop", (PyCFunction)Wrap_stop, METH_NOARGS, "Stops computing."},
 
1859
    {"setMin", (PyCFunction)Wrap_setMin, METH_O, "Sets the minimum value."},
 
1860
    {"setMax", (PyCFunction)Wrap_setMax, METH_O, "Sets the maximum value."},
 
1861
    {"setMul", (PyCFunction)Wrap_setMul, METH_O, "Sets oscillator mul factor."},
 
1862
    {"setAdd", (PyCFunction)Wrap_setAdd, METH_O, "Sets oscillator add factor."},
 
1863
    {"setSub", (PyCFunction)Wrap_setSub, METH_O, "Sets inverse add factor."},
 
1864
    {"setDiv", (PyCFunction)Wrap_setDiv, METH_O, "Sets inverse mul factor."},
 
1865
    {NULL}  /* Sentinel */
 
1866
};
 
1867
 
 
1868
static PyNumberMethods Wrap_as_number = {
 
1869
    (binaryfunc)Wrap_add,                      /*nb_add*/
 
1870
    (binaryfunc)Wrap_sub,                 /*nb_subtract*/
 
1871
    (binaryfunc)Wrap_multiply,                 /*nb_multiply*/
 
1872
    (binaryfunc)Wrap_div,                   /*nb_divide*/
 
1873
    0,                /*nb_remainder*/
 
1874
    0,                   /*nb_divmod*/
 
1875
    0,                   /*nb_power*/
 
1876
    0,                  /*nb_neg*/
 
1877
    0,                /*nb_pos*/
 
1878
    0,                  /*(unaryfunc)array_abs,*/
 
1879
    0,                    /*nb_nonzero*/
 
1880
    0,                    /*nb_invert*/
 
1881
    0,               /*nb_lshift*/
 
1882
    0,              /*nb_rshift*/
 
1883
    0,              /*nb_and*/
 
1884
    0,              /*nb_xor*/
 
1885
    0,               /*nb_or*/
 
1886
    0,                                          /*nb_coerce*/
 
1887
    0,                       /*nb_int*/
 
1888
    0,                      /*nb_long*/
 
1889
    0,                     /*nb_float*/
 
1890
    0,                       /*nb_oct*/
 
1891
    0,                       /*nb_hex*/
 
1892
    (binaryfunc)Wrap_inplace_add,              /*inplace_add*/
 
1893
    (binaryfunc)Wrap_inplace_sub,         /*inplace_subtract*/
 
1894
    (binaryfunc)Wrap_inplace_multiply,         /*inplace_multiply*/
 
1895
    (binaryfunc)Wrap_inplace_div,           /*inplace_divide*/
 
1896
    0,        /*inplace_remainder*/
 
1897
    0,           /*inplace_power*/
 
1898
    0,       /*inplace_lshift*/
 
1899
    0,      /*inplace_rshift*/
 
1900
    0,      /*inplace_and*/
 
1901
    0,      /*inplace_xor*/
 
1902
    0,       /*inplace_or*/
 
1903
    0,             /*nb_floor_divide*/
 
1904
    0,              /*nb_true_divide*/
 
1905
    0,     /*nb_inplace_floor_divide*/
 
1906
    0,      /*nb_inplace_true_divide*/
 
1907
    0,                     /* nb_index */
 
1908
};
 
1909
 
 
1910
PyTypeObject WrapType = {
 
1911
    PyObject_HEAD_INIT(NULL)
 
1912
    0,                         /*ob_size*/
 
1913
    "_pyo.Wrap_base",         /*tp_name*/
 
1914
    sizeof(Wrap),         /*tp_basicsize*/
 
1915
    0,                         /*tp_itemsize*/
 
1916
    (destructor)Wrap_dealloc, /*tp_dealloc*/
 
1917
    0,                         /*tp_print*/
 
1918
    0,                         /*tp_getattr*/
 
1919
    0,                         /*tp_setattr*/
 
1920
    0,                         /*tp_compare*/
 
1921
    0,                         /*tp_repr*/
 
1922
    &Wrap_as_number,             /*tp_as_number*/
 
1923
    0,                         /*tp_as_sequence*/
 
1924
    0,                         /*tp_as_mapping*/
 
1925
    0,                         /*tp_hash */
 
1926
    0,                         /*tp_call*/
 
1927
    0,                         /*tp_str*/
 
1928
    0,                         /*tp_getattro*/
 
1929
    0,                         /*tp_setattro*/
 
1930
    0,                         /*tp_as_buffer*/
 
1931
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
1932
    "Wrap objects. Wraps-around the signal that exceeds the min and max thresholds.",           /* tp_doc */
 
1933
    (traverseproc)Wrap_traverse,   /* tp_traverse */
 
1934
    (inquiry)Wrap_clear,           /* tp_clear */
 
1935
    0,                         /* tp_richcompare */
 
1936
    0,                         /* tp_weaklistoffset */
 
1937
    0,                         /* tp_iter */
 
1938
    0,                         /* tp_iternext */
 
1939
    Wrap_methods,             /* tp_methods */
 
1940
    Wrap_members,             /* tp_members */
 
1941
    0,                      /* tp_getset */
 
1942
    0,                         /* tp_base */
 
1943
    0,                         /* tp_dict */
 
1944
    0,                         /* tp_descr_get */
 
1945
    0,                         /* tp_descr_set */
 
1946
    0,                         /* tp_dictoffset */
 
1947
    (initproc)Wrap_init,      /* tp_init */
 
1948
    0,                         /* tp_alloc */
 
1949
    Wrap_new,                 /* tp_new */
 
1950
};
 
1951
 
 
1952
/*****************/
 
1953
/** Degrade object **/
 
1954
/*****************/
 
1955
 
 
1956
typedef struct {
 
1957
    pyo_audio_HEAD
 
1958
    PyObject *input;
 
1959
    Stream *input_stream;
 
1960
    PyObject *bitdepth;
 
1961
    Stream *bitdepth_stream;
 
1962
    PyObject *srscale;
 
1963
    Stream *srscale_stream;
 
1964
    MYFLT value;
 
1965
    int sampsCount;
 
1966
    int modebuffer[4];
 
1967
} Degrade;
 
1968
 
 
1969
static MYFLT 
 
1970
_bit_clip(MYFLT x) {
 
1971
    if (x < 1.0)
 
1972
        return 1.0;
 
1973
    else if (x > 32.0)
 
1974
        return 32.0;
 
1975
    else
 
1976
        return x;
 
1977
}
 
1978
 
 
1979
static MYFLT 
 
1980
_sr_clip(MYFLT x) {
 
1981
    // half sr ten times
 
1982
    if (x <= 0.0009765625)
 
1983
        return 0.0009765625;
 
1984
    else if (x > 1.0)
 
1985
        return 1.0;
 
1986
    else
 
1987
        return x;
 
1988
}
 
1989
 
 
1990
static void
 
1991
Degrade_transform_ii(Degrade *self) {
 
1992
    MYFLT bitscl, ibitscl, newsr;
 
1993
    int i, nsamps, tmp;
 
1994
    
 
1995
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
1996
    MYFLT bitdepth = _bit_clip(PyFloat_AS_DOUBLE(self->bitdepth));
 
1997
    MYFLT srscale = _sr_clip(PyFloat_AS_DOUBLE(self->srscale));
 
1998
    
 
1999
    bitscl = MYPOW(2.0, bitdepth-1);
 
2000
    ibitscl = 1.0 / bitscl;
 
2001
    
 
2002
    newsr = self->sr * srscale;
 
2003
    nsamps = (int)(self->sr / newsr);
 
2004
    
 
2005
    for (i=0; i<self->bufsize; i++) {
 
2006
        self->sampsCount++;
 
2007
        if (self->sampsCount >= nsamps) {
 
2008
            self->sampsCount = 0;
 
2009
            tmp = (int)(in[i] * bitscl + 0.5);
 
2010
            self->value = tmp * ibitscl;    
 
2011
        }
 
2012
        self->data[i] = self->value;
 
2013
    }
 
2014
}
 
2015
 
 
2016
static void
 
2017
Degrade_transform_ai(Degrade *self) {
 
2018
    MYFLT bitscl, ibitscl, newsr;
 
2019
    int i, nsamps, tmp;
 
2020
    
 
2021
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
2022
    MYFLT *bitdepth = Stream_getData((Stream *)self->bitdepth_stream);
 
2023
    MYFLT srscale = _sr_clip(PyFloat_AS_DOUBLE(self->srscale));
 
2024
 
 
2025
    newsr = self->sr * srscale;
 
2026
    nsamps = (int)(self->sr / newsr);
 
2027
    
 
2028
    for (i=0; i<self->bufsize; i++) {
 
2029
        self->sampsCount++;
 
2030
        if (self->sampsCount >= nsamps) {
 
2031
            self->sampsCount = 0;
 
2032
            bitscl = MYPOW(2.0, _bit_clip(bitdepth[i])-1);
 
2033
            ibitscl = 1.0 / bitscl;
 
2034
            tmp = (int)(in[i] * bitscl + 0.5);
 
2035
            self->value = tmp * ibitscl;    
 
2036
        }
 
2037
        self->data[i] = self->value;
 
2038
    }
 
2039
}
 
2040
 
 
2041
static void
 
2042
Degrade_transform_ia(Degrade *self) {
 
2043
    MYFLT bitscl, ibitscl, newsr;
 
2044
    int i, nsamps, tmp;
 
2045
    
 
2046
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
2047
    MYFLT bitdepth = _bit_clip(PyFloat_AS_DOUBLE(self->bitdepth));
 
2048
    MYFLT *srscale = Stream_getData((Stream *)self->srscale_stream);
 
2049
    
 
2050
    bitscl = MYPOW(2.0, bitdepth-1);
 
2051
    ibitscl = 1.0 / bitscl;
 
2052
 
 
2053
    for (i=0; i<self->bufsize; i++) {
 
2054
        newsr = self->sr * _sr_clip(srscale[i]);
 
2055
        nsamps = (int)(self->sr / newsr);
 
2056
        self->sampsCount++;
 
2057
        if (self->sampsCount >= nsamps) {
 
2058
            self->sampsCount = 0;
 
2059
            tmp = (int)(in[i] * bitscl + 0.5);
 
2060
            self->value = tmp * ibitscl;    
 
2061
        }
 
2062
        self->data[i] = self->value;
 
2063
    }
 
2064
}
 
2065
 
 
2066
static void
 
2067
Degrade_transform_aa(Degrade *self) {
 
2068
    MYFLT bitscl, ibitscl, newsr;
 
2069
    int i, nsamps, tmp;
 
2070
    
 
2071
    MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
2072
    MYFLT *bitdepth = Stream_getData((Stream *)self->bitdepth_stream);
 
2073
    MYFLT *srscale = Stream_getData((Stream *)self->srscale_stream);
 
2074
 
 
2075
    for (i=0; i<self->bufsize; i++) {
 
2076
        newsr = self->sr * _sr_clip(srscale[i]);
 
2077
        nsamps = (int)(self->sr / newsr);
 
2078
        self->sampsCount++;
 
2079
        if (self->sampsCount >= nsamps) {
 
2080
            self->sampsCount = 0;
 
2081
            bitscl = MYPOW(2.0, _bit_clip(bitdepth[i])-1);
 
2082
            ibitscl = 1.0 / bitscl;
 
2083
            tmp = (int)(in[i] * bitscl + 0.5);
 
2084
            self->value = tmp * ibitscl;    
 
2085
        }
 
2086
        self->data[i] = self->value;
 
2087
    }
 
2088
}
 
2089
 
 
2090
static void Degrade_postprocessing_ii(Degrade *self) { POST_PROCESSING_II };
 
2091
static void Degrade_postprocessing_ai(Degrade *self) { POST_PROCESSING_AI };
 
2092
static void Degrade_postprocessing_ia(Degrade *self) { POST_PROCESSING_IA };
 
2093
static void Degrade_postprocessing_aa(Degrade *self) { POST_PROCESSING_AA };
 
2094
static void Degrade_postprocessing_ireva(Degrade *self) { POST_PROCESSING_IREVA };
 
2095
static void Degrade_postprocessing_areva(Degrade *self) { POST_PROCESSING_AREVA };
 
2096
static void Degrade_postprocessing_revai(Degrade *self) { POST_PROCESSING_REVAI };
 
2097
static void Degrade_postprocessing_revaa(Degrade *self) { POST_PROCESSING_REVAA };
 
2098
static void Degrade_postprocessing_revareva(Degrade *self) { POST_PROCESSING_REVAREVA };
 
2099
 
 
2100
static void
 
2101
Degrade_setProcMode(Degrade *self)
 
2102
{
 
2103
    int procmode, muladdmode;
 
2104
    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
 
2105
    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
2106
    
 
2107
        switch (procmode) {
 
2108
        case 0:    
 
2109
            self->proc_func_ptr = Degrade_transform_ii;
 
2110
            break;
 
2111
        case 1:    
 
2112
            self->proc_func_ptr = Degrade_transform_ai;
 
2113
            break;
 
2114
        case 10:        
 
2115
            self->proc_func_ptr = Degrade_transform_ia;
 
2116
            break;
 
2117
        case 11:    
 
2118
            self->proc_func_ptr = Degrade_transform_aa;
 
2119
            break;
 
2120
    } 
 
2121
        switch (muladdmode) {
 
2122
        case 0:        
 
2123
            self->muladd_func_ptr = Degrade_postprocessing_ii;
 
2124
            break;
 
2125
        case 1:    
 
2126
            self->muladd_func_ptr = Degrade_postprocessing_ai;
 
2127
            break;
 
2128
        case 2:    
 
2129
            self->muladd_func_ptr = Degrade_postprocessing_revai;
 
2130
            break;
 
2131
        case 10:        
 
2132
            self->muladd_func_ptr = Degrade_postprocessing_ia;
 
2133
            break;
 
2134
        case 11:    
 
2135
            self->muladd_func_ptr = Degrade_postprocessing_aa;
 
2136
            break;
 
2137
        case 12:    
 
2138
            self->muladd_func_ptr = Degrade_postprocessing_revaa;
 
2139
            break;
 
2140
        case 20:        
 
2141
            self->muladd_func_ptr = Degrade_postprocessing_ireva;
 
2142
            break;
 
2143
        case 21:    
 
2144
            self->muladd_func_ptr = Degrade_postprocessing_areva;
 
2145
            break;
 
2146
        case 22:    
 
2147
            self->muladd_func_ptr = Degrade_postprocessing_revareva;
 
2148
            break;
 
2149
    }   
 
2150
}
 
2151
 
 
2152
static void
 
2153
Degrade_compute_next_data_frame(Degrade *self)
 
2154
{
 
2155
    (*self->proc_func_ptr)(self); 
 
2156
    (*self->muladd_func_ptr)(self);
 
2157
}
 
2158
 
 
2159
static int
 
2160
Degrade_traverse(Degrade *self, visitproc visit, void *arg)
 
2161
{
 
2162
    pyo_VISIT
 
2163
    Py_VISIT(self->input);
 
2164
    Py_VISIT(self->input_stream);    
 
2165
    Py_VISIT(self->bitdepth);    
 
2166
    Py_VISIT(self->bitdepth_stream);    
 
2167
    Py_VISIT(self->srscale);    
 
2168
    Py_VISIT(self->srscale_stream);    
 
2169
    return 0;
 
2170
}
 
2171
 
 
2172
static int 
 
2173
Degrade_clear(Degrade *self)
 
2174
{
 
2175
    pyo_CLEAR
 
2176
    Py_CLEAR(self->input);
 
2177
    Py_CLEAR(self->input_stream);
 
2178
    Py_CLEAR(self->bitdepth);    
 
2179
    Py_CLEAR(self->bitdepth_stream);    
 
2180
    Py_CLEAR(self->srscale);    
 
2181
    Py_CLEAR(self->srscale_stream);    
 
2182
    return 0;
 
2183
}
 
2184
 
 
2185
static void
 
2186
Degrade_dealloc(Degrade* self)
 
2187
{
 
2188
    free(self->data);
 
2189
    Degrade_clear(self);
 
2190
    self->ob_type->tp_free((PyObject*)self);
 
2191
}
 
2192
 
 
2193
static PyObject * Degrade_deleteStream(Degrade *self) { DELETE_STREAM };
 
2194
 
 
2195
static PyObject *
 
2196
Degrade_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
2197
{
 
2198
    int i;
 
2199
    Degrade *self;
 
2200
    self = (Degrade *)type->tp_alloc(type, 0);
 
2201
    
 
2202
    self->bitdepth = PyFloat_FromDouble(16);
 
2203
    self->srscale = PyFloat_FromDouble(1.0);
 
2204
    self->value = 0.0;
 
2205
    self->sampsCount = 0;
 
2206
        self->modebuffer[0] = 0;
 
2207
        self->modebuffer[1] = 0;
 
2208
        self->modebuffer[2] = 0;
 
2209
        self->modebuffer[3] = 0;
 
2210
    
 
2211
    INIT_OBJECT_COMMON
 
2212
    Stream_setFunctionPtr(self->stream, Degrade_compute_next_data_frame);
 
2213
    self->mode_func_ptr = Degrade_setProcMode;
 
2214
    
 
2215
    return (PyObject *)self;
 
2216
}
 
2217
 
 
2218
static int
 
2219
Degrade_init(Degrade *self, PyObject *args, PyObject *kwds)
 
2220
{
 
2221
    PyObject *inputtmp, *input_streamtmp, *bitdepthtmp=NULL, *srscaletmp=NULL, *multmp=NULL, *addtmp=NULL;
 
2222
    
 
2223
    static char *kwlist[] = {"input", "bitdepth", "srscale", "mul", "add", NULL};
 
2224
    
 
2225
    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &bitdepthtmp, &srscaletmp, &multmp, &addtmp))
 
2226
        return -1; 
 
2227
    
 
2228
    INIT_INPUT_STREAM
 
2229
    
 
2230
    if (bitdepthtmp) {
 
2231
        PyObject_CallMethod((PyObject *)self, "setBitdepth", "O", bitdepthtmp);
 
2232
    }
 
2233
    
 
2234
    if (srscaletmp) {
 
2235
        PyObject_CallMethod((PyObject *)self, "setSrscale", "O", srscaletmp);
 
2236
    }
 
2237
    
 
2238
    if (multmp) {
 
2239
        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
 
2240
    }
 
2241
    
 
2242
    if (addtmp) {
 
2243
        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
 
2244
    }
 
2245
    
 
2246
    Py_INCREF(self->stream);
 
2247
    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
2248
    
 
2249
    (*self->mode_func_ptr)(self);
 
2250
        
 
2251
    Py_INCREF(self);
 
2252
    return 0;
 
2253
}
 
2254
 
 
2255
static PyObject * Degrade_getServer(Degrade* self) { GET_SERVER };
 
2256
static PyObject * Degrade_getStream(Degrade* self) { GET_STREAM };
 
2257
static PyObject * Degrade_setMul(Degrade *self, PyObject *arg) { SET_MUL };     
 
2258
static PyObject * Degrade_setAdd(Degrade *self, PyObject *arg) { SET_ADD };     
 
2259
static PyObject * Degrade_setSub(Degrade *self, PyObject *arg) { SET_SUB };     
 
2260
static PyObject * Degrade_setDiv(Degrade *self, PyObject *arg) { SET_DIV };     
 
2261
 
 
2262
static PyObject * Degrade_play(Degrade *self, PyObject *args, PyObject *kwds) { PLAY };
 
2263
static PyObject * Degrade_out(Degrade *self, PyObject *args, PyObject *kwds) { OUT };
 
2264
static PyObject * Degrade_stop(Degrade *self) { STOP };
 
2265
 
 
2266
static PyObject * Degrade_multiply(Degrade *self, PyObject *arg) { MULTIPLY };
 
2267
static PyObject * Degrade_inplace_multiply(Degrade *self, PyObject *arg) { INPLACE_MULTIPLY };
 
2268
static PyObject * Degrade_add(Degrade *self, PyObject *arg) { ADD };
 
2269
static PyObject * Degrade_inplace_add(Degrade *self, PyObject *arg) { INPLACE_ADD };
 
2270
static PyObject * Degrade_sub(Degrade *self, PyObject *arg) { SUB };
 
2271
static PyObject * Degrade_inplace_sub(Degrade *self, PyObject *arg) { INPLACE_SUB };
 
2272
static PyObject * Degrade_div(Degrade *self, PyObject *arg) { DIV };
 
2273
static PyObject * Degrade_inplace_div(Degrade *self, PyObject *arg) { INPLACE_DIV };
 
2274
 
 
2275
static PyObject *
 
2276
Degrade_setBitdepth(Degrade *self, PyObject *arg)
 
2277
{
 
2278
        PyObject *tmp, *streamtmp;
 
2279
        
 
2280
        if (arg == NULL) {
 
2281
                Py_INCREF(Py_None);
 
2282
                return Py_None;
 
2283
        }
 
2284
    
 
2285
        int isNumber = PyNumber_Check(arg);
 
2286
        
 
2287
        tmp = arg;
 
2288
        Py_INCREF(tmp);
 
2289
        Py_DECREF(self->bitdepth);
 
2290
        if (isNumber == 1) {
 
2291
                self->bitdepth = PyNumber_Float(tmp);
 
2292
        self->modebuffer[2] = 0;
 
2293
        }
 
2294
        else {
 
2295
                self->bitdepth = tmp;
 
2296
        streamtmp = PyObject_CallMethod((PyObject *)self->bitdepth, "_getStream", NULL);
 
2297
        Py_INCREF(streamtmp);
 
2298
        Py_XDECREF(self->bitdepth_stream);
 
2299
        self->bitdepth_stream = (Stream *)streamtmp;
 
2300
                self->modebuffer[2] = 1;
 
2301
        }
 
2302
    
 
2303
    (*self->mode_func_ptr)(self);
 
2304
    
 
2305
        Py_INCREF(Py_None);
 
2306
        return Py_None;
 
2307
}       
 
2308
 
 
2309
static PyObject *
 
2310
Degrade_setSrscale(Degrade *self, PyObject *arg)
 
2311
{
 
2312
        PyObject *tmp, *streamtmp;
 
2313
        
 
2314
        if (arg == NULL) {
 
2315
                Py_INCREF(Py_None);
 
2316
                return Py_None;
 
2317
        }
 
2318
    
 
2319
        int isNumber = PyNumber_Check(arg);
 
2320
        
 
2321
        tmp = arg;
 
2322
        Py_INCREF(tmp);
 
2323
        Py_DECREF(self->srscale);
 
2324
        if (isNumber == 1) {
 
2325
                self->srscale = PyNumber_Float(tmp);
 
2326
        self->modebuffer[3] = 0;
 
2327
        }
 
2328
        else {
 
2329
                self->srscale = tmp;
 
2330
        streamtmp = PyObject_CallMethod((PyObject *)self->srscale, "_getStream", NULL);
 
2331
        Py_INCREF(streamtmp);
 
2332
        Py_XDECREF(self->srscale_stream);
 
2333
        self->srscale_stream = (Stream *)streamtmp;
 
2334
                self->modebuffer[3] = 1;
 
2335
        }
 
2336
    
 
2337
    (*self->mode_func_ptr)(self);
 
2338
    
 
2339
        Py_INCREF(Py_None);
 
2340
        return Py_None;
 
2341
}       
 
2342
 
 
2343
static PyMemberDef Degrade_members[] = {
 
2344
{"server", T_OBJECT_EX, offsetof(Degrade, server), 0, "Pyo server."},
 
2345
{"stream", T_OBJECT_EX, offsetof(Degrade, stream), 0, "Stream object."},
 
2346
{"input", T_OBJECT_EX, offsetof(Degrade, input), 0, "Input sound object."},
 
2347
{"bitdepth", T_OBJECT_EX, offsetof(Degrade, bitdepth), 0, "Number of bits for amplitude values."},
 
2348
{"srscale", T_OBJECT_EX, offsetof(Degrade, srscale), 0, "Sampling depth factor."},
 
2349
{"mul", T_OBJECT_EX, offsetof(Degrade, mul), 0, "Mul factor."},
 
2350
{"add", T_OBJECT_EX, offsetof(Degrade, add), 0, "Add factor."},
 
2351
{NULL}  /* Sentinel */
 
2352
};
 
2353
 
 
2354
static PyMethodDef Degrade_methods[] = {
 
2355
{"getServer", (PyCFunction)Degrade_getServer, METH_NOARGS, "Returns server object."},
 
2356
{"_getStream", (PyCFunction)Degrade_getStream, METH_NOARGS, "Returns stream object."},
 
2357
{"deleteStream", (PyCFunction)Degrade_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
 
2358
{"play", (PyCFunction)Degrade_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 
2359
{"out", (PyCFunction)Degrade_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 
2360
{"stop", (PyCFunction)Degrade_stop, METH_NOARGS, "Stops computing."},
 
2361
{"setBitdepth", (PyCFunction)Degrade_setBitdepth, METH_O, "Sets the bitdepth value."},
 
2362
{"setSrscale", (PyCFunction)Degrade_setSrscale, METH_O, "Sets the srscale value."},
 
2363
{"setMul", (PyCFunction)Degrade_setMul, METH_O, "Sets oscillator mul factor."},
 
2364
{"setAdd", (PyCFunction)Degrade_setAdd, METH_O, "Sets oscillator add factor."},
 
2365
{"setSub", (PyCFunction)Degrade_setSub, METH_O, "Sets inverse add factor."},
 
2366
{"setDiv", (PyCFunction)Degrade_setDiv, METH_O, "Sets inverse mul factor."},
 
2367
{NULL}  /* Sentinel */
 
2368
};
 
2369
 
 
2370
static PyNumberMethods Degrade_as_number = {
 
2371
(binaryfunc)Degrade_add,                      /*nb_add*/
 
2372
(binaryfunc)Degrade_sub,                 /*nb_subtract*/
 
2373
(binaryfunc)Degrade_multiply,                 /*nb_multiply*/
 
2374
(binaryfunc)Degrade_div,                   /*nb_divide*/
 
2375
0,                /*nb_remainder*/
 
2376
0,                   /*nb_divmod*/
 
2377
0,                   /*nb_power*/
 
2378
0,                  /*nb_neg*/
 
2379
0,                /*nb_pos*/
 
2380
0,                  /*(unaryfunc)array_abs,*/
 
2381
0,                    /*nb_nonzero*/
 
2382
0,                    /*nb_invert*/
 
2383
0,               /*nb_lshift*/
 
2384
0,              /*nb_rshift*/
 
2385
0,              /*nb_and*/
 
2386
0,              /*nb_xor*/
 
2387
0,               /*nb_or*/
 
2388
0,                                          /*nb_coerce*/
 
2389
0,                       /*nb_int*/
 
2390
0,                      /*nb_long*/
 
2391
0,                     /*nb_float*/
 
2392
0,                       /*nb_oct*/
 
2393
0,                       /*nb_hex*/
 
2394
(binaryfunc)Degrade_inplace_add,              /*inplace_add*/
 
2395
(binaryfunc)Degrade_inplace_sub,         /*inplace_subtract*/
 
2396
(binaryfunc)Degrade_inplace_multiply,         /*inplace_multiply*/
 
2397
(binaryfunc)Degrade_inplace_div,           /*inplace_divide*/
 
2398
0,        /*inplace_remainder*/
 
2399
0,           /*inplace_power*/
 
2400
0,       /*inplace_lshift*/
 
2401
0,      /*inplace_rshift*/
 
2402
0,      /*inplace_and*/
 
2403
0,      /*inplace_xor*/
 
2404
0,       /*inplace_or*/
 
2405
0,             /*nb_floor_divide*/
 
2406
0,              /*nb_true_divide*/
 
2407
0,     /*nb_inplace_floor_divide*/
 
2408
0,      /*nb_inplace_true_divide*/
 
2409
0,                     /* nb_index */
 
2410
};
 
2411
 
 
2412
PyTypeObject DegradeType = {
 
2413
PyObject_HEAD_INIT(NULL)
 
2414
0,                         /*ob_size*/
 
2415
"_pyo.Degrade_base",         /*tp_name*/
 
2416
sizeof(Degrade),         /*tp_basicsize*/
 
2417
0,                         /*tp_itemsize*/
 
2418
(destructor)Degrade_dealloc, /*tp_dealloc*/
 
2419
0,                         /*tp_print*/
 
2420
0,                         /*tp_getattr*/
 
2421
0,                         /*tp_setattr*/
 
2422
0,                         /*tp_compare*/
 
2423
0,                         /*tp_repr*/
 
2424
&Degrade_as_number,             /*tp_as_number*/
 
2425
0,                         /*tp_as_sequence*/
 
2426
0,                         /*tp_as_mapping*/
 
2427
0,                         /*tp_hash */
 
2428
0,                         /*tp_call*/
 
2429
0,                         /*tp_str*/
 
2430
0,                         /*tp_getattro*/
 
2431
0,                         /*tp_setattro*/
 
2432
0,                         /*tp_as_buffer*/
 
2433
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
 
2434
"Degrade objects. Applies different bitdepth and sr on a signal.",           /* tp_doc */
 
2435
(traverseproc)Degrade_traverse,   /* tp_traverse */
 
2436
(inquiry)Degrade_clear,           /* tp_clear */
 
2437
0,                             /* tp_richcompare */
 
2438
0,                             /* tp_weaklistoffset */
 
2439
0,                             /* tp_iter */
 
2440
0,                             /* tp_iternext */
 
2441
Degrade_methods,             /* tp_methods */
 
2442
Degrade_members,             /* tp_members */
 
2443
0,                      /* tp_getset */
 
2444
0,                         /* tp_base */
 
2445
0,                         /* tp_dict */
 
2446
0,                         /* tp_descr_get */
 
2447
0,                         /* tp_descr_set */
 
2448
0,                         /* tp_dictoffset */
 
2449
(initproc)Degrade_init,      /* tp_init */
 
2450
0,                         /* tp_alloc */
 
2451
Degrade_new,                 /* tp_new */
 
2452
};
 
2453