8585else :
8686 big_endian = 0
8787
88- def _read_long (file ):
89- x = 0L
90- for i in range (4 ):
91- byte = file .read (1 )
92- if byte == '' :
93- raise EOFError
94- x = x + (ord (byte ) << (8 * i ))
95- if x >= 0x80000000L :
96- x = x - 0x100000000L
97- return int (x )
98-
99- def _read_ulong (file ):
100- x = 0L
101- for i in range (4 ):
102- byte = file .read (1 )
103- if byte == '' :
104- raise EOFError
105- x = x + (ord (byte ) << (8 * i ))
106- return x
107-
108- def _read_short (file ):
109- x = 0
110- for i in range (2 ):
111- byte = file .read (1 )
112- if byte == '' :
113- raise EOFError
114- x = x + (ord (byte ) << (8 * i ))
115- if x >= 0x8000 :
116- x = x - 0x10000
117- return x
118-
119- def _write_short (f , x ):
120- d , m = divmod (x , 256 )
121- f .write (chr (m ))
122- f .write (chr (d ))
123-
124- def _write_long (f , x ):
125- if x < 0 :
126- x = x + 0x100000000L
127- for i in range (4 ):
128- d , m = divmod (x , 256 )
129- f .write (chr (int (m )))
130- x = d
131-
132- class Chunk :
133- def __init__ (self , file ):
134- self .file = file
135- self .chunkname = self .file .read (4 )
136- if len (self .chunkname ) < 4 :
137- raise EOFError
138- self .chunksize = _read_long (self .file )
139- self .size_read = 0
140- self .offset = self .file .tell ()
141-
142- def rewind (self ):
143- self .file .seek (self .offset , 0 )
144- self .size_read = 0
145-
146- def setpos (self , pos ):
147- if pos < 0 or pos > self .chunksize :
148- raise RuntimeError
149- self .file .seek (self .offset + pos , 0 )
150- self .size_read = pos
151-
152- def read (self , length ):
153- if self .size_read >= self .chunksize :
154- return ''
155- if length > self .chunksize - self .size_read :
156- length = self .chunksize - self .size_read
157- data = self .file .read (length )
158- self .size_read = self .size_read + len (data )
159- return data
160-
161- def skip (self ):
162- try :
163- self .file .seek (self .chunksize - self .size_read , 1 )
164- except RuntimeError :
165- while self .size_read < self .chunksize :
166- dummy = self .read (8192 )
167- if not dummy :
168- raise EOFError
88+ from chunk import Chunk
16989
17090class Wave_read :
17191 # Variables used in this class:
@@ -197,41 +117,34 @@ class Wave_read:
197117 # _data_chunk -- instantiation of a chunk class for the DATA chunk
198118 # _framesize -- size of one frame in the file
199119
200- ## access _file, _nchannels, _nframes, _sampwidth, _framerate, \
201- ## _comptype, _compname, _soundpos, \
202- ## _fmt_chunk_read, _data_seek_needed, \
203- ## _data_chunk, _framesize: private
204-
205120 def initfp (self , file ):
206- self ._file = file
207121 self ._convert = None
208122 self ._soundpos = 0
209- form = self ._file . read ( 4 )
210- if form != 'RIFF' :
123+ self ._file = Chunk ( file , bigendian = 0 )
124+ if self . _file . getname () != 'RIFF' :
211125 raise Error , 'file does not start with RIFF id'
212- formlength = _read_long (self ._file )
213- if formlength <= 0 :
214- raise Error , 'invalid FORM chunk data size'
215- formdata = self ._file .read (4 )
216- formlength = formlength - 4
217- if formdata != 'WAVE' :
126+ if self ._file .read (4 ) != 'WAVE' :
218127 raise Error , 'not a WAVE file'
219128 self ._fmt_chunk_read = 0
220- while formlength > 0 :
129+ self ._data_chunk = None
130+ while 1 :
221131 self ._data_seek_needed = 1
222- chunk = Chunk (self ._file )
223- if chunk .chunkname == 'fmt ' :
132+ try :
133+ chunk = Chunk (self ._file , bigendian = 0 )
134+ except EOFError :
135+ break
136+ chunkname = chunk .getname ()
137+ if chunkname == 'fmt ' :
224138 self ._read_fmt_chunk (chunk )
225139 self ._fmt_chunk_read = 1
226- elif chunk . chunkname == 'data' :
140+ elif chunkname == 'data' :
227141 if not self ._fmt_chunk_read :
228142 raise Error , 'data chunk before fmt chunk'
229143 self ._data_chunk = chunk
230144 self ._nframes = chunk .chunksize / self ._framesize
231145 self ._data_seek_needed = 0
232- formlength = formlength - 8 - chunk .chunksize
233- if formlength > 0 :
234- chunk .skip ()
146+ break
147+ chunk .skip ()
235148 if not self ._fmt_chunk_read or not self ._data_chunk :
236149 raise Error , 'fmt chunk and/or data chunk missing'
237150
@@ -241,10 +154,6 @@ def __init__(self, f):
241154 # else, assume it is an open file object already
242155 self .initfp (f )
243156
244- def __del__ (self ):
245- if self ._file :
246- self .close ()
247-
248157 #
249158 # User visible methods.
250159 #
@@ -298,10 +207,10 @@ def setpos(self, pos):
298207
299208 def readframes (self , nframes ):
300209 if self ._data_seek_needed :
301- self ._data_chunk .rewind ( )
210+ self ._data_chunk .seek ( 0 , 0 )
302211 pos = self ._soundpos * self ._framesize
303212 if pos :
304- self ._data_chunk .setpos (pos )
213+ self ._data_chunk .seek (pos , 0 )
305214 self ._data_seek_needed = 0
306215 if nframes == 0 :
307216 return ''
@@ -310,12 +219,17 @@ def readframes(self, nframes):
310219 # something that only looks like a file object, so
311220 # we have to reach into the innards of the chunk object
312221 import array
222+ chunk = self ._data_chunk
313223 data = array .array (_array_fmts [self ._sampwidth ])
314224 nitems = nframes * self ._nchannels
315- if nitems * self ._sampwidth > self ._data_chunk .chunksize - self ._data_chunk .size_read :
316- nitems = (self ._data_chunk .chunksize - self ._data_chunk .size_read ) / self ._sampwidth
317- data .fromfile (self ._data_chunk .file , nitems )
318- self ._data_chunk .size_read = self ._data_chunk .size_read + nitems * self ._sampwidth
225+ if nitems * self ._sampwidth > chunk .chunksize - chunk .size_read :
226+ nitems = (chunk .chunksize - chunk .size_read ) / self ._sampwidth
227+ data .fromfile (chunk .file .file , nitems )
228+ # "tell" data chunk how much was read
229+ chunk .size_read = chunk .size_read + nitems * self ._sampwidth
230+ # do the same for the outermost chunk
231+ chunk = chunk .file
232+ chunk .size_read = chunk .size_read + nitems * self ._sampwidth
319233 data .byteswap ()
320234 data = data .tostring ()
321235 else :
@@ -328,16 +242,12 @@ def readframes(self, nframes):
328242 #
329243 # Internal methods.
330244 #
331- ## access *: private
332245
333246 def _read_fmt_chunk (self , chunk ):
334- wFormatTag = _read_short (chunk )
335- self ._nchannels = _read_short (chunk )
336- self ._framerate = _read_long (chunk )
337- dwAvgBytesPerSec = _read_long (chunk )
338- wBlockAlign = _read_short (chunk )
247+ wFormatTag , self ._nchannels , self ._framerate , dwAvgBytesPerSec , wBlockAlign = struct .unpack ('<hhllh' , chunk .read (14 ))
339248 if wFormatTag == WAVE_FORMAT_PCM :
340- self ._sampwidth = (_read_short (chunk ) + 7 ) / 8
249+ sampwidth = struct .unpack ('<h' , chunk .read (2 ))[0 ]
250+ self ._sampwidth = (sampwidth + 7 ) / 8
341251 else :
342252 raise Error , 'unknown format: ' + `wFormatTag`
343253 self ._framesize = self ._nchannels * self ._sampwidth
@@ -369,10 +279,6 @@ class Wave_write:
369279 # _nframeswritten -- the number of frames actually written
370280 # _datawritten -- the size of the audio samples actually written
371281
372- ## access _file, _comptype, _compname, _nchannels, _sampwidth, \
373- ## _framerate, _nframes, _nframeswritten, \
374- ## _datalength, _datawritten: private
375-
376282 def __init__ (self , f ):
377283 if type (f ) == type ('' ):
378284 f = __builtin__ .open (f , 'wb' )
@@ -512,7 +418,6 @@ def close(self):
512418 #
513419 # Internal methods.
514420 #
515- ## access *: private
516421
517422 def _ensure_header_written (self , datasize ):
518423 if not self ._datawritten :
@@ -530,28 +435,23 @@ def _write_header(self, initlength):
530435 self ._nframes = initlength / (self ._nchannels * self ._sampwidth )
531436 self ._datalength = self ._nframes * self ._nchannels * self ._sampwidth
532437 self ._form_length_pos = self ._file .tell ()
533- _write_long (self ._file , 36 + self ._datalength )
534- self ._file .write ('WAVE' )
535- self ._file .write ('fmt ' )
536- _write_long (self ._file , 16 )
537- _write_short (self ._file , WAVE_FORMAT_PCM )
538- _write_short (self ._file , self ._nchannels )
539- _write_long (self ._file , self ._framerate )
540- _write_long (self ._file , self ._nchannels * self ._framerate * self ._sampwidth )
541- _write_short (self ._file , self ._nchannels * self ._sampwidth )
542- _write_short (self ._file , self ._sampwidth * 8 )
543- self ._file .write ('data' )
438+ self ._file .write (struct .pack ('<lsslhhllhhs' ,
439+ 36 + self ._datalength , 'WAVE' , 'fmt ' , 16 ,
440+ WAVE_FORMAT_PCM , self ._nchannels , self ._framerate ,
441+ self ._nchannels * self ._framerate * self ._sampwidth ,
442+ self ._nchannels * self ._sampwidth ,
443+ self ._sampwidth * 8 , 'data' ))
544444 self ._data_length_pos = self ._file .tell ()
545- _write_long ( self ._file , self ._datalength )
445+ self ._file . write ( struct . pack ( '<l' , self ._datalength ) )
546446
547447 def _patchheader (self ):
548448 if self ._datawritten == self ._datalength :
549449 return
550450 curpos = self ._file .tell ()
551451 self ._file .seek (self ._form_length_pos , 0 )
552- _write_long ( self ._file , 36 + self ._datawritten )
452+ self ._file . write ( struct . pack ( '<l' , 36 + self ._datawritten ) )
553453 self ._file .seek (self ._data_length_pos , 0 )
554- _write_long ( self ._file , self ._datawritten )
454+ self ._file . write ( struct . pack ( '<l' , self ._datawritten ) )
555455 self ._file .seek (curpos , 0 )
556456 self ._datalength = self ._datawritten
557457
0 commit comments