2305
2304
Looper_new, /* tp_new */
2307
static const MYFLT Granule_MAX_GRAINS = 1024;
2313
Stream *dens_stream;
2315
Stream *pitch_stream;
2332
Granule_transform_i(Granule *self) {
2333
MYFLT dens, inc, index, amp, phase;
2336
MYFLT pit = 0, pos = 0, dur = 0;
2338
MYFLT *tablelist = TableStream_getData(self->table);
2339
int size = TableStream_getSize(self->table);
2341
MYFLT *envlist = TableStream_getData(self->env);
2342
int envsize = TableStream_getSize(self->env);
2344
dens = PyFloat_AS_DOUBLE(self->dens);
2348
inc = dens * self->oneOnSr;
2350
for (i=0; i<self->bufsize; i++) {
2351
self->data[i] = 0.0;
2355
if (self->timer >= 1.0) {
2360
/* need to start a new grain */
2362
for (j=0; j<Granule_MAX_GRAINS; j++) {
2363
if (self->flags[j] == 0) {
2367
if (self->modebuffer[3] == 0)
2368
pit = PyFloat_AS_DOUBLE(self->pitch);
2370
pit = Stream_getData((Stream *)self->pitch_stream)[i];
2371
if (self->modebuffer[4] == 0)
2372
pos = PyFloat_AS_DOUBLE(self->pos);
2374
pos = Stream_getData((Stream *)self->pos_stream)[i];
2375
if (self->modebuffer[5] == 0)
2376
dur = PyFloat_AS_DOUBLE(self->dur);
2378
dur = Stream_getData((Stream *)self->dur_stream)[i];
2381
else if (pos >= size)
2383
self->gpos[j] = pos;
2384
self->glen[j] = dur * self->sr * pit;
2385
if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
2387
self->phase[j] = 0.0;
2388
self->inc[j] = 1.0 / (dur * self->sr);
2394
/* compute active grains */
2395
for (j=0; j<self->num; j++) {
2396
if (self->flags[j]) {
2397
phase = self->phase[j];
2398
if (phase >= 0.0 && phase < 1.0) {
2400
index = phase * envsize;
2402
amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart);
2405
index = phase * self->glen[j] + self->gpos[j];
2407
self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp;
2409
phase += self->inc[j];
2413
self->phase[j] = phase;
2422
Granule_transform_a(Granule *self) {
2423
MYFLT index, amp, phase;
2426
MYFLT pit = 0, pos = 0, dur = 0;
2428
MYFLT *tablelist = TableStream_getData(self->table);
2429
int size = TableStream_getSize(self->table);
2431
MYFLT *envlist = TableStream_getData(self->env);
2432
int envsize = TableStream_getSize(self->env);
2434
MYFLT *density = Stream_getData((Stream *)self->dens_stream);
2436
for (i=0; i<self->bufsize; i++) {
2437
self->data[i] = 0.0;
2440
self->timer += density[i] * self->oneOnSr;
2441
if (self->timer >= 1.0) {
2446
/* need to start a new grain */
2448
for (j=0; j<Granule_MAX_GRAINS; j++) {
2449
if (self->flags[j] == 0) {
2453
if (self->modebuffer[3] == 0)
2454
pit = PyFloat_AS_DOUBLE(self->pitch);
2456
pit = Stream_getData((Stream *)self->pitch_stream)[i];
2457
if (self->modebuffer[4] == 0)
2458
pos = PyFloat_AS_DOUBLE(self->pos);
2460
pos = Stream_getData((Stream *)self->pos_stream)[i];
2461
if (self->modebuffer[5] == 0)
2462
dur = PyFloat_AS_DOUBLE(self->dur);
2464
dur = Stream_getData((Stream *)self->dur_stream)[i];
2467
else if (pos >= size)
2469
self->gpos[j] = pos;
2470
self->glen[j] = dur * self->sr * pit;
2471
if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
2473
self->phase[j] = 0.0;
2474
self->inc[j] = 1.0 / (dur * self->sr);
2480
/* compute active grains */
2481
for (j=0; j<self->num; j++) {
2482
if (self->flags[j]) {
2483
phase = self->phase[j];
2484
if (phase >= 0.0 && phase < 1.0) {
2486
index = phase * envsize;
2488
amp = envlist[ipart] + (envlist[ipart+1] - envlist[ipart]) * (index - ipart);
2491
index = phase * self->glen[j] + self->gpos[j];
2493
self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp;
2495
phase += self->inc[j];
2499
self->phase[j] = phase;
2507
static void Granule_postprocessing_ii(Granule *self) { POST_PROCESSING_II };
2508
static void Granule_postprocessing_ai(Granule *self) { POST_PROCESSING_AI };
2509
static void Granule_postprocessing_ia(Granule *self) { POST_PROCESSING_IA };
2510
static void Granule_postprocessing_aa(Granule *self) { POST_PROCESSING_AA };
2511
static void Granule_postprocessing_ireva(Granule *self) { POST_PROCESSING_IREVA };
2512
static void Granule_postprocessing_areva(Granule *self) { POST_PROCESSING_AREVA };
2513
static void Granule_postprocessing_revai(Granule *self) { POST_PROCESSING_REVAI };
2514
static void Granule_postprocessing_revaa(Granule *self) { POST_PROCESSING_REVAA };
2515
static void Granule_postprocessing_revareva(Granule *self) { POST_PROCESSING_REVAREVA };
2518
Granule_setProcMode(Granule *self)
2520
int procmode, muladdmode;
2521
procmode = self->modebuffer[2];
2522
muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
2526
self->proc_func_ptr = Granule_transform_i;
2529
self->proc_func_ptr = Granule_transform_a;
2532
switch (muladdmode) {
2534
self->muladd_func_ptr = Granule_postprocessing_ii;
2537
self->muladd_func_ptr = Granule_postprocessing_ai;
2540
self->muladd_func_ptr = Granule_postprocessing_revai;
2543
self->muladd_func_ptr = Granule_postprocessing_ia;
2546
self->muladd_func_ptr = Granule_postprocessing_aa;
2549
self->muladd_func_ptr = Granule_postprocessing_revaa;
2552
self->muladd_func_ptr = Granule_postprocessing_ireva;
2555
self->muladd_func_ptr = Granule_postprocessing_areva;
2558
self->muladd_func_ptr = Granule_postprocessing_revareva;
2564
Granule_compute_next_data_frame(Granule *self)
2566
(*self->proc_func_ptr)(self);
2567
(*self->muladd_func_ptr)(self);
2571
Granule_traverse(Granule *self, visitproc visit, void *arg)
2574
Py_VISIT(self->table);
2575
Py_VISIT(self->env);
2576
Py_VISIT(self->dens);
2577
Py_VISIT(self->dens_stream);
2578
Py_VISIT(self->pitch);
2579
Py_VISIT(self->pitch_stream);
2580
Py_VISIT(self->pos);
2581
Py_VISIT(self->pos_stream);
2582
Py_VISIT(self->dur);
2583
Py_VISIT(self->dur_stream);
2588
Granule_clear(Granule *self)
2591
Py_CLEAR(self->table);
2592
Py_CLEAR(self->env);
2593
Py_CLEAR(self->dens);
2594
Py_CLEAR(self->dens_stream);
2595
Py_CLEAR(self->pitch);
2596
Py_CLEAR(self->pitch_stream);
2597
Py_CLEAR(self->pos);
2598
Py_CLEAR(self->pos_stream);
2599
Py_CLEAR(self->dur);
2600
Py_CLEAR(self->dur_stream);
2605
Granule_dealloc(Granule* self)
2613
Granule_clear(self);
2614
self->ob_type->tp_free((PyObject*)self);
2618
Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2621
PyObject *tabletmp, *envtmp, *denstmp=NULL, *pitchtmp=NULL, *postmp=NULL, *durtmp=NULL, *multmp=NULL, *addtmp=NULL;
2623
self = (Granule *)type->tp_alloc(type, 0);
2625
self->dens = PyFloat_FromDouble(50);
2626
self->pitch = PyFloat_FromDouble(1);
2627
self->pos = PyFloat_FromDouble(0.0);
2628
self->dur = PyFloat_FromDouble(0.1);
2631
self->modebuffer[0] = 0;
2632
self->modebuffer[1] = 0;
2633
self->modebuffer[2] = 0;
2634
self->modebuffer[3] = 0;
2635
self->modebuffer[4] = 0;
2636
self->modebuffer[5] = 0;
2640
self->oneOnSr = 1.0 / self->sr;
2642
Stream_setFunctionPtr(self->stream, Granule_compute_next_data_frame);
2643
self->mode_func_ptr = Granule_setProcMode;
2645
static char *kwlist[] = {"table", "env", "dens", "pitch", "pos", "dur", "mul", "add", NULL};
2647
if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOOO", kwlist, &tabletmp, &envtmp, &denstmp, &pitchtmp, &postmp, &durtmp, &multmp, &addtmp))
2650
if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
2651
PySys_WriteStderr("TypeError: \"table\" argument of Granule must be a PyoTableObject.\n");
2652
if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
2653
PyObject_CallMethod(self->server, "shutdown", NULL);
2657
Py_XDECREF(self->table);
2658
self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
2660
if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) {
2661
PySys_WriteStderr("TypeError: \"env\" argument of Granule must be a PyoTableObject.\n");
2662
if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
2663
PyObject_CallMethod(self->server, "shutdown", NULL);
2667
Py_XDECREF(self->env);
2668
self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", "");
2671
PyObject_CallMethod((PyObject *)self, "setDens", "O", denstmp);
2675
PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
2679
PyObject_CallMethod((PyObject *)self, "setPos", "O", postmp);
2683
PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp);
2687
PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
2691
PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
2694
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
2696
self->gpos = (MYFLT *)realloc(self->gpos, Granule_MAX_GRAINS * sizeof(MYFLT));
2697
self->glen = (MYFLT *)realloc(self->glen, Granule_MAX_GRAINS * sizeof(MYFLT));
2698
self->inc = (MYFLT *)realloc(self->inc, Granule_MAX_GRAINS * sizeof(MYFLT));
2699
self->phase = (MYFLT *)realloc(self->phase, Granule_MAX_GRAINS * sizeof(MYFLT));
2700
self->flags = (int *)realloc(self->flags, Granule_MAX_GRAINS * sizeof(int));
2702
for (i=0; i<Granule_MAX_GRAINS; i++) {
2703
self->gpos[i] = self->glen[i] = self->inc[i] = self->phase[i] = 0.0;
2707
(*self->mode_func_ptr)(self);
2709
return (PyObject *)self;
2712
static PyObject * Granule_getServer(Granule* self) { GET_SERVER };
2713
static PyObject * Granule_getStream(Granule* self) { GET_STREAM };
2714
static PyObject * Granule_setMul(Granule *self, PyObject *arg) { SET_MUL };
2715
static PyObject * Granule_setAdd(Granule *self, PyObject *arg) { SET_ADD };
2716
static PyObject * Granule_setSub(Granule *self, PyObject *arg) { SET_SUB };
2717
static PyObject * Granule_setDiv(Granule *self, PyObject *arg) { SET_DIV };
2719
static PyObject * Granule_play(Granule *self, PyObject *args, PyObject *kwds) { PLAY };
2720
static PyObject * Granule_out(Granule *self, PyObject *args, PyObject *kwds) { OUT };
2721
static PyObject * Granule_stop(Granule *self) { STOP };
2723
static PyObject * Granule_multiply(Granule *self, PyObject *arg) { MULTIPLY };
2724
static PyObject * Granule_inplace_multiply(Granule *self, PyObject *arg) { INPLACE_MULTIPLY };
2725
static PyObject * Granule_add(Granule *self, PyObject *arg) { ADD };
2726
static PyObject * Granule_inplace_add(Granule *self, PyObject *arg) { INPLACE_ADD };
2727
static PyObject * Granule_sub(Granule *self, PyObject *arg) { SUB };
2728
static PyObject * Granule_inplace_sub(Granule *self, PyObject *arg) { INPLACE_SUB };
2729
static PyObject * Granule_div(Granule *self, PyObject *arg) { DIV };
2730
static PyObject * Granule_inplace_div(Granule *self, PyObject *arg) { INPLACE_DIV };
2733
Granule_setDens(Granule *self, PyObject *arg)
2735
PyObject *tmp, *streamtmp;
2742
int isNumber = PyNumber_Check(arg);
2746
Py_DECREF(self->dens);
2747
if (isNumber == 1) {
2748
self->dens = PyNumber_Float(tmp);
2749
self->modebuffer[2] = 0;
2753
streamtmp = PyObject_CallMethod((PyObject *)self->dens, "_getStream", NULL);
2754
Py_INCREF(streamtmp);
2755
Py_XDECREF(self->dens_stream);
2756
self->dens_stream = (Stream *)streamtmp;
2757
self->modebuffer[2] = 1;
2760
(*self->mode_func_ptr)(self);
2767
Granule_setPitch(Granule *self, PyObject *arg)
2769
PyObject *tmp, *streamtmp;
2776
int isNumber = PyNumber_Check(arg);
2780
Py_DECREF(self->pitch);
2781
if (isNumber == 1) {
2782
self->pitch = PyNumber_Float(tmp);
2783
self->modebuffer[3] = 0;
2787
streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL);
2788
Py_INCREF(streamtmp);
2789
Py_XDECREF(self->pitch_stream);
2790
self->pitch_stream = (Stream *)streamtmp;
2791
self->modebuffer[3] = 1;
2799
Granule_setPos(Granule *self, PyObject *arg)
2801
PyObject *tmp, *streamtmp;
2808
int isNumber = PyNumber_Check(arg);
2812
Py_DECREF(self->pos);
2813
if (isNumber == 1) {
2814
self->pos = PyNumber_Float(tmp);
2815
self->modebuffer[4] = 0;
2819
streamtmp = PyObject_CallMethod((PyObject *)self->pos, "_getStream", NULL);
2820
Py_INCREF(streamtmp);
2821
Py_XDECREF(self->pos_stream);
2822
self->pos_stream = (Stream *)streamtmp;
2823
self->modebuffer[4] = 1;
2831
Granule_setDur(Granule *self, PyObject *arg)
2833
PyObject *tmp, *streamtmp;
2840
int isNumber = PyNumber_Check(arg);
2844
Py_DECREF(self->dur);
2845
if (isNumber == 1) {
2846
self->dur = PyNumber_Float(tmp);
2847
self->modebuffer[5] = 0;
2851
streamtmp = PyObject_CallMethod((PyObject *)self->dur, "_getStream", NULL);
2852
Py_INCREF(streamtmp);
2853
Py_XDECREF(self->dur_stream);
2854
self->dur_stream = (Stream *)streamtmp;
2855
self->modebuffer[5] = 1;
2863
Granule_getTable(Granule* self)
2865
Py_INCREF(self->table);
2870
Granule_setTable(Granule *self, PyObject *arg)
2880
Py_DECREF(self->table);
2881
self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
2888
Granule_getEnv(Granule* self)
2890
Py_INCREF(self->env);
2895
Granule_setEnv(Granule *self, PyObject *arg)
2905
Py_DECREF(self->env);
2906
self->env = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
2912
static PyMemberDef Granule_members[] = {
2913
{"server", T_OBJECT_EX, offsetof(Granule, server), 0, "Pyo server."},
2914
{"stream", T_OBJECT_EX, offsetof(Granule, stream), 0, "Stream object."},
2915
{"table", T_OBJECT_EX, offsetof(Granule, table), 0, "Sound table."},
2916
{"env", T_OBJECT_EX, offsetof(Granule, env), 0, "Envelope table."},
2917
{"dens", T_OBJECT_EX, offsetof(Granule, dens), 0, "Density of grains per second."},
2918
{"pitch", T_OBJECT_EX, offsetof(Granule, pitch), 0, "Speed of the reading pointer."},
2919
{"pos", T_OBJECT_EX, offsetof(Granule, pos), 0, "Position in the sound table."},
2920
{"dur", T_OBJECT_EX, offsetof(Granule, dur), 0, "Duration of each grains."},
2921
{"mul", T_OBJECT_EX, offsetof(Granule, mul), 0, "Mul factor."},
2922
{"add", T_OBJECT_EX, offsetof(Granule, add), 0, "Add factor."},
2923
{NULL} /* Sentinel */
2926
static PyMethodDef Granule_methods[] = {
2927
{"getTable", (PyCFunction)Granule_getTable, METH_NOARGS, "Returns sound table object."},
2928
{"setTable", (PyCFunction)Granule_setTable, METH_O, "Sets sound table."},
2929
{"getEnv", (PyCFunction)Granule_getEnv, METH_NOARGS, "Returns envelope table object."},
2930
{"setEnv", (PyCFunction)Granule_setEnv, METH_O, "Sets envelope table."},
2931
{"getServer", (PyCFunction)Granule_getServer, METH_NOARGS, "Returns server object."},
2932
{"_getStream", (PyCFunction)Granule_getStream, METH_NOARGS, "Returns stream object."},
2933
{"play", (PyCFunction)Granule_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
2934
{"out", (PyCFunction)Granule_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
2935
{"stop", (PyCFunction)Granule_stop, METH_NOARGS, "Stops computing."},
2936
{"setDens", (PyCFunction)Granule_setDens, METH_O, "Sets the density of grains per second."},
2937
{"setPitch", (PyCFunction)Granule_setPitch, METH_O, "Sets global pitch factor."},
2938
{"setPos", (PyCFunction)Granule_setPos, METH_O, "Sets position in the sound table."},
2939
{"setDur", (PyCFunction)Granule_setDur, METH_O, "Sets the grain duration."},
2940
{"setMul", (PyCFunction)Granule_setMul, METH_O, "Sets Granule mul factor."},
2941
{"setAdd", (PyCFunction)Granule_setAdd, METH_O, "Sets Granule add factor."},
2942
{"setSub", (PyCFunction)Granule_setSub, METH_O, "Sets inverse add factor."},
2943
{"setDiv", (PyCFunction)Granule_setDiv, METH_O, "Sets inverse mul factor."},
2944
{NULL} /* Sentinel */
2947
static PyNumberMethods Granule_as_number = {
2948
(binaryfunc)Granule_add, /*nb_add*/
2949
(binaryfunc)Granule_sub, /*nb_subtract*/
2950
(binaryfunc)Granule_multiply, /*nb_multiply*/
2951
(binaryfunc)Granule_div, /*nb_divide*/
2957
0, /*(unaryfunc)array_abs,*/
2971
(binaryfunc)Granule_inplace_add, /*inplace_add*/
2972
(binaryfunc)Granule_inplace_sub, /*inplace_subtract*/
2973
(binaryfunc)Granule_inplace_multiply, /*inplace_multiply*/
2974
(binaryfunc)Granule_inplace_div, /*inplace_divide*/
2975
0, /*inplace_remainder*/
2976
0, /*inplace_power*/
2977
0, /*inplace_lshift*/
2978
0, /*inplace_rshift*/
2982
0, /*nb_floor_divide*/
2983
0, /*nb_true_divide*/
2984
0, /*nb_inplace_floor_divide*/
2985
0, /*nb_inplace_true_divide*/
2989
PyTypeObject GranuleType = {
2990
PyObject_HEAD_INIT(NULL)
2992
"_pyo.Granule_base", /*tp_name*/
2993
sizeof(Granule), /*tp_basicpitch*/
2995
(destructor)Granule_dealloc, /*tp_dealloc*/
3001
&Granule_as_number, /*tp_as_number*/
3002
0, /*tp_as_sequence*/
3003
0, /*tp_as_mapping*/
3010
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
3011
"Granule objects. Accumulation of multiples grains of sound.", /* tp_doc */
3012
(traverseproc)Granule_traverse, /* tp_traverse */
3013
(inquiry)Granule_clear, /* tp_clear */
3014
0, /* tp_richcompare */
3015
0, /* tp_weaklistoffset */
3017
0, /* tp_iternext */
3018
Granule_methods, /* tp_methods */
3019
Granule_members, /* tp_members */
3023
0, /* tp_descr_get */
3024
0, /* tp_descr_set */
3025
0, /* tp_dictoffset */
3028
Granule_new, /* tp_new */