Mercurial > hg > cm
changeset 3:2d80632482b3
* Added exponential smoothing filtering into get_excitation_i() + dependencies
* Broke up get_specific_loudness to allow user to return loudness parameters tq, A, G and alpha using get_specific_loudness_parameters().
* Commented all functions
author | Carl Bussey <c.bussey@se10.qmul.ac.uk> |
---|---|
date | Tue, 04 Feb 2014 14:46:06 +0000 |
parents | 3b3c1c4ad283 |
children | 29cd3e735c4c |
files | cortical_model.py |
diffstat | 1 files changed, 161 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/cortical_model.py Sun Feb 02 22:48:18 2014 +0000 +++ b/cortical_model.py Tue Feb 04 14:46:06 2014 +0000 @@ -29,18 +29,21 @@ def get_specific_loudness(exc_i, inc_loud_region = False): """ - A function to calculate the specific loudness of the excitation patterns at each ERB. + A function to calculate the specific loudness of the excitation patterns at each ERB. Specific loudness is calculated for three regions of + signal intensity, low level, mid level and high level. The high level processing is optional, and by default, ignored. When ignored the high level + region is processed equivalent to that of the mid region. + + Parameters: + * exc_i (type: array-like of floats) - an array of shape (39, lenSig) of the excitation intensity of the signal. The outer dimension determines the + ERB channel. (Required) + * inc_loud_region (type: boolean) - Specifies whether to process the high levels differently to the mid levels. (Optional; Default = False) TO DO """ + exc_i = np.array(exc_i) + lenSig = np.shape(exc_i)[-1] #length signal - tq_dB, A, alpha = utils.load_sl_parameters() #load tq, A and alpha parameters - tq_dB = np.transpose(np.tile(tq_dB, (lenSig,1))) - tq = 10**(tq_dB / 10) - A = np.transpose(np.tile(A, (lenSig,1))) - alpha = np.transpose(np.tile(alpha, (lenSig,1))) - tq500_dB = 3.73 #threshold of quiet at 500Hz reference - G = 10**((tq500_dB - tq_dB)/10) #gain parameter + tq, G, A, alpha = get_specific_loudness_parameters(lenSig) specific_loudness = exc_low = exc_mid = exc_high = np.zeros(np.shape(exc_i)) less_than_tq = get_less_than_tq(exc_i, tq) #boolean array of elements less than or equal to the threshold of quiet @@ -62,7 +65,61 @@ return specific_loudness +def get_specific_loudness_parameters(lenSig = 1): + """ + Loads and returns the specific loudness values. If lenSig is specified, the parameters are shaped equal to the excitation signal to allow for + matrix elementwise operations between the parameters and signal. (Assumes excitation signal shape is [39, lenSig]). + + Parameters: + * lenSig (type: numerical int) - the length of the excitation signal to be analysed. (Optional; Default = 1) + + Returns: + * tq (type: numpy array of floats) - the threshold of quiet for each centre frequency of the ERBs + * G (type: numpy array of floats) - the frequency dependent gain values for each centre frequency of the ERBs + * A (type: numpy array of floats) - the frequency dependent A values for each centre frequency of the ERBs + * alpha (type: numpy array of floats) - the frequency dependent alpha values for each centre frequency of the ERBs + """ + + tq_dB, A, alpha = utils.load_sl_parameters() #load tq, A and alpha parameters + tq_dB = np.transpose(np.tile(tq_dB, (lenSig,1))) + tq = 10**(tq_dB / 10) + A = np.transpose(np.tile(A, (lenSig,1))) + alpha = np.transpose(np.tile(alpha, (lenSig,1))) + tq500_dB = 3.73 #threshold of quiet at 500Hz reference + G = 10**((tq500_dB - tq_dB)/10) #gain parameters + + return tq, G, A, alpha + def get_specific_loudness_low(exc_low, G, tq, A, alpha): + """ + Returns the specific loudness of the low level parts of the signal. Use get_specific_loudness_parameters() and specify lenSig + to obtain the correct values for G, tq, A and alpha. Use get_less_than_tq() to find the indexes of the samples with lower level + excitations. + + e.g., + + # exc_i is the excitation intensity + lenSig = np.shape(exc_i)[-1] # find the length of the signal + tq, G, A, alpha = get_specific_loudness_parameters(lenSig) # get the shaped loudness parameters + less_than_tq = get_less_than_tq(exc_i, tq) # find which samples are lower level + specific_loudness[less_than_tq] = get_specific_loudness_low(exc_low[less_than_tq], G[less_than_tq], tq[less_than_tq], A[less_than_tq], alpha[less_than_tq]) + # only process the low level part of the signal + + Parameters: + * exc_low (type: array-like matrix of floats) - the lower level (less than or equal to tq) excitation pattern for each ERB + (Required) + * G (type: array-like matrix of floats) - the frequency dependent loudness gain parameters for each ERB, must be same shape + as exc_low. (Required) + * tq (type: array-like matrix of floats) - the frequency dependent threshold of quiet parameters for each ERB. Must be same + shape as exc_low. (Required) + * A (type: array-like matrix of floats) - the frequency dependent A parameters for each ERB. Must be same shape as exc_low. + * alpha (type: array-like matrix of floats) - the frequency dependent alpha parameters for each ERB. Must be same shape as + exc_low. (Required) + + Returns: + * specific_loudness_low (type: array-like matrix of floats) - An array with dimensions equal to the exc_low containing the + specific loudness of the signal at levels below the threshold of quiet. + """ C = 0.047 #constant parameter specific_loudness_low = C * ((2*exc_low)/(exc_low+tq))**1.5 * ((G * exc_low + A)**alpha - A**alpha) @@ -70,6 +127,38 @@ return specific_loudness_low def get_specific_loudness_mid(exc_mid, G, A, alpha): + """ + Returns the specific loudness of the mid level parts of the signal. + + e.g., + + # exc_i is the excitation intensity + lenSig = np.shape(exc_i)[-1] # find the length of the signal + tq, G, A, alpha = get_specific_loudness_parameters(lenSig) # get the shaped loudness parameters + less_than_tq = get_less_than_tq(exc_i, tq) # find which samples are lower level + greater_than_tq = ~less_than_tq # find which samples are greater than the threshold of quiet + greater_than_tl = get_greater_than_tl(exc_i) # find which samples are greater than the loud threshold + gttq_lttl = greater_than_tq[~greater_than_tl] # find which samples are mid level + specific_loudness[gttq_lttl] = get_specific_loudness_low(exc_low[gttq_lttl], G[gttq_lttl], tq[gttq_lttl], A[gttq_lttl], alpha[gttq_lttl]) + # only process the mid level part of the signal + + NOTE: The above is an example of use assuming the higher level processing IS NOT IGNORED. Use variable greater_than_tq if processing + higher levels equivalent to the mid. + + + Parameters: + * exc_mid (type: array-like matrix of floats) - the mid level (larger than tq (and, optionally less than high level threshold)) + excitation pattern for each ERB (Required) + * G (type: array-like matrix of floats) - the frequency dependent loudness gain parameters for each ERB, must be same shape + as exc_low. (Required) + * A (type: array-like matrix of floats) - the frequency dependent A parameters for each ERB. Must be same shape as exc_low. + * alpha (type: array-like matrix of floats) - the frequency dependent alpha parameters for each ERB. Must be same shape as + exc_low. (Required) + + Returns: + * specific_loudness_mid (type: array-like matrix of floats) - An array with dimensions equal to the exc_mid containing the + specific loudness of the signal at mid levels. + """ C = 0.047 #constant parameter specific_loudness_mid = C * ((G * exc_mid + A)**alpha - A**alpha) @@ -78,7 +167,24 @@ def get_specific_loudness_high(exc_high): """ - + Returns the specific loudness of the high level parts of the signal. + + e.g., + + # exc_i is the excitation intensity + lenSig = np.shape(exc_i)[-1] # find the length of the signal + tq, G, A, alpha = get_specific_loudness_parameters(lenSig) # get the shaped loudness parameters + greater_than_tl = get_greater_than_tl(exc_i) # find which samples are greater than the loud threshold + specific_loudness[greater_than_tl] = get_specific_loudness_low(exc_low[greater_than_tl], G[greater_than_tl], tq[greater_than_tl], A[greater_than_tl], alpha[greater_than_tl]) + # only process the mid level part of the signal + + Parameters: + * exc_high (type: array-like matrix of floats) - the high level (larger than the threshold of high level) excitation pattern + for each ERB (Required) + + Returns: + * specific_loudness_high (type: array-like matrix of floats) - An array with dimensions equal to the exc_high containing the + specific loudness of the signal at high levels. """ C = 0.047 #constant parameter @@ -94,8 +200,8 @@ * exc_i (type: array-like matrix of floats) - the input excitation intensity Returns: - * le_tq (type: array-like matrix of booleans) - a boolean array with dimensions equal to the input - specifying if the excitation intensity is greater than the threshold of loud + * le_tq (type: array-like matrix of booleans) - a boolean array with dimensions equal to the input + specifying if the excitation intensity is greater than the threshold of loud """ lenSig = np.shape(exc_i)[-1] @@ -150,6 +256,8 @@ gtfs = half_rectification(gtfs) gtfs = pa_i(gtfs) gtfs = at_normalise(gtfs) + b,a = exp_smoothing(fs) + gtfs = sp.lfilter(b,a,gtfs) return gtfs @@ -325,27 +433,6 @@ return output -def antialias_fir(fs, fc=100, order=64): - """ - A function which returns the b coefficients for a lowpass fir filter with specified requirements. - Made specifically to remove aliasing when downsampling, but can be used for any application that - requires a lowpass filter. - - Parameters: - * fs (type: numerical) - sampling frequency of the signal to be filtered (Required) - * fc (type: numerical) - unnormalised cut off frequency of the filter (Optional; Default = 100) - * order (type: numerical int) - the order of the filter (number of taps minus 1) (Optional; Default = 64) - - Returns: - * b (type: numpy array of floats) - an array of size order + 1 (i.e. a coefficient for each tap) - """ - - nyquist = 0.5*fs - fcNorm = fc/nyquist - b = sp.firwin(order+1, fcNorm) - - return b - def half_rectification(input): """ A function which performs a half-wave rectification on the input signal. @@ -405,6 +492,48 @@ return y +def exp_smoothing(fs, tc = 0.01): + """ + Designs an exponential filter, y[n] = alpha*x[n] - -(1-alpha)*y[n-1], where alpha = T/(tc+T), where T + is the inverse of the sampling frequency and time constant, tc, is specified. + + Parameters: + * fs (type: numerical) - sampling frequency of the signal to be filtered (Required) + * tc (type: numerical) - the time constant of the filter. (Optional; Default = 0.01) + + Returns: + * b (type: numerical) - the coefficient of x[n]. Equal to alpha. + * a (type: numpy array of floats) - an array of size 2 of the coefficients of y[n] (a[0] = 1) and y[n-1] + """ + + T = 1.0/fs + alpha = T/(tc + T) + b = [alpha] + a = [1, -(1-alpha)] + + return b, a + +def antialias_fir(fs, fc=100, order=64): + """ + A function which returns the b coefficients for a lowpass fir filter with specified requirements. + Made specifically to remove aliasing when downsampling, but can be used for any application that + requires a lowpass filter. + + Parameters: + * fs (type: numerical) - sampling frequency of the signal to be filtered (Required) + * fc (type: numerical) - unnormalised cut off frequency of the filter (Optional; Default = 100) + * order (type: numerical int) - the order of the filter (number of taps minus 1) (Optional; Default = 64) + + Returns: + * b (type: numpy array of floats) - an array of size order + 1 (i.e. a coefficient for each tap) + """ + + nyquist = 0.5*fs + fcNorm = fc/nyquist + b = sp.firwin(order+1, fcNorm) + + return b + def fir_bandpass(low, high, fs, order = 1024, verbose = False): """ A function which returns the b coefficients for a bandpass fir filter with specified requirements.