bumping version to 3.5-rc1
[supercollider.git] / lang / LangPrimSource / PyrSignalPrim.cpp
blob6edfeed7a2d1af3663d0c6e98b72eb1fa642079a
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "PyrSymbol.h"
22 #include "PyrKernel.h"
23 #include "PyrObject.h"
24 #include "PyrPrimitive.h"
25 #include "PyrSignal.h"
26 #include "PyrSignalPrim.h"
27 #include "PyrMessage.h"
28 #include "SC_Constants.h"
29 #include "SCBase.h"
30 #include "clz.h"
31 extern "C" {
32 #include "fftlib.h"
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
39 int prSignalFill(struct VMGlobals *g, int numArgsPushed)
41 PyrSlot *a, *b;
42 int err;
43 float value;
45 a = g->sp - 1;
46 b = g->sp;
48 err = slotFloatVal(b, &value);
49 if (err != errNone) return err;
50 signal_fill(slotRawObject(a), value);
51 return errNone;
54 int prSignalScale(struct VMGlobals *g, int numArgsPushed)
56 PyrSlot *a, *b;
57 int err;
58 float value;
60 a = g->sp - 1;
61 b = g->sp;
63 err = slotFloatVal(b, &value);
64 if (err != errNone) return err;
65 signal_scale(slotRawObject(a), value);
66 return errNone;
69 int prSignalOffset(struct VMGlobals *g, int numArgsPushed)
71 PyrSlot *a, *b;
72 int err;
73 float value;
75 a = g->sp - 1;
76 b = g->sp;
78 err = slotFloatVal(b, &value);
79 if (err != errNone) return err;
80 signal_offset(slotRawObject(a), value);
81 return errNone;
84 int prSignalString(struct VMGlobals *g, int numArgsPushed)
86 PyrSlot *a;
87 PyrString *string;
88 PyrObject *signal;
89 float *x;
90 char str[128];
92 a = g->sp;
93 slotString(a, str);
95 signal = slotRawObject(a);
96 if (signal->size) {
97 x = (float*)(signal->slots);
98 sprintf(str, "%s[%g .. %g]", slotRawSymbol(&signal->classptr->name)->name,
99 x[0], x[signal->size-1]);
100 } else {
101 sprintf(str, "%s[none]", slotRawSymbol(&signal->classptr->name)->name);
103 string = newPyrString(g->gc, str, 0, true);
104 SetObject(a, string);
105 return errNone;
108 int prSignalPeak(struct VMGlobals *g, int numArgsPushed)
110 PyrSlot *a;
112 a = g->sp;
114 SetFloat(a, signal_findpeak(slotRawObject(a)));
115 return errNone;
118 int prSignalNormalize(struct VMGlobals *g, int numArgsPushed)
120 PyrSlot *a, *b, *c;
121 int err, start, end;
123 a = g->sp - 2;
124 b = g->sp - 1;
125 c = g->sp;
127 err = slotIntVal(b, &start);
128 if (err) {
129 if (IsNil(c)) start = 0;
130 else return err;
133 err = slotIntVal(c, &end);
134 if (err) {
135 if (IsNil(c)) end = slotRawObject(a)->size;
136 else return err;
139 signal_normalize_range(slotRawObject(a), start, end);
140 return errNone;
143 int prSignalNormalizeTransferFn(struct VMGlobals *g, int numArgsPushed)
145 PyrSlot *a;
147 a = g->sp;
149 signal_normalize_transfer_fn(slotRawObject(a));
150 return errNone;
153 int prSignalIntegral(struct VMGlobals *g, int numArgsPushed)
155 PyrSlot *a;
157 a = g->sp;
159 SetFloat(a, signal_integral(slotRawObject(a)));
160 return errNone;
163 int prSignalInvert(struct VMGlobals *g, int numArgsPushed)
165 PyrSlot *a, *b, *c;
166 int err, start, end;
168 a = g->sp - 2;
169 b = g->sp - 1;
170 c = g->sp;
172 err = slotIntVal(b, &start);
173 if (err) {
174 if (IsNil(c)) start = 0;
175 else return err;
178 err = slotIntVal(c, &end);
179 if (err) {
180 if (IsNil(c)) end = slotRawObject(a)->size;
181 else return err;
184 signal_invert_range(slotRawObject(a), start, end);
185 return errNone;
188 int prSignalReverse(struct VMGlobals *g, int numArgsPushed)
190 PyrSlot *a, *b, *c;
191 int err, start, end;
193 a = g->sp - 2;
194 b = g->sp - 1;
195 c = g->sp;
197 err = slotIntVal(b, &start);
198 if (err) {
199 if (IsNil(b)) start = 0;
200 else return err;
203 err = slotIntVal(c, &end);
204 if (err) {
205 if (IsNil(c)) end = slotRawObject(a)->size;
206 else return err;
209 signal_reverse_range(slotRawObject(a), start, end);
210 return errNone;
213 int prSignalRotate(struct VMGlobals *g, int numArgsPushed)
215 PyrSlot *a, *b;
216 int err, rot;
218 a = g->sp - 1;
219 b = g->sp;
221 err = slotIntVal(b, &rot);
222 if (err) return err;
224 SetRaw(a, signal_rotate(g, slotRawObject(a), rot));
225 return errNone;
228 int prSignalOverDub(struct VMGlobals *g, int numArgsPushed)
230 PyrSlot *a, *b, *c;
231 int err;
232 int index;
234 a = g->sp - 2;
235 b = g->sp - 1;
236 c = g->sp;
238 if (NotObj(b) || !isKindOf(slotRawObject(b), class_signal)) return errWrongType;
239 err = slotIntVal(c, &index);
240 if (err) return errWrongType;
242 signal_overdub(g, slotRawObject(a), slotRawObject(b), index);
243 return errNone;
246 int prSignalOverWrite(struct VMGlobals *g, int numArgsPushed)
248 PyrSlot *a, *b, *c;
249 int err;
250 int index;
252 a = g->sp - 2;
253 b = g->sp - 1;
254 c = g->sp;
256 if (NotObj(b) || !isKindOf(slotRawObject(b), class_signal)) return errWrongType;
257 err = slotIntVal(c, &index);
258 if (err) return errWrongType;
260 signal_overwrite(g, slotRawObject(a), slotRawObject(b), index);
261 return errNone;
264 int prSignalFade(struct VMGlobals *g, int numArgsPushed)
266 PyrSlot *a, *b, *c, *d, *e;
267 int err;
268 int start, end;
269 float lvl0, lvl1;
271 a = g->sp - 4;
272 b = g->sp - 3;
273 c = g->sp - 2;
274 d = g->sp - 1;
275 e = g->sp;
277 err = slotIntVal(b, &start);
278 if (err) {
279 if (IsNil(b)) start = 0;
280 else return err;
283 err = slotIntVal(c, &end);
284 if (err) {
285 if (IsNil(c)) end = slotRawObject(a)->size;
286 else return err;
289 err = slotFloatVal(d, &lvl0);
290 if (err) return err;
292 err = slotFloatVal(e, &lvl1);
293 if (err) return err;
295 signal_fade_range(slotRawObject(a), start, end, lvl0, lvl1);
296 return errNone;
299 int prSignalAddHarmonic(struct VMGlobals *g, int numArgsPushed)
301 PyrSlot *a, *b, *c, *d;
302 int err;
303 float harmonic, amp;
304 double phase, step;
305 PyrObject *signal;
306 float *out;
308 a = g->sp - 3;
309 b = g->sp - 2;
310 c = g->sp - 1;
311 d = g->sp;
313 err = slotFloatVal(b, &harmonic);
314 if (err) return errWrongType;
315 err = slotFloatVal(c, &amp);
316 if (err) return errWrongType;
317 err = slotDoubleVal(d, &phase);
318 if (err) return errWrongType;
320 signal = slotRawObject(a);
321 out = (float*)(signal->slots) - 1;
322 step = twopi * harmonic / signal->size;
323 UNROLL_CODE(signal->size, out, *++out += sin(phase) * amp; phase += step; );
325 return errNone;
328 int prSignalAddChebyshev(struct VMGlobals *g, int numArgsPushed);
329 int prSignalAddChebyshev(struct VMGlobals *g, int numArgsPushed)
331 PyrSlot *a, *b, *c;
332 int err;
333 float harmonic, amp;
334 double x, step;
335 PyrObject *signal;
336 float *out;
338 a = g->sp - 2;
339 b = g->sp - 1;
340 c = g->sp;
342 err = slotFloatVal(b, &harmonic);
343 if (err) return errWrongType;
344 err = slotFloatVal(c, &amp);
345 if (err) return errWrongType;
347 signal = slotRawObject(a);
348 out = (float*)(signal->slots) - 1;
349 x = -1.0;
350 step = 2.0 / (signal->size - 1);
351 UNROLL_CODE(signal->size, out, *++out += cos(harmonic * acos(x)) * amp; x += step; );
353 return errNone;
356 //////////////////////////////////////////////////////////////////////////////
358 void signalAsWavetable(float *signal, float *wavetable, int size)
360 int i, imax;
361 float *in, *out;
362 float val1, val2;
364 in = signal;
365 out = wavetable - 1;
366 imax = size-1;
367 for (i=0; i<imax; ++i) {
368 val1 = in[i];
369 val2 = in[i+1];
370 *++out = 2.f * val1 - val2;
371 *++out = val2 - val1;
373 val1 = in[imax];
374 val2 = in[0];
375 *++out = 2.f * val1 - val2;
376 *++out = val2 - val1;
379 void wavetableAsSignal(float *wavetable, float *signal, int size)
381 int i, imax;
382 float *in, *out;
383 in = wavetable;
384 out = signal - 1;
385 imax = size;
386 for (i=0; i<size; ++i) {
387 *++out = in[0] + in[1];
388 in += 2;
393 //////////////////////////////////////////////////////////////////////////////
395 int prSignalAsWavetable(struct VMGlobals *g, int numArgsPushed)
397 PyrSlot *a;
398 int size;
399 PyrObject *signal, *wavetable;
401 a = g->sp;
403 signal = slotRawObject(a);
405 size = signal->size;
406 if ((size & (size - 1)) != 0) {
407 error("Signal size not a power of two.\n");
408 return errFailed;
410 wavetable = newPyrSignal(g, signal->size * 2);
411 wavetable->classptr = class_wavetable;
412 signalAsWavetable((float*)signal->slots, (float*)wavetable->slots, signal->size);
414 SetObject(a, wavetable);
415 return errNone;
419 int prWavetableAsSignal(struct VMGlobals *g, int numArgsPushed)
421 PyrSlot *a;
422 PyrObject *signal, *wavetable;
424 a = g->sp;
426 wavetable = slotRawObject(a);
427 signal = newPyrSignal(g, wavetable->size / 2);
428 wavetableAsSignal((float*)wavetable->slots, (float*)signal->slots, signal->size);
429 SetObject(a, signal);
430 return errNone;
432 //class_signal
434 #if 1
435 int prSignal_FFT(struct VMGlobals *g, int numArgsPushed);
436 int prSignal_FFT(struct VMGlobals *g, int numArgsPushed)
438 PyrSlot *a, *b, *c;
440 int i, M, fftsize, fftbufsize, asize;
441 float *inreal, *inimag, *fftbuf, *costable, *outreal, *outimag;
442 PyrObject *fftoutobj, *complexobj, *realobj, *imagobj;
444 a = g->sp - 2;
445 b = g->sp - 1;
446 c = g->sp;
448 asize = slotRawObject(a)->size;
449 if (slotRawFloat(b) != 0.0 && !(isKindOfSlot(b, class_signal) && slotRawObject(b)->size == asize)) { /// check: is the first condition safe?
450 error("Signal::fft imaginary part wrong type or length.\n");
451 return errFailed;
454 M = LOG2CEIL(asize);
455 fftsize = 1L << M;
457 if (!(isKindOfSlot(c, class_floatarray))) {
458 error("Signal::fft must be provided a table containing 1/4 cycle of a cosine.\n");
459 return errFailed;
461 if (slotRawObject(c)->size != fftsize/4+1) {
462 error("Signal::fft cosine table wrong size (%d), expected %d.\n", slotRawObject(c)->size, fftsize/4+1);
463 return errFailed;
465 costable = (float*)slotRawObject(c)->slots;
467 fftbufsize = fftsize * 2;
468 fftoutobj = newPyrSignal(g, fftbufsize);
469 fftoutobj->size = fftbufsize;
470 ++g->sp; SetObject(g->sp, fftoutobj);
472 complexobj = instantiateObject(g->gc, s_complex->u.classobj, 0, false, true);
473 ++g->sp; SetObject(g->sp, complexobj);
475 realobj = newPyrSignal(g, fftbufsize);
476 SetObject(complexobj->slots + 0, realobj);
477 g->gc->GCWriteNew(complexobj, realobj);
479 imagobj = newPyrSignal(g, fftbufsize);
480 SetObject(complexobj->slots + 1, imagobj);
481 g->gc->GCWriteNew(complexobj, imagobj);
483 inreal = (float*)slotRawObject(a)->slots - 1;
484 if (slotRawFloat(b) == 0.0) { /// check: is the condition safe?
486 fftbuf = (float*)fftoutobj->slots - 1;
487 for (i=0; i<asize; ++i) {
488 *++fftbuf = *++inreal;
490 for (i=asize; i<fftsize; ++i) {
491 *++fftbuf = 0.f;
494 fftbuf = (float*)fftoutobj->slots;
495 rffts(fftbuf, M, 1, costable);
496 } else {
497 inimag = (float*)slotRawObject(b)->slots - 1;
499 fftbuf = (float*)fftoutobj->slots - 1;
500 for (i=0; i<asize; ++i) {
501 *++fftbuf = *++inreal;
502 *++fftbuf = *++inimag;
504 for (i=asize; i<fftsize; ++i) {
505 *++fftbuf = 0.f;
506 *++fftbuf = 0.f;
509 fftbuf = (float*)fftoutobj->slots;
510 ffts(fftbuf, M, 1, costable);
512 outreal = (float*)realobj->slots - 1;
513 outimag = (float*)imagobj->slots - 1;
514 fftbuf = (float*)fftoutobj->slots - 1;
515 for (i=0; i<fftsize; ++i) {
516 *++outreal = *++fftbuf;
517 *++outimag = *++fftbuf;
519 realobj->size = fftsize;
520 imagobj->size = fftsize;
522 g->sp -= 2;
523 SetRaw(a, complexobj);
525 return errNone;
528 int prSignal_IFFT(struct VMGlobals *g, int numArgsPushed);
529 int prSignal_IFFT(struct VMGlobals *g, int numArgsPushed)
531 PyrSlot *a, *b, *c;
533 int i, M, fftsize, fftbufsize, asize;
534 float *inreal, *inimag, *fftbuf, *costable, *outreal, *outimag;
535 PyrObject *fftoutobj, *complexobj, *realobj, *imagobj;
537 a = g->sp - 2;
538 b = g->sp - 1;
539 c = g->sp;
541 asize = slotRawObject(a)->size;
542 if (!(isKindOfSlot(b, class_signal) && slotRawObject(b)->size == asize)) {
543 error("Signal::ifft imaginary part wrong type or length.\n");
544 return errFailed;
547 M = LOG2CEIL(asize);
548 fftsize = 1L << M;
550 if (!(isKindOfSlot(c, class_floatarray))) {
551 error("Signal::ifft must be provided a table containing 1/4 cycle of a cosine.\n");
552 return errFailed;
554 if (slotRawObject(c)->size != fftsize/4+1) {
555 error("Signal::ifft cosine table wrong size (%d), expected %d.\n", slotRawObject(c)->size, fftsize/4+1);
556 return errFailed;
558 costable = (float*)slotRawObject(c)->slots;
560 fftbufsize = fftsize * 2;
561 fftoutobj = newPyrSignal(g, fftbufsize);
562 fftoutobj->size = fftbufsize;
563 ++g->sp; SetObject(g->sp, fftoutobj);
565 complexobj = instantiateObject(g->gc, s_complex->u.classobj, 0, false, true);
566 ++g->sp; SetObject(g->sp, complexobj);
568 realobj = newPyrSignal(g, fftbufsize);
569 SetObject(complexobj->slots + 0, realobj);
570 g->gc->GCWriteNew(complexobj, realobj);
572 imagobj = newPyrSignal(g, fftbufsize);
573 SetObject(complexobj->slots + 1, imagobj);
574 g->gc->GCWriteNew(complexobj, imagobj);
576 inreal = (float*)slotRawObject(a)->slots - 1;
577 inimag = (float*)slotRawObject(b)->slots - 1;
579 fftbuf = (float*)fftoutobj->slots - 1;
580 for (i=0; i<asize; ++i) {
581 *++fftbuf = *++inreal;
582 *++fftbuf = *++inimag;
584 for (i=asize; i<fftsize; ++i) {
585 *++fftbuf = 0.f;
586 *++fftbuf = 0.f;
589 fftbuf = (float*)fftoutobj->slots;
590 iffts(fftbuf, M, 1, costable);
592 outreal = (float*)realobj->slots - 1;
593 outimag = (float*)imagobj->slots - 1;
594 fftbuf = (float*)fftoutobj->slots - 1;
595 for (i=0; i<fftsize; ++i) {
596 *++outreal = *++fftbuf;
597 *++outimag = *++fftbuf;
599 realobj->size = fftsize;
600 imagobj->size = fftsize;
602 g->sp -= 2;
603 SetRaw(a, complexobj);
605 return errNone;
607 #endif
609 void initSignalPrimitives()
611 int base, index;
613 base = nextPrimitiveIndex();
614 index = 0;
615 definePrimitive(base, index++, "_SignalPeak", prSignalPeak, 1, 0);
616 definePrimitive(base, index++, "_SignalNormalize", prSignalNormalize, 3, 0);
617 definePrimitive(base, index++, "_SignalNormalizeTransferFn", prSignalNormalizeTransferFn, 1, 0);
618 definePrimitive(base, index++, "_SignalIntegral", prSignalIntegral, 1, 0);
619 definePrimitive(base, index++, "_SignalReverse", prSignalReverse, 3, 0);
620 definePrimitive(base, index++, "_SignalInvert", prSignalInvert, 3, 0);
621 definePrimitive(base, index++, "_SignalRotate", prSignalRotate, 2, 0);
623 definePrimitive(base, index++, "_SignalFill", prSignalFill, 2, 0);
624 definePrimitive(base, index++, "_SignalScale", prSignalScale, 2, 0);
625 definePrimitive(base, index++, "_SignalOffset", prSignalOffset, 2, 0);
626 definePrimitive(base, index++, "_SignalOverDub", prSignalOverDub, 3, 0);
627 definePrimitive(base, index++, "_SignalOverWrite", prSignalOverWrite, 3, 0);
628 definePrimitive(base, index++, "_SignalFade", prSignalFade, 5, 0);
629 definePrimitive(base, index++, "_SignalAddHarmonic", prSignalAddHarmonic, 4, 0);
630 definePrimitive(base, index++, "_SignalAddChebyshev", prSignalAddChebyshev, 3, 0);
631 definePrimitive(base, index++, "_SignalString", prSignalString, 1, 0);
632 definePrimitive(base, index++, "_SignalAsWavetable", prSignalAsWavetable, 1, 0);
633 definePrimitive(base, index++, "_WavetableAsSignal", prWavetableAsSignal, 1, 0);
635 definePrimitive(base, index++, "_Signal_FFT", prSignal_FFT, 3, 0);
636 definePrimitive(base, index++, "_Signal_IFFT", prSignal_IFFT, 3, 0);