comparison utils.py @ 0:5609fd93e935

First commit.
author Carl Bussey <c.bussey@se10.qmul.ac.uk>
date Sat, 25 Jan 2014 20:00:38 +0000
parents
children dc43033a2c20
comparison
equal deleted inserted replaced
-1:000000000000 0:5609fd93e935
1 """
2 A utility module to assist cortical_model.py with general procedures, e.g., file reading and writing.
3
4 Packaged dependencies:
5 * erb.dat
6 * outMidFir.dat
7
8 External dependencies:
9 * scipy
10 * numpy
11 * matplotlib
12 """
13
14 import numpy as np
15 import scipy.io.wavfile as wave
16 import matplotlib.pyplot as plt
17 import scipy.fftpack as fft
18
19 def load_erb_data():
20 """
21 Loads and returns 39 ERB frequencies and bandwidths
22
23 Parameters:
24 NONE
25
26 Returns:
27 * fc (type: numpy array of floats) - a vector of length 39 with elements containing
28 the centre frequencies of each ERB.
29 * bw (type: numpy array of floats) - a vector of length 39 with elements containing
30 the bandwidths of each ERB.
31
32 Dependencies:
33 * erb.dat (place in the same folder as utils.pyc)
34 """
35 # read our data from a text file
36 data=np.loadtxt("erb.dat",delimiter=",")
37
38 # load centre frequencies from the first column into fc
39 fc=np.array(data[:,0])
40 # load bandwidths from the second column into bw
41 bw=np.array(data[:,1])
42
43 return fc,bw
44
45 def load_outMidFir_coeff():
46 """
47 Loads and returns 39 ERB frequencies and bandwidths
48
49 Parameters:
50 NONE
51
52 Returns:
53 * b (type: numpy array of floats) - a vector of length 4097 containing the impulse
54 response of the outer middle ear.
55
56 Dependencies:
57 * outMidFir.dat (place in the same folder as utils.pyc)
58 """
59
60 b=np.loadtxt("outMidFir.dat", delimiter=",")
61
62 return b
63
64 def exp_sequence(start, stop, n, base=2):
65 """
66 Creates a linear sequence with n points starting from start and ending at stop. For each
67 element in the sequence, e, the output sequence is 2^e, generating an exponential sequence
68 with base 2.
69
70 Parameters:
71 * start (type: numerical int) - determines the first element of the sequence, i.e.,
72 base^start. (Required)
73 * stop (type: numerical int) - determines the last element of the sequence, i.e.,
74 base^stop. (Required)
75 * n (type = numerical int) - determines the number of elements in the sequence. (Required)
76 * base (type: numerical) - determines the exponential base. (Optional; Default = 2)
77
78 Returns:
79 * seq - the exponential sequence
80 """
81
82 seq = [base**x for x in np.linspace(start,stop,n)]
83
84 return seq
85
86 def wavread(file):
87 """
88 Reads the audio data from a wav file and converts it to floating point ranging from -1 to 1.
89
90 Parameters:
91 * file (type: string) - the name of the wav file to read from. (Required)
92
93 Returns:
94 * fs (type: numerical) - the sampling frequency of the signal storied in file
95 * data (type: numpy array of floats) - the data of the signal stored in file normalised
96 to an amplitude range of -1 to 1.
97 """
98
99 fs,data = wave.read(file)
100 data = np.array(int16_to_nfloat(data))
101
102 return fs,data
103
104 def wavwrite(file, fs, data, precision = 16):
105 """
106 Unnormalises the audio data to a specified integer precision and converts to an int, then
107 writes the audio data to a wav file. (E.g., if 16-bit precision, then highest amplitude
108 is equal to 2^16).
109
110 Parameters:
111 * file (type: string) - the name of the wav file to write to. (Required)
112 * fs (type: numerical) - the sampling frequency of the signal. (Required)
113 * data (type: array-like matrix of floats) - the signal data normalised from -1 to 1. The signal will be clipped if not
114 in this range. (Required)
115 * precision (type: numerical int)- the bit precision to store at. Can only be 16 or 32 bit, because that is
116 all scipy allows.
117
118 Returns:
119 NONE
120
121 TODO explore WAVE package to be allow for 24bit precision.
122 """
123
124 data[data>1] = 1
125 data[data<-1] = -1
126
127 if(precision == 16):
128 dtype = np.int16
129 elif(precision == 32):
130 dtype = np.int32
131 else:
132 print "Error: precision can only be 16 or 32 bit due to scipy package."
133 return
134
135 data = nfloat_to_int(data)
136 wave.write(file, fs, data)
137
138 return
139
140 def plot_fft(x, xscale = 'log', yscale = 'log', show = True):
141 """
142 Plots the fft of signal x. If the figure is not shown, the current plot is held to allow other plots to
143 be added to the same figure.
144
145 Parameters:
146 * x (type: array-like matrix of floats) - the signal to be analysed. (Required)
147 * xscale (type: string) - the scale of the frequency axis. Values are 'log' or 'linear'. (Optional; Default = 'log')
148 * yscale (type: string) - the scale of the amplitude axis. Values are 'log' or 'linear'. (Optional; Default = 'log')
149 * show (type: boolean) - specifies whether the figure should be shown. If False, the current plot will be held so
150 other plots can be added to the figure. (Optional; Default = True)
151
152 Returns:
153 NONE
154 """
155
156 if(xscale.lower() == "log"): plt.gca().set_xscale('log')
157 if(xscale.lower() == "log"): plt.gca().set_yscale('log')
158
159 fftx = np.absolute(fft.fft(x))
160 plt.plot(range(np.shape(x)[0]),fftx)
161 if(show):
162 plt.show()
163 else:
164 plt.hold(True)
165
166 return
167
168 def int_to_nfloat(input, type=np.float32):
169 """
170 Convert integer with to floating point with a range from -1 to 1.
171
172 Parameters:
173 * input (type: array-like matrix of ints) - a signed integer array. (Required)
174 dtype : the output datatype. (Optional; Default = np.float32)
175
176 Returns:
177 * y (type: array-like matrix of floats) - a float array normalised to a
178 range of -1 to 1.
179 """
180
181 input = np.array(input)
182 assert input.dtype.kind == 'i', "'input' must be an array-like matrix of integers."
183 type = np.dtype(type);
184 inputdtype = np.dtype(type(input[0]))
185 input = input.astype(type)
186
187 input[input > 0] = input[input > 0] / np.iinfo(inputdtype).max
188 input[input < 0] = input[input < 0] / -np.iinfo(inputdtype).min
189
190 y = input
191 return y
192
193 def nfloat_to_int(input, type=np.int16):
194 """
195 Convert a float array with amplitude ranging from -1 to 1 to a unnormalised signed
196 integer array with specified precision.
197
198 Parameters:
199 * input (type: array-like matrix of floats) - a float array. (Required)
200 dtype : the output datatype (also determines the precision).
201 (Optional; Default = np.int16)
202
203 Returns:
204 * y (type: array-like matrix of ints) - an unnormalised to a
205 range of -1 to 1.
206 """
207
208 input = np.array(input)
209 assert input.dtype.kind == 'f', "'input' must be an array of floats!"
210
211 input[input > 0] = input[ input > 0 ] * np.iinfo(np.int16).max
212 input[input < 0] = input[ input < 0 ] * -np.iinfo(np.int16).min
213
214 y = input.astype(type)
215
216 return y