[R] Filter design in R?

Martin Maechler maechler at stat.math.ethz.ch
Fri Oct 21 11:33:03 CEST 2005


>>>>> "tom" == tom wright <tom at maladmin.com>
>>>>>     on Thu, 20 Oct 2005 09:26:05 -0400 writes:

    tom> On Wed, 2005-19-10 at 17:49 -0400, Israel Christie wrote:
    >> Dr. Williams,
    >> I ran across your inquiry on one of the R-help mailing lists regarding 
    >> digital filter design and implementation. I found no response to your 
    >> email in the archives and was wondering if you were able to find anything.
    >> 
    >> Thanks,
    >> Israel

    tom> I'm not Dr Williams, but I've been doing some work on filter design
    tom> recently. I'm also no expert in this area but I found some very useful
    tom> resources, primarily the online book "The scientist and engineers guide
    tom> to digital signal processing" http://www.dspguide.com

    tom> I came up with some code for generating simple highpass; low pass and
    tom> bandpass filters, the filters can be applied using the filter() function


    tom> Since I'm no expert here I'd really appreciate any comment from people
    tom> who know more than me about these techniques.

I'm neither Dr. Williams nor an expert in the ("engineer point of
view on") filter design.

Note however that R (in 'stats') , additionally to filter() 
has a function  kernel()  which is used to build some common
(non-recursive) filters and produce objects of (S3) class
"tskernel".
These were primarily designed for use in spectrum(), but should
be more generally useful, and could serve as an initial role
model for extention.

The "real" source is in
https://svn.R-project.org/R/trunk/src/library/stats/R/kernel.R

Martin Maechler

    tom> Regards
    tom> Tom

    >> ================== BEGIN USAGE CODE==================
    >> t<-c(1:1000)/1000     #timeline 1KHz
    >> s1<-sin(2*pi*t*3)     #3Hz waveform
    >> s2<-sin(2*pi*t*5)     #5Hz waveform
    >> s3<-sin(2*pi*t*10)    #10Hz waveform
    >> 
    >> stot<-s1+s2+s3                #complex waveform
    >> 
    >> plot(stot,type='l')
    >> 
    >> #create the filter, the longer it is the better cutoff
    >> #length must be an even number
    >> f<-calcbpfilt(length=900,samplerate=1000,lowfreq=7,highfreq=4) 
    >> 
    >> sfilt<-filter(stot,f,circular=TRUE)   #apply the filter
    >> 
    >> lines(sfilt,type='l',col='red')               
    >> #only the 5Hz freq should be let through
    >> 
    >> ================== END USAGE CODE==================
    tom> ==============BEGIN CODE=================
    tom> calclpfilt<-function(length,fc){
    
    tom> t<-c(0:length+1)
    tom> for (val in t){
    tom> if(val-length/2==0){
    tom> f[val]<-as.numeric(2*pi*fc)
    tom> }else{

    tom> f[val]<-as.numeric(sin(2*pi*fc*(val-length/2))/(val-length/2))
    tom> }
    tom> f[val]=as.numeric(f[val])*(0.54-0.46*cos(2*pi*val/length))
    tom> }
    tom> #f<-convolve(f,f)
    tom> #normalise filter

    tom> filt.total<-sum(as.numeric(f))
    tom> f<-as.numeric(f)/filt.total
    tom> }

    tom> calcbpfilt<-function(length,samplerate,lowfreq,highfreq){
    tom> f.low<-list()
    tom> f.high<-list()

    tom> fc.low<-1/(samplerate/lowfreq)
    tom> fc.high<-1/(samplerate/highfreq)

    tom> t<-c(0:length+1)

    tom> #calculate the lowpass filter
    tom> for (val in t){
    tom> if(val-length/2==0){
    tom> f.low[val]<-as.numeric(2*pi*fc.low)
    tom> }else{

    tom> f.low[val]<-as.numeric(sin(2*pi*fc.low*(val-length/2))/(val-length/2))
    tom> }

    tom> f.low[val]=as.numeric(f.low[val])*(0.54-0.46*cos(2*pi*val/length))
    tom> }
    tom> #f<-convolve(f,f)
    tom> #normalise filter

    tom> filt.total<-sum(as.numeric(f.low))
    tom> f.low<-as.numeric(f.low)/filt.total

    tom> #calculate the second filter
    tom> for (val in t){
    tom> if(val-length/2==0){
    tom> f.high[val]<-as.numeric(2*pi*fc.high)
    tom> }else{

    tom> f.high[val]<-as.numeric(sin(2*pi*fc.high*(val-length/2))/(val-length/2))
    tom> }

    tom> f.high[val]=as.numeric(f.high[val])*(0.54-0.46*cos(2*pi*val/length))
    tom> }
    tom> #f<-convolve(f,f)
    tom> #normalise filter

    tom> filt.total<-sum(as.numeric(f.high))
    tom> f.high<-as.numeric(f.high)/filt.total

    tom> #invert the high filter to make it high pass

    tom> f.high<-0-f.high
    tom> f.high[length/2]<-f.high[length/2]+1

    tom> #add lowpass filterkernal and highpass filter kernel
    tom> #makes band reject filter
    tom> f.bandreject<-f.low+f.high

    tom> #make band pass by spectral inversion
    tom> f.bandpass<-0-f.bandreject
    tom> f.bandpass[length/2]<-f.bandpass[length/2]+1
    tom> f.bandpass
    tom> }
    tom> ==============END CODE=================




More information about the R-help mailing list