File: UnpackFFT.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 (79 lines) | stat: -rw-r--r-- 2,720 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
class:: UnpackFFT
summary:: Unpack an FFT chain into separate demand-rate FFT bin streams
categories:: UGens>FFT, UGens>Demand
related:: Classes/PackFFT, Classes/Unpack1FFT

description::
Takes an FFT chain and separates the magnitude and phase data into separate demand-rate streams, for arithmetic manipulation etc.

This is technically a demand-rate UGen. The actual "demand" is usually created by PackFFT later on in the graph, which requests the values in order to re-pack the data. This allows for processing to occur in between.

See also link::Classes/PV_ChainUGen#-pvcollect::, link::Classes/PV_ChainUGen#-pvcalc::, and link::Classes/PV_ChainUGen#-pvcalc2::, which provide convenient ways to process audio in the frequency domain. The help for pvcollect includes notes on efficiency considerations.

classmethods::
private:: categories

method:: new
argument:: chain
FFT chain
argument:: bufsize
FFT buffer size
argument:: frombin
limiting analysis to the bins of interest
argument:: tobin
limiting analysis to the bins of interest
returns::
A list from DC up to Nyquist of code:: [mag[0], phase[0], mag[1], phase[1], ... mag[nyquist], phase[nyquist]]. ::
discussion::
Note that you do have to decide your FFT buffer size in advance, since this determines how many values the UGen will output.
code::
#magsphases = UnpackFFT(chain, bufsize)
::

examples::
code::

// This one just drags out various the values and posts them - a little bit pointless!
(
{
	var sig, chain, stream, windowStarts, fftSize;
	fftSize = 1024;

	sig = SinOsc.ar(LFDNoise3.kr(LFNoise0.kr(1) * 40 + 60) * 700 + 800);
	chain = FFT(LocalBuf(1, fftSize), sig);

	// a window start is indicated by a signal leaving the -1 bottom line
	windowStarts = chain > -1;

	// Using the frombin & tobin args makes it much more efficient, limiting analysis to the bins of interest
	stream = UnpackFFT(chain, fftSize, frombin: 0, tobin: 4);

	// Demand some data from the unpacker.
	// NOTE: At present, Demand.kr is unable to handle more than 32 inputs,
	// so using frombin & tobin to limit the number of bins is compulsory.

	Demand.kr(windowStarts, 0, stream).collect { |anunp, index|
		var label = if(index.even) { "Magnitude" } { "Phase" };
		label = label + (index / 2).floor;
		anunp.poll(windowStarts, label)
	};

	sig * 0.05
}.play
)

// simple frequency-domain manipulation, square-rooting the magnitudes AND phases.
(
x = {
	var sig, chain, magsphases, b;
	b = LocalBuf(1, 1024);
	sig = SinOsc.ar(LFDNoise3.kr(LFNoise0.kr(1) * 40 + 60) * 700 + 800);
	chain = FFT(b, sig);
	magsphases = UnpackFFT(chain, b.numFrames);
	magsphases = magsphases.collect(_.sqrt);
	chain = PackFFT(chain, b.numFrames, magsphases);
	IFFT(chain) * 0.1
}.play
)
::