Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b90bdeb

Browse files
committed
sndhdr.py: restored lost file; audiodev.py: import platform specific
modules only when needed
1 parent 8f0d15c commit b90bdeb

1 file changed

Lines changed: 270 additions & 0 deletions

File tree

Lib/sndhdr.py

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
# This module contains several routines that help recognizing sound
2+
# files.
3+
#
4+
# Function whathdr() recognizes various types of sound file headers.
5+
# It understands almost all headers that SOX can decode.
6+
#
7+
# The return tuple contains the following items, in this order:
8+
# - file type (as SOX understands it)
9+
# - sampling rate (0 if unknown or hard to decode)
10+
# - number of channels (0 if unknown or hard to decode)
11+
# - number of frames in the file (-1 if unknown or hard to decode)
12+
# - number of bits/sample, or 'U' for U-LAW, or 'A' for A-LAW
13+
#
14+
# If the file doesn't have a recognizable type, it returns None.
15+
# If the file can't be opened, IOError is raised.
16+
#
17+
# To compute the total time, divide the number of frames by the
18+
# sampling rate (a frame contains a sample for each channel).
19+
#
20+
# Function whatraw() calls the "whatsound" program and interprets its
21+
# output. You'll have to guess the sampling rate by listening though!
22+
#
23+
# Function what() calls whathdr() and if it doesn't recognize the file
24+
# then calls whatraw().
25+
#
26+
# Finally, the function test() is a simple main program that calls
27+
# what() for all files mentioned on the argument list. For directory
28+
# arguments it calls what() for all files in that directory. Default
29+
# argument is "." (testing all files in the current directory). The
30+
# option -r tells it to recurse down directories found inside
31+
# explicitly given directories.
32+
#
33+
# The file structure is top-down except that the test program and its
34+
# subroutine come last.
35+
36+
37+
#------------------------------------------------------#
38+
# Guess the type of any sound file, raw or with header #
39+
#------------------------------------------------------#
40+
41+
def what(filename):
42+
res = whathdr(filename)
43+
if not res:
44+
res = whatraw(filename)
45+
return res
46+
47+
48+
#-----------------------------#
49+
# Guess the type of raw sound #
50+
#-----------------------------#
51+
52+
def whatraw(filename):
53+
# Assume it's always 1 channel, byte-sized samples
54+
# Don't assume anything about the rate
55+
import os
56+
from stat import ST_SIZE
57+
# XXX "whatsound" should be part of the distribution somehow...
58+
cmd = 'whatsound ' + filename + ' 2>/dev/null'
59+
cmd = 'PATH=$PATH:/ufs/guido/bin/sgi\n' + cmd
60+
pipe = os.popen(cmd, 'r')
61+
data = pipe.read()
62+
sts = pipe.close()
63+
if sts:
64+
return None
65+
if data[:13] == '-t raw -b -s ':
66+
type = 'sb'
67+
sample_size = 8
68+
elif data[:13] == '-t raw -b -u ':
69+
type = 'ub'
70+
sample_size = 8
71+
elif data[:13] == '-t raw -b -U ':
72+
type = 'ul'
73+
sample_size = 'U'
74+
else:
75+
return None
76+
try:
77+
frame_count = os.stat(filename)[ST_SIZE]
78+
except IOError:
79+
frame_count = -1
80+
return type, 0, 1, frame_count, sample_size
81+
82+
83+
#-------------------------#
84+
# Recognize sound headers #
85+
#-------------------------#
86+
87+
def whathdr(filename):
88+
f = open(filename, 'r')
89+
h = f.read(512)
90+
for tf in tests:
91+
res = tf(h, f)
92+
if res:
93+
return res
94+
return None
95+
96+
97+
#-----------------------------------#
98+
# Subroutines per sound header type #
99+
#-----------------------------------#
100+
101+
tests = []
102+
103+
def test_aifc(h, f):
104+
import aifc
105+
if h[:4] <> 'FORM':
106+
return None
107+
if h[8:12] == 'AIFC':
108+
fmt = 'aifc'
109+
elif h[8:12] == 'AIFF':
110+
fmt = 'aiff'
111+
else:
112+
return None
113+
f.seek(0)
114+
try:
115+
a = aifc.openfp(f, 'r')
116+
except (EOFError, aifc.Error):
117+
return None
118+
return (fmt, a.getframerate(), a.getnchannels(), \
119+
a.getnframes(), 8*a.getsampwidth())
120+
121+
tests.append(test_aifc)
122+
123+
124+
def test_au(h, f):
125+
if h[:4] == '.snd':
126+
f = get_long_be
127+
elif h[:4] in ('\0ds.', 'dns.'):
128+
f = get_long_le
129+
else:
130+
return None
131+
type = 'au'
132+
hdr_size = f(h[4:8])
133+
data_size = f(h[8:12])
134+
encoding = f(h[12:16])
135+
rate = f(h[16:20])
136+
nchannels = f(h[20:24])
137+
sample_size = 1 # default
138+
if encoding == 1:
139+
sample_bits = 'U'
140+
elif encoding == 2:
141+
sample_bits = 8
142+
elif encoding == 3:
143+
sample_bits = 16
144+
sample_size = 2
145+
else:
146+
sample_bits = '?'
147+
frame_size = sample_size * nchannels
148+
return type, rate, nchannels, data_size/frame_size, sample_bits
149+
150+
tests.append(test_au)
151+
152+
153+
def test_hcom(h, f):
154+
if h[65:69] <> 'FSSD' or h[128:132] <> 'HCOM':
155+
return None
156+
divisor = get_long_be(h[128+16:128+20])
157+
return 'hcom', 22050/divisor, 1, -1, 8
158+
159+
tests.append(test_hcom)
160+
161+
162+
def test_voc(h, f):
163+
if h[:20] <> 'Creative Voice File\032':
164+
return None
165+
sbseek = get_short_le(h[20:22])
166+
rate = 0
167+
if 0 <= sbseek < 500 and h[sbseek] == '\1':
168+
ratecode = ord(h[sbseek+4])
169+
rate = int(1000000.0 / (256 - ratecode))
170+
return 'voc', rate, 1, -1, 8
171+
172+
tests.append(test_voc)
173+
174+
175+
def test_wav(h, f):
176+
# 'RIFF' <len> 'WAVE' 'fmt ' <len>
177+
if h[:4] <> 'RIFF' or h[8:12] <> 'WAVE' or h[12:16] <> 'fmt ':
178+
return None
179+
style = get_short_le(h[20:22])
180+
nchannels = get_short_le(h[22:24])
181+
rate = get_long_le(h[24:28])
182+
sample_bits = get_short_le(h[34:36])
183+
return 'wav', rate, nchannels, -1, sample_bits
184+
185+
tests.append(test_wav)
186+
187+
188+
def test_8svx(h, f):
189+
if h[:4] <> 'FORM' or h[8:12] <> '8SVX':
190+
return None
191+
# Should decode it to get #channels -- assume always 1
192+
return '8svx', 0, 1, 0, 8
193+
194+
tests.append(test_8svx)
195+
196+
197+
def test_sndt(h, f):
198+
if h[:5] == 'SOUND':
199+
nsamples = get_long_le(h[8:12])
200+
rate = get_short_le(h[20:22])
201+
return 'sndt', rate, 1, nsamples, 8
202+
203+
tests.append(test_sndt)
204+
205+
206+
def test_sndr(h, f):
207+
if h[:2] == '\0\0':
208+
rate = get_short_le(h[2:4])
209+
if 4000 <= rate <= 25000:
210+
return 'sndr', rate, 1, -1, 8
211+
212+
tests.append(test_sndr)
213+
214+
215+
#---------------------------------------------#
216+
# Subroutines to extract numbers from strings #
217+
#---------------------------------------------#
218+
219+
def get_long_be(s):
220+
return (ord(s[0])<<24) | (ord(s[1])<<16) | (ord(s[2])<<8) | ord(s[3])
221+
222+
def get_long_le(s):
223+
return (ord(s[3])<<24) | (ord(s[2])<<16) | (ord(s[1])<<8) | ord(s[0])
224+
225+
def get_short_be(s):
226+
return (ord(s[0])<<8) | ord(s[1])
227+
228+
def get_short_le(s):
229+
return (ord(s[1])<<8) | ord(s[0])
230+
231+
232+
#--------------------#
233+
# Small test program #
234+
#--------------------#
235+
236+
def test():
237+
import sys
238+
recursive = 0
239+
if sys.argv[1:] and sys.argv[1] == '-r':
240+
del sys.argv[1:2]
241+
recursive = 1
242+
try:
243+
if sys.argv[1:]:
244+
testall(sys.argv[1:], recursive, 1)
245+
else:
246+
testall(['.'], recursive, 1)
247+
except KeyboardInterrupt:
248+
sys.stderr.write('\n[Interrupted]\n')
249+
sys.exit(1)
250+
251+
def testall(list, recursive, toplevel):
252+
import sys
253+
import os
254+
for filename in list:
255+
if os.path.isdir(filename):
256+
print filename + '/:',
257+
if recursive or toplevel:
258+
print 'recursing down:'
259+
import glob
260+
names = glob.glob(os.path.join(filename, '*'))
261+
testall(names, recursive, 0)
262+
else:
263+
print '*** directory (use -r) ***'
264+
else:
265+
print filename + ':',
266+
sys.stdout.flush()
267+
try:
268+
print what(filename)
269+
except IOError:
270+
print '*** not found ***'

0 commit comments

Comments
 (0)