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

);