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
)
::
|