File: PV_Copy.schelp

package info (click to toggle)
supercollider 1%3A3.13.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 80,292 kB
  • sloc: cpp: 476,363; lisp: 84,680; ansic: 77,685; sh: 25,509; python: 7,909; makefile: 3,440; perl: 1,964; javascript: 974; xml: 826; java: 677; yacc: 314; lex: 175; objc: 152; ruby: 136
file content (168 lines) | stat: -rw-r--r-- 3,836 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
class:: PV_Copy
summary:: Copy an FFT buffer
categories:: UGens>FFT

description::

Copies the spectral frame in code::bufferA:: to code::bufferB::. This allows for parallel processing of spectral data without the need for multiple FFT UGens. Further it allows to extract data at a given point in the FFT chain e.g. for monitoring purposes. 

note::As of SC 3.7 instances of PV_Copy are added automatically where necessary for parallel processing. Please see link::Guides/FFT-Overview:: for the current implementation. 

This document is provided for legacy purposes only. Existing code explicitly using PV_Copy should continue to work.::

classmethods::
method:: new
argument:: bufferA
source buffer.
argument:: bufferB
destination buffer.

note:: 
code::bufferA:: and code::bufferB:: must be the same size.
::

examples::

code::

// read a sound file
d = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");


// crossfade between original and magmul-ed whitenoise
(
{
	var in, in2, chain, chainB, chainC;
	in = PlayBuf.ar(1, d, BufRateScale.kr(d), loop: 1) * 2;
	in2 = WhiteNoise.ar;
	chain = FFT(LocalBuf(2048), in);
	chainB = FFT(LocalBuf(2048), in2);
	chainC = PV_Copy(chain, LocalBuf(2048));
	chainB = PV_MagMul(chainB, chainC);
	XFade2.ar(IFFT(chain), IFFT(chainB) * 0.1, SinOsc.kr(0.2, 1.5pi));
}.play

)


// as previous but with Blip for 'vocoder' cross synthesis effect
(
{
	var in, in2, chain, chainB, chainC;
	in = PlayBuf.ar(1, d, BufRateScale.kr(d), loop: 1) * 2;
	in2 = Blip.ar(100, 50);
	chain = FFT(LocalBuf(2048), in);
	chainB = FFT(LocalBuf(2048), in2);
	chainC = PV_Copy(chain, LocalBuf(2048));
	chainB = PV_MagMul(chainB, chainC);
	XFade2.ar(IFFT(chain), IFFT(chainB) * 0.1, SinOsc.ar(0.2));
}.play

)



// Spectral 'pan'
(
{
	var in, chain, chainB, pan;
	in = PlayBuf.ar(1, d, BufRateScale.kr(d), loop: 1);
	chain = FFT(LocalBuf(2048), in);
	chainB = PV_Copy(chain, LocalBuf(2048));
	pan = MouseX.kr(0.001, 1.001, 'exponential') - 0.001;
	chain = PV_BrickWall(chain, pan);
	chainB = PV_BrickWall(chainB, -1 + pan);
	IFFT([chain, chainB])
}.play
)

// free sound file buffer
d.free;





// proof of concept: copy has identical data
// global buffers for plotting the data
(
b = Buffer.alloc(s, 2048, 1);
c = Buffer.alloc(s, 2048, 1);
)

//  silently record some FFT data into the buffers
(
x = {
	var inA, chainA, chainB;
    inA = LFClipNoise.ar(100);
    chainA = FFT(b, inA);
    chainB = PV_Copy(chainA, c);
    IFFT(chainA) - IFFT(chainB); // proof of concept: cancels to zero
}.play;
)
x.free;

// IFFTed frames contain the same windowed output data
(
b.plot(\b, Rect(200, 430, 700, 300));
c.plot(\c, Rect(200, 100, 700, 300));
)

// free the buffers
[b, c].do(_.free);



// Multiple Magnitude plots



(
~fftSize = 2048;
~allBuffers = ();
~copyToBuffer = { |chain, name|
	var buffer = Buffer.alloc(s, ~fftSize);
	~allBuffers.put(name, buffer);
	PV_Copy(chain, buffer)
};
)

(
x = { var in, chain, chainB, chainC;
	in = WhiteNoise.ar;
	chain = FFT(LocalBuf(~fftSize), in);
	chain = ~copyToBuffer.(chain, 'initial'); // initial spectrum
	chain = PV_RectComb(chain, 20, 0, 0.2);
	chain = ~copyToBuffer.(chain, 'After RectComb'); // after comb
	2.do { chain = PV_MagSquared(chain) };
	chain = ~copyToBuffer.(chain, 'After MagSquared'); // after magsquared
	0.00001 * Pan2.ar(IFFT(chain)); // silently play back
}.play
)


x.free;

// post all buffers
(
~allBuffers.keysValuesDo { |name, buffer, i|
	buffer.getToFloatArray(action: { arg array;
		var z, x;
		// Initially, data is in complex form
		z = array.clump(2).flop;
		z = z.collect { |each| Signal.newFrom(each) };
		x = Complex(z[0], z[1]);
		{ x.magnitude.plot(name, Rect(200, 100 + (230 * i), 700, 200)) }.defer
	});
}
)

 // free the buffers and clean up
(
~allBuffers.do { |x| x.free };
~allBuffers = nil;
~copyToBuffer = nil;
)

::