WT_Transient Wavelet transient filter
WT_Transient(buffer, branchthreshold=0.5, prunethreshold=0.1, mode=0)
Masks out wavelet coefficients which aren't part of detected 'transient branches' following:
Laurent Daudet (2001) Transients modelling by pruned wavelet trees. ICMC 2001, Cuba.
Result is the transient part of a signal, with longer tonal/time-stable components removed (rationale is that sufficiently energetic coefficients at positions correlated across scales is a time-localized transient). Daudet recommends using Haar wavelet (D2) or Daubechies D4 for the analysis.
buffer - dwt buffer.
branchthreshold - Minimum detection threshold for a branch
prunethreshold - Minimum detection threshold for the first node from the top of a branch to avoid pruning
mode - Normal mode, multiplies coefficients by the transient branch mask, retaining only coefficients on transient branches. Mode 1, outputs the mask itself (1 on a transient branch, 0 otherwise).
s.boot;
(
b = Buffer.alloc(s,1024,1);
c = Buffer.read(s,"sounds/a11wlk01.wav");
)
(
SynthDef("help-Transient", { arg out=0, bufnum=0, soundBufnum=2;
var in, chain;
in = PlayBuf.ar(1, soundBufnum, BufRateScale.kr(soundBufnum), loop: 1);
chain = DWT(bufnum, in, wavelettype:0);
chain = WT_Transient(chain, MouseX.kr(0.0,2.0),MouseY.kr(0.0,0.05));
Out.ar(out, IDWT(chain).dup);
}).play(s,[\out, 0, \bufnum, b, \soundBufnum, c]);
)
//with SoundIn
(
SynthDef("help-Transient", { arg out=0, bufnum=0, soundBufnum=2;
var in, chain;
in = SoundIn.ar;
chain = DWT(bufnum, in, wavelettype:18);
chain = WT_Transient(chain, MouseX.kr(0.0,1.0),MouseY.kr(0.0,0.01));
Out.ar(out, IDWT(chain).dup);
}).play(s,[\out, 0, \bufnum, b, \soundBufnum, c]);
)
(
SynthDef("help-Transient", { arg out=0, bufnum=0, soundBufnum=2;
var in, chain;
var residual;
var delaylength = 0.0217813; //(1024-64)/44100 //1024.0/SampleRate.ir + ControlDur.ir;
var transientresynthesis;
delaylength.poll;
in = PlayBuf.ar(1, soundBufnum, BufRateScale.kr(soundBufnum), loop: 1);
chain = DWT(bufnum, in);
chain = WT_Transient(chain,MouseX.kr(0.0,3.0),MouseY.kr(0.0,0.1));
transientresynthesis = IDWT(chain);
residual = DelayN.ar(in,delaylength,delaylength) - transientresynthesis;
Out.ar(out, residual.dup);
}).play(s,[\out, 0, \bufnum, b, \soundBufnum, c]);
)
b.free; c.free;
//as preprocessing for onset detection (related to its use in Bello et al (2005) A Tutorial on Onset Detection Signals, IEEE Transactions on Speech and Audio Processing
(
SynthDef("help-Transient", { arg out=0, bufnum=0, soundBufnum=2;
var in, chain,onset;
in = PlayBuf.ar(1, soundBufnum, BufRateScale.kr(soundBufnum), loop: 1);
chain = DWT(bufnum, in);
chain = WT_Transient(chain,MouseY.kr(0.0,2.0),0.001);
onset = WT_Onset.kr(chain, MouseX.kr(0.0,0.1));
Out.ar(out, [in,SinOsc.ar(440,0,0.1*Trig1.ar(onset,0.05))]);
}).play(s,[\out, 0, \bufnum, b, \soundBufnum, c]);
)
(
{
var in, chain;
in = PlayBuf.ar(1, c, BufRateScale.kr(c), loop: 1);
chain = DWT(b, in);
chain = WT_Transient(chain,0.01,0.0005);
WT_Onset.kr(chain, rawodf:1)*20.0;
}.plot(1.0)
)
//feature; detecting total 'transientness' by summing all transient coefficient moduli
(
SynthDef("help-Transient", { arg out=0, bufnum=0, soundBufnum=2;
var in, chain,transient, transientmeasure, sound;
in = PlayBuf.ar(1, soundBufnum, BufRateScale.kr(soundBufnum), loop: 1);
chain = DWT(bufnum, in, wavelettype:2);
chain = WT_Transient(chain, MouseX.kr(0.0,3.0),MouseY.kr(0.0,0.5));
transientmeasure = WT_ModulusSum.kr(chain);
transientmeasure.poll(100);
sound = Mix(Saw.ar([100+transientmeasure,220,440],0.3)*((transientmeasure/100.0).min(1.0).lag(0.05)));
Out.ar(out,[in,sound]);
}).play(s,[\out, 0, \bufnum, b, \soundBufnum, c]);
)
//cross synthesis via transient mask
(
{
var inA, chainA, inB, chainB, chain ;
inA = PlayBuf.ar(c,1,loop:1);
inB = Pulse.ar(LFNoise1.kr(2).exprange(10, 1000));
//inB = SoundIn.ar;
chainA = DWT(LocalBuf(2048), inA);
chainB = DWT(LocalBuf(2048), inB);
chainA = WT_Transient(chainA, MouseX.kr(0.0,3.0),MouseY.kr(0.0,0.5),mode:1); //get transient mask
chain = WT_Mul(chainA, chainB); //use on other sound direct (could also use mode 0, for more gradual multiply)
[inA, 0.2 *IDWT(chain)];
}.play
);