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 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
title:: jitlib_fading
summary:: Fade envelope generation and crossfading
categories:: Libraries>JITLib>Tutorials
related:: Overviews/JITLib
link::Classes/NodeProxy:: ( link::Classes/ProxySynthDef:: ) looks for inner envelopes in your definition function to find out whether a fade envelope is needed or not. In case there is no other inner possibility of freeing the synth, either
list::
## link::#a)_automatic_fade_envelope_generation#a):: a fade envelope is created (audio / control rate output)
## link::#b)_automatic_free_instead_of_crossfade#b):: the synth is freed directly with no fading (scalar output or doneAction 1)
## link::#c)_custom_fade_envelope#c):: if you provide a gate arg and a doneAction 2 to your ugenGraph function, this is supposed to be a fade envelope for the synth
## link::#d)_synthdef_name_assignment#d):: if a synthdef name is used, case link::#c)_custom_fade_envelope#c):: is supposed
::
... so in most cases, there is not much to worry about, just these two points ar important, if one wants to use a self releasing synth or a different out ugen:
list::
## link::#e)_own_free_responsibility#e):: own responsibility: if the function creates a ugengraph that can be freed by trigger or other things, it waits for this action instead of the node proxy freeing the synth.
## link::#f)_own_output_responsibility#f):: own out channel with 'out' arg: the control ugen with the name 'out' is set to the output channel number of the proxy.
::
code::
p = ProxySpace.push(s.boot);
~out.play;
// note that you can use this functionality also when using ProxySynthDef directly:
d = ProxySynthDef("test", { arg freq=440; SinOsc.ar(freq) }).send(s);
s.sendMsg("/s_new", "test", 1980, 1, 1, \freq, 340);
s.sendMsg("/n_set", 1980, \freq, 240);
s.sendMsg("/n_set", 1980, \fadeTime, 4);
s.sendMsg("/n_set", 1980, \gate, 0);
::
section::a) automatic fade envelope generation
code::
// no inner envelope and audio / control rate output
(
~out = { PinkNoise.ar([1,1]*0.1) };
)
(
~kout = { PinkNoise.kr([1,1]*0.1) };
)
::
section::b) automatic free instead of crossfade
code::
// inner envelope that cannot free the synth, the synth is freed when a new
// function is assigned.
(
~out = { arg t_trig; EnvGen.kr(Env.asr, t_trig) * PinkNoise.ar([1,1]) };
)
~out.group.set(\t_trig, 1);
(
~out = { arg t_trig; EnvGen.kr(Env.asr, t_trig) * SinOsc.ar([1,1]*400) };
)
~out.group.set(\t_trig, 1);
// for a scalar output also no fade env is created, but the synth is freed (without fading)
(
~out = { Out.ar(0, SinOsc.ar(Rand(440,550),0,0.2)) };
)
::
section::c) custom fade envelope
code::
// when a gate arg is provided, and the env can free the synth, this envelope
// is supposed to be the fade envelope for the synth: no extra fade env is created.
(
~out = { arg gate=1; EnvGen.kr(Env.asr, gate, doneAction:2) * 0.2 * SinOsc.ar([1,1]*Rand(440,550)) };
)
::
section::d) SynthDef name assignment
code::
// if a symbol is used as input, the defname of a def on the server is supposed
// to represent a SynthDef that has a gate, an out input and can free itself.
(
~out = \default;
)
// this is the minimal requirement arguments for such a use (similar to Pbind)
(
SynthDef("test", { arg gate=1, out;
Out.ar(out, Formant.ar(300, 200, 10) * EnvGen.kr(Env.asr, gate, doneAction:2))
}).send(s);
)
// you can also provide a fadeTime arg, whic is set by the proxy:
(
SynthDef("test", { arg gate=1, out, fadeTime=1;
Out.ar(out,
Formant.ar(Rand(20,40), 600, 10, 0.2)
* EnvGen.kr(Env.asr(fadeTime,1,fadeTime), gate, doneAction:2)
)
}).send(s);
)
~out = \test;
~out.fadeTime = 3;
::
note::
the strong::number of channels:: is your own responsibility when using symbols, as a symbol carries no channel information! (in all other cases the number of channels is wrapped or expanded to fit the proxy)
::
code::
// if the synthdef has a fixed duration envelope, there is a FAILURE /n_set Node not found message.
// with no further significance
(
SynthDef("test", { arg gate=1, out;
Out.ar(out,
Formant.ar(Rand(20,40), 600, 10, 0.6)
* EnvGen.kr(Env.perc, gate, doneAction:2)
)
}).send(s);
)
~out = \test;
::
section::e) own free responsibility
code::
//inner envelope that can free the synth, no extra fade env is created:
(
~out = { arg t_trig; EnvGen.kr(Env.asr, t_trig, doneAction:2) * PinkNoise.ar([1,1]) };
)
~out.group.set(\t_trig, 1); //end it
~out.send; //start a new synth
~out.group.set(\t_trig, 1); //end it again
// if there is a ugen that can free the synth, no extra fade env is created either,
// but it supposes the synth frees itself, so if a new function is assigned it does
// not get freed.
(
~out = { arg t_trig;
FreeSelf.kr(t_trig);
PinkNoise.ar([1,1]*0.3);
};
)
~out.group.set(\t_trig, 1);
::
section::f) own output responsibility
code::
// the arg name 'out' can be used to output through the right channel.
// of course with this one can get problems due to a wrong number of channels
// or deliberate hacks.
//left speaker
(
~out = { arg out;
OffsetOut.ar(out, Impulse.ar(10,0,0.1))
}
)
//both speakers
(
~out = { arg out;
OffsetOut.ar(out, Impulse.ar([10, 10],0,0.1))
}
)
//this plays out into another adjacent bus: this is a possible source of confusion.
(
~out = { arg out;
OffsetOut.ar(out, Impulse.ar([10, 10, 10],0,0.1))
}
)
::
|