Package lib :: Module dirty_io
[frames] | no frames]

Source Code for Module lib.dirty_io

  1   
  2  import re 
  3  import numpy 
  4  from gmisclib import die 
  5  from gmisclib import wavio 
  6  from gmisclib import Numeric_gpk as NG 
  7   
8 -class BadChannel(ValueError):
9 - def __init__(self, *s):
10 ValueError.__init__(self, *s)
11 12 13 NEARCLIP = 32500 14 15 16 17
18 -def wav_read(filename, channel=None, info={}):
19 """Quick and dirty way to read a single channel of audio from a 20 multichannel file. If the channel is not specified, either as an 21 argument or as info['Channel'], then it will pick whatever channel 22 has the largest amplitude. Needless to say, this is not entirely 23 reliable unless you know that the other channel is silent. 24 @param channel: which channel to use? It can be a string name, an integer column number 25 or None. 26 @param info: a dictionary with miscellaneous metadata. C{info['Channel']} is inspected. 27 @type info: C{dict}. 28 @type channel: C{string}, C{int}, or C{None}. 29 @return: audio data with header information 30 A gpk_img data structure holding the audio and header information. 31 C{hdr['AudioChannel']}, C{hdr['Trouble']} and C{hdr['WhyAudioChannel']} are set. 32 @rtype: gpkimgclass.gpk_img 33 @except BadChannel: when you ask for a channel that isn't there. 34 @note: Channel numbers start with zero! 35 """ 36 if channel is None: 37 channel = info.get('Channel', None) 38 39 x = wavio.read(filename) 40 nch0 = x.d.shape[1] 41 trouble = [] 42 if channel is None and x.d.shape[1] > 1: 43 assert x.d.shape[1] < 1000 44 rms = NG.block_stdev(x.d) 45 channel = numpy.argmax(rms) 46 x.d = x.d.take([channel], axis=1) 47 assert len(x.d.shape) == 2 48 die.info('Taking data from channel %d' % channel) 49 if rms[1-channel] > 0.1*rms[channel]: 50 die.warn('Warning: channel %d is comparable: MAD=%.2g/%.2g' 51 % (1-channel, rms[1-channel], rms[channel]) 52 ) 53 x.hdr['WhyAudioChannel'] = 'It was slightly louder' 54 trouble.append('Ambiguous channel') 55 else: 56 x.hdr['WhyAudioChannel'] = 'It was much louder' 57 elif channel is None and x.d.shape[1]==1: 58 x.hdr['WhyAudioChannel'] = 'There was only one' 59 channel = 0 60 elif channel=='mono': 61 assert x.d.shape[1]==1 62 x.hdr['WhyAudioChannel'] = 'There was only one' 63 channel = 0 64 elif 0 <= channel < x.d.shape[1]: 65 x.d = x.d.take([channel], axis=1) 66 x.hdr['WhyAudioChannel'] = 'Specified in g_audioprep.py' 67 else: 68 raise BadChannel, "Channel=%s but available channels are %s" % (channel, range(x.d.shape[1])) 69 70 # x is now reduced to a single channel: 0. 71 72 if NG.N_maximum(x.column(0)) > NEARCLIP or NG.N_minimum(x.column(0))< -NEARCLIP: 73 da = numpy.absolute(x.column(0)) 74 die.warn("Data is near clipping: maximum abs(value)=%d, %.1f%% near clipping" 75 % (NG.N_maximum(da), numpy.sum(numpy.greater(da, NEARCLIP))/float(da.shape[0]))) 76 trouble.append('Near clipping') 77 78 x.hdr['Trouble'] = ','.join(trouble) 79 assert 0 <= channel < nch0 80 x.hdr['AudioChannel'] = channel 81 assert x.d.shape[1] == 1 82 return x
83 84 85 _nmparse = re.compile(r'(.*)\[([0-9_a-zA-Z]+)\]$')
86 -def splitname(filename):
87 """Splits filenames in the form pathname[channel] into a pathname 88 and a channel. 89 """ 90 m = _nmparse.match(filename) 91 if m: 92 name = m.group(1) 93 try: 94 channel = int(m.group(2)) 95 except ValueError: 96 channel = m.group(2) 97 else: 98 name = filename 99 channel = None 100 return (name, channel)
101 102
103 -def wav_read2(filename):
104 """Deal with filenames in the form path/name[channel]. 105 """ 106 name, channel = splitname(filename) 107 try: 108 rv = wav_read(name, channel=channel, info={}) 109 except IOError, x: 110 raise IOError(*(x.args + ('From dirty_io.wav_read2', 'Filename=%s' % filename))) 111 return rv
112