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"
39 int prSignalFill(struct VMGlobals
*g
, int numArgsPushed
)
48 err
= slotFloatVal(b
, &value
);
49 if (err
!= errNone
) return err
;
50 signal_fill(slotRawObject(a
), value
);
54 int prSignalScale(struct VMGlobals
*g
, int numArgsPushed
)
63 err
= slotFloatVal(b
, &value
);
64 if (err
!= errNone
) return err
;
65 signal_scale(slotRawObject(a
), value
);
69 int prSignalOffset(struct VMGlobals
*g
, int numArgsPushed
)
78 err
= slotFloatVal(b
, &value
);
79 if (err
!= errNone
) return err
;
80 signal_offset(slotRawObject(a
), value
);
84 int prSignalString(struct VMGlobals
*g
, int numArgsPushed
)
95 signal
= slotRawObject(a
);
97 x
= (float*)(signal
->slots
);
98 sprintf(str
, "%s[%g .. %g]", slotRawSymbol(&signal
->classptr
->name
)->name
,
99 x
[0], x
[signal
->size
-1]);
101 sprintf(str
, "%s[none]", slotRawSymbol(&signal
->classptr
->name
)->name
);
103 string
= newPyrString(g
->gc
, str
, 0, true);
104 SetObject(a
, string
);
108 int prSignalPeak(struct VMGlobals
*g
, int numArgsPushed
)
114 SetFloat(a
, signal_findpeak(slotRawObject(a
)));
118 int prSignalNormalize(struct VMGlobals
*g
, int numArgsPushed
)
127 err
= slotIntVal(b
, &start
);
129 if (IsNil(c
)) start
= 0;
133 err
= slotIntVal(c
, &end
);
135 if (IsNil(c
)) end
= slotRawObject(a
)->size
;
139 signal_normalize_range(slotRawObject(a
), start
, end
);
143 int prSignalNormalizeTransferFn(struct VMGlobals
*g
, int numArgsPushed
)
149 signal_normalize_transfer_fn(slotRawObject(a
));
153 int prSignalIntegral(struct VMGlobals
*g
, int numArgsPushed
)
159 SetFloat(a
, signal_integral(slotRawObject(a
)));
163 int prSignalInvert(struct VMGlobals
*g
, int numArgsPushed
)
172 err
= slotIntVal(b
, &start
);
174 if (IsNil(c
)) start
= 0;
178 err
= slotIntVal(c
, &end
);
180 if (IsNil(c
)) end
= slotRawObject(a
)->size
;
184 signal_invert_range(slotRawObject(a
), start
, end
);
188 int prSignalReverse(struct VMGlobals
*g
, int numArgsPushed
)
197 err
= slotIntVal(b
, &start
);
199 if (IsNil(b
)) start
= 0;
203 err
= slotIntVal(c
, &end
);
205 if (IsNil(c
)) end
= slotRawObject(a
)->size
;
209 signal_reverse_range(slotRawObject(a
), start
, end
);
213 int prSignalRotate(struct VMGlobals
*g
, int numArgsPushed
)
221 err
= slotIntVal(b
, &rot
);
224 SetRaw(a
, signal_rotate(g
, slotRawObject(a
), rot
));
228 int prSignalOverDub(struct VMGlobals
*g
, int numArgsPushed
)
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
);
246 int prSignalOverWrite(struct VMGlobals
*g
, int numArgsPushed
)
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
);
264 int prSignalFade(struct VMGlobals
*g
, int numArgsPushed
)
266 PyrSlot
*a
, *b
, *c
, *d
, *e
;
277 err
= slotIntVal(b
, &start
);
279 if (IsNil(b
)) start
= 0;
283 err
= slotIntVal(c
, &end
);
285 if (IsNil(c
)) end
= slotRawObject(a
)->size
;
289 err
= slotFloatVal(d
, &lvl0
);
292 err
= slotFloatVal(e
, &lvl1
);
295 signal_fade_range(slotRawObject(a
), start
, end
, lvl0
, lvl1
);
299 int prSignalAddHarmonic(struct VMGlobals
*g
, int numArgsPushed
)
301 PyrSlot
*a
, *b
, *c
, *d
;
313 err
= slotFloatVal(b
, &harmonic
);
314 if (err
) return errWrongType
;
315 err
= slotFloatVal(c
, &
);
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
; );
328 int prSignalAddChebyshev(struct VMGlobals
*g
, int numArgsPushed
);
329 int prSignalAddChebyshev(struct VMGlobals
*g
, int numArgsPushed
)
342 err
= slotFloatVal(b
, &harmonic
);
343 if (err
) return errWrongType
;
344 err
= slotFloatVal(c
, &
);
345 if (err
) return errWrongType
;
347 signal
= slotRawObject(a
);
348 out
= (float*)(signal
->slots
) - 1;
350 step
= 2.0 / (signal
->size
- 1);
351 UNROLL_CODE(signal
->size
, out
, *++out
+= cos(harmonic
* acos(x
)) * amp
; x
+= step
; );
356 //////////////////////////////////////////////////////////////////////////////
358 void signalAsWavetable(float *signal
, float *wavetable
, int size
)
367 for (i
=0; i
<imax
; ++i
) {
370 *++out
= 2.f
* val1
- val2
;
371 *++out
= val2
- val1
;
375 *++out
= 2.f
* val1
- val2
;
376 *++out
= val2
- val1
;
379 void wavetableAsSignal(float *wavetable
, float *signal
, int size
)
386 for (i
=0; i
<size
; ++i
) {
387 *++out
= in
[0] + in
[1];
393 //////////////////////////////////////////////////////////////////////////////
395 int prSignalAsWavetable(struct VMGlobals
*g
, int numArgsPushed
)
399 PyrObject
*signal
, *wavetable
;
403 signal
= slotRawObject(a
);
406 if ((size
& (size
- 1)) != 0) {
407 error("Signal size not a power of two.\n");
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
);
419 int prWavetableAsSignal(struct VMGlobals
*g
, int numArgsPushed
)
422 PyrObject
*signal
, *wavetable
;
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
);
435 int prSignal_FFT(struct VMGlobals
*g
, int numArgsPushed
);
436 int prSignal_FFT(struct VMGlobals
*g
, int numArgsPushed
)
440 int i
, M
, fftsize
, fftbufsize
, asize
;
441 float *inreal
, *inimag
, *fftbuf
, *costable
, *outreal
, *outimag
;
442 PyrObject
*fftoutobj
, *complexobj
, *realobj
, *imagobj
;
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");
457 if (!(isKindOfSlot(c
, class_floatarray
))) {
458 error("Signal::fft must be provided a table containing 1/4 cycle of a cosine.\n");
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);
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
) {
494 fftbuf
= (float*)fftoutobj
->slots
;
495 rffts(fftbuf
, M
, 1, costable
);
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
) {
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
;
523 SetRaw(a
, complexobj
);
528 int prSignal_IFFT(struct VMGlobals
*g
, int numArgsPushed
);
529 int prSignal_IFFT(struct VMGlobals
*g
, int numArgsPushed
)
533 int i
, M
, fftsize
, fftbufsize
, asize
;
534 float *inreal
, *inimag
, *fftbuf
, *costable
, *outreal
, *outimag
;
535 PyrObject
*fftoutobj
, *complexobj
, *realobj
, *imagobj
;
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");
550 if (!(isKindOfSlot(c
, class_floatarray
))) {
551 error("Signal::ifft must be provided a table containing 1/4 cycle of a cosine.\n");
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);
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
) {
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
;
603 SetRaw(a
, complexobj
);
609 void initSignalPrimitives()
613 base
= nextPrimitiveIndex();
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);