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
22 #include "FFT_UGens.h"
25 struct PV_OutOfPlace
: Unit
31 struct PV_MagSmear
: PV_OutOfPlace
35 struct PV_MagShift
: PV_OutOfPlace
39 struct PV_BinShift
: PV_OutOfPlace
43 struct PV_Diffuser
: Unit
46 float m_prevtrig
, *m_shift
;
50 struct PV_MagFreeze
: Unit
53 float *m_mags
, m_dc
, m_nyq
;
56 struct PV_RandWipe
: Unit
58 int *m_ordering
, m_numbins
;
63 struct PV_RandComb
: Unit
65 int *m_ordering
, m_numbins
;
70 struct PV_BinScramble
: Unit
72 int *m_from
, *m_to
, m_numbins
;
78 struct PV_Conj
: PV_Unit
{};
80 //////////////////////////////////////////////////////////////////////////////////////////////////
84 void PV_PhaseShift_Ctor(PV_Unit
*unit
);
85 void PV_PhaseShift_next(PV_Unit
*unit
, int inNumSamples
);
87 void PV_PhaseShift90_Ctor(PV_Unit
*unit
);
88 void PV_PhaseShift90_next(PV_Unit
*unit
, int inNumSamples
);
90 void PV_PhaseShift270_Ctor(PV_Unit
*unit
);
91 void PV_PhaseShift270_next(PV_Unit
*unit
, int inNumSamples
);
93 void PV_MagClip_Ctor(PV_Unit
*unit
);
94 void PV_MagClip_next(PV_Unit
*unit
, int inNumSamples
);
96 void PV_MagAbove_Ctor(PV_Unit
*unit
);
97 void PV_MagAbove_next(PV_Unit
*unit
, int inNumSamples
);
99 void PV_MagBelow_Ctor(PV_Unit
*unit
);
100 void PV_MagBelow_next(PV_Unit
*unit
, int inNumSamples
);
102 void PV_Min_Ctor(PV_Unit
*unit
);
103 void PV_Min_next(PV_Unit
*unit
, int inNumSamples
);
105 void PV_Max_Ctor(PV_Unit
*unit
);
106 void PV_Max_next(PV_Unit
*unit
, int inNumSamples
);
108 void PV_Mul_Ctor(PV_Unit
*unit
);
109 void PV_Mul_next(PV_Unit
*unit
, int inNumSamples
);
111 void PV_Div_Ctor(PV_Unit
*unit
);
112 void PV_Div_next(PV_Unit
*unit
, int inNumSamples
);
114 void PV_Add_Ctor(PV_Unit
*unit
);
115 void PV_Add_next(PV_Unit
*unit
, int inNumSamples
);
117 void PV_RectComb_Ctor(PV_Unit
*unit
);
118 void PV_RectComb_next(PV_Unit
*unit
, int inNumSamples
);
120 void PV_RectComb2_Ctor(PV_Unit
*unit
);
121 void PV_RectComb2_next(PV_Unit
*unit
, int inNumSamples
);
123 void PV_MagSquared_Ctor(PV_Unit
*unit
);
124 void PV_MagSquared_next(PV_Unit
*unit
, int inNumSamples
);
126 void PV_MagMul_Ctor(PV_Unit
*unit
);
127 void PV_MagMul_next(PV_Unit
*unit
, int inNumSamples
);
129 void PV_MagDiv_Ctor(PV_Unit
*unit
);
130 void PV_MagDiv_next(PV_Unit
*unit
, int inNumSamples
);
132 void PV_Copy_Ctor(PV_Unit
*unit
);
133 void PV_Copy_next(PV_Unit
*unit
, int inNumSamples
);
135 void PV_CopyPhase_Ctor(PV_Unit
*unit
);
136 void PV_CopyPhase_next(PV_Unit
*unit
, int inNumSamples
);
138 void PV_MagSmear_Ctor(PV_MagSmear
*unit
);
139 void PV_MagSmear_Dtor(PV_MagSmear
*unit
);
140 void PV_MagSmear_next(PV_MagSmear
*unit
, int inNumSamples
);
142 void PV_BinShift_Ctor(PV_BinShift
*unit
);
143 void PV_BinShift_Dtor(PV_BinShift
*unit
);
144 void PV_BinShift_next(PV_BinShift
*unit
, int inNumSamples
);
146 void PV_MagShift_Ctor(PV_MagShift
*unit
);
147 void PV_MagShift_Dtor(PV_MagShift
*unit
);
148 void PV_MagShift_next(PV_MagShift
*unit
, int inNumSamples
);
150 void PV_MagNoise_Ctor(PV_Unit
*unit
);
151 void PV_MagNoise_next(PV_Unit
*unit
, int inNumSamples
);
153 void PV_BrickWall_Ctor(PV_Unit
*unit
);
154 void PV_BrickWall_next(PV_Unit
*unit
, int inNumSamples
);
156 void PV_BinWipe_Ctor(PV_Unit
*unit
);
157 void PV_BinWipe_next(PV_Unit
*unit
, int inNumSamples
);
159 void PV_LocalMax_Ctor(PV_Unit
*unit
);
160 void PV_LocalMax_next(PV_Unit
*unit
, int inNumSamples
);
162 void PV_RandComb_Ctor(PV_RandComb
*unit
);
163 void PV_RandComb_Dtor(PV_RandComb
*unit
);
164 void PV_RandComb_next(PV_RandComb
*unit
, int inNumSamples
);
166 void PV_RandWipe_Ctor(PV_RandWipe
*unit
);
167 void PV_RandWipe_Dtor(PV_RandWipe
*unit
);
168 void PV_RandWipe_next(PV_RandWipe
*unit
, int inNumSamples
);
170 void PV_Diffuser_Ctor(PV_Diffuser
*unit
);
171 void PV_Diffuser_Dtor(PV_Diffuser
*unit
);
172 void PV_Diffuser_next(PV_Diffuser
*unit
, int inNumSamples
);
174 void PV_MagFreeze_Ctor(PV_MagFreeze
*unit
);
175 void PV_MagFreeze_Dtor(PV_MagFreeze
*unit
);
176 void PV_MagFreeze_next(PV_MagFreeze
*unit
, int inNumSamples
);
178 void PV_BinScramble_Ctor(PV_BinScramble
*unit
);
179 void PV_BinScramble_Dtor(PV_BinScramble
*unit
);
180 void PV_BinScramble_next(PV_BinScramble
*unit
, int inNumSamples
);
182 void PV_Conj_Ctor(PV_Unit
*unit
);
183 void PV_Conj_next(PV_Unit
*unit
, int inNumSamples
);
185 /* spectral feature extractors? :
190 average magnitude over a range of bins
191 max magnitude over a range of bins
192 max magnitude bin freq
199 //////////////////////////////////////////////////////////////////////////////////////////////////
202 //SCPolarBuf* ToPolarApx(SndBuf *buf);
204 SCPolarBuf* ToPolarApx(SndBuf *buf)
206 if (buf->coord == coord_Complex) {
207 SCComplexBuf* p = (SCComplexBuf*)buf->data;
208 int numbins = buf->samples - 2 >> 1;
209 for (int i=0; i<numbins; ++i) {
210 p->bin[i].ToPolarApxInPlace();
212 buf->coord = coord_Polar;
214 return (SCPolarBuf*)buf->data;
217 //SCComplexBuf* ToComplexApx(SndBuf *buf);
219 SCComplexBuf* ToComplexApx(SndBuf *buf)
221 if (buf->coord == coord_Polar) {
222 SCPolarBuf* p = (SCPolarBuf*)buf->data;
223 int numbins = buf->samples - 2 >> 1;
224 for (int i=0; i<numbins; ++i) {
225 p->bin[i].ToComplexApxInPlace();
227 buf->coord = coord_Complex;
229 return (SCComplexBuf*)buf->data;
233 /////////////////////////////////////////////////////////////////////////////////////////////
235 void PV_MagAbove_next(PV_Unit
*unit
, int inNumSamples
)
239 SCPolarBuf
*p
= ToPolarApx(buf
);
241 float thresh
= ZIN0(1);
243 if(std::abs(p
->dc
) < thresh
) p
->dc
= 0.f
;
244 if(std::abs(p
->nyq
) < thresh
) p
->nyq
= 0.f
;
245 for (int i
=0; i
<numbins
; ++i
) {
246 float mag
= p
->bin
[i
].mag
;
247 if (mag
< thresh
) p
->bin
[i
].mag
= 0.f
;
251 void PV_MagAbove_Ctor(PV_Unit
*unit
)
253 SETCALC(PV_MagAbove_next
);
257 void PV_MagBelow_next(PV_Unit
*unit
, int inNumSamples
)
261 SCPolarBuf
*p
= ToPolarApx(buf
);
263 float thresh
= ZIN0(1);
265 if(std::abs(p
->dc
) > thresh
) p
->dc
= 0.f
;
266 if(std::abs(p
->nyq
) > thresh
) p
->nyq
= 0.f
;
267 for (int i
=0; i
<numbins
; ++i
) {
268 float mag
= p
->bin
[i
].mag
;
269 if (mag
> thresh
) p
->bin
[i
].mag
= 0.f
;
273 void PV_MagBelow_Ctor(PV_Unit
*unit
)
275 SETCALC(PV_MagBelow_next
);
279 void PV_MagClip_next(PV_Unit
*unit
, int inNumSamples
)
283 SCPolarBuf
*p
= ToPolarApx(buf
);
285 float thresh
= ZIN0(1);
287 if(std::abs(p
->dc
) > thresh
) p
->dc
= p
->dc
< 0.f
? -thresh
: thresh
;
288 if(std::abs(p
->nyq
) > thresh
) p
->nyq
= p
->nyq
< 0.f
? -thresh
: thresh
;
289 for (int i
=0; i
<numbins
; ++i
) {
290 float mag
= p
->bin
[i
].mag
;
291 if (mag
> thresh
) p
->bin
[i
].mag
= thresh
;
295 void PV_MagClip_Ctor(PV_Unit
*unit
)
297 SETCALC(PV_MagClip_next
);
301 void PV_LocalMax_next(PV_Unit
*unit
, int inNumSamples
)
305 SCPolarBuf
*p
= ToPolarApx(buf
);
307 float thresh
= ZIN0(1);
310 // DC is only compared with the one above it
311 dc
= std::abs(p
->dc
);
313 if(dc
< thresh
|| dc
< mag
) p
->dc
= 0.f
;
314 // 0th bin compared against DC and 1th
315 if(mag
< thresh
|| mag
< dc
|| mag
< p
->bin
[1].mag
) p
->bin
[0].mag
= 0.f
;
316 // All the middling bins
317 for (int i
=1; i
<numbins
-1; ++i
) {
318 float mag
= p
->bin
[i
].mag
;
319 if (mag
< thresh
|| mag
< p
->bin
[i
-1].mag
|| mag
< p
->bin
[i
+1].mag
) {
323 // Penultimate is compared against the one below and the nyq
324 nyq
= std::abs(p
->nyq
);
325 mag
= p
->bin
[numbins
-1].mag
;
326 if(mag
< thresh
|| mag
< nyq
|| mag
< p
->bin
[numbins
-2].mag
) p
->bin
[numbins
-1].mag
= 0.f
;
327 // Nyquist compared against penultimate
328 if(nyq
< thresh
|| nyq
< mag
) p
->nyq
= 0.f
;
331 void PV_LocalMax_Ctor(PV_Unit
*unit
)
333 SETCALC(PV_LocalMax_next
);
337 void PV_MagSmear_next(PV_MagSmear
*unit
, int inNumSamples
)
342 SCPolarBuf
*p
= ToPolarApx(buf
);
343 SCPolarBuf
*q
= (SCPolarBuf
*)unit
->m_tempbuf
;
345 int width
= (int)ZIN0(1);
346 width
= sc_clip(width
, 0, numbins
-1);
347 float scale
= 1.f
/ (2*width
+1);
351 for (int j
=0; j
<numbins
; j
++) {
353 for (int pos
= j
-width
; pos
<= j
+width
; pos
++) {
354 if (pos
>= 0 && pos
< numbins
) {
355 sum
+= p
->bin
[pos
].mag
;
358 q
->bin
[j
].Set( sum
* scale
, p
->bin
[j
].phase
);
360 for (int i
=0; i
<numbins
; i
++) {
361 p
->bin
[i
] = q
->bin
[i
];
365 void PV_MagSmear_Ctor(PV_MagSmear
*unit
)
367 SETCALC(PV_MagSmear_next
);
372 void PV_MagSmear_Dtor(PV_MagSmear
*unit
)
374 RTFree(unit
->mWorld
, unit
->m_tempbuf
);
377 void PV_BinShift_next(PV_BinShift
*unit
, int inNumSamples
)
382 // get shift and stretch params
383 float stretch
= ZIN0(1);
384 float shift
= ZIN0(2);
386 SCComplexBuf
*p
= ToComplexApx(buf
);
387 SCComplexBuf
*q
= (SCComplexBuf
*)unit
->m_tempbuf
;
389 // initialize output buf to zeroes
390 for (int i
=0; i
<numbins
; ++i
) {
398 for (i
=0, fpos
= shift
; i
< numbins
; ++i
, fpos
+= stretch
) {
399 int32 pos
= (int32
)(fpos
+ 0.5);
400 if (pos
>= 0 && pos
< numbins
) {
401 q
->bin
[pos
] += p
->bin
[i
];
404 memcpy(p
->bin
, q
->bin
, numbins
* sizeof(SCComplex
));
408 void PV_BinShift_Ctor(PV_BinShift
*unit
)
410 SETCALC(PV_BinShift_next
);
415 void PV_BinShift_Dtor(PV_BinShift
*unit
)
417 RTFree(unit
->mWorld
, unit
->m_tempbuf
);
420 void PV_MagShift_next(PV_MagShift
*unit
, int inNumSamples
)
425 // get shift and stretch params
426 float stretch
= ZIN0(1);
427 float shift
= ZIN0(2);
429 SCPolarBuf
*p
= ToPolarApx(buf
);
430 SCPolarBuf
*q
= (SCPolarBuf
*)unit
->m_tempbuf
;
432 // initialize output buf to zeroes
433 for (int i
=0; i
<numbins
; ++i
) {
435 q
->bin
[i
].phase
= p
->bin
[i
].phase
;
442 for (i
=0, fpos
= shift
; i
< numbins
; ++i
, fpos
+= stretch
) {
443 int32 pos
= (int32
)(fpos
+ 0.5);
444 if (pos
>= 0 && pos
< numbins
) {
445 q
->bin
[pos
].mag
+= p
->bin
[i
].mag
;
448 memcpy(p
->bin
, q
->bin
, numbins
* sizeof(SCComplex
));
451 void PV_MagShift_Ctor(PV_MagShift
*unit
)
453 SETCALC(PV_MagShift_next
);
458 void PV_MagShift_Dtor(PV_MagShift
*unit
)
460 RTFree(unit
->mWorld
, unit
->m_tempbuf
);
463 void PV_MagNoise_next(PV_Unit
*unit
, int inNumSamples
)
468 if (buf
->coord
== coord_Complex
) {
469 SCComplexBuf
*p
= (SCComplexBuf
*)buf
->data
;
470 for (int i
=0; i
<numbins
; ++i
) {
471 float r
= frand2(s1
, s2
, s3
);
475 p
->dc
*= frand2(s1
, s2
, s3
);
476 p
->nyq
*= frand2(s1
, s2
, s3
);
478 SCPolarBuf
*p
= (SCPolarBuf
*)buf
->data
;
479 for (int i
=0; i
<numbins
; ++i
) {
480 float r
= frand2(s1
, s2
, s3
);
483 p
->dc
*= frand2(s1
, s2
, s3
);
484 p
->nyq
*= frand2(s1
, s2
, s3
);
489 void PV_MagNoise_Ctor(PV_Unit
*unit
)
491 SETCALC(PV_MagNoise_next
);
495 void PV_PhaseShift_next(PV_Unit
*unit
, int inNumSamples
)
499 SCPolarBuf
*p
= ToPolarApx(buf
);
501 float shift
= ZIN0(1);
503 for (int i
=0; i
<numbins
; ++i
) {
504 p
->bin
[i
].phase
+= shift
;
508 void PV_PhaseShift_Ctor(PV_Unit
*unit
)
510 SETCALC(PV_PhaseShift_next
);
514 void PV_PhaseShift90_next(PV_Unit
*unit
, int inNumSamples
)
518 SCComplexBuf
*p
= ToComplexApx(buf
);
520 for (int i
=0; i
<numbins
; ++i
) {
521 float temp
= p
->bin
[i
].real
;
522 p
->bin
[i
].real
= -p
->bin
[i
].imag
;
523 p
->bin
[i
].imag
= temp
;
527 void PV_PhaseShift90_Ctor(PV_Unit
*unit
)
529 SETCALC(PV_PhaseShift90_next
);
533 void PV_PhaseShift270_next(PV_Unit
*unit
, int inNumSamples
)
537 SCComplexBuf
*p
= ToComplexApx(buf
);
539 for (int i
=0; i
<numbins
; ++i
) {
540 float temp
= p
->bin
[i
].real
;
541 p
->bin
[i
].real
= p
->bin
[i
].imag
;
542 p
->bin
[i
].imag
= -temp
;
546 void PV_PhaseShift270_Ctor(PV_Unit
*unit
)
548 SETCALC(PV_PhaseShift270_next
);
552 void PV_MagSquared_next(PV_Unit
*unit
, int inNumSamples
)
556 SCPolarBuf
*p
= ToPolarApx(buf
);
558 p
->dc
= p
->dc
* p
->dc
;
559 p
->nyq
= p
->nyq
* p
->nyq
;
560 for (int i
=0; i
<numbins
; ++i
) {
561 float mag
= p
->bin
[i
].mag
;
562 p
->bin
[i
].mag
= mag
* mag
;
566 void PV_MagSquared_Ctor(PV_Unit
*unit
)
568 SETCALC(PV_MagSquared_next
);
572 void PV_BrickWall_next(PV_Unit
*unit
, int inNumSamples
)
576 SCComplexBuf
*p
= (SCComplexBuf
*)buf
->data
;
578 int wipe
= (int)(ZIN0(1) * numbins
);
580 wipe
= sc_min(wipe
, numbins
);
582 for (int i
=0; i
< wipe
; ++i
) {
585 if(wipe
==numbins
) p
->nyq
= 0.f
;
586 } else if (wipe
< 0) {
587 wipe
= sc_max(wipe
, -numbins
);
588 if(wipe
==-numbins
) p
->dc
= 0.f
;
589 for (int i
=numbins
+wipe
; i
< numbins
; ++i
) {
596 void PV_BrickWall_Ctor(PV_Unit
*unit
)
598 SETCALC(PV_BrickWall_next
);
602 void PV_BinWipe_next(PV_Unit
*unit
, int inNumSamples
)
606 SCComplexBuf
*p
= (SCComplexBuf
*)buf1
->data
;
607 SCComplexBuf
*q
= (SCComplexBuf
*)buf2
->data
;
609 int wipe
= (int)(ZIN0(2) * numbins
);
611 wipe
= sc_min(wipe
, numbins
);
613 for (int i
=0; i
< wipe
; ++i
) {
614 p
->bin
[i
] = q
->bin
[i
];
616 if(wipe
==numbins
) p
->nyq
= q
->nyq
;
617 } else if (wipe
< 0) {
618 wipe
= sc_max(wipe
, -numbins
);
619 if(wipe
==-numbins
) p
->dc
= q
->dc
;
620 for (int i
=numbins
+wipe
; i
< numbins
; ++i
) {
621 p
->bin
[i
] = q
->bin
[i
];
627 void PV_BinWipe_Ctor(PV_Unit
*unit
)
629 SETCALC(PV_BinWipe_next
);
633 void PV_MagMul_next(PV_Unit
*unit
, int inNumSamples
)
637 SCPolarBuf
*p
= ToPolarApx(buf1
);
638 SCPolarBuf
*q
= ToPolarApx(buf2
);
642 for (int i
=0; i
<numbins
; ++i
) {
643 p
->bin
[i
].mag
*= q
->bin
[i
].mag
;
647 void PV_MagMul_Ctor(PV_Unit
*unit
)
649 SETCALC(PV_MagMul_next
);
653 void PV_MagDiv_next(PV_Unit
*unit
, int inNumSamples
)
657 SCPolarBuf
*p
= ToPolarApx(buf1
);
658 SCPolarBuf
*q
= ToPolarApx(buf2
);
660 float zeroed
= ZIN0(2);
662 p
->dc
/= sc_max(q
->dc
, zeroed
);
663 p
->nyq
/= sc_max(q
->nyq
, zeroed
);
664 for (int i
=0; i
<numbins
; ++i
) {
665 p
->bin
[i
].mag
/= sc_max(q
->bin
[i
].mag
, zeroed
);
669 void PV_MagDiv_Ctor(PV_Unit
*unit
)
671 SETCALC(PV_MagDiv_next
);
675 void PV_Copy_next(PV_Unit
*unit
, int inNumSamples
)
677 float fbufnum1
= ZIN0(0);
678 float fbufnum2
= ZIN0(1);
679 if (fbufnum1
< 0.f
|| fbufnum2
< 0.f
) { ZOUT0(0) = -1.f
; return; }
681 uint32 ibufnum1
= (int)fbufnum1
;
682 uint32 ibufnum2
= (int)fbufnum2
;
683 World
*world
= unit
->mWorld
;
686 if (ibufnum1
>= world
->mNumSndBufs
) {
687 int localBufNum
= ibufnum1
- world
->mNumSndBufs
;
688 Graph
*parent
= unit
->mParent
;
689 if(localBufNum
<= parent
->localBufNum
) {
690 buf1
= parent
->mLocalSndBufs
+ localBufNum
;
692 buf1
= world
->mSndBufs
;
695 buf1
= world
->mSndBufs
+ ibufnum1
;
697 if (ibufnum2
>= world
->mNumSndBufs
) {
698 int localBufNum
= ibufnum2
- world
->mNumSndBufs
;
699 Graph
*parent
= unit
->mParent
;
700 if(localBufNum
<= parent
->localBufNum
) {
701 buf2
= parent
->mLocalSndBufs
+ localBufNum
;
703 buf2
= world
->mSndBufs
;
706 buf2
= world
->mSndBufs
+ ibufnum2
;
709 if (buf1
->samples
!= buf2
->samples
) return;
710 int numbins
= buf1
->samples
- 2 >> 1;
713 LOCK_SNDBUF2_SHARED_EXCLUSIVE(buf1
, buf2
);
714 buf2
->coord
= buf1
->coord
;
715 memcpy(buf2
->data
, buf1
->data
, buf1
->samples
* sizeof(float));
718 void PV_Copy_Ctor(PV_Unit
*unit
)
720 SETCALC(PV_Copy_next
);
724 void PV_CopyPhase_next(PV_Unit
*unit
, int inNumSamples
)
728 SCPolarBuf
*p
= ToPolarApx(buf1
);
729 SCPolarBuf
*q
= ToPolarApx(buf2
);
731 if((p
->dc
> 0.f
) == (q
->dc
< 0.f
)) p
->dc
= -p
->dc
;
732 if((p
->nyq
> 0.f
) == (q
->nyq
< 0.f
)) p
->nyq
= -p
->nyq
;
733 for (int i
=0; i
<numbins
; ++i
) {
734 p
->bin
[i
].phase
= q
->bin
[i
].phase
;
738 void PV_CopyPhase_Ctor(PV_Unit
*unit
)
740 SETCALC(PV_CopyPhase_next
);
744 void PV_Mul_next(PV_Unit
*unit
, int inNumSamples
)
748 SCComplexBuf
*p
= ToComplexApx(buf1
);
749 SCComplexBuf
*q
= ToComplexApx(buf2
);
751 float preal
, realmul
, imagmul
;
755 for (int i
=0; i
<numbins
; ++i
) {
756 preal
= p
->bin
[i
].real
;
757 // Complex multiply using only 3 multiplications rather than 4. http://mathworld.wolfram.com/ComplexMultiplication.html
758 realmul
= (preal
* q
->bin
[i
].real
);
759 imagmul
= (p
->bin
[i
].imag
* q
->bin
[i
].imag
);
760 p
->bin
[i
].real
= realmul
- imagmul
;
761 p
->bin
[i
].imag
= (preal
+ p
->bin
[i
].imag
) * (q
->bin
[i
].real
+ q
->bin
[i
].imag
) - realmul
- imagmul
;
765 void PV_Mul_Ctor(PV_Unit
*unit
)
767 SETCALC(PV_Mul_next
);
771 void PV_Div_next(PV_Unit
*unit
, int inNumSamples
)
775 SCComplexBuf
*p
= ToComplexApx(buf1
);
776 SCComplexBuf
*q
= ToComplexApx(buf2
);
780 for (int i
=0; i
<numbins
; ++i
) {
781 // See http://gcc.gnu.org/ml/fortran/2004-05/msg00029.html
782 // Note that hypot has danger of overflow (see URL above),
783 // however FFT values typically stay within a small range,
784 // so I'm considering this OK for now.
785 float hypot
= q
->bin
[i
].real
* q
->bin
[i
].real
+ q
->bin
[i
].imag
* q
->bin
[i
].imag
;
786 float preal
= p
->bin
[i
].real
;
787 p
->bin
[i
].real
= (preal
* q
->bin
[i
].real
+ p
->bin
[i
].imag
* q
->bin
[i
].imag
) / hypot
;
788 p
->bin
[i
].imag
= (p
->bin
[i
].imag
* q
->bin
[i
].real
- preal
* q
->bin
[i
].imag
) / hypot
;
792 void PV_Div_Ctor(PV_Unit
*unit
)
794 SETCALC(PV_Div_next
);
798 void PV_Add_next(PV_Unit
*unit
, int inNumSamples
)
802 SCComplexBuf
*p
= ToComplexApx(buf1
);
803 SCComplexBuf
*q
= ToComplexApx(buf2
);
807 for (int i
=0; i
<numbins
; ++i
) {
808 p
->bin
[i
].real
+= q
->bin
[i
].real
;
809 p
->bin
[i
].imag
+= q
->bin
[i
].imag
;
813 void PV_Add_Ctor(PV_Unit
*unit
)
815 SETCALC(PV_Add_next
);
819 void PV_Max_next(PV_Unit
*unit
, int inNumSamples
)
823 SCPolarBuf
*p
= ToPolarApx(buf1
);
824 SCPolarBuf
*q
= ToPolarApx(buf2
);
826 if(std::abs(q
->dc
) > std::abs(p
->dc
)) p
->dc
= q
->dc
;
827 if(std::abs(q
->nyq
) > std::abs(p
->nyq
)) p
->nyq
= q
->nyq
;
828 for (int i
=0; i
<numbins
; ++i
) {
829 if (q
->bin
[i
].mag
> p
->bin
[i
].mag
) {
830 p
->bin
[i
] = q
->bin
[i
];
835 void PV_Max_Ctor(PV_Unit
*unit
)
837 SETCALC(PV_Max_next
);
841 void PV_Min_next(PV_Unit
*unit
, int inNumSamples
)
845 SCPolarBuf
*p
= ToPolarApx(buf1
);
846 SCPolarBuf
*q
= ToPolarApx(buf2
);
848 if(std::abs(q
->dc
) < std::abs(p
->dc
)) p
->dc
= q
->dc
;
849 if(std::abs(q
->nyq
) < std::abs(p
->nyq
)) p
->nyq
= q
->nyq
;
850 for (int i
=0; i
<numbins
; ++i
) {
851 if (q
->bin
[i
].mag
< p
->bin
[i
].mag
) {
852 p
->bin
[i
] = q
->bin
[i
];
857 void PV_Min_Ctor(PV_Unit
*unit
)
859 SETCALC(PV_Min_next
);
863 void PV_RectComb_next(PV_Unit
*unit
, int inNumSamples
)
867 float numTeeth
= ZIN0(1);
868 float phase
= ZIN0(2);
869 float width
= ZIN0(3);
870 float freq
= numTeeth
/ (numbins
+ 1);
872 SCComplexBuf
*p
= (SCComplexBuf
*)buf
->data
;
874 if (phase
> width
) p
->dc
= 0.f
;
876 if (phase
>= 1.f
) phase
-= 1.f
;
877 else if (phase
< 0.f
) phase
+= 1.f
;
879 for (int i
=0; i
< numbins
; ++i
) {
880 if (phase
> width
) p
->bin
[i
] = 0.f
;
882 if (phase
>= 1.f
) phase
-= 1.f
;
883 else if (phase
< 0.f
) phase
+= 1.f
;
886 if (phase
> width
) p
->nyq
= 0.f
;
889 void PV_RectComb_Ctor(PV_Unit
*unit
)
891 SETCALC(PV_RectComb_next
);
895 void PV_RectComb2_next(PV_Unit
*unit
, int inNumSamples
)
899 float numTeeth
= ZIN0(2);
900 float phase
= ZIN0(3);
901 float width
= ZIN0(4);
902 float freq
= numTeeth
/ (numbins
+ 1);
904 SCComplexBuf
*p
= (SCComplexBuf
*)buf1
->data
;
905 SCComplexBuf
*q
= (SCComplexBuf
*)buf2
->data
;
907 if (phase
> width
) p
->dc
= q
->dc
;
909 if (phase
>= 1.f
) phase
-= 1.f
;
910 else if (phase
< 0.f
) phase
+= 1.f
;
912 for (int i
=0; i
< numbins
; ++i
) {
913 if (phase
> width
) p
->bin
[i
] = q
->bin
[i
];
915 if (phase
>= 1.f
) phase
-= 1.f
;
916 else if (phase
< 0.f
) phase
+= 1.f
;
919 if (phase
> width
) p
->nyq
= q
->nyq
;
922 void PV_RectComb2_Ctor(PV_Unit
*unit
)
924 SETCALC(PV_RectComb2_next
);
929 static void PV_RandComb_choose(PV_RandComb
* unit
)
931 int numbins
= unit
->m_numbins
;
932 for (int i
=0; i
<numbins
; ++i
) {
933 unit
->m_ordering
[i
] = i
;
936 for (int i
=0; i
<numbins
; ++i
) {
937 int32 j
= (int32
)(frand(s1
,s2
,s3
) * (numbins
- i
));
938 int32 temp
= unit
->m_ordering
[i
];
939 unit
->m_ordering
[i
] = unit
->m_ordering
[j
];
940 unit
->m_ordering
[j
] = temp
;
945 void PV_RandComb_next(PV_RandComb
*unit
, int inNumSamples
)
947 float trig
= ZIN0(2);
948 if (trig
> 0.f
&& unit
->m_prevtrig
<= 0.f
) unit
->m_triggered
= true;
949 unit
->m_prevtrig
= trig
;
953 if (!unit
->m_ordering
) {
954 unit
->m_ordering
= (int*)RTAlloc(unit
->mWorld
, numbins
* sizeof(int));
955 unit
->m_numbins
= numbins
;
956 PV_RandComb_choose(unit
);
958 if (numbins
!= unit
->m_numbins
) return;
959 if (unit
->m_triggered
) {
960 unit
->m_triggered
= false;
961 PV_RandComb_choose(unit
);
965 int n
= (int)(ZIN0(1) * numbins
);
966 n
= sc_clip(n
, 0, numbins
);
968 SCComplexBuf
*p
= (SCComplexBuf
*)buf
->data
;
970 int *ordering
= unit
->m_ordering
;
971 for (int i
=0; i
<n
; ++i
) {
972 p
->bin
[ordering
[i
]] = 0.f
;
975 // including dc and nyq in the above shuffle would add too much complexity. but at full "wipe" we should get silence.
982 void PV_RandComb_Ctor(PV_RandComb
* unit
)
984 SETCALC(PV_RandComb_next
);
986 unit
->m_ordering
= 0;
987 unit
->m_prevtrig
= 0.f
;
988 unit
->m_triggered
= false;
991 void PV_RandComb_Dtor(PV_RandComb
* unit
)
993 RTFree(unit
->mWorld
, unit
->m_ordering
);
996 //////////////////////
998 static void PV_RandWipe_choose(PV_RandWipe
* unit
)
1000 int numbins
= unit
->m_numbins
;
1001 for (int i
=0; i
<numbins
; ++i
) {
1002 unit
->m_ordering
[i
] = i
;
1005 for (int i
=0; i
<numbins
; ++i
) {
1006 int32 j
= (int32
)(frand(s1
,s2
,s3
) * (numbins
- i
));
1007 int32 temp
= unit
->m_ordering
[i
];
1008 unit
->m_ordering
[i
] = unit
->m_ordering
[j
];
1009 unit
->m_ordering
[j
] = temp
;
1014 void PV_RandWipe_next(PV_RandWipe
*unit
, int inNumSamples
)
1016 float trig
= ZIN0(3);
1017 if (trig
> 0.f
&& unit
->m_prevtrig
<= 0.f
) unit
->m_triggered
= true;
1018 unit
->m_prevtrig
= trig
;
1022 if (!unit
->m_ordering
) {
1023 unit
->m_ordering
= (int*)RTAlloc(unit
->mWorld
, numbins
* sizeof(int));
1024 unit
->m_numbins
= numbins
;
1025 PV_RandWipe_choose(unit
);
1027 if (numbins
!= unit
->m_numbins
) return;
1028 if (unit
->m_triggered
) {
1029 unit
->m_triggered
= false;
1030 PV_RandWipe_choose(unit
);
1034 int n
= (int)(ZIN0(2) * numbins
);
1035 n
= sc_clip(n
, 0, numbins
);
1037 SCComplexBuf
*p
= (SCComplexBuf
*)buf1
->data
;
1038 SCComplexBuf
*q
= (SCComplexBuf
*)buf2
->data
;
1040 int *ordering
= unit
->m_ordering
;
1041 for (int i
=0; i
<n
; ++i
) {
1042 p
->bin
[ordering
[i
]] = q
->bin
[ordering
[i
]];
1047 void PV_RandWipe_Ctor(PV_RandWipe
* unit
)
1049 SETCALC(PV_RandWipe_next
);
1051 unit
->m_ordering
= 0;
1052 unit
->m_prevtrig
= 0.f
;
1053 unit
->m_triggered
= false;
1056 void PV_RandWipe_Dtor(PV_RandWipe
* unit
)
1058 RTFree(unit
->mWorld
, unit
->m_ordering
);
1061 //////////////////////
1063 static void PV_Diffuser_choose(PV_Diffuser
* unit
)
1066 for (int i
=0; i
<unit
->m_numbins
; ++i
) {
1067 unit
->m_shift
[i
] = frand(s1
,s2
,s3
) * twopi
;
1072 void PV_Diffuser_next(PV_Diffuser
*unit
, int inNumSamples
)
1074 float trig
= ZIN0(1);
1075 if (trig
> 0.f
&& unit
->m_prevtrig
<= 0.f
) unit
->m_triggered
= true;
1076 unit
->m_prevtrig
= trig
;
1080 if (!unit
->m_shift
) {
1081 unit
->m_shift
= (float*)RTAlloc(unit
->mWorld
, numbins
* sizeof(float));
1082 unit
->m_numbins
= numbins
;
1083 PV_Diffuser_choose(unit
);
1085 if (numbins
!= unit
->m_numbins
) return;
1086 if (unit
->m_triggered
) {
1087 unit
->m_triggered
= false;
1088 PV_Diffuser_choose(unit
);
1092 int n
= (int)(ZIN0(1) * numbins
);
1093 n
= sc_clip(n
, 0, numbins
);
1095 SCPolarBuf
*p
= ToPolarApx(buf
);
1097 float *shift
= unit
->m_shift
;
1098 for (int i
=0; i
<n
; ++i
) {
1099 p
->bin
[i
].phase
+= shift
[i
];
1104 void PV_Diffuser_Ctor(PV_Diffuser
* unit
)
1106 SETCALC(PV_Diffuser_next
);
1109 unit
->m_prevtrig
= 0.f
;
1110 unit
->m_triggered
= false;
1113 void PV_Diffuser_Dtor(PV_Diffuser
* unit
)
1115 RTFree(unit
->mWorld
, unit
->m_shift
);
1118 //////////////////////
1120 void PV_MagFreeze_next(PV_MagFreeze
*unit
, int inNumSamples
)
1124 float freeze
= ZIN0(1);
1126 if (!unit
->m_mags
) {
1127 unit
->m_mags
= (float*)RTAlloc(unit
->mWorld
, numbins
* sizeof(float));
1128 unit
->m_numbins
= numbins
;
1129 // The first fft frame must use the else branch below
1130 // so that unit->m_mags gets populated with actual mag data
1131 // before reading; otherwise it might be used uninitialized.
1133 } else if (numbins
!= unit
->m_numbins
) return;
1135 SCPolarBuf
*p
= ToPolarApx(buf
);
1137 float *mags
= unit
->m_mags
;
1139 for (int i
=0; i
<numbins
; ++i
) {
1140 p
->bin
[i
].mag
= mags
[i
];
1143 p
->nyq
= unit
->m_nyq
;
1145 for (int i
=0; i
<numbins
; ++i
) {
1146 mags
[i
] = p
->bin
[i
].mag
;
1149 unit
->m_nyq
= p
->nyq
;
1154 void PV_MagFreeze_Ctor(PV_MagFreeze
* unit
)
1156 SETCALC(PV_MagFreeze_next
);
1161 void PV_MagFreeze_Dtor(PV_MagFreeze
* unit
)
1163 RTFree(unit
->mWorld
, unit
->m_mags
);
1166 //////////////////////
1168 static void PV_BinScramble_choose(PV_BinScramble
* unit
)
1170 int numbins
= unit
->m_numbins
;
1171 int *to
= unit
->m_to
;
1172 int *from
= unit
->m_from
;
1174 for (int i
=0; i
<numbins
; ++i
) {
1178 for (int i
=0; i
<numbins
; ++i
) {
1179 int32 j
= (int32
)(frand(s1
,s2
,s3
) * (numbins
- i
));
1185 int32 width
= (int32
)(ZIN0(2) * numbins
);
1186 for (int i
=0; i
<numbins
; ++i
) {
1188 int32 minr
= sc_max(0, k
-width
);
1189 int32 maxr
= sc_min(numbins
-1, k
+width
);
1190 int32 j
= (int32
)(frand(s1
,s2
,s3
) * (maxr
- minr
) + minr
);
1196 void PV_BinScramble_next(PV_BinScramble
*unit
, int inNumSamples
)
1198 float trig
= ZIN0(3);
1199 if (trig
> 0.f
&& unit
->m_prevtrig
<= 0.f
) unit
->m_triggered
= true;
1200 unit
->m_prevtrig
= trig
;
1205 unit
->m_to
= (int*)RTAlloc(unit
->mWorld
, numbins
* 2 * sizeof(int));
1206 unit
->m_from
= unit
->m_to
+ numbins
;
1207 unit
->m_numbins
= numbins
;
1208 unit
->m_tempbuf
= (float*)RTAlloc(unit
->mWorld
, buf
->samples
* sizeof(float));
1209 PV_BinScramble_choose(unit
);
1211 if (numbins
!= unit
->m_numbins
) return;
1212 if (unit
->m_triggered
) {
1213 unit
->m_triggered
= false;
1214 PV_BinScramble_choose(unit
);
1218 SCComplexBuf
*p
= (SCComplexBuf
*)buf
->data
;
1219 SCComplexBuf
*q
= (SCComplexBuf
*)unit
->m_tempbuf
;
1221 float wipe
= ZIN0(1);
1222 int32 scrambleBins
= (int32
)(numbins
* sc_clip(wipe
, 0.f
, 1.f
));
1224 int *to
= unit
->m_to
;
1225 int *from
= unit
->m_from
;
1226 for (int j
=0; j
<scrambleBins
; j
++) {
1227 q
->bin
[to
[j
]] = p
->bin
[from
[j
]];
1229 for (int j
=scrambleBins
; j
<numbins
; j
++) {
1231 q
->bin
[a
] = p
->bin
[a
];
1235 memcpy(p
->bin
, q
->bin
, numbins
* sizeof(SCComplex
));
1239 void PV_BinScramble_Ctor(PV_BinScramble
* unit
)
1241 SETCALC(PV_BinScramble_next
);
1244 unit
->m_prevtrig
= 0.f
;
1245 unit
->m_triggered
= false;
1246 unit
->m_tempbuf
= 0;
1249 void PV_BinScramble_Dtor(PV_BinScramble
* unit
)
1251 RTFree(unit
->mWorld
, unit
->m_to
);
1252 RTFree(unit
->mWorld
, unit
->m_tempbuf
);
1256 void PV_Conj_Ctor(PV_Unit
*unit
)
1258 SETCALC(PV_Conj_next
);
1262 void PV_Conj_next(PV_Unit
*unit
, int inNumSamples
)
1266 SCComplexBuf
*p
= ToComplexApx(buf
);
1268 for (int i
=0; i
<numbins
; ++i
) {
1269 p
->bin
[i
].imag
= 0.f
- p
->bin
[i
].imag
;
1274 ////////////////////////////////////////////////////////////////////////////////////////////////////////
1276 #define DefinePVUnit(name) \
1277 (*ft->fDefineUnit)(#name, sizeof(PV_Unit), (UnitCtorFunc)&name##_Ctor, 0, 0);
1280 void initPV(InterfaceTable
*inTable
)
1282 DefinePVUnit(PV_MagAbove
);
1283 DefinePVUnit(PV_MagBelow
);
1284 DefinePVUnit(PV_MagClip
);
1285 DefinePVUnit(PV_MagMul
);
1286 DefinePVUnit(PV_MagDiv
);
1287 DefinePVUnit(PV_MagSquared
);
1288 DefinePVUnit(PV_MagNoise
);
1289 DefinePVUnit(PV_Copy
);
1290 DefinePVUnit(PV_CopyPhase
);
1291 DefinePVUnit(PV_PhaseShift
);
1292 DefinePVUnit(PV_PhaseShift90
);
1293 DefinePVUnit(PV_PhaseShift270
);
1294 DefinePVUnit(PV_Min
);
1295 DefinePVUnit(PV_Max
);
1296 DefinePVUnit(PV_Mul
);
1297 DefinePVUnit(PV_Div
);
1298 DefinePVUnit(PV_Add
);
1299 DefinePVUnit(PV_RectComb
);
1300 DefinePVUnit(PV_RectComb2
);
1301 DefinePVUnit(PV_BrickWall
);
1302 DefinePVUnit(PV_BinWipe
);
1303 DefinePVUnit(PV_LocalMax
);
1304 DefinePVUnit(PV_Conj
);
1306 DefineDtorUnit(PV_BinScramble
);
1307 DefineDtorUnit(PV_MagSmear
);
1308 DefineDtorUnit(PV_MagShift
);
1309 DefineDtorUnit(PV_BinShift
);
1310 DefineDtorUnit(PV_RandWipe
);
1311 DefineDtorUnit(PV_Diffuser
);
1312 DefineDtorUnit(PV_RandComb
);
1313 DefineDtorUnit(PV_MagFreeze
);