import numpy as np
from .filterbank import FunctionFilterbank, CombinedFilterbank
from .filterbanklibrary import *
__all__ = ['DRNL']
def set_parameters(cf,type,param):
parameters=dict()
parameters['stape_scale']=0.00014
parameters['order_linear']=3
parameters['order_nonlinear']=3
if type=='guinea pig':
parameters['cf_lin_p0']=0.339
parameters['cf_lin_m']=0.339
parameters['bw_lin_p0']=1.3
parameters['bw_lin_m']=0.53
parameters['cf_nl_p0']=0
parameters['cf_nl_m']=1.
parameters['bw_nl_p0']=0.8
parameters['bw_nl_m']=0.58
parameters['a_p0']=1.87
parameters['a_m']=0.45
parameters['b_p0']=-5.65
parameters['b_m']=0.875
parameters['c_p0']=-1.
parameters['c_m']=0
parameters['g_p0']=5.68
parameters['g_m']=-0.97
parameters['lp_lin_cutoff_p0']=0.339
parameters['lp_lin_cutoff_m']=0.339
parameters['lp_nl_cutoff_p0']=0
parameters['lp_nl_cutoff_m']=1.
elif type=='human':
parameters['cf_lin_p0']=-0.067
parameters['cf_lin_m']=1.016
parameters['bw_lin_p0']=0.037
parameters['bw_lin_m']=0.785
parameters['cf_nl_p0']=-0.052
parameters['cf_nl_m']=1.016
parameters['bw_nl_p0']=-0.031
parameters['bw_nl_m']=0.774
parameters['a_p0']=1.402
parameters['a_m']=0.819
parameters['b_p0']=1.619
parameters['b_m']=-0.818
parameters['c_p0']=-0.602
parameters['c_m']=0
parameters['g_p0']=4.2
parameters['g_m']=0.48
parameters['lp_lin_cutoff_p0']=-0.067
parameters['lp_lin_cutoff_m']=1.016
parameters['lp_nl_cutoff_p0']=-0.052
parameters['lp_nl_cutoff_m']=1.016
if param:
if not isinstance(param, dict):
raise TypeError('given parameters must be a dict')
for key in param.keys():
if not key in parameters:
raise Exception(key + ' is invalid key entry for given parameters')
parameters[key] = param[key]
return parameters
[docs]class DRNL(CombinedFilterbank):
r'''
Implementation of the dual resonance nonlinear (DRNL) filter
as described in Lopez-Paveda, E. and Meddis, R.,
"A human nonlinear cochlear filterbank", JASA 2001.
The entire pathway consists of the sum of a linear and a nonlinear pathway.
The linear path consists of a bank of bandpass filters (second order
gammatone), a low pass function, and a gain/attenuation factor, g, in a
cascade.
The nonlinear path is a cascade consisting of a bank of gammatone filters, a
compression function, a second bank of gammatone filters, and a low
pass function, in that order.
Initialised with arguments:
``source``
Source of the cochlear model.
``cf``
List or array of center frequencies.
``type``
defines the parameters set corresponding to a certain fit. It can be
either:
``type='human'``
The parameters come from Lopez-Paveda, E. and Meddis, R.., "A human
nonlinear cochlear filterbank", JASA 2001.
``type ='guinea pig'``
The parameters come from Summer et al., "A nonlinear filter-bank
model of the guinea-pig cochlear nerve: Rate responses", JASA 2003.
``param``
Dictionary used to overwrite the default parameters given in the
original papers.
The possible parameters to change and their default values for humans (see
Lopez-Paveda, E. and Meddis, R.,"A human nonlinear cochlear filterbank",
JASA 2001. for notation) are::
param['stape_scale']=0.00014
param['order_linear']=3
param['order_nonlinear']=3
from there on the parameters are given in the form
:math:`x=10^{\mathrm{p0}+m\log_{10}(\mathrm{cf})}` where
``cf`` is the center frequency::
param['cf_lin_p0']=-0.067
param['cf_lin_m']=1.016
param['bw_lin_p0']=0.037
param['bw_lin_m']=0.785
param['cf_nl_p0']=-0.052
param['cf_nl_m']=1.016
param['bw_nl_p0']=-0.031
param['bw_nl_m']=0.774
param['a_p0']=1.402
param['a_m']=0.819
param['b_p0']=1.619
param['b_m']=-0.818
param['c_p0']=-0.602
param['c_m']=0
param['g_p0']=4.2
param['g_m']=0.48
param['lp_lin_cutoff_p0']=-0.067
param['lp_lin_cutoff_m']=1.016
param['lp_nl_cutoff_p0']=-0.052
param['lp_nl_cutoff_m']=1.016
'''
def __init__(self, source, cf, type='human', param={}):
CombinedFilterbank.__init__(self, source)
source = self.get_modified_source()
cf = np.asarray(np.atleast_1d(cf))
nbr_cf=len(cf)
parameters=set_parameters(cf,type,param)
#conversion to stape velocity (which are the units needed for the further centres)
source=source*parameters['stape_scale']
#### Linear Pathway ####
#bandpass filter (second order gammatone filter)
cf_linear=10**(parameters['cf_lin_p0']+parameters['cf_lin_m']*np.log10(cf))
bandwidth_linear=10**(parameters['bw_lin_p0']+parameters['bw_lin_m']*np.log10(cf))
gammatone=ApproximateGammatone(source, cf_linear, bandwidth_linear, order=parameters['order_linear'])
#linear gain
g=10**(parameters['g_p0']+parameters['g_m']*np.log10(cf))
func_gain=lambda x:g*x
gain= FunctionFilterbank(gammatone,func_gain)
#low pass filter(cascade of 4 second order lowpass butterworth filters)
cutoff_frequencies_linear=10**(parameters['lp_lin_cutoff_p0']+parameters['lp_lin_cutoff_m']*np.log10(cf))
order_lowpass_linear=2
lp_l=LowPass(gain,cutoff_frequencies_linear)
lowpass_linear=Cascade(gain,lp_l,4)
#### Nonlinear Pathway ####
#bandpass filter (third order gammatone filters)
cf_nonlinear=10**(parameters['cf_nl_p0']+parameters['cf_nl_m']*np.log10(cf))
bandwidth_nonlinear=10**(parameters['bw_nl_p0']+parameters['bw_nl_m']*np.log10(cf))
bandpass_nonlinear1=ApproximateGammatone(source, cf_nonlinear, bandwidth_nonlinear, order=parameters['order_nonlinear'])
#compression (linear at low level, compress at high level)
a=10**(parameters['a_p0']+parameters['a_m']*np.log10(cf)) #linear gain
b=10**(parameters['b_p0']+parameters['b_m']*np.log10(cf))
v=10**(parameters['c_p0']+parameters['c_m']*np.log10(cf))#compression exponent
func_compression=lambda x:np.sign(x)*np.minimum(a*abs(x),b*abs(x)**v)
compression=FunctionFilterbank(bandpass_nonlinear1, func_compression)
#bandpass filter (third order gammatone filters)
bandpass_nonlinear2=ApproximateGammatone(compression, cf_nonlinear, bandwidth_nonlinear, order=parameters['order_nonlinear'])
#low pass filter
cutoff_frequencies_nonlinear=10**(parameters['lp_nl_cutoff_p0']+parameters['lp_nl_cutoff_m']*np.log10(cf))
order_lowpass_nonlinear=2
lp_nl=LowPass(bandpass_nonlinear2,cutoff_frequencies_nonlinear)
lowpass_nonlinear=Cascade(bandpass_nonlinear2,lp_nl,3)
#adding the two pathways
drnl_filter=lowpass_linear+lowpass_nonlinear
self.set_output(drnl_filter)