annotate ext/kissfft/test/fastfir.py @ 409:1f1999b0f577

Bring in kissfft into this repo (formerly a subrepo, but the remote is not responding)
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 21 Jul 2015 07:34:15 +0100
parents
children
rev   line source
c@409 1 #!/usr/bin/env python
c@409 2
c@409 3 from Numeric import *
c@409 4 from FFT import *
c@409 5
c@409 6 def make_random(len):
c@409 7 import random
c@409 8 res=[]
c@409 9 for i in range(int(len)):
c@409 10 r=random.uniform(-1,1)
c@409 11 i=random.uniform(-1,1)
c@409 12 res.append( complex(r,i) )
c@409 13 return res
c@409 14
c@409 15 def slowfilter(sig,h):
c@409 16 translen = len(h)-1
c@409 17 return convolve(sig,h)[translen:-translen]
c@409 18
c@409 19 def nextpow2(x):
c@409 20 return 2 ** math.ceil(math.log(x)/math.log(2))
c@409 21
c@409 22 def fastfilter(sig,h,nfft=None):
c@409 23 if nfft is None:
c@409 24 nfft = int( nextpow2( 2*len(h) ) )
c@409 25 H = fft( h , nfft )
c@409 26 scraplen = len(h)-1
c@409 27 keeplen = nfft-scraplen
c@409 28 res=[]
c@409 29 isdone = 0
c@409 30 lastidx = nfft
c@409 31 idx0 = 0
c@409 32 while not isdone:
c@409 33 idx1 = idx0 + nfft
c@409 34 if idx1 >= len(sig):
c@409 35 idx1 = len(sig)
c@409 36 lastidx = idx1-idx0
c@409 37 if lastidx <= scraplen:
c@409 38 break
c@409 39 isdone = 1
c@409 40 Fss = fft(sig[idx0:idx1],nfft)
c@409 41 fm = Fss * H
c@409 42 m = inverse_fft(fm)
c@409 43 res.append( m[scraplen:lastidx] )
c@409 44 idx0 += keeplen
c@409 45 return concatenate( res )
c@409 46
c@409 47 def main():
c@409 48 import sys
c@409 49 from getopt import getopt
c@409 50 opts,args = getopt(sys.argv[1:],'rn:l:')
c@409 51 opts=dict(opts)
c@409 52
c@409 53 siglen = int(opts.get('-l',1e4 ) )
c@409 54 hlen =50
c@409 55
c@409 56 nfft = int(opts.get('-n',128) )
c@409 57 usereal = opts.has_key('-r')
c@409 58
c@409 59 print 'nfft=%d'%nfft
c@409 60 # make a signal
c@409 61 sig = make_random( siglen )
c@409 62 # make an impulse response
c@409 63 h = make_random( hlen )
c@409 64 #h=[1]*2+[0]*3
c@409 65 if usereal:
c@409 66 sig=[c.real for c in sig]
c@409 67 h=[c.real for c in h]
c@409 68
c@409 69 # perform MAC filtering
c@409 70 yslow = slowfilter(sig,h)
c@409 71 #print '<YSLOW>',yslow,'</YSLOW>'
c@409 72 #yfast = fastfilter(sig,h,nfft)
c@409 73 yfast = utilfastfilter(sig,h,nfft,usereal)
c@409 74 #print yfast
c@409 75 print 'len(yslow)=%d'%len(yslow)
c@409 76 print 'len(yfast)=%d'%len(yfast)
c@409 77 diff = yslow-yfast
c@409 78 snr = 10*log10( abs( vdot(yslow,yslow) / vdot(diff,diff) ) )
c@409 79 print 'snr=%s' % snr
c@409 80 if snr < 10.0:
c@409 81 print 'h=',h
c@409 82 print 'sig=',sig[:5],'...'
c@409 83 print 'yslow=',yslow[:5],'...'
c@409 84 print 'yfast=',yfast[:5],'...'
c@409 85
c@409 86 def utilfastfilter(sig,h,nfft,usereal):
c@409 87 import compfft
c@409 88 import os
c@409 89 open( 'sig.dat','w').write( compfft.dopack(sig,'f',not usereal) )
c@409 90 open( 'h.dat','w').write( compfft.dopack(h,'f',not usereal) )
c@409 91 if usereal:
c@409 92 util = './fastconvr'
c@409 93 else:
c@409 94 util = './fastconv'
c@409 95 cmd = 'time %s -n %d -i sig.dat -h h.dat -o out.dat' % (util, nfft)
c@409 96 print cmd
c@409 97 ec = os.system(cmd)
c@409 98 print 'exited->',ec
c@409 99 return compfft.dounpack(open('out.dat').read(),'f',not usereal)
c@409 100
c@409 101 if __name__ == "__main__":
c@409 102 main()