1
2
3 """Perceptual loudness measurement.
4 This is an implementation of
5 "Percieved Level of Noise by Mark VII and Decibels (E)"
6 S. S. Stevens,
7 J. Acoustical Soc. Am. v. 51(2, part 2) 1972
8 pages 575-602.
9
10 The algorithm matches the paper for FractOct==ThirdOct or OneOct.
11 The algorithm assumes that the level defined by SIXTY_EIGHT
12 corresponds to 68dB relative to 20 micro-Newtons per square meter
13 sound pressure.
14
15 USER INFORMATION:
16
17 You'll find, somewhere, a subdirectory named
18 speechresearch/voicing .
19 Within this is a script called emphasis_stevens.py .
20 This can be run as
21 python emphasis_stevens.py -o outputfile -write BITPIX=0 -c channelnumber inputfile
22 (there are a couple of other flags, too).
23
24 It will then read the input file (which is an audio recording)
25 and produce a time-series of the loudness. Data input and
26 output is via the gpkio library, in .../speechresearch/gpkio.
27 That library has many virtues, but reading WAV files is not
28 one of them, so you have to convert .wav files to
29 the "GPK ASCII image" format (or one of several other formats),
30 using .../speechresearch/lib/wavio.py .
31
32 The output will be in an ASCII version of the format,
33 which should be reasonably intelligible. (The GPK ASCII image
34 format is based on the FITS astronomy format from NASA.)
35
36 However, that script uses the gpkio and gpklib libraries
37 (also under ../speechresearch). These need to be compiled,
38 and it uses the gpk_img_python package that needs to be
39 installed via "python setup.py install".
40 Oh, and .../speechresearch/gmisclib needs to be in
41 your PYTHONPATH.
42
43 Give it a try, and I'll be happy to help, and will
44 incorporate the troubles you have into some form of
45 documentation. Sorry, I have nothing better yet.
46 """
47
48 import sys
49 import gpkimgclass
50 from gmisclib import Num
51 from gmisclib import die
52 from gpk_voicing import emphasis
53
54
55 if __name__ == '__main__':
56 DT = 0.01
57 arglist = sys.argv[1:]
58 columns = []
59 signalfile = None
60 outfile = None
61 extrahdr = {}
62 while len(arglist)>0 and arglist[0][0]=='-':
63 arg = arglist.pop(0)
64 if arg == '-c':
65 tmp = arglist.pop(0)
66 try:
67 col = int(tmp)
68 except ValueError:
69 col = tmp
70 columns.append(col)
71 elif arg == '-cal':
72 emphasis.SIXTY_EIGHT = float(arglist.pop(0))
73 elif arg == '-f':
74 signalfile = arglist.pop(0)
75 die.note("signalfile", signalfile)
76 elif arg == '-o':
77 outfile = arglist.pop(0)
78 elif arg == '-dt':
79 DT = float(arglist.pop(0))
80 elif arg == '-write':
81 extrahdr = dict( [q.strip().split('=', 1)
82 for q in arglist.pop(0).split(';') ]
83 )
84 else:
85 die.die("Unrecognized flag: %s" % arg)
86 if len(arglist) > 0:
87 rootname = arglist.pop(0)
88 if signalfile == None:
89 signalfile = rootname + '.d'
90 if outfile == None:
91 outfile = rootname + '.emph.dat'
92 if outfile == None:
93 outfile = 'emph.dat'
94 signal = gpkimgclass.read(signalfile)
95 nch = signal.d.shape[1]
96 if not columns:
97 columns = range(nch)
98 die.note("columns", str(columns))
99 for c in columns:
100 try:
101 signal.column(c)
102 except KeyError:
103 die.info("File has %d columns" % signal.n[1])
104 die.die("Bad column: %s" % str(c))
105
106 tmp = [ emphasis.simple_emphasis(signal.column(i), signal.dt(), DT)
107 for i in columns ]
108 n = len(tmp[0])
109 o = Num.zeros((n,), Num.Float)
110 for t in tmp:
111 Num.add(o, t, o)
112 o = o / nch
113
114 hdr = signal.hdr.copy()
115 hdr['CDELT2'] = DT
116 hdr['CRPIX2'] = 0
117 hdr['CRVAL2'] = signal.start()
118 hdr['CDELT1'] = 1
119 hdr['TTYPE1'] = 'loudness'
120 hdr['BITPIX'] = -32
121 hdr.update( extrahdr )
122 oo = gpkimgclass.gpk_img(hdr, Num.transpose( [o]))
123 oo.write(outfile)
124