diff trunk/matlab/bmm/carfac/Carfac.py @ 706:f8e90b5d85fd tip

Delete CARFAC code from this repository. It has been moved to https://github.com/google/carfac Please email me with your github username to get access. I've also created a new mailing list to discuss CARFAC development: https://groups.google.com/forum/#!forum/carfac-dev
author ronw@google.com
date Thu, 18 Jul 2013 20:56:51 +0000
parents be2b68ced23d
children
line wrap: on
line diff
--- a/trunk/matlab/bmm/carfac/Carfac.py	Tue Jul 16 19:56:16 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +0,0 @@
-# Carfac.py - Cochlear filter model based on Dick Lyons work.  This material taken from his Hearing book (to be published)
-# Author: Al Strelzoff: strelz@mit.edu
-
-# The point of this file is to extract some of the formulas from the book and practice with them so as to better understand the filters.
-# The file has been written and tested for python 2.7
-
-from numpy import cos, sin, pi, e, real,imag,arctan2,log10
-
-
-from pylab import figure, plot,loglog, title, axis, show
-
-fs = 22050.0            # sampling rate
-
-
-# given a frequency f, return the ERB
-def ERB_Hz(f):
-#    Ref: Glasberg and Moore: Hearing Research, 47 (1990), 103-138
-    return 24.7 * (1.0 + 4.37 * f / 1000.0)
-
-
-# ERB parameters
-ERB_Q = 1000.0/(24.7*4.37)  # 9.2645
-ERB_break_freq = 1000/4.37  # 228.833
-
-ERB_per_step = 0.3333        
-
-# set up channels
-
-first_pole_theta = .78 * pi # We start at the top frequency.
-pole_Hz = first_pole_theta * fs / (2.0*pi)  # frequency of top pole
-min_pole_Hz = 40.0    # bottom frequency
-
-# set up the pole frequencies according to the above parameters
-pole_freqs = []     # empty list of pole frequencies to fill, zeroth will be the top
-while pole_Hz >  min_pole_Hz:
-    pole_Hz = pole_Hz - ERB_per_step * ERB_Hz(pole_Hz)
-    pole_freqs.append(pole_Hz)
-    
-n_ch = len(pole_freqs)      # n_ch is the number of channels or frequency steps
-print('num channels',n_ch)
-
-# Now we have n_ch, the number of channels, so can make the array of filters by instantiating the filter class (see below)
-
-# before we make the filters, let's plot the position of the frequencies and the values of ERB at each.
-
-fscale = []
-erbs = []
-
-figure(1)
-for i in range(n_ch):
-    
-    f = pole_freqs[i]        # the frequencies from the list
-    ERB = ERB_Hz(f)       # the ERB value at each frequency
-    fscale.append(f)
-    erbs.append(ERB)
-    
-# plot a verticle hash at each frequency:
-    u = []
-    v = []
-    for j in range(5):
-        u.append(f)
-        v.append(10.0 + float(j))
-
-    plot(u,v)  
-    
-loglog(fscale,erbs)
-
-title('ERB scale')
-
-
-
-# This filter class includes some methods useful only in design.  They will not be used in run time implementation.
-#  From figure 14.3 in Dick Lyon's book.
-#  When translating to C++, this class will become a struct, and all the methods will be moved outside.
-
-
-#########################################################The Carfac filter class#################################################################################
-
-# fixed parameters
-min_zeta = 0.12
-
-class carfac():
-    
-    
-    # instantiate the class (in C++, the constructor)
-    def __init__(self,f):
-        
-        self.frequency = f
-       
-        theta = 2.0 * pi * f/fs
-        r =  1.0 - sin(theta) * min_zeta
-        a = r * cos(theta)
-        c = r * sin(theta)
-        h = sin(theta)
-        g = (1.0 - 2.0 * a + r ** 2)/(1.0 - 2.0 * a + h * c + r ** 2)
-      
-       
-        
-        self.gh = g*h       # no need to repeat in real time
-        
-        # make all parameters properties of the class 
-        self.a = a
-        self.c = c
-        self.r = r
-        self.theta = theta
-        self.h = h
-        self.g = g
-        
-        
-        # the two storage elements.  Referring to diagram 14.3 on p.263, z2 is the upper storage register, z1, the lower
-        self.z1 = 0.0    
-        self.z2 = 0.0    
-      
-        
-        # frequency response of this filter
-        self.H = []
-        
-       
-        
-        # the total  frequency magnitude of this filter including all the filters in front of this one
-        self.HT = []       # this list will be filled by multiplying all the H's ahead of it together with its own (H)
-        
-        
-    
-    # execute one clock tick.  Take in one input and output one result. Execution semantics taken from fig. 14.3
-    #  This execution model is not tested in this file.  Here for reference.  See the file Exec.py for testing this execution model.  This is the main run time method.
-    def input(self,X):
-
-        # recover the class definitions of these variables.  These statements below take up zero time at execution since they are just compiler declarations.
-        # computation below is organized as some loads, followed by 3 2x2 multiply accumulates
-        #  Note: this function is not exercised in this file and is here only for reference
-        
-        a = self.a
-        c = self.c
-        g = self.g
-        gh = self.gh
-        z1 = self.z1                    # z1 is the lower storage in fig. 14.3
-        z2 = self.z2
-        
-        # calculate what the next value of z1 will be, but don't overwrite current value yet.   
-        next_z1 = (a * z1) + (c * z2)   # Note:  it is a 2 element multiply accumulate. compute first so as not to have to do twice.
-        # the output Y
-        Y = g * X + gh * next_z1       # Note: organized as a 2 element multiply accumulate.
-        
-        #stores
-        self.z2 = X + (a * z2) - (c * z1)        #Note: this is a 2 element multiply accumulate
-        self.z1 = next_z1
-        
-        return Y                        # The output
-    
-    # complex frequency response of this filter at frequency w.  That is, what it contributes to the cascade
-    # this method is used for test only.  It finds the frequency magnitude.  Not included in run time filter class.
-    def Hw(self,w):
-
-        a = self.a
-        c = self.c
-        g = self.g
-        h = self.h
-        r = self.r
-        z = e ** (complex(0,w))         # w is in radians so this is z = exp(jw)
-        return g * (1.0 + (h*c*z)/(z**2 - 2.0*a*z + r**2 ))      
-        
-    
-    
-######################################################End of Carfac filter class########################################################################
-
-
-# instantiate the filters
-
-# n_ch is the number of filters as determined above
-
-Filters = []    # the list of all filters, the zeroth is the top frequency
-for i in range(n_ch):
-    f = pole_freqs[i]
-    filter = carfac(f)  # note: get the correct parameters for r and h from Dick's matlab script.  Load them here from a table.
-    Filters.append(filter)
-    
-
-
-# sweep parameters
-steps = 1000
-
-figure(2)   
-title('CarFac individual filter frequency response')
-# note:  the  scales are linear, not logrithmic as in the book
-
-
-for i in range(n_ch):
-    filter = Filters[i]
-    # plotting arrays
-    u = []
-    v = []
-    # calculate the frequency magnitude by stepping the frequency in radians
-    for j in range(steps):
-        
-        w = pi * float(j)/steps     
-        u.append(w)
-        mag = filter.Hw(w)      # freq mag at freq w
-        filter.H.append(mag)        # save for later use
-        filter.HT.append(mag)       # will be total response of cascade to this point after we do the multiplication in a step below
-        v.append(abs(mag))           # y plotting axis
-        
-      
-    plot(u,v)
-
-
-# calculate the phase response of the same group of  filters
-figure(3)
-title('Carfac individual filter Phase lag')
-
-
-for i in range(n_ch):
-    filter = Filters[i]
-    
-    u = []
-    v = []
-    for j in range(steps):
-        x = pi * float(j)/steps
-        
-        u.append(x)
-       
-        mag = filter.H[j]
-        phase = arctan2(-imag(mag),-real(mag))  - pi    # this formula used to avoid wrap around 
-       
-        v.append(phase)           # y plotting axis 
-     
-    plot(u,v)
-    axis([0.0,pi,-3.0,0.05])
-    
-    
-# calulate and plot cascaded frequency response    
-
-figure(4)   
-title('CarFac cascaded filter frequency response')
-
-
-for i in range(n_ch-1):
-   
-    filter = Filters[i]
-    next = Filters[i+1]
-    
-    
-    u = []
-    v = []
-    for j in range(steps):
-        w = pi * float(j)/steps    
-        u.append(w)
-        mag = filter.HT[j] * next.HT[j]
-        next.HT[j] = mag
-        v.append(abs(mag))
-
-      
-    plot(u,v)
-   
-  
-
-# calculate and plot the phase responses of the cascaded filters
-
-figure(5)
-title('Carfac cascaded filter Phase lag')
-
-for i in range(n_ch):
-
-    filter = Filters[i]
-    
-
-    u = []
-    v = []          # store list of phases
-    w = []          # second copy of phases needed for phase unwrapping
-    for j in range(steps):
-        x = pi * float(j)/steps
-        
-        u.append(x)
-        mag = filter.HT[j]
-        a = imag(mag)
-        b = real(mag)
-        phase = arctan2(a,b) 
-        
-        v.append(phase)  
-        w.append(phase)
-        
-    # unwrap the phase
-
-
-    for i in range(1,len(v)):
-        diff = v[i]-v[i-1]
-        if diff > pi:
-            for j in range(i,len(w)):
-                w[j] -= 2.0 * pi
-        elif diff < -pi:
-            for j in range(i,len(w)):
-                w[j] += 2.0 * pi
-                
-        else: continue
-    
-    # convert delay to cycles    
-    for i in range(len(w)):
-        w[i] /= 2.0 * pi
-         
-     
-    plot(u,w)
-    axis([0.0,pi,-5.0,0.05])
-    
-# calculate group delay as cascaded lag/filter center frequency
-    
-figure(6)
-title('Carfac group delay')
-
-for i in range(n_ch):
-
-    filter = Filters[i]
-    
-
-    u = []
-    v = []          # store list of phases
-    w = []          # second copy of phases needed for phase unwrapping
-    for j in range(1,steps):
-        x = pi * float(j)/steps
-        
-        u.append(x)
-        mag = filter.HT[j]
-        a = imag(mag)
-        b = real(mag)
-        phase = arctan2(a,b) 
-        
-        v.append(phase)  
-        w.append(phase)
-        
-   
-    for i in range(1,len(v)):
-        diff = v[i]-v[i-1]
-        if diff > pi:
-            for j in range(i,len(w)):
-                w[j] -= 2.0 * pi
-        elif diff < -pi:
-            for j in range(i,len(w)):
-                w[j] += 2.0 * pi
-                
-        else: continue
-    
-    # calculate the group delay from: GroupDelay(n)=-[((ph(n+1)-ph(n-1))/(w(n+1)-w(n-1))]/2pi # w in radians
-    # or gd[n] = - ((delta ph)/(delta w))/2pi
-    # delta ph = w[n+1] - w[n-1]
-    # delta w = pi* fs/steps        # we divide up the frequency range fs into fractions of pi radians.
-    # gd[n] = - steps(w[n+1] - w[n-1])/fs
-    
-    A = -(float(steps))/(2 *fs)     # note.  could have calculated this once outside the filter loop
-    
-    # gd[n] = A *(w[n+1] - w[n-1])
-    
-    gd = []             # in radians
-    gd.append(0.0)      # pad to equalize size of u array, end points are then meaningless
-    for n in range(1,len(w)-1):
-        gd.append(A * (w[n+1] - w[n-1]))
-         
-    gd.append(0.0)
-    
-    plot(u,gd)
-    axis([0.1,pi,-0.01,0.05])
-
-show()
-