Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /external /github.com /python /cpython /refs/tags/v1.0.1 /. /Lib /aifc.py
blob: aa1e56c4aaf116a2b86183f4a29b9f462e3ad042 [file] [log] [blame]
# Stuff to parse AIFF-C and AIFF files.
#
# Unless explicitly stated otherwise, the description below is true
# both for AIFF-C files and AIFF files.
#
# An AIFF-C file has the following structure.
#
#+-----------------+
#| FORM |
#+-----------------+
#| <size> |
#+----+------------+
#| | AIFC |
#| +------------+
#| | <chunks> |
#| | . |
#| | . |
#| | . |
#+----+------------+
#
# An AIFF file has the string "AIFF" instead of "AIFC".
#
# A chunk consists of an identifier (4 bytes) followed by a size (4 bytes,
# big endian order), followed by the data. The size field does not include
# the size of the 8 byte header.
#
# The following chunk types are recognized.
#
#FVER
#<version number of AIFF-C defining document> (AIFF-C only).
#MARK
#<# of markers> (2 bytes)
#list of markers:
#<marker ID> (2 bytes, must be > 0)
#<position> (4 bytes)
#<marker name> ("pstring")
#COMM
#<# of channels> (2 bytes)
#<# of sound frames> (4 bytes)
#<size of the samples> (2 bytes)
#<sampling frequency> (10 bytes, IEEE 80-bit extended
#floating point)
#in AIFF-C files only:
#<compression type> (4 bytes)
#<human-readable version of compression type> ("pstring")
#SSND
#<offset> (4 bytes, not used by this program)
#<blocksize> (4 bytes, not used by this program)
#<sound data>
#
# A pstring consists of 1 byte length, a string of characters, and 0 or 1
# byte pad to make the total length even.
#
# Usage.
#
# Reading AIFF files:
#f = aifc.open(file, 'r')
# where file is either the name of a file or an open file pointer.
# The open file pointer must have methods read(), seek(), and close().
# In some types of audio files, if the setpos() method is not used,
# the seek() method is not necessary.
#
# This returns an instance of a class with the following public methods:
#getnchannels()-- returns number of audio channels (1 for
# mono, 2 for stereo)
#getsampwidth()-- returns sample width in bytes
#getframerate()-- returns sampling frequency
#getnframes()-- returns number of audio frames
#getcomptype()-- returns compression type ('NONE' for AIFF files)
#getcompname()-- returns human-readable version of
# compression type ('not compressed' for AIFF files)
#getparams()-- returns a tuple consisting of all of the
# above in the above order
#getmarkers()-- get the list of marks in the audio file or None
# if there are no marks
#getmark(id)-- get mark with the specified id (raises an error
# if the mark does not exist)
#readframes(n)-- returns at most n frames of audio
#rewind()-- rewind to the beginning of the audio stream
#setpos(pos)-- seek to the specified position
#tell()-- return the current position
#close()-- close the instance (make it unusable)
# The position returned by tell(), the position given to setpos() and
# the position of marks are all compatible and have nothing to do with
# the actual postion in the file.
# The close() method is called automatically when the class instance
# is destroyed.
#
# Writing AIFF files:
#f = aifc.open(file, 'w')
# where file is either the name of a file or an open file pointer.
# The open file pointer must have methods write(), tell(), seek(), and
# close().
#
# This returns an instance of a class with the following public methods:
#aiff()-- create an AIFF file (AIFF-C default)
#aifc()-- create an AIFF-C file
#setnchannels(n)-- set the number of channels
#setsampwidth(n)-- set the sample width
#setframerate(n)-- set the frame rate
#setnframes(n)-- set the number of frames
#setcomptype(type, name)
#-- set the compression type and the
# human-readable compression type
#setparams(nchannels, sampwidth, framerate, nframes, comptype, compname)
#-- set all parameters at once
#setmark(id, pos, name)
#-- add specified mark to the list of marks
#tell()-- return current position in output file (useful
# in combination with setmark())
#writeframesraw(data)
#-- write audio frames without pathing up the
# file header
#writeframes(data)
#-- write audio frames and patch up the file header
#close()-- patch up the file header and close the
# output file
# You should set the parameters before the first writeframesraw or
# writeframes. The total number of frames does not need to be set,
# but when it is set to the correct value, the header does not have to
# be patched up.
# It is best to first set all parameters, perhaps possibly the
# compression type, and then write audio frames using writeframesraw.
# When all frames have been written, either call writeframes('') or
# close() to patch up the sizes in the header.
# Marks can be added anytime. If there are any marks, ypu must call
# close() after all frames have been written.
# The close() method is called automatically when the class instance
# is destroyed.
#
# When a file is opened with the extension '.aiff', an AIFF file is
# written, otherwise an AIFF-C file is written. This default can be
# changed by calling aiff() or aifc() before the first writeframes or
# writeframesraw.
import __builtin__
try:
import CL
exceptImportError:
pass
Error='aifc.Error'
_AIFC_version=0xA2805140# Version 1 of AIFF-C
_skiplist='COMT','INST','MIDI','AESD', \
'APPL','NAME','AUTH','(c) ','ANNO'
def _read_long(file):
x=0L
for iin range(4):
byte= file.read(1)
if byte=='':
raiseEOFError
x= x*256+ ord(byte)
if x>=0x80000000L:
x= x-0x100000000L
return int(x)
def _read_ulong(file):
x=0L
for iin range(4):
byte= file.read(1)
if byte=='':
raiseEOFError
x= x*256+ ord(byte)
return x
def _read_short(file):
x=0
for iin range(2):
byte= file.read(1)
if byte=='':
raiseEOFError
x= x*256+ ord(byte)
if x>=0x8000:
x= x-0x10000
return x
def _read_string(file):
length= ord(file.read(1))
data= file.read(length)
if length&1==0:
dummy= file.read(1)
return data
_HUGE_VAL=1.79769313486231e+308# See <limits.h>
def _read_float(f):# 10 bytes
import math
expon= _read_short(f)# 2 bytes
sign=1
if expon<0:
sign=-1
expon= expon+0x8000
himant= _read_ulong(f)# 4 bytes
lomant= _read_ulong(f)# 4 bytes
if expon== himant== lomant==0:
f=0.0
elif expon==0x7FFF:
f= _HUGE_VAL
else:
expon= expon-16383
f=(himant*0x100000000L+ lomant)* pow(2.0, expon-63)
return sign* f
def _write_short(f, x):
d, m= divmod(x,256)
f.write(chr(d))
f.write(chr(m))
def _write_long(f, x):
if x<0:
x= x+0x100000000L
data=[]
for iin range(4):
d, m= divmod(x,256)
data.insert(0, m)
x= d
for iin range(4):
f.write(chr(int(data[i])))
def _write_string(f, s):
f.write(chr(len(s)))
f.write(s)
if len(s)&1==0:
f.write(chr(0))
def _write_float(f, x):
import math
if x<0:
sign=0x8000
x= x*-1
else:
sign=0
if x==0:
expon=0
himant=0
lomant=0
else:
fmant, expon= math.frexp(x)
if expon>16384or fmant>=1:# Infinity or NaN
expon= sign|0x7FFF
himant=0
lomant=0
else:# Finite
expon= expon+16382
if expon<0:# denormalized
fmant= math.ldexp(fmant, expon)
expon=0
expon= expon| sign
fmant= math.ldexp(fmant,32)
fsmant= math.floor(fmant)
himant= long(fsmant)
fmant= math.ldexp(fmant- fsmant,32)
fsmant= math.floor(fmant)
lomant= long(fsmant)
_write_short(f, expon)
_write_long(f, himant)
_write_long(f, lomant)
classChunk:
def __init__(self, file):
self.file= file
self.chunkname= self.file.read(4)
if len(self.chunkname)<4:
raiseEOFError
self.chunksize= _read_long(self.file)
self.size_read=0
self.offset= self.file.tell()
def rewind(self):
self.file.seek(self.offset,0)
self.size_read=0
def setpos(self, pos):
if pos<0or pos> self.chunksize:
raiseRuntimeError
self.file.seek(self.offset+ pos,0)
self.size_read= pos
def read(self, length):
if self.size_read>= self.chunksize:
return''
if length> self.chunksize- self.size_read:
length= self.chunksize- self.size_read
data= self.file.read(length)
self.size_read= self.size_read+ len(data)
return data
def skip(self):
try:
self.file.seek(self.chunksize- self.size_read,1)
exceptRuntimeError:
while self.size_read< self.chunksize:
dummy= self.read(8192)
ifnot dummy:
raiseEOFError
if self.chunksize&1:
dummy= self.read(1)
classAifc_read:
# Variables used in this class:
#
# These variables are available to the user though appropriate
# methods of this class:
# _file -- the open file with methods read(), close(), and seek()
#set through the __init__() method
# _nchannels -- the number of audio channels
#available through the getnchannels() method
# _nframes -- the number of audio frames
#available through the getnframes() method
# _sampwidth -- the number of bytes per audio sample
#available through the getsampwidth() method
# _framerate -- the sampling frequency
#available through the getframerate() method
# _comptype -- the AIFF-C compression type ('NONE' if AIFF)
#available through the getcomptype() method
# _compname -- the human-readable AIFF-C compression type
#available through the getcomptype() method
# _markers -- the marks in the audio file
#available through the getmarkers() and getmark()
#methods
# _soundpos -- the position in the audio stream
#available through the tell() method, set through the
#setpos() method
#
# These variables are used internally only:
# _version -- the AIFF-C version number
# _decomp -- the decompressor from builtin module cl
# _comm_chunk_read -- 1 iff the COMM chunk has been read
# _aifc -- 1 iff reading an AIFF-C file
# _ssnd_seek_needed -- 1 iff positioned correctly in audio
#file for readframes()
# _ssnd_chunk -- instantiation of a chunk class for the SSND chunk
# _framesize -- size of one frame in the file
access _file, _nchannels, _nframes, _sampwidth, _framerate, \
_comptype, _compname, _markers, _soundpos, _version, \
_decomp, _comm_chunk_read, __aifc, _ssnd_seek_needed, \
_ssnd_chunk, _framesize: private
def initfp(self, file):
self._file= file
self._version=0
self._decomp=None
self._convert=None
self._markers=[]
self._soundpos=0
form= self._file.read(4)
if form!='FORM':
raiseError,'file does not start with FORM id'
formlength= _read_long(self._file)
if formlength<=0:
raiseError,'invalid FORM chunk data size'
formdata= self._file.read(4)
formlength= formlength-4
if formdata=='AIFF':
self._aifc=0
elif formdata=='AIFC':
self._aifc=1
else:
raiseError,'not an AIFF or AIFF-C file'
self._comm_chunk_read=0
while formlength>0:
self._ssnd_seek_needed=1
#DEBUG: SGI's soundfiler has a bug. There should
# be no need to check for EOF here.
try:
chunk=Chunk(self._file)
exceptEOFError:
if formlength==8:
print'Warning: FORM chunk size too large'
formlength=0
break
raiseEOFError# different error, raise exception
if chunk.chunkname=='COMM':
self._read_comm_chunk(chunk)
self._comm_chunk_read=1
elif chunk.chunkname=='SSND':
self._ssnd_chunk= chunk
dummy= chunk.read(8)
self._ssnd_seek_needed=0
elif chunk.chunkname=='FVER':
self._version= _read_long(chunk)
elif chunk.chunkname=='MARK':
self._readmark(chunk)
elif chunk.chunknamein _skiplist:
pass
else:
raiseError,'unrecognized chunk type '+chunk.chunkname
formlength= formlength-8- chunk.chunksize
if chunk.chunksize&1:
formlength= formlength-1
if formlength>0:
chunk.skip()
ifnot self._comm_chunk_readornot self._ssnd_chunk:
raiseError,'COMM chunk and/or SSND chunk missing'
if self._aifcand self._decomp:
params=[CL.ORIGINAL_FORMAT,0,
CL.BITS_PER_COMPONENT, self._sampwidth*8,
CL.FRAME_RATE, self._framerate]
if self._nchannels==1:
params[1]= CL.MONO
elif self._nchannels==2:
params[1]= CL.STEREO_INTERLEAVED
else:
raiseError,'cannot compress more than 2 channels'
self._decomp.SetParams(params)
def __init__(self, f):
if type(f)== type(''):
f= __builtin__.open(f,'r')
# else, assume it is an open file object already
self.initfp(f)
def __del__(self):
if self._file:
self.close()
#
# User visible methods.
#
def getfp(self):
return self._file
def rewind(self):
self._ssnd_seek_needed=1
self._soundpos=0
def close(self):
if self._decomp:
self._decomp.CloseDecompressor()
self._decomp=None
self._file=None
def tell(self):
return self._soundpos
def getnchannels(self):
return self._nchannels
def getnframes(self):
return self._nframes
def getsampwidth(self):
return self._sampwidth
def getframerate(self):
return self._framerate
def getcomptype(self):
return self._comptype
def getcompname(self):
return self._compname
##def getversion(self):
##return self._version
def getparams(self):
return self.getnchannels(), self.getsampwidth(), \
self.getframerate(), self.getnframes(), \
self.getcomptype(), self.getcompname()
def getmarkers(self):
if len(self._markers)==0:
returnNone
return self._markers
def getmark(self, id):
for markerin self._markers:
if id== marker[0]:
return marker
raiseError,'marker '+`id`+' does not exist'
def setpos(self, pos):
if pos<0or pos> self._nframes:
raiseError,'position not in range'
self._soundpos= pos
self._ssnd_seek_needed=1
def readframes(self, nframes):
if self._ssnd_seek_needed:
self._ssnd_chunk.rewind()
dummy= self._ssnd_chunk.read(8)
pos= self._soundpos* self._framesize
if pos:
self._ssnd_chunk.setpos(pos+8)
self._ssnd_seek_needed=0
if nframes==0:
return''
data= self._ssnd_chunk.read(nframes* self._framesize)
if self._convertand data:
data= self._convert(data)
self._soundpos= self._soundpos+ len(data)/(self._nchannels* self._sampwidth)
return data
#
# Internal methods.
#
access*: private
def _decomp_data(self, data):
dummy= self._decomp.SetParam(CL.FRAME_BUFFER_SIZE,
len(data)*2)
return self._decomp.Decompress(len(data)/ self._nchannels,
data)
def _ulaw2lin(self, data):
import audioop
return audioop.ulaw2lin(data,2)
def _read_comm_chunk(self, chunk):
self._nchannels= _read_short(chunk)
self._nframes= _read_long(chunk)
self._sampwidth=(_read_short(chunk)+7)/8
self._framerate= int(_read_float(chunk))
self._framesize= self._nchannels* self._sampwidth
if self._aifc:
#DEBUG: SGI's soundeditor produces a bad size :-(
kludge=0
if chunk.chunksize==18:
kludge=1
print'Warning: bad COMM chunk size'
chunk.chunksize=23
#DEBUG end
self._comptype= chunk.read(4)
#DEBUG start
if kludge:
length= ord(chunk.file.read(1))
if length&1==0:
length= length+1
chunk.chunksize= chunk.chunksize+ length
chunk.file.seek(-1,1)
#DEBUG end
self._compname= _read_string(chunk)
if self._comptype!='NONE':
try:
import cl, CL
exceptImportError:
if self._comptype=='ULAW':
try:
import audioop
self._convert= self._ulaw2lin
self._framesize= self._framesize/2
return
exceptImportError:
pass
raiseError,'cannot read compressed AIFF-C files'
if self._comptype=='ULAW':
scheme= CL.G711_ULAW
self._framesize= self._framesize/2
elif self._comptype=='ALAW':
scheme= CL.G711_ALAW
self._framesize= self._framesize/2
else:
raiseError,'unsupported compression type'
self._decomp= cl.OpenDecompressor(scheme)
self._convert= self._decomp_data
else:
self._comptype='NONE'
self._compname='not compressed'
def _readmark(self, chunk):
nmarkers= _read_short(chunk)
# Some files appear to contain invalid counts.
# Cope with this by testing for EOF.
try:
for iin range(nmarkers):
id= _read_short(chunk)
pos= _read_long(chunk)
name= _read_string(chunk)
self._markers.append((id, pos, name))
exceptEOFError:
print'Warning: MARK chunk contains only',
print len(self._markers),
if len(self._markers)==1:print'marker',
else:print'markers',
print'instead of', nmarkers
classAifc_write:
# Variables used in this class:
#
# These variables are user settable through appropriate methods
# of this class:
# _file -- the open file with methods write(), close(), tell(), seek()
#set through the __init__() method
# _comptype -- the AIFF-C compression type ('NONE' in AIFF)
#set through the setcomptype() or setparams() method
# _compname -- the human-readable AIFF-C compression type
#set through the setcomptype() or setparams() method
# _nchannels -- the number of audio channels
#set through the setnchannels() or setparams() method
# _sampwidth -- the number of bytes per audio sample
#set through the setsampwidth() or setparams() method
# _framerate -- the sampling frequency
#set through the setframerate() or setparams() method
# _nframes -- the number of audio frames written to the header
#set through the setnframes() or setparams() method
# _aifc -- whether we're writing an AIFF-C file or an AIFF file
#set through the aifc() method, reset through the
#aiff() method
#
# These variables are used internally only:
# _version -- the AIFF-C version number
# _comp -- the compressor from builtin module cl
# _nframeswritten -- the number of audio frames actually written
# _datalength -- the size of the audio samples written to the header
# _datawritten -- the size of the audio samples actually written
access _file, _comptype, _compname, _nchannels, _sampwidth, \
_framerate, _nframes, _aifc, _version, _comp, \
_nframeswritten, _datalength, _datawritten: private
def __init__(self, f):
if type(f)== type(''):
filename= f
f= __builtin__.open(f,'w')
else:
# else, assume it is an open file object already
filename='???'
self.initfp(f)
if filename[-5:]=='.aiff':
self._aifc=0
else:
self._aifc=1
def initfp(self, file):
self._file= file
self._version= _AIFC_version
self._comptype='NONE'
self._compname='not compressed'
self._comp=None
self._convert=None
self._nchannels=0
self._sampwidth=0
self._framerate=0
self._nframes=0
self._nframeswritten=0
self._datawritten=0
self._datalength=0
self._markers=[]
self._marklength=0
self._aifc=1# AIFF-C is default
def __del__(self):
if self._file:
self.close()
#
# User visible methods.
#
def aiff(self):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
self._aifc=0
def aifc(self):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
self._aifc=1
def setnchannels(self, nchannels):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
if nchannels<1:
raiseError,'bad # of channels'
self._nchannels= nchannels
def getnchannels(self):
ifnot self._nchannels:
raiseError,'number of channels not set'
return self._nchannels
def setsampwidth(self, sampwidth):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
if sampwidth<1or sampwidth>4:
raiseError,'bad sample width'
self._sampwidth= sampwidth
def getsampwidth(self):
ifnot self._sampwidth:
raiseError,'sample width not set'
return self._sampwidth
def setframerate(self, framerate):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
if framerate<=0:
raiseError,'bad frame rate'
self._framerate= framerate
def getframerate(self):
ifnot self._framerate:
raiseError,'frame rate not set'
return self._framerate
def setnframes(self, nframes):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
self._nframes= nframes
def getnframes(self):
return self._nframeswritten
def setcomptype(self, comptype, compname):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
if comptypenotin('NONE','ULAW','ALAW'):
raiseError,'unsupported compression type'
self._comptype= comptype
self._compname= compname
def getcomptype(self):
return self._comptype
def getcompname(self):
return self._compname
##def setversion(self, version):
##if self._nframeswritten:
##raise Error, 'cannot change parameters after starting to write'
##self._version = version
def setparams(self,(nchannels, sampwidth, framerate, nframes, comptype, compname)):
if self._nframeswritten:
raiseError,'cannot change parameters after starting to write'
if comptypenotin('NONE','ULAW','ALAW'):
raiseError,'unsupported compression type'
self.setnchannels(nchannels)
self.setsampwidth(sampwidth)
self.setframerate(framerate)
self.setnframes(nframes)
self.setcomptype(comptype, compname)
def getparams(self):
ifnot self._nchannelsornot self._sampwidthornot self._framerate:
raiseError,'not all parameters set'
return self._nchannels, self._sampwidth, self._framerate, \
self._nframes, self._comptype, self._compname
def setmark(self, id, pos, name):
if id<=0:
raiseError,'marker ID must be > 0'
if pos<0:
raiseError,'marker position must be >= 0'
if type(name)!= type(''):
raiseError,'marker name must be a string'
for iin range(len(self._markers)):
if id== self._markers[i][0]:
self._markers[i]= id, pos, name
return
self._markers.append((id, pos, name))
def getmark(self, id):
for markerin self._markers:
if id== marker[0]:
return marker
raiseError,'marker '+`id`+' does not exist'
def getmarkers(self):
if len(self._markers)==0:
returnNone
return self._markers
def tell(self):
return self._nframeswritten
def writeframesraw(self, data):
self._ensure_header_written(len(data))
nframes= len(data)/(self._sampwidth* self._nchannels)
if self._convert:
data= self._convert(data)
self._file.write(data)
self._nframeswritten= self._nframeswritten+ nframes
self._datawritten= self._datawritten+ len(data)
def writeframes(self, data):
self.writeframesraw(data)
if self._nframeswritten!= self._nframesor \
self._datalength!= self._datawritten:
self._patchheader()
def close(self):
self._ensure_header_written(0)
if self._datawritten&1:
# quick pad to even size
self._file.write(chr(0))
self._datawritten= self._datawritten+1
self._writemarkers()
if self._nframeswritten!= self._nframesor \
self._datalength!= self._datawrittenor \
self._marklength:
self._patchheader()
if self._comp:
self._comp.CloseCompressor()
self._comp=None
self._file.flush()
self._file=None
#
# Internal methods.
#
access*: private
def _comp_data(self, data):
dum= self._comp.SetParam(CL.FRAME_BUFFER_SIZE, len(data))
dum= self._comp.SetParam(CL.COMPRESSED_BUFFER_SIZE, len(data))
return self._comp.Compress(nframes, data)
def _lin2ulaw(self, data):
import audioop
return audioop.lin2ulaw(data,2)
def _ensure_header_written(self, datasize):
ifnot self._nframeswritten:
if self._comptypein('ULAW','ALAW'):
ifnot self._sampwidth:
self._sampwidth=2
if self._sampwidth!=2:
raiseError,'sample width must be 2 when compressing with ULAW or ALAW'
ifnot self._nchannels:
raiseError,'# channels not specified'
ifnot self._sampwidth:
raiseError,'sample width not specified'
ifnot self._framerate:
raiseError,'sampling rate not specified'
self._write_header(datasize)
def _init_compression(self):
try:
import cl, CL
exceptImportError:
if self._comptype=='ULAW':
try:
import audioop
self._convert= self._lin2ulaw
return
exceptImportError:
pass
raiseError,'cannot write compressed AIFF-C files'
if self._comptype=='ULAW':
scheme= CL.G711_ULAW
elif self._comptype=='ALAW':
scheme= CL.G711_ALAW
else:
raiseError,'unsupported compression type'
self._comp= cl.OpenCompressor(scheme)
params=[CL.ORIGINAL_FORMAT,0,
CL.BITS_PER_COMPONENT, self._sampwidth*8,
CL.FRAME_RATE, self._framerate,
CL.FRAME_BUFFER_SIZE,100,
CL.COMPRESSED_BUFFER_SIZE,100]
if self._nchannels==1:
params[1]= CL.MONO
elif self._nchannels==2:
params[1]= CL.STEREO_INTERLEAVED
else:
raiseError,'cannot compress more than 2 channels'
self._comp.SetParams(params)
# the compressor produces a header which we ignore
dummy= self._comp.Compress(0,'')
self._convert= self._comp_data
def _write_header(self, initlength):
if self._aifcand self._comptype!='NONE':
self._init_compression()
self._file.write('FORM')
ifnot self._nframes:
self._nframes= initlength/(self._nchannels* self._sampwidth)
self._datalength= self._nframes* self._nchannels* self._sampwidth
if self._datalength&1:
self._datalength= self._datalength+1
if self._aifcand self._comptypein('ULAW','ALAW'):
self._datalength= self._datalength/2
if self._datalength&1:
self._datalength= self._datalength+1
self._form_length_pos= self._file.tell()
commlength= self._write_form_length(self._datalength)
if self._aifc:
self._file.write('AIFC')
self._file.write('FVER')
_write_long(self._file,4)
_write_long(self._file, self._version)
else:
self._file.write('AIFF')
self._file.write('COMM')
_write_long(self._file, commlength)
_write_short(self._file, self._nchannels)
self._nframes_pos= self._file.tell()
_write_long(self._file, self._nframes)
_write_short(self._file, self._sampwidth*8)
_write_float(self._file, self._framerate)
if self._aifc:
self._file.write(self._comptype)
_write_string(self._file, self._compname)
self._file.write('SSND')
self._ssnd_length_pos= self._file.tell()
_write_long(self._file, self._datalength+8)
_write_long(self._file,0)
_write_long(self._file,0)
def _write_form_length(self, datalength):
if self._aifc:
commlength=18+5+ len(self._compname)
if commlength&1:
commlength= commlength+1
verslength=12
else:
commlength=18
verslength=0
_write_long(self._file,4+ verslength+ self._marklength+ \
8+ commlength+16+ datalength)
return commlength
def _patchheader(self):
curpos= self._file.tell()
if self._datawritten&1:
datalength= self._datawritten+1
self._file.write(chr(0))
else:
datalength= self._datawritten
if datalength== self._datalengthand \
self._nframes== self._nframeswrittenand \
self._marklength==0:
self._file.seek(curpos,0)
return
self._file.seek(self._form_length_pos,0)
dummy= self._write_form_length(datalength)
self._file.seek(self._nframes_pos,0)
_write_long(self._file, self._nframeswritten)
self._file.seek(self._ssnd_length_pos,0)
_write_long(self._file, datalength+8)
self._file.seek(curpos,0)
self._nframes= self._nframeswritten
self._datalength= datalength
def _writemarkers(self):
if len(self._markers)==0:
return
self._file.write('MARK')
length=2
for markerin self._markers:
id, pos, name= marker
length= length+ len(name)+1+6
if len(name)&1==0:
length= length+1
_write_long(self._file, length)
self._marklength= length+8
_write_short(self._file, len(self._markers))
for markerin self._markers:
id, pos, name= marker
_write_short(self._file, id)
_write_long(self._file, pos)
_write_string(self._file, name)
def open(f, mode):
if mode=='r':
returnAifc_read(f)
elif mode=='w':
returnAifc_write(f)
else:
raiseError,"mode must be 'r' or 'w'"
openfp= open# B/W compatibility

[8]ページ先頭

©2009-2025 Movatter.jp