198 lines
16 KiB
HTML
198 lines
16 KiB
HTML
|
<!doctype html><html lang='en'><head><title>PV_ChainUGen | SuperCollider 3.9.3 Help</title>
|
||
|
<link rel='stylesheet' href='./../scdoc.css' type='text/css' />
|
||
|
<link rel='stylesheet' href='./../frontend.css' type='text/css' />
|
||
|
<link rel='stylesheet' href='./../custom.css' type='text/css' />
|
||
|
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
|
||
|
<script>
|
||
|
var helpRoot = './..';
|
||
|
var scdoc_title = 'PV_ChainUGen';
|
||
|
var scdoc_sc_version = '3.9.3';
|
||
|
</script>
|
||
|
<script src='./../scdoc.js' type='text/javascript'></script>
|
||
|
<script src='./../docmap.js' type='text/javascript'></script>
|
||
|
<script src='./../prettify.js' type='text/javascript'></script>
|
||
|
<script src='./../lang-sc.js' type='text/javascript'></script>
|
||
|
</head>
|
||
|
<body onload='fixTOC();prettyPrint()'>
|
||
|
<div id='toc'>
|
||
|
<div id='toctitle'>PV_ChainUGen:</div>
|
||
|
<span class='toc_search'>Filter: <input id='toc_search'></span><ul class='toc'><li class='toc1'><a href='#description'>Description</a></li>
|
||
|
<ul class='toc'></ul><li class='toc1'><a href='#classmethods'>Class methods</a></li>
|
||
|
<ul class='toc'><li class='toc2'><a href='#Inherited%20class%20methods'>Inherited class methods</a></li>
|
||
|
</ul><li class='toc1'><a href='#instancemethods'>Instance methods</a></li>
|
||
|
<ul class='toc'><li class='toc3'><a href='#-fftSize'>fftSize</a> </li>
|
||
|
<li class='toc3'><a href='#-pvcalc'>pvcalc</a> </li>
|
||
|
<li class='toc3'><a href='#-pvcalc2'>pvcalc2</a> </li>
|
||
|
<li class='toc3'><a href='#-pvcollect'>pvcollect</a> </li>
|
||
|
<li class='toc2'><a href='#Inherited%20instance%20methods'>Inherited instance methods</a></li>
|
||
|
</ul><li class='toc1'><a href='#examples'>Examples</a></li>
|
||
|
<ul class='toc'><li class='toc2'><a href='#pvcalc'>pvcalc</a></li>
|
||
|
<ul class='toc'></ul><li class='toc2'><a href='#pvcalc2'>pvcalc2</a></li>
|
||
|
<ul class='toc'></ul><li class='toc2'><a href='#pvcollect'>pvcollect</a></li>
|
||
|
<ul class='toc'></ul></ul></ul></div><div class='contents'>
|
||
|
<div id='menubar'></div>
|
||
|
<div class='header'>
|
||
|
<div id='label'>
|
||
|
<span id='folder'>Classes</span>
|
||
|
| <span id='categories'><a href='./../Browse.html#UGens'>UGens</a> > <a href='./../Browse.html#UGens>FFT'>FFT</a></span>
|
||
|
</div><h1>PV_ChainUGen<span id='superclasses'> : <a href="../Classes/WidthFirstUGen.html">WidthFirstUGen</a> : <a href="../Classes/UGen.html">UGen</a> : <a href="../Classes/AbstractFunction.html">AbstractFunction</a> : <a href="../Classes/Object.html">Object</a></span>
|
||
|
</h1>
|
||
|
<div id='summary'>Base class for UGens that operate on FFT chains</div>
|
||
|
</div>
|
||
|
<div class='subheader'>
|
||
|
<div id='filename'>Source: <a href='file:///Applications/SuperCollider.app/Contents/Resources/SCClassLibrary/Common/Audio/FFTUnpacking.sc' title='/Applications/SuperCollider.app/Contents/Resources/SCClassLibrary/Common/Audio/FFTUnpacking.sc'>FFTUnpacking.sc</a></div><div id='subclasses'>Subclasses: <a href="../Classes/FFT.html">FFT</a>, <a href="../Classes/FFTTrigger.html">FFTTrigger</a>, <a href="../Classes/PV_BinScramble.html">PV_BinScramble</a>, <a href="../Classes/PV_BinShift.html">PV_BinShift</a>, <span id='hiddensubclasses' style='display:none;'><a href="../Classes/PV_BinWipe.html">PV_BinWipe</a>, <a href="../Classes/PV_BrickWall.html">PV_BrickWall</a>, <a href="../Classes/PV_ConformalMap.html">PV_ConformalMap</a>, <a href="../Classes/PV_Diffuser.html">PV_Diffuser</a>, <a href="../Classes/PV_HainsworthFoote.html">PV_HainsworthFoote</a>, <a href="../Classes/PV_JensenAndersen.html">PV_JensenAndersen</a>, <a href="../Classes/PV_MagAbove.html">PV_MagAbove</a>, <a href="../Classes/PV_MagDiv.html">PV_MagDiv</a>, <a href="../Classes/PV_MagFreeze.html">PV_MagFreeze</a>, <a href="../Classes/PV_MagMul.html">PV_MagMul</a>, <a href="../Classes/PV_MagShift.html">PV_MagShift</a>, <a href="../Classes/PV_MagSmear.html">PV_MagSmear</a>, <a href="../Classes/PV_MagSquared.html">PV_MagSquared</a>, <a href="../Classes/PV_PhaseShift.html">PV_PhaseShift</a>, <a href="../Classes/PV_RandComb.html">PV_RandComb</a>, <a href="../Classes/PV_RandWipe.html">PV_RandWipe</a>, <a href="../Classes/PV_RectComb.html">PV_RectComb</a>, <a href="../Classes/PV_RectComb2.html">PV_RectComb2</a>, <a href="../Classes/PackFFT.html">PackFFT</a></span><a class='subclass_toggle' href='#' onclick='javascript:showAllSubclasses(this); return false'>… see all</a></div>
|
||
|
</div>
|
||
|
<h2><a class='anchor' name='description'>Description</a></h2>
|
||
|
|
||
|
<p><code class='code prettyprint lang-sc'>PV_ChainUGen</code> is an abstract class, not used directly, but only its subclasses are. It represents phase-vocoder UGens - i.e. UGens which apply some kind of transformation to the frequency-domain signal produced by <a href="./../Classes/FFT.html">FFT</a>.
|
||
|
<p>It encompasses all unit generators whose output is an FFT chain. This is why <a href="./../Classes/FFT.html">FFT</a> is in this group but <a href="./../Classes/IFFT.html">IFFT</a> is not - the IFFT ugen outputs ordinary time-domain audio.
|
||
|
<p>For more information on using these unit generators, see <a href="./../Guides/FFT-Overview.html">FFT Overview</a>.<h2><a class='anchor' name='classmethods'>Class Methods</a></h2>
|
||
|
<h3><a class='anchor' name='Inherited%20class%20methods'>Inherited class methods</a></h3>
|
||
|
<div id='inheritedclassmets'></div><h2><a class='anchor' name='instancemethods'>Instance Methods</a></h2>
|
||
|
<h3 class='method-code'><span class='method-prefix'>.</span><a class='method-name' name='-fftSize' href='./../Overviews/Methods.html#fftSize'>fftSize</a></h3>
|
||
|
<div class='method'>
|
||
|
<p>Returns the FFT chain buffer's size.<pre class='code prettyprint lang-sc'>(
|
||
|
{
|
||
|
var chain = FFT(LocalBuf(1024));
|
||
|
chain.fftSize.poll;
|
||
|
0.0
|
||
|
}.play;
|
||
|
)</pre>
|
||
|
</div><h3 class='method-code'><span class='method-prefix'>.</span><a class='method-name' name='-pvcalc' href='./../Overviews/Methods.html#pvcalc'>pvcalc</a>(<span class='argstr'>numframes</span>, <span class='argstr'>func</span>, <span class='argstr'>frombin: 0</span>, <span class='argstr'>tobin</span>, <span class='argstr'>zeroothers: 0</span>)</h3>
|
||
|
<div class='method'>
|
||
|
<p>pvcalc applies a function to the frequency-domain data of an FFT chain. See <a href="#-pvcollect">-pvcollect</a> below for discussion of efficiency considerations. See also <a href="#-pvcalc2">-pvcalc2</a> below, and <a href="./../Classes/UnpackFFT.html">UnpackFFT</a>.<pre class='code prettyprint lang-sc'>chain = chain.pvcalc(numframes, func, frombin, tobin, zeroothers)</pre>
|
||
|
<h4>Arguments:</h4>
|
||
|
<table class='arguments'>
|
||
|
<tr><td class='argumentname'>numframes<td class='argumentdesc'>
|
||
|
<p>Number of FFT frames to process<tr><td class='argumentname'>func<td class='argumentdesc'>
|
||
|
<p>The function that takes two arrays as inputs (<code class='code prettyprint lang-sc'>magnitude</code>, and <code class='code prettyprint lang-sc'>phase</code>) and returns a resulting pair of arrays <code class='code prettyprint lang-sc'>[magnitude, phase]</code>.<pre class='code prettyprint lang-sc'>// example function
|
||
|
{ | magnitudes, phases |
|
||
|
[mags.reverse, phases.reverse] // e.g. upside-down spectrum
|
||
|
}</pre>
|
||
|
<tr><td class='argumentname'>frombin<td class='argumentdesc'>
|
||
|
<p>Range start (optional)<tr><td class='argumentname'>tobin<td class='argumentdesc'>
|
||
|
<p>Range end (optional)<tr><td class='argumentname'>zeroothers<td class='argumentdesc'>
|
||
|
<p>If set to 1 then bins outside of the range being processed are silenced.</table></div><h3 class='method-code'><span class='method-prefix'>.</span><a class='method-name' name='-pvcalc2' href='./../Overviews/Methods.html#pvcalc2'>pvcalc2</a>(<span class='argstr'>chain2</span>, <span class='argstr'>numframes</span>, <span class='argstr'>func</span>, <span class='argstr'>frombin: 0</span>, <span class='argstr'>tobin</span>, <span class='argstr'>zeroothers: 0</span>)</h3>
|
||
|
<div class='method'>
|
||
|
<p>The method pvcalc2 is just like <a href="#-pvcalc">-pvcalc</a> but can combine two FFT chains.<pre class='code prettyprint lang-sc'>chain = chain.pvcalc2(chain2, numframes, func, frombin, tobin, zeroothers)</pre>
|
||
|
<h4>Arguments:</h4>
|
||
|
<table class='arguments'>
|
||
|
<tr><td class='argumentname'>chain2<td class='argumentdesc'>
|
||
|
<p>The scond FFT chain.<tr><td class='argumentname'>numframes<td class='argumentdesc'>
|
||
|
<p>Number of FFT frames to process<tr><td class='argumentname'>func<td class='argumentdesc'>
|
||
|
<p>The function that takes four arrays as inputs (magnitudes1, phases1, magnitudes2, phases2) and returns a resulting pair of arrays <code class='code prettyprint lang-sc'>[magnitude, phase]</code>.<pre class='code prettyprint lang-sc'>// example function
|
||
|
{ | magnitudes1, phases1, magnitudes2, phases2 |
|
||
|
[magnitudes1, phases2] // e.g. use the magnitudes of one, ane the phases of the other
|
||
|
}</pre>
|
||
|
<tr><td class='argumentname'>frombin<td class='argumentdesc'>
|
||
|
<p>Range start (optional)<tr><td class='argumentname'>tobin<td class='argumentdesc'>
|
||
|
<p>Range end (optional)<tr><td class='argumentname'>zeroothers<td class='argumentdesc'>
|
||
|
<p>If set to 1 then bins outside of the range being processed are silenced.</table></div><h3 class='method-code'><span class='method-prefix'>.</span><a class='method-name' name='-pvcollect' href='./../Overviews/Methods.html#pvcollect'>pvcollect</a>(<span class='argstr'>numframes</span>, <span class='argstr'>func</span>, <span class='argstr'>frombin: 0</span>, <span class='argstr'>tobin</span>, <span class='argstr'>zeroothers: 0</span>)</h3>
|
||
|
<div class='method'>
|
||
|
<p>Process each bin of an FFT chain, separately, by applying a function to each bin of an FFT chain.<pre class='code prettyprint lang-sc'>chain = chain.pvcollect(numframes, func, frombin, tobin, zeroothers)</pre>
|
||
|
<h4>Arguments:</h4>
|
||
|
<table class='arguments'>
|
||
|
<tr><td class='argumentname'>numframes<td class='argumentdesc'>
|
||
|
<p>Number of FFT frames to process<tr><td class='argumentname'>func<td class='argumentdesc'>
|
||
|
<p>The function that processes each bin. It should be a function that takes <code class='code prettyprint lang-sc'>magnitude, phase, bin, index</code> as inputs and returns a resulting array <code class='code prettyprint lang-sc'>[magnitude, phase]</code>.<pre class='code prettyprint lang-sc'>// example function
|
||
|
{ | magnitude, phase, bin, index |
|
||
|
[mags.reverse, phases.reverse] // e.g. upside-down spectrum
|
||
|
}</pre>
|
||
|
|
||
|
<p>The <strong>bin</strong> is the integer bin number, starting at 0 for DC, while <strong>index</strong> is the iteration number, always starting with 0. You can optionally ignore the phase and only return a single (magnitude) value, in which case the phase is assumed to be left unchanged.<tr><td class='argumentname'>frombin<td class='argumentdesc'>
|
||
|
<p>Range start (optional)<tr><td class='argumentname'>tobin<td class='argumentdesc'>
|
||
|
<p>Range end (optional)<tr><td class='argumentname'>zeroothers<td class='argumentdesc'>
|
||
|
<p>If set to 1 then bins outside of the range being processed are silenced.</table><h4>Discussion:</h4>
|
||
|
|
||
|
<p>Note that this procedure can be relatively CPU-heavy, depending on how you use it. Using pvcollect (or its components, UnpackFFT & PackFFT) is usually less efficient than using a single "PV_" unit generator to process an FFT chain, because it involves the creation of quite a large graph of demand-rate unit generators.
|
||
|
<p>If you wish to reduce the CPU impact of using this approach, try the following:<ul>
|
||
|
<li>Use the frombin and tobin arguments to limit the number of FFT bins that will be included in the calculation. Often the lower FFT bins contain the loudest and/or most relevant information, so perhaps your effect sounds very similar if you ignore the higher-up bins (either leave them unprocessed, or discard them by setting the zeroothers argument to 1, which has the effect of a band-pass frequency-domain filter).<li>Use a smaller FFT buffer size.<li>Avoid creating ugens inside your calculation function if at all possible. For example, a deterministic ugen such as LFPar.kr(0.5, 0, 1) will be replicated once for each bin if specified inside the function, despite the fact that the output is always the same. Define it outside the calculation function and then reference it by variable name.<li>Avoid unused calculations! For example, uncommenting all the different lines in the above will waste effort because many values will be calculated but not used. This cannot be optimised away during compilation. It is particularly important because all calculations are duplicated (once for each bin) so can have a significant impact on efficiency.<li>If you find yourself calling pvcollect on an FFT chain more than once in series, you should definitely try to combine your processing into a single pvcollect function, to avoid unnecessary unpacking-then-packing-then-unpacking-then-packing.</ul>
|
||
|
</div><h3><a class='anchor' name='Inherited%20instance%20methods'>Inherited instance methods</a></h3>
|
||
|
<div id='inheritedinstmets'></div><h2><a class='anchor' name='examples'>Examples</a></h2>
|
||
|
<h3><a class='anchor' name='pvcalc'>pvcalc</a></h3>
|
||
|
<pre class='code prettyprint lang-sc'>// a sound file
|
||
|
c.free; c = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
|
||
|
|
||
|
(
|
||
|
{
|
||
|
var in, chain, v;
|
||
|
in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
|
||
|
chain = FFT(LocalBuf(1024), in);
|
||
|
|
||
|
chain = chain.pvcalc(1024, {|mags, phases|
|
||
|
//////// Try uncommenting each of these lines in turn and re-running the synth:
|
||
|
[mags * {1.5.rand}.dup(mags.size), phases + {pi.rand}.dup(phases.size)]; // Arbitrary filter, arbitrary phase shift
|
||
|
//[mags.reverse, phases.reverse]; // Upside-down!
|
||
|
//[mags.differentiate, phases.differentiate]; // Differentiate along frequency axis
|
||
|
//[mags[30..] ++ mags[..30], phases[30..] ++ phases[..30]]; // ".rotate" doesn't work directly, but this is equivalent
|
||
|
}, frombin: 0, tobin: 250, zeroothers: 0);
|
||
|
|
||
|
0.5 * IFFT(chain).dup
|
||
|
}.play
|
||
|
)</pre>
|
||
|
<h3><a class='anchor' name='pvcalc2'>pvcalc2</a></h3>
|
||
|
<pre class='code prettyprint lang-sc'>c.free; c = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
|
||
|
|
||
|
(
|
||
|
x = {
|
||
|
var fftsize = 1024;
|
||
|
var in, chain, in2, chain2, out;
|
||
|
in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
|
||
|
chain = FFT(LocalBuf(fftsize), in);
|
||
|
|
||
|
// JMcC babbling brook
|
||
|
in2 = ({
|
||
|
RHPF.ar(OnePole.ar(BrownNoise.ar, 0.99), LPF.ar(BrownNoise.ar, 14)
|
||
|
* 400 + 500, 0.03, 0.003) }!2)
|
||
|
+ ({ RHPF.ar(OnePole.ar(BrownNoise.ar, 0.99), LPF.ar(BrownNoise.ar, 20)
|
||
|
* 800 + 1000, 0.03, 0.005) }!2
|
||
|
) * 4;
|
||
|
chain2 = FFT(LocalBuf(fftsize), in2);
|
||
|
|
||
|
chain = chain.pvcalc2(chain2, fftsize, { |mags, phases, mags2, phases2|
|
||
|
[
|
||
|
mags * mags2 / 10,
|
||
|
phases2 + phases
|
||
|
]
|
||
|
}, frombin: 0, tobin: 125, zeroothers: 0);
|
||
|
|
||
|
out = IFFT(chain);
|
||
|
0.5 * out.dup
|
||
|
}.play
|
||
|
)</pre>
|
||
|
<h3><a class='anchor' name='pvcollect'>pvcollect</a></h3>
|
||
|
<pre class='code prettyprint lang-sc'>c.free; c = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
|
||
|
|
||
|
|
||
|
(
|
||
|
{
|
||
|
var in, chain, v;
|
||
|
in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
|
||
|
chain = FFT(LocalBuf(1024), in);
|
||
|
|
||
|
v = LFPar.kr(0.5).range(0.1, 1);
|
||
|
|
||
|
chain = chain.pvcollect(1024, {|mag, phase, index|
|
||
|
|
||
|
//////// Try uncommenting each of these lines in turn and re-running the synth:
|
||
|
//mag;
|
||
|
//[mag, phase];
|
||
|
//[mag, phase] / 3;
|
||
|
//[mag, phase].sqrt;
|
||
|
//[mag, 3.14.rand];
|
||
|
//[mag, LFNoise0.kr.range(0, 3.14)];
|
||
|
//[mag * Dseq([1, 0, 0, 1, 1, 0, 1, 0].stutter(8), 999999999999)]; // Can even use Demand ugens! One val demanded each frame
|
||
|
//[mag.sqrt, 3.14.rand];
|
||
|
//if(index % 7 == 0, mag, 0); // Comb filter
|
||
|
//if(LFNoise0.kr(10) > 0.5, mag, 0);
|
||
|
//mag + DelayN.kr(mag, 1, v); // Spectral delay
|
||
|
|
||
|
if((index - LFPar.kr(0.1).range(2, 1024/20)).abs < 10, mag, 0); // Swept bandpass
|
||
|
|
||
|
}, frombin: 0, tobin: 250, zeroothers: 0);
|
||
|
|
||
|
0.5 * IFFT(chain).dup
|
||
|
}.play
|
||
|
)</pre>
|
||
|
|
||
|
<p><div class='doclink'>helpfile source: <a href='file:///Applications/SuperCollider.app/Contents/Resources/HelpSource/Classes/PV_ChainUGen.schelp'>/Applications/SuperCollider.app/Contents/Resources/HelpSource/Classes/PV_ChainUGen.schelp</a><br>link::Classes/PV_ChainUGen::<br></div></div></body></html>
|