183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""Stuff to parse AIFF-C and AIFF files. 283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehUnless explicitly stated otherwise, the description below is true 483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehboth for AIFF-C files and AIFF files. 583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehAn AIFF-C file has the following structure. 783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh +-----------------+ 983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | FORM | 1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh +-----------------+ 1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | <size> | 1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh +----+------------+ 1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | | AIFC | 1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | +------------+ 1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | | <chunks> | 1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | | . | 1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | | . | 1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh | | . | 1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh +----+------------+ 2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehAn AIFF file has the string "AIFF" instead of "AIFC". 2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehA chunk consists of an identifier (4 bytes) followed by a size (4 bytes, 2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehbig endian order), followed by the data. The size field does not include 2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehthe size of the 8 byte header. 2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe following chunk types are recognized. 2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh FVER 3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <version number of AIFF-C defining document> (AIFF-C only). 3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh MARK 3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <# of markers> (2 bytes) 3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh list of markers: 3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <marker ID> (2 bytes, must be > 0) 3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <position> (4 bytes) 3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <marker name> ("pstring") 3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh COMM 3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <# of channels> (2 bytes) 3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <# of sound frames> (4 bytes) 4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <size of the samples> (2 bytes) 4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <sampling frequency> (10 bytes, IEEE 80-bit extended 4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh floating point) 4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh in AIFF-C files only: 4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <compression type> (4 bytes) 4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <human-readable version of compression type> ("pstring") 4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh SSND 4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <offset> (4 bytes, not used by this program) 4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <blocksize> (4 bytes, not used by this program) 4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh <sound data> 5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehA pstring consists of 1 byte length, a string of characters, and 0 or 1 5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehbyte pad to make the total length even. 5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehUsage. 5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehReading AIFF files: 5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = aifc.open(file, 'r') 5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwhere file is either the name of a file or an open file pointer. 5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe open file pointer must have methods read(), seek(), and close(). 6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehIn some types of audio files, if the setpos() method is not used, 6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehthe seek() method is not necessary. 6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThis returns an instance of a class with the following public methods: 6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getnchannels() -- returns number of audio channels (1 for 6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh mono, 2 for stereo) 6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getsampwidth() -- returns sample width in bytes 6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getframerate() -- returns sampling frequency 6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getnframes() -- returns number of audio frames 6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getcomptype() -- returns compression type ('NONE' for AIFF files) 7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getcompname() -- returns human-readable version of 7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh compression type ('not compressed' for AIFF files) 7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getparams() -- returns a tuple consisting of all of the 7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh above in the above order 7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getmarkers() -- get the list of marks in the audio file or None 7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if there are no marks 7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh getmark(id) -- get mark with the specified id (raises an error 7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if the mark does not exist) 7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh readframes(n) -- returns at most n frames of audio 7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh rewind() -- rewind to the beginning of the audio stream 8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setpos(pos) -- seek to the specified position 8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh tell() -- return the current position 8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh close() -- close the instance (make it unusable) 8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe position returned by tell(), the position given to setpos() and 8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehthe position of marks are all compatible and have nothing to do with 8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehthe actual position in the file. 8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe close() method is called automatically when the class instance 8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehis destroyed. 8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehWriting AIFF files: 9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = aifc.open(file, 'w') 9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwhere file is either the name of a file or an open file pointer. 9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe open file pointer must have methods write(), tell(), seek(), and 9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclose(). 9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThis returns an instance of a class with the following public methods: 9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh aiff() -- create an AIFF file (AIFF-C default) 9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh aifc() -- create an AIFF-C file 9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setnchannels(n) -- set the number of channels 9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setsampwidth(n) -- set the sample width 10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setframerate(n) -- set the frame rate 10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setnframes(n) -- set the number of frames 10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setcomptype(type, name) 10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh -- set the compression type and the 10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh human-readable compression type 10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setparams(tuple) 10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh -- set all parameters at once 10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh setmark(id, pos, name) 10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh -- add specified mark to the list of marks 10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh tell() -- return current position in output file (useful 11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh in combination with setmark()) 11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh writeframesraw(data) 11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh -- write audio frames without pathing up the 11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh file header 11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh writeframes(data) 11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh -- write audio frames and patch up the file header 11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh close() -- patch up the file header and close the 11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh output file 11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehYou should set the parameters before the first writeframesraw or 11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwriteframes. The total number of frames does not need to be set, 12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehbut when it is set to the correct value, the header does not have to 12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehbe patched up. 12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehIt is best to first set all parameters, perhaps possibly the 12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehcompression type, and then write audio frames using writeframesraw. 12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehWhen all frames have been written, either call writeframes('') or 12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclose() to patch up the sizes in the header. 12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehMarks can be added anytime. If there are any marks, ypu must call 12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclose() after all frames have been written. 12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe close() method is called automatically when the class instance 12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehis destroyed. 13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehWhen a file is opened with the extension '.aiff', an AIFF file is 13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwritten, otherwise an AIFF-C file is written. This default can be 13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehchanged by calling aiff() or aifc() before the first writeframes or 13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwriteframesraw. 13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh""" 13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport struct 13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport __builtin__ 13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__all__ = ["Error","open","openfp"] 14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Error(Exception): 14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pass 14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_AIFC_version = 0xA2805140L # Version 1 of AIFF-C 14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _read_long(file): 14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return struct.unpack('>l', file.read(4))[0] 15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except struct.error: 15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise EOFError 15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _read_ulong(file): 15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return struct.unpack('>L', file.read(4))[0] 15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except struct.error: 15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise EOFError 15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _read_short(file): 16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return struct.unpack('>h', file.read(2))[0] 16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except struct.error: 16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise EOFError 16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _read_ushort(file): 16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return struct.unpack('>H', file.read(2))[0] 16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except struct.error: 16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise EOFError 17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _read_string(file): 17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh length = ord(file.read(1)) 17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if length == 0: 17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = '' 17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = file.read(length) 17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if length & 1 == 0: 17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = file.read(1) 17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return data 18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh_HUGE_VAL = 1.79769313486231e+308 # See <limits.h> 18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _read_float(f): # 10 bytes 18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = _read_short(f) # 2 bytes 18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sign = 1 18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if expon < 0: 18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sign = -1 18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = expon + 0x8000 18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh himant = _read_ulong(f) # 4 bytes 19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh lomant = _read_ulong(f) # 4 bytes 19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if expon == himant == lomant == 0: 19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = 0.0 19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif expon == 0x7FFF: 19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = _HUGE_VAL 19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = expon - 16383 19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = (himant * 0x100000000L + lomant) * pow(2.0, expon - 63) 19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return sign * f 19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _write_short(f, x): 20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.write(struct.pack('>h', x)) 20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _write_ushort(f, x): 20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.write(struct.pack('>H', x)) 20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _write_long(f, x): 20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.write(struct.pack('>l', x)) 20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _write_ulong(f, x): 21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.write(struct.pack('>L', x)) 21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _write_string(f, s): 21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(s) > 255: 21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise ValueError("string exceeds maximum pstring length") 21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.write(struct.pack('B', len(s))) 21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.write(s) 21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(s) & 1 == 0: 21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.write(chr(0)) 21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _write_float(f, x): 22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import math 22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if x < 0: 22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sign = 0x8000 22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh x = x * -1 22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sign = 0 22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if x == 0: 22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = 0 22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh himant = 0 23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh lomant = 0 23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fmant, expon = math.frexp(x) 23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if expon > 16384 or fmant >= 1 or fmant != fmant: # Infinity or NaN 23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = sign|0x7FFF 23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh himant = 0 23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh lomant = 0 23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: # Finite 23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = expon + 16382 23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if expon < 0: # denormalized 24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fmant = math.ldexp(fmant, expon) 24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = 0 24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh expon = expon | sign 24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fmant = math.ldexp(fmant, 32) 24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fsmant = math.floor(fmant) 24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh himant = long(fsmant) 24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fmant = math.ldexp(fmant - fsmant, 32) 24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fsmant = math.floor(fmant) 24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh lomant = long(fsmant) 24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ushort(f, expon) 25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(f, himant) 25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(f, lomant) 25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom chunk import Chunk 25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Aifc_read: 25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Variables used in this class: 25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # These variables are available to the user though appropriate 25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # methods of this class: 26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _file -- the open file with methods read(), close(), and seek() 26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the __init__() method 26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _nchannels -- the number of audio channels 26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the getnchannels() method 26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _nframes -- the number of audio frames 26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the getnframes() method 26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _sampwidth -- the number of bytes per audio sample 26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the getsampwidth() method 26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _framerate -- the sampling frequency 26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the getframerate() method 27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _comptype -- the AIFF-C compression type ('NONE' if AIFF) 27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the getcomptype() method 27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _compname -- the human-readable AIFF-C compression type 27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the getcomptype() method 27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _markers -- the marks in the audio file 27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the getmarkers() and getmark() 27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # methods 27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _soundpos -- the position in the audio stream 27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # available through the tell() method, set through the 27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # setpos() method 28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # These variables are used internally only: 28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _version -- the AIFF-C version number 28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _decomp -- the decompressor from builtin module cl 28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _comm_chunk_read -- 1 iff the COMM chunk has been read 28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _aifc -- 1 iff reading an AIFF-C file 28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _ssnd_seek_needed -- 1 iff positioned correctly in audio 28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # file for readframes() 28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _ssnd_chunk -- instantiation of a chunk class for the SSND chunk 28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _framesize -- size of one frame in the file 29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def initfp(self, file): 29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._version = 0 29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._decomp = None 29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = None 29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._markers = [] 29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._soundpos = 0 29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file = file 29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chunk = Chunk(file) 29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if chunk.getname() != 'FORM': 30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'file does not start with FORM id' 30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh formdata = chunk.read(4) 30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if formdata == 'AIFF': 30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._aifc = 0 30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif formdata == 'AIFC': 30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._aifc = 1 30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'not an AIFF or AIFF-C file' 30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comm_chunk_read = 0 30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh while 1: 31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_seek_needed = 1 31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chunk = Chunk(self._file) 31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except EOFError: 31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh break 31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chunkname = chunk.getname() 31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if chunkname == 'COMM': 31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._read_comm_chunk(chunk) 31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comm_chunk_read = 1 31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif chunkname == 'SSND': 32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_chunk = chunk 32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = chunk.read(8) 32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_seek_needed = 0 32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif chunkname == 'FVER': 32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._version = _read_ulong(chunk) 32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif chunkname == 'MARK': 32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._readmark(chunk) 32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chunk.skip() 32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._comm_chunk_read or not self._ssnd_chunk: 32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'COMM chunk and/or SSND chunk missing' 33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._aifc and self._decomp: 33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import cl 33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh params = [cl.ORIGINAL_FORMAT, 0, 33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cl.BITS_PER_COMPONENT, self._sampwidth * 8, 33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cl.FRAME_RATE, self._framerate] 33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nchannels == 1: 33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh params[1] = cl.MONO 33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif self._nchannels == 2: 33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh params[1] = cl.STEREO_INTERLEAVED 33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot compress more than 2 channels' 34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._decomp.SetParams(params) 34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, f): 34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if type(f) == type(''): 34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = __builtin__.open(f, 'rb') 34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # else, assume it is an open file object already 34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.initfp(f) 34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # User visible methods. 35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getfp(self): 35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._file 35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 35583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def rewind(self): 35683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_seek_needed = 1 35783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._soundpos = 0 35883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 35983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def close(self): 36083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._decomp: 36183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._decomp.CloseDecompressor() 36283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._decomp = None 36383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.close() 36483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 36583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def tell(self): 36683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._soundpos 36783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 36883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getnchannels(self): 36983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._nchannels 37083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getnframes(self): 37283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._nframes 37383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getsampwidth(self): 37583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._sampwidth 37683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 37783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getframerate(self): 37883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._framerate 37983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 38083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getcomptype(self): 38183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._comptype 38283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 38383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getcompname(self): 38483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._compname 38583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 38683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## def getversion(self): 38783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## return self._version 38883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 38983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getparams(self): 39083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self.getnchannels(), self.getsampwidth(), \ 39183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.getframerate(), self.getnframes(), \ 39283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.getcomptype(), self.getcompname() 39383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 39483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getmarkers(self): 39583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(self._markers) == 0: 39683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return None 39783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._markers 39883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 39983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getmark(self, id): 40083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for marker in self._markers: 40183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if id == marker[0]: 40283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return marker 40383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'marker %r does not exist' % (id,) 40483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 40583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setpos(self, pos): 40683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if pos < 0 or pos > self._nframes: 40783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'position not in range' 40883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._soundpos = pos 40983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_seek_needed = 1 41083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 41183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def readframes(self, nframes): 41283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._ssnd_seek_needed: 41383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_chunk.seek(0) 41483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = self._ssnd_chunk.read(8) 41583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pos = self._soundpos * self._framesize 41683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if pos: 41783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_chunk.seek(pos + 8) 41883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_seek_needed = 0 41983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if nframes == 0: 42083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return '' 42183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = self._ssnd_chunk.read(nframes * self._framesize) 42283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._convert and data: 42383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = self._convert(data) 42483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._soundpos = self._soundpos + len(data) // (self._nchannels * self._sampwidth) 42583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return data 42683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 42783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 42883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Internal methods. 42983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 43083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 43183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _decomp_data(self, data): 43283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import cl 43383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = self._decomp.SetParam(cl.FRAME_BUFFER_SIZE, 43483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh len(data) * 2) 43583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._decomp.Decompress(len(data) // self._nchannels, 43683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data) 43783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 43883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _ulaw2lin(self, data): 43983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import audioop 44083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return audioop.ulaw2lin(data, 2) 44183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 44283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _adpcm2lin(self, data): 44383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import audioop 44483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not hasattr(self, '_adpcmstate'): 44583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # first time 44683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._adpcmstate = None 44783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data, self._adpcmstate = audioop.adpcm2lin(data, 2, 44883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._adpcmstate) 44983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return data 45083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 45183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _read_comm_chunk(self, chunk): 45283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nchannels = _read_short(chunk) 45383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes = _read_long(chunk) 45483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._sampwidth = (_read_short(chunk) + 7) // 8 45583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framerate = int(_read_float(chunk)) 45683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framesize = self._nchannels * self._sampwidth 45783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._aifc: 45883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #DEBUG: SGI's soundeditor produces a bad size :-( 45983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh kludge = 0 46083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if chunk.chunksize == 18: 46183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh kludge = 1 46283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print 'Warning: bad COMM chunk size' 46383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chunk.chunksize = 23 46483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #DEBUG end 46583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comptype = chunk.read(4) 46683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #DEBUG start 46783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if kludge: 46883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh length = ord(chunk.file.read(1)) 46983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if length & 1 == 0: 47083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh length = length + 1 47183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chunk.chunksize = chunk.chunksize + length 47283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chunk.file.seek(-1, 1) 47383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh #DEBUG end 47483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._compname = _read_string(chunk) 47583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype != 'NONE': 47683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype == 'G722': 47783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 47883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import audioop 47983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except ImportError: 48083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pass 48183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 48283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = self._adpcm2lin 48383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framesize = self._framesize // 4 48483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 48583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # for ULAW and ALAW try Compression Library 48683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 48783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import cl 48883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except ImportError: 48983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype == 'ULAW': 49083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 49183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import audioop 49283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = self._ulaw2lin 49383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framesize = self._framesize // 2 49483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 49583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except ImportError: 49683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pass 49783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot read compressed AIFF-C files' 49883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype == 'ULAW': 49983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh scheme = cl.G711_ULAW 50083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framesize = self._framesize // 2 50183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif self._comptype == 'ALAW': 50283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh scheme = cl.G711_ALAW 50383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framesize = self._framesize // 2 50483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 50583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'unsupported compression type' 50683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._decomp = cl.OpenDecompressor(scheme) 50783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = self._decomp_data 50883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 50983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comptype = 'NONE' 51083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._compname = 'not compressed' 51183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 51283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _readmark(self, chunk): 51383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh nmarkers = _read_short(chunk) 51483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Some files appear to contain invalid counts. 51583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Cope with this by testing for EOF. 51683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 51783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for i in range(nmarkers): 51883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh id = _read_short(chunk) 51983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pos = _read_long(chunk) 52083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh name = _read_string(chunk) 52183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if pos or name: 52283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # some files appear to have 52383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # dummy markers consisting of 52483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # a position 0 and name '' 52583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._markers.append((id, pos, name)) 52683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except EOFError: 52783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print 'Warning: MARK chunk contains only', 52883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print len(self._markers), 52983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(self._markers) == 1: print 'marker', 53083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: print 'markers', 53183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print 'instead of', nmarkers 53283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 53383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass Aifc_write: 53483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Variables used in this class: 53583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 53683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # These variables are user settable through appropriate methods 53783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # of this class: 53883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _file -- the open file with methods write(), close(), tell(), seek() 53983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the __init__() method 54083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _comptype -- the AIFF-C compression type ('NONE' in AIFF) 54183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the setcomptype() or setparams() method 54283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _compname -- the human-readable AIFF-C compression type 54383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the setcomptype() or setparams() method 54483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _nchannels -- the number of audio channels 54583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the setnchannels() or setparams() method 54683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _sampwidth -- the number of bytes per audio sample 54783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the setsampwidth() or setparams() method 54883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _framerate -- the sampling frequency 54983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the setframerate() or setparams() method 55083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _nframes -- the number of audio frames written to the header 55183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the setnframes() or setparams() method 55283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _aifc -- whether we're writing an AIFF-C file or an AIFF file 55383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # set through the aifc() method, reset through the 55483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # aiff() method 55583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 55683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # These variables are used internally only: 55783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _version -- the AIFF-C version number 55883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _comp -- the compressor from builtin module cl 55983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _nframeswritten -- the number of audio frames actually written 56083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _datalength -- the size of the audio samples written to the header 56183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # _datawritten -- the size of the audio samples actually written 56283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 56383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, f): 56483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if type(f) == type(''): 56583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh filename = f 56683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = __builtin__.open(f, 'wb') 56783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 56883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # else, assume it is an open file object already 56983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh filename = '???' 57083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.initfp(f) 57183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if filename[-5:] == '.aiff': 57283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._aifc = 0 57383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 57483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._aifc = 1 57583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 57683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def initfp(self, file): 57783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file = file 57883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._version = _AIFC_version 57983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comptype = 'NONE' 58083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._compname = 'not compressed' 58183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comp = None 58283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = None 58383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nchannels = 0 58483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._sampwidth = 0 58583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framerate = 0 58683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes = 0 58783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframeswritten = 0 58883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datawritten = 0 58983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = 0 59083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._markers = [] 59183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._marklength = 0 59283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._aifc = 1 # AIFF-C is default 59383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 59483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __del__(self): 59583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._file: 59683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.close() 59783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 59883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 59983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # User visible methods. 60083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 60183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def aiff(self): 60283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 60383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 60483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._aifc = 0 60583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 60683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def aifc(self): 60783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 60883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 60983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._aifc = 1 61083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 61183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setnchannels(self, nchannels): 61283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 61383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 61483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if nchannels < 1: 61583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'bad # of channels' 61683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nchannels = nchannels 61783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 61883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getnchannels(self): 61983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._nchannels: 62083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'number of channels not set' 62183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._nchannels 62283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 62383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setsampwidth(self, sampwidth): 62483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 62583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 62683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if sampwidth < 1 or sampwidth > 4: 62783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'bad sample width' 62883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._sampwidth = sampwidth 62983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 63083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getsampwidth(self): 63183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._sampwidth: 63283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'sample width not set' 63383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._sampwidth 63483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 63583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setframerate(self, framerate): 63683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 63783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 63883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if framerate <= 0: 63983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'bad frame rate' 64083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._framerate = framerate 64183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 64283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getframerate(self): 64383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._framerate: 64483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'frame rate not set' 64583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._framerate 64683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 64783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setnframes(self, nframes): 64883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 64983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 65083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes = nframes 65183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 65283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getnframes(self): 65383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._nframeswritten 65483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 65583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setcomptype(self, comptype, compname): 65683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 65783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 65883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'): 65983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'unsupported compression type' 66083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comptype = comptype 66183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._compname = compname 66283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 66383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getcomptype(self): 66483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._comptype 66583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 66683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getcompname(self): 66783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._compname 66883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 66983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## def setversion(self, version): 67083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## if self._nframeswritten: 67183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## raise Error, 'cannot change parameters after starting to write' 67283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh## self._version = version 67383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 67483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setparams(self, info): 67583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh nchannels, sampwidth, framerate, nframes, comptype, compname = info 67683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten: 67783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot change parameters after starting to write' 67883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722'): 67983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'unsupported compression type' 68083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.setnchannels(nchannels) 68183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.setsampwidth(sampwidth) 68283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.setframerate(framerate) 68383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.setnframes(nframes) 68483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.setcomptype(comptype, compname) 68583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 68683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getparams(self): 68783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._nchannels or not self._sampwidth or not self._framerate: 68883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'not all parameters set' 68983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._nchannels, self._sampwidth, self._framerate, \ 69083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes, self._comptype, self._compname 69183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 69283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def setmark(self, id, pos, name): 69383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if id <= 0: 69483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'marker ID must be > 0' 69583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if pos < 0: 69683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'marker position must be >= 0' 69783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if type(name) != type(''): 69883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'marker name must be a string' 69983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for i in range(len(self._markers)): 70083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if id == self._markers[i][0]: 70183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._markers[i] = id, pos, name 70283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 70383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._markers.append((id, pos, name)) 70483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 70583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getmark(self, id): 70683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for marker in self._markers: 70783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if id == marker[0]: 70883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return marker 70983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'marker %r does not exist' % (id,) 71083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 71183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def getmarkers(self): 71283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(self._markers) == 0: 71383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return None 71483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._markers 71583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 71683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def tell(self): 71783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._nframeswritten 71883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 71983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def writeframesraw(self, data): 72083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ensure_header_written(len(data)) 72183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh nframes = len(data) // (self._sampwidth * self._nchannels) 72283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._convert: 72383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = self._convert(data) 72483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write(data) 72583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframeswritten = self._nframeswritten + nframes 72683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datawritten = self._datawritten + len(data) 72783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 72883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def writeframes(self, data): 72983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.writeframesraw(data) 73083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten != self._nframes or \ 73183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength != self._datawritten: 73283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._patchheader() 73383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 73483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def close(self): 73583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._file is None: 73683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 73783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 73883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ensure_header_written(0) 73983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._datawritten & 1: 74083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # quick pad to even size 74183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write(chr(0)) 74283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datawritten = self._datawritten + 1 74383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._writemarkers() 74483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nframeswritten != self._nframes or \ 74583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength != self._datawritten or \ 74683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._marklength: 74783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._patchheader() 74883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comp: 74983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comp.CloseCompressor() 75083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comp = None 75183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh finally: 75283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Prevent ref cycles 75383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = None 75483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = self._file 75583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file = None 75683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.close() 75783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 75883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 75983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # Internal methods. 76083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # 76183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 76283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _comp_data(self, data): 76383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import cl 76483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = self._comp.SetParam(cl.FRAME_BUFFER_SIZE, len(data)) 76583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = self._comp.SetParam(cl.COMPRESSED_BUFFER_SIZE, len(data)) 76683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return self._comp.Compress(self._nframes, data) 76783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 76883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _lin2ulaw(self, data): 76983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import audioop 77083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return audioop.lin2ulaw(data, 2) 77183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 77283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _lin2adpcm(self, data): 77383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import audioop 77483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not hasattr(self, '_adpcmstate'): 77583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._adpcmstate = None 77683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data, self._adpcmstate = audioop.lin2adpcm(data, 2, 77783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._adpcmstate) 77883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return data 77983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 78083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _ensure_header_written(self, datasize): 78183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._nframeswritten: 78283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype in ('ULAW', 'ALAW'): 78383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._sampwidth: 78483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._sampwidth = 2 78583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._sampwidth != 2: 78683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'sample width must be 2 when compressing with ULAW or ALAW' 78783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype == 'G722': 78883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._sampwidth: 78983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._sampwidth = 2 79083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._sampwidth != 2: 79183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'sample width must be 2 when compressing with G7.22 (ADPCM)' 79283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._nchannels: 79383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, '# channels not specified' 79483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._sampwidth: 79583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'sample width not specified' 79683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._framerate: 79783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'sampling rate not specified' 79883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._write_header(datasize) 79983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 80083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _init_compression(self): 80183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype == 'G722': 80283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = self._lin2adpcm 80383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 80483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 80583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import cl 80683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except ImportError: 80783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype == 'ULAW': 80883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 80983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import audioop 81083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = self._lin2ulaw 81183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 81283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except ImportError: 81383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pass 81483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot write compressed AIFF-C files' 81583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype == 'ULAW': 81683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh scheme = cl.G711_ULAW 81783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif self._comptype == 'ALAW': 81883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh scheme = cl.G711_ALAW 81983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 82083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'unsupported compression type' 82183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comp = cl.OpenCompressor(scheme) 82283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh params = [cl.ORIGINAL_FORMAT, 0, 82383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cl.BITS_PER_COMPONENT, self._sampwidth * 8, 82483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cl.FRAME_RATE, self._framerate, 82583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cl.FRAME_BUFFER_SIZE, 100, 82683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh cl.COMPRESSED_BUFFER_SIZE, 100] 82783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._nchannels == 1: 82883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh params[1] = cl.MONO 82983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif self._nchannels == 2: 83083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh params[1] = cl.STEREO_INTERLEAVED 83183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 83283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, 'cannot compress more than 2 channels' 83383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._comp.SetParams(params) 83483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # the compressor produces a header which we ignore 83583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = self._comp.Compress(0, '') 83683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._convert = self._comp_data 83783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 83883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _write_header(self, initlength): 83983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._aifc and self._comptype != 'NONE': 84083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._init_compression() 84183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write('FORM') 84283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self._nframes: 84383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes = initlength // (self._nchannels * self._sampwidth) 84483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = self._nframes * self._nchannels * self._sampwidth 84583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._datalength & 1: 84683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = self._datalength + 1 84783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._aifc: 84883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._comptype in ('ULAW', 'ALAW'): 84983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = self._datalength // 2 85083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._datalength & 1: 85183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = self._datalength + 1 85283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif self._comptype == 'G722': 85383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = (self._datalength + 3) // 4 85483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._datalength & 1: 85583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = self._datalength + 1 85683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._form_length_pos = self._file.tell() 85783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh commlength = self._write_form_length(self._datalength) 85883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._aifc: 85983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write('AIFC') 86083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write('FVER') 86183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, 4) 86283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, self._version) 86383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 86483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write('AIFF') 86583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write('COMM') 86683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, commlength) 86783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_short(self._file, self._nchannels) 86883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes_pos = self._file.tell() 86983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, self._nframes) 87083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_short(self._file, self._sampwidth * 8) 87183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_float(self._file, self._framerate) 87283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._aifc: 87383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write(self._comptype) 87483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_string(self._file, self._compname) 87583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write('SSND') 87683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._ssnd_length_pos = self._file.tell() 87783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, self._datalength + 8) 87883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, 0) 87983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, 0) 88083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 88183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _write_form_length(self, datalength): 88283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._aifc: 88383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh commlength = 18 + 5 + len(self._compname) 88483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if commlength & 1: 88583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh commlength = commlength + 1 88683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh verslength = 12 88783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 88883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh commlength = 18 88983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh verslength = 0 89083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, 4 + verslength + self._marklength + \ 89183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 8 + commlength + 16 + datalength) 89283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return commlength 89383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 89483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _patchheader(self): 89583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh curpos = self._file.tell() 89683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self._datawritten & 1: 89783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh datalength = self._datawritten + 1 89883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write(chr(0)) 89983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 90083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh datalength = self._datawritten 90183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if datalength == self._datalength and \ 90283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes == self._nframeswritten and \ 90383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._marklength == 0: 90483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.seek(curpos, 0) 90583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 90683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.seek(self._form_length_pos, 0) 90783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dummy = self._write_form_length(datalength) 90883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.seek(self._nframes_pos, 0) 90983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, self._nframeswritten) 91083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.seek(self._ssnd_length_pos, 0) 91183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, datalength + 8) 91283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.seek(curpos, 0) 91383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._nframes = self._nframeswritten 91483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._datalength = datalength 91583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 91683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _writemarkers(self): 91783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(self._markers) == 0: 91883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 91983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._file.write('MARK') 92083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh length = 2 92183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for marker in self._markers: 92283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh id, pos, name = marker 92383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh length = length + len(name) + 1 + 6 92483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if len(name) & 1 == 0: 92583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh length = length + 1 92683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, length) 92783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self._marklength = length + 8 92883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_short(self._file, len(self._markers)) 92983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh for marker in self._markers: 93083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh id, pos, name = marker 93183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_short(self._file, id) 93283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_ulong(self._file, pos) 93383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh _write_string(self._file, name) 93483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 93583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef open(f, mode=None): 93683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if mode is None: 93783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if hasattr(f, 'mode'): 93883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh mode = f.mode 93983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 94083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh mode = 'rb' 94183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if mode in ('r', 'rb'): 94283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return Aifc_read(f) 94383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh elif mode in ('w', 'wb'): 94483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return Aifc_write(f) 94583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 94683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh raise Error, "mode must be 'r', 'rb', 'w', or 'wb'" 94783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 94883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehopenfp = open # B/W compatibility 94983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 95083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif __name__ == '__main__': 95183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh import sys 95283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not sys.argv[1:]: 95383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh sys.argv.append('/usr/demos/data/audio/bach.aiff') 95483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh fn = sys.argv[1] 95583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f = open(fn, 'r') 95683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "Reading", fn 95783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "nchannels =", f.getnchannels() 95883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "nframes =", f.getnframes() 95983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "sampwidth =", f.getsampwidth() 96083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "framerate =", f.getframerate() 96183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "comptype =", f.getcomptype() 96283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "compname =", f.getcompname() 96383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if sys.argv[2:]: 96483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh gn = sys.argv[2] 96583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "Writing", gn 96683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh g = open(gn, 'w') 96783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh g.setparams(f.getparams()) 96883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh while 1: 96983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh data = f.readframes(1024) 97083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not data: 97183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh break 97283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh g.writeframes(data) 97383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh g.close() 97483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh f.close() 97583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh print "Done." 976