DWT Discrete Wavelet Transform


Inherits from: Object : AbstractFunction : UGen



DWT.new(buffer, input, hop, wintype, active, winsize, wavelettype)


The wavelet transform analyzes the input signal with respect to a mother wavelet at a number of scales. 


buffer - The buffer where a frame will be held. Its size must be a power of two. LocalBuf is useful here, because processes should not share data between synths. 


input - the audio signal to be analyzed


hop - the amount of offset from one analysis frame to the next, measured in multiples of the analysis frame size. This can range between zero and one, and the default is 0.5 (meaning each frame has a 50% overlap with the preceding/following frames).

wintype - defines how the data is windowed:

-1 is for rectangular windowing, simple but typically not recommended; 

0 (the default) is for Sine windowing, typically recommended for work where the signal is eventually re-constructed; 

1 is for Hann windowing, typically recommended for analysis work.

active - is a simple control allowing analysis to be active (>0) or inactive (<=0). This is mainly useful for signal analysis processes which are only intended to analyse at specific times rather than continuously. NOT CURRENTLY IMPLEMENTED.

winsize - the windowed audio frames are usually the same size as the buffer. If you wish the DWT to be zero-padded then you can specify a window size smaller than the actual buffer size (e.g. window size 1024 with buffer size 2048). Both values must still be a power of two. Leave this at its default of zero for no zero-padding.

wavelettype - The choices of wavelet are those available in the gsl wavelet library code (http://www.gnu.org/s/gsl/manual/html_node/DWT-Initialization.html). Each is given a numeric code as follows (see the web page for the explanation of k):

0-8 gsl_wavelet_daubechies, k = 4,6,8,10,12,14,16,18,20

9-17 gsl_wavelet_daubechies_centered, k = 4,6,8,10,12,14,16,18,20

18 gsl_wavelet_haar, k=2

19 gsl_wavelet_haar_centered, k=2

20-30 gsl_wavelet_bspline, k=103, 105, 202, 204, 206, 208, 301, 303, 305, 307, 309

31-41 gsl_wavelet_bspline_centered k=103, 105, 202, 204, 206, 208, 301, 303, 305, 307, 309





(

{ arg out=0;

var in, chain;

in = WhiteNoise.ar(0.05);

chain = DWT(LocalBuf(1024), in);

Out.ar(out, 

[IDWT(chain),in] // inverse DWT

);

}.play;

)




//no overlap, slight delays between left and right apparent due to processing delay, but reconstruction basically sound

(

{ arg out=0;

var in, chain;

in = SoundIn.ar; 

chain = DWT(LocalBuf(1024), in, 1.0, wavelettype:9);

Out.ar(out, 

[IDWT(chain),in] // inverse DWT

);

}.play;

)


//try to compensate

(

{ arg out=0;

var in, chain;

var delaytime = 1024.0/SampleRate.ir;

in = SoundIn.ar; 

chain = DWT( LocalBuf(1024), in, 1.0, wavelettype:20);

Out.ar(out, 

[IDWT(chain),DelayN.ar(in,delaytime,delaytime)] // inverse DWT

);

}.play;

)




//plot wavelet coefficients live

(

SynthDef("plotWaveletCoefficients", { arg out=0, buffer=0;

var in, chain;

in = SoundIn.ar; 

chain = DWT(buffer, in, 1.0, wavelettype:9);

}).add;

)



(

n = 1024; 

b= Buffer.alloc(s,n,1); 

)


(

var w;

var transformsize=n; //no more than this, using getn: can adapt with loadToFloatArray et al, see Buffer helpfile

var numscales = log2(transformsize); 

var width = transformsize.div(2); 

var dataarray = 0.0.dup(transformsize); 

var cellheight = 10; 


Synth(\plotWaveletCoefficients,[\buffer, b]);


w = Window("Wavelet coefficients",Rect(100,100,width,cellheight*numscales)).front;


w.view.background_(Color.white);

w.drawHook = {

numscales.do{|i|

var numatscale = 2**i; 

var widthperwaveletcoeff= width/numatscale; 

var y = i*cellheight; 

numatscale.do{|j|

var x = j*widthperwaveletcoeff;

var coeff = dataarray[numatscale+j];

// set the Color

Pen.color = Color.green((coeff+2.0)/4.0); //assumes coeffs in a particular range around -2 to 2

Pen.addRect(

Rect(x, y, widthperwaveletcoeff, cellheight); 

);

Pen.fill;

}


}

};


{


inf.do{


b.getn(0,transformsize,{|val| 


//val.postln;


dataarray = val; 


{w.refresh;}.defer;


});


(1024/(s.sampleRate)).wait;


}


}.fork; 

)




b.free;





//processing chain

(

{ var in, chain;

in = WhiteNoise.ar(0.2);

chain = DWT(LocalBuf(2048), in);

chain = WT_FilterScale(chain, MouseX.kr(-1.0,1.0)); 

chain = WT_MagAbove(chain, MouseY.kr(-0.5,0.5));

IDWT(chain).dup(2)

}.play;

)



//naughty: mix and match FFT and DWT! 

(

{ arg out=0;

var in, chain;

in = SoundIn.ar;

chain = DWT(LocalBuf(1024), in);

Out.ar(out, 

(10*IFFT(chain)).dup(2) // inverse DWT

);

}.play;

)



//naughty: other way around 

(

{ arg out=0;

var in, chain;

in = SoundIn.ar;

chain = FFT(LocalBuf(1024), in);

Out.ar(out, 

(0.05*IDWT(chain)).dup(2) // inverse DWT

);

}.play;

)