annotate utils.py @ 7:0ee61aeb789a

* Changed normalisation of gammatone_filter * Changed run.py to test calc_loudness_quiet()
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Mon, 24 Feb 2014 15:31:15 +0000
parents d7b2784ff5a3
children d5693c7aa0ae
rev   line source
c@0 1 """
c@0 2 A utility module to assist cortical_model.py with general procedures, e.g., file reading and writing.
c@0 3
c@0 4 Packaged dependencies:
c@0 5 * erb.dat
c@0 6 * outMidFir.dat
c@1 7 * tq.dat
c@0 8
c@0 9 External dependencies:
c@0 10 * scipy
c@0 11 * numpy
c@0 12 * matplotlib
c@0 13 """
c@0 14
c@0 15 import numpy as np
c@0 16 import scipy.io.wavfile as wave
c@0 17 import matplotlib.pyplot as plt
c@0 18 import scipy.fftpack as fft
c@0 19
c@0 20 def load_erb_data():
c@0 21 """
c@0 22 Loads and returns 39 ERB frequencies and bandwidths
c@0 23
c@0 24 Parameters:
c@0 25 NONE
c@0 26
c@0 27 Returns:
c@0 28 * fc (type: numpy array of floats) - a vector of length 39 with elements containing
c@0 29 the centre frequencies of each ERB.
c@0 30 * bw (type: numpy array of floats) - a vector of length 39 with elements containing
c@0 31 the bandwidths of each ERB.
c@0 32
c@0 33 Dependencies:
c@0 34 * erb.dat (place in the same folder as utils.pyc)
c@0 35 """
c@1 36 # read data from a text file
c@0 37 data=np.loadtxt("erb.dat",delimiter=",")
c@0 38
c@0 39 # load centre frequencies from the first column into fc
c@0 40 fc=np.array(data[:,0])
c@0 41 # load bandwidths from the second column into bw
c@0 42 bw=np.array(data[:,1])
c@0 43
c@0 44 return fc,bw
c@0 45
c@0 46 def load_outMidFir_coeff():
c@0 47 """
c@0 48 Loads and returns 39 ERB frequencies and bandwidths
c@0 49
c@0 50 Parameters:
c@0 51 NONE
c@0 52
c@0 53 Returns:
c@0 54 * b (type: numpy array of floats) - a vector of length 4097 containing the impulse
c@0 55 response of the outer middle ear.
c@0 56
c@0 57 Dependencies:
c@0 58 * outMidFir.dat (place in the same folder as utils.pyc)
c@0 59 """
c@0 60
c@1 61 b=np.array(np.loadtxt("outMidFir.dat", delimiter=","))
c@0 62
c@0 63 return b
c@0 64
c@1 65 def load_sl_parameters():
c@1 66 """
c@1 67 Loads the loudness parameters for each ERB fc into a tuple. A shortcut for load_tq_data(), load_A_data() and load_alpha_data().
c@1 68
c@1 69 Parameters:
c@1 70 NONE
c@1 71
c@1 72 Returns:
c@1 73 * tq (type: numpy array of floats) - a vector of length 39 containing the threshold excitation
c@1 74 intensity in quietat each ERB centre frequency
c@1 75 * A (type: numpy array of floats) - a vector of length 39 containing the parameter A for each ERB fc
c@1 76 * alpha (type: numpy array of floats) - a vector of length 39 containing the parameter alpha for each ERB fc
c@1 77
c@1 78 Dependencies:
c@1 79 * tq.dat (place in the same folder as utils.pyc)
c@1 80 * A.dat (place in the same folder as utils.pyc)
c@1 81 * alpha.dat (place in the same folder as utils.pyc)
c@1 82 """
c@5 83 tq_dB = load_tqdB_data()
c@1 84 A = load_A_data()
c@1 85 alpha = load_alpha_data()
c@1 86
c@5 87 return tq_dB, A, alpha
c@1 88
c@5 89 def load_tqdB_data():
c@1 90 """
c@1 91 Loads and returns the excitation threshold of quiet for each ERB fc.
c@1 92
c@1 93 Parameters:
c@1 94 NONE
c@1 95
c@1 96 Returns:
c@1 97 * tq (type: numpy array of floats) - a vector of length 39 containing the threshold excitation
c@1 98 intensity in quietat each ERB centre frequency
c@1 99
c@1 100 Dependencies:
c@1 101 * tq.dat (place in the same folder as utils.pyc)
c@1 102 """
c@1 103
c@5 104 tq = np.array(np.loadtxt("tq_dB.dat",delimiter=","))
c@1 105
c@1 106 return tq
c@1 107
c@1 108 def load_A_data():
c@1 109 """
c@1 110 Loads and returns the excitation A parameters for each ERB fc.
c@1 111
c@1 112 Parameters:
c@1 113 NONE
c@1 114
c@1 115 Returns:
c@1 116 * A (type: numpy array of floats) - a vector of length 39 containing the parameter A for each ERB fc
c@1 117
c@1 118 Dependencies:
c@1 119 * A.dat (place in the same folder as utils.pyc)
c@1 120 """
c@1 121
c@1 122 A = np.array(np.loadtxt("A.dat",delimiter=","))
c@1 123
c@1 124 return A
c@1 125
c@1 126 def load_alpha_data():
c@1 127 """
c@1 128 Loads and returns the excitation alpha parameters for each ERB fc.
c@1 129
c@1 130 Parameters:
c@1 131 NONE
c@1 132
c@1 133 Returns:
c@1 134 * alpha (type: numpy array of floats) - a vector of length 39 containing the parameter alpha for each ERB fc
c@1 135
c@1 136 Dependencies:
c@1 137 * alpha.dat (place in the same folder as utils.pyc)
c@1 138 """
c@1 139
c@1 140 alpha = np.array(np.loadtxt("alpha.dat",delimiter=","))
c@1 141
c@1 142 return alpha
c@1 143
c@0 144 def exp_sequence(start, stop, n, base=2):
c@0 145 """
c@0 146 Creates a linear sequence with n points starting from start and ending at stop. For each
c@1 147 element in the sequence, i, the output sequence is 2**i, generating an exponential sequence
c@0 148 with base 2.
c@0 149
c@0 150 Parameters:
c@0 151 * start (type: numerical int) - determines the first element of the sequence, i.e.,
c@1 152 base**start. (Required)
c@0 153 * stop (type: numerical int) - determines the last element of the sequence, i.e.,
c@1 154 base**stop. (Required)
c@0 155 * n (type = numerical int) - determines the number of elements in the sequence. (Required)
c@0 156 * base (type: numerical) - determines the exponential base. (Optional; Default = 2)
c@0 157
c@0 158 Returns:
c@0 159 * seq - the exponential sequence
c@0 160 """
c@0 161
c@0 162 seq = [base**x for x in np.linspace(start,stop,n)]
c@0 163
c@0 164 return seq
c@0 165
c@0 166 def wavread(file):
c@0 167 """
c@0 168 Reads the audio data from a wav file and converts it to floating point ranging from -1 to 1.
c@0 169
c@0 170 Parameters:
c@0 171 * file (type: string) - the name of the wav file to read from. (Required)
c@0 172
c@0 173 Returns:
c@0 174 * fs (type: numerical) - the sampling frequency of the signal storied in file
c@0 175 * data (type: numpy array of floats) - the data of the signal stored in file normalised
c@0 176 to an amplitude range of -1 to 1.
c@0 177 """
c@0 178
c@0 179 fs,data = wave.read(file)
c@1 180 data = np.array(int_to_nfloat(data))
c@0 181
c@0 182 return fs,data
c@0 183
c@0 184 def wavwrite(file, fs, data, precision = 16):
c@0 185 """
c@0 186 Unnormalises the audio data to a specified integer precision and converts to an int, then
c@0 187 writes the audio data to a wav file. (E.g., if 16-bit precision, then highest amplitude
c@1 188 is equal to 2**16).
c@0 189
c@0 190 Parameters:
c@0 191 * file (type: string) - the name of the wav file to write to. (Required)
c@0 192 * fs (type: numerical) - the sampling frequency of the signal. (Required)
c@0 193 * data (type: array-like matrix of floats) - the signal data normalised from -1 to 1. The signal will be clipped if not
c@0 194 in this range. (Required)
c@0 195 * precision (type: numerical int)- the bit precision to store at. Can only be 16 or 32 bit, because that is
c@0 196 all scipy allows.
c@0 197
c@0 198 Returns:
c@0 199 NONE
c@0 200
c@0 201 TODO explore WAVE package to be allow for 24bit precision.
c@0 202 """
c@0 203
c@0 204 data[data>1] = 1
c@0 205 data[data<-1] = -1
c@0 206
c@0 207 if(precision == 16):
c@0 208 dtype = np.int16
c@0 209 elif(precision == 32):
c@0 210 dtype = np.int32
c@0 211 else:
c@0 212 print "Error: precision can only be 16 or 32 bit due to scipy package."
c@0 213 return
c@0 214
c@0 215 data = nfloat_to_int(data)
c@0 216 wave.write(file, fs, data)
c@0 217
c@0 218 return
c@0 219
c@0 220 def plot_fft(x, xscale = 'log', yscale = 'log', show = True):
c@0 221 """
c@0 222 Plots the fft of signal x. If the figure is not shown, the current plot is held to allow other plots to
c@0 223 be added to the same figure.
c@0 224
c@0 225 Parameters:
c@0 226 * x (type: array-like matrix of floats) - the signal to be analysed. (Required)
c@0 227 * xscale (type: string) - the scale of the frequency axis. Values are 'log' or 'linear'. (Optional; Default = 'log')
c@0 228 * yscale (type: string) - the scale of the amplitude axis. Values are 'log' or 'linear'. (Optional; Default = 'log')
c@0 229 * show (type: boolean) - specifies whether the figure should be shown. If False, the current plot will be held so
c@0 230 other plots can be added to the figure. (Optional; Default = True)
c@0 231
c@0 232 Returns:
c@0 233 NONE
c@0 234 """
c@0 235
c@4 236 plt.gca().set_xscale(xscale)
c@4 237 plt.gca().set_yscale(yscale)
c@1 238
c@1 239 x = np.array(x)
c@0 240 fftx = np.absolute(fft.fft(x))
c@0 241 plt.plot(range(np.shape(x)[0]),fftx)
c@0 242 if(show):
c@0 243 plt.show()
c@0 244 else:
c@0 245 plt.hold(True)
c@0 246
c@0 247 return
c@0 248
c@1 249 def plot_waveform(x, show = True):
c@1 250 """
c@1 251 Plots the waveform of signal x. If the figure is not shown, the current plot is held to allow other plots to
c@1 252 be added to the same figure.
c@1 253
c@1 254 Parameters:
c@1 255 * x (type: array-like matrix of floats) - the signal to be plotted. (Required)
c@1 256 * show (type: boolean) - specifies whether the figure should be shown. If False, the current plot will be held so
c@1 257 other plots can be added to the figure. (Optional; Default = True)
c@1 258
c@1 259 Returns:
c@1 260 NONE
c@1 261 """
c@1 262
c@1 263 x = np.array(x)
c@1 264 plt.plot(x)
c@1 265
c@1 266 if(show): plt.show()
c@1 267 else: plt.hold(True)
c@1 268
c@1 269 return
c@1 270
c@1 271 def int_to_nfloat(input, outputtype=np.float32):
c@0 272 """
c@0 273 Convert integer with to floating point with a range from -1 to 1.
c@0 274
c@0 275 Parameters:
c@0 276 * input (type: array-like matrix of ints) - a signed integer array. (Required)
c@0 277 dtype : the output datatype. (Optional; Default = np.float32)
c@0 278
c@0 279 Returns:
c@0 280 * y (type: array-like matrix of floats) - a float array normalised to a
c@0 281 range of -1 to 1.
c@0 282 """
c@0 283
c@0 284 input = np.array(input)
c@0 285 assert input.dtype.kind == 'i', "'input' must be an array-like matrix of integers."
c@1 286 outputtype = np.dtype(outputtype)
c@0 287 inputdtype = np.dtype(type(input[0]))
c@1 288 input = input.astype(outputtype)
c@0 289
c@0 290 input[input > 0] = input[input > 0] / np.iinfo(inputdtype).max
c@0 291 input[input < 0] = input[input < 0] / -np.iinfo(inputdtype).min
c@0 292
c@0 293 y = input
c@0 294 return y
c@0 295
c@0 296 def nfloat_to_int(input, type=np.int16):
c@0 297 """
c@0 298 Convert a float array with amplitude ranging from -1 to 1 to a unnormalised signed
c@0 299 integer array with specified precision.
c@0 300
c@0 301 Parameters:
c@0 302 * input (type: array-like matrix of floats) - a float array. (Required)
c@0 303 dtype : the output datatype (also determines the precision).
c@0 304 (Optional; Default = np.int16)
c@0 305
c@0 306 Returns:
c@0 307 * y (type: array-like matrix of ints) - an unnormalised to a
c@0 308 range of -1 to 1.
c@0 309 """
c@0 310
c@0 311 input = np.array(input)
c@0 312 assert input.dtype.kind == 'f', "'input' must be an array of floats!"
c@0 313
c@1 314 input[input > 0] = input[ input > 0 ] * np.iinfo(type).max
c@1 315 input[input < 0] = input[ input < 0 ] * -np.iinfo(type).min
c@0 316
c@0 317 y = input.astype(type)
c@0 318
c@0 319 return y