Mercurial > hg > cm
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 |